Spring整合RabbitMQ:
SpringBoot 整合RabbitMQ:
RabbitMQ 镜像队列:(待补充)
-------------------------------
Spring整合RabbitMQ:
整合demo 如下:
demo:
1.加上POM文件:
public class TulingMsgDelegate {
public void handleMessage(String msgBody) {
System.out.println("TulingMsgDelegate。。。。。。handleMessage"+msgBody);
}
public void consumerMsg(String msg){
System.out.println("TulingMsgDelegate。。。。。。consumerMsg"+msg);
}
public void consumerTopicQueue(String msgBody) {
System.out.println("TulingMsgDelegate。。。。。。consumerTopicQueue"+msgBody);
}
public void consumerTopicQueue2(String msgBody) {
System.out.println("TulingMsgDelegate。。。。。。consumerTopicQueue2"+msgBody);
}
/**
* 处理json
* @param jsonMap
*/
public void consumerJsonMessage(Map jsonMap) {
System.out.println("TulingMsgDelegate ============================处理json"+jsonMap);
}
/**
* 处理order得
* @param order
*/
public void consumerJavaObjMessage(Order order) {
System.out.println("TulingMsgDelegate ============================处理java对象"+order.toString());
}
public void consumerFileMessage(File file) {
System.out.println("TulingMsgDelegate========================处理文件"+file.getName());
}
}
消费者容器,监听多个队列,设置多个Queue,多写几个。监听我们的文件,设置消费者最大消费者数量,设置最大数值的消费者数量签收模式;是自动还是手动的。然后设置拒绝重回队列。创建我们消息的监听器,使用默认的监听方法,代码如下:
@Test
public void testRabbitmqTemplate() {
MessageProperties messageProperties = new MessageProperties();
messageProperties.getHeaders().put("company","tuling");
messageProperties.getHeaders().put("name","smlz");
String msgBody = "hello tuling";
Message message = new Message(msgBody.getBytes(),messageProperties);
//rabbitTemplate.send("tuling.topic.exchange","topic.haha",message);
//不需要message对象发送
rabbitTemplate.convertAndSend("tuling.direct.exchange","direct.key","smlz");
}
消费者方法,接受的第一种用法,其实有很多很简单的,其实使用很多的Springboot设置更简单。
真正开发中非常简单的,启动工程,发送信息,说明拦截掉了,然后呢,
制定方法,具体的某一个队列被某一个消费者消费,制定消费方法,setDefalutMessage()方法。重启一下,我们不同的队列,不同的方法消费,queue new 一个hashmap 的方法,
//指定具体某一个队列被某一个消费者消费
/* Map<String,String> queueOrTagToMethodName = new HashMap<>();
queueOrTagToMethodName.put("testTopicQueue","consumerTopicQueue");
queueOrTagToMethodName.put("testTopicQueue2","consumerTopicQueue2");
messageListenerAdapter.setQueueOrTagToMethodName(queueOrTagToMethodName);*/
测试方法:
@Test
public void messageListenerAdaperQueueOrTagToMethodName(){
rabbitTemplate.convertAndSend("tuling.topic.exchange","topic.xixi","你好 图灵");
rabbitTemplate.convertAndSend("tuling.topic.exchange","topic.key.xixi","你好 ");
}
创建一个quenrTopic Queue,制定一个队列的方法,监听另外一个方法,来这儿方法,设置
队列消费和绑定,listener 把,把工程给起起来,然后这边测试,发生的事情,同样;有一条信息luyo
路由到这边的高级的。一直Spring类型的,JSON的,Object 方法,处理JSON的,中间的方法处理JSON的。
然后把接着把new 一个JSON转换器的方法,这个设置,人家底层处理的使用Map 来接受的,通发送处理JSON
配置文件:
/**
* 处理json
* 1:需要创建一个消息转换器对象
* 2:把消息转换器设置到消息监听适配器上
* 3:把监听器设置到容器中
messageListenerAdapter.setDefaultListenerMethod("consumerJsonMessage");
Jackson2JsonMessageConverter jackson2JsonMessageConverter = new Jackson2JsonMessageConverter();
messageListenerAdapter.setMessageConverter(jackson2JsonMessageConverter);
simpleMessageListenerContainer.setMessageListener(messageListenerAdapter);
*/
通过消息属性体方法,这是处理JSON的,发送我们java Object 的处理的方法,处理Java 对象的。其中有少许的不同。
setfault 方法,设置处理的方法,设置我们的消息转换器方法,new 一个JSON 类对象转化的方法
@Test
public void sendJson() throws JsonProcessingException {
Order order = new Order();
order.setOrderNo(UUID.randomUUID().toString());
order.setCreateDt(new Date());
order.setPayMoney(10000.00);
order.setUserName("smlz");
ObjectMapper objectMapper = new ObjectMapper();
String orderJson = objectMapper.writeValueAsString(order);
MessageProperties messageProperties = new MessageProperties();
messageProperties.setContentType("application/json");
Message orderMsg = new Message(orderJson.getBytes(),messageProperties);
rabbitTemplate.convertAndSend("tuling.direct.exchange","rabbitmq.order",orderMsg);
}
不信任的信息,Java 最终把我们的LIstenAdapter ,
发送端:
@Test
public void sendJavaObj() throws JsonProcessingException {
Order order = new Order();
order.setOrderNo(UUID.randomUUID().toString());
order.setCreateDt(new Date());
order.setPayMoney(10000.00);
order.setUserName("smlz");
ObjectMapper objectMapper = new ObjectMapper();
String orderJson = objectMapper.writeValueAsString(order);
MessageProperties messageProperties = new MessageProperties();
messageProperties.setContentType("application/json");
messageProperties.getHeaders().put("__TypeId__","com.tuling.entity.Order");
Message orderMsg = new Message(orderJson.getBytes(),messageProperties);
rabbitTemplate.convertAndSend("tuling.direct.exchange","rabbitmq.order",orderMsg);
}
标记一个数值的方法,序列化和反序列化的方法,测试我们发送得java 对象的方法:
看一下的一个是ListAdapter方法,创建一个DefalutJackJSON ,找一下错误的原因的方法,JSON的
方法,
//设置java 转JSON的
试一下,把文字,图片发到MQ写出来,创建到一个方法,时间的方法,consumer方法,
设置转换器的方法,new一个messageconvert 方法,//设置转换器方法,把代码的跑起来的方法,
也可以发一个图片,进行发送测试:
/**
* 处理pdf image 等等
*/
messageListenerAdapter.setDefaultListenerMethod("consumerFileMessage");
//全局转换器
ContentTypeDelegatingMessageConverter messageConverter = new ContentTypeDelegatingMessageConverter();
messageConverter.addDelegate("img/png", new TulingImageConverter());
messageConverter.addDelegate("img/jpg",new TulingImageConverter());
messageConverter.addDelegate("application/word",new TulingWordConverter());
messageConverter.addDelegate("word",new TulingWordConverter());
messageListenerAdapter.setMessageConverter(messageConverter);
simpleMessageListenerContainer.setMessageListener(messageListenerAdapter);
return simpleMessageListenerContainer;
}
也可以发送一个文档,进行测试:
测试案例如下:
@Test
public void sendImage() throws IOException {
byte[] imgBody = Files.readAllBytes(Paths.get("D:/smlz/file01","smlz.png"));
MessageProperties messageProperties = new MessageProperties();
messageProperties.setContentType("img/png");
Message message = new Message(imgBody, messageProperties);
rabbitTemplate.send("tuling.direct.exchange","rabbitmq.file",message);
}
@Test
public void sendWord() throws IOException {
byte[] imgBody = Files.readAllBytes(Paths.get("D:/smlz/file01","spring.docx"));
MessageProperties messageProperties = new MessageProperties();
messageProperties.setContentType("application/word");
Message message = new Message(imgBody, messageProperties);
rabbitTemplate.send("tuling.direct.exchange","rabbitmq.file",message);
}
下载延时插件:
@Bean
测试发送延迟插件:
https://blog.csdn.net/joy_pan/article/details/90600642
-----------------------
SpringBoot 整合RabbitMQ:
1.加载POM文件:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
参考博文:https://blog.csdn.net/qq_35387940/article/details/100514134
我们来看一下配置文件,:
消费端: 导入一个包,另外一个东西,配置签收模式的,线程最大并发数目是10,new messagePostProcess,延迟10s 种
清空一下,发送延时消息,发送延插件消息,Spring 提供的
分布式事务,同一个事务中,CTL调用我们的Serc中,消息实体,然后保存到我们的数据库,两点,同一个事务中,如果我抛出异常, 消息不会发送,这是在同一个事务中,saveOrderInfo 中,业务都保存下来,消息没有发送出去,回调我们的错误的状态,看一下消息状态,定时任务会把消息更新重试次数再次发哦少年宫,生产端都细发送。
设置消息转换器,起作用了,设置我们生产端的方法,组件不清楚的话,看下Spring,
看一下消费端的代码:
@RabbitListener(queues = {ORDER_TO_PRODUCT_QUEUE_NAME})
@RabbitHandler
public void consumerMsgWithLock(Message message, Channel channel) throws IOException {
ObjectMapper objectMapper = new ObjectMapper();
MsgTxtBo msgTxtBo = objectMapper.readValue(message.getBody(), MsgTxtBo.class);
Long deliveryTag = (Long) message.getMessageProperties().getDeliveryTag();
if (redisTemplate.opsForValue().setIfAbsent(LOCK_KEY + msgTxtBo.getMsgId(), msgTxtBo.getMsgId())) {
log.info("消费消息:{}", msgTxtBo);
try {
//更新消息表也业务表
productService.updateProductStore(msgTxtBo);
//消息签收
System.out.println(1/0);
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
/**
* 更新数据库异常说明业务没有操作成功需要删除分布式锁
*/
if (e instanceof BizExp) {
BizExp bizExp = (BizExp) e;
log.info("数据业务异常:{},即将删除分布式锁", bizExp.getErrMsg());
//删除分布式锁
redisTemplate.delete(LOCK_KEY);
}
//更新消息表状态
MessageContent messageContent = new MessageContent();
messageContent.setMsgStatus(MsgStatusEnum.CONSUMER_FAIL.getCode());
messageContent.setUpdateTime(new Date());
messageContent.setErrCause(e.getMessage());
messageContent.setMsgId(msgTxtBo.getMsgId());
msgContentMapper.updateMsgStatus(messageContent);
channel.basicReject(deliveryTag,false);
}
} else {
log.warn("请不要重复消费消息{}", msgTxtBo);
channel.basicReject(deliveryTag,false);
}
}
我是在这个服务上加上一个服务的,加上一个数据异常,模拟更新,
把消费者启动,消息表没哟了,保存订单,插入消息表,定时任务去扫表。事务回滚了,
由于是业务异常,更新库存报异常,所以说是没有问题的,把product 关掉,模拟另外一个
抛出异常,模拟网络闪断,业务员正常之后,模拟网络抖动,
上了三节课的资料,模拟网络抖动,生产端跑起来之后,定时任务去扫描,通过我们的redis 命令,处理我们任务,
假如说业务抛出异常之后,封装了异常类型,失败,把锁给删除了。进步了,把锁给删除了。如果不是业务异常,模拟网络抖动,业务数据已经更新过了,更新状态下次重发就进不来,模拟网络抖动,唯一性锁的约束,现在模拟一下,现在我们把product 重启,如果分布式锁,确实可以做到,同学就数据库更能挂,现在处理1,始终只扣一个,加上服务。
我们会发送我们的消费端,UUID,传过来之后,消息之后,CorrlaionData 给我们生产端,那就根据ID更新的。
代码:
rabbitmq 镜像队列:
现在一个raabiitmq 如何做集群呢?
现在能配置3个节点的集群,启动之后,执行集群命令,
但是同步会同步到集群,镜像队列,集群同步之后,不支持集群的方法,
开启分析,启动我们的Down机的话,发送我们的集群信息,成功了,重启一下,监听到我们的消费,换了几台之后,集群模式,
集群的命令:
rabbitmqctl stop_all
rabbitmqctl join
参考博文:
https://blog.csdn.net/qq_18483301/article/details/90268453
https://blog.csdn.net/fall_hat/article/details/104980971
https://blog.csdn.net/zhanglong_longlong/article/details/78262459