• Nginx反向代理WebSocket(WSS)


    1. WebSocket协议

    WebSocket 协议提供了一种创建支持客户端和服务端实时双向通信Web应用程序的方法。作为HTML5规范的一部分,WebSockets简化了开发Web实时通信程序的难度。目前主流的浏览器都支持WebSockets,包括火狐、IE、Chrome、Safari以及Opera等,而且,越来越多的服务器应用框架也开始支持WebSockets。

    要在企业产品中使用WebSockets,为满足高性能和高可用性,需要多个WebSocket服务器。负载均衡层需要支持WebSocket协议。Nginx从1.3版起就开始支持WebSocket协议,而且可以担当WebSocket应用程序的反向代理以及实现负载均衡。

    WebSocket协议和HTTP协议不同,但是WebSocket协议的握手和HTTP是兼容的,它使用HTTP的Upgrade协议头将连接从HTTP连接升级到WebSocket连接。这个特性使得WebSocket应用程序可以很容易地应用到现有的基础设施。例如,WebSocket应用可以使用标准的80和443 HTTP端口,因此可以通过现有的防火墙设施。

    WebSockets应用程序会在客户端和服务器之间建立一个长连接,使得开发实时应用很容易。HTTP的Upgrade协议头机制用于将连接从HTTP连接升级到WebSocket连接,Upgrade机制使用了Upgrade协议头和Connection协议头。反向代理服务器在支持WebSocket协议方面面临着一些挑战。挑战之一是WebSocket是一个逐段转发(hop-by-hop)协议,因此当代理服务器拦截到来自客户端的Upgrade请求时,代理服务器需要将自己的Upgrade请求发送给后端服务器,包括适合的请求头。而且,由于WebSocket连接是长连接,与传统的HTTP端连接截然不同,故反向代理服务器还需要允许这些连接处于打开(Open)状态,而不能因为其空闲就关闭了连接。

    NGINX支持WebSocket。对于NGINX将升级请求从客户端发送到后台服务器,必须明确设置Upgrade和Connection标题。

    2. Nginx配置

     Nginx通过在客户端和后端服务器之间建立隧道来支持WebSockets通信。为了让Nginx可以将来自客户端的Upgrade请求发送到后端服务器,Upgrade和Connection的头信息必须被显式的设置。

    1)编辑nginx.conf,在http区域内一定要添加下面配置:
    map $http_upgrade $connection_upgrade {
        default upgrade;
        '' close;
    }
     
    map指令的作用:
    该作用主要是根据客户端请求中$http_upgrade 的值,来构造改变$connection_upgrade的值,即根据变量$http_upgrade的值创建新的变量$connection_upgrade,
    创建的规则就是{}里面的东西。其中的规则没有做匹配,因此使用默认的,即 $connection_upgrade 的值会一直是 upgrade。然后如果 $http_upgrade为空字符串的话,
    那值会是 close。
     
     
    2)编辑vhosts下虚拟主机的配置文件,在location匹配配置中添加如下内容:
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "Upgrade";
     
    示例如下:
    upstream socket.kevin.com {
        hash $remote_addr consistent;
        server 10.0.12.108:9000;
        server 10.0.12.109:9000;
    }
     
     location / {
                proxy_pass http://socket.kevin.com/;
                proxy_set_header Host $host:$server_port;
                proxy_http_version 1.1;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection "upgrade";
            }

    3)可能会出现跨域问题,server区块填写以下跨域配置即可

    add_header Access-Control-Allow-Origin *;
    add_header Access-Control-Allow-Methods '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';
    if ($request_method = 'OPTIONS') {
    return 204;
    }

     一旦我们完成以上设置,Nginx就可以处理WebSocket连接了

    proxy_http_version 1.1;,为什么使用http1.1协议?(https://blog.csdn.net/moxiaomomo/article/details/74734565)

    设置代理使用的HTTP协议版本。默认使用的版本是1.0,而1.1版本则推荐在使用keepalive连接时一起使用。

    因为http1.0不支持keepalive特性,当没有使用http1.1的时候,后端服务会返回101错误,然后断开连接。

    map的作用

    1.map的作用主要是根据客户端请求中 $http_upgrade 的值,来构造改变 $connection_upgrade 的值,即根据变量 $http_upgrade 的值创建新的变量 $connection_upgrade,创建的规则就是 {} 里面的东西,上图代码中(第一个标记点)的规则没有做匹配,因此使用默认的,即 $connection_upgrade 的值会一直是 upgrade。然后如果 $http_upgrade为空字符串的话,那值会是 close。

    HTTP的Upgrade协议头

    HTTP的Upgrade协议头机制用于将连接从HTTP连接升级到WebSocket连接,Upgrade机制使用了Upgrade协议头和Connection协议头;为了让Nginx可以将来自客户端的Upgrade请求发送到后端服务器,Upgrade和Connection的头信息必须被显式的设置。

    3. Nginx代理WebSocket保持长连接的方案

    现象描述:用nginx反代代理某个业务,发现平均1分钟左右,就会出现webSocket连接中断,然后查看了一下,是nginx出现的问题。
    产生原因:nginx等待第一次通讯和第二次通讯的时间差,超过了它设定的最大等待时间,简单来说就是超时!

    解决方法1
    其实只要配置nginx.conf的对应localhost里面的这几个参数就好
    proxy_connect_timeout;
    proxy_read_timeout;
    proxy_send_timeout;

    解决方法2
    发心跳包,原理就是在有效地再读时间内进行通讯,重新刷新再读时间

    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; 
                proxy_set_header Connection "Upgrade";  
            }
        }
    }

    关于上面配置2的解释
    这个是服务器对你等待最大的时间,也就是说当你webSocket使用nginx转发的时候,用上面的配置2来说,如果60秒内没有通讯,依然是会断开的,所以,你可以按照你的需求来设定。比如说,我设置了10分钟,那么如果我10分钟内有通讯,或者10分钟内有做心跳的话,是可以保持连接不中断的,详细看个人需求

    WebSocket与Socket的关系
    - Socket其实并不是一个协议,而是为了方便使用TCP或UDP而抽象出来的一层,是位于应用层和传输控制层之间的一组接口。当两台主机通信时,必须通过Socket连接,Socket则利用TCP/IP协议建立TCP连接。TCP连接则更依靠于底层的IP协议,IP协议的连接则依赖于链路层等更低层次。
    - WebSocket就像HTTP一样,则是一个典型的应用层协议。
    总的来说:Socket是传输控制层接口,WebSocket是应用层协议。

    参考:

    https://www.cnblogs.com/kevingrace/p/9512287.html

    https://yq.aliyun.com/articles/73865

    https://www.cnblogs.com/piperck/p/7066286.html

    http://www.ttlsa.com/nginx/using-nginx-map-method/

    https://blog.csdn.net/chszs/article/details/26369257

  • 相关阅读:
    赫尔维茨公式
    从解析几何的角度分析二次型
    Struts 1 Struts 2
    记一次服务器被入侵的调查取证
    契约式设计 契约式编程 Design by contract
    lsblk df
    Linux Find Out Last System Reboot Time and Date Command 登录安全 开关机 记录 帐号审计 历史记录命令条数
    Infrastructure for container projects.
    更新文档 版本控制 多版本并发控制
    Building Microservices: Using an API Gateway
  • 原文地址:https://www.cnblogs.com/ybyqjzl/p/10350732.html
Copyright © 2020-2023  润新知