首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

一次由你飞IOS推送问题排查全过程

内容来源:工业互联网研发--冯孟 原创

发现问题

在上周一个将要下班的夜晚,小祥突然和我打招呼,说IOS推送修复的更新包上线后存在问题,后台报错。

顿时有点惊慌失措,功能我都是在我自己外网机测试好的,怎么可能出问题!

连忙跑到小祥那里看报错详情,报错如下:

重现问题

看到这个问题后,心里一阵窃喜,这个报错我好像以前遇到过,因为给IOS发推送消息内部是通过给苹果服务器发https消息实现的,Https基于SSL\TLS协议实现的,估计是SSL\TLS协议握手过程中不信任服务端证书导致的,由于不能冒然在线上修改解决问题,于是获取推送相关信息(设备token等)后,到自己电脑上去运行一下,看是否能重现问题。

啪啦啪啦,代码修改完毕,点运行坐等错误出现。

5秒钟过后,发现推送消息发送成功了,没有出现报错,顿时一脸懵!

心里想,代码都是完全一样的啊,怎么线上报错,我这却是好的呢???不应该啊(对小祥说的)

纠结了一会,静下心来看看是否有什么不同

代码肯定是一样的,应该不是代码原因==》其次推送设备是一样的,应该不是手机问题==》那么。。。

扫了一眼工程目录,看到了jdk8,而由你飞线上使用的是jdk7,只有这个不同了。

于是我将自己工程的jdk8换成jdk7试一下,同样的报错终于出现了!

寻找原因

按照之前说的,围绕着以前的经验,这hand_failure应该是SSL\TLS握手过程中不信任服务端证书导致的,办法很简单,去苹果官网找苹果服务端提供的证书,导入到java的证书信任库cacert文件中即可。

啪啦啪啦,下载了证书GeoTrust_Global__CA.cer文件,并用keytool工具导入到了cacert文件中,发现已经有这个证书了,仍然导入 ,再次运行代码,等待问题解决的那一刻。

结果还是报错,怎么办?

怎么办?

心里又慌张起来,自己没招了,接下来只能百度啦,一翻搜索,网上结论几乎都是证书信任问题,和自己的招式一样!

网上了解一翻,SSL\TLS握手过程大约如下:

大致过程是:

客户端发送clientHello消息,告诉服务端我使用的TLS版本与加密套件等。

服务器返回serverHello消息,告诉自己选择哪个TLS协议版本与加密套件等。

服务器发送Certification消息,将自己的数字证书(包括服务器名称、CA和公钥)作为消息内容发给客户端。

客户端Certificate verify校验服务器的数字证书的有效性。

客户端Change cipher spec选择加密套件并生成会话密钥(客户端与服务器之间后续的数据传输将使用此会话密钥)。

客户端、服务器之间发送加密数据。

记得jvm有一个的参数,可以把SSL\TLS的握手过程都在控制台通过日志显示出来。

Ok,既然知道了握手过程,那就把SSL\TLS的日志显示出来看一下吧,看看是什么阶段出现的问题,运行过后日志如下:

如上图,说明GeoTrust_Global.cer证书确实已经添加到信任库中了

如上图,报错发生在clientHello发送之后,在读服务端返回的serverHello消息时,却读到的是警告信息,然后网络就断开了,就好像你在和服务器打招呼,然后服务器回复了一个滚蛋一样!

百思不得其解?

准备放弃

这时看到小祥走过来了

小祥:“问题解决的怎么样了,啥情况啊”

:“还不知道,本来以为很简单,实际上并没有,jdk8可以,7不行”

小祥:“好吧”

然后小祥就这样回到座位上了。

我也只能默默地继续查找问题原因了,大概过了40分钟吧,感觉已经查不到了,看了看小祥,为了他能早点回家睡觉,我想还是直接升级吧。

:”要不升级jdk8吧“

小祥:”能行吗“

:”……能行,jdk都是向前兼容的,要是降级就会有问题,升级一般不会有问题的“

小祥:”……好的“

小祥去升级jdk8了,本来我应该站在小祥身后等待问题被解决,但我还是想在这期间查一查其中原因,于是又琢磨了一翻

发现真相

以前由你飞升级jdk7,就是因为苹果强制开发者必须使用Https,且其中TLS协议要V1.2版本,而jdk7才开始支持==》现在报错会不会…

赶紧使用TLSv1.2试一下,在jvm运行时加参数即可强制https使用TLSv1.2版本协议,加完后运行…

报错依旧,那还有那里可能会有问题呢?

于是我将jdk7运行之后的网络日志与jdk8下运行之后的网络日志拿出来对比看,突然注意到某一点上,即TLS协议的加密套件不同,如下图:

jdk7的调试信息如下 :

jdk8的调试信息如下:

jdk8的TLS握手在服务端ServerHello之后,选择的加密套件是,而jdk7中可供选择的加密套件中没有,问题差不多清晰了,应该是jdk7中的加密套件,苹果服务器觉得太老,都不支持,那么如果我使用jdk8,将加密套件强制使用jdk7中的加密套件呢,应该也是有问题的

于是如下图,在jvm运行时加参数,强制jdk8使用jdk7的加密套件,运行过后,果然报错了

然后去查了一个jdk8的新增特性日志,发现中AES加密算法的GCM模式在jdk8中才支持。

那么问题原因基本全部搞清楚了,小祥升级jdk8后也报告推送正常,此时已是10点多,两人写写日报赶紧回家去了……

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180322G0MM8500?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券