写点什么

Nginx 配置 Websocket

作者:EquatorCoco
  • 2023-11-22
    福建
  • 本文字数:2492 字

    阅读完需:约 8 分钟

WebSocket 和 HTTP 虽然是不同协议,但是两者“握手”方式兼容。通过 HTTP 升级机制,使用 HTTP 的 Upgrade 和 Connection 协议头的方式可以将连接从 HTTP 升级为 WebSocket。



Websocket 使用 ws 或 wss 的统一资源标志符,类似于 HTTPS,其中 wss 表示在 TLS 之上的 Websocket。如:


ws://example.com/wsapiwss://secure.example.com/
复制代码


Websocket 使用和 HTTP 相同的 TCP 端口,可以绕过大多数防火墙的限制。默认情况下,Websocket 协议使用 80 端口;运行在 TLS 之上时,默认使用 443 端口。


一个典型的 Websocket 握手请求如下:


客户端请求:


GET / HTTP/1.1Upgrade: websocketConnection: UpgradeHost: example.comOrigin: http://example.comSec-WebSocket-Key: sN9cRrP/n9NdMgdcy2VJFQ==Sec-WebSocket-Version: 13
复制代码


服务器回应:


HTTP/1.1 101 Switching ProtocolsUpgrade: websocketConnection: UpgradeSec-WebSocket-Accept: fFBooB7FAkLlXgRSz0BT3v4hq5s=Sec-WebSocket-Location: ws://example.com/
复制代码


关键点:


  • Connection 必须设置 Upgrade,表示客户端希望连接升级。


  • Upgrade 字段必须设置 Websocket,表示希望升级到 Websocket 协议。


知识点参考:《HTML5 WebSocket》


一、对 wss 与 nginx 代理 wss 的理解:


1、wss 协议实际是 websocket +SSL,就是在 websocket 协议上加入 SSL 层,类似 https(http+SSL)。


2、利用 nginx 代理 wss【通讯原理及流程】


  • 客户端发起 wss 连接连到 nginx


  • nginx 将 wss 协议的数据转换成 ws 协议数据并转发到 Workerman 的 websocket 协议端口


  • Workerman 收到数据后做业务逻辑处理


  • Workerman 给客户端发送消息时,则是相反的过程,数据经过 nginx/转换成 wss 协议然后发给客户端


二、Nginx 配置 Websocket 参数


示例一:某站点或域名下面代理配置


server {    listen       80;    server_name  域名;
proxy_http_version 1.1; ……
#启用支持websocket连接的配置 proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade";
location / { proxy_redirect off; proxy_pass http://myweb_backend; proxy_connect_timeout 60; proxy_read_timeout 600; proxy_send_timeout 600; }
}
复制代码


重要的是这两行,它表明是 websocket 连接进入的时候,进行一个连接升级将 http 连接变成 websocket 的连接。启用支持 websocket 连接:proxy_set_header Upgrade $http_upgrade;


proxy_set_header Connection "upgrade";


proxy read timeout 表明连接成功以后等待服务器响应的时候,如果不配置默认为 60s;


proxy_http_version 1.1;


表明使用 http 版本为 1.1


示例二:全部站点或全部服务的代理配置


上面的配置将 websocket 写到某个 server 里了。实际项目上 nginx 代理的可能是多个站点,多个服务,这就需要统一设置一下。另外对于低版本 nginx 的配置不支持"upgrade"参数的情况下可以这样写:


首先在 nginx 的全局块(一般是 http 块)里面加上 websocket 的参数映射


http {    include       mime.types;    default_type  text/html;    charset utf-8;
log_format proxy '$http_x_real_ip - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for" $request_time $upstream_response_time';
access_log /dev/stdout proxy;
sendfile on; tcp_nopush on; tcp_nodelay on;
keepalive_timeout 75; keepalive_requests 1000;
client_max_body_size 1020000M; client_body_buffer_size 256k; large_client_header_buffers 4 128k; client_header_buffer_size 32k; server_names_hash_max_size 512; server_names_hash_bucket_size 128;
#注意,必须加下面这段websocket的参数映射 map $http_upgrade $connection_upgrade { default upgrade; '' close; }
include /etc/nginx/conf.d/*.conf;}
复制代码


这里重要的是这四行:


注意,必须加下面这段 websocket 的参数映射


然后在你的 server 或者 location 块里面加上这两行即可:


server {    listen       80;    server_name  域名;
proxy_http_version 1.1; ……
#注意,必须加下面这段websocket的配置 proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade;
location / { proxy_redirect off; proxy_pass http://myweb_backend; proxy_connect_timeout 60; proxy_read_timeout 600; proxy_send_timeout 600; }
}
复制代码


  • 示例一和示例二配置一种就行。


状态码说明


注意:因为 websocket 是长连接,请求过程不关闭的所以一般连接状态码是 101(请求者已要求服务器切换协议,服务器已确认并准备切换。)


CloseEvent 接口的代码只读属性返回 WebSocket 连接关闭代码,指示服务器关闭连接的原因。


值:一个整数的 WebSocket 连接关闭范围为 1000-4999 的代码,指示服务器关闭连接的原因。websocket 连接关闭状态码:https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent/code


不支持 websocket 协议现象说明


网页控制台报错现象:


1)现象一:


网页控制台报"WebSocket connection to 'ws://' failed:<无报错信息>"


2)现象二:


网页控制台报"WebSocket connection to 'ws://' failed:Error during WebSocket handshake: Unexpected response code: 400"


3)现象三:网页控制台报"WebSocket connection to 'ws://' failed:The request timed out.


问题原因与处理方法:


1.代理/防火墙对访问端口只开通了 http 协议,未支持 websocket 协议。可以将代理/防火墙的 7 层转发改为 4 层转发,确认是否为 websocket 协议/长连接的支持问题。


2.代理 nginx 未支持 websocket 协议转发,检查 nginx 配置文件中的 Upgrade 和 Connection 配置。


文章转载自:熊仔其人

原文链接:https://www.cnblogs.com/xiongzaiqiren/p/Nginx_Websocket.html

用户头像

EquatorCoco

关注

还未添加个人签名 2023-06-19 加入

还未添加个人简介

评论

发布
暂无评论
Nginx配置Websocket_HTTP_EquatorCoco_InfoQ写作社区