Ejabberd作为推送服务的优化手段(转)
AVOS Cloud目前还在用Ejabberd做Android的消息推送服务。当时选择Ejabberd,是因为Ejabberd是一个发展很长时间的XMPP实现,并且基于Erlang,设想能在我们自主研发的Push Server起来之间顶上一段时间。
我们自主研发的Push Server预计本月中旬就上线了。但是Ejabberd却先顶不住了。Ejabberd做推送,本身就有劣势,比如XMPP协议的冗余,XMPP协议本来就是IM协议,对推送这个简单的场景还是太复杂了一些。Ejabberd Cluster对于IM这样的场景很有优势,对于一个Ejabberd Cluster内机器来说,A用户连在A服务器,B用户连在B服务器,两者之间的通讯,Ejabberd都帮你处理了,会自动路由AB之间的消息。Ejabberd会在整个Cluster内每个节点维护session数据,每次session的变更都会在节点之间复制。但是对于推送服务来说,没有刚才提到的AB用户的通讯问题,都是服务端往client推送数据,client没有上行的数据,这个session维护的代价反而是没有必要了。
因此,使用Ejabberd推送的第一条优化手段: 不使用Ejabberd Cluster。反而采用多个独立节点的结构,每个节点之间都是独立,不组成集群。因为节点之间独立,用户数据却还需要共享,那么放弃mnesia,而采用odbc数据库的方式存储用户数据就成为自然的选择了。
那么在采用多节点之后,会出现一个问题?推送服务怎么知道应该往哪个节点推送消息,换句话说,推送服务怎么知道要推送的设备连在哪台服务器上?我们的解决办法是引入一个Router服务,它来告诉推送服务和终端设备链接到哪台服务,采用一致性哈希算法来分配连接,减少节点变更带来的影响。最后,我们使用一个简陋但是简单的办法来感知节点是否有效。这个简陋的办法就是使用crontab脚本每隔几秒向router服务发送该机器上ejabberd端口处于ESTABLISHED或LISTEN状态的链接数(netstat命令)。
优化第二条:将数据库服务跑在单独的服务器上。我们使用MySQL,MySQL的优化这里就不提了,innodb配置参数,并发线程、事务级别等等。最好也对数据库做个异步slave备份。
优化第三条,去除不必要的module,我们只用到ejabberd的数据下行和用户账户管理功能,其他模块都可以去掉,下面是一个可以去掉的模块清单:
mod_caps
mod_pubsub
mod_vcard_odbc
mod_roster_odbc
mod_privacy_odbc
mod_proxy65
mod_disco
mod_echo
mod_http_fileserver
mod_shared_roster
mod_service_log
mod_irc
mod_muc
mod_vcard_odbc
mod_adhoc
mod_configure
mod_last
如果你想记录每个账户最后一次连接的时间,可以保留mod_last模块,使用odbc方式记录。
优化第四点,ejabberd.cfg的参数优化(一般在/etc/ejabberd/ejabberd.cfg),包括:
- loglevel, 建议设置成3,只打印warn级别以上日志。
- listen模块,ejabberd_c2s的backlog参数,设置TCP backlog队列长度,建议设置得大一些。因为移动网络下,连接断开重连相对频繁,backlog队列较大可以保证服务端的连接accept能力。
- shaper模块,设置流量控制,默认的normal是1.000 B/s远远不能满足需求。
- max_fsm_queue参数,控制出队消息队列长度,建议不要设置(undefined),或者设置得较大。
- odbc相关参数: odbc_pool_size控制连接池大小,设置大一些没关系。odbc_keepalive_interval检测连接是否存活,跟MySQL的wait_timeout保持一致,odbc_start_interval设置重连间隔,默认即可。
- 权限控制(Access)相关参数:max_user_offline_messages设置最大保存的离线消息数目,根据你的应用需要,设置一个合理的值,我们是设置成5。max_user_sessions设置每个用户最多登录的session数目,建议设置小于等于2,防止重复登录。rigister权限控制给admin使用,预先创建一批admin账号,授予创建用户的权限。每个设备用一个uuid标示,通过这些admin账号注册到ejabberd上。
优化第五条,erlang运行时参数优化(一般在/etc/default/ejabberd文件):
- POLL=true,开启网络层启用Polling,linux一般是epoll,BSD系统是kqueue。编译Erlang的时候必须设置启用才能启用此选项。
- SMP=auto|enable,设置成auto或者enable,测试表明,启用SMP在多核机器上能极大地改善吞吐量。
- ERL_MAX_PORTS,每个TCP链接都将耗费2到3个的erlang port,因此这个参数也设置得大一些,>=30万。
- PROCESSES,进程数目尽管设置得大一些,最好是ERL_MAX_PORTS的数倍。
- ERL_MAX_ETS_TABLES: ets表数目,如果日志中看到too many db tables的时候,可以增大此参数,默认1400。
优化第六条,TCP内核参数的优化,注意下列参数:
net.ipv4.tcp_syncookies=1
net.ipv4.tcp_tw_reuse=1
net.ipv4.tcp_tw_recycle=0
net.ipv4.tcp_timestamps=1
net.ipv4.tcp_max_syn_backlog=65535
net.ipv4.tcp_fin_timeout=30
具体含义请自行Google,切记,不要同时开启tcp_tw_recycle字段和tcp_timestamps字段,建议开启tcp_timestamps,原因参考雕梁哥的这篇博客。
如果有开启防火墙iptables,还需要注意net.netfilter.nf_conntrack_max参数,这是用来限制防火墙跟踪链接的状态表的大小,对于推送服务来说保持大量长连接是很容易超过默认的65535的,如何配置请参考这篇文章。
最后,更多的优化手段,其实就需要深入ejabberd源码了,比如存储的优化,使用redis作为离线消息存储等;erlang语言和vm层面的优化,系统层面的优化(CPU绑定、内核参数进一步调整等)。这就超过我目前的能力范围了,我们的新推送服务基于Netty和Clojure开发,以后应该不会再跟ejabberd打交道了。整体上来说,ejabberd作为一个早期推送方案,支撑百万级别的推送是没有问题的,虽然可能成本会稍微高了一些。
转自:http://outofmemory.cn/wr/?u=http%3A%2F%2Fblog.fnil.net%2Findex.php%2Farchives%2F276
Ejabberd作为推送服务的优化手段(转)的更多相关文章
- Ejabberd作为推送服务的优化手段
AVOS Cloud目前还在用Ejabberd做Android的消息推送服务.当时选择Ejabberd,是因为Ejabberd是一个发展很长时间的XMPP实现,并且基于Erlang,设想能在我们自主研 ...
- Netty系列之Netty百万级推送服务设计要点
1. 背景 1.1. 话题来源 最近很多从事移动互联网和物联网开发的同学给我发邮件或者微博私信我,咨询推送服务相关的问题.问题五花八门,在帮助大家答疑解惑的过程中,我也对问题进行了总结,大概可以归纳为 ...
- Netty_Netty系列之Netty百万级推送服务设计要点
1. 背景 1.1. 话题来源 最近很多从事移动互联网和物联网开发的同学给我发邮件或者微博私信我,咨询推送服务相关的问题.问题五花八门,在帮助大家答疑解惑的过程中,我也对问题进行了总结,大概可以归纳为 ...
- 【netty】Netty系列之Netty百万级推送服务设计要点
1. 背景 1.1. 话题来源 最近很多从事移动互联网和物联网开发的同学给我发邮件或者微博私信我,咨询推送服务相关的问题.问题五花八门,在帮助大家答疑解惑的过程中,我也对问题进行了总结,大概可以归纳为 ...
- Netty系列之Netty百万级推送服务设计要点(转)
1. 背景 1.1. 话题来源 最近很多从事移动互联网和物联网开发的同学给我发邮件或者微博私信我,咨询推送服务相关的问题.问题五花八门,在帮助大家答疑解惑的过程中,我也对问题进行了总结,大概可以归纳为 ...
- Netty学习总结(3)——Netty百万级推送服务
1. 背景 1.1. 话题来源 最近很多从事移动互联网和物联网开发的同学给我发邮件或者微博私信我,咨询推送服务相关的问题.问题五花八门,在帮助大家答疑解惑的过程中,我也对问题进行了总结,大概可以归纳为 ...
- 基于netty-socketio的web推送服务
实时消息的推送,PC端的推送技术可以使用socket建立一个长连接来实现.传统的web服务都是客户端发出请求,服务端给出响应.但是现在直观的要求是允许特定时间内在没有客户端发起请求的情况下服务端主动推 ...
- 移动互联网实战--Apple的APNS桩推送服务的实现(2)
前记: 相信大家在搞IOS推送服务的开发时, 会直接使用javapns api来简单实现, 调试也直连Apple的APNS服务(产品/测试版)来实现. 很少有人会写个APNS的桩服务, 事实也是如此. ...
- iOS推送服务细节回顾
iOS推送服务细节回顾 之前在做推送功能时候,就总结过一系列证书的制作,OC代码实现和服务器搭建等经验.又过了一段时间了,前前后后对推送服务做了多次的完善和优化,有iOS客户端的,还有本地服务器端的. ...
随机推荐
- [SaltStack] Return日志入库审计
SaltStack日志return审计 在我们执行salt任务时, 默认日志是屏幕打印的, 对于我们审计任务运行情况带来很不方便, 因此我们对日志结果进行了二次开发, 将job日志处理后入库, 方便查 ...
- LeetCode OJ-- Populating Next Right Pointers in Each Node
https://oj.leetcode.com/problems/populating-next-right-pointers-in-each-node/ 二叉树遍历的变种:树的节点多了个next指针 ...
- 用户找回密码功能JS验证邮箱通过点击下一步隐藏邮箱输入框并修改下一步按钮的ID
//这里是BaseDao /** * 获得一个对象 * @param hql * @param param * @return */ public Object get(String hql, Obj ...
- BZOJ1088(SCOI2005)
枚举第一行第一个格子的状态(有雷或者无雷,0或1),然后根据第一个格子推出后面所有格子的状态.推出之后判断解是否可行即可. #include <bits/stdc++.h> using n ...
- Codechef Chef and Triangles(离散化+区间并集)
题目链接 Chef and Triangles 先排序,然后得到$m - 1$个区间: $(a[2] - a[1], a[2] + a[1])$ $(a[3] - a[2], a[3] + a[2]) ...
- Codeforces 754A Lesha and array splitting (搜索)
题目链接 Lesha and array splitting 设s[i][j]为序列i到j的和,当s[i][j]≠0时,即可从i跳到j+1.目标为从1跳到n+1,所以按照题意暴力即可. #includ ...
- IT人为了自己父母和家庭,更得注意自己的身体和心理健康
我前一阵在一家互联网公司,工作节奏是995,忙的时候,要晚上10点才能离开公司,有时候周六还得加班.自己感觉身体状况有所下降,且听说其它一个组,在体检后多少都查出问题来,细思极恐. 有时候确实忙,那么 ...
- JMeter常见四种变量简介
在JMeter自动化测试脚本编写过程中,经常需要对测试脚本进行一些参数设置.例如,设置测试计划的全局变量(方便切换不同的测试环境).样本线程(HTTP请求等)的参数传递等. 通常,JMeter中常用的 ...
- luogu P1616 疯狂的采药
题目背景 此题为NOIP2005普及组第三题的疯狂版. 此题为纪念LiYuxiang而生. 题目描述 LiYuxiang是个天资聪颖的孩子,他的梦想是成为世界上最伟大的医师.为此,他想拜附近最有威望的 ...
- 使用Git Gui从Bonobo服务器中克隆Repository(仓库)
刚开始在使用Git Gui从Bonobo服务器中克隆Repository(仓库)中遇到一些问题,如下图所示: 后来百度,有人遇到类似的问题,得到解决思路,请大家参考这里.大意说出现这个问题是因为要克隆 ...