在了解rocketMq之前先了解一下jms规范,rocketmq虽然不完全基于jms规范,但是他参考了jms规范和 CORBA Notification 规范等,可以说是青出于蓝而胜于蓝。
JMS即Java消息服务(Java Message Service)应用程序接口,是一个Java平台中关于面向消息中间件(MOM)的API,用于在两个应用程序之间,或分布式系统中发送消息,进行异步通信。Java消息服务是一个与具体平台无关的API,绝大多数MOM提供商都对JMS提供支持。
RocketMQ原理:mmap+write,文件系统,数据存储结构,队列,刷盘策略,消息查询,消息过滤,事务消息,发送、订阅负载均衡,同步双写/异步复制,充分利用内存,消息堆积能力以及解决办法。
RcoketMQ 是一款低延迟、高可靠、可伸缩、易于使用的消息中间件。具有以下特性:
(1)点对点消息模型:
点对点就是一对一的关系,一个消息发出只有一个接受者所处理。每个消息都被发送到一个特定的队列,接收者从队列中获取消息。队列保留着消息,直到他们被消费或超时。
(2)发布订阅消息模型:
客户端将消息发送到主题。多个发布者将消息发送到Topic,系统将这些消息传递给多个订阅者。如果你希望发送的消息可以不被做任何处理、或者被一个消息者处理、或者可以被多个消费者处理的话,那么可以采用Pub/Sub模型。
2. 在一个队列中可靠的先进先出(FIFO)和严格的顺序传递
3. 支持拉(pull)和推(push)两种消息模式
4. 单一队列百万消息的堆积能力
5. 支持多种消息协议,如 JMS、MQTT 等
6. 分布式高可用的部署架构,满足至少一次消息传递语义
7. 提供 docker 镜像用于隔离测试和云集群部署
8. 提供配置、指标和监控等功能丰富的 Dashboard
1. 在pom文件中引入rocketMq
com.alibaba.rocketmq
rocketmq-client
3.2.6
2. 构建Producer类(消息生产者由Session创建,并用于将消息发送到Destination。同样,消息生产者分两种类型:QueueSender和TopicPublisher。可以调用消息生产者的方法(send或publish方法)发送消息)
public class Producer {
public void test(String msgString){
DefaultMQProducer producer = new DefaultMQProducer("Producer_ChenHT_Test");
producer.setNamesrvAddr("192.168.20.31:9876");
try {
producer.start();
Message msg = new Message("PushTopicChenhaitao",
"push",
"1",
msgString.getBytes());
SendResult result = producer.send(msg);
System.out.println("发送端:"+"id:" + result.getMsgId() +
" result:" + result.getSendStatus());
} catch (Exception e) {
e.printStackTrace();
}finally{
producer.shutdown();
}
}
}
3. 构建Consumer类,消息消费者由Session创建,用于接收被发送到Destination的消息。两种类型:QueueReceiver和TopicSubscriber。可分别通过session的createReceiver(Queue)或createSubscriber(Topic)来创建。当然,也可以session的creatDurableSubscriber方法来创建持久化的订阅者。
public class Consumer {
public void testConsume(){
DefaultMQPushConsumer consumer =
new DefaultMQPushConsumer("consumer_test_msg");
consumer.setNamesrvAddr("192.168.20.31:9876");
try {
//订阅PushTopic下Tag为push的消息
consumer.subscribe("pushTopicHaleyliu", "push");
//程序第一次启动从消息队列头取数据
System.out.println("开始监听推送topic频道的push动作。。。。。。");
consumer.setConsumeFromWhere(
ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET);
consumer.registerMessageListener(
new MessageListenerConcurrently() {
public ConsumeConcurrentlyStatus consumeMessage(
List list,
ConsumeConcurrentlyContext Context) {
Message msg = list.get(0);
System.out.println("接收到的消息是:"+msg.toString());
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
}
}
);
consumer.start();
} catch (Exception e) {
e.printStackTrace();
}
}
}
4. Service层
public interface RocketMqService {
void testRocketMQForProduceAndConsume(String msg);
}
@Service
public class RocketMqServiceImpl implements RocketMqService{
@Override
public void testRocketMQForProduceAndConsume(String msg){
Producer producer = new Producer();
producer.test(msg);
}
}
5. Controller层
@Controller
public class RocketMqController {
@Autowired
private RocketMqService rocketMqService;
@GetMapping("/mq")
public String getMq(@RequestParam("msg") String msg){
rocketMqService.testRocketMQForProduceAndConsume(msg);
return "完成";
}
}
如果出现rocketmq运行时提示 No route info of this topic 异常产生的原因可能是:
① Broker禁止自动创建Topic,且用户没有通过手工方式创建Topic
mqbroker.exe -n 电脑ipv4地址:9876 autoCreateTopicEnable=true
② Broker没有正确连接到Name Server
③ Producer没有正确连接到Name Server
④ 防火墙未关闭
⑤ 少 jar 包:fastjson-1.2.29.jar
⑥ mqnameserver 或者 mqbroker 会报错内存不够
vim bin/runserver.sh (调整nameserver启动的内存,不调整此文件,可能导致无法启动。)
JAVA_OPT="${JAVA_OPT} -server -Xms256m -Xmx256m -Xmn512m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=320m"
vim bin/runbroker.sh
JAVA_OPT="${JAVA_OPT} -server -Xms256m -Xmx256m -Xmn128m"