RocketMQ
は、Alibaba が Java で開発し、Apache に追加された分散メッセージミドルウェアで、高性能、低遅延、高信頼性を備えています。
1. RocketMQ のインストール プロセスには Baidu を使用してください。この記事には含まれません
2. 個人的には、RocketMQ には、RabbitMQ に比べて次のような明らかな利点があると思います: RocketMQ は、トランザクション、メッセージ フィルタリング、およびメッセージ クエリをサポートしています。非常に多くの Double 11 の後)、 RabbitMQ のパフォーマンスは大幅に低下しており、RocketMQ には視覚的な中国の管理背景があり、非常にフレンドリーですが、RabbitMQ のアクティビティははるかに高く、RocketMQ に関する関連情報は比較的少なくなっています。
更新: ここでは、参考までに、docker を使用して rocketmq をインストールする際のメモを共有します。
リンク: https://pan.baidu.com/s/1GC_d1UV7RAO0kHlGVoLYNg romq
ステップ 1: Maven の依存関係と構成を導入する
次の依存関係を pom.xml に追加します (ここで使用されている 2.0.4 バージョンはそれほど古いものではなく、完全に十分です。新しい 2.x バージョンでは、トランザクション メッセージのコードが少し変更されています)
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-spring-boot-starter</artifactId>
<version>2.0.4</version>
</dependency>
<!-- 还有其它需要的jar包自由引入(注:fastjson不要使用低于1.2.60版本,会有安全漏洞) -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.62</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
application.yml に次の設定を追加します。
rocketmq:
name-server: 192.168.1.224:9876 # 访问地址
producer:
group: Pro_Group # 必须指定group
send-message-timeout: 3000 # 消息发送超时时长,默认3s
retry-times-when-send-failed: 3 # 同步发送消息失败重试次数,默认2
retry-times-when-send-async-failed: 3 # 异步发送消息失败重试次数,默认2
ステップ 2: プロデューサーを書く
次のように、新しい MQProducerService クラスを作成します (手動で入力し、rocketMQTemplate の使用法に慣れておくことをお勧めします)。
@Slf4j
@Component
public class MQProducerService {
@Value("${rocketmq.producer.send-message-timeout}")
private Integer messageTimeOut;
// 建议正常规模项目统一用一个TOPIC
private static final String topic = "RLT_TEST_TOPIC";
// 直接注入使用,用于发送消息到broker服务器
@Autowired
private RocketMQTemplate rocketMQTemplate;
/**
* 普通发送(这里的参数对象User可以随意定义,可以发送个对象,也可以是字符串等)
*/
public void send(User user) {
rocketMQTemplate.convertAndSend(topic + ":tag1", user);
// rocketMQTemplate.send(topic + ":tag1", MessageBuilder.withPayload(user).build()); // 等价于上面一行
}
/**
* 发送同步消息(阻塞当前线程,等待broker响应发送结果,这样不太容易丢失消息)
* (msgBody也可以是对象,sendResult为返回的发送结果)
*/
public SendResult sendMsg(String msgBody) {
SendResult sendResult = rocketMQTemplate.syncSend(topic, MessageBuilder.withPayload(msgBody).build());
log.info("【sendMsg】sendResult={}", JSON.toJSONString(sendResult));
return sendResult;
}
/**
* 发送异步消息(通过线程池执行发送到broker的消息任务,执行完后回调:在SendCallback中可处理相关成功失败时的逻辑)
* (适合对响应时间敏感的业务场景)
*/
public void sendAsyncMsg(String msgBody) {
rocketMQTemplate.asyncSend(topic, MessageBuilder.withPayload(msgBody).build(), new SendCallback() {
@Override
public void onSuccess(SendResult sendResult) {
// 处理消息发送成功逻辑
}
@Override
public void onException(Throwable throwable) {
// 处理消息发送异常逻辑
}
});
}
/**
* 发送延时消息(上面的发送同步消息,delayLevel的值就为0,因为不延时)
* 在start版本中 延时消息一共分为18个等级分别为:1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h
*/
public void sendDelayMsg(String msgBody, int delayLevel) {
rocketMQTemplate.syncSend(topic, MessageBuilder.withPayload(msgBody).build(), messageTimeOut, delayLevel);
}
/**
* 发送单向消息(只负责发送消息,不等待应答,不关心发送结果,如日志)
*/
public void sendOneWayMsg(String msgBody) {
rocketMQTemplate.sendOneWay(topic, MessageBuilder.withPayload(msgBody).build());
}
/**
* 发送带tag的消息,直接在topic后面加上":tag"
*/
public SendResult sendTagMsg(String msgBody) {
return rocketMQTemplate.syncSend(topic + ":tag2", MessageBuilder.withPayload(msgBody).build());
}
}
最初のメソッドと最後のメソッドのパラメータ トピックが他とは異なります。実際、これは rocketmq と
springboot の統合後にタグを設定する方法です (タグ: に使用されていました) 。フィルタリングを区別する (同じトピックの下にある異なるビジネス タイプのメッセージは非常に実用的です)
プロジェクト内でメッセージを mq に書き込む場合、消費時にビジネスに応じてフィルタリングするために各メッセージにタグを付けるのが最善です
さらに、遅延メッセージのパラメーターの理解は次のとおりです。合計 18 レベル、値は上にマークされており、下付き文字は 1 から始まります。たとえば、「遅延 1 でメッセージを送信したい」分の場合、パラメーターの値は 5 になります。
rocketmq-spring-boot-starter でタグを設定する方法: トピックの後に「:tagName」を追加します
ソースコードは「:」で区切られており、前がトピック、後ろがタグとなっており、スクリーンショットは以下の通りです
。メッセージ送信時にヘッダーに設定されます。
MessageBuilder.withPayload(msgBody).setHeader(RocketMQHeaders.KEYS, "key1")
ステップ 3: コンシューマを作成する
新しい MQConsumerService クラスを作成します (この場合、上記のプロデューサーの最初と最後のタグ付けされたメッセージを消費します)
@Slf4j
@Component
public class MQConsumerService {
// topic需要和生产者的topic一致,consumerGroup属性是必须指定的,内容可以随意
// selectorExpression的意思指的就是tag,默认为“*”,不设置的话会监听所有消息
@Service
@RocketMQMessageListener(topic = "RLT_TEST_TOPIC", selectorExpression = "tag1", consumerGroup = "Con_Group_One")
public class ConsumerSend implements RocketMQListener<User> {
// 监听到消息就会执行此方法
@Override
public void onMessage(User user) {
log.info("监听到消息:user={}", JSON.toJSONString(user));
}
}
// 注意:这个ConsumerSend2和上面ConsumerSend在没有添加tag做区分时,不能共存,
// 不然生产者发送一条消息,这两个都会去消费,如果类型不同会有一个报错,所以实际运用中最好加上tag,写这只是让你看知道就行
@Service
@RocketMQMessageListener(topic = "RLT_TEST_TOPIC", consumerGroup = "Con_Group_Two")
public class ConsumerSend2 implements RocketMQListener<String> {
@Override
public void onMessage(String str) {
log.info("监听到消息:str={}", str);
}
}
// MessageExt:是一个消息接收通配符,不管发送的是String还是对象,都可接收,当然也可以像上面明确指定类型(我建议还是指定类型较方便)
@Service
@RocketMQMessageListener(topic = "RLT_TEST_TOPIC", selectorExpression = "tag2", consumerGroup = "Con_Group_Three")
public class Consumer implements RocketMQListener<MessageExt> {
@Override
public void onMessage(MessageExt messageExt) {
byte[] body = messageExt.getBody();
String msg = new String(body);
log.info("监听到消息:msg={}", msg);
}
}
}
コンシューマは、ここでの正しいパラメータに注意を払う必要があります。便宜上、クラスに記述します。ここでは、
コンシューマは、プロデューサによって送信されたメッセージを直接監視します。メッセージがプロデューサによって送信されると、それに応じて消費されます。また、アノテーションを追加でき
ます @RocketMQMessageListener クリックすると、その属性パラメータが表示されます。これは非常によく知られています。
さらに、実際の運用では、コンシューマ コードでの非ビジネス ロジック エラー (コンシューマがコンシューマ中に型変換例外を報告するなど) を避ける必要があります。区別するにはTAGを使用することをお勧めします
ステップ 4: テスト
ここでコントローラーを構築するだけです
@RestController
@RequestMapping("/rocketmq")
public class RocketMQController {
@Autowired
private MQProducerService mqProducerService;
@GetMapping("/send")
public void send() {
User user = User.getUser();
mqProducerService.send(user);
}
@GetMapping("/sendTag")
public Result<SendResult> sendTag() {
SendResult sendResult = mqProducerService.sendTagMsg("带有tag的字符消息");
return Result.success(sendResult);
}
}
郵便配達員による通話テスト:
(1) http://localhost:8080/rocketmq/send
(2) http://localhost:8080/rocketmq/sendTag
メッセージを消費するときにタグを指定しないこともできます。これにより、すべてのメッセージが監視され、消費されます。
冒頭で述べたように、rocketmq には視覚的な背景があり、そこでメッセージと消費ステータスを確認することもできます。
要約:
- 実際の使用では、一部の構成は上記のようにコードに記述するのではなく、構成ファイルまたは統合構成に記述する必要があります。
- メッセージ送信の成否はsendResultによって判断できます メッセージ消費が成功したか否かは実際にソースコード内で処理されています 例外がない限り消費は成功です 問題があればビジネスコードのロジックについて話しましょう
- 実際の運用では、繰り返し消費の問題にも注意する必要がありますが、ここではデータベースに重複排除テーブルを追加し、テーブル内のキーなどのフィールドに一意のインデックスを追加し、事前にウェアハウスに格納する方法を提供します。ロジック、ストレージに障害が発生した場合、メッセージは消費されており、ダウンできないことを意味します
- 実は、rocketmq には、他の mq ではサポートされていないトランザクションという非常に重要な機能があり、トランザクションを使用してお金関連のビジネスや分散トランザクションなど、さまざまな処理を行うことができますが、トランザクションの実装プロセスはさらに面倒です。
- 上記は RocketMQ と Springboot の統合であり、比較的簡単に使用できます。
- 分散トランザクションが更新されました: Springboot の RocketMQ を使用した分散トランザクションの解決