WebSocket 结合 Nginx 实现域名及 WSS 协议访问

简单了解一下 WebSocket

如今,不少网站为了实现推送技术,所用的技术都是轮询。轮询是在特定的的时间间隔(如每1秒),由浏览器对服务器发出HTTP请求,而后由服务器返回最新的数据给客户端的浏览器。这种传统的模式带来很明显的缺点,即浏览器须要不断的向服务器发出请求,然而HTTP请求可能包含较长的头部,其中真正有效的数据可能只是很小的一部分,显然这样会浪费不少的带宽等资源。
在这种状况下,HTML5定义了WebSocket协议,能更好的节省服务器资源和带宽,而且可以更实时地进行通信。
WebSocket一种在单个 TCP 链接上进行全双工通信的协议。使得客户端和服务器之间的数据交换变得更加简单,容许服务端主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只须要完成一次握手,二者之间就直接能够建立持久性的链接,并进行双向数据传输。html

以上信息摘自维基百科(https://zh.wikipedia.org/wiki/WebSocketnginx

简单点说,WebSocket 就是减少客户端与服务器端创建链接的次数,减少系统资源开销,只须要一次 HTTP 握手,整个通信过程是创建在一次链接/状态中,也就避免了HTTP的非状态性,服务端会一直与客户端保持链接,直到你关闭请求,同时由本来的客户端主动询问,转换为服务器有信息的时候推送。固然,它还能作实时通讯、更好的二进制支持、支持扩展、更好的压缩效果等这些优势。web

推荐一个知乎上叫 Ovear 的网友关于 WebSocket 原理的回答,嘻哈风格科普文,简直不要更赞了!地址:https://www.zhihu.com/question/20215561/answer/40316953后端

ws 和 wss 又是什么鬼?

Websocket使用 wswss 的统一资源标志符,相似于 HTTPHTTPS,其中 wss 表示在 TLS 之上的 Websocket ,至关于 HTTPS 了。如:浏览器

ws://example.com/chat
wss://example.com/chat

默认状况下,Websocket 的 ws 协议使用 80 端口;运行在TLS之上时,wss 协议默认使用 443 端口。其实说白了,wss 就是 ws 基于 SSL 的安全传输,与 HTTPS 同样样的道理。安全

若是你的网站是 HTTPS 协议的,那你就不能使用 ws:// 了,浏览器会 block 掉链接,和 HTTPS 下不容许 HTTP 请求同样,以下图:
ws_https服务器

Mixed Content: The page at 'https://domain.com/' was loaded over HTTPS, but attempted to connect to the insecure WebSocket endpoint 'ws://x.x.x.x:xxxx/'. This request has been blocked; this endpoint must be available over WSS.

这种状况,毫无疑问咱们就须要使用 wss:\\ 安全协议了,咱们是否是简单的把 ws:\\ 改成 wss:\\ 就好了?那试试呗。websocket

改好了,报错啦!!!
wss_ipmarkdown

VM512:35 WebSocket connection to 'wss://IP地址:端口号/websocket' failed: Error in connection establishment: net::ERR_SSL_PROTOCOL_ERROR

很明显 SSL 协议错误,说明就是证书问题了。记着,这时候咱们一直拿的是 IP地址 + 端口号 这种方式链接 WebSocket 的,这根本就没有证书存在好么,何况生成环境你也要用 IP地址 + 端口号 这种方式链接 WebSocket 吗?确定不行阿,要用域名方式链接 WebSocket 阿。负载均衡

Nginx 配置域名支持 WSS

不用废话,直接在配置 HTTPS 域名位置加入以下配置:

location /websocket {
    proxy_pass http://backend;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
}

接着拿域名再次链接试一下,不出意外会看 101 状态码:
upgrade_101

这样就完成了,在 HTTPPS 下以域名方式链接 WebSocket ,能够开心的玩耍了。

稍微解释一下 Nginx 配置
Nginx 自从 1.3 版本就开始支持 WebSocket 了,而且能够为 WebSocket 应用程序作反向代理和负载均衡。
WebSocket 和 HTTP 协议不一样,可是 WebSocket 中的握手和 HTTP 中的握手兼容,它使用 HTTP 中的 Upgrade 协议头将链接从 HTTP 升级到 WebSocket,当客户端发过来一个 Connection: Upgrade请求头时,Nginx 是不知道的,因此,当 Nginx 代理服务器拦截到一个客户端发来的 Upgrade 请求时,须要显式来设置ConnectionUpgrade 头信息,并使用 101(交换协议)返回响应,在客户端和代理服务器、后端服务器之间创建隧道来支持 WebSocket。

固然,还须要注意一下,WebSockets 仍然受到 Nginx 缺省为60秒的 proxy_read_timeout 的影响。这意味着,若是你有一个程序使用了 WebSockets,但又可能超过60秒不发送任何数据的话,那你要么须要增长超时时间,要么实现一个 ping 的消息以保持联系。使用 ping 的解决方法有额外的好处,能够发现链接是否被意外关闭。

更具体文档详见 Nginx 官方文档:http://nginx.org/en/docs/http/websocket.html

总结一下

这一篇文章主要了解一下 WebSocket 基本原理和一些使用用途,并解决在实际开发使用过程当中遇到的坑,HTTPS 下使用 wss 协议的问题,以及配合 Nginx 使用域名方式创建链接,不使用 IP地址 + 端口号 链接 WebSocket,由于这种方式不够优雅。

下一篇,全站升级 HTTPS 之路,并没你想象的那么简单。

原文地址:https://www.cnblogs.com/mafly/p/websocket.html
相关文章
相关标签/搜索