菜鸟也能学会RocketMq

RocketMq是什么

RocketMQ 是一款分布式、队列模型的消息中间件,具有以下特点:

能够保证严格的消息顺序
提供丰富的消息拉取模式
高效的订阅者水平扩展能力
实时的消息订阅机制
亿级消息堆积能力

选择RocketMQ的理由:

强调集群模式无单点,可扩展,任意一点高可用,水平扩展
海量数据的堆积能力,消息堆积后,写入延迟低
支持上万个队列
消息失败重试机制
消息可查询
开源社区灵活
成熟度(支持阿里双十一)

Windows下开发环境搭建

考虑到大部分Java开发者还是习惯于在windows环境下开发,因此,推荐一篇文章,从资料下载,环境配置到实际操作都有详细的描述
https://blog.csdn.net/zxl646801924/article/details/105637278#comments_15530472

学会上面的搭建以后,我们来到代码实战

代码实战

思路:启动消息服务器->生产者实现->消费者实现

启动服务器

上面的文章里已经有 NameServer 和 Broker 两个部分的教学,这里就不细说了。

生产者实现

我们需要在项目中加上依赖

		<dependency>
		    <groupId>org.apache.rocketmq</groupId>
		    <artifactId>rocketmq-client</artifactId>
		    <version>4.7.0</version>
		</dependency>
		<dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.16.14</version>
            <scope>provided</scope>
        </dependency>

首先可以先创建一个配置类

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
 
/**
 * @author: lfr
 * @Date: 2020/4/12 10:28
 * @Description: mq生产者配置
 */
@Getter
@Setter
@ToString
@Configuration
@ConfigurationProperties(prefix = "rocketmq.producer")
public class MQProducerConfigure {
    public static final Logger LOGGER = LoggerFactory.getLogger(MQProducerConfigure.class);
 
    private String groupName="producer-group";
    private String namesrvAddr="127.0.0.1:9876";
    // 消息最大值
    private Integer maxMessageSize=4096;
    // 消息发送超时时间
    private Integer sendMsgTimeOut=300;
    // 失败重试次数
    private Integer retryTimesWhenSendFailed=2;
 
    /**
     * mq 生成者配置
     * @return
     * @throws MQClientException
     */
    @Bean
    @ConditionalOnProperty(prefix = "rocketmq.producer", value = "isOnOff", havingValue = "on")
    public DefaultMQProducer defaultProducer() throws MQClientException {
    	int num = (int) (Math.random()*100);
        LOGGER.info("defaultProducer 正在创建---------------------------------------");
        DefaultMQProducer producer = new DefaultMQProducer(groupName+num);
        producer.setNamesrvAddr(namesrvAddr);
        producer.setVipChannelEnabled(false);
        producer.setNamespace("restful-service");
        producer.setMaxMessageSize(maxMessageSize);
        producer.setSendMsgTimeout(sendMsgTimeOut);
        producer.setRetryTimesWhenSendAsyncFailed(retryTimesWhenSendFailed);
        producer.start();
        LOGGER.info("rocketmq producer server 开启成功----------------------------------");
        return producer;
    }
}

然后再创建一个生产者Controller,用来测试发送消息

import org.apache.commons.lang3.StringUtils;
import org.apache.rocketmq.client.exception.MQBrokerException;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.remoting.exception.RemotingException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
 
/**
 * @author: lfr
 * @Date: 2021/4/12 11:17
 * @Description:
 */
@RestController
@RequestMapping("/mqProducer")
public class MQProducerController {
    public static final Logger LOGGER = LoggerFactory.getLogger(MQProducerController.class);
 
    @Autowired(required = false)
    DefaultMQProducer defaultMQProducer ;//= new DefaultMQProducer();
 
   
    
    /**
     * 发送简单的MQ消息
     * @param msg
     * @return
     */
    @GetMapping("/send")
    public String send(String msg) throws InterruptedException, RemotingException, MQClientException, MQBrokerException {
    	MQProducerConfigure configure = new MQProducerConfigure();
    	defaultMQProducer = configure.defaultProducer();
    	String s="";
        if (StringUtils.isEmpty(msg)) {
            return s;
        }
        LOGGER.info("发送MQ消息内容:" + msg);
        System.out.println("发送MQ消息内容:" + msg);
        Message sendMsg = new Message("TestTopic", "TestTag", msg.getBytes());
        // 默认3秒超时
        SendResult sendResult = defaultMQProducer.send(sendMsg);
        LOGGER.info("消息发送响应:" + sendResult.toString());
        System.out.println();
        return sendResult.toString();
    }
 
}

启动项目,在浏览器访问我们的生产者
http://127.0.0.1:9010/restful-service/mqProducer/send?msg=hello
可以看到,调用后返回了这样的信息
在这里插入图片描述

消费者实现

根据生产者的地址,toptic来生成消费者

import java.util.List;
import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus;
import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.common.consumer.ConsumeFromWhere;
import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.common.protocol.heartbeat.MessageModel;
public class MQPushConsumer {
	

    public static void main(String[] args) throws MQClientException {
        String groupName = "consumer-group";
        // 用于把多个Consumer组织到一起,提高并发处理能力
       
        DefaultMQPushConsumer consumer = new DefaultMQPushConsumer(groupName);
        // 设置nameServer地址,多个以;分隔
        consumer.setNamesrvAddr("127.0.0.1:9876");
        consumer.setConsumeThreadMin(5);
        consumer.setConsumeThreadMax(32);
        consumer.setConsumeMessageBatchMaxSize(1);
        /**
         * 1. CONSUME_FROM_LAST_OFFSET:第一次启动从队列最后位置消费,后续再启动接着上次消费的进度开始消费 
           2. CONSUME_FROM_FIRST_OFFSET:第一次启动从队列初始位置消费,后续再启动接着上次消费的进度开始消费 
           3. CONSUME_FROM_TIMESTAMP:第一次启动从指定时间点位置消费,后续再启动接着上次消费的进度开始消费 
                以上所说的第一次启动是指从来没有消费过的消费者,如果该消费者消费过,那么会在broker端记录该消费者的消费位置,如果该消费者挂了再启动,那么自动从上次消费的进度开始
         */
        consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET);
        /**
         * CLUSTERING:默认模式,同一个ConsumerGroup(groupName相同)每个consumer只消费所订阅消息的一部分内容,同一个ConsumerGroup里所有的Consumer消息加起来才是所
         *  订阅topic整体,从而达到负载均衡的目的
         * BROADCASTING:同一个ConsumerGroup每个consumer都消费到所订阅topic所有消息,也就是一个消费会被多次分发,被多个consumer消费。
         * 
         */
        consumer.setMessageModel(MessageModel.BROADCASTING);
        consumer.subscribe("restful-service%TestTopic", "*");
      //4.注册消息监听器
		consumer.registerMessageListener(
			new MessageListenerConcurrently() {
				public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> list, ConsumeConcurrentlyContext Context) {
					Message msg = list.get(0);
					System.out.println(msg);
					String msgstr = new String(msg.getBody());
					System.out.println(msgstr);
					return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
				}
			}
		);
		try {
			//5.启动消费者
			consumer.start();
			System.out.println("consumer创建成功");
			//Thread.sleep(50 * 1000);
		} catch (Exception e) {
			e.printStackTrace();
		}
		//System.out.println("shutdown...");
		//6.关闭消费者
		//consumer.shutdown();
    }
}

启动后,可以看到成功接收生产者发送的消息
在这里插入图片描述监听类我们可以根据实际业务要求来自定义监听类。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值