Openfire 是一个XMPP协议的IM Server。java
基于MINA的java nio服务器。mysql
通常就是使用mysql来做为数据库,保存配置配置信息、离线信息、用户数据。linux
官网的数据是支持5000人同时在线,使用connectionManager能够实现支持3.3万人在线。redis
这数据一点都不漂亮,只能做为一个相似腾讯通的局域网聊天工具使用。sql
首先说点题外话,我测试用connectionManager。数据库
这是一个openfire提供的链接管理器,做用实际上是数据整流。缓存
源码里是经过阻塞式多线程将信息经过特定端口与openfire提交数据。服务器
测试以后的结果,这玩意严重影响效率,放弃,咱们的目标不仅是3.3万人。网络
Openfire使用mysql配合它不知所谓几乎无效的的Cache机制就注定没法支撑高并发,多线程
因此第一步,将数据库切换为比较强一点的MongoDB。
可是MongoDB也是有问题的,在高并发时才会发现,MongoDB的锁表十分严重,
通过调查发现,MongoDB也比较坑爹,他是使用“全局锁”的,也就是说,你更新A表的时候,会锁住B表,数据更新后解锁。
因此做为实时查询数据库即便是使用MongoDB的master/slave模式依然不能胜任。
增长解决方案,缓存层,使用redis做为MongoDB的数据缓存,在访问时数据时,首先进入Cache层访问redis,若是没有,再去访问MongoDB,而后再回头填充Redis。
OK,数据源解决了,接下来确认须要在什么地方切入。
1,首先是将用户信息数据切换到MongoDB中。并中止Openfire本身的Roster服务,在管理控制台设置 xmpp.client.roster.active = false
2,AuthProvider,这里是登录模块,能够继承接口重写一个属于本身的Provider。
重写authenticate方法,将登录验证请求交给cache层。
3,离线信息的存储在以后也会成为负担,那么继承OfflineMessageStore类,重写属于本身的离线信息策略,将离线信息保存到Redis中。
4,重写状态更新的广播:PresenceUpdateHandler中的broadcastUpdate方法。
好了,这时候Openfire已经被修改的面目全非,可是效率已经不可同日而语了。
这时候还有一个问题,就是Openfire没有消息保障机制,也就是说,网络不稳定的时候,客户端异常断线,信息就会发送到空气中,
须要再发送信息的时候实现“握手机制”来保障信息的可靠性。不细说了,本身百度。
这时候Openfire的在线用户能够飚到6W无压力,可是死活上不去了,又被限制了。
在error.log中会发现相似 “open files too larger” 一类的错误,这些是linux系统参数:最大文件打开数。
在linux下执行ulimit -a就能观察最大的文件打开数,执行ulimit -n 350000设置为35万,而后kill掉openfire退出控制台,从新链接控制台使其生效,从新启动Openfire。
好吧,这时候用户量能够飙6W以上了。
XMPP服务器的测试工具,比较简单的可使用tsung来实现,简单的配置,模拟成千上万的用户登录,而且能够模拟HTTP等其余请求。
接下来就是单台服务器容量的问题了,咱们服务器是Dell R710, 64G内存 16核CPU,15000转硬盘。
服务器在这种架构下在线用户数据在29W左右,几乎已是单台Openfire封顶了。
开始考虑集群,不过Openfire的几种集群都测试过,效果不理想,有一个神马war包的插件,弄上去时好时坏,放弃。
还有一个oracle的集群插件,不过在高压下多台Openfire直接脱离集群,本身玩本身的了。。。日。
若是到了十万二十万左右的在线用户级别,就放弃掉Openfire,能够尝试使用tigase试试,尽管我没试过,不过看过源码,以为仍是比较可靠。
或者和咱们同样,本身写通信服务器。