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

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学习笔记23(Set接口)

    Set接口: 1.Set接口是不包含重复元素的Collection: 2.set集合没有索引,只能通过增强型for循环或迭代器来遍历: 3.Set接口只包含从collection接口继承的方法,并且增 ...

  2. wewqe

    script.cscript_runreason(const struct interface *ifp, const char *reason)elen = (size_t)make_env(ifp ...

  3. c语言求最大公约数和最小公倍数(转)

    最大公约数与最小公倍数的求解是很多初学C的人所面临的一道问题.当然这道问题并不难解答,也有很多人已经写过相关的博客,我在此书写此篇博客,一是为了让自己能够夯实基础,另外就是希望能够帮到和我一样的初学者 ...

  4. Linux audit安全审计工具

    /********************************************************************** * Linux audit安全审计工具 * 说明: * ...

  5. Linux上统计文件夹下文件个数以及目录个数

    对于linux终端用户而言,统计文件夹下文件的多少是经常要做的操作,于我而言,我会经常在谷歌搜索一个命令,“如何在linux统计文件夹的个数”,然后点击自己想要的答案,但是有时候不知道统计文件夹命令运 ...

  6. SPI有关CPOL和CPHA的时序图

    SPI模块为了和外设进行数据交换,根据外设工作要求,其输出串行同步时钟极性和相位可以进行配置. 时钟极性(CPOL)对传输协议没有重大的影响. 如果CPOL=0,串行同步时钟的空闲状态为低电平: 如果 ...

  7. django 浅谈CSRF(Cross-site request forgery)跨站请求伪造

    浅谈CSRF(Cross-site request forgery)跨站请求伪造(写的非常好) 本文目录 一 CSRF是什么 二 CSRF攻击原理 三 CSRF攻击防范 回到目录 一 CSRF是什么 ...

  8. 【HDOJ4612】【双连通分量缩点+找树的直径】

    http://acm.hdu.edu.cn/showproblem.php?pid=4612 Warm up Time Limit: 10000/5000 MS (Java/Others)    Me ...

  9. js的以及前端框架

    js定义:浏览器的脚本语言,用简单的语言实现浏览器的操控 基础语法:基础的运算.函数.对象(原型链.对象构造.class) 所有的框架都是基于原生的js来进行的 js的事件:什么时候.什么情况下处理的 ...

  10. JSP中页面向Action传递参数的几种方式

    <form name="ThisForm" method="POST" action="index.jsp"> form是表单, ...