消息中间件对目前大中型互联网来说是非常重要的,在业务数据流动中仅次于RPC服务调用,担负着越来越复杂的网站业务从主流程上解耦的重要责任;
从目前互联网对消息中间件的需求来看应该分为两种类型,一种是和钱相关的需求,一种是和钱无关的需求;和钱相关的需求消息的可靠性是放在第一位的,和钱无关的需求是速度放在第一位的,但这两种需求又是矛盾的,很难设计出一种既可靠又高效的系统,除非将两套方案捏合成一个系统,通过配置来选择不同方案,但从实现上说还是两种实现。所以目前业界有几种不同的设计方式来满足不同的需求。下面看几种典型的实现方案:
1、以ActiveMQ为代表的可靠性优先的设计原理:简单、轻量、易部署(JMS Provider负责消息路由)
此种方案将所有的消息数据和消息的发送状态都存储在消息服务器上,可以在消息服务上通过多种手段来保证消息的可靠性,但增加了众多复杂的可靠性保证手段后,消息从发布者到订阅者的速度势必会受到影响;此种方式发布者将消息推向消息服务器,消息服务器再将消息推向订阅者,为消息发送策略提供了很好的可扩展性;
ActiveMQ参见:http://manzhizhen.iteye.com/category/318342
2、以KafKa为代表的速度优先的设计原理
此种方式将消息的发送状态保存在客户端,同时客户端用拉的模式从消息服务器上获取消息,由于是顺序读,同时还采取了很多保证速度的策略,如zero-copy,所以此种方案速度比较快,但牺牲了很多可靠性方面的保证,比较适合Web2.0网站,这些网站对消息的可靠性要求不是很高,同时由于产生了大量的和用户状态相关的消息,需要一个高效的系统来处理这些消息;另外这种方案也比较适合日志消息的收集;
- broker: 缓存代理,kafka集群中的一个kafka服务节点称为一个broker,主要存储消息数据。不是主从关系,各个broker在集群中地位一样,可以随意的增删broker节点。
- topic: kafka 处理的消息的分类。
- partition: 一个topic在broker中被分为1个或者多个partition,分区在创建topic的时候指定。
- message: 消息(offset,MessageSize,data),是通信的基本单位,每个消息都属于一个partition。
- producer: 生产者,向kafka的一个topic发布消息。
- consumer: 消费者,订阅topic并处理其发布的消息。
- zookeeper: 协调kafka的正常运行。
- push-and-pull : Kafka中的Producer和consumer采用的是push-and-pull模式,即Producer只管向broker push消息,consumer只管从broker pull消息,两者对消息的生产和消费是异步的。
消息的发送流程如下:
- 1、Producer: 可以根据用户自定义算法来根据消息的key来计算输入到哪个partition。可以指定同步异步(producer.type),异步发送模式允许进行批量发送,先将消息缓存在内存中,然后一次请求批量发送出去。(queue.buffering.max.ms=5000、queue.buffering.max.messages=10000)。
- 2、broker 为了减少磁盘写入的次数,broker会将消息暂时buffer起来,当消息的个数达到一定阀值或者过了一定的时间间隔时,再flush到磁盘,这样减少了磁盘IO调用的次数。配置(log.flush.interval…、log.retention…默认7天)。
- 3、kafka: 集群接收到Producer发过来的消息后,将其持久化到硬盘,并保留消息指定时长(可配置),不关注消息是否被消费。
- 4、Consumer: 从kafka集群pull数据,并控制获取消息的offset。每个consumer属于一个consumer group,可以指定组id。Group.id。
3、传统的解耦方案
消息队列中间件的技术选型分析请参见:http://www.cnblogs.com/lsx1993/p/4657897.html