相关文章推荐
酷酷的羊肉串  ·  npm安装 (high ...·  6 月前    · 
温文尔雅的砖头  ·  android service 广播 ...·  1 年前    · 
精彩文章免费看

Nginx配置之WebSocket配置

引言

WebSocket 在云服务器上的配置,会出现一些异常情况,例如:WebSocket无法正常访问到,WebSocket断开连接等。

本文意在解决上述出现的一些故障现象。

1. Nginx 支持WebSocket的配置

server {
      listen   80;
      server_name localhost;
      location /sell {
        proxy_pass   http://127.0.0.1:8080/; // 代理转发地址
        proxy_http_version 1.1;
        proxy_read_timeout   3600s; // 超时设置
        // 启用支持websocket连接
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";

重要的是这两行,它表明是websocket连接进入的时候,进行一个连接升级将http连接变成websocket的连接。

proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout; 表明连接成功以后等待服务器响应的时候,如果不配置默认为60s;
proxy_http_version 1.1; 表明使用http版本为1.1 

据参考资料 : nginx配置websocket(官方)来编写一份标准配置文件。

map $http_upgrade $connection_upgrade {
    default upgrade;
    '' close;
upstream wsbackend{
    server ip1:port1;
    server ip2:port2;
    keepalive 1000;
server {
    listen 20038;
    location /{
        proxy_http_version 1.1;
        proxy_pass http://wsbackend;
        proxy_redirect              off;
        proxy_set_header            Host $host;
        proxy_set_header            X-Real-IP $remote_addr;
        proxy_read_timeout          3600s;
        proxy_set_header            X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
map $http_upgrade $connection_upgrade {
    default upgrade;
    '' close;
1. 如果 $http_upgrade 不为 '' (空),则 $connection_upgrade 为 upgrade
2. 如果 $http_upgrade 为 '' (空),则 $connection_upgrade 为 close
upstream wsbackend{
    server ip1:port1;
    server ip2:port2;
    keepalive 1000;
表示的是 nginx负载均衡
1. 两台服务器 (ip1:port1)和(ip2:port2)
2. keepalive 1000 表示的是每个nginx进程中上游服务器保持的空闲连接,当空闲连接过多时,会关闭最少使用的空闲连接.当然,这不是限制连接总数的,可以想象成空闲连接池的大小.设置的值应该是上游服务器能够承受的
server {
    listen 80;
    location /{
        proxy_http_version 1.1;
        proxy_pass http://wsbackend;
        proxy_redirect  off;
        proxy_set_header  Host $host;
        proxy_set_header  X-Real-IP $remote_addr;
        proxy_read_timeout  3600s;
        proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
表示的是监听的服务器的配置
1. listen 80                                    表示 nginx 监听的端口
2. locations /                                  表示监听的路径(/表示所有路径,通用匹配,相当于default)
3. proxt_http_version 1.1                       表示反向代理发送的HTTP协议的版本是1.1,HTTP1.1支持长连接
4. proxy_pass http://wsbackend;                 表示反向代理的uri,这里可以使用负载均衡变量
5. proxy_redirect off;                          表示不要替换路径,其实这里如果是/则有没有都没关系,因为default也是将路径替换到proxy_pass的后边
6. proxy_set_header Host $host;                 表示传递时请求头不变, $host是nginx内置变量,表示的是当前的请求头,proxy_set_header表示设置请求头
7. proxy_set_header X-Real-IP $remote_addr;        表示传递时来源的ip还是现在的客户端的ip
8. proxy_read_timeout 3600s;                    表示两次请求之间的间隔超过 3600s 后才关闭这个连接,默认的60s.自动关闭的元凶
9. proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;        表示X-Forwarded-For头不发生改变
10. proxy_set_header Upgrade $http_upgrade;        表示设置Upgrade不变
11. proxy_set_header Connection $connection_upgrade;        表示如果 $http_upgrade为upgrade,则请求为upgrade(websocket),如果不是,就关闭连接

简要版本:

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;

2. Nginx代理webSocket经常出现中断的解决方案, 如何保持长连接

原因是: nginx等待客户端第一次通讯和第二次通讯的时间差,超过了它设定的最大等待时间,简单来说就是,超时,所以就断了webSocket连接,开始上解决步骤。

解决方案一

其实只要配置nginx.conf的对应localhost里面的这几个参数就好

  • proxy_connect_timeout
  • proxy_read_timeout
  • proxy_send_timeout
  • http {
        server {
            location / {
                root   html;
                index  index.html index.htm;
                proxy_pass http://webscoket; 
                proxy_http_version 1.1; 
                proxy_connect_timeout 4s; #配置点1
                proxy_read_timeout 60s; #配置点2,如果没效,可以考虑这个时间配置长一点
                proxy_send_timeout 12s; #配置点3
                proxy_set_header Upgrade $http_upgrade; #这是webSocket的配置,与此解决方案无关
                proxy_set_header Connection "Upgrade"; #这是webSocket的配置,与此解决方案无关
    

    关于配置点2的解释
    备注:这个是服务器对客户端等待最大的时间,也就是说,当你webSocket使用nginx转发的时候,对于上面的配置点2来说,如果60秒内没有通讯,依然是会断开的,所以,你可以按照你的需求来设定。

    比如说,我设置了10分钟,那么如果我10分钟内有通讯,或者10分钟内有做心跳的话,是可以保持连接不中断的,详细看个人需求

    解决方案二

    发心跳包,原理就是在有效的再读时间内进行通讯,重新刷新再读时间

    3. Nginx超时设置详解

    上面所讲的超时设置,显得有些模糊,索性将涉及到的超时设置一并归拢了吧。

    Nginx处理的每个请求均有相应的超时设置。如果做好这些超时时间的限定,判定超时后资源被释放,用来处理其他的请求,以此提升 Nginx 的性能。

    1. client_header_timeout

    客户端向服务端发送一个完整的 request header 的超时时间。如果客户端在指定时间内没有发送一个完整的 request headerNginx 返回 HTTP 408(Request Timed Out)。

    client_header_timeout time

    http, server

    指定等待client发送一个请求头的超时时间(例如:GET / HTTP/1.1).仅当在一次read中,没有收到请求头,才会算成超时。如果在超时时间内,client没发送任何东西,nginx返回HTTP状态码408(“Request timed out”)

    接收客户端header超时, 默认60s, 如果60s内没有收到完整的http包头, 返回408

    Syntax: client_header_timeout time;
    Default: client_header_timeout 60s;
    Context:  http, server
    Defines a timeout for reading client request header. If a client does not transmit the entire header within this time,
    the 408 (Request Time-out) error is returned to the client.
    
    2. client_body_timeout

    指定客户端与服务端建立连接后发送 request body 的超时时间。如果客户端在指定时间内没有发送任何内容,Nginx 返回 HTTP 408(Request Timed Out)。

    client_body_timeout time

    http, server, location

    该指令设置请求体(request body)的读超时时间。仅当在一次readstep中,没有得到请求体,就会设为超时。超时后,nginx返回HTTP状态码408(“Request timed out”)

    接收客户端body超时, 默认60s, 如果连续的60s内没有收到客户端的1个字节, 返回408

    Syntax: client_body_timeout time;
    Default: 
    client_body_timeout 60s;
    Context:  http, server, location
    Defines a timeout for reading client request body. The timeout is set only for a period between two successive read operations, not for the transmission of the whole request body.
    If a client does not transmit anything within this time,
    the 408 (Request Time-out) error is returned to the client.
    
    3. keepalive_timeout

    HTTP 是一种无状态协议,客户端向服务器发送一个 TCP 请求,服务端响应完毕后断开连接。

    如果客户端向服务器发送多个请求,每个请求都要建立各自独立的连接以传输数据。

    HTTP 有一个 KeepAlive 模式,它告诉 webserver 在处理完一个请求后保持这个 TCP 连接的打开状态。若接收到来自客户端的其它请求,服务端会利用这个未被关闭的连接,而不需要再建立一个连接。

    KeepAlive 在一段时间内保持打开状态,它们会在这段时间内占用资源。占用过多就会影响性能。

    Nginx 使用 keepalive_timeout 来指定 KeepAlive 的超时时间(timeout)。指定每个 TCP 连接最多可以保持多长时间。Nginx 的默认值是 75 秒,有些浏览器最多只保持 60 秒,所以可以设定为 60 秒。若将它设置为 0,就禁止了 keepalive 连接。

    keepalive_timeout timeout [ header_timeout ]

    http, server, location

    第一个参数指定了与clientkeep-alive连接超时时间。服务器将会在这个时间后关闭连接。
    可选的第二个参数指定了在响应头Keep-Alive: timeout=time中的time值。这个头能够让一些浏览器主动关闭连接,这样服务器就不必要去关闭连接了。没有这个参数,nginx不会发送Keep-Alive响应头(尽管并不是由这个头来决定连接是否“keep-alive”)
    两个参数的值可不相同

    keepalive时间,默认75s,通常keepalive_timeout应该比client_body_timeout

    Syntax: keepalive_timeout timeout [header_timeout];
    Default: 
    keepalive_timeout 75s;
    Context:  http, server, location
    The first parameter sets a timeout during which a keep-alive client connection will stay open on the server side. The zero value disables keep-alive client connections.
    The optional second parameter sets a value in the “Keep-Alive: timeout=time” response header field. Two parameters may differ.
    
    The “Keep-Alive: timeout=time” header field is recognized by Mozilla and Konqueror. 
    MSIE closes keep-alive connections by itself in about 60 seconds.
    
    4. lingering_timeout
    lingering_timeout time

    http server location

    lingering_close生效后,在关闭连接前,会检测是否有用户发送的数据到达服务器,如果超过lingering_timeout时间后还没有数据可读,就直接关闭连接;否则,必须在读取完连接缓冲区上的数据并丢弃掉后才会关闭连接。

    Syntax: lingering_timeout time;
    Default: 
    lingering_timeout 5s;
    Context:  http, server, location
    When lingering_close is in effect, this directive specifies the maximum waiting time for more client data to arrive. If data are not received during this time,
    the connection is closed. Otherwise, the data are read and ignored, and nginx starts waiting for more data again.
    The “wait-read-ignore” cycle is repeated, but no longer than specified by the lingering_time directive.
    
    5. resolver_timeout
    resolver_timeout time

    http server location

    该指令设置DNS解析超时时间

    域名解析超时,默认30s

    Syntax: resolver_timeout time;
    Default: 
    resolver_timeout 30s;
    Context:  http, server, location
    Sets a timeout for name resolution, for example:
    resolver_timeout 5s;
    
    6. proxy_connect_timeout
    proxy_connect_timeout time

    http server location

    该指令设置与upstream server的连接超时时间,有必要记住,这个超时不能超过75秒。
    这个不是等待后端返回页面的时间,那是由proxy_read_timeout声明的。如果你的upstream服务器起来了,但是hanging住了(例如,没有足够的线程处理请求,所以把你的请求放到请求池里稍后处理),那么这个声明是没有用的,由于与upstream服务器的连接已经建立了。

    nginxupstream server的连接超时时间

    Syntax: proxy_connect_timeout time;
    Default: 
    proxy_connect_timeout 60s;
    Context:  http, server, location
    Defines a timeout for establishing a connection with a proxied server. It should be noted that this timeout cannot usually exceed 75 seconds.
    
    7. proxy_read_timeout
    proxy_read_timeout time

    http server location

    该指令设置与代理服务器的读超时时间。它决定了nginx会等待多长时间来获得请求的响应。这个时间不是获得整个response的时间,而是两次reading操作的时间。

    nginx接收upstream server数据超时, 默认60s, 如果连续的60s内没有收到1个字节, 连接关闭

    Syntax: proxy_read_timeout time;
    Default: 
    proxy_read_timeout 60s;
    Context:  http, server, location
    Defines a timeout for reading a response from the proxied server. The timeout is set only between two successive read operations,
    not for the transmission of the whole response. If the proxied server does not transmit anything within this time, the connection is closed.
    
    8. proxy_send_timeout
    proxy_send_timeout time

    http server location

    这个指定设置了发送请求给upstream服务器的超时时间。超时设置不是为了整个发送期间,而是在两次write操作期间。如果超时后,upstream没有收到新的数据,nginx会关闭连接

    nginx发送数据至upstream server超时, 默认60s, 如果连续的60s内没有发送1个字节, 连接关闭

    Syntax: proxy_send_timeout time;
    Default: 
    proxy_send_timeout 60s;
    Context:  http, server, location
    Sets a timeout for transmitting a request to the proxied server. The timeout is set only between two successive write operations,
    not for the transmission of the whole request. If the proxied server does not receive anything within this time, the connection is closed.
    
    9. proxy_upstream_fail_timeout(fail_timeout)
    server address [fail_timeout=30s]

    upstream

    Upstream模块下 server指令的参数,设置了某一个upstream后端失败了指定次数(max_fails)后,该后端不可操作的时间,默认为10秒

    最后编辑于:2019-09-19 22:58