WebSocket :Nginx+WebSocket内部路由策略推送服务器的实现(附可生产环境应用代码)

1.项目背景

前几天写了一篇WebSocket推送的博客:WebSocket :用WebSocket实现推送你必须考虑的几个问题 支持的连接数大概几千个,具体数量依赖于tomcat能并发的线程数,但很多时候生产环境应用的话几千个肯定是不行的,所以本问介绍Nginx+WebSocket的实现思路及代码.

2.实现思路

依照设计模式中的 迪米特法则 外部调用模块来讲要尽量少的参与推送模块的逻辑,以达到解耦的目的,所以我们虽然通过Nginx+WebSocket做了集群策略,但是不应该让外部感知.对于外部调用模块来讲你是否应用集群与我调用你无关.

大概实现思路是这样的,推送服务要把不是本机的请求内部路由到相应兄弟服务器.很多同学有疑问了为什么要路由呢,Nginx到任意一个节点处理不是就可以了. 大家注意哈,http实现了无状态请求,但是对于ws来讲tcp长连接显然是一个有状态请求,举个例子:server A连接client a,你想通过server B给client a发消息是做不到的,因为tcp连接在server A上.

设计图: 

连接过程: 所有client连接地址均为Nginx地址,但是实际tcp连接是建立在具体服务器上的.连接完成后redis中要存储对应用户的serverId和SessionId(WsSession 是ws用来标识具体连接的).

发送消息过程:外部调用模块将消息发送到Nginx,假设发送消息的请求发送到了Server B上,那么Server B需要查出具体用户当前所连接的服务器,将请求路由转发到兄弟服务器上去.

3.源码地址

下载地址 
http://download.csdn.net/download/shangmingtao/9920532

4.可优化的点

1.路由转发方式: 现在实现是用http转发的,效率很低,可以采用redis PUB/SUB方式 或者 rabbitMQ等. 
2.路由转发内容: 我先再路由转发的是Client的userId+platform ,为的是能复用外部调用模块访问的接口.其实这里转发sessionId就可以了. 
3.redis存储用户信息当前是序列化进去的.最好用hash这种数据类型.

5.Nginx配置及说明

user  nobody;
worker_processes 1;

events {
    worker_connections  8192; #这个要大一些
}


http {

    upstream ws{
        server 127.0.0.1:18080;
        server 127.0.0.1:28080;
    }

        server {

             listen 81;
             server_name localhost;

 #           动静分离处理
 #           location ~ .*.(gif|jpg|jpeg|png|bmp|swf|js|css)$ {
 #                   root html;
 #          }


             location ~/WSPush {
                proxy_pass http://ws;
                proxy_http_version 1.1;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection "upgrade";
                proxy_set_header Host $host:$server_port; #这个用来透传用户http请求头的,因为我代码里调用了request.getServerName()方法,如果不加个配置,取出来是http://ws
                proxy_read_timeout 30m;#这里一定不要忘了改,默认1分钟后nginx会断开ws
            }
        }
}

转自:http://m.blog.csdn.net/shangmingtao/article/details/76639821
原文地址:https://www.cnblogs.com/duanxz/p/5149403.html