rocketmq

消息生产者

package com.rocketmqpro.producer;

import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.client.producer.SendCallback;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.common.message.MessageQueue;

import java.util.List;

public class RMQPro {
    public static void main(String[] args) {
        final boolean[] close = {false};
        DefaultMQProducer producer = new DefaultMQProducer("Producer");
        // 必须要设置nameserver地址
        producer.setNamesrvAddr("127.0.0.1:9876");
        try {
            producer.setClientIP("**");
            //设置实例名称
            producer.setInstanceName("rocketMQ");
            //设置重试的次数
            producer.setRetryTimesWhenSendFailed(3);
            //开启生产者
            producer.start();
            //创建一条消息
            Message msg = new Message("PushTopic", "PushTopic", "PushTopic_01", "内容一".getBytes());
            //发送,并触发回调函数
            producer.send(msg, new SendCallback() {
                @Override
                //成功的回调函数
                public void onSuccess(SendResult sendResult) {
                    System.out.println(sendResult.getSendStatus());
                    State.sta = true;
                }

                @Override
                //出现异常的回调函数
                public void onException(Throwable e) {
                    System.out.println("SEND_EXCEPTION:" + e.getMessage());
                    State.sta = true;
                }
            });
            //获取某个主题的消息队列
            //List<MessageQueue> messageQueues = producer.fetchPublishMessageQueues("PushTopic");
            //System.out.println("消息队列数量:" + messageQueues.size());
            //for (int i = 0; i < messageQueues.size(); i++) {
            //    System.out.println(messageQueues.get(i).toString());
            //}
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            while (!State.sta) {
            }
            producer.shutdown();
            System.out.println("producer shutdown......");
        }
    }
}
package com.rocketmqpro.producer;

public class State {
    public volatile static boolean sta=false;
}

消息消费者(用的springboot)

server:
  port: 8080
  server-header:
rocketmq:
  name-server: 127.0.0.1:9876 #私有云消费mq地址
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.10</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <groupId>com.example</groupId>
    <artifactId>rocketmqpro</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>rocketmqpro</name>

    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- RocketMQ -->
        <dependency>
            <groupId>org.apache.rocketmq</groupId>
            <artifactId>rocketmq-spring-boot-starter</artifactId>
            <version>2.1.0</version>
        </dependency>

        <dependency>
            <groupId>org.apache.rocketmq</groupId>
            <artifactId>rocketmq-client</artifactId>
            <version>4.6.0</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>
package com.rocketmqpro;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class RocketmqproApplication {

    public static void main(String[] args) {
        SpringApplication.run(RocketmqproApplication.class, args);
    }

}
package com.rocketmqpro.consumer;

import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
import org.apache.rocketmq.common.consumer.ConsumeFromWhere;
import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.common.protocol.heartbeat.MessageModel;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.apache.rocketmq.spring.core.RocketMQPushConsumerLifecycleListener;
import org.springframework.stereotype.Component;


@Component
@RocketMQMessageListener(topic = "PushTopic", consumerGroup = "jhc")
public class RMQCon implements RocketMQListener<MessageExt>, RocketMQPushConsumerLifecycleListener {


    @Override
    public void onMessage(MessageExt message) {
        System.out.println(new String(message.getBody()));
    }

    @Override
    public void prepareStart(DefaultMQPushConsumer consumer) {

        //从消息队列头部开始消费
        consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET);
        //设置广播消费模式
        consumer.setMessageModel(MessageModel.BROADCASTING);

    }
}
广播消费
一条消息被多个 Consumer 消费,即使这些 Consumer 属于同一个 Consumer Group ,消息也会
Consumer Group 中的每个 Consumer 都消费一次,广播消费中的 Consumer Group 概念可以认为在消息划分方面无意义。
集群消费
一个 Consumer Group 中的 Consumer 实例平均分摊消费消息。例如某个 Topic 9 条消息,其
中一个 Consumer Group 3 个实例 ( 可能是 3 个进程,或者 3 台机器 ) ,那举每个实例只消费其中的 3条消息。
标签(Tag)
为消息设置的标志,用于同一主题下区分不同类型的消息。来自同一业务单元的消息,可以根据不
同业务目的在同一主题下设置不同标签。标签能够有效地保持代码的清晰度和连贯性,并优化
RocketMQ 提供的查询系统。消费者可以根据 Tag 实现对不同子主题的不同消费逻辑,实现更好的扩展性。
生产者发送消息发生返回状态(SendResult#SendStatus)有如下四种:
FLUSH_DISK_TIMEOUT
FLUSH_SLAVE_TIMEOUT
SLAVE_NOT_AVAILABLE
SEND_OK
不同状态在不同的刷盘策略和同步策略的配置下含义是不同的:
1. FLUSH_DISK_TIMEOUT: 表示没有在规定时间内完成刷盘(需要 Broker 的刷盘策略被设置成
SYNC_FLUSH 才会报这个错误)。
2. FLUSH_SLAVE_TIMEOUT: 表示在主备方式下,并且 Broker 被设置成 SYNC_MASTER 方式,
没有在设定时间内完成主从同步。
3. SLAVE_NOT_AVAILABLE 这个状态产生的场景和 FLUSH_SLAVE_TIMEOUT 类似,表示在主 备方式下,并且 Broker 被设置成 SYNC_MASTER ,但是没有找到被配置成 Slave Broker
4. SEND_OK 表示发送成功,发送成功的具体含义,比如消息是否已经被存储到磁盘?消息是
否被同步到了 Slave 上?消息在 Slave 上是否被写入磁盘?需要结合所配置的刷盘策略、主从策
略来定。这个状态还可以简单理解为,没有发生上面列出的三个问题状态就是 SEND_OK
在Linux操作系统层级进行调优,推荐使用EXT4文件系统,IO调度算法使用deadline算法。
消费上的优化
提高消费并行度
同一个 ConsumerGroup 下( Clustering 方式),可以通过 增加 Consumer 实例 的数量来提
高并行度。通过加机器,或者在已有机器中启动多个 Consumer 进程都可以增加 Consumer 实例数。 注意:总的 Consumer 数量不要超过 Topic Read Queue 数量,超过的 Consumer 实例接收
不到消息。此外,通过提高单个 Consumer 实例中的 并行处理的线程数 ,可以在同一个 Consumer 内增加 并行度来提高吞吐量(设置方法是修改 consumeThreadMin consumeThreadMax )。
 
以批量方式进行消费
某些业务场景下,多条消息同时处理的时间会大大小于逐个处理的时间总和,比如消费消息中
涉及 update 某个数据库,一次 update10 条的时间会大大小于十次 update1 条数据的时间。
可以通过批量方式消费来提高消费的吞吐量。实现方法是设置 Consumer
consumeMessageBatchMaxSize 这个参数,默认是 1 ,如果设置为 N ,在消息多的时候每次
收到的是个长度为 N 消息链表
检测延时情况,跳过非重要消息
Consumer 在消费的过程中,如果发现由于某种原因发生严重的消息堆积,短时间无法消除堆
积,这个时候可以选择丢弃不重要的消息,使 Consumer 尽快追上 Producer 的进度。
MQ消息丢失
mq消息丢失分三种。分别是在发送端丢失消息,服务端丢失消息和消费端丢失消息。
发送端丢失消息处理1、采用同步发送的方式;2、异步发送+回调通知+本地消息列表,如果当前消息多次发送失败,则通过人工介入处理
服务端消息丢失1、mq宕机,未刷盘的数据可能丢失,则将异步刷盘改为同步刷盘
消费端消息丢失1、用ack机制保证消息正常消费
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值