基于SEDA的异步框架设计与实现
三、异步框架技术选型
在这次实现的SEDA异步框架中,采用的基础架构原型如下:
采用了spring+quartz+fastjson+rabbitmq来实现。和传统SEDA架构区别比较大的地方在于:
1、采用分布式mq(使用了rabbitmq)而不是blockingqueue。如此既可以支持以后可能进行的分布式化扩展,也可以使得框架具有高可用性,在大数据处理的时候仍可具有较为客观的性能。同时,消息的传递过程中,采用了高性能的fastjson进行数据序列化和反序列化。使得数据在stage之间的传递速度更快。
2、除了分布式mq之外,还提供了本地动态线程池所需要的队列。避免了consumer由于长时间处理导致数据在队列中积压。
3、stage利用quartz来提供定时功能,使得stage中的work可以选择定时/实时进行数据处理。从而迎合更多不同类型的需求。(比如定时报警,定时分析监控数据)
1、spring
spring无需再赘述,使用其IOC、AOP等功能,并同时使用spring的其他组件比如spring-rabbit、spring-quartz等。保证spring各包兼容即可。
2、quartz
quartz 的介绍文档网上很多,quartz作为一款优秀的定时器框架可以和spring无缝结合,同时还具有java自带的定时器timer所不具备的定时启动的 功能。其类crontab风格的定时任务声明也更符合我们企业级应用过程中的书写风格。之前文章中介绍过使用quartz过程中需要关注的几个点,复述如 下:1)Job不能为内部类,否则无法初始化
2)保证spring升级到新版本。如果使用老版本比如3.0.5,则会出现如下异常:
- java.lang.IncompatibleClassChangeError: Found interface org.quartz.JobExecutionContext, but class was expected
4)其定时语法和crontab有些许差别。语法见:
http://www.blogjava.net/javainthink/archive/2006/10/19/76077.html
3、fastjson
fastjson官网:http://code.alibabatech.com/wiki/display/FastJSON/Home-zh。如其描 述,"fastjson是最快的json库。特别在parser方面,fastjson的性能令人惊奇,甚至超越了二进制协议的protobuf"。虽然 只是fastjson一家之辞,但是从protobuf官网上对各种序列化/反序列化工具进行的性能测试中,也可以看出fastjson优异的性能已经将 传统的jackson工具抛在身后。除了速度这一最大优势之外,其还具有如下优势:
1)遵循http://json.org标准,为其官方网站收录的参考实现之一。
2)功能强大,支持JDK的各种类型,包括基本的JavaBean、Collection、Map、Date、Enum、泛型。
3)无依赖,不需要例外额外的jar,能够直接跑在JDK上。
4)开源,使用Apache License 2.0协议开源
在异步框架中的使用场景:辅助stage到stage之间的数据通信,负责数据在通信过程中的序列化和反序列化过程。
4、rabbitmq
stage与stage之间需要依靠事件队列来进行通信,如果依赖于SEDA官网推荐的BlockingQueue,则无法满足未来的分布式部署。所以决定采用分布式mq来实现。以下比较几个主流的消息中间件:
1) activemq:
被称为消息中间件中的瑞士军刀。支持JMS,性能不错。开源社区活跃。能与java很好结合。Spring有相应lib。其功能较为完备,可支持P2P和代理,但性能逊于rabbitmq。从性能角度出发来考虑,决定不使用activemq。
2)zeromq
性能比其他中间件优异得多。但无法持久化,不能保证数据的可靠性。由于数据的可靠性不能被保证,所以暂时也不考虑。
3)redis 可以当作轻量级的中间件。当传输数据大小少于10k时入队性能优异,数据较大时性能急剧下降。而其出队性能不论数据量大小都十分优秀。考虑到项目实现过程 中可能出现的大于10K的请求响应事件数据(比如推荐关键词、比如与后端服务交互返回的数据),所以不采用redis。
4)kafka
除此之外,kafka也是一款值得注目的,性能优异的分布式消息中间件,通过producer的push和consumer的poll来实现数据的交互。 kafka自带负载均衡、并有高可用、高吞吐等特性。但是考虑到实际项目的适用情况,暂时还不需要zookeeper集群,broker集群来进行如此大 规模的数据处理。加上其依赖于scala环境,所以要部署和运维显得不那么方便。所以暂时不考虑。
5)rabbitmq
支持AMQP,性能优于activemq。能与java很好结合。Spring有相应lib。环境部署起来不如activemq便捷,需要erlang环境。
在http://www.aqee.net/message-queue-shootout/一文中对activemq和rabbitmq进行的性能比较显示出rabbitmq更佳的性能。如下图所示:
综上所述,考虑到该次项目所应用的场景和处理数据量的规模,且需要较为优秀的性能,较为便捷的部署方式,能保证消息可靠性以及可持久化,并且对java友好。最终权衡之下,选择了基于AMPQ的rabbitmq消息中间件。
(Surlymo)