热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Golang踩坑分析之Gorm

案例1:GolangGorm踩坑##影响情况##服务A是定时调度系统,利用github.comrobfigcron来实现,发现服务运行3小时左右就不打印sql日志,但是API服务响

案例1:Golang Gorm踩坑

## 影响情况##
服务A 是定时调度系统,利用github.com/robfig/cron 来实现,发现服务运行3小时左右就不打印sql 日志,但是API 服务响应正常. 导致调度服务不执行、
##分析思路##
Golang 编写调度的服务遇到不调度的情况如何分析处理那?首先我们利用golang 自带的pprof来分析。在main.go中 增加`
go func() {
if err := http.ListenAndServe("0.0.0.0:12345", nil); err != nil {
log.Println(err)
}
}()`

然后再结合火焰图 去分析。可惜这次,pprof 并没有帮上我们的忙,因为调度服务很轻量,内存方面没超过1MB,profile cpu等也很正常、那么接下来怎么办?

由于是服务调度每次都会打印sql,那么我们就去查看mysql 的资源吧、
首先 通过show full process list; 如下

mysql> show full processlist;
+---------+-----------+------------------+---------+---------+------+----------+-----------------------+-----------+---------------+
| Id | User | Host | db | Command | Time | State | Info | Rows_sent | Rows_examined |
+---------+-----------+------------------+---------+---------+------+----------+-----------------------+-----------+---------------+
| 2855999 | A | *:52898 | my | Sleep | 37 | | NULL | 0 | 0 |
| 2880711 | A | *:26280 | my | Sleep | 10 | | NULL | 0 | 0 |
| 2904663 | A | *:50519 | my | Sleep | 2544 | | NULL | 0 | 0 |
| 2905293 | A | *:6492 | my | Sleep | 567 | | NULL | 0 | 0 |
| 2905341 | A | *:2777 | my | Query | 0 | starting | show full processlist | 0 | 0 |
| 2905425 | A | *:4081 | my | Sleep | 57 | | NULL | 0 | 0 |
| 2905444 | A | *:15888 | my | Sleep | 92 | | NULL | 0 | 0 |
| 2905523 | A | *:13524 | my | Sleep | 10 | | NULL | 0 | 0 |
+---------+-----------+------------------+---------+---------+------+----------+-----------------------+-----------+———————+

测试环境服务 发现会有大量的sleep,那么我们再看下my.conf 配置。一般最大连接数就设置200左右。所所以1分钟调度一次,200分钟我们的服务就被把数据库连接数占满。那么接下来去分析下源码。

//以下是调度的问题代码
for rowsInner.Next() {
dataMap[supportInt] = true
break
}
我们发现 直接做了break、但是为什么会导致连接被占用 不能释放那?

func (rs *Rows) Next() bool {
var doClose, ok bool
withLock(rs.closemu.RLocker(), func() {
doClose, ok = rs.nextLocked()
})
if doClose {
rs.Close()
}
return ok
}
func (rs *Rows) Scan(dest ...interface{}) error {
rs.closemu.RLock()
if rs.lasterr != nil && rs.lasterr != io.EOF {
rs.closemu.RUnlock()
return rs.lasterr
}
if rs.closed {
err := rs.lasterrOrErrLocked(errRowsClosed)
rs.closemu.RUnlock()
return err
}
rs.closemu.RUnlock()
if rs.lastcols == nil {
return errors.New("sql: Scan called without calling Next")
}
if len(dest) != len(rs.lastcols) {
return fmt.Errorf("sql: expected %d destination arguments in Scan, not %d", len(rs.lastcols), len(dest))
}
for i, sv := range rs.lastcols {
err := convertAssignRows(dest[i], sv, rs)
if err != nil {
return fmt.Errorf(`sql: Scan error on column index %d, name %q: %v`, i, rs.rowsi.Columns()[i], err)
}
}
return nil
}

我们通过源码可以发现,Next()方法判断下一个元素有没有,但是我们没有用scan,因为scan 每次返回都会释放掉一行数据库的缓存,所以 我们 手动rows.Close(),这种情况也很难遇到,因为一般情况下,我们都是 scan到底,最后底层代码会 执行 d.close(rows.lasterr)、所以我们一般不需要手动close rows.

结论:每次返回的rows 都是新的实例,占用一个数据库连接. rows.next()直到false 就会关闭,否则就会出现资源没有被回收,但数据库设置的超时回收也会去回收 但是会降低服务Tps。


推荐阅读
  • 本文介绍了Python爬虫技术基础篇面向对象高级编程(中)中的多重继承概念。通过继承,子类可以扩展父类的功能。文章以动物类层次的设计为例,讨论了按照不同分类方式设计类层次的复杂性和多重继承的优势。最后给出了哺乳动物和鸟类的设计示例,以及能跑、能飞、宠物类和非宠物类的增加对类数量的影响。 ... [详细]
  • 本文详细介绍了Linux中进程控制块PCBtask_struct结构体的结构和作用,包括进程状态、进程号、待处理信号、进程地址空间、调度标志、锁深度、基本时间片、调度策略以及内存管理信息等方面的内容。阅读本文可以更加深入地了解Linux进程管理的原理和机制。 ... [详细]
  • Linux学习笔记:psef、ps aux、kill9
    一、查看进程命令1.ps命令Linux中的ps命令是ProcessStatus的缩写。ps命令用来列出系统中当前运行的那些进程。ps命令列出的是当前那些进程的快照,就 ... [详细]
  • linux 循环 cpu使用率脚本,Linux Shell脚本监视CPU利用率,达到设置的CPU利用率时发送电子邮件...
    有很多开源监控工具可用于监控Linux系统性能,当系统达到给定的阈值限制时,它将发送电子邮件警报。它监视CPU利用率、内存利用率、交换利用率、磁盘空间利 ... [详细]
  • SpringBoot uri统一权限管理的实现方法及步骤详解
    本文详细介绍了SpringBoot中实现uri统一权限管理的方法,包括表结构定义、自动统计URI并自动删除脏数据、程序启动加载等步骤。通过该方法可以提高系统的安全性,实现对系统任意接口的权限拦截验证。 ... [详细]
  • 本文介绍了Redis的基础数据结构string的应用场景,并以面试的形式进行问答讲解,帮助读者更好地理解和应用Redis。同时,描述了一位面试者的心理状态和面试官的行为。 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • 本文介绍了使用PHP实现断点续传乱序合并文件的方法和源码。由于网络原因,文件需要分割成多个部分发送,因此无法按顺序接收。文章中提供了merge2.php的源码,通过使用shuffle函数打乱文件读取顺序,实现了乱序合并文件的功能。同时,还介绍了filesize、glob、unlink、fopen等相关函数的使用。阅读本文可以了解如何使用PHP实现断点续传乱序合并文件的具体步骤。 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • 不同优化算法的比较分析及实验验证
    本文介绍了神经网络优化中常用的优化方法,包括学习率调整和梯度估计修正,并通过实验验证了不同优化算法的效果。实验结果表明,Adam算法在综合考虑学习率调整和梯度估计修正方面表现较好。该研究对于优化神经网络的训练过程具有指导意义。 ... [详细]
  • 本文探讨了C语言中指针的应用与价值,指针在C语言中具有灵活性和可变性,通过指针可以操作系统内存和控制外部I/O端口。文章介绍了指针变量和指针的指向变量的含义和用法,以及判断变量数据类型和指向变量或成员变量的类型的方法。还讨论了指针访问数组元素和下标法数组元素的等价关系,以及指针作为函数参数可以改变主调函数变量的值的特点。此外,文章还提到了指针在动态存储分配、链表创建和相关操作中的应用,以及类成员指针与外部变量的区分方法。通过本文的阐述,读者可以更好地理解和应用C语言中的指针。 ... [详细]
  • 本文介绍了机器学习手册中关于日期和时区操作的重要性以及其在实际应用中的作用。文章以一个故事为背景,描述了学童们面对老先生的教导时的反应,以及上官如在这个过程中的表现。同时,文章也提到了顾慎为对上官如的恨意以及他们之间的矛盾源于早年的结局。最后,文章强调了日期和时区操作在机器学习中的重要性,并指出了其在实际应用中的作用和意义。 ... [详细]
  • 深入理解Kafka服务端请求队列中请求的处理
    本文深入分析了Kafka服务端请求队列中请求的处理过程,详细介绍了请求的封装和放入请求队列的过程,以及处理请求的线程池的创建和容量设置。通过场景分析、图示说明和源码分析,帮助读者更好地理解Kafka服务端的工作原理。 ... [详细]
  • 服务器上的操作系统有哪些,如何选择适合的操作系统?
    本文介绍了服务器上常见的操作系统,包括系统盘镜像、数据盘镜像和整机镜像的数量。同时,还介绍了共享镜像的限制和使用方法。此外,还提供了关于华为云服务的帮助中心,其中包括产品简介、价格说明、购买指南、用户指南、API参考、最佳实践、常见问题和视频帮助等技术文档。对于裸金属服务器的远程登录,本文介绍了使用密钥对登录的方法,并提供了部分操作系统配置示例。最后,还提到了SUSE云耀云服务器的特点和快速搭建方法。 ... [详细]
author-avatar
W_庆祥
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有