今天要介绍的问题,是一个相对来说比较经典的问题,问题表面看不是很复杂的问题,但是反映出的背后通信逻辑,其实还是比较有意义的。

websocket协议是当前绝大部分浏览器都支持的长连接协议,是HTTP协议的升级版协议,解决HTTP协议的单向通信的弊端,WS(websocket协议的简写)协议,基于长连接,实现客户端和服务端之间的双向通信,这个技术在我们项目里面,主要用来解决客服系统问题,即客户发送的消息以及坐席回复的消息之间,可以实时交互。关于这个协议的更多介绍,请参考官方网站,这里不多做介绍。

下面说下我们项目中,研究websocket连接,在集群环境下,如何解决后端tomcat上只有一个连接实例问题。我们的实验环境,topo架构如下:

结合上面的topo架构,客户端的请求,只有在涉及到websocket的连接的时候,才会从Client LB一直走到Server LB的后面tomcat上。除此之外,其他的客户端请求,只会到client app对应的tomcat即停止。

0.环境信息
1).客户端后台nginx,充当Client LB 
这里的客户端,主要指类似聊天窗的渲染以及基本的和客户端相关的逻辑主体。我们的实验中,客户端,主要就是一个聊天窗口和附着在这个上面的辅助应用。

[root@localhost sbin]# ./nginx -V
nginx version: openresty/1.11.2.2
built by gcc 4.1. (Red Hat 4.1.-)
built with OpenSSL 0.9.8e-fips-rhel5 Jul
TLS SNI support disabled
configure arguments: --prefix=/usr/local/nginx --with-cc-opt=-O2 --add-module=../ngx_devel_kit-0.3. --add-module=../echo-nginx-module-0.60 --add-module=../xss-nginx-module-0.05 --add-module=../ngx_coolkit-.2rc3 --add-module=../set-misc-nginx-module-0.31 --add-module=../form-input-nginx-module-0.12 --add-module=../encrypted-session-nginx-module-0.06 --add-module=../srcache-nginx-module-0.31 --add-module=../ngx_lua-0.10. --add-module=../ngx_lua_upstream-0.06 --add-module=../headers-more-nginx-module-0.32 --add-module=../array-var-nginx-module-0.05 --add-module=../memc-nginx-module-0.17 --add-module=../redis2-nginx-module-0.13 --add-module=../redis-nginx-module-0.3. --add-module=../rds-json-nginx-module-0.14 --add-module=../rds-csv-nginx-module-0.07 --with-ld-opt=-Wl,-rpath,/usr/local/luajit/lib --with-http_realip_module --with-pcre --add-module=/usr/local/openresty-1.11.2.2/bundle/ngx_cache_purge-2.3 --add-module=/usr/local/openresty-1.11.2.2/bundle/nginx_upstream_check_module-0.3. --with-http_ssl_module

2)服务端后台nginx,充当Server LB
这里主要指websocket消息的通信处理逻辑,即客户端收到客户的消息后要通过客户端后台反向代理推送给的目的服务地址。

[root@bogon nginx]# ./sbin/nginx -V
nginx version: openresty/1.11.2.2
built by gcc 4.8. (Red Hat 4.8.-) (GCC)
built with OpenSSL 1.0.1e-fips Feb
TLS SNI support enabled
configure arguments: --prefix=/usr/local/openresty/nginx --with-cc-opt=-O2 --add-module=../ngx_devel_kit-0.3. --add-module=../echo-nginx-module-0.60 --add-module=../xss-nginx-module-0.05 --add-module=../ngx_coolkit-.2rc3 --add-module=../set-misc-nginx-module-0.31 --add-module=../form-input-nginx-module-0.12 --add-module=../encrypted-session-nginx-module-0.06 --add-module=../srcache-nginx-module-0.31 --add-module=../ngx_lua-0.10. --add-module=../ngx_lua_upstream-0.06 --add-module=../headers-more-nginx-module-0.32 --add-module=../array-var-nginx-module-0.05 --add-module=../memc-nginx-module-0.17 --add-module=../redis2-nginx-module-0.13 --add-module=../redis-nginx-module-0.3. --add-module=../rds-json-nginx-module-0.14 --add-module=../rds-csv-nginx-module-0.07 --with-ld-opt=-Wl,-rpath,/usr/local/openresty/luajit/lib --add-module=/opt/nginx-rtmp-module-master --with-http_ssl_module

1.客户端应用对应的后台nginx的反向代理配置

upstream ims_client {
server 10.90.9.20:;
server 10.90.9.20:;
}
upstream ims_svr {
server 10.90.7.10:;
}
server {
listen ;
server_name localhost;
default_type text/html;
proxy_send_timeout ;
proxy_read_timeout ; location /IMS_SVR/websocket {
proxy_pass http://ims_svr;
proxy_set_header Host $host:$server_port;
proxy_set_header Remote_Addr $remote_addr;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade"
;
}

location /IMS {
proxy_pass http://ims_client;
proxy_set_header Host $host:$server_port;
proxy_set_header Remote_Addr $remote_addr;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; }
}

对应的客户端应用,在我本地开发机器上,启动了两个tomcat,一个端口7080,另外一个8080,也就是上面nginx配置中的ims_client部分,当客户端请求IMS这个客户端应用时,客户端的界面渲染以及在客户端本地能完成的工作,都在这个应用里面。只有客户端涉及到和websocket连接有关的请求,会被反向代理到ims_svr对应的服务入口上。如上面的nginx配置,ims_svr对应的服务入口,其实就是websocket后端服务端的负载均衡入口地址,这里10.90.7.10:9091其实就是另外一个nginx服务的入口地址。

2. 服务端应用对应的后台nginx的反向代理配置

upstream ims_svr {
server 10.90.9.20:;
server 10.90.9.20:;
#hash $query_string;
#hash $request_uri;
#hash $arg_userId;
}
server {
listen ;
server_name localhost;
default_type text/html; location /IMS_SVR/websocket {
proxy_pass http://ims_svr;
proxy_set_header Host $host:$server_port;
proxy_set_header Remote_Addr $remote_addr;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}

这里,主要是将websocket的请求反向代理到后端具体的tomcat服务器上,websocket的对应tomcat服务器有2个,也是本地基于不同端口启动的9080和9081两个tomcat应用。

这次实验的目的,主要是想知道,nginx配置的轮询的方式做反向代理,WS连接,是否也会在后端服务器之间不停的切换,造成后端tomcat上存在多个连接实例peer,因为长连接通信,是存在两个对端实例的。若出现tomcat端出现多个客户端的连接对端peer,那么,就不符合我们业务的需要了,即浪费资源,又不便于逻辑管理。

我们的测试过程中,发现,不论客户端HTML5页面如何刷新,最终websocket总是在同一个tomcat上。这个是非常重要的结论。另外,当Server 端的tomcat停掉一个,比如9080对应的app停掉,客户端HTML5,因为websocket页面js里面添加心跳机制,实现重连,客户在无感知的情况下,websocket重新连接上来,接到了server app 9081上面来了。

客户端聊天界面如下:

通过这次实验得出如下结论:

1. 基于websocket长连接的通信,可以不用通过客户id等指定唯一字段信息进行hash来锁定客户端和websocket服务端之间的peer到peer的映射关系,这个映射关系,应该是在websocket的配置,即nginx中配置代码段中红色部分指定的。

2. 基于websocket的长连接的反向代理,客户端和服务端的反向代理nginx配置逻辑要一致,保证连接正常通信。

3. 基于websocket的长连接的通信,前端的业务层面的heartbeat心跳机制,是非常有用的,这个保证某个websocket后端服务出现异常的时候,客户可以无感知的继续得到服务。

websocket连接的后台反向代理问题的更多相关文章

  1. websocket使用nginx作为反向代理

    需要nginx作为websocket的反向代理,没有nginx反向代理时候没有问题,通过nginx反向代理后会报400错误,查后台调试信息: tornado.general – DEBUG – Can ...

  2. Nginx支持WebSocket反向代理-学习小结

    WebSocket是目前比较成熟的技术了,WebSocket协议为创建客户端和服务器端需要实时双向通讯的webapp提供了一个选择.其为HTML5的一部分,WebSocket相较于原来开发这类app的 ...

  3. Nginx反向代理WebSocket(WSS)

    1. WebSocket协议 WebSocket 协议提供了一种创建支持客户端和服务端实时双向通信Web应用程序的方法.作为HTML5规范的一部分,WebSockets简化了开发Web实时通信程序的难 ...

  4. Nginx支持WebSocket反向代理

    WebSocket是目前比较成熟的技术了,WebSocket协议为创建客户端和服务器端需要实时双向通讯的webapp提供了一个选择.其为HTML5的一部分,WebSocket相较于原来开发这类app的 ...

  5. 配置 Nginx 反向代理 WebSocket

    用Nginx给网站做反向代理和负载均衡是广泛使用的一种Web服务器部署技术.不仅能够保证后端服务器的隐蔽性,还可以提高网站部署灵活性. 今天我们来讲一下,如何用Nginx给WebSocket服务器实现 ...

  6. 负载均衡DNS和反向代理优缺点

    负载均衡 (Load Balancing) 建立在现有网络结构之上,它提供了一种廉价有效透明的方法扩展网络设备和服务器的带宽.增加吞吐量.加强网络数据处理能力.提高网络的灵活性和可用性. 负载均衡(又 ...

  7. nginx反向代理时保持长连接

    ·[场景描述] HTTP1.1之后,HTTP协议支持持久连接,也就是长连接,优点在于在一个TCP连接上可以传送多个HTTP请求和响应,减少了建立和关闭连接的消耗和延迟. 如果我们使用了nginx去作为 ...

  8. Nginx配置WebSocket反向代理(Tomcat+Nginx)

    @toc WebSocket 和HTTP协议不同,但是WebSocket中的握手和HTTP中的握手兼容,它使用HTTP中的Upgrade协议头将连接从HTTP升级到WebSocket.这使得WebSo ...

  9. 使用ssh正向连接、反向连接、做socks代理的方法

     ssh -L 219.143.16.157:58080:172.21.163.32:8080 用户名@localhost -p 10142  在 219.143.16.157机器执行   将ssh隧 ...

随机推荐

  1. JAVA_关键词01_instanceof的应用

    A instanceof  B: 对象A是否是 B类的一个实例 应用举例:

  2. 2017ICPC南宁赛区网络赛 The Heaviest Non-decreasing Subsequence Problem (最长不下降子序列)

    Let SSS be a sequence of integers s1s_{1}s​1​​, s2s_{2}s​2​​, ........., sns_{n}s​n​​ Each integer i ...

  3. PAT 乙级 1061. 判断题(15)

    判断题的评判很简单,本题就要求你写个简单的程序帮助老师判题并统计学生们判断题的得分. 输入格式: 输入在第一行给出两个不超过100的正整数N和M,分别是学生人数和判断题数量.第二行给出M个不超过5的正 ...

  4. quartz定时任务及时间设置

    quartz 定时任务时间设置1.这些星号由左到右按顺序代表 :     *    *     *     *    *     *   *                               ...

  5. JS导入导出Excel表格的方法

    https://blog.csdn.net/aa122273328/article/details/50388673 导出 https://blog.csdn.net/qq_37281252/arti ...

  6. HDU 1686:Oulipo(KMP模板,子串出现次数)

    Oulipo Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Sub ...

  7. Apache Kafka 源码剖析

    Getting Start 下载 http://kafka.apache.org/ 优点和应用场景 Kafka消息驱动,符合发布-订阅模式,优点和应用范围都共通 发布-订阅模式优点 解耦合 : 两个应 ...

  8. emacs安装

    1.我选用的是Ubuntu16.04. 2.Ubuntu安装好之后不能直接sudo apt-get install emacs,因为Ubuntu的源默认是emacs24,最好是用最新的emacs25, ...

  9. 彻底理解一致性哈希算法(consistent hashing)

    转载请说明出处:http://blog.csdn.net/cywosp/article/details/23397179     一致性哈希算法在1997年由麻省理工学院提出的一种分布式哈希(DHT) ...

  10. jQuery -> 基于当前元素的遍历

    版权声明:本文为博主原创文章,转载请注明出处 https://blog.csdn.net/FeeLang/article/details/26257549 假设我们已经通过jQuery方法选中了一组元 ...