socket.io是目前较为流行的web实时推送框架,其基于nodejs语言开发,底层用engine.io实现。 借助nodejs语言异步的特性,其获得了不错的性能。但单个实例的socket.io依然承载能力有限,最多只能容纳3000个long-polling方式的客户端进行连接。

将socket.io进行分布式扩展的难点有两处:

1. 进行负载均衡时客户端必须保证始终连到一个节点上

     如果客户端采用long-polling长轮训方式进行连接,则每次轮训都会产生一个新的请求,若不进行限制。就有可能连接到集群内新的 socket.io节点上,导致异常的发生。

     解决方法:使用nginx的ip_hash实现session sticky ,让客户端始终连接到集群内一台节点上。

2. 多个实例之间的消息推送

     当集群内某台节点想要向连接到集群的所有客户端发送消息时,某些客户端因为负载均衡时ip_hash可能被分配到了其他的节点上,这时就需要向其他节点发布推送消息,让其他节点的同时向客户端进行推送。

解决方法:使用redis的发布与订阅功能与socket.io-redis开源库,该库在节点向客户端群发消息时会将该消息发布到redis的订阅队列中,让其他节点能够订阅到该消息,从而实现节点间消息推送。

上图是采用该架构的一个聊天服务器集群示例,每个chatnode相当于一个socket.io实例,其中的chatModule负责客户端连接,adminModule负责聊天服务器的管理功能。

adminnode作为整个集群的管理节点,通过redis的消息订阅功能来与各个chatnode通信, 并通过开放http接口来与外部系统进行交互。

准备安装的软件:

nginxnodejsredis以及一个socket.io应用,如一个聊天服务器,例子请见官网这里

具体步骤:

1.将socket.io应用部署成两个实例,如在同一台主机上为每个实例分配不同的端口号4000, 5000:

  1. http.listen(4000, function(){
  2. console.log('listening on *:4000');
  3. });

2.配置nginx文件,设置负载均衡proxy

upstream chat_nodes {
        ip_hash;
        server 127.0.0.1:4000;
        server 127.0.0.1:5000;
}

以及反向代理设置 (注意为了支持websocket协议,需将nginx升级至1.3.12版本以上

location / {
        proxy_pass              http://chat_nodes;
        proxy_set_header        Upgrade $http_upgrade;
        proxy_set_header        Connection "upgrade";
        proxy_http_version      1.1;
        proxy_set_header        Host $host;
        proxy_set_header        X-Real-IP $remote_addr;
        proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
    }

完成配置后,重启nginx。

3.安装nodejs模块 socket.io-redis

sudo npm install socket.io-redis

4.在原来socket.io应用中初始化io的位置加入io的redis适配器:

  1. var redis = require('socket.io-redis');
  2. io.adapter(redis({ host: 'localhost', port: 6379 }));

5. 重启各个socket.io应用,进行测试。

其他注意点:

    • 由于nginx的反向代理机制和socket.io的自动重连机制,上述架构还具备高可用的特性,即当某个节点down机时,原先连接到该节点上的客户端会自动重连至其它节点上。

    • 节点的数量可以随时增减,不需要暂停服务,只需修改nginx配置即可。

    • nginx的ip_hash是基于ip的前三段进行计算的,也就是说ip只有D段不同的两台客户端一定会连接到同一台服务器上,这点测试的时候需要注意。

    • 可以通过redis的订阅发布服务来实现其他系统同集群的通信,完成集群的管理工作。

    • 由于是分布式环境,所以节点内存中存储的信息(如用户、房间信息)可以考虑持久化到redis或mongodb中。

socket.io分布式的更多相关文章

  1. Node+Express+MongoDB + Socket.io搭建实时聊天应用

    Node+Express+MongoDB + Socket.io搭建实时聊天应用 前言 本来开始写博客的时候只是想写一下关于MongoDB的使用总结的,后来觉得还不如干脆写一个node项目实战教程实战 ...

  2. socket.io搭配pm2(cluster)集群解决方案

    socket.io与cluster 在线上系统中,需要使用node的多进程模型,我们可以自己实现简易的基于cluster模式的socket分发模型,也可以使用比较稳定的pm2这样进程管理工具.在常规的 ...

  3. Node+Express+MongoDB + Socket.io搭建实时聊天应用实战教程(二)--node解析与环境搭建

    前言 本来开始写博客的时候只是想写一下关于MongoDB的使用总结的,后来觉得还不如干脆写一个node项目实战教程实战.写教程一方面在自己写的过程中需要考虑更多的东西,另一方面希望能对node入门者有 ...

  4. 【Spring Boot】集成Netty Socket.IO通讯框架

    服务端 @Configuration public class NettySocketConfig { private static final Logger logger = LoggerFacto ...

  5. 在web浏览器上显示室内温度(nodeJs+arduino+socket.io)

    上次的nodejs操作arduino入门篇中实现了如何连接arduino.这次我们来实现通过arduino测量室内温度并在浏览器上显示出来. [所需材料] 硬件:LM35温度传感器,arduino u ...

  6. Node学习笔记(三):基于socket.io web版你画我猜(二)

    上一篇基础实现的功能是客户端canvas作图,导出dataURL从而实现图片信息推送,下面具体讲下服务端的配置及客户端的配置同步 首先先画一个流程图,讲下大概思路 <canvas id=&quo ...

  7. node.js+socket.io配置详解

    由于我是在win7的环境下,在这里就以win7系统为例进行讲解了. 首先需要在nodejs官网下载最新版的node.js,下载完毕直接安装即可,安装成功后在cmd命令行中执行node指令,如下结果就说 ...

  8. 使用Node.js+Socket.IO搭建WebSocket实时应用

    Web领域的实时推送技术,也被称作Realtime技术.这种技术要达到的目的是让用户不需要刷新浏览器就可以获得实时更新.它有着广泛的应用场景,比如在线聊天室.在线客服系统.评论系统.WebIM等. W ...

  9. socket.io简单入门(一.实现简单的图表推送)

    引子:随着nodejs蓬勃发展,虽然主要业务系统因为架构健壮性不会选择nodejs座位应用服务器.但是大量的内部系统却可以使用nodejs试水,大量的前端开发人员转入全堆开发也是一个因素. 研究本例主 ...

随机推荐

  1. python 获取文件md5

    def GetFileMd5(filename): if not os.path.isfile(filename): return myhash = hashlib.md5() f = file(fi ...

  2. $(window).load与$(document).ready的区别

    刚好今天学了用jQuery实现瀑布流的用法,但加载时发现了一个小小的问题,那就是分别用$(window).load与$(document).ready实现加载时,$(document).ready的布 ...

  3. bzoj 3884 欧拉定理

    求$$2^{2^{2^{2^{…}}}} mod n$$的值,其中n有1e7. 老实说这题挺有趣的,关键是怎么化掉指数,由于是取模意义下的无限个指数,所以使用欧拉定理一定是可以把指数变为不大于$\va ...

  4. 云风pbc源码alloc.c

    #include <stdlib.h> #include <stdio.h> // 用于统计内存的申请和释放次数匹配 ; void * _pbcM_malloc(size_t ...

  5. 【AtCoder】ARC086 E - Smuggling Marbles

    [题目]E - Smuggling Marbles [题意]给定n+1个点的树(root=0),每个点可以选择放或不放弹珠,每一轮顺序进行以下操作: 1.将根节点0的弹珠加入答案. 2.每个点的弹珠移 ...

  6. WebStorm 2016激活

    最近在网上找到一个激活webStorm 的好东西.博主说对jetbrains下的所有产品都是可以用这种方式激活的...如:PhpStorm,IntelliJ JDEA等. 但别的产品我没有试过.对于w ...

  7. spring-boot 更换依赖版本

    创建Spring Boot操作步骤如下: 在File菜单里面选择 New > Project,然后选择Spring Initializr 更换版本 或 pom spring-boot-start ...

  8. BeanPostProcessor的五大接口

    BeanPostProcessor 关于对象初始化前后的回调. public interface BeanPostProcessor { //该方法在bean实例化完毕(且已经注入完毕),在after ...

  9. 匿名函数、lambda表达式

    匿名函数 func = lambda x: y #x是形参,y是返回值 键字lambda表示匿名函数,冒号前面的x表示函数参数,冒号后面的y表示匿名函数的返回值. 例1:返回列表中长度大于等于3的元素 ...

  10. Java Web Project Problems

    A: 项目红叉 1. 检验 Java Builder  Path 2. 检查 Projects Facets 3. 查看 Targets Runtimes B:项目红感叹号 1. 查看问题栏 Prob ...