最近项目有块业务要用mq去给其他项目发送消息,由于没有权限直接登录阿里云mq的主页控制台,所以就先本地搭建了一个rocketmq,大体上基本一样的。
由于搭建本地mq的时候生产者和消费者都是在本地,所以就把服务器做到了其他机器上(部署就不说了,网上有好多)
服务器开好,创建好topic,就可以搭建demo去测了。
如图,用springboot项目整合了,发现阿里云mq只需要ons-client-1.8.0.Final.jar这个包,日志包是共需,下图所示的包几乎全是rocketmq的包
消费者代码如下(机器地址这里我改成了本地的,实际上用的是其他电脑的)
public class TestM {
public static void main(String[] args) throws InterruptedException, MQClientException {
// 实例化 consumer,指定 consumer 组名
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("defaultConsumer");
// 指定 name server
consumer.setNamesrvAddr("127.0.0.1:9876");
// 订阅1个或多个topic
consumer.subscribe("TopicTest", "*");
// 注册回调,当收到消息时执行
consumer.registerMessageListener(new MessageListenerConcurrently() {
public ConsumeConcurrentlyStatus consumeMessage(final List msgs, final ConsumeConcurrentlyContext context) {
System.out.printf("%s Receive New Messages: %s %n", Thread.currentThread().getName(), msgs);
for(MessageExt mext : msgs) {
System.out.println("message body: " + new String(mext.getBody()));
}
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;}
});
// 启动 consumer
consumer.start();
System.out.printf("Consumer Started.%n");
System.out.println("-------"+(int)((Math.random()*9+1)*100000));
}
}
生产者代码如下
public class TestP {
public static void main(String[] args) {
DefaultMQProducer producer = new DefaultMQProducer("demoGroup");
producer.setNamesrvAddr("127.0.0.1:9876");
//producer.setVipChannelEnabled(false);
// 在发送消息前,必须调用 start 方法来启动 Producer,只需调用一次即可
try {
producer.start();
} catch (MQClientException e) {
e.printStackTrace();
}
//循环发送消息
try {
for (int i = 0; i < 10; i++) {
Message msg = new Message("TopicTest","TagA",("Good!" + i).getBytes("UTF-8"));
SendResult sendResult = producer.send(msg);
// 同步发送消息,只要不抛异常就是成功
if (sendResult != null) {
System.out.println(new Date() + " Send mq message success. Topic is:" + msg.getTopic() + " msgId is: " + sendResult.getMsgId());
}
}
}
catch (Exception e) {
System.out.println("失败失败失败");
// 消息发送失败,需要进行重试处理,可重新发送这条消息或持久化这条数据进行补偿处理
e.printStackTrace();
}
// 在应用退出前,销毁 Producer 对象
// 注意:如果不销毁也没有问题
producer.shutdown();
}
}
二个都启动,都能收到消息就表示成功了,失败了就看看是不是机器名,端口,topic不对,一般大概率是这个,还有问题的话就看看是不是被防火请拦到了,关闭下防火请,一般就没啥问题了。
本地的还算比较成功的,在看看阿里云mq,开通服务和申请资源是主要麻烦,由于没权限,所以大家可以去看看这篇博客,特别详细
https://blog.csdn.net/liuchaoxuan/article/details/83717101
资源申请好后,就可以本地搞个demo试试了,消费者代码如下
public class ConsumerTest {
public static void main(String[] args) {
Properties properties = new Properties();
// 您在控制台创建的 Group ID
properties.put(PropertyKeyConst.GROUP_ID, "GID_ID");
// AccessKey 阿里云身份验证,在阿里云服务器管理控制台创建
properties.put(PropertyKeyConst.AccessKey, ");
// SecretKey 阿里云身份验证,在阿里云服务器管理控制台创建
properties.put(PropertyKeyConst.SecretKey, "");
// 设置 TCP 接入域名,进入控制台的实例管理页面的“获取接入点信息”区域查看
properties.put(PropertyKeyConst.NAMESRV_ADDR,"");
// 顺序消息消费失败进行重试前的等待时间,单位(毫秒),取值范围: 10 毫秒 ~ 1800 毫秒
properties.put(PropertyKeyConst.SuspendTimeMillis, "100");
// 消息消费失败时的最大重试次数
properties.put(PropertyKeyConst.MaxReconsumeTimes, "20");
// 在订阅消息前,必须调用 start 方法来启动 Consumer,只需调用一次即可。
OrderConsumer consumer = ONSFactory.createOrderedConsumer(properties);
consumer.subscribe(
// Message 所属的 Topic
"topic",
// 订阅指定 Topic 下的 Tags:
// 1. * 表示订阅所有消息
// 2. TagA || TagB || TagC 表示订阅 TagA 或 TagB 或 TagC 的消息
"*",
new MessageOrderListener() {
/**
* 1. 消息消费处理失败或者处理出现异常,返回 OrderAction.Suspend
* 2. 消息处理成功,返回 OrderAction.Success
*/
@Override
public OrderAction consume(Message message, ConsumeOrderContext context) {
System.out.println("message body: " + new String(message.getBody()));
return OrderAction.Success;
}
});
consumer.start();
}
}
生产者代码如下
public class ProducerTest {
public static void main(String[] args) {
Properties properties = new Properties();
// AccessKey 阿里云身份验证,在阿里云服务器管理控制台创建
properties.put(PropertyKeyConst.AccessKey,"");
// SecretKey 阿里云身份验证,在阿里云服务器管理控制台创建
properties.put(PropertyKeyConst.SecretKey, "");
//设置发送超时时间,单位毫秒
properties.setProperty(PropertyKeyConst.SendMsgTimeoutMillis, "3000");
// 设置 TCP 接入域名,进入控制台的实例管理页面的“获取接入点信息”区域查看
properties.put(PropertyKeyConst.NAMESRV_ADDR,"");
Producer producer = ONSFactory.createProducer(properties);
// 在发送消息前,必须调用 start 方法来启动 Producer,只需调用一次即可
producer.start();
System.out.println(producer);
//循环发送消息
for (int i = 0; i < 10; i++){
Message msg = new Message();
msg.setTopic("topic");
msg.setBody("Good!".getBytes());
try {
SendResult sendResult = producer.send(msg);
// 同步发送消息,只要不抛异常就是成功
if (sendResult != null) {
System.out.println(new Date() + " Send mq message success. Topic is:" + msg.getTopic() + " msgId is: " + sendResult.getMessageId());
}
}
catch (Exception e) {
// 消息发送失败,需要进行重试处理,可重新发送这条消息或持久化这条数据进行补偿处理
System.out.println(new Date() + " Send mq message failed. Topic is:" + msg.getTopic());
e.printStackTrace();
}
}
// 在应用退出前,销毁 Producer 对象
// 注意:如果不销毁也没有问题
producer.shutdown();
}
}
都启动,能正常消费消息就表示成功了,如果没成功,先看看身份验证的那些参数,topic,tcp接入域名对不对,还有问题,可以ping一下tcp的地址,如果能接通,看看是不是ecc没通阿里云,如果还有问题可以在maven引入fastjson包看看,好像老版本的mq需要fastjson,还有问题请自行bing
这次项目中我们只是生产者,所以mq嵌入项目中还是挺简单的,加包,工具类,用的地方单独开个线程(不影响业务流程)调一下就完了,以前没接触过,正好这次学习了下。