用NodeJS打造可扩展聊天服务

利用Nodejs实现即时通讯的选择最常见的就是socket.io,

首先来说说socket.io

优势:

1. 上手容易

2. 社区活跃(评价优秀开源项目的重要指标)

3. 对开发者友好, 避免开发者适配IE等不支持websocket的浏览器

4. 生态完整, 有对应Android,iOS SDK

缺点:

坑1. 一上生产环境就各种内存高或者cpu占用高

坑2. 扩展性

坑3. 从0.9x的不兼容性升级

坑1 内存问题的解决

socket.io在跑一段时间后, 内存占用并没有下来,猜测难道断开连接后,内存没有释放?  但通过heapdump分析快照,记录下三个状态进行对比,1>服务启动时 2>使用高峰时 3>使用低谷时 , 三者进行对比后发现并不是猜测的情况, socket.io自身的变量是已经销毁了的, 经历多次优化尝试后,原来是v8引擎并没有释放内存, 解决方案:启用--expose-gc,定时global.gc(),

坑2 CPU问题的解决

当时socket.io版本还为0.9.16, 并没有官方推荐的负载方案, 使用cluster做多进程时, 无论用redis store 还是 memory store都会造成nodejs服务或redis服务cpu高压力,导致服务响应变慢,解决方案:仅使用单进程,不做多进程负载(服务横向扩展后面会讨论)

其余优化: v8引擎在64位机器侠默认在允许一个进程占用1.4G内存, 通过设置启动参数--max-old-space-size 和 --max-new-space-size 提高 v8 使用内存的上限,提高服务器内存使用率


下面来说说服务最重要的横向扩展

需求1. 用户可能同时打开多个网页和手机App, 用户的操作在多个页面都需要同步(如,切换聊天对象,发送消息等)

需求2. 尽可能减少服务之间的消息同步

现状1. 所有认证通过nodejs 读取用户请求cookie获取会话信息

现状2. 常见的Nginx负载方案有round-robin,least-connected,ip-hash , 但这三种并不能很好的满足需求, 当backend增加时, 如果使用nodejs官方方案用所有消息在服务之间同步,会造成同步量非常大

解决方案: 将会话前置到Nginx,并动态路由

使用Nginx+lua(openresty)来读取会话信息, 并动态路由至指定backend服务,如 将user1的5个网页连接和1个app连接全部路由至server1

这里的用户连接路由规则参照的是常见的数据库分表规则, 根据用户ID计算出对应chat server, 将单一用户连接锁定在单台服务上, 这样做的好处是, 不管是lua,nodejs或者其他语言都可简单的计算出用户对应连接的chat server, 有利于聊天服务与其他服务之间的对接.

服务之间消息同步: 使用redis的pub/sub, 每台server订阅自己的频道, 当用户1要发送消息至连接到另外一台服务的用户2时,nodejs根据上面描述的路由规则计算出用户2对应的server, publish至用户2对应的server2, server2再将消息推送给user2

写完才发现不能贴代码, 下次用markdown来写...

参考链接

Nginx lua wiki

https://www.nginx.com/resources/wiki/modules/lua/

OpenResty 中文wiki

https://github.com/iresty/nginx-lua-module-zh-wiki

OpenResty 系列课程

http://www.stuq.org/course/detail/1015

socket.io

socket.io

时间: 2024-10-28 21:58:27

用NodeJS打造可扩展聊天服务的相关文章

通讯聚合类Chrome 扩展:All-in-One Messenger,把主流聊天服务聚合在一个应用窗口内

原文地址:http://whosmall.com/?post=420 本文标签: Chrome扩展 Chrome浏览器 通讯聚合类Chrome扩展 All-in-One-Messenger 主流聊天服务聚合 我发现了 All-in-One Messenger,它是一款轻量的 Chrome 扩展,作用与 Franz基本相同,只需要打开一个窗口,所有的通讯服务会以网页标签栏的形式呈现,方便你自如切换,可以大大提高了沟通的效率.但是和「庞大」的 Franz 相比,All-in-One Messenge

用 consul + consul-template + registrator + nginx 打造真正可动态扩展的服务架构

在互联网应用领域,服务的动态性需求十分常见,这就对服务的自动发现和可动态扩展提出了很高的要求. Docker 的出现,以及微服务架构的兴起,让众多开源项目开始关注在松耦合的架构前提下,如何基于 Docker 实现一套真正可动态扩展的服务架构. 基本需求 基本的需求包括: 服务启动后要能自动被发现(vs 传统需要手动进行注册): 负载要能动态在可用的服务实例上进行均衡(vs 传统需要静态写入配置): 服务规模要方便进行快速调整(vs 传统需要较长时间的手动调整). 相关项目 服务发现 服务发现的项

5分钟快速打造WebRTC视频聊天<转>

原文地址: 5分钟快速打造WebRTC视频聊天 百度一下WebRTC,我想也是一堆.本以为用这位朋友( 搭建WebRtc环境 )的SkyRTC-demo 就可以一马平川的实现聊天,结果折腾了半天,文本信息都发不出去,更别说视频了.于是自己动手. 想在公网上实现视频通信,需要下面3个核心元素: 一个是NAT穿透服务器(ICE Server),实现内网穿透,具体的作用可以自行百度. 基于WebSocket的信令服务器(Signaling Server),用于建立点对点的通道. Web客户端.通过H5

用nodejs搭建一个简单的服务监听程序

作为一个从业三年左右的,并且从事过半年左右PHP开发工作的前端,对于后台,尤其是对以js语言进行开发的nodejs,那是比较有兴趣的,虽然本身并没有接触过相关的工作,只是自己私下做的一下小实验,但是还是记录一下方便以后复习! 今天主要记录一下,很久以前用nodejs制作一个简单的服务监听程序的一些过程! 大家都知道,通过nodejs可以对前台请求进行监听,这里就放一个官网的hello world例子吧: var http = require('http'); http.createServer(

Mina airQQ聊天 服务端篇(二)

Mina聊天服务端实现思路:在用户登录的时候.连接服务端而且验证登录用户,假设成功,则将IoSession保存到map<账号,IoSession>中,而且通知该用户的好友上线,然 后再请求好友列表:若不成功,则断开连接. 自己定义协议格式:包头+包体 包头(10字节):包头长度(short)+ 消息类型(byte)+ 内容类型(byte) +  消息命令(short)+ 包体长度(int) 包体:JSON字符串 自己定义编码解码:因为数据在网络传输过程中都是以二进制传输的,所以我们能够自己定义

nodejs入门——搭建一个聊天室应用

个人博客 http://mvc.coding.io/ 1入门教程推荐 node入门 很早之前看的就是这个,比较浅显易懂,看一遍就明白nodejs到底是怎么一回事儿了 2开源项目 昨天在coding上看到了一个nodejs聊天室,fork了一份 nodejs聊天室 3环境搭建 nodejs官网,下载最新版本(本人电脑win7 64位),安装过程下一步下一步就行,安装会自动配置环境变量, 建议安装目录自己选择一下,别默认安装在C:\Program Files\ 目录下(目录有空格 会出现一些问题)

Seafile 推出 “分布式文件同步技术” 打造的私有云服务

近两年来 Dropbox 等云储存服务迅速窜红,各大巨头纷纷推出自家的云储存服务(苹果的 iCloud, 微软的 SkyDrive, Google 即将推出的 GDrive),国内也有类似的服务(金山网盘.袋鼠盘.坚果云等).用户只需将自己的文件资料储存到这些云储存空间上,就可以从自己的台式机.手机.平板等终端设备随时随地访问自己的文件资料,用户如果在一个地方更新文件,其它地方也会自动同步. 挑战以 Dropbox 为代表的传统 “同步网盘”,Seafile 推出 “分布式文件同步技术” 打造的

改进基于Boost.Asio的聊天服务

Boost.Asio是个非常易用的C++异步网络库,官网上有很详细文档和示例代码.其中一个示例是聊天服务,分成chat_message.chat_client.chat_server这么三个部分.chat_server的启动代码如下. 1 if (argc < 2) 2 { 3 std::cerr << "Usage: chat_server <port> [<port> ...]\n"; 4 return 1; 5 } 6 7 boost::

NodeJs 加入Windows开机自启动服务

首先需要到http://nssm.cc/download/?page=download 下载 nssm,下下来之后是压缩包形式的解压之后,在命令行模式下进入到nssm的目录.之后运行:nssm install NodeJS "\node.exe" "\server.js" net start NodeJS. nssm install NodeJS(安装后的服务名称) "(node.exe安装的地址)\node.exe" "(要启动的JS