我有一个 Java 应用程序,可以与远程服务器建立 SSL 连接。
当我从开发机器运行应用程序时(该服务器在地理位置上更接近远程服务器,位于不同的网络上,并且运行的是 Win7) 连接只需不到一秒钟即可完成。
当我从生产机器运行应用程序时(索拉里斯)SSL 连接需要超过 10 秒才能完成。
我想了解如何才能加快这个连接时间。
我已经打开调试跟踪(使用扩展的打印流来记录经过的时间):
-Djavax.net.debug=全部
我可以看到,大部分丢失的时间发生在客户端完成客户端更改密码规范之后,即写入和读取之间。
<Elapsed [4249]ms> *** Finished
<Elapsed [4251]ms> ***
<Elapsed [4251]ms> [write] MD5 and SHA1 hashes: len = 16
<Elapsed [4254]ms> Padded plaintext before ENCRYPTION: len = 48
<Elapsed [4258]ms> main, WRITE: TLSv1 Handshake, length = 48
<Elapsed [11230]ms> main, READ: TLSv1 Change Cipher Spec, length = 1
<Elapsed [11231]ms> JsseJce: Using cipher AES/CBC/NoPadding from provider SunJCE
<Elapsed [11360]ms> main, READ: TLSv1 Handshake, length = 48
<Elapsed [11360]ms> Padded plaintext after DECRYPTION: len = 48
<Elapsed [11364]ms> *** Finished
我可以考虑哪些选项来帮助加快握手速度?
- 正在更新 JRE?服务器当前运行的是 1.4.2 版本。
- 反向 DNS?我看到一些建议说反向 DNS 可以帮助加快 SSL 握手速度。我的开发服务器和生产服务器目前都没有使用反向 DNS。
- 网络故障排除 — 网络团队指示网络正常吗?
- 增加 CPU/内存 - 监控表明我们在握手期间没有达到内存或 CPU 的 100%?
- /dev/random?我曾看到过一些参考资料,称在 Solaris 上,握手过程中使用的随机数据访问 /dev/random 可能会很慢?
--
参考:
本文详细介绍了 SSL 握手 – 向下滚动到 SSL 协议部分,其中有图表和注释,解释了握手的 15 个步骤过程:
http://docs.oracle.com/javase/1.5.0/docs/guide/security/jsse/JSSERefGuide.html#SSLOverview
本文描述了完整的 SSL 握手,并提供了调试消息以供参考:
http://docs.oracle.com/javase/1.5.0/docs/guide/security/jsse/ReadDebug.html
-- 编辑
在问题网络内的另一台机器上进行测试时,出现了一些有趣的结果。SSL 握手的前 10 个步骤发生得快了两倍,但“完成”阶段的延迟写入占用了总握手时间的 80%。
<Elapsed [1816]ms> main, WRITE: TLSv1 Handshake, length = 48
<Elapsed [10078]ms> main, READ: TLSv1 Change Cipher Spec, length = 1
答案1
您是否尝试过从同一站点的另一台机器进行连接,速度是否仍然一样慢?远程机器是否也是 Solaris?
我想说,如果您可以先在相同的机器上进行测试,请尝试更新 JVM。
对于反向 DNS,在 /etc/hosts 中放置一个条目就足够了。
Solaris 机器的型号和操作系统版本是什么?有些机器有加密芯片,你可以试试看它是否已启用。
答案2
该问题的这一特定实例的原因是服务器上的反向 DNS 查找失败。
这是由于客户端的 DNS 名称服务器发生变化而导致的,但服务器端却没有接收到该变化。
可以使用客户端和服务器计算机上的 Wireshark 隔离此问题,并可以使用以下方法确认:dig
dig @namserverURL -x serverIP +trace
一旦解决了 DNS 问题,SSL 握手速度就会大大提高。