当前位置: 首页 > news >正文

杭州市工程建设安全管理社会网站精准客户运营推广

杭州市工程建设安全管理社会网站,精准客户运营推广,在凡科网申请的网站设置网页访问密码,电商网站设计思想延迟队列与SpringBoot实战 概念 延时队列,队列内部是有序的,最重要的特性就体现在它的延时属性上,延时队列中的元素是希望在指定时间到了以后或之前取出和处理,简单来说,延时队列就是用来存放需要在指定时间被处理的元素的队列 …

延迟队列与SpringBoot实战

概念

延时队列,队列内部是有序的,最重要的特性就体现在它的延时属性上,延时队列中的元素是希望在指定时间到了以后或之前取出和处理,简单来说,延时队列就是用来存放需要在指定时间被处理的元素的队列

TTL介绍

TTL 是什么呢?TTL 是 RabbitMQ 中一个消息或者队列的属性,表明一条消息或者该队列中的所有消息的最大存活时间,单位是毫秒。换句话说,如果一条消息设置了 TTL 属性或者进入了设置TTL 属性的队列,那么这条消息如果在TTL 设置的时间内没有被消费,则会成为"死信"。如果同时配置了队列的TTL 和消息的TTL,那么较小的那个值将会被使用,有两种方式设置 TTL。

设置TTL
  • 消息设置TTL

    rabbitTemplate.convertAndSend("X", "XC", message + "ttl:" + ttl, msg -> {msg.getMessageProperties().setExpiration(ttl);return msg;});
    
  • 队列设置TTL

    args.put("x-message-ttl",15000);
    QueueBuilder.durable(QUEUE_B).withArguments(args).build();
    
  • 如果不设置 TTL,表示消息永远不会过期,如果将 TTL 设置为 0,则表示除非此时可以直接投递该消息到消费者,否则该消息将会被丢弃

代码实战

配置POM
<dependencies><!--RabbitMQ 依赖--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.47</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><!--swagger--><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId><version>2.9.2</version></dependency><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger-ui</artifactId><version>2.9.2</version></dependency><!--RabbitMQ 测试依赖--><dependency><groupId>org.springframework.amqp</groupId><artifactId>spring-rabbit-test</artifactId><scope>test</scope></dependency></dependencies>
配置application
spring.rabbitmq.host=192.168.31.232
spring.rabbitmq.port=5672
spring.rabbitmq.username=admin
spring.rabbitmq.password=admin
配置Swagger
package com.vmware.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;@Configuration
@EnableSwagger2
public class SwaggerConfig {@Beanpublic Docket webApiConfig() {return new Docket(DocumentationType.SWAGGER_2).groupName("webApi").apiInfo(webApiInfo()).select().build();}private ApiInfo webApiInfo() {return new ApiInfoBuilder().title("rabbitmq 接口文档").description("本文档描述了 rabbitmq 微服务接口定义").version("1.0").contact(new Contact("name", "url","email")).build();}
}
代码架构图

创建两个队列 QA 和 QB,两者队列 TTL 分别设置为 10S 和 40S,然后在创建一个交换机 X 和死信交换机 Y,它们的类型都是direct,创建一个死信队列 QD,它们的绑定关系如下

在这里插入图片描述

RabbitMQ配置类
package com.vmware.config;import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import java.util.HashMap;
import java.util.Map;@Configuration
public class RabbitConfig {//普通交换机private static final String X_EXCHANGE = "X";//死信交换机private static final String Y_EXCHANGE = "Y";//普通队列Aprivate static final String QUEUE_A = "QA";//普通队列Bprivate static final String QUEUE_B = "QB";//普通队列Cprivate static final String QUEUE_C = "QC";//死信队列Dprivate static final String QUEUE_D = "QD";@Bean("xExchange")public DirectExchange xExchange() {return new DirectExchange(X_EXCHANGE);}@Bean("yExchange")public DirectExchange yExchange() {return new DirectExchange(Y_EXCHANGE);}@Bean("queueA")public Queue queueA() {Map<String, Object> args = new HashMap<>();//设置死信交换机args.put("x-dead-letter-exchange", Y_EXCHANGE);//设置死信Routing Keyargs.put("x-dead-letter-routing-key", "YD");//设置超时args.put("x-message-ttl", 10000);//构建队列return QueueBuilder.durable(QUEUE_A).withArguments(args).build();}@Bean("queueB")public Queue queueB() {Map<String, Object> args = new HashMap<>();//设置死信交换机args.put("x-dead-letter-exchange", Y_EXCHANGE);//设置死心Routing Keyargs.put("x-dead-letter-routing-key", "YD");//设置超时ttlargs.put("x-message-ttl",15000);//构建队列return QueueBuilder.durable(QUEUE_B).withArguments(args).build();}@Bean("queueC")public Queue queueC(){Map<String,Object> args=new HashMap<>();//设置死信交换机args.put("x-dead-letter-exchange", Y_EXCHANGE);//设置死信Routing Keyargs.put("x-dead-letter-routing-key", "YD");//构建队列return QueueBuilder.durable(QUEUE_C).withArguments(args).build();}@Bean("queueD")public Queue queueD(){//构建死信队列Dreturn QueueBuilder.durable(QUEUE_D).build();}//绑定普通交换机和队列A@Beanpublic Binding queueABindingX(){return BindingBuilder.bind(queueA()).to(xExchange()).with("XA");}//绑定普通交换机与队列B@Beanpublic Binding queueBBindingX(){return BindingBuilder.bind(queueB()).to(xExchange()).with("XB");}//绑定普通交换机与队列C@Beanpublic Binding queueCBindingX(){return BindingBuilder.bind(queueC()).to(xExchange()).with("XC");}//绑定死信交换机与死信队列@Beanpublic Binding queueDBindingY(){return BindingBuilder.bind(queueD()).to(yExchange()).with("YD");}
}
生产者
package com.vmware.controller;import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;import java.util.Date;@RestController
@RequestMapping("/ttl")
@Slf4j
public class SendMsgController {@Autowiredprivate RabbitTemplate rabbitTemplate;/*** @param message 消息* @apiNote 生产者代码*/@GetMapping("/sendMsg/{message}")public void sendMsg(@PathVariable String message) {log.info("当前时间:{},发送消息给两个队列:{}", new Date(), message);rabbitTemplate.convertAndSend("X", "XA", "消息来自ttl为10秒的队列" + message);rabbitTemplate.convertAndSend("X", "XB", "消息来自ttl为15秒的队列" + message);}@GetMapping("/sendMsg/{message}/{ttl}")public void sendMsg(@PathVariable String message, @PathVariable String ttl) {rabbitTemplate.convertAndSend("X", "XC", message + "ttl:" + ttl, msg -> {msg.getMessageProperties().setExpiration(ttl);return msg;});log.info("当前时间:{},发送消息:{}给队列:XC,ttl:{}", new Date(), message, ttl);}
}
消费者
package com.vmware.consumer;import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;import java.util.Date;@Slf4j
@Component
public class DeadLetterQueueConsumer {@RabbitListener(queues = {"QD"})public void receiveD(Message message, Channel channel) {log.info("当前时间:{} 死信队列收到消息:{}", new Date(), message);}
}
存在的问题

当生产者发布消息到延迟队列后,消息只能按顺序被消费者消费,当某一消息阻塞时间很长时则会导致其他消息一同阻塞,不能达到ttl到期优先被延时队列的消费者所消费的效果

优化

下载插件rabbitmq_delayed_message_exchange到rabbit的plugin目录下

  • 官网:https://www.rabbitmq.com/community-plugins.html

  • ubuntu下载方式

    cd /usr/lib/rabbitmq/lib/rabbitmq_server-3.8.2/plugins
    sudo wget https://github.com/rabbitmq/rabbitmq-delayed-message-exchange/releases/download/v3.8.0/rabbitmq_delayed_message_exchange-3.8.0.ez
    
  • 启用插件

    rabbitmq-plugins enable rabbitmq_delayed_message_exchange
    
  • 重启服务

    systemctl restart rabbitmq-server
    
  • 安装完成后可以在rabbit交换机页面看到x-delayed-message
    在这里插入图片描述

基于插件的延时队列代码实战

在我们自定义的交换机中,这是一种新的交换类型,该类型消息支持延迟投递机制 消息传递后并不会立即投递到目标队列中,而是存储在 mnesia(一个分布式数据系统)表中,当达到投递时间时,才投递到目标队列中
在这里插入图片描述

配置延时队列与交换机
package com.vmware.config;import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.CustomExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import java.util.HashMap;
import java.util.Map;@Configuration
public class DelayQueueConfig {private static final String DELAY_QUEUE_NAME = "delayed.queue";private static final String DELAY_EXCHANGE_NAME = "delayed.exchange";private static final String DELAY_ROUTING_KEY = "delayed.routingkey";@Beanpublic Queue delayQueue(){return new Queue(DELAY_QUEUE_NAME);}@Beanpublic CustomExchange delayExchange(){Map<String,Object> args =new HashMap<>();args.put("x-delayed-type", "direct");/*** 1.交换机名称* 2.交换机类型:插件类型* 3.是否持久化* 4.是否自动删除*/return new CustomExchange(DELAY_EXCHANGE_NAME,"x-delayed-message",true,false,args);}@Beanpublic Binding delayQueueBindExchange(){return BindingBuilder.bind(delayQueue()).to(delayExchange()).with(DELAY_ROUTING_KEY).noargs();}
}
生产者
package com.vmware.controller;import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;import java.util.Date;@RestController
@RequestMapping("/ttl")
@Slf4j
public class SendMsgController {@Autowiredprivate RabbitTemplate rabbitTemplate;@GetMapping("/sendDelayMsg/{message}/{delayTime}")public void sendMsg(@PathVariable String message, @PathVariable Integer delayTime) {rabbitTemplate.convertAndSend("delayed.exchange", "delayed.routingkey", message, msg -> {msg.getMessageProperties().setDelay(delayTime);return msg;});log.info("当前时间:{},发送一条延迟{}毫秒的信息给队列 delayed.queue:{}", new Date(), delayTime, message);}
}
消费者
package com.vmware.consumer;import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
import java.util.Date;@Slf4j
@Component
public class DeadLetterQueueConsumer {@RabbitListener(queues = {"delayed.queue"})public void receiveDelayedQueue(Message message) {String msg = new String(message.getBody());log.info("当前时间:{},收到延时队列的消息:{}", new Date(), msg);}
}
实际效果
2022-07-19 23:33:18.021  INFO 23040 --- [nio-8080-exec-4] com.vmware.controller.SendMsgController  : 当前时间:Tue Jul 19 23:33:18 CST 2022,发送一条延迟20000毫秒的信息给队列 delayed.queue:哈哈哈
2022-07-19 23:33:23.349  INFO 23040 --- [nio-8080-exec-5] com.vmware.controller.SendMsgController  : 当前时间:Tue Jul 19 23:33:23 CST 2022,发送一条延迟2000毫秒的信息给队列 delayed.queue:哈
2022-07-19 23:33:25.332  INFO 23040 --- [ntContainer#0-1] c.v.consumer.DeadLetterQueueConsumer     : 当前时间:Tue Jul 19 23:33:25 CST 2022,收到延时队列的消息:哈
2022-07-19 23:33:37.830  INFO 23040 --- [ntContainer#0-1] c.v.consumer.DeadLetterQueueConsumer     : 当前时间:Tue Jul 19 23:33:37 CST 2022,收到延时队列的消息:哈哈哈
  • 可以看到前一条延时消息并没有阻塞到后面的消息
http://www.15wanjia.com/news/6056.html

相关文章:

  • 做网站需要提供哪些资料优化的定义
  • 珠海做网站优化的公司美业推广平台
  • 网站建设哪个比较好国家税务总局网
  • 做平台好还是做网站好大数据营销的案例
  • 我想做个网站怎么做营销团队公司
  • 辽宁省建设教育协会网站seo内链优化
  • 网站建设文件夹布局电脑培训学校课程
  • 批量上传网站产品互联网营销推广
  • 卢湾区网站建设制作今日资讯最新消息
  • 新手如何自学编程扬州seo推广
  • 潍坊大宇网络网站建设nba今日数据
  • 怎么创立自己的网站网络推广有哪些渠道
  • wordpress站点统计插件搭建网站基本步骤
  • div css企业网站seo网站优化收藏
  • 怎样做外国石雕产品网站百度seo排名优化技巧分享
  • 完整网站开发唐山建站公司模板
  • dreamweaver做的网站百度直播平台
  • 广州网站改版 网站建设网店推广常用的方法
  • 承德网站建设服务网络营销公司是做什么的
  • 住房和城乡建设部网站八大员网站的收录情况怎么查
  • 网站收录怎么弄哪些平台可以发布软文
  • 网站上传工具有什么武汉网站建设公司
  • 怎么做网站收录的关键词专业做网站建设的公司
  • 网站开发建设总结新塘网站seo优化
  • 外贸英文商城网站建设优化教程
  • 太原网站建设王道下拉惠优秀营销软文范例800字
  • 无线网络优化是做什么的seo技术快速网站排名
  • 公司做网站价格网站流量统计系统
  • 做网站客户需要提供的资料成都品牌推广
  • 网站平台需要做无形资产吗 怎么做6怎么做好营销推广