RocketMQ的集群、SprinBoot整合RocketMQ

1 RocketMQ的集群

1.1 集群模式

在RocketMQ中,集群的部署模式是比较多的,有以下几种:
单个Master
这种方式风险较大,一旦Broker重启或者宕机时,会导致整个服务不可用,不建议线上环境使用。
多Master模式
一个集群无Slave,全是Master,例如2个Master或者3个Master.
单台机器宕机期间,这台机器上未被消费的消息在机器恢复之前不可订阅,消息实时性会受到影响。
多Master多Slave模式,异步复制
每个Master配置一个Slave,有多对Master-Slave,HA采用异步复制方式,主备有短暂消息延迟,毫秒级。
优点:即使磁盘损坏,消息丢失的非常少,且消息实时性不会受影响,因为Master宕机后,消费者仍然可以从Slave消费,此过程对应用透明,不需要人工干预。性能同多Master模式几乎一样。
缺点:Master宕机,磁盘损坏情况,会丢失少量消息。
多Master多Slave模式,同步双写
每个Master配置一个Slave,有多对Master-Slave,HA采用同步双写方式,主备都写成功,向应用返回成功。
优点:数据与服务都无单点,Master宕机情况下,消息无延迟,服务可用性与数据可用性都非常高。
缺点:性能比异步复制模式略低,大约低10%左右。

1.2 搭建2m2s集群

1.创建2个master nameserver1的代码如下:

docker create -p 9876:9876 --name rmqserver01 \
-e "JAVA_OPT_EXT=-server -Xms128m -Xmx128m -Xmn128m" \
-e "JAVA_OPTS=-Duser.home=/opt" \
-v /mydata/rmq/rmqserver01/logs:/opt/logs \
-v /mydata/rmq/rmqserver01/store:/opt/store \
foxiswho/rocketmq:server

如图所示:在这里插入图片描述
2.创建2个master nameserver2的代码如下:

docker create -p 9877:9876 --name rmqserver02 \
-e "JAVA_OPT_EXT=-server -Xms128m -Xmx128m -Xmn128m" \
-e "JAVA_OPTS=-Duser.home=/opt" \
-v /mydata/rmq/rmqserver02/logs:/opt/logs \
-v /mydata/rmq/rmqserver02/store:/opt/store \
foxiswho/rocketmq:server

如图所示:在这里插入图片描述
3.创建第1个master broker的master broker01的代码如下:

docker create --net host --name rmqbroker01 \
-e "JAVA_OPTS=-Duser.home=/opt" \
-e "JAVA_OPT_EXT=-server -Xms128m -Xmx128m -Xmn128m" \
-v /mydata/rmq/rmqbroker01/conf/broker.conf:/etc/rocketmq/broker.conf \
-v /mydata/rmq/rmqbroker01/logs:/opt/logs \
-v /mydata/rmq/rmqbroker01/store:/opt/store \
foxiswho/rocketmq:broker

如图所示:在这里插入图片描述
4.配置的代码如下:

mkdir -p /mydata/rmq/rmqbroker01/conf
touch /mydata/rmq/rmqbroker01/conf/broker.conf
vim /mydata/rmq/rmqbroker01/conf/broker.conf
##配置内容如下:
namesrvAddr=192.168.56.10:9876;192.168.56.10:9877
brokerClusterName=Cluster
brokerName=broker01
brokerId=0
deleteWhen=04
fileReservedTime=48
brokerRole=SYNC_MASTER
flushDiskType=ASYNC_FLUSH
brokerIP1=192.168.56.10
brokerIp2=192.168.56.10
listenPort=10911

如图所示:在这里插入图片描述
5.创建第2个master broker master broker02的代码如下:

docker create --net host --name rmqbroker02 \
-e "JAVA_OPTS=-Duser.home=/opt" \
-e "JAVA_OPT_EXT=-server -Xms128m -Xmx128m -Xmn128m" \
-v /mydata/rmq/rmqbroker02/conf/broker.conf:/etc/rocketmq/broker.conf \
-v /mydata/rmq/rmqbroker02/logs:/opt/logs \
-v /mydata/rmq/rmqbroker02/store:/opt/store \
foxiswho/rocketmq:broker

如图所示:在这里插入图片描述
6.配置的代码如下:

mkdir -p /mydata/rmq/rmqbroker02/conf
touch /mydata/rmq/rmqbroker02/conf/broker.conf
vim /mydata/rmq/rmqbroker02/conf/broker.conf
##配置内容如下:
namesrvAddr=192.168.56.10:9876;192.168.56.10:9877
brokerClusterName=Cluster
brokerName=broker02
brokerId=0
deleteWhen=04
fileReservedTime=48
brokerRole=SYNC_MASTER
flushDiskType=ASYNC_FLUSH
brokerIP1=192.168.56.10
brokerIp2=192.168.56.10
listenPort=10811

如图所示:在这里插入图片描述
7.创建第1个slave broke、slave broker03的代码如下:

docker create --net host --name rmqbroker03 \
-e "JAVA_OPTS=-Duser.home=/opt" \
-e "JAVA_OPT_EXT=-server -Xms128m -Xmx128m -Xmn128m" \
-v /mydata/rmq/rmqbroker03/conf/broker.conf:/etc/rocketmq/broker.conf \
-v /mydata/rmq/rmqbroker03/logs:/opt/logs \
-v /mydata/rmq/rmqbroker03/store:/opt/store \
foxiswho/rocketmq:broker

如图所示:在这里插入图片描述
8.配置的代码如下:

mkdir -p /mydata/rmq/rmqbroker03/conf
touch /mydata/rmq/rmqbroker03/conf/broker.conf
vim /mydata/rmq/rmqbroker03/conf/broker.conf
##配置内容如下:
namesrvAddr=192.168.56.10:9876;192.168.56.10:9877
brokerClusterName=Cluster
brokerName=broker01
brokerId=1
deleteWhen=04
fileReservedTime=48
brokerRole=SLAVE
flushDiskType=ASYNC_FLUSH
brokerIP1=192.168.56.10
brokerIp2=192.168.56.10
listenPort=10711

如图所示:在这里插入图片描述
9.创建第2个slave broker ,slave broker01的代码如下:

docker create --net host --name rmqbroker04 \
-e "JAVA_OPTS=-Duser.home=/opt" \
-e "JAVA_OPT_EXT=-server -Xms128m -Xmx128m -Xmn128m" \
-v /mydata/rmq/rmqbroker04/conf/broker.conf:/etc/rocketmq/broker.conf \
-v /mydata/rmq/rmqbroker04/logs:/opt/logs \
-v /mydata/rmq/rmqbroker04/store:/opt/store \
foxiswho/rocketmq:broker

如图所示:在这里插入图片描述
10.配置的代码如下:

mkdir -p /mydata/rmq/rmqbroker04/conf
touch /mydata/rmq/rmqbroker04/conf/broker.conf
vim /mydata/rmq/rmqbroker04/conf/broker.conf
##配置内容如下:
namesrvAddr=192.168.56.10:9876;192.168.56.10:9877
brokerClusterName=Cluster
brokerName=broker02
brokerId=1
deleteWhen=04
fileReservedTime=48
brokerRole=SLAVE
flushDiskType=ASYNC_FLUSH
brokerIP1=192.168.56.10
brokerIp2=192.168.56.10
listenPort=10611

如图所示:在这里插入图片描述
11.启动容器的代码如下:

docker start rmqserver01 rmqserver02 
docker start rmqbroker01 rmqbroker02 rmqbroker03 rmqbroker04

如图所示:在这里插入图片描述
12.设置启动方式的代码如下:

docker update rmqserver01 rmqserver02 --restart=always
docker update rmqbroker01 rmqbroker02 rmqbroker03 rmqbroker04 --restart=always

如图所示:在这里插入图片描述

2 SprinBoot整合RocketMQ

1.引入依赖的代码如下:

<?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 http://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.1.0.RELEASE</version>
    </parent>
    <groupId>com.txw.rocketmq</groupId>
    <artifactId>rocketmq-demo</artifactId>
    <version>1.0-SNAPSHOT</version>
    <dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
        <dependency>
            <groupId>org.apache.rocketmq</groupId>
            <artifactId>rocketmq-spring-boot-starter</artifactId>
            <version>2.0.3</version>
        </dependency>
        <dependency>
            <groupId>org.apache.rocketmq</groupId>
            <artifactId>rocketmq-client</artifactId>
            <version>4.9.0</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <!-- java编译插件 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.2</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

如图所示:在这里插入图片描述
2.编写application.properties配置文件的代码如下:

##应用名
spring.application.name=rocketmq-demo
##rocketmq配置
rocketmq.name-server=192.168.56.10:9876
rocketmq.producer.group=my-group

如图所示:在这里插入图片描述
3.编写SpringProducer的代码如下:

package com.txw.rocketmq.spring;

import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
 * 生产者发送消息 {@link SpringProducer}
 * @author Adair
 * @date 2022/5/25 下午 2:41
 * @email [email protected]
 */
@SuppressWarnings("all")  // 注解警告信息
@Component
public class SpringProducer {
    
    

    // 注入rocketMQ的模板
    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    /**
     * 发送消息
     * @param topic
     * @param msg
     */
    public void sendMsg(String topic, String msg) {
    
    
        this.rocketMQTemplate.convertAndSend(topic, msg);
    }
}

如图所示:在这里插入图片描述
4.编写SpringConsumer的代码如下:

package com.txw.rocketmq.spring;

import org.apache.rocketmq.spring.annotation.ConsumeMode;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.springframework.stereotype.Component;
/**
 * 消费消息 {@link SpringConsumer}
 * @author Adair
 * @date 2022/5/25 下午 2:45
 * @email [email protected]
 */
@Component
@RocketMQMessageListener(
        topic = "my-topic",
        consumerGroup = "haoke-consumer",
        selectorExpression = "*",
        consumeMode = ConsumeMode.CONCURRENTLY)
@SuppressWarnings("all")  // 注解警告信息
public class SpringConsumer implements RocketMQListener<String> {
    
    

    @Override
    public void onMessage(String msg) {
    
    
        System.out.println("接收到消息 -> " + msg);
    }
}

如图所示:在这里插入图片描述
5.编写MyApplication的代码如下:

package com.txw.rocketmq.spring;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
 * 启动类 {@link MyApplication}
 * @author Adair
 * @date 2022/5/25 下午 2:48
 * @email [email protected]
 */
@SuppressWarnings("all")  // 注解警告信息
@SpringBootApplication
public class MyApplication {
    
    

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

如图所示:在这里插入图片描述
6.编写TestSpringRocketMQ的代码如下:

package com.txw.rocketmq.spring;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
/**
 * 测试类 {@link TestSpringRocketMQ}
 * @author Adair
 * @date 2022/5/25 下午 2:51
 * @email [email protected]
 */
@RunWith(SpringRunner.class)
@SpringBootTest
@SuppressWarnings("all")  // 注解警告信息
public class TestSpringRocketMQ {
    
    

    @Autowired
    private SpringProducer springProducer;

    @Test
    public void testSendMsg(){
    
    
        this.springProducer.sendMsg("my-topic", "第一个Spring消息");
    }
}

如图所示:在这里插入图片描述
测试,先启动springboot,再运行测试用例,即可看到消费者接收到生产者发送的消息。

2.1 事务消息

1.编写TransactionListenerImpl的代码如下:

package com.txw.rocketmq.spring.transaction;

import org.apache.rocketmq.spring.annotation.RocketMQTransactionListener;
import org.apache.rocketmq.spring.core.RocketMQLocalTransactionListener;
import org.apache.rocketmq.spring.core.RocketMQLocalTransactionState;
import org.apache.rocketmq.spring.support.RocketMQHeaders;
import org.springframework.messaging.Message;
import java.util.HashMap;
import java.util.Map;
/**
 * 事务消息监听 {@link TransactionListenerImpl}
 * @author Adair
 * @date 2022/5/25 下午 5:08
 * @email [email protected]
 */
@SuppressWarnings("all")  // 注解警告信息
@RocketMQTransactionListener(txProducerGroup = "myTransactionGroup")
public class TransactionListenerImpl implements RocketMQLocalTransactionListener {
    
    

    private static Map<String, RocketMQLocalTransactionState> STATE_MAP = new HashMap<>();

    /**
     * 执行业务逻辑
     * @param message
     * @param o
     * @return
     */
    @Override
    public RocketMQLocalTransactionState executeLocalTransaction(Message message, Object o) {
    
    
        String transId = (String)message.getHeaders().get(RocketMQHeaders.TRANSACTION_ID);
        try {
    
    
            System.out.println("执行操作1");
            Thread.sleep(500);
            System.out.println("执行操作2");
            Thread.sleep(800);
            STATE_MAP.put(transId, RocketMQLocalTransactionState.COMMIT);
            return RocketMQLocalTransactionState.UNKNOWN;
        } catch (Exception e) {
    
    
            e.printStackTrace();
        }
        STATE_MAP.put(transId, RocketMQLocalTransactionState.ROLLBACK);
        return RocketMQLocalTransactionState.ROLLBACK;

    }

    /**
     * 回查
     * @param message
     * @return
     */
    @Override
    public RocketMQLocalTransactionState checkLocalTransaction(Message message) {
    
    
        String transId = (String)message.getHeaders().get(RocketMQHeaders.TRANSACTION_ID);
        System.out.println("回查消息 -> transId = " + transId + ", state = " + STATE_MAP.get(transId));
        return STATE_MAP.get(transId);
    }
}

如图所示:在这里插入图片描述
2.编写SpringTransactionProducer的代码如下:

package com.txw.rocketmq.spring.transaction;

import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Component;
/**
 * 生产者 {@link SpringTransactionProducer}
 * @author Adair
 * @date 2022/5/25 下午 5:14
 * @email [email protected]
 */
@Component
@SuppressWarnings("all")  // 注解警告信息
public class SpringTransactionProducer {
    
    

    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    /**
     * 发送消息
     * @param topic
     * @param msg
     */
    public void sendMsg(String topic, String msg) {
    
    
        Message message = MessageBuilder.withPayload(msg).build();
        // myTransactionGroup要和@RocketMQTransactionListener(txProducerGroup = "myTransactionGroup")定义的一致
        this.rocketMQTemplate.sendMessageInTransaction("myTransactionGroup",
                topic,
                message,
                null);
        System.out.println("发送消息成功");
    }
}

如图所示:在这里插入图片描述
3.编写TestSpringRocketMQ的代码如下:

package com.txw.rocketmq.spring;

import com.txw.rocketmq.spring.transaction.SpringTransactionProducer;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
/**
 * 测试类 {@link TestSpringRocketMQ}
 * @author Adair
 * @date 2022/5/25 下午 2:51
 * @email [email protected]
 */
@RunWith(SpringRunner.class)
@SpringBootTest
@SuppressWarnings("all")  // 注解警告信息
public class TestSpringRocketMQ {
    
    

    @Autowired
    private SpringProducer springProducer;

    @Autowired
    private SpringTransactionProducer springTransactionProducer;

    @Test
    public void testSendMsg(){
    
    
        this.springProducer.sendMsg("my-topic", "第一个Spring消息");
    }
    @Test
    public void testSendMsg2(){
    
    
        this.springTransactionProducer.sendMsg("my-topic", "第3个Spring消息");
    }
}

如图所示:在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_40055163/article/details/124964199