3 短消息网关通信模块的设计与实现
短消息网关通信模块是整个短消息网关的基础。无论是计费、统计,还是超时重传,高质量的通信构架是必不可少的保障。这个通信构架不仅要完成基本的收发消息的功能,而且还要有好的结构以支撑各种业务需求,保证良好的扩展性。
3.1. 短消息网关通信模块的设计
在设计短消息网关通信模块时,我们考虑了以下几点:
第一,由于短消息网关功能繁多,如果把通信和具体业务合在一起开发,容易顾此失彼。可能会因为开始的考虑不周全,造成在增加某项新业务时不得不修改通信底层和原来的业务代码,导致重复开发。所以我们采用通信代理的方式把通信和具体业务分开,在增加新业务时,就只需少量修改通信代理的设置,而且不必再改动原来的业务代码了。
第二,通信代理需要同时侦听多个端口,我们选用多路复用I/O这种方式。虽然多线程能够通过并行计算和共享内存提高代码效率和资源利用率,但在短消息网关中,处理的数据量大,多线程方式的并行处理会造成一些消息的逻辑混乱,资源共享也会增加代码的复杂度。而多路复用使用简单,逻辑清晰明了,不易发生错误,也不会出现因资源共享带来同步和互斥问题。因此使用多路复用I/O是比较合理的。
第三,业务处理模块与通信代理之间可以使用队列进行通信,对队列的管理和参数的设置(例如对同一队列操作的互斥,以及队列个数的设置等)都使用专门的队列内核程序统一调度并封装成函数接口,以方便业务处理模块对队列的使用。另外,通过队列通信,也可以为今后增加的业务提供良好的扩展性。
第四,为了达到99.999%的不丢包率,通信代理需要使用流量控制机制以保证网关内部不丢包。这是因为无论队列设置有多大,如果出现消息只发不收的情况,都会造成队列溢出而丢包。因此,为每个队列中缓存的消息做记录,当某个时刻队列消息的数量达到规定限度,队列就不再收包,以保证到达网关的消息不会丢失。
3.2. 短消息网关通信模块的实现
基于以上设计思路,我们实现的短消息通信模块包括四个父进程:CMPP通信代理(cmpp_server)、SMPP通信代理(smpp_server)、消息分发处理server(package_server)和前转消息处理server(route_server)。它们之间通过6个消息队列相互通信。具体的软件结构如图2所示。
Cmpp_server主要为SP和网关之间建立一条高质量的传输通道。它同时侦听与它相连的多个socket,通过队列接口函数mqm_send( )把接收到的CMPP格式的消息送入队列2中。同时,它也要通过函数mqm_recv( )不停的从队列1中获得消息,并把它转发到相应的目的SP。cmpp_server不需判断收到的消息类型,只负责通信,因此称通信代理。
Smpp_server与cmpp_server基本一致,唯一不同的只有一点:SMPP协议规定smpp_server是客户端,需要主动发起建立连接的请求;而CMPP协议规定cmpp_server是服务器端,需等待对方连接。
Package_server是短消息网关的核心,所有的消息都要经过它,包括协议转换,超时重传,计费,路由,都需要在package_server中完成。package_server同时监听2、4、6三个队列,根据不同的消息头来判断这个消息的下一个目的地。路由表也需要在package_server中维护,以便package_server能得到路由信息,转发消息。如果路由表中找不到相关的信息,package_server就要把该消息转发给route_server,由route_server从汇接网关处获得路由信息后发送该消息。
Route_server主要处理需要转发到其他网关的消息。当package_server发现消息的目的地不是本地网关所连的SP或SMSC,那么它就会把消息转发给route_server处理。Route_server接到消息后与汇接网关通信,请求目的地的网关地址,然后与目的网关建立socket连接,交付该消息并记录前转话单。
在整个通信模块中,所有的server都使用队列接口函数mqm_init( )初始化消息队列并复接在队列上。收发数据使用mqm_send( )和mqm_recv( )函数完成。存储消息采用固定的数据结构,其结构如下:
struct mqm_connection { unsigned int package_server_seqnum; //由网关自行产生。若消息从队列4中来,该元素将是转化后的//CMPP协议格式的消息序列号;若消息从队列2中来,该元素将是转化后的SMPP协议格式的消息序列号。 short mqm_sockfd; //接收该消息的socket; short mqm_seqnum; //收到的消息序列号; time_t mqm_timeout; //收到该消息的时间; int total_length; //该消息的长度; char mqm_buf[MAX_PACKET_SIZE]; //该消息的内容; char converted_buf[MAX_PACKET_SIZE]; //转换协议后的消息内容; }; |
现以MO请求业务为例,描述通信模块的工作流程。
当SMSC以SMPP格式的DELIVER_SM消息发出订阅某个SP的言语传情短消息,经由smpp_server收到,从队列4中转发给package_server。Package_server收到MO请求后回送给SP一个SMPP格式的DELIVER_SM_REP应答消息,并用mqm_connection结构体存储这条MO消息的各个信息。 之后,package_server就把该消息转换成CMPP协议的CMPP_Deliver消息,并通过队列1送到cmpp_server中,转发给目的SP。SP在接收到这个消息后,会产生一个CMPP格式的CMPP_Deliver_Rep的应答消息返回给网关。当package_server收到了应答信号,也需要用mqm_connection结构体存储。这时,一条MO短消息转发成功,package_server记录SMO话单。
下面给出在Linux7.2版本的操作系统下,用C语言实现的package_server的主要代码:
main() { mqm_init( ); //初始化队列; …… pipe( ); //建立管道; if (( child_pid = fork( ) ) ==0) { //通过管道通知2队列有数; while(1){ get_result_msg_info(REQUEST_2,pipfd2[1]); } } …… //建立监听描述符集; FD_ZERO ( &monit); FD_SET ( )_; …… //处理队列中来的数据 while(1) { select ( ); //监听2,4,6队列; if ( FD_ISSET(queue2,&read_monit )) //如果2队列有数; { handle_queue2_in( );//处理2队列来的数据; } …… }//end while; } //end main;
|
4 结束语 短消息网关是无线互联网短消息业务中最为关键的一个设备,它为手机用户和互联网的信息资源架起了一座桥梁。本文中短消息网关的通信模块设计周全,结构合理,为计费、路由、超时重传等模块提供了良好的扩展性。经实验室测试,在奔2处理器,64兆内存的机器上,收发包速率为每秒5000条,不丢包率达到100%,是一个稳定的系统。
查看本文来源