一、前言
前两天销售数据实时刷新功能开发测试完成,开开心心部署到生产环境,然后直接懵逼傻眼了,竟然连接不上WebSocket服务端,浏览器端请求头报 Provisional headers are shown 信息,然后采用一系列操作排查问题。
友情链接
1、WebSocket实战之一
二、排查问题步骤
1、怀疑服务端WebSocket对应的8098端口被防火墙关闭了,登录AWS查看出入站规则,入站允许8098,出站允许所有端口。
2、在服务端检测8098端口启动情况,netstat -anp | grep :8098,然后发现监听在8098端口的协议是TCP6,核对出入站访问规则发现只有IP4没有IP6但出入站规则无法设置IP6,然后在在java 命令参数中加入 -Djava.net.preferIPv4Stack=true,重新启动,但仍然无效。
注:其实监听在TCP6上是正常的,TCP6很好兼容TCP4.
3、在本地机器直接使用 telnet 服务器地址 8098,可以正常连接,说明远程服务器端口没有被限制,这时又傻眼了。
4、怀疑是Java写的WebSocket服务端代码有问题,然后用WebSocket实战之一 极简node.js服务端例子部署上去,发现同样无法连接。。
5、这时开始怀疑服务端到底有没有收到数据包,使用tcpdump监听8098端口,发现根本没有数据包进来,命令如下:tcpdump -ieth0 port 8098.
6、代码回滚,回家睡觉,反正数据没有实时刷新也没啥大不了的。
7、第二天忙完一些事情后,想想换一下浏览器试试,用了Safari,额竟然可以连接。。
8、最后发现我们技术所有人都配置了PAC,因为我们应用部署在AWS悉尼,不配置VPN是访问不了的,把VPN关掉就完全正常。
注:这里一个奇怪问题是VPN的配置应该是针对整台电脑的,不知为何safari没有走VPN
三、PAC文件
我们在使用一些VPN时,它会提供一个PAC文件,然后你在自动代理配置把该文件URL配置进去,一个PAC文件包含一个JavaScript形式的函数“FindProxyForURL(url, host)”。这个函数返回包含一个或多个访问规则的字符串。用户代理根据这些规则适用一个特定的代理或者直接访问。当一个代理服务器无法响应的时候,多个访问规则提供了其他的后备访问方法。浏览器在访问其他页面以前,首先访问这个PAC文件.一个PAC文件大致如下。
四、websocket与PAC
如果是未加密的WebSocket信息流通过透明的代理传输到WebSocket服务器,实践中连接很可能失败,因为在这种情况下,当代理服务器将请求转发到(WebSocket)服务器时,将会被剥去一些特定的消息头,包括 Connection消息头。
但并非所有的代理服务器在所期待的代理行为方面都遵循HTTP标准。比如一些代理服务器被配置为不删除Connection: Upgrade消息头,并将其传送给WebSocket服务器,反过来服务器又会发送101 Web Socket Protocol Handshake响应。而当客户端或服务器开始发送第一个WebSocket帧时问题就出现了。因为这帧数据与代理服务器所期待的任何事物(比如常规的 HTTP流量)都不相同,就可能会产生一些异常,除非代理服务器被特别配置为处理WebSocket流量。
注:后来邮件VPN提供方他们答应调整了代理规则,但还是无效。有人有相关经验的微信我提供一下解决方案,是否在客户端代码可以指定websocket流量绕过所有代理,谢谢啦。有空要读一下RFC6455.