Android 小问题汇总(3)

1.客户端异常中可以看到很多connection reset by peer的错误

发现这个错误我们经常手足无措。结果是,服务器连接开的少了,给你解释下原理。

问题现象:

JAVA的client和server,使用socket通信。server使用NIO。
1.间歇性的出现client向server建立连接三次握手已经完成,但server的selector没有响应到这连接。
2.出问题的时间点,会同时有很多连接出现这个问题。
3.selector没有销毁重建,一直用的都是一个。
4.程序刚启动的时候必会出现一些,之后会间歇性出现。

正常TCP建连接三次握手过程:
第一步:client 发送 syn 到server 发起握手;
第二步:server 收到 syn后回复syn+ack给client;
第三步:client 收到syn+ack后,回复server一个ack表示收到了server的syn+ack(此时client的56911端口的连接已经是established)
从问题的描述来看,有点像TCP建连接的时候全连接队列(accept队列)满了,尤其是症状2、4. 为了证明是这个原因,马上通过 ss -s 去看队列的溢出统计数据:

反复看了几次之后发现这个overflowed 一直在增加,那么可以明确的是server上全连接队列一定溢出了

......
为了证明客户端应用代码的异常跟全连接队列满有关系,我先把tcp_abort_on_overflow修改成 1,1表示第三步的时候如果全连接队列满了,server发送一个reset包给client,表示废掉这个握手过程和这个连接(本来在server端这个连接就还没建立起来)。

接着测试然后在客户端异常中可以看到很多connection reset by peer的错误,到此证明客户端错误是这个原因导致的。

于是开发同学翻看java 源代码发现socket 默认的backlog(这个值控制全连接队列的大小,后面再详述)是50,于是改大重新跑,经过12个小时以上的压测,这个错误一次都没出现过,同时 overflowed 也不再增加了。

到此问题解决,简单来说TCP三次握手后有个accept队列,进到这个队列才能从Listen变成accept,默认backlog 值是50,很容易就满了。满了之后握手第三步的时候server就忽略了client发过来的ack包(隔一段时间server重发握手第二步的syn+ack包给client),如果这个连接一直排不上队就异常了。
........
深层次问题,可以自行搜索了。知道这个,就可以和服务端对峙了

【参考】

2. Android手机在没有/data/anr目录权限的情况下如何分析ANR

Step1: 将发生ANR的手机打开"开发者选项"并启动"调试模式"
Step2:将手机连接到电脑上
Step3:在电脑的命令行里面执行命令 "adb bugreport anrlog.zip" (anrlog.zip是生成文件的名字,自己可以随便写),这里有个前提是你的电脑装了adb,没装的自行百度如何安装。
Step4:解压生成好的anrlog.zip文件,大概是下图的结构,打开第一个文件,也就是体积最大的那个文件。

image.png

Step5:文件打开一看乱七八糟啥都有,其实这就对了,那么我们开始分析这个文件,找出trace信息。

我的经验搜索关键字:VM TRACES AT LAST ANR,一般就能定位到下图的位置,你看看进程名和时间跟你的进程对上不,对上那就OK了,顺着往下翻就是这次ANR的trace信息了。

还有一个关键字可以用:onAppNotResponding error = Application Not Responding for at least 5000 ms

Step6:至于分析ANR到底是啥原因引起,那就学问大了去了,我一般也就是分析下主线程卡在哪里了,就跟下图一样。如果一眼看不出来,那就继续去搜索前人的经验吧,怎么根据trace信息分析ANR。

image.png

参考

你可能感兴趣的:(Android 小问题汇总(3))