新手问题,如何解决用gin做的api接口经常无响应?

biolt · 2023-01-07 19:55:20 · 9310 次点击 · 大约8小时之前 开始浏览    置顶
这是一个创建于 2023-01-07 19:55:20 的主题,其中的信息可能已经有所发展或是发生改变。

用gin做了一些api接口,经常运行中挂掉,处于访问无响应的状态,只能重启解决。用netstat -ano查看端口状态,处于CLOSE_WAIT。用wireshark监测确实可以看到有访问进来,但是gin没有相应。这些api有些是访问数据库返回结果的,有些是访问其它外部接口再返回结果的。单独每个api都用postman测试过几千次,并无逻辑问题。但就是运行中偶发变成无响应状态,无响应状态时数据库无死锁(排除数据库问题)。起初我猜测是不是访问其它外部接口超时所致,后来访问外部接口加入了超时5秒的限制,无效。后来猜测是gin自身未设置超时,于是改成如下启动参数

&http.Server{ Addr: address, Handler: router, ReadTimeout: 10 time.Second, WriteTimeout: 10 time.Second, MaxHeaderBytes: 1 << 20, }

仍然无效。请问在api中访问其它外部接口有什么需要注意的地方?是否会引起gin自身无响应?如何能让gin在api请求失败后超时不影响其它访问? 求指教,新手拜谢 代码.png

下面是对外访问接口时候,使用的get,post方法,加了5秒超时 get.png

post.png


有疑问加站长微信联系(非本文作者)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

9310 次点击  ∙  1 赞  
加入收藏 微博
22 回复  |  直到 2024-02-29 09:34:29
don178
don178 · #1 · 2年之前

贴代码看看

tuzhiya
tuzhiya · #2 · 2年之前

recovery中间件加上没有

biolt
biolt · #3 · 2年之前
don178don178 #1 回复

贴代码看看

代码已贴图,请看有问题吗

biolt
biolt · #4 · 2年之前
tuzhiyatuzhiya #2 回复

recovery中间件加上没有

用router := gin.Default() 创建的,好像是自动开启recovery中间件吧

don178
don178 · #5 · 2年之前

你说加了5秒超时,是怎么加的,不会是设置 ReadTimeout 吧。这不是访问外部接口的超时。

biolt
biolt · #6 · 2年之前
don178don178 #5 回复

你说加了5秒超时,是怎么加的,不会是设置 ReadTimeout 吧。这不是访问外部接口的超时。

对外部访问的get,post方法代码已贴,您看写的有问题吗

don178
don178 · #7 · 2年之前

日志呢,没报错吗。是你监听的 8080 端口状态是 CLOSE_WAIT?

biolt
biolt · #8 · 2年之前
don178don178 #7 回复

日志呢,没报错吗。是你监听的 8080 端口状态是 CLOSE_WAIT?

日志里没有报错。就仿佛gin假死了完全没有收到请求一样。但用wireshark能看到请求确实到端口了,用netstat 命令看端口状态确实是CLOSE_WAIT

biolt
biolt · #9 · 2年之前
don178don178 #7 回复

日志呢,没报错吗。是你监听的 8080 端口状态是 CLOSE_WAIT?

难道是我的gin版本太老有什么隐藏bug?我的gin是v1.4.0-dev

biolt
biolt · #10 · 2年之前

另外还有个怀疑,是不是遇到了拒绝服务攻击?

don178
don178 · #11 · 2年之前

端口状态应该是listen, 你接收下 s.listenAndServer() 的err 看看。

biolt
biolt · #12 · 2年之前

11楼 @don178 这是其中一次TCP状态,监听的端口6692是listen没错。但就是不响应了微信图片_20230126211502.png

symphony09
symphony09 · #13 · 2年之前
bioltbiolt #12 回复

11楼 @don178 这是其中一次TCP状态,监听的端口6692是listen没错。但就是不响应了![微信图片_20230126211502.png](https://static.golangjob.cn/230126/20b7c054d891a6528192bf39f98b9eec.png)

首先应该不是拒绝服务攻击,因为从图中看是客户端可以顺利建立连接,并且是主动断开连接。 一般还是怀疑服务端超时,我在 handler 中 sleep 一段时间就可以复现你描述的情况

    e.GET("/", func(c *gin.Context) {
        time.Sleep(time.Minute)
    })

屏幕截图 2023-01-28 214931.png 至于你设置的 gin read timeout 和 write timeout 对业务逻辑应该是无效的。 具体故障原因,看下来,还是数据库方面问题可能性大一点,虽然排除了死锁问题,但是可能存在连接池泄露导致长时间无法获取连接的问题,可以观察一下问题出现时数据库的非活跃连接数量。

haha_cat
haha_cat · #14 · 2年之前
symphony09symphony09 #13 回复

#12楼 @biolt 首先应该不是拒绝服务攻击,因为从图中看是客户端可以顺利建立连接,并且是主动断开连接。 一般还是怀疑服务端超时,我在 handler 中 sleep 一段时间就可以复现你描述的情况 ```go e.GET("/", func(c *gin.Context) { time.Sleep(time.Minute) }) ``` ![屏幕截图 2023-01-28 214931.png](https://static.golangjob.cn/230128/2be171b55c067b4d9f07b6f14dda14e5.png) 至于你设置的 gin read timeout 和 write timeout 对业务逻辑应该是无效的。 具体故障原因,看下来,还是数据库方面问题可能性大一点,虽然排除了死锁问题,但是可能存在连接池泄露导致长时间无法获取连接的问题,可以观察一下问题出现时数据库的非活跃连接数量。

赞同

PaiGack
PaiGack · #15 · 2年之前

可以考虑在 gin 根路由挂个日志看看,是不是收到了请求

biolt
biolt · #16 · 2年之前

13楼 @symphony09 谢谢指点。这是我数据库连接参数,请问有没有问题。最初我设的是SqlDB.SetMaxIdleConns(50),SqlDB.SetMaxOpenConns(100)。曾经怀疑连接池不够用,分别放大了10倍,但没有解决问题,服务挂掉的时候查非活跃连接数量并不多,不到10个。还有一点我百思不得其解,服务挂掉的时候,一些并不访问数据库的api(只是简单返回时间或者字符串的功能),也失去了响应。sqlcon.png

biolt
biolt · #17 · 2年之前
PaiGackPaiGack #15 回复

可以考虑在 gin 根路由挂个日志看看,是不是收到了请求

谢谢指点。gin日志已挂,挂日志代码如下。当服务挂掉的时候,日志就停止输出了。但从wireshark里能看到请求已经访问到本机端口卡在那里。 ginlog.png

symphony09
symphony09 · #18 · 2年之前
bioltbiolt #16 回复

13楼 @symphony09 谢谢指点。这是我数据库连接参数,请问有没有问题。最初我设的是SqlDB.SetMaxIdleConns(50),SqlDB.SetMaxOpenConns(100)。曾经怀疑连接池不够用,分别放大了10倍,但没有解决问题,服务挂掉的时候查非活跃连接数量并不多,不到10个。还有一点我百思不得其解,服务挂掉的时候,一些并不访问数据库的api(只是简单返回时间或者字符串的功能),也失去了响应。![sqlcon.png](https://static.golangjob.cn/230206/28e83d2d83372a3194e1856ec8033269.png)

确实奇怪,有用 pprof 分析过吗

biolt
biolt · #19 · 2年之前
symphony09symphony09 #18 回复

#16楼 @biolt 确实奇怪,有用 pprof 分析过吗

有加载pprof,但还不太会看这个东西

tuzhiya
tuzhiya · #20 · 2年之前

建议还是升级下gin版本到最新。 gin的http是用的协成,基本是不会出现无法响应的问题

biolt
biolt · #21 · 2年之前
tuzhiyatuzhiya #20 回复

建议还是升级下gin版本到最新。 gin的http是用的协成,基本是不会出现无法响应的问题

我现在用的是 gin是v1.4.0-dev,不确认是不是我这个gin版本的问题,请问有谁用过这个版本吗。有下载最新版尝试升级过,但最新版里面的一些引用文件,怎么都go get不到,真是喝凉水都塞牙

archxm
archxm · #22 · 大约1年之前

不知道如何了,我也遇到类似问题。我用gin弄了个服务,目前在测试阶段,就我一个人用。 如果长时间没访问,然后再次访问时,第一次会502,再次访问就好了。 再长时间搁置不访问,再次访问时,依然会复现。 我感觉是 ReadTimeout 和 WriteTimeout 导致的

添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传