聊聊 消息中心的设计与实现

设计消息中心的主要原因

1.实现系统解耦

各个子系统或者组件通过消息中心进行通信,而不是直接调用,这可以实现系统解耦,降低各组件之间的依赖性。这有利于系统的稳定性、扩展性和维护性。

2.异步处理

消息中心实现的是异步通信机制,这可以帮助我们实现异步处理任务或者流程。生产者投递消息后不需要等待消费者的响应,继续处理其他任务。这有助于提高处理效率。

3.流量削峰

利用消息队列,可以实现消息缓冲,在高峰期将消息暂存于队列中,待处理资源释放后再进行消费。这有助于应对高并发场景,防止系统崩溃。

4.自动重试

消费发生异常时,消息并不会丢失,会重新回到队列中。消费者可以定期重新消费,实现自动重试机制。这有助于提高系统的稳定性。

5.顺序保证

某些场景下,消息消费需要保证顺序。消息中心利用队列的先入先出特性,可以实现消息有序消费。

6.消息投递保障

利用消息队列,生产环境的重要消息可以实现持久化存储。这样即使消费者在处理消息的过程中发生故障,也不会导致消息丢失。消费者重启后可以重新消费消息,从而确保消息不会遗漏。

7.流量控制

通过消息中心,可以实现对消息生产和消费速率的管控。当下游处理能力上不去时,可以通过速率限制避免消息堆积过快;当处理能力释放时,也可以accordion提高速率。这有助于避免系统崩溃。

总之,设计消息中心主要是为了实现系统解耦,支持异步处理,削峰限流,自动重试,顺序保障,消息可靠投递以及流量控制等目的。它是构建一个稳定可靠、灵活可扩展的系统架构的核心组件之一。
但引入消息中心也会增加系统的复杂性,需要对消息传输过程进行严密管理,避免消息丢失或重复消费等情况出现。所以,是否需要消息中心,还需要结合具体的系统架构和业务场景进行权衡。

其具体典型的设计与实现如下(这里以RocketMQ为例,给出一个简单的消息中心设计与实现):

1.消息格式定义

首先需要定义消息的通用格式和协议,一般包含消息ID、消息类型、消息体、时间戳等字段。格式常用JSON,XML或自定义二进制格式。

扫描二维码关注公众号,回复: 15222734 查看本文章

以JSON格式定义消息:

{
    "id": "msg_001",
    "type": "ORDER_CREATE", 
    "content": {
        "orderNo": "123456789",
        "productCode": "P123456789"
    },
    "timestamp": 1577836800
}

2.消息发送

提供消息发送与接收的API,供系统内各业务模块调用。发送API一般需要接收消息体、消息类型、接收者列表等参数

使用RocketMQ提供的发送API:

Message msg = new Message("TOPIC1", "ORDER_CREATE", "{'orderNo':'12345'}".getBytes(RemotingHelper.DEFAULT_CHARSET));
SendResult sendResult = rocketMQProducer.send(msg);

3.消息接收API

接收API一般返回一个消息队列或流供业务模块消费。

使用RocketMQ提供的接收API:

// 定义消费者
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("CID1");
// 设置消费者订阅的Topic和Tag    
consumer.setNamesrvAddr("127.0.0.1:9876");
consumer.subscribe("TOPIC1", "*");
// 注册消费者监听并设置消费逻辑
consumer.registerMessageListener(new MessageListenerConcurrently() {
    @Override
    public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs, ConsumeConcurrentlyContext context) {
        for (MessageExt msg : msgs) {
            // 消费逻辑
        }
        return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
    }
});
// 启动消费者
consumer.start(); 

4.消息队列

实现消息的异步传输和解耦合合,一般用到消息队列中间件,如Kafka、RabbitMQ、RocketMQ等。这些消息队列能实现消息的管道化和缓冲。

RocketMQ本身就是一款消息队列产品,会隐式使用其消息队列功能。

5.消息分发

当生产者产生消息时,需要实现分发机制将消息投递到指定接收者或接收组。这需要在消息和接收者之间建立关联关系,一般通过配置的形式完成。

通过RocketMQ的Topic实现消息分发,生产者定义发送到哪个Topic,消费者订阅该Topic即可获取消息。

6.消息并发控制

考虑到高并发场景下消息的产生速度可能远远超过消费速度,需要实现機制避免消息堆积过多而导致系统崩溃。常用的方式是设置消息队列大小限制和拒绝策略。

RocketMQ支持设置各个主题的队列数和消息大小限制,可以通过这两者避免消息堆积过多。

7.消息可靠性

为保证消息不丢失,通常需要消息中心实现消息持久化、消息回溯、消息补发等机制。持久化一般用数据库完成;回溯和补发利用消息队列中的消息历史轨迹实现。

RocketMQ支持持久化,同时提供延迟队列和死信队列功能,可以保证消息不丢失。

8.系统监控

消息中心作为一个关键的基础组件,需要提供丰富的监控指标和监控接口,包括消息产生速率、消息堆积量、消息消费速率、连接数、时延等关键指标的监测。

RocketMQ提供丰富的Dashboard和Metrics用于监控消息产生与消费的速率、时延、堆积等指标。

9.权限管理

对消息中心的访问需要进行权限管理,不同的系统模块和用户应具有不同的权限,如某些模块只能发送消息而不能消费消息。权限管理一般通过登录认证结合配置的方式完成。

RocketMQ提供基于用户、权限、角色的访问控制功能,可以控制用户对Topic的读写权限。

以上就是一个简单的RocketMQ消息中心设计与实现的示例。利用RocketMQ提供的完备服务,我们可以快速构建一套消息中心方案,实现系统内各模块的异步解耦和通信。RocketMQ只是众多消息队列产品的一种选择,其它如Kafka、RabbitMQ也同样具备实现消息中心的全部功能。可以根据业务场景具体选择和设计。

写在最后

如果大家对相关文章感兴趣,可以关注公众号"架构殿堂",会持续更新AIGC,java基础面试题, netty, spring boot,spring cloud等系列文章,一系列干货随时送达!

猜你喜欢

转载自blog.csdn.net/jinxinxin1314/article/details/130987911