RocketMQ安装和使用

概念

RocketMQ安装和使用_第1张图片

下载安装

下载地址:https://www.apache.org/dyn/closer.cgi?path=rocketmq/4.9.4/rocketmq-all-4.9.4-bin-release.zip
安装:

unzip rocketmq-all-4.9.4-bin-release.zip
cd rocketmq-all-4.9.4-bin-release/

修改broker配置(默认8g, 4g内存太大了)
vim ./bin/runbroker.sh
RocketMQ安装和使用_第2张图片
vim ./bin/runserver.sh
RocketMQ安装和使用_第3张图片
vim conf/broker.conf 在随后添加下面两行

namesrvAddr=127.0.0.1:9876
brokerIP1=192.168.174.129 # 自己的IP地址

启动Name Server

nohup sh bin/mqnamesrv &
tail -f ~/logs/rocketmqlogs/namesrv.log
(关闭sh bin/mqshutdown namesrv)
RocketMQ安装和使用_第4张图片

启动Broker

nohup bin/mqbroker -n localhost:9876 -c conf/broker.conf autoCreateTopicEnable=true &
tail -f ~/logs/rocketmqlogs/broker.log
(关闭sh bin/mqshutdown broker)
RocketMQ安装和使用_第5张图片

RocketMQ控制台安装

  1. 在git上下载下面的工程 rocketmq-console-1.0.0
    https://github.com/apache/rocketmq-externals/releases
  2. 修改配置文件 rocketmq-console\src\main\resources\application.properties
    server.port=7777 #项目启动后的端口号
    rocketmq.config.namesrvAddr=192.168.88.128:9876 #nameserv的地址,注意关闭防火墙
  3. 进入控制台项目,将工程打成jar包
    mvn clean package -Dmaven.test.skip=true
  4. 启动控制台
    java -jar target/rocketmq-console-ng-1.0.0.jar
  5. 访问控制台(可以创建主题,查看消息)
    http://localhost:7777/#/message
    RocketMQ安装和使用_第6张图片

基本使用

发送同步消息

同步发送是指消息发送方发出数据后,会在收到接收方发回响应之后才发下一个数据包的通讯方
式。此种方式应用场景非常广泛,例如重要通知邮件、报名短信通知、营销短信系统等。

    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    //同步消息
    @Test
    public void testSyncSend() {
        //参数一: topic:tag
        //参数二: 消息体
        //参数三: 超时时间
        SendResult result =
                rocketMQTemplate.syncSend("test-topic-1:tag", "这是一条同步消息", 10000);
        System.out.println(result);
    }

发送异步消息

异步发送是指发送方发出数据后,不等接收方发回响应,接着发送下个数据包的通讯方式。发送
方通过回调接口接收服务器响应,并对响应结果进行处理。
异步发送一般用于链路耗时较长,对 RT 响应时间较为敏感的业务场景,例如用户视频上传后通知
启动转码服务,转码完成后通知推送转码结果等。

    //异步消息
    @Test
    public void testAsyncSend() throws InterruptedException {
        //参数一: topic:tag
        //参数二: 消息体
        //参数三: 回调
        rocketMQTemplate.asyncSend("test-topic-1", "这是一条异步消息", new SendCallback() {
            //成功响应的回调
            @Override
            public void onSuccess(SendResult result) {
                System.out.println(result);
            }

            //异常响应的回调
            @Override
            public void onException(Throwable throwable) {
                System.out.println(throwable);
            }
        });
        System.out.println("==================");
        Thread.sleep(300000000);
    }

发送单向消息

单向发送是指发送方只负责发送消息,不等待服务器回应且没有回调函数触发,即只发送请求不
等待应答。
适用于某些耗时非常短,但对可靠性要求并不高的场景,例如日志收集。

    //单向消息
    @Test
    public void testOneWay() {
        for (int i = 0; i < 10; i++) {
            rocketMQTemplate.sendOneWay("test-topic-1", "这是一条单向消息");
        }
    }

发送顺序消息

顺序消息是消息队列提供的一种严格按照顺序来发布和消费的消息类型。
就是将原来方法换为xxxOrderly, 例如:

    //单向顺序消息(其他顺序消息都是调用对应的xxxSendOrderly方法)
    @Test
    public void testOneWayOrderly() {
        for (int i = 0; i < 10; i++) {
            //第三个参数的作用是用来决定这些消息发送到哪个队列的上的(随便写,唯一即可)
            rocketMQTemplate.sendOneWayOrderly("test-topic-1", "这是一条单向消息","xx");
        }
    }

    //异步顺序消息
    @Test
    public void testAsyncSendOrderly() throws InterruptedException {
        //参数一: topic:tag
        //参数二: 消息体
        //参数三: 回调
        rocketMQTemplate.asyncSendOrderly("test-topic-1", "这是一条异步顺序消息", "yy", new SendCallback() {
            //成功响应的回调
            @Override
            public void onSuccess(SendResult result) {
                System.out.println(result);
            }

            //异常响应的回调
            @Override
            public void onException(Throwable throwable) {
                System.out.println(throwable);
            }
        });
        System.out.println("==================");
        Thread.sleep(300000000);
    }

发送事务消息

交互流程
RocketMQ安装和使用_第7张图片

@Service
public class OrderServiceImpl4 {

    @Autowired
    private OrderDao orderDao;

    @Autowired
    private TxLogDao txLogDao; // 用来记录事务日志

    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    public void createOrderBefore(Order order) {
        // 事务id
        String txId = UUID.randomUUID().toString();

        //发送半事务消息
        rocketMQTemplate.sendMessageInTransaction(
                "tx_producer_group",
                "tx_topic",
                MessageBuilder.withPayload(order).setHeader("txId", txId).build(),
                order
        );
    }
    
    @Transactional
    public void createOrder(String txId, Order order) {
        //保存订单
        orderDao.save(order);
        TxLog txLog = new TxLog();
        txLog.setTxId(txId);
        txLog.setDate(new Date());
        //记录事物日志(事务日志和保存订单是同成功,同失败的)
        txLogDao.save(txLog);
    }
}
@Service
//这里值必须跟发送消息的时候txProducerGroup参数值保持一致
@RocketMQTransactionListener(txProducerGroup = "tx_producer_group")
public class OrderServiceImpl4Listener implements RocketMQLocalTransactionListener {

    @Autowired
    private OrderServiceImpl4 orderServiceImpl4;

    @Autowired
    private TxLogDao txLogDao;

    //执行本地事物
    @Override
    public RocketMQLocalTransactionState executeLocalTransaction(Message msg, Object arg) {
        String txId = (String) msg.getHeaders().get("txId");
        try {
            //本地事物,成功就commit, 异常就rollback
            Order order = (Order) arg;
            orderServiceImpl4.createOrder(txId,order);
            return RocketMQLocalTransactionState.COMMIT;
        } catch (Exception e) {
            return RocketMQLocalTransactionState.ROLLBACK;
        }
    }

    //消息回查
    @Override
    public RocketMQLocalTransactionState checkLocalTransaction(Message msg) {
        String txId = (String) msg.getHeaders().get("txId");
        TxLog txLog = txLogDao.findById(txId).get();

        if (txLog != null){
            //本地事物(订单)成功了
            return RocketMQLocalTransactionState.COMMIT;
        }else {
            return RocketMQLocalTransactionState.ROLLBACK;
        }
    }
}

生产案例

加依赖

        <dependency>
            <groupId>org.apache.rocketmq</groupId>
            <artifactId>rocketmq-spring-boot-starter</artifactId>
            <version>2.0.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.rocketmq</groupId>
            <artifactId>rocketmq-client</artifactId>
            <version>4.4.0</version>
        </dependency>

写配置

#rocketmq
rocketmq:
  name-server: 192.168.174.129:9876   #rocketMQ服务的地址
  producer:
    group: shop-order # 生产者组

发送消息

    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    //下单--fegin
    @RequestMapping("/order/prod/{pid}")
    public Order order(@PathVariable("pid") Integer pid) {
        log.info("接收到{}号商品的下单请求,接下来调用商品微服务查询此商品信息", pid);

        //调用商品微服务,查询商品信息
        Product product = productService.findByPid(pid);

        if (product.getPid() == -100) {
            Order order = new Order();
            order.setOid(-100L);
            order.setPname("下单失败");
            return order;
        }

        log.info("查询到{}号商品的信息,内容是:{}", pid, JSON.toJSONString(product));

        //下单(创建订单)
        Order order = new Order();
        order.setUid(1);
        order.setUsername("测试用户");
        order.setPid(pid);
        order.setPname(product.getPname());
        order.setPprice(product.getPprice());
        order.setNumber(1);

        orderService.createOrder(order);

        log.info("创建订单成功,订单信息为{}", JSON.toJSONString(order));

        //向mq中投递一个下单成功的消息
        //参数一: 指定topic
        //参数二: 指定消息体
        rocketMQTemplate.convertAndSend("order-topic", order);
        return order;
    }

消费消息

@Slf4j
@Service("shopSmsService")
//consumerGroup-消费者组名  topic-要消费的主题
@RocketMQMessageListener(
        consumerGroup = "shop-user", //消费者组名
        topic = "order-topic",//消费主题
        consumeMode = ConsumeMode.CONCURRENTLY,//消费模式,指定是否顺序消费 CONCURRENTLY(同步,默认) ORDERLY(顺序)
        messageModel = MessageModel.CLUSTERING//消息模式 BROADCASTING(广播)  CLUSTERING(集群,默认)
)
public class SmsService implements RocketMQListener<Order> {

    //消费逻辑
    @Override
    public void onMessage(Order message) {
        log.info("接收到了一个订单信息{},接下来就可以发送短信通知了", message);
    }

}

常见问题和解决方案

RemotingConnectException: connect to <172.17.0.1: 10911>

vim conf/broker.conf 在随后添加下面两行

namesrvAddr=127.0.0.1:9876
brokerIP1=192.168.174.129 # 自己的IP地址

然后 重启nameserv和broker

bin/mqshutdown broker
bin/mqshutdown namesrv
nohup ./bin/mqnamesrv &
nohup bin/mqbroker -n localhost:9876 -c conf/broker.conf &

你可能感兴趣的:(MQ,java-rocketmq,rocketmq,java)