本文中的nginx版本:nginx/1.16.1
话不多说,直接上配置:
server { listen 80; server_name test.css3er.com; index index.html index.htm index.php; root /home/wwwroot/default; autoindex on; #显示目录列表 autoindex_exact_size on; #显示出文件的确切大小,单位是bytes autoindex_localtime on; #显示的文件时间为文件的服务器时间 #error_page 404 /404.html; # Deny access to PHP files in specific directory #location ~ /(wp-content|uploads|wp-includes|images)/.*\.php$ { deny all; } include enable-php.conf; location /nginx_status { stub_status on; access_log off; } # 添加websocket的反向代理配置 location /ws/ { proxy_pass http://192.168.1.101:6688/; # websocket服务器 不用管ws:// 根据自己的实际情况进行调整(这一步必须有) proxy_http_version 1.1; # 代理http协议的版本,因为这里是代理websocket协议,所以http协议使用1.1 用于keepalive连接 也就是保持长连接(这一步必须有) proxy_set_header Upgrade "websocket"; # 表示要“升级”成websocket协议(这一步必须有) # proxy_set_header Upgrade $http_upgrade; 这个和上面的proxy_set_header Upgrade "websocket";是一个意思,两个写其中一个即可 proxy_set_header Connection "Upgrade"; # 表示要求协议“升级”,也就是说这不是一个普通的http协议 # proxy_set_header X-real-ip $remote_addr; # 这个没啥好解释的(这一步可以没有) # proxy_set_header X-Forwarded-For $remote_addr;# 标记通过http代理或负载均衡方式连接到web服务器的客户端最原始的ip地址的http请求头字段(这一步可以没有) } location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$ { expires 30d; } location ~ .*\.(js|css)?$ { expires 12h; } location ~ /.well-known { allow all; } location ~ /\. { deny all; } access_log /home/wwwlogs/access.log; }
以上就完成了一个最简单最普通的nginx反向代理websocket协议的配置,使用如下(这里以javascript代码举例)
没有使用nginx反向代理之前,我们使用websocket协议需要这么连接,直接写ip+端口 var ws = new WebSocket("ws://192.168.1.101:6688"); 使用了nginx反向代理之后: var ws = new WebSocket("ws://test.css3er.com/ws/"); 好处:假如说我们开发有测试服务器和线上正式服务器,项目在测试服和正式服之间的websocket的连接地址依然是ws://test.css3er.com/ws 如果没有使用nginx反向代理,那我们客户端的websocket连接地址在测试服的时候只能写测试服的ip+端口,项目上线的时候就要换成正式服的ip+端口。。很麻烦。。
支持跨域版:
server { listen 80; server_name test.css3er.com; index index.html index.htm index.php; root /home/wwwroot/default; autoindex on; autoindex_exact_size on; autoindex_localtime on; # 允许跨域相关配置 add_header Access-Control-Allow-Origin *; # 允许跨域请求的域, *代表所有 add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS'; # 允许请求的方法,如 GET/POST/OPTIONS add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization'; # 允许请求的header # 给OPTIONS添加204的返回,是为了处理在发送POST请求时nginx依然拒绝访问的错误 发送"预检请求"时,需要用到方法OPTIONS,所以服务器需要允许该方法 if ($request_method = 'OPTIONS') { return 204; } #error_page 404 /404.html; # Deny access to PHP files in specific directory #location ~ /(wp-content|uploads|wp-includes|images)/.*\.php$ { deny all; } include enable-php.conf; location /nginx_status { stub_status on; access_log off; } # 添加websocket的反向代理配置 location /ws/ { proxy_pass http://192.168.1.101:6688/; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "Upgrade"; } location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$ { expires 30d; } location ~ .*\.(js|css)?$ { expires 12h; } location ~ /.well-known { allow all; } location ~ /\. { deny all; } access_log /home/wwwlogs/access.log; }
nginx配置了反向代理,会有几个关于超时或连接关闭的选项配置需要注意下:
proxy_connect_timeout #与代理服务器建立连接时的超时时间。 proxy_read_timeout #从代理服务器读取响应的超时时间,也就是在配置的时间内,代理服务器没有响应的话,则断开连接。 proxy_send_timeout #代理服务器数据回传时间,就是在规定时间之内代理服务器必须传完所有的数据。 #以上几个配置选项的配置上下文都可以在http,server,location段内进行配置,同时,这个几个选项的默认时间都是60s(秒)
注意:我这里配置的反向代理websocket协议都是ws://(80端口),如果要配置成ssl,即wss:// 也很简单 和配置https差不多 就是一个证书的事,这里就不上demo了
默认情况下,Websocket的ws协议使用80端口。运行在TLS之上的时候,wss协议默认使用443端口。其实说白了,wss就是ws基于SSL 的安全传输,与https一样样的道理。
如果你的网站是https协议的,那你websocket连接的时候就不能使用 ws://了,浏览器会block掉连接,和https下不允许http请求一样。
websocket和http协议的相关概念补充
WebSocket和HTTP协议不同,但是WebSocket中的握手和HTTP中的握手兼容,它使用HTTP中的Upgrade协议头将连接从HTTP升级到WebSocket。这使得WebSocket程序可以更容易的使用现已存在的基础设施。例如,WebSocket可以使用标准的HTTP端口 80 和 443,因此,现存的防火墙规则也同样适用。
当客户端发过来一个Connection: Upgrade请求头时,nginx是不知道的,所以,当nginx代理服务器拦截到一个客户端发来的 Upgrade请求时,需要显式来设置Connection 、Upgrade 头信息,并使用 101(交换协议)返回响应,在客户端和代理服务器、后端服务器之间建立隧道来支持WebSocket。
当然,还需要注意一下,WebSocket仍然受到nginx缺省为60秒的proxy_read_timeout的影响。这意味着,如果你有一个程序使用了 WebSocket,但又可能超过60秒不发送任何数据的话,那你要么需要增加超时时间,你可以使用proxy_read_timeout指令来增加此超时时间 。或者,每过几秒钟就让代理服务器使用websocket协议发送一个ping的消息给后端服务器,以保持他们之间的联系。使用ping的解决方法有额外的好处,可以发现连接是否被意外关闭。
更具体文档详见nginx官方文档:http://nginx.org/en/docs/http/websocket.html
nginx配置websocket协议的反向代理
nginx通过在客户端和后端服务器之间建立起一条隧道来支持websocket。为了使nginx可以将来自客户端的Upgrade请求转发给后端服务器,Upgrade和Connection的头信息必须被显式的设置。如下所示:
location /ws/ { proxy_pass http://wsbackend; # 这里请根据自己的实际情况进行填写 proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; }
一旦完成以上设置,nginx就可以处理websocket连接了。
尾声:
本篇博文主要说一下在nginx中如何使用反向代理来代理WebSocket协议,并补充了一些websocket和http协议的一些基本区别。以及配合nginx使用域名方式建立连接,不使用 ip地址 + 端口号 连接 WebSocket,因为这种方式不够优雅,并且多个服务器之间进行切换的时候,客户端连接服务器时,需要改对应服务器的ip地址+端口号。
声明:禁止任何非法用途使用,凡因违规使用而引起的任何法律纠纷,本站概不负责。
精彩评论