Tigase--packet流转机制

初看Tigase的packet内部流转机制。Tigase通过tigase.io包当中的代码读取网络中的字节数组,然后通过tigase.net包当中的类把字节数组转换为字符,最后通过tigase.xml包当中的XML解析器把这些字符转换成XML DOM对象。

图片流程说明

看tigase源码你会发现所有的tigase处理都是基于多线程,每个component都有自己的in和out处理线程,线程间的数据传输通过queue
总的流程大致就是:


Tigase的packet内部流转机制

文字流程说明

下面是请求和响应的步骤说明(只列出了关键的步骤)。

A. 从client到server的过程(请求-Request)

ClientConnectionManager和MessageRouter都间接或直接继承了AbstractMessageReceiver。

tigase.server.AbstractMessageReceiver

– 它已经实现了四个接口:ServerComponent,MessageReceiver,Configurable和StatisticsContainer。

它通过自己的多个线程来管理内部数据队列,且能避免死锁。

它使用事件驱动的方式来处理数据,当packet被发送到AbstractMessageReceiver实例的abstract void processPacket(Packet packet)方法时,就立即启动了packet的处理工作。当然你还是需要实现抽象类当中的抽象方法,如果你还希望输出packet数据(例如当它收到请求时还需要发送响应),可以调用boolean addOutPacket(Packet packet)方法。

a. XMPPIOService负责接收客户端报文并转换为对应的packet放入队列receivedPackets(相当于in_queues)中,而SocketThread负责创建ReadThread和WriteThread线程,

ResultsListener则是SocketThread的一个内部类。ResultsListener负责调度socketReadThread()和
socketWriteThread(), Client2Server读取和写入数据包的IO操作主要由XMPPIOService来完XMPPIOService实例则在read和write线程中被使用。

b. ClientConnectionManager则负责从XMPPIOService获取receivedPackets,并对收到的报文进行处理,并将处理后的报文放入MessageRouter的out_queues队列中。

c.MessageRouter重写了AbstractMessageReceiver的processPacket方法,在该方法中MessageRouter通过packet.getTo()得到组件的名称并转发packet到该组件的in_queues队列中,该目标服务组件(如ses-man,即SessionManager)可能在本机服务器上,也可能在该域(domain)集群的其他服务器上运行MessageRouter的查找顺序是先查本机服务器,找不到的话再去集群中查找;如果找到则将packet转发给目标组件处理,如果没找到则返回没有找到目标组件的错误消息。

d. 我们的组件一般都有自己的in_queues和out_queues. 当前组件的in_queues的数据来自于上一组件的out_queues。

int  queueIdx = Math.abs(hashCodeForPacket(packet) % in_queues_size*);
boolean  result = in_queues.get(queueIdx).offer(packet, packet.getPriority().ordinal());

//这里的packet数据来自于packetFrom="xxx",即传给当前组件的上一组件。

B.从Service到Client的过程(响应-Response)

服务端响应的数据也是放到out_queues中的,各组件的对应的线程会对out_queues中的packet的to属性做解析,并将消息转发到指定目标。其实消息的流转传递机制实现的核心就是packet的 from包含packetFrom和stanzaFrom) 和 to(packetTo和stanzaTo)属性,路由的路径会默认先取packetFrom或packetTo,其次再去取stanzaFrom和stanzaTo。

客户端发送一条ping命令

<iq type='get' id='purplee4ad721'>
<ping xmlns='urn:xmpp:ping'/>
</iq>

IOService.java

public abstract class IOService<RefObject>
            implements Callable<IOService<?>>, TLSEventHandler,
            IOListener {

/**接收报文后call->处理客户端报文数据信息*/
@Override
public IOService<?> call() throws IOException {
   writeData(null);

   boolean readLock = true;

   if (stopping) {
      stop();
   } else {
      readLock = readInProgress.tryLock();
      if (readLock) {
         try {
            processSocketData();
            if ((receivedPackets() > 0) && (serviceListener != null)) {
               serviceListener.packetsReady(this);
            }    // end of if (receivedPackets.size() > 0)
         } finally {
            readInProgress.unlock();
            if (!isConnected()) {
               // added to sooner detect disconnection of peer - ie. client
               if (log.isLoggable(Level.FINEST)) {
                  log.log(Level.FINEST, "{0}, stopping connection due to the fact that it was disconnected, forceStop()", toString());
               }
               forceStop();
            }
         }
      }
   }

   return readLock
         ? this
         : null;
}

/**
 * Describe
 * <code>writeData</code> method here.
 * 这里是最后响应消息给客户端的方法,写入TCP连接中的Socket
 * @param data a
 * <code>String</code> value
 */
protected void writeData(final String data) {

返回消息前还调用了下面两个类的对应write方法

SocketIO.java
@Override
public int write(final ByteBuffer buff) throws IOException {
}


TLSIO.java
public class TLSIO implements IOInterface {
         private int writeBuff(ByteBuffer buff) throws IOException {
          }
}

IOService打包好了消息之后形成响应的packet包,->然后再执行到ConnectionManager的writePacketToSocket()方法->再执行到ClientConnectionManager的processPacket方法。

至此本次消息的请求和响应结束!server会继续通过AbstractMessageReceiver获取下一条消息进行处理,如此循环。。。


  1. tigase.server.ServerComponent – 这是一个非常基本的component接口。所有的component都必须实现接口中定义的方法。

  2. tigase.server.MessageReceiver – 这个接口extends ServerComponent,所有希望接收数据packets的Component都需要实现接口中定义的方法,比如session manager和c2s connection manager。
    tigase.conf.Configurable – 如果希望components可以被配置,则需要实现这个接口,所有默认定义基本都在这。在运行时,配置信息会被推送到这种类型的对象。components必须能够在运行时对变更的配置项进行处理,这一点在实现时要留神。

  3. tigase.disco.XMPPService – 实现了这个对象的类可以对“ServiceDiscovery”请求做出响应。

  4. tigase.stats.StatisticsContainer – 实现了这个对象的类可以返回运行时的统计信息。任何一个对象都可以实现这个接口用来收集统计信息

  5. tigase.server.AbstractMessageReceiver – 它已经实现了四个接口:ServerComponent,MessageReceiver,Configurable和StatisticsContainer。它通过自己的多个线程来管理内部数据队列,且能避免死锁。
    它使用事件驱动的方式来处理数据,当packet被发送到AbstractMessageReceiver实例的abstract void processPacket(Packet packet)方法时,就立即启动了packet的处理工作。当然你还是需要实现抽象类当中的抽象方法,如果你还希望输出packet数据(例如当它收到请求时还需要发送响应),可以调用boolean addOutPacket(Packet packet)方法。

  6. tigase.server.ConnectionManager – 这是一个extend AbstractMessageReceiver的抽象类。正如其名,这个类专注于对连接进行管理工作。如果你的组件需要通过网络直接发送或接受数据(比如c2s connection,s2s connection 或者 连接到外部第三方jabber服务),你可以把它作为基类进行扩展。它会帮你把所有和网络有关的工作都打理好(例如io,重连,socket监听和连接握手等工作)。
    如果你extend这个类,你需要知道数据来源于哪里:如果来源于MessageRouter,那么abstract void processPacket(Packet packet)方法会被调用; 如果来源于网络连接,那么abstract Queue processSocketData(XMPPIOService serv)方法会被调用。

网络

connectionManager同时协调ConnectionOpenThread与SocketThread。
ConnectionOpenThread脱离上述组件,属于网络层实现,操作selector。它负责Selector.open。
IOService提供线程安全的call方法,XMPPIOService继承它,保存了连接信息,每个连接一个IOService。
SocketThread在实例化时,会启动多个线程,同时盯住selector。负责将每个确定的IOService进行数据处理。
实现ConnectionOpenListener接口accept方法接收SocketChannel,组装IOService,交由SocketThread处理。
ConnectionManager用ConcurrentHashMap记录了所有的连接。
零碎

AbstractMessageReceiver.addPacket 往自己的in_queue里加数据,是阻塞的,如果满了会出事。
AbstractMessageReceiver.addPacketNB 往自己的in_queue里加数据,非阻塞的,和上一个的区别在于,一个是put一个是offer到queue。
AbstractMessageReceiver.addPackets 来一堆数据。
所有in_queue里的数据,会被processPacket方法所处理。
对应有addOutPacket。
所有out_queue里的数据,都默认扔给parent的in_queue,没有parent就扔到自己的in_queue。
所有in_queue的数据,都由processPacket具体的实现来处理。

企业级独立部署应用:知行办公http://zx.naton.cn
【总监】十二春秋之,3483099@qq.com
【Master】zelo,616701261@qq.com
【运营】运维艄公,897221533@qq.com
【产品设计】流浪猫,364994559@qq.com
【体验设计】兜兜,2435632247@qq.com
【iOS】淘码小工,492395860@qq.com;iMcG33K,imcg33k@gmail.com
【Android】人猿居士,1059604515@qq.com;思路的顿悟,1217022114@qq.com
【java】首席工程师MR_W,feixue300@qq.com
【测试】土镜问道,847071279@qq.com
【数据】fox009521,42151960@qq.com
【安全】保密,你懂的。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,126评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,254评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,445评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,185评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,178评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,970评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,276评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,927评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,400评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,883评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,997评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,646评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,213评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,204评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,423评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,423评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,722评论 2 345

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,599评论 18 139
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,498评论 25 707
  • 从三月份找实习到现在,面了一些公司,挂了不少,但最终还是拿到小米、百度、阿里、京东、新浪、CVTE、乐视家的研发岗...
    时芥蓝阅读 42,184评论 11 349
  • 今日看到《失控的“中杯”,星巴克们到底错在哪?》一文,想起几年前曾看过的一本书——《在星巴克要点大杯咖啡》(书中以...
    风起云卷纵四海阅读 2,233评论 0 0