Android推送注册失败问题排查

最近项目在生产环境上发现有android手机无法连上推送服务器的现象,导致推送无法正常使用。经过之后项目组一系列的排查之后,基本锁定问题原因,下面就是介绍下问题的现象及排查步骤。

现象
生产环境上,如使用3G/4G网络时Android手机无法收到推送消息。但如果切换到行内wifi时,则能正常收到推送。在测试环境上无此现象,一切正常。

排查流程
1、通过客户端日志发现,在使用3G/4G网络时,手机在连接ejabberd推送服务器时注册失败,并不断重新连接。但具体失败原因从客户端日志中无法确定。
2、然后去查看ejabberd的日志,如下图所示

图1 注册失败日志
从日志上看,并没发现任何报错或异常信息,只是看到ejabberd在收到客户端发送的starttls请求之后再也没收到其他任何请求。
为了对比成功和失败两种情况的日志,我们使用行内wifi,得到如下日志。

图2 注册成功日志(上)

图3 注册成功日志(下)
这两张图是同一个日志的两页,需要连起来看。可以发现在starttls请求之后ejabberd还会收到客户端重新初始化的stream流、用户名密码等信息。
通过比较得出的结论:连接中断是发生在starttls和重新初始化stream流之间的环节。

3、由于没有更多的日志信息,客户端只能做各种更改配置的测试。其中客户端在跳过tls验证时,发现就能成功连上。客户端的配置修改如下:
connConfig.setSecurityMode(ConnectionConfiguration.SecurityMode.disabled);
因此得出结论,问题出在tls验证这块。

4、由于客户端和服务端代码都没改动的情况下,使用行方wifi就成功,使用非行方网络就失败,因此我们怀疑可能是行方网络问题导致,可能在某些网络设备中加了某些网络策略,把tls验证的连接掐断了。咨询行方后,行方也认为有可能,但不敢确定,建议我们抓包分析。

5、于是在公网中分别抓了成功和失败的包,如下图所示。
Android推送注册失败问题排查_第1张图片
图4 成功时的包

Android推送注册失败问题排查_第2张图片
图5 失败时的包
从图4可以看到,在TLS握手过程中,客户端向ejabberd发送Client Hello请求后,后面会有个ejabberd的Server Hello、certificate、server hello done应答包;而对比图5,发现ejabberd没有返回Server Hello包,而是回了个结束TCP会话的Reset包,从而导致整个TLS握手没有成功,TCP连接中断。
从这里可以得出结论,服务器端没有响应Client Hello,并发了个中断会话的包导致握手失败。更加确定是网络策略或防火墙原因导致。
6、之后又从服务器的网关处进行抓包,如下图所示。(说明下,图5和图6是同一个请求,只是抓包的位置不同。图5在公网中抓的包,图6在内网中抓的。)
Android推送注册失败问题排查_第3张图片
图6 网关处失败时的包
由于抓包工具不同,图6的显示略显不同。观察图6,第55个包是Client Hello的请求包,第57个是Reset包,粗看和图5差不多,但细看会发现两个问题:1、多了第56个包,图5上没有类似的包。对比图4和分析它的长度、内容后我们基本确定第56个包应该是服务器返回的Server Hello包;2、第57个的Reset包对比图5上的Reset包发现,他们的源、目地址不同,正好相反。也就是说图5是服务器告诉客户端TCP请求中断了,而图6是客户端告诉服务器TCP请求中断了。
请教网络工程师分析后得出结论:
针对问题1,服务器已经返回Server Hello的包,但是由于某些原因(如被网络策略拦截、防火墙等)没有正确的发送到公网中,因此在公网中没抓到。
针对问题2,如果确实中间有设备把这一请求中断,那作为中间方会对两边(客户端和服务器)都会发送一个RST包,那对于客户端来说,中间方是服务器,因此源地址是服务器地址;服务器情况就相反。
也就是说我们的猜测完全能解释清楚这两个问题。
7、把这一分析结果给行方网络部后,他们就尝试了下把服务器ip加入网络设备的直通名单中,测试后发现问题解决。

经验分享
分析过程一波三折,为了排查问题走了很多弯路。其中收获了几点经验:
1、如果从日志上看不到有价值的信息,建议通过抓包的方式查找问题。
2、特别是生产环境问题排查,抓包需要在内外网同时抓,然后对比,可以很大程度上排除网络方面的原因。
3、由于不了解网络的结构,建议把抓到的包请相关网络人员分析,能更快得出结论。

你可能感兴趣的:(Erlang)