客服 IM 类系统,一般都必定使用 WebSocket 协议,因此简单的了解和使用。
背景
网站为了实现推送技术,所用的技术一般都是轮询。轮询是在特定的时间间隔(比如每秒一次)由浏览器对服务器发出 HTTP 请求,然后由服务器返回最新的数据给客户端的浏览器。这种传统的模式一个很明显的缺点,就是浏览器需要不断的向服务器发出请求,然而 HTTP 请求都是完整的请求,不支持增量信息传输,因此传输中大部分可能是较长的头部信息,其中真正有效的数据可能只是很小的一部分,显然这样会浪费很多服务器资源。
在这种情况下,WebSocket 横空出世,HTML5 定义了 WebSocket 协议,能更好的节省服务器资源和带宽,并且能够更实时地进行通讯。
使用
WS 简介
WebSocket 是一种在单个 TCP 连接上进行全双工通讯的协议。使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。
WebSocket 是一种与 HTTP 不同的协议。两者都位于 OSI 模型的应用层,并且都依赖于传输层的 TCP 协议。虽然两者不同,但是 RFC 6455 中规定 WebSocket 默认通过 HTTP 端口 80 和 443 进行工作,并支持 HTTP 代理和中继,从而使其与 HTTP 协议兼容。为了实现兼容性,WebSocket 握手使用 HTTP Upgrade 请求头对 HTTP 协议更改为 WebSocket协议。
与 HTTP 不同,WebSocket 提供全双工通信。此外,WebSocket 还可以在 TCP 之上实现消息流。TCP 单独处理字节流,没有固有的消息概念。
WebSocket 协议规范将 ws(WebSocket) 和 wss(WebSocket Secure) 定义为两个新的 URI(统一资源标识符)方案,分别对应明文和加密连接(类似于 HTTP 与 HTTPS 的关系)。除了方案名称和片段ID(不支持#)之外,其余的URI组件都被定义为此 URI 的通用语法。
需要注意的是若网站使用了 HTTPS,则嵌套其中的 WS 协议会被屏蔽,必须使用 WSS 协议,具体报错如下
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.
小贴士:如果使用了插件或者 JS 等方式调用 WS 协议,需要全部改为 WSS 协议。
由于一般情况下 WebSocket 会默认调用 IP 方式,因此仅仅修改 URI 后可能会看到以下报错,这是由于证书和域名不匹配导致的。
WebSocket connection to 'wss://172.16.4.111:4232/websocket' failed: Error in connection establishment: net::ERR_SSL_PROTOCOL_ERROR
WS 简单反代
为了美观和访问方便,推荐用 WEB 服务对 WebSocket 进行反代,可以美化路径,同时可以完成 WSS 协议的过渡。
location /chat/ {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
反代后,直接调用 wss://www.domain.com/websocket
即可,在访问时可见其状态码为 101 Switching Protocols
且在响应头中可见字段 Connection: upgrade
。
小贴士:由于反向代理默认继承 proxy_read_timeout
属性,因此在默认情况下最长连接时长为一分钟,若对其有需求进行修改,则需要对其重新定义。
WS 复杂反代
下面为一个复杂示例,会自动检测客户端的请求头是否包含 "Upgrade"
字段
http {
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
...
location /chat/ {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
}
附录
参考链接
- WebSocket 结合 Nginx 实现域名及 WSS 协议访问 - CSDN
- WebSocket 是什么原理?为什么可以实现持久连接?Ovear的回答 - 知乎
- Module ngx_http_proxy_module - NGINX Documentation
本文由 柒 创作,采用 知识共享署名4.0
国际许可协议进行许可。
转载本站文章前请注明出处,文章作者保留所有权限。
最后编辑时间: 2020-04-09 10:36 AM