RocketMQ 简介 -- Producer And Consumer

RocketMQ Producer And Consumer

Producer

  • Producer实例都有的Producer Group Name,此Name在事务消息时起作用。

  • Producer发送消息时,会尝试从NameServer获取TopicRoute信息。

  • Producer发送消息时,TopicPublishInfo中的每个MessageQueue代表一个Master的Broker。

  • Producer发送消息时,更具Topic选择Broker时的策略有延迟发送策略以及默认策略:

    1. 延迟发送策略:每次连接异常、或其他异常都会将Broker作为隔离broker设置禁用时间为3000;每次操作完成都会将目标broker的请求总时间保存;当每次请求时根据brokerName获取可用的(当前系统时间大于broker的启用时间)的Broker。

    2. 默认策略:在不使用上次使用的Broker前提下,通过ThreadLocal持有的Integer取模得到Broker。

      以上策略由于使用到了ThreadLocal,所以可能出现多个线程同时向同一个Broker发送的情况。

  • Producer发送的结果只能保证送达到Broker,无法确认是否被消费,即SEND_OK。

  • Producer发送的消息只能到Master Broker上,不能向Slave发送。

  • Producer发送的消息方式有:onway、sync、async三种。

  • Producer在发送消息时,如果消息体长度大于默认的4k,则进行压缩后发送。

TransactionProducer

  • RocketMQ使用的分布式事务相对于两段式提交是最终一致性的(弱一致性),即A成功后B才会执行,且不能保证B何时执行。
  • Producer发送事务消息时使用sendMessageInTransaction。
  • 使用SendMessageRequestHeader消息体头中的properties中的TRAN_MSG属性标识为事务消息,以及PGROUP属性标识ProducerGroupName。
  • 事务消息处理流程:
    1. Producer发送TRAN_MSG为true、包含PGROUP属性、sysflag为100或101的消息给Broker,作为事务起始标识,此消息消息码为普通消息码。
    2. Producer接收到Broker返回的成功消息后,执行本地事务,然后发送本地事务执行结果到Broker(END_TRANSACTION)。
    3. 如果最终本地执行成功(END_TRANSACTION消息是Commit),那么Comsumer才能看到并消费事务消息。所以第一步发送的Prepare和Rollback的消息是对Consumer不可见的

Consumer

  • Consumer实例都有的Consumer Group Name,此Name在CLUSTERING方式消费消息时起作用。

  • Consumer默认可以通过Tag来进行Topic下一层的消息过滤。每个Consumer对每个Topic只能有一个订阅。

  • Consumer有两种消息消费方式:一种是BROADCASTING,另一种是CLUSTERING。默认使用CLUSTERING方式。

    1. BROADCASTING,是广播方式。 即各个Consumer都会消费消息。

      使用本地文件(userHome/.rocketmq_offsets/clientID/groupName/offsets.json或加.bak文件)存储消费偏移量(offsetStore)。

      再平衡时,直接删除本地保存的MessageQueue和对应的ProcessQueue。同时将新的MessageQueue添加到本地。且不会用到AllocateMessageQueueStrategy接口的平衡策略。

    2. CLUSTERING,类似于P2P的方式。即同一Consumer Group Name下的Consumer分摊消费消息。使用远程(Broker)存储消费偏移量(offsetStore)。

      再平衡时,先从Broker获取统一ConsumerGroup下的ConsumerID列表;然后根据MessageQueue列表、consumerGroupName、当前consumerID、所有的ConsumerID,通过AllocateMessageQueueStrategy的策略进行再平衡,然后同广播方式类似,但是会向Broker注册偏移量。

  • 对于CLUSTERING方式消费的Consumer,内部会有多一个%RETRY%GroupName的Topic订阅。

  • Consumer在再平衡时通过AllocateMessageQueueStrategy接口的实现类分配MessageQueue,默认为:AllocateMessageQueueAveragely,可选策略有:

    1. AllocateMessageQueueAveragely:分布策略。7个Broker,5个Consumer时,再平衡后结果为:
    ConsumerIndex MessageQueue
    0 [0, 1]
    1 [2, 3]
    2 [4]
    3 [5]
    4 [6]
    1. AllocateMessageQueueAveragelyByCircle:轮询分布策略。7个Broker,5个Consumer时,再平衡后结果为:
    ConsumerIndex MessageQueue
    0 [0, 5]
    1 [1, 6]
    2 [2]
    3 [3]
    4 [4]
    1. AllocateMessageQueueByConfig:根据此策略中的配置,直接返回配置的MessageQueue集合,无算法。

    2. AllocateMessageQueueByMachineRoom:机房策略,每个Consumer自身持有一部分consumeids,在这部分ids内部平衡。

    3. AllocateMessageQueueConsistentHash:一致性Hash策略,引入虚拟节点平衡。

  • Consumer消费消息时的监听器(消息到达Consumer后执行逻辑所处的回调类),分为两种:MessageListenerConcurrently和MessageListenerOrderly:

    1. MessageListenerConcurrently用于并发消费消息。

      启动时会启动一个周期线程池清理过期消息(通过CONSUMER_SEND_MSG_BACK将消息返回给Broker并从本地队列删除)。

    2. MessageListenerOrderly用于按顺序、单队列、单线程的消费消息。

      启动时会启动一个周期线程池定期锁定消息队列(向Broker发送LOCK_BATCH_MQ消息)。

  • 无论是使用Push方式还是Pull方式消费消息,本质上都是使用Pull的方式从Broker拉取消息,然后本地消费。区别在于使用DefaultMQPullConsumerImpl是主动调用API的方式从Broker获取消息并消费,而DefaultMQPushConsumerImpl是通过后台线程从Broker拉取消息,然后回调监听器进行消费。

  • 使用Push方式时,Consumer拉取消息是从RebalanceService的再平衡开始触发(RebalancePushImpl.dispatchPullRequest),通过向Broker发送(PULL_MESSAGE)拉取消息,并回调消息返回值进行消费。

Common

公共部分指Producer、Consumer启动都会启动的服务(MQClientInstance.start()方法中),但是对于Producer或Consumer可能无意义:

  • 获取NameServer地址,从环境变量或web服务。
  • 启动NettyRemotingClient服务,只有NettyRemotingServer才有registerDefaultProcessor,NettyRemotingClient不存在registerDefaultProcessor。
  • 启动周期执行任务,包括获取NameServer信息、从NameServer获取Topic信息、从topicRouteTable清空无效Broker、向各个Broker发送心跳、将消费偏移量持久化(本地或Broker)、调整线程池(目前没有实现)
  • 启动PullMessageService,通过PULL_MESSAGE从Broker拉取消息消息。
  • 启动RebalanceService,CLUSTERING方式消费消息时通过AllocateMessageQueueStrategy接口的策略再平衡,所谓的再平衡就是重新构建本地订阅的Broker数量、地址。

猜你喜欢

转载自blog.csdn.net/woshismyawei/article/details/79916677