记一次TcpListenOverflows报警解决过程

简介:

http://blog.csdn.net/puma_dong/article/details/46669499


问题描述


2015-06-25,晚上21:33收到报警,截图如下:


此时,登陆服务器,用curl检查,发现服务报500错误,不能正常提供服务。


问题处理


tail各种日志,jstat看GC,不能很快定位问题,于是dump内存和线程stack后重启应用。

jps -v,找出Process ID

jstack -l PID > 22-31.log

jmap -dump:format=b,file=22-29.bin PID


TcpListenOverflows


应用处理网络请求的能力,由两个因素决定:

1、应用的OPS容量(本例中是 就是我们的jetty应用:controller和thrift的处理能力)

2、Socket等待队列的长度(这个是os级别的,cat  /proc/sys/net/core/somaxconn 可以查看,默认是128,可以调优成了4192,有的公司会搞成32768)

当这两个容量都满了的时候,应用就不能正常提供服务了,TcpListenOverflows就开始计数,zabbix监控设定了>5发警报,于是就收到报警短信和邮件了。

这个场景下,如果我们到服务器上看看 listen情况,watch "netstat -s | grep listen",会看到“xxx times the listen queue of a socket overflowed”,并且这个xxx在不断增加,这个xxx就是我们没有对网络请求正常处理的次数。


参考文章:

关于tcp listen queue的一点事

如何判断是否丢掉用户请求

linux里的backlog详解

linux下socket函数之listen的参数backlog

TCP SNMP counters

LINUX下解决netstat查看TIME_WAIT状态过多问题


理解了以上,我们已经可以大致认为,问题的根源,就是应用处理能力不足。以下的问题分析步骤,可以继续对此进行佐证。


问题分析


线程栈


首先看线程栈,大约12000多个线程,大量线程被TIME_WAIT/WAIT在不同的地址,偶有多个线程被同一个地址WAIT的情况,但是都找不到这个地址运行的是什么程序,貌似这个线程栈意义不大。

关于这点,还请高手进一步帮助分析,能否可以通过这个文件直接定位问题。


Eclipse Memory Analyzer


MAT分析工具,分析JVM内存dump文件,下载地址: http://www.eclipse.org/mat/downloads.php 。

通过分析,我们可以看到,内存中最多的类,是socket相关的,截图如下:


Shallow heap & Retained heap


Zabbix监控




问题解决


1、申请两台新虚拟机,挂上负载。

2、Jetty调优,增大线程数,maxThreads设置为500。

3、调用外部接口Timeout时间,统一调整为3秒,3秒前端就会超时,继续让用户走别的,所以我们的后端进程继续处理已经毫无意义。


问题完全解决了吗?


找个时间,请高手帮忙分析日志,发现一个线程数太多的问题,两类线程太多(HttpClientPool、HttpMonitorCheckTimer );看事发时zabbix的截图,也是JVM线程很大,2万多了,并且不会减小。



一起定位问题,定位到一个问题,每次都会news一个HttpClientHelper,new的过程中有两件事:

1、起一个HttpMonitor线程,里面有定时任务,所以这个线程是不死的。这个线程起名了,“Executors.newScheduledThreadPool(1, new NamedThreadFactory("HttpMonitorCheckTimer"))”,所以我们看多很多叫这个名字的线程

2、起一个HttpClientPool$IdleConnectionMonitorThread线程,这个线程是定时回收池子中过期以及空闲超过一点时间的线程,这个线程没起名,所以叫Thread-XXX这样的名字



grep HttpClientPool 22-31.log | wc -l     11857

grep HttpMonitorCheckTimer 22-31.log | wc -l    11856

这两种线程一定是1:1的关系,都是不死的。看起来Thread-XXX的多,这是因为其他的线程,没起名字的,也是这样命名的,所以。。。所以运行Thread,还是起个名字吧。

查阅一些“PoolingHttpClientConnectionManager”线程池方式进行http调用的例子,根据HttpClientHelper的实现方式,写个PoolingHttpClientConnectionManagerDemo.java代码,运行1个小时,基本确认单例方式能正常运行;

于是修改单例方式调用HttpClientHelper,增加一点对调用次数的统计,上线。








https://segmentfault.com/a/1190000008222890

三次握手

bVIFjo?w=717&h=800

ListenOverflows

root@b5dbe93bcb04:/opt# netstat -s | grep listen
    22438 times the listen queue of a socket overflowed

tcp_v4_syn_recv_sock():三路握手最后一步完成之后,Accept queue队列(完全连接队列,其大小为min(/proc/sys/net/core/somaxconn, backlog))超过上限时加1.

ListenDrops

root@b5dbe93bcb04:/opt# netstat -s | grep LISTEN
    49148 SYNs to LISTEN sockets dropped

tcp_v4_syn_recv_sock():任何原因,包括Accept queue超限,创建新连接,继承端口失败等,加1. 包含ListenOverflows的情况,也就是说当出现ListenOverflows时,它也会增加1;除此之外,当内存不够无法为新的连接分配socket相关的数据结构时,也会增加1,当然还有别的异常情况下会增加1。

AttemptFails

  • tcp_done():如果在SYN_SENT/SYN_RECV状态下结束一个连接,加1

  • tcp_check_req():被动三路握手最后一个阶段中的输入包中如果有RST|SYN标志,加1

1.试图和一个不存在的套接口建立连接时,连接失败,而TcpAttemptFails同时会加1

2.被动连接(SYN_SEND)等待第三次握手的ack应答信号超时或者为其它的错误应答时,连接将会失败,且同时TcpAttemptFails的值将加1。

ActiveOpens

客户端通过connect 发起主动打开(active open),tcp_connect(),发送SYN时,加1。

PassiveOpens

服务器必须准备好接受外来连接。通常调用的是socket,bind和listen这三个函数来完成。我们称之为被动打开(passive open)。被动三路握手完成,加1。

CurrEstab

tcp_set_state(),根据ESTABLISHED是新/旧状态,分别加减一。

EstabResets

tcp_set_state(),新状态为TCP_CLOSE,如果旧状态是ESTABLISHED/TCP_CLOSE_WAIT就加1。

doc





      本文转自Tenderrain 51CTO博客,原文链接:http://blog.51cto.com/tenderrain/1975719,如需转载请自行联系原作者







相关文章
|
5天前
|
弹性计算 运维 监控
自动化监控网站性能并发送警报
【4月更文挑战第30天】
5 0
|
存储 资源调度 运维
如何通过链路追踪进行定时任务诊断
分布式任务调度平台 SchedulerX 有效地将用于微服务场景下的可视化全链路追踪能力引入至定时任务处理场景,这将大大提升定时任务在运行时可观测能力,有效地帮助定时任务执行过程中异常、耗时、执行卡住等问题的定位分析。
如何通过链路追踪进行定时任务诊断
|
监控 NoSQL 数据库
监控与报警|学习笔记
快速学习监控与报警
81 0
监控与报警|学习笔记
|
资源调度 运维 Java
定时任务报警通知解决方案详解
随着微服务和云计算的兴起,定时任务技术也是发展迅速,不仅能做单机的定时任务,而且在分布式系统下应用也很广泛,成为了业务做兜底、数据处理的第一选择。
2431 3
定时任务报警通知解决方案详解
|
Java
报警系统QuickAlarm之报警规则解析
前面两篇分别说了报警执行器和报警规则的定义及用户扩展加载,接下来就是比较核心的一块了,如何将报警规则和报警执行器关联起来,即当发生报警时,应该call哪一个报警执行器
354 0
|
缓存 Java Spring
报警系统QuickAlarm之报警执行器的设计与实现
根据前面一篇总纲的博文,将整体结构划分为了四大块,本文则主要目标集中在第一块,报警执行器(AlarmExecute)的设计与加载上了 主要的关注点无外乎 定义-》加载-》实现逻辑三块了: 1.AlarmExecute 的接口定义 2.如何加载用户自定义的AlarmExecute 3.AlarmExecute的内部实现
281 0
报警系统QuickAlarm之报警执行器的设计与实现
|
存储 JSON 数据格式
报警系统QuickAlarm之报警规则的设定与加载
既然命名为规则,那么就需要有对应的解析器,以根据报警规则和报警类型等相关输入条件,来选择对应的报警执行器,因此本文主要包括的内容就比较清晰了 1.报警规则的定义 2.报警规则的加载 3.报警规则的解析以及报警执行器选择
220 0
报警系统QuickAlarm之报警规则的设定与加载
|
SQL 运维 监控
监控异常操作频率并报警
当企业上云后,监控云资源的异常操作就是一件非常重要的事情。如何监控这些异常操作呢?答案就是操作审计。接下来就以一些实际场景为例,介绍如何基于操作审计,监控云上异常操作或操作频率,进行报警。
监控异常操作频率并报警
|
监控
日志服务数据加工: 任务状态监控与告警
日志服务数据加工最佳实践: 任务状态监控与告警, 介绍如何监控数据加工的任务状态, 并配置相应的监控.
2176 0