connect reset/timeout/reject 排查

这篇具有很好参考价值的文章主要介绍了connect reset/timeout/reject 排查。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

问题描述

最初出现的时候,是在每天的早上8-10这个时间范围内,服务A上的有一个接口时不时报警,内容不一,有 connect timeoutconnect resetconnect reject等,其中connect reject比较频繁。在后续观察中,发现tomcatnio线程一般正常运行下为100以下,但是在异常重启前一个小时内会飙升至1000也就是配置的最大线程数。

问题处理

初步分析

线上部署的服务A有4个pod,每台机器的配置是1g。是springboot项目,tomcat配置如下

server:
  tomcat:
    uri-encoding: UTF-8 
    accept-count: 1000
    max-connections: 2000
    max-threads: 1000
    min-spare-threads: 10
  connection-timeout: 60000

乍一看线程数量有一点多。之后看了一下是不是有问题的接口逻辑,主要交互节点如下

1、接收请求,根据token查缓存获取用户数据
2、feign调用用户服务获取用户信息
3、根据获取的信息查数据库,然后组装结果返回

整体逻辑看着也很简单,feign调用耗时也不是很高。查缓存的话,应该也没有问题,不然就单是一个服务的问题了。那就是查库的问题了,我把执行sql分析了一下,走了索引,表的数据量也不是很大,那是哪一步出问题了。。

http配置即服务整体情况

接口处理时间变长的一种情况是,并发请求太大,导致服务请求处理不过来(如果接口有限流配置那么其实就直接拒掉了,这个服务没有配置)。我在ES上看了一个服务的峰值请求量,秒级不超过一千。异常接口峰值秒级也只有3、4百,分到每台机器上也就100多,1000个线程怎么都处理的过来吧。除非其他接口请求量也大,而且处理时间长,占用了线程。但是我在ES上看了一下接口处理耗时,报警的那一会的确有耗时变长的情况,请求量的确也有所上升。
此外,我看了一个物理机的tcp配置

net.core.somaxcon  // 128
net.ipv4.tcp_max_back_log  // 1000

这两配置有点小了。

此时,我的推测如下:

1、connect timeout 是因为处理请求不过来
2、connect reset 是因为 http全连接 半连接池太小,被请求占满导致
3、connect reject 服务不可用

经过灰度测试,发现不明显。connect reject 仍出现。

整体排查

服务重启

connect reject出现的原因,理论上是服务寄了。但是怎么能知道它寄没寄呢。突然想到,这个服务有注册到注册中心,也就是eureka。上去一下,没有下线信息,但是报错那个时间点有上线信息。

connect reset/timeout/reject 排查

于是,推测那个时间点是不是服务重启了。看了一下线上服务的日志,发现日志归档了,gc信息也归档了。然后看技术上线记录,发现没人手动上线,于是推测是服务自动重启,然后找运维确定了一下,的确有重启记录。容器默认配置3分钟内5次心跳没通过重启。。

gc

connect reset/timeout/reject 排查
将运行时的gc日志文件分析后,发现gc很频繁。而且full gc后内存下降不是很明显。但是gc停顿时间最长就1.7秒,不可能3秒内都不可用,所以gc有问题,但可能不是主要问题。

CPU

connect reset/timeout/reject 排查

可以看到,使用情况还是挺高的。具体看进行的CPU情况,发现基本是在100%。

// 看进行下哪个线程使用的cpu比较高
top -Hp 进程id 
// 10进制 转为 16进制
printf '%x\n' 线程id
// 定位线程的信息  d8为上面转换后的16进制
jstack 进程id | grep '0xd8' 

connect reset/timeout/reject 排查

这里拍的有点糊哈,最终定位到是 AsyncReporter 190行代码,我这里zipkin版本是2.7.10,对应的就是flush节点。
这里服务配置的是zipkin收集方式是kafka,大小是默认的1000000,可以认为是1M,时间的话配置了60s’.

connect reset/timeout/reject 排查

然后在线上用arthas看了一下方法运行信息
connect reset/timeout/reject 排查

最后推测出可能是AsyncReporter265行的问题,因为一直没到配置的最大大小(1M),导致一直在死循环。

// ByteBoundedQueue#offer   131行
@Override
public boolean offer(S next, int nextSizeInBytes) {
  int x = messageSizeInBytes(nextSizeInBytes);
  int y = maxBytes;
  int includingNextVsMaxBytes = (x < y) ? -1 : ((x == y) ? 0 : 1); // Integer.compare, but JRE 6

  if (includingNextVsMaxBytes > 0) return false; // can't fit the next message into this buffer

  addSpanToBuffer(next, nextSizeInBytes);
  messageSizeInBytes = x;

  if (includingNextVsMaxBytes == 0) bufferFull = true;
  return true;
}
// 这里可以看到,只有刚好填充满,bufferFull才可能等于true
// BoundedAsyncReporter#flush()  
void flush(BufferNextMessage<S> bundler) {
      if (closed.get()) throw new IllegalStateException("closed");

      pending.drainTo(bundler, bundler.remainingNanos());

      // record after flushing reduces the amount of gauge events vs on doing this on report
      metrics.updateQueuedSpans(pending.count);
      metrics.updateQueuedBytes(pending.sizeInBytes);

      // loop around if we are running, and the bundle isn't full
      // if we are closed, try to send what's pending
      if (!bundler.isReady() && !closed.get()) return;
      
      // ...省略
}      

// 这里的  bundler.isReady() 判断逻辑如下
boolean isReady() {
   return bufferFull || remainingNanos() <= 0;
 }
 // 也就是说,如果时间没到,且没满,那么返回false,此时 flush方法return。这样就开始死循环了,类似while(true)。
 // 如果超时时间比较短,例如默认的1s,那其实也能接受。但是这里我们自己改了默认值,配置了60s,
 // 也就是说在这一分钟内,如果大小刚好卡死,例如当前buffer使用了950kb,下一个100kb,
 // 两者相加不等于1000kb,此时剩余时长都在死循环,CPU自然使用率高了。

修改配置,变为默认值后灰度发布

connect reset/timeout/reject 排查

这里可以看到,明显降低了,使用率基本在1%左右,原先都是10%以上。。后面去看了一下最新版本实现,发现这个bug已经修复了。

connect reset/timeout/reject 排查

可以看到,这里大于最大值后也会认为满了,而不是一定要等于最大值。。

JVM

connect reset/timeout/reject 排查

可以看到,这里的堆使用也不能说有啥大的问题,最多full gc有点多吧,相对而言。但是非堆的话,明显感觉有点问题,理论上来说应该是稳定的。它这里有起伏。

connect reset/timeout/reject 排查

后面用arthas执行memory看了一下内存使用情况,发现没设置mataspace的大小。所以理论上来说它可以无限占用物理机内存。图片可以看到,目前已经用了1.9g了,不太合理。
metaspace主要放的是类的信息,所以推测是不是在运行过程中在动态创建类。dump线上的堆栈信息,用visualvm打开。默认是类实例数正向排序的。

connect reset/timeout/reject 排查

这么看其实看不出啥问题,最多会看看类实例多的是不是内存泄露了。但这次我们得反向排序,因为matespace异常大,说明类都是不一样的。

connect reset/timeout/reject 排查

这么一看,是不是明显发现问题了。都是Script_前缀开头的。本地起一下项目,用arthas找一下类信息 sc -d -n 10 Script_*

connect reset/timeout/reject 排查

这里看到是aviator,它是谷歌开发的一个表达式引擎。在代码里全局搜了一下,发现就一个地方在使用,看了一下具体内容,发现是没有开启缓存导致反复创建代码。

connect reset/timeout/reject 排查
connect reset/timeout/reject 排查

改为之后,灰度发布,过一天运行结果

connect reset/timeout/reject 排查

这里可以看到,非堆使用基本稳定了,堆使用也基本平滑了。但是那两次异常GC看着还有点问题。

暂存疑问点

1、最后平稳后的gc原因,是什么触发的。
2、tomcat线程数异常飙升的原因 是因为metaspace没法分配空间导致线程阻塞么。。
3、服务重启的原因 nio处理线程都被阻塞了,导致心跳接口没人处理么。。

总结

启动参数要配全

像gc具体信息、最大mataspace大小、OOMdump等配置参数最好都加上,不然出现问题了手上都没啥资料。。

监控体系健全

有良好的监控,分析问题起来事陪功半。一开始没有cpu、堆等使用的监控图表,光靠脑子想还是太抽象了

科学使用jar包

使用开源jar包,最好自己看一下实现方法,别直接拿来用。不然坑了自己都不知道

降配参数是参数得动态变

1g内存配了1000个线程,有点不太合理了吧。降配不能单单改内存,其他配置也得一起变化。。。文章来源地址https://www.toymoban.com/news/detail-461079.html

到了这里,关于connect reset/timeout/reject 排查的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 有关 java.io.IOException: Connection reset by peer 解决问题方法之一

    有很多大佬已经终结出现这个错误的原因有一下几种 1. 服务器在接受处理用户请求时,自身的cpu、io、内存、线程等资源都是有最大限制的。当并发请求超过服务器的承载量时,服务器会停掉一些请求。(但是要注意如果实际的并发数量没有超过服务器的承载量,可能中了木

    2024年02月22日
    浏览(66)
  • ssh连接有问题:kex_exchange_identification: read: Connection reset

    今天连接服务器的时候连接不上了,报了这个错, kex_exchange_identification: read: Connection reset 我出现这个问题是服务器禁止了我这个IP进行连接,所以把这个IP删除就可以。 解决办法如下: 如果这个文件中存在你的电脑IP的话,把那个IP从这个文件中删除就可以,然后安ESC退出,

    2024年02月12日
    浏览(40)
  • curl: (56) Recv failure: Connection reset by peer问题汇总和解决方案

    这两天正在学习用docker制作tomcat镜像,有一个问题困扰了我3天,可能大家在学习时也会遇到,于是我就单独发一篇文章来解决这个问题。 解决办法我在上一篇文章 Docker进阶篇之DockerFile制作Tomcat镜像,教你如何发布镜像到DockerHub和阿里云 已经详细说明了,这里再说明一次。

    2024年02月01日
    浏览(57)
  • #Redis问题排查#Connection failure occurred

    问题描述 springboot报错日志如下 这个日志的意思就是redis连接失败,5秒后尝试重新连接。许多博客提供的解决方案是改最大缓存,但并不能解决所有情况。 其实这个报错的原因有很多,我们可以从两个角度尝试解决问题。 一、检查Redis服务 这个报错首先要检查redis服务是否启

    2024年02月14日
    浏览(32)
  • 解决kali虚拟机连接github问题,git/‘: Recv failure: Connection reset by peer

    直接使用ssh连接方式,以下终端全部为kali虚拟机的终端 1、在终端中执行以下命令,将你的电子邮件地址替换为GitHub帐户关联的电子邮件地址。          ssh-keygen -t ed25519 -C \\\"youremail@example.com\\\"         这会在默认目录(通常是 ~/.ssh/ )中生成一个新的SSH密钥对 遇到输入

    2024年01月17日
    浏览(55)
  • 【解决vscode连ssh问题:kex_exchange_identification: read: Connection reset】ssh无法重启

    实验室的服务器连不上了,试了很多种方法,包括 删除known_hosts 和卸载重装本地的vscode和ssh,但还是连不上,基本上可以确定是服务器方面的问题。vscod最开始是弹出以下报错 网上很多解决方法我也试过了,包括 重新生成密钥 ssh-keygen 和 修改/etc/hosts.deny或/etc/hosts.allow ,但

    2024年02月05日
    浏览(42)
  • 解决Git Clone时出现 OpenSSL SSL_read: Connection was reset, 连接被重置的问题

    解决Git Clone时出现 OpenSSL SSL_read: Connection was reset, 连接被重置的问题 在使用Git Clone命令从GitHub或其他Git托管服务中克隆代码库时,有时会遇到以下错误信息: fatal: unable to access ‘https://github.com/username/repo.git/’: OpenSSL SSL_read: Connection was reset, errno 10054 这个错误通常表示在尝试

    2024年02月13日
    浏览(57)
  • 【问题记录】fatal: unable to access ‘https://github.com/‘: Recv failure: Connection was reset

    GitHub上的项目克隆到本地 一般是这是因为服务器的SSL证书没有经过第三方机构的签署,所以才报错 在 GitBash 中执行以下命令

    2024年02月15日
    浏览(66)
  • FTP上传超时问题排查 ftpClient.storeFile Connection timed out

    Ftp storeFile 超时日志如下 Caused by: java.net.ConnectException: Connection timed out (Connection timed out) at java.net.PlainSocketImpl.socketConnect(Native Method) at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350) at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206) at java.net.Abstract

    2024年02月14日
    浏览(80)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包