首页 > 编程知识 正文

强制重启远程死机服务器,正在摧毁协议处理器8080

时间:2023-05-05 20:39:02 阅读:62735 作者:3605

1 .症状生产环境的一个服务突然无法访问,服务交互过程如下:

的所有请求都通过网关访问,并分发给后端服务。

在当前情况下,用户服务无法访问旅行服务。 网关上有大量的Java.net.sockettimeoutexception 3360 read timed out错误日志,目的地服务也继续打印日志。 由于大多数是回调和定时任务日志,故障点是网关和旅行服务,旅行服务很可能无法访问而导致网关超时。

之后,进行了以下操作。

重新启动旅行服务,正常访问,几个小时后服务又不能访问重新启动网关,服务仍然不能访问,接着重新启动旅行服务,正常访问,几个小时后服务或者用户可以访问旅行爸爸用网关机访问旅行目的地测试界面,但仍然无法访问; 旅行目的地重启后,可以通过网关机访问旅行目的地的路径测试界面,通过上述操作可以判断网关OK,故障点在旅行目的地提供服务。

2 .第一个定位运维使用Top命令(类似于Windows任务管理器)查看机器停机情况,如下所示(仅供参考) :

参数解释如下:

VIRT :进程占用的虚拟内存

RES :进程占用的物理内存

SHR :进程使用的共享内存

s :进程状态。 s表示休眠,r表示执行中,z表示僵硬状态,n表示该过程优先值为负

%CPU :进程占用了CPU的使用率

%MEM :进程使用的物理内存和总内存的百分比

运行netstat -nat | grep 'CLOSE_WAIT '时检测到大量CLOSE_WAIT连接。 仅供参考:

目的地的JVM堆内存限制为512米,但显示使用了988米(相当大)。 然后,在JDK7升级到JDK8之后,您看到了一些JVM参数的有效性,现在使用的JVM参数是-ms512m -mx512m,这可能是旧的JVM参数。 因此,它确定由于JVM参数无效而导致内存不受限制,并且多个JVM内存冲突导致服务不可用。 因此制定了以下解决方案。

将JVM启动参数从-ms512m -mx512m更改为-XMS256m-xmx512m,重新启动服务并成功访问。

3 .距离第二次定位还不到一天。 无法访问服务。 top命令的结果与第一次定位一致。 此时,JVM参数尚未有效,可能是内存冲突。 由于在线服务中有些人正在等待订票,因此运行jmap -dump:format=b,file=文件名[pid]导出dump文件,然后重新启动服务以恢复正常。

可以分析Dump文件,使用jhat、MAT和jvisualvm进行分析,并检查JVM堆的内存使用情况,以确定内存溢出的原因。

正如Thread Dump文件记录当时JVM线程的执行情况一样,Heap Dump记录JVM堆内存的执行情况。

jhat是一个用于分析JDK附带的JVM Heap Dump文件的工具,可以使用jhat heap-dump-file命令将堆文件的分析结果显示为HTML页面。 成功运行后,将显示以下结果: snapshot resolved.startedhttpserveronport 7000 serverisready .此时访问http://localhost:7000/可以看到结果。 但实际上通常使用MAT、jvisualvm进行分析。

建议在JVM启动时添加- xx : heapdumponoutofmemoryerror-xx : heap dump path=c :/heap .纤细的烤鸡参数。 这意味着当程序显示内存输出时,MAT工具可以直接生成dump文件,而无需在相应的目录下生成一部分,但在生产环境中几乎无法在线分析

3.1使用jvisualvm的jvisualvm是JDK附带的Java配置文件工具,在JDK纤细的烤鸡目录下,文件名为jvisualvm.exe。

jvisualvm监视本地和远程java进程,实时显示进程的cpu、堆和线程等参数,为java进程生成dump文件,并分析dump文件。

这次从服务器上dump文件,扔给jvisualvm进行分析。

使用方法:直接双击以打开jvisualvm.exe,然后单击“文件”—“导入”,在文件类型列中选择堆,选择要分析的dump文件,然后打开。

经分析,未见异常,无内存泄漏痕迹,也无异常大对象。

3.2Eclipse Memory Analyzer(MAT ) eclipsememoryanalyzer (mat )是一款功能丰富、操作简单的JVM Heap Dump分析工具,可帮助发现内存泄漏,减少内存占有量。

MAT支持两种安装方式。 一种是Eclipse插件的方式,另一种是独立运行的方式,建议独立运行的方式。

分析结果如下。

概述:显示概述信息的概述界面

Histogram :直方图可以显示每个类的实例,也就是对象的数量

和大小。

Dominator Tree:支配树,列出Heap Dump中处于活跃状态中的最大的几个对象,默认按 retained size进行排序,因此很容易找到占用内存最多的对象。

通过分析,均无内存溢出的痕迹,也无大对象等。MAT用法详见:
Java内存泄漏分析系列之六:JVM Heap Dump(堆转储文件)的生成和MAT的使用
Java内存分析工具MAT(Memory Analyzer Tool)安装使用实例

3.3结论

商旅服务无内存泄露的问题,也不存在内存争用的问题(下面会讲),定位的方向最初就是错误的,于是换思路重新定位问题。

4.第三次定位

很快,服务有发生了不可访问,不过这次的重点放在了已近有一些征兆的CLOSE_WAIT上。

4.1 文确认件描述符超出限制导致

执行ulimit -a, 发现open files是65535,已经做过了优化,不是fd的问题。
查看商旅进程使用的Fd数量(统计进程打开的句柄数)。ls -l /proc/pid/fd | wc -l结果如下,打开的确实很多,但是距离65535相差甚远。

4.2 查看堆的情况

执行jmap -heap pid查看堆信息,一切正常,最大堆设置已经生效。

对应关系,给张图自己体会:

最大堆为512M,但是top命令看到实际使用了988M,什么原因?

什么是RES和VIRT?

RES:resident memory usage 常驻内存
(1)进程当前使用的内存大小,但不包括swap out
(2)包含其他进程的共享
(3)如果申请100m的内存,实际使用10m,它只增长10m,与VIRT相反
(4)关于库占用内存的情况,它只统计加载的库文件所占内存大小
RES = CODE + DATA

VIRT:virtual memory usage
(1)进程“需要的”虚拟内存大小,包括进程使用的库、代码、数据等
(2)假如进程申请100m的内存,但实际只使用了10m,那么它会增长100m,而不是实际的使用量
VIRT = SWAP + RES

Linux与进程内存模型

JVM内存模型(1.7与1.8之间的区别)

所以JVM进程内存大小大致为:
非heap(非heap=元空间+栈内存+…)+heap+JVM进程运行所需内存+其他数据等。

所以对应到商旅988M= 512M(堆) + 283 *1M(283个线程,每个线程占用1M)+JVM进程本身运行内存+ NIO的DirectBuffer +JIT+JNI+…,所以top命令显示出的实际内存大于512是合理的。

使用系统命令pmap -x pid查看进程的内存映射情况,会发现大量的六十多MB内存块存在,这个就表示申请了这么大的内存(影响VIRT),但是实际使用的肯定小于这个值(影响RES),这也解释了为什么VIRT很大,几个G。

4.3 查看商旅进程中的线程数

执行ls /proc/17493/task |wc -l(统计进程打开的线程数),结果如下:

总计283个线程。也不是很多。

4.4查看GC情况

执行jstat -gc pid或者stat -gc pid 5000 2000

gc的次数也不是很多,时间也不长。

4.5TCP连接状态统计

执行netstat -n | awk '/^tcp/ {++state[$NF]} END {for(key in state) print key,"t",state[key]}'统计TCP状态情况,

常用的三个状态是:ESTABLISHED 表示正在通信,TIME_WAIT 表示主动关闭,CLOSE_WAIT 表示被动关闭 因为linux分配给一个用户的文件句柄是有限的,而TIME_WAIT和CLOSE_WAIT两种状态如果一直被保持,那么意味着对应数目的通道就一直被占着,而且是“占着茅坑不使劲”,一旦达到句柄数上限,新的请求就无法被处理了,接着就是大量Too Many Open Files异常;如果未达到句柄数上限,也可能会出现无连接可用的情况。
上面发现大量的连接处于CLOSE_WAIT,这可能就是服务不可访问的原因。
这说明是客户端先关闭了连接,服务器端没有执行关闭连接的操作,导致服务器端一直维持在CLOSE_WAIT的状态。详见下图:

查看TCP的keep_alive参数sysctl -a |grep keepalive ,结果如下:

TCP默认的保活时间为2个小时,也就是说两个小时TCP才会主动帮我们会清理一次无用的连接。所以现在的问题是什么原因造成了大量CLOSE_WAIT的产生。

TIME_WAIT状态可以通过优化服务器参数得到解决,因为发生TIME_WAIT的情况一般是就是对方连接的异常,总之不是由于自己程序错误导致的。

但是CLOSE_WAIT就不一样了,如果一直保持在CLOSE_WAIT状态,那么只有一种情况,就是在对方连接关闭之后,程序里没有检测到,或者程序压根就忘记了这个时候需要关闭连接,于是这个资源就一直被程序占着。个人觉得这种情况,通过服务器内核参数也没办法解决,服务器对于程序抢占的资源没有主动回收的权利,除非终止程序运行。
所以如果将大量CLOSE_WAIT的解决办法总结为一句话那就是:查代码。因为问题出在服务器程序里头啊。

5.找到问题并复现

大量CLOSE_WAIT是则么出现的呢?一下两个线索为我们提供了思路:

生产的日志大多是同城火车票回调同城火车票目前只有测试环境,回调地址配置到了生产环境,而开发、黑盒、沙河无回调,使用主动查询逻辑。同城火车票上线之前服务正常

一个定位的方向就是:同城的回调导致大量CLOSE_WAIT,于是走读代码,果然有端倪.

这段代码的大致意思是: 收到回调,查询订单是否存在,存在则处理,不存在则执行30的睡眠,之后返回。(不要问为什么有这样的逻辑)。

同程回调接口是这样说明的:

所以原因是:开发、黑盒、沙河、生产为了发版本产生了大量的订单、但是只有生产配置了回调地址,所以有大量的回调到生产环境,但是很多单子不是生产环境的,所以导致Sleep了30S,于是在回调返回之前,同城已经超时,程服务端直接关闭连接,同时会再次发送新的回调。一直不停的这样,这样商旅通服务端会造成大量CLOSE_WAIT堆积,一个CLOSE_WAIT会维持至少2个小时的时间(系统默认超时时间的是7200秒,也就是2小时)。

造成CLOSE_WAIT占用过多的资源,等不到释放那一刻,系统就已崩溃。

6.解决

生产环境查不到订单立即返回,不进行SLEEP。
生产环境升级后,几天内正常,问题解决。

7.参考文献 java.io.IOException 断开的管道 解决方法 ClientAbortException: java.io.IOException: Broken pipe

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。