Ejabberd 套接字基础架构

Ejabberd 是一个网络服务器, 那么套接字必然是通信的基础. 通过本文我们要搞清楚下面几个问题:

  1. Ejabberd 是如何工作的
  2. 如何Hack它获取自定义的特性

本文分析的源码版本基于Ejabberd 2.1.10

Ejabberd 调试

2015-11-12 更新: 动态修改日志等级

进入调试控制台

1
ejabberdctl debug

设置日志等级

1
ejabberd_logger:set(4).

本文通过分析Ejabberd服务器和客户端之间的通信,帮助你理解XMPP协议.

Ejabberd 集群

更新

安装Erlang 17.3 (Ubuntu 14.04)

配置工作流概要

  • 修改两个服务器的HOSTNAME
  • 修改两个服务器的/etc/hosts(内网)或DNS(外网)
  • 修改/etc/ejabberd/ejabberd.ymlhosts
    • 设置虚拟主机名称
  • 修改/etc/ejabberd/ejabberdctl.cfg
    • 修改ERLANG_NODE(节点名)
    • 修改INET_DIST_INTERFACE(节点地址)
  • 下载和编译easy_cluster

    1
    wget https://github.com/chadillac/ejabberd-easy_cluster/raw/master/easy_cluster.erl
    mv easy_cluster.erl /lib/ejabberd/ebin
    cd /lib/ejabberd/ebin
    erlc easy_cluster.erl
  • 使用easy_cluster

启动ejabberd到live模式

1
ejabberdctl live

执行

1
easy_cluster:test_node('name@node')
  • 如何验证集群成功了
    ejabberdctl live模式下执行

    1
    mnesia:info().
    查看`running db nodes`, 如果包含两个集群的节点列表. 那么集群就运行起来了.

配置示例

将设有两台服务器

1
master.chat-server.info
slave.chat-server.info

使用MySQL替代Mnesia

登陆MySQL

1
mysql> mysql -uroot -proot --host=192.168.8.33

创建数据库

1
create database ejabberd charset = utf8

导入表结构

1
source /root/ejabberd/sql/mysql.sql

Ejabberd的部分模块支持在MySQL存储数据, 比如mod_roster, 需要在模块配置中设置db_type: odbc并创建数据库表结构, 例如:

编辑/etc/ejabberd/ejabber.yml,设置mod_roster模块的db_type: odbc

1
mod_roster:
  db_type: odbc
  • 修改/etc/hosts, 在两台服务器上分别增加如下记录:

    1
    192.168.8.100   ejabberd@master.chat-server.info
    192.168.8.200   ejabberd@slave.chat-server.info
  • 两台服务器上分别设置HOSTNAME为master.chat-server.info, 和slave.chat-server.info

    1
    vi /etc/hostname

两台服务器分别配置/etc/ejabberd/ejabberdctl.cfg:

  • 修改节点名称ERLANG_NODE
1
# master
ERLANG_NODE=ejabberd@master.chat-server.info
# slave
ERLANG_NODE=ejabberd@slave.chat-server.info
  • 分别设置/etc/ejabberd/ejabberd.yml中的hosts
1
# master
hosts:
  - "master.chat-server.info"
# slave
hosts:
  - "slave.chat-server.info"

参考资料

  1. http://chad.ill.ac/post/35967173942/easy-ejabberd-clustering-guide-mnesia-mysql
  2. https://raymii.org/s/tutorials/Set_up_a_federated_XMPP_Chat_Network_with_ejabberd.html
  3. https://www.ejabberd.im/node/5669?q=node/5669
  4. http://cqwjfck.blog.chinaunix.net/uid-22312037-id-3509097.html
  5. http://chad.ill.ac/post/55193155663/easy-ejabberd-clustering-multi-master-fault-tolerant
  6. http://tdewolf.blogspot.com/2009/07/clustering-ejabberd-nodes-using-mnesia.html

XMPP XEP-0047 带内字节流

该协议扩展有一个比较经典的应用场景. 通常XMPP服务器为了性能上的考虑,限制了Stanza(XML节)的大小不能超过指定的字节数.

当我在野外探险的时候,我发现了一个仙境,但是我通过XMPP客户端给我的兄弟伙说的时候,他既然不相信,怎么能让他相信我呢,我带了手机,我首先想到的时给他发送一张我拍的照片. 但是我的XMPP服务器限制了最大不能发送超过64KB大小的. 所以我不得不把照片数据切分为多个小于64KB的, 然后把这些块连续的发给我的兄弟,让他收完后在组装起来.

SVG 精灵图片

font-awesome图标转换为Svg精灵(Sprite)

这篇文章 说明了如何把font-awesome的png图片转换为svg精灵图片

参考资料

  1. 未来必热:SVG Sprite技术介绍
    http://www.zhangxinxu.com/wordpress/2014/07/introduce-svg-sprite-technology/

  2. Icon System with SVG Sprites
    http://css-tricks.com/svg-sprites-use-better-icon-fonts/

  3. UNLEASH THE POWER OF SVG SPRITES
    http://dev.webonomic.nl/unleash-the-power-of-svg-sprites

  4. How to Use SVG Image Sprites
    http://www.sitepoint.com/use-svg-image-sprites/

  5. Ten reasons we switched from an icon font to SVG
    http://ianfeather.co.uk/ten-reasons-we-switched-from-an-icon-font-to-svg/

XMPP XEP-0085 聊天状态通知

该扩展协议比较容易理解, 在我们最常用的多数IM即时聊天工具都能看到对方是否正在输入. 可以让我们知道对方对此次会话的关注情况. 该扩展协议解决了即时聊天中记的几个问题:

  1. 这个参与者是否已经停止了输入?
  2. 这个参与者是否注意这次聊天?
  3. 这个参与者是否暂时没有激活这个会话(换言之,此时没有注意这次聊天)?
  4. 这个参与者是否已离开(也就是说不再参与这次聊天了)?

Ejabberd 配置

从Ejabber 13.10开始Ejabberd把原来Erlang Term的配置文件格式改为YAML格式的配置文件. 下面列举了一些常用的配置项

XMPP 设置BOSH连接管理器

Web 浏览器对XMPP没有原生的支持, 为了在Web应用中使用XMPP, 需要一个中间件来把无状态的HTTP请求转换为有状态的XMPP连接. 这个过程被称为同步HTTP双向流(Bi-directional stream Over Synchronous HTTP), 提供这个服务的服务器被称为连接管理器.

工具 - screen

使用screen命令在多个终端之间切换,同时又不会导致退出终端会自动终止运行的进程. 三个最常用的操作

  • 创建会话

    创建一个网卡流量监控的会话

    1
    screen -S nload
  • 离开

    按住 Ctrl 不放, 按 A D

  • 恢复

    1
    screen -r nload

Tsung 用户手册

Tsung是用Erlang开发的一个大规模负载测试工具, 由于Erlang天生就是为大规模并发设计的, 因此Tsung可以模拟大规模的用户操作, 这是Erlang本身给Tsung带来的优势.

XMPP Stanza (节)

XMPP 通信的基本单元是本成为stanza的东西,类似下面的实例:

1
<stream:stream>
    <iq type="get"><query xmlns="jabber:iq:roster"/></iq>
    <presence/>
    <message to="william_duan@jabber.org" from="test_account@jabber.org" type="chat"><body>Hello</body></message>
    <presence type="unavailable"/>
</stream:stream>

XMPP Addressing

  • 每个实体(Entity)有一个或多个地址, 这个地址被称为JID(Jabber Identifer)
  • 每个地址由三部分组成, 本地部分, 域名, 资源, 域名部分是必须的, 取决于上下文的不同,另外两个部分(本地部分,资源)是可选的.

Jabber 服务器/客户端库

文章目录
  1. 1. Clients
  2. 2. Servers
  3. 3. Gateways/Connection Managers
  4. 4. Articles

Clients

Name Language Official Site
XMPPFramework Objective-C https://github.com/robbiehanson/XMPPFramework
Strophe.js Javascript http://strophe.im/strophejs/
Candy.js Javascript https://github.com/candy-chat/candy
Converse.js Javascript https://conversejs.org/
stanza.io Javascript https://github.com/otalk/stanza.io
gloox C++ http://camaya.net/

Servers

Server Implementation Language Official Website
Prosody Lua https://prosody.im/
Ejabberd Erlang https://www.ejabberd.im/
Tigase Java http://www.tigase.org/
MongooseIM Erlang https://github.com/esl/MongooseIM

Gateways/Connection Managers

Name
Kaazing WebSocket Gateway
node-xmpp-bosh

Articles

  1. https://www.linode.com/docs/applications/messaging/
  2. http://anders.conbere.org/2011/05/03/get_xmpp_-_bosh_working_with_ejabberd_firefox_and_strophe.html
  3. http://kaazing.com/products/editions/kaazing-websocket-gateway-xmpp/

问题: 使用命令mongooseim start后大概30秒内,服务器自动停止,
mongooseim ping出现 Failed RPC connection to the node mongooseim@localhost: nodedown

答案: 使用sudo mongooseim start