消息处理方法 【技术领域】
本发明涉及计算机技术领域, 特别涉及一种消息分发及性能调优技术中的消息处理方法。 背景技术 在大访问量、 高并发的大型网站中, Web 服务器的线程消耗是非常严重的, 线程资 源十分保贵, 如何提高线程利用率、 提高请求的响应能力常常是网站性能优化的关键点。 但 在系统中又常常会有一些高并发、 高耗时、 低实时性的操作, 这些操作的结果对于网站用户 来说并不需要及时反馈, 但是如果网页等待这些同步操作返回, 则对线程占用和响应都有 严重的影响, 减少服务的吞吐量。 这样, 如何分流这些消息, 进行异步处理就变得重要了。 异 步调用框架就提供了一个通用的模型来处理这样的调用。
现有方案一 : 使用线程池对耗时操作进行异步处理。把一个需要执行的操作交给 线程池, 线程池自己负责线程的创建、 分配和销毁。 通过使用线程池可以对高消耗的操作进 行优化, 从而提高系统的处理能力和吞吐量。其缺陷是 : 线程池仍然是消耗本机线程, 在高 并发的情况下对 CPU 和内存消耗非常严重, 虽然可以通过修改配置提高线程数, 但是对本 机资源的消耗是无法有效解决的。
现有方案二 : 使用消息队列 (MSMQ) 异步处理高消耗的操作。 通过使用消息队列可 以把待处理的消息路由到本机或者别的机器上的另外一个进程进行处理。 这种方式提供更 好的资源扩展, 通过把消息路由到别的机器进行处理, 可以降低对本机资源的消耗, 同时消 息队列所提供的异步和离线机制可以更好的提高主程序的响应能力。 消息队列的离线机制 也有效保障了消息传递的可靠性。 其缺陷是 : 消息队列本身没有合适的可编程机制, 支持针 对不同的消息处理应用相对应的插件进行处理的机制, 以及针对不同消息的按需的灵活路 由, 需要在此基础上进行扩展。
发明内容 ( 一 ) 要解决的技术问题
本发明要解决的技术问题是 : 如何提供一个通用的框架, 对消息进行分流和异步 处理, 并且使服务端能够支持针对不同的消息动态地选择相应的插件分别进行处理。
( 二 ) 技术方案
为解决上述技术问题, 本发明提供了一种消息处理方法, 其特征在于, 包括以下步 骤:
S1 : 客户端把要进行异步处理或离线处理的消息路由到对应的服务端 ;
S2 : 服务端接收所述消息, 然后分析其中的消息来源参数, 生成可在反转控制 IOC 容器中提取的关系名称 ;
S3 : 通过所述关系名称从所述 IOC 容器中提取与消息对应的消息处理器 ;
S4 : 在各自的消息处理器中实现对消息的处理。
其中, 步骤 S1 具体包括 :
S11 : 客户端把要进行异步处理或离线处理的消息写入微软消息队列 MSMQ ;
S12 : Windows 操作系统根据服务端提供的服务地址, 把消息自动路由到服务端。
其中, 步骤 S1 中消息队列的写入操作应用 Windows 通信基础 WCF 来处理。
其中, 步骤 S2 中生成可在反转控制 IOC 容器中提取的关系名称具体方式为 : 根据 事先在 IOC 容器中注册的消息来源参数与消息处理器的对应关系提取关系名称。
其中, 在步骤 S2 中, 通过所述服务端提供的消息服务接口接收所述消息。
其中, 消息接口中的参数包括 : 消息标识和消息来源标识, 所述消息来源标识包 括: 客户端标识、 服务标识及服务的版本 ID。
其中, 在步骤 S2 中, 所述消息处理器通过统一的接口被调用。
其中, 在步骤 S4 中, 对消息的处理包括对外部服务的调用、 对数据库的操作以及 进行日志记录。
( 三 ) 有益效果
本发明通过综合应用 MSMQ、 WCF、 IOC 容器和巧妙的接口设计, 我们开发出了一个 可以支持异步处理消息、 具有自动选择插件进行消息处理功能的通用的异步调用方法。通 过应用此方法可以把消息的处理路由给别的进程或者别的服务器进行处理, 能够指定不同 的服务地址和部署更多的服务器进行处理, 从而可以支持大量的消息处理任务, 进而大大 地优化网站或服务的性能, 提高该网站或服务的吞吐量和降低响应时间, 更有效地利用服 务器资源。 附图说明
图 1 是本发明的一种消息处理方法流程图 ; 图 2 是实现本发明的消息处理方法的客户端服务端框架结构图 ; 图 3 是本发明实施例的消息处理时序图。具体实施方式
为使本发明的目的、 内容、 和优点更加清楚, 下面将结合附图对本发明实施方式作 进一步地详细描述。
本发明的整体思路是 : 设计一个分布式调用框架, 分为客户端调用和服务端处理。
如图 1 所示, 本发明的步骤包括 :
步骤 S 1, 客户端把要进行异步或离线处理的消息写入 MSMQ(MicroSoft Message Queue, 微软消息队列 ), Windows 操作系统根据服务端提供的服务地址, 把消息自动路由到 服务端。
步骤 S2, 服务端接收来自于消息队列的消息, 然后分析其中的消息来源参数, 生成 可在 IOC(Inversion of Control, 反转控制 ) 容器中提取的关系名称。
步骤 S3, 服务端通过所述关系名称从所述 IOC 容器中提取与消息对应的消息处理 器。
步骤 S4, 在各自的消息处理器中实现对消息的处理, 包括对外部服务的调用, 数据 库的操作, 日志记录等。其中, 消息队列的写入和提取, 以及服务端的并发控制等相关网络问题通过应用 微软的 WCF(Windows CommunicationFoundation, Windows 通信基础 ) 技术进行统一处理。
图 2 示出了实现本发明方法的框架结构示意图, 图中示出了客户端 1 和客户端 2 分别通过各自的消息来源参数 source 和消息标识 identity 来调用服务, 具体通过 source 中的 serviceName 在分组中获取要调用服务的地址 address, 调用服务采用上述的 WCF 技术 将各自的消息放入消息队列中。服务端获取消息队列后, 根据消息来源参数和消息标识从 IOC 容器中选择正确的处理器来处理消息。具体步骤结合时序图进行描述。
如图 3 所示, 为消息处理时序图。
上述步骤 S1 具体包括 :
步骤 S 11, 客户端通过 WCF 把需要处理的消息写入本地的消息队列 MSMQ。因为应 用了微软的 WCF, 客户端把消息写入队列, 服务端获取队列中的消息均被表现为对服务接口 的调用和服务接口的实现处理。所以这里所谓的把消息写入消息队列, 实际上是对服务端 提供的一个消息服务接口进行调用。本实施例中, 消息服务接口 IServiceInvoker 定义如 下表 1 所示 :
表 1 服务端提供的服务接口定义
上述接口定义中, 参数 source 表示消息来源的标识, 用于对消息进行标记。其格 式为 : “clientName-serviceName-versionID”
clientName 表示客户端调用方的一个标识, 如客户端的某个服务或方法, 可自定 义。
serviceName 表示调用了服务端的消息处理器接口的哪个具体实现。
versionID 表示服务端消息处理接口的具体实现的哪个版本, 它与 serviceName 联合决定使用的具体的消息处理器。
例如 : 若消息的格式为 “Register-MailCallService-1.0” , 则 Registe 可以表示 在注册的过程中调用了异步服务 ; MailCallService-1.0 表示调用了服务端消息处理器接 口的 1.0 版本的 MailCallService 实现。
其中, 参数 identity 表示需要处理的消息内容或者消息标识, 是客户端和服务端
约定的参数。
步骤 S12, Windows 操作系统根据服务端提供的服务地址, 把消息自动路由到服务 端。
因为消息队列的应用是通过 WCF 实现, WCF 表现为服务端提供服务, 客户端调用服 务; 而服务端提供的服务为所有调用方都提供了一个服务地址, 客户端通过指定该服务地 址, 本地消息队列中的消息便可以自动地路由到服务地址所提供的服务的消息队列中。服 务地址的例子如下 :
net.msmq://192.168.200.13/private/ServiceInvokerProvider
该 服 务 地 址 表 明, 处理消息的服务器为 “192.168.200.13” ; 队列为私有队列 “ServiceInvokerProvider” ; net.msmq 表明应用了 WCF 的 NetMsmqBinding 邦定来处理服 务消息。
服务端从消息队列中获取消息是由 WCF 进行监听, 服务端的消息队列中接收到消 息后, WCF 便会把消息提取出来并且路由给提供服务的接口, 服务接口的实现便可以接收到 该消息, 以进行业务处理, 例如对外部服务的调用, 数据库的操作, 日志记录等。
服务端如何并发提取消息或者其它事务问题, 均由 WCF 内部管理实现, 我们只需 要进行相应的配置便可以控制消息队列中消息的处理频率等问题。 步骤 S2 采用了处理消息的插件机制实现。如上所述, 在服务端的接口实现中已经 能获取到从客户端传递过来的消息 (source 和 identity), 但如何让服务端自动选择正确 的消息处理器来处理对应的消息?在这里引入了 IOC 容器, 同时指定一个专门用于处理消 息的统一的消息处理接口, 该接口定义如下表 2 所示 :
表 2 消息处理接口定义
上述定义中, Call 方法的两个参数实质上与 IServiceInvoker 对外服务接口的 Invoke 方法的两个对应参数相同。但 IServiceInvoker.Invoke 方法如何知道该把消息发 送给哪个 ICallService 接口实现呢。在这里就引入的 IOC 容器, 本实施例中, IOC 容器使 用了开源项目 Castle 的 Windsor 容器。
IOC 容器的作用是 : 先为某个接口向容器中注册一些具体实现, 本实施例中采用 配置文件的方式实现注册, 配置文件记录了处理接口、 处理接口的具体实现以及它们之前
的关系名称。 这个关系名称定位了消息处理器。 IOC 容器在初始化的时候会读取配置文件, 在运行时动态提取接口的具体实现时便可以通过该关系名称进行动态提取。比如下表 3 中 向容器注册的具体实现为 :
表 3 配置文件中的注册信息部分
这 里 向 容 器 注 册 了 两 个 具 体 的 ICallService 接 口 的 实 现, 索引服务 IndexCallService 和 邮 件 服 务 MailCallService, 并且为这个关系定义了对应的关 系 名 称, 关系名称的命名规则为 “ICallService.{serviceName}-{versionID}” , 其中 {serviceName} 和 {versionID} 即为客户端调用 IServiceInvoker.Call 方法时所使用的 source 参数的 serviceName 和 versionID。前面说过这个参数格式中的这两个部分决定了 选择哪个具体的消息处理接口 ICallService。
步骤 S3 中, 通过 IOC 容器的选择功能, 可以轻松实现待处理消息与消息处理器的 对应关系, 以 IOC 容器为基础可以实现一个插件机制, 为不同的消息类型应用不同的消息 处理器, 不同的业务应用只需实现自已的 ICallService 接口并在 IOC 容器中通过命名进行 注册, 便可以实现服务在运行时的自动选择。
以 下 是 一 个 简 单 的 示 例,如 表 4 所 示,说 明 了 WCF 的 对 外 服 务 接 口 IServiceInvoker 接收到消息后把消息通过 IOC 容器转发给对应的 ICallService 消息处理 器。
表 4 从所述 IOC 容器中提取与消息对应的消息处理器的实现
表 4 中可看出在服务端提供的消息服务接口 IServiceInvoker 中统一调用了消 息处理接口 iCallService.Call, 且参数都是消息来源参数 source 和消息标识 identity, 在 iCallService.Call 中, 由上述的关系名称就能选择正确的消息处理器进行消息处理, 具体根据 source 参数中的 MailCallService-1.0 部分 (Register-MailCallService-1.0) 和 ICallService.{MailCallService}-{1.0} 选 择 iCallService 接 口 对 应 的 处 理 器 为 MailCallService 的 1.0 版本。选择处理器后即可执行步骤 S4, 步骤 S4 中包括对消息的处 理包括对外部服务的调用、 对数据库的操作以及进行日志记录等。
以上实施方式仅用于说明本发明, 而并非对本发明的限制, 有关技术领域的普通 技术人员, 在不脱离本发明的精神和范围的情况下, 还可以做出各种变化和变型, 因此所有 等同的技术方案也属于本发明的范畴, 本发明的专利保护范围应由权利要求限定。