RabbitMQ学习笔记(下):延迟队列,发布确认高级,备份交换机

十、延迟队列

延迟队列

概念:

延迟队列使用场景:

 

流程图:

延迟队列整合Springboot

导入依赖:

<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><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><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><dependency><groupId>org.springframework.amqp</groupId><artifactId>spring-rabbit-test</artifactId><scope>test</scope></dependency></dependencies>

在java/com/atguigu/rabbitmq下创建config创建类SwaggerConfig,写入代码:

@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("enjoy6288","http://atguigu.com","1551388580@qq.com")).build();}
}

队列TTL代码框架图:

队列TTL(配置类代码):

@Configuration
public class TtlQueueConfig {//普通交换机的名称public static final String X_EXCHANGE = "X";//死信交换机的名称public static final String Y_DEAD_LETTER_EXCHANGE = "Y";//普通队列的名称public static final String QUEUE_A = "QA";public static final String QUEUE_B = "QB";//死信队列的名称public static final String DEAD_LETTER_QUEUE = "QD";//声明xExchange@Bean("xExchange")public DirectExchange xExchange(){return new DirectExchange(X_EXCHANGE);}//声明yExchange@Bean("yExchange")public DirectExchange yExchange(){return new DirectExchange(Y_DEAD_LETTER_EXCHANGE);}//声明普通队列A的TTL为10s@Bean("queueA")public Queue queueA(){Map<String,Object> arguments = new HashMap<>(3);//设置死信交换机arguments.put("x-dead-letter-exchange",Y_DEAD_LETTER_EXCHANGE);//设置死信RoutingKeyarguments.put("x-dead-letter-routing-key","YD");//设置TTLarguments.put("x-message-ttl",10000);return QueueBuilder.durable(QUEUE_A).withArguments(arguments).build();}//声明普通队列B的TTL为40s@Bean("queueB")public Queue queueB(){Map<String,Object> arguments = new HashMap<>(3);//设置死信交换机arguments.put("x-dead-letter-exchange",Y_DEAD_LETTER_EXCHANGE);//设置死信RoutingKeyarguments.put("x-dead-letter-routing-key","YD");//设置TTLarguments.put("x-message-ttl",40000);return QueueBuilder.durable(QUEUE_B).withArguments(arguments).build();}//死信队列@Bean("queueD")public Queue queueD() {return QueueBuilder.durable(DEAD_LETTER_QUEUE).build();}//绑定A-X@Beanpublic Binding queueABindingX(@Qualifier("queueA") Queue queueA,@Qualifier("xExchange") DirectExchange xExchange){return BindingBuilder.bind(queueA).to(xExchange).with("XA");}//绑定B-x@Beanpublic Binding queueBBindingX(@Qualifier("queueB") Queue queueB,@Qualifier("xExchange") DirectExchange xExchange){return BindingBuilder.bind(queueB).to(xExchange).with("XB");}//绑定D-y@Beanpublic Binding queueDBindingY(@Qualifier("queueD") Queue queueD,@Qualifier("yExchange") DirectExchange yExchange){return BindingBuilder.bind(queueD).to(yExchange).with("YD");}
}

队列TTL(生产者):

@Slf4j
@RestController
@RequestMapping("/ttl")
public class SendMsgController {@Autowiredprivate RabbitTemplate rabbitTemplate;@GetMapping("/sendMsg/{message}")public void sendMsg(@PathVariable String message){log.info("当前时间:{},发送一条信息给两个TTL队列:{}",new Date().toString(),message);rabbitTemplate.convertAndSend("X","XA","消息来自ttl为10s的队列:"+message);rabbitTemplate.convertAndSend("X","XB","消息来自ttl为40s的队列:"+message);}
}

队列TTL(消费者)

@Slf4j
@Component
public class DeadLetterQueueConsumer {//接收消息@RabbitListener(queues="QD")public void receiveD(Message message, Channel channel) throws Exception{String msg = new String(message.getBody());log.info("当前时间:{},收到死信队列的消息:{}",new Date().toString(),msg);}
}

延迟队列优化

不能为需求增加队列,

写一个通用队列作为延迟队列:

配置类,在上面配置类中加入如下代码:

public static final String QUEUE_C = "QC";
//和死信交换机连接
@Bean("queueC")
public Queue queue(){Map<String,Object> arguments = new HashMap<>(3);//设置死信交换机arguments.put("x-dead-letter-exchange",Y_DEAD_LETTER_EXCHANGE);//设置死信RoutingKeyarguments.put("x-dead-letter-routing-key","YD");return QueueBuilder.durable(QUEUE_C).withArguments(arguments).build();
}
//和普通交换机绑定
@Bean
public Binding queueCBindingX(@Qualifier("queueC") Queue queueC,@Qualifier("xExchange") DirectExchange xExchange){return BindingBuilder.bind(queueC).to(xExchange).with("XC");
}

在前面生产者的基础上写入如下代码: 

@Slf4j
@RestController
@RequestMapping("/ttl")
public class SendMsgController {@Autowiredprivate RabbitTemplate rabbitTemplate;@GetMapping("/sendExpirationMsg/{message}/{ttlTime}")public void sendMsg(@PathVariable String message,@PathVariable String ttlTime){log.info("当前时间:{},发送一条时长{}毫秒TTL信息给队列QC:{}",new Date().toString(),ttlTime,message);rabbitTemplate.convertAndSend("X","XC",message,msg->{//发送消息的时候延迟时长msg.getMessageProperties().setExpiration(ttlTime);return msg;});}
}

点击启动类重新启动,在网页端输入:localhost:8080/ttl/sendExpirationMsg/你好1/20000和localhost:8080/ttl/sendExpirationMsg/你好2/2000。

问题:延迟队列是排队的,当队列中有多条消息时,延迟队列的消息会根据前面最长时间发送。

安装延迟队列插件:

在https://github.com/rabbitmq/rabbitmq-delayed-message-exchange/releases下载rabbitmq_delayed_message_exchange插件,解压放置到RabbitMQ的插件目录。

rabbitmq的插件在:/usr/lib/rabbitmq/lib/rabbitmq_server-3.8.8/plugins目录下,上传插件到目录下,如果上传失败用sudo rz先获得权限。

输入:rabbitmq-plugins enable rabbitmq_delayed_message_exchange

重启rabbitmq:systemctl restart rabbitmq-server

进入rabbitmq的交换机界面,查看下面是否出现,如果出现代表安装成功:

基于插件的延迟队列:

配置类

@Configuration
public class DelayedQueueConfig {//队列public static final String DELAYED_QUEUEE_NAME="delayed.queue";//交换机public static final String DELAYED_EXCHANGE_NAME="delayed.exchange";//routingKeypublic static final String DELAYED_ROUTING_KEY="delayed.routingkey";//声明队列@Beanpublic Queue delayedQueue(){return new Queue(DELAYED_QUEUEE_NAME);}//声明交换机,基于插件的@Beanpublic CustomExchange delayedExchange(){Map<String,Object> arguments = new HashMap<>();arguments.put("x-delayed-type","direct");//交换机名称,交换机类型,是否需要持久化,是否需要自动删除,其它参数return new CustomExchange(DELAYED_EXCHANGE_NAME,"x-delayed-message",true,false,arguments);}//绑定@Beanpublic Binding delayedQueueBindingDelayedExchange(@Qualifier("delayedQueue") Queue delayedQueue,@Qualifier("delayedExchange") CustomExchange delayedExchange){return BindingBuilder.bind(delayedQueue).to(delayedExchange).with(DELAYED_ROUTING_KEY).noargs();}
}

生产者

//发消息,基于插件的消息及延迟时间
@GetMapping("/sendDelayMsg/{message}/{delayTime}")
public void sendMsg(@PathVariable String message,@PathVariable  Integer delayTime){log.info("当前时间:{},发送一条时长{}毫秒信息给延迟队列delayed.queue:{}",new Date().toString(),delayTime,message);rabbitTemplate.convertAndSend(DelayedQueueConfig.DELAYED_EXCHANGE_NAME,DelayedQueueConfig.DELAYED_ROUTING_KEY,message,msg->{//发送消息时延迟时间(毫秒)msg.getMessageProperties().setDelay(delayTime);return msg;});
}

消费者,创建DelayQueueConsumer类:

@Slf4j
@Component
public class DelayQueueConsumer {//监听消息@RabbitListener(queues = DelayedQueueConfig.DELAYED_QUEUEE_NAME)public void receiveDelayQueue(Message message){String msg = new String(message.getBody());log.info("当前时间:{},收到延迟队列的消息:{}",new Date().toString(),msg);}}

测试:localhost:8080/ttl/sendDelayMsg/come on baby1/20000。localhost:8080/ttl/sendDelayMsg/come on baby2/2000

十一、发布确认高级

加入交换机或者队列两者有其中一者宕掉,消息都会丢失。

配置类:

@Configuration
public class ConfirmConfig {//交换机public static final String CONFIRM_EXCHANGE_NAME="confirm.exchange";//队列public static final String CONFIRM_QUEUE_NAME="confirm.queue";//RoutingKeypublic static final String CONFIRM_ROUTING_KEY="key1";//声明交换机@Bean("confirmExchange")public DirectExchange confirmExchange(){return new DirectExchange(CONFIRM_EXCHANGE_NAME);}//声明队列@Bean("confirmQueue")public Queue confirmQueue(){return QueueBuilder.durable(CONFIRM_QUEUE_NAME).build();}//绑定@Beanpublic Binding queueBindingExchange(@Qualifier("confirmQueue") Queue confirmQueue,@Qualifier("confirmExchange") DirectExchange confirmExchange){return BindingBuilder.bind(confirmQueue).to(confirmExchange).with(CONFIRM_ROUTING_KEY);}
}

生产者:

@RestController
@Slf4j
@RequestMapping("/confirm")
public class ProducerController {@Autowiredprivate RabbitTemplate rabbitTemplate;//发消息@GetMapping("/sendMessage/{message}")public void sendMessage(@PathVariable String message){rabbitTemplate.convertAndSend(ConfirmConfig.CONFIRM_EXCHANGE_NAME,ConfirmConfig.CONFIRM_ROUTING_KEY,message);log.info("发送消息内容:{}",message);}
}

消费者: 

@Slf4j
@Component
public class Consumer {@RabbitListener(queues = ConfirmConfig.CONFIRM_QUEUE_NAME)public void receiveConfirmMessagee(Message message){String msg = new String(message.getBody());log.info("接受到的队列confirm.queue消息:{}",msg);}
}

实验步骤:先输入localhost:8080/confirm/sendMessage/大家好1。

MyCallBack是一个实现类,继承了RabbitTemplate.ConfirmCallback接口,因为不再里面,所以到时候掉接口根本调不到实现类,因此需要注入。

回调接口:

先在配置文件中写入如下:

spring.rabbitmq.publisher-confirm-type=correlated
@Slf4j
@Component
public class MyCallBack implements RabbitTemplate.ConfirmCallback {@Autowiredprivate RabbitTemplate rabbitTemplate;@PostConstructpublic void init(){//注入rabbitTemplate.setConfirmCallback(this);}/*交换机确认回调方法* 1.发消息,交换机接收到了,回调*  1.1.correlationData保存回调消息的ID及相关信息*  1.2.交换机收到消息 ack = true*  1.3.cause null* 2.发消息,交换机接收失败了,回调*  2.1.correlationData保存回调信息的ID及相关信息*  2.2.交换机收到消息 ack = false*  2.3.cause 失败的原因*/@Overridepublic void confirm(CorrelationData correlationData,boolean ack,String cause){String id = correlationData!=null?correlationData.getId():"";if(ack){log.info("交换机已经收到了Id为:{}的消息",id);}else{log.info("交换机已经收到了Id为:{}的消息,由于原因:{}",id,cause);}}
}

如果交换机没有确认或者确认是失败的,都证明是失败的,会确认回调。

交换机确认

@RestController
@Slf4j
@RequestMapping("/confirm")
public class ProducerController {@Autowiredprivate RabbitTemplate rabbitTemplate;//发消息@GetMapping("/sendMessage/{message}")public void sendMessage(@PathVariable String message){CorrelationData correlationData = new CorrelationData("1");rabbitTemplate.convertAndSend(ConfirmConfig.CONFIRM_EXCHANGE_NAME,ConfirmConfig.CONFIRM_ROUTING_KEY,message,correlationData);log.info("发送消息内容:{}",message);}
}

输入:localhost:8080/confirm/sendMessage/大家好1,测试回调。

回退消息

退回的情况是当routingkey出现错误,差不多就是队列出现问题时,需要回退错误的消息。

Mandatory参数:

首先在配置文件中加入下面代码:

spring.rabbitmq.publisher-returns=true

 代码是在上面MyCallBack基础上进行修改,首先在implements后面加上RabbitTemplate.ReturnCallback,记得在init里注入setReturnCallback,returnedMessage是重写的方法,点击MyCallBack然后按住alt+enter重写。

@Slf4j
@Component
public class MyCallBack implements RabbitTemplate.ConfirmCallback,RabbitTemplate.ReturnCallback {@Autowiredprivate RabbitTemplate rabbitTemplate;@PostConstructpublic void init(){//注入rabbitTemplate.setConfirmCallback(this);rabbitTemplate.setReturnCallback(this);}//可以在当消息传递过程中不可达目的地时将消息返回给生产者//只有不可达目的地的时候,才进行回退@Overridepublic void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {log.error("消息{},被交换机{}退回,退回原因:{},路由Key:{}",new String(message.getBody()),exchange,replyText,routingKey);}
}

十二、备份交换机

要写一个备份交换机,一个备份队列,一个报警队列。

配置类ConfirmConfig,注意要【修改确认交换机】,使其与备份交换机关联;注意要在绑定的方法上面加上@Bean:

//声明确认交换机
@Bean("confirmExchange")
public DirectExchange confirmExchange(){return ExchangeBuilder.directExchange(CONFIRM_EXCHANGE_NAME).durable(true).withArgument("alternate-exchange",BACKUP_EXCHANGE_NAME).build();
}
public static final String BACKUP_EXCHANGE_NAME = "backup_exchange";
public static final String BACKUP_QUEUE_NAME="backup_queue";
public static final String WARNING_QUEUE_NAME="warning_queue";
//备份交换机
@Bean("backupExchange")
public FanoutExchange backupExchange(){return new FanoutExchange(BACKUP_EXCHANGE_NAME);
}
//备份队列
@Bean("backupQueue")
public Queue backupQueue(){return QueueBuilder.durable(BACKUP_QUEUE_NAME).build();
}
//报警队列
@Bean("warningQueue")
public Queue warningQueue(){return QueueBuilder.durable(WARNING_QUEUE_NAME).build();
}
//绑定
@Bean
public Binding backupQueueBindingBackupExchange(@Qualifier("backupQueue") Queue backupQueue,@Qualifier("backupExchange") FanoutExchange backupExchange){return BindingBuilder.bind(backupQueue).to(backupExchange);
}
@Bean
public Binding warningQueueBindingBackupExchange(@Qualifier("warningQueue") Queue warningQueue,@Qualifier("backupExchange") FanoutExchange backupExchange){return BindingBuilder.bind(warningQueue).to(backupExchange);
}

结果分析:

在consumer下创建一个WarningConsumer类,写入如下代码:

@Component
@Slf4j
public class WarningConsumer {//接收报警消息@RabbitListener(queues = ConfirmConfig.WARNING_QUEUE_NAME)public void receiveWarningMsg(Message message){String msg = new String(message.getBody());log.error("报警发现不可路由消息:{}",msg);}
}

然后要在rabbitmq可视化界面将【confirm交换机删除掉】:

若想实现如下效果需要更改routingkey的值,比如加上一个“2”。

由此看出备份交换机的优先级高于回退消息。

幂等性:

概念:

消息重复消费:

解决思路:

消费端的幂等性保障:

1. 唯一ID+指纹码机制

2.利用Redis原子性

优先级队列使用场景:

优先级队列0到255越大越优先执行

优先级队列代码实现:

生产者代码如下:

public class producer {//队列名称public static final String QUEUE_NAME = "hello";//发消息public static void main( String[] args ) throws IOException, TimeoutException {//第1步:创建一个连接工程ConnectionFactory factory = new ConnectionFactory();//第2步:输入工厂IP,用户名和密码——连接RabbitMQd队列factory.setHost("192.168.182.157");factory.setUsername("admin");factory.setPassword("123");//第3步:创建连接Connection connection = factory.newConnection();//第4步:获取信道Channel channel = connection.createChannel();Map<String,Object> arguments = new HashMap<>();arguments.put("x-max-priority",10);channel.queueDeclare(QUEUE_NAME,true,false,false,arguments);for(int i=1;i<11;i++){String message = "info"+i;if(i==5){AMQP.BasicProperties properties = new AMQP.BasicProperties().builder().priority(5).build();channel.basicPublish("",QUEUE_NAME,properties,message.getBytes());channel.basicPublish("",QUEUE_NAME,null,message.getBytes());}else{channel.basicPublish("",QUEUE_NAME,null,message.getBytes());}}}
}

测试:生产者先将所有消息发到队列当中,然后再由消费者消费。先启动生产者,再启动消费者。最后info5在控制台最上面,是最后打印的,符合逻辑。

十三、集群

惰性队列:

消息保存在内存中还是在磁盘上。正常情况:消息保存在内存中。惰性队列:消息保存在磁盘中。惰性队列消费速度很慢,需要先提取到内存中。使用场景:消息堆积太多比如有100万,但消费者宕机了。

使用场景:

两种模式:

集群原理:

搭建集群:

先关机,克隆出2台机器,然后全部启动。查看ip地址,然后用xshell连接上3台主机。

 

第1步:修改3台机器的主机名称。在第1台主机上输入hostname,显示node1。在第2台和第3台主机上输入vi /etc/hostname,然后把node1分别改成node2和node3,要输入【reboot】进行重启。

第2步:配置各个节点的hosts文件,让各个节点能互相识别对方。vi /etc/hosts。把3条ip node值,赋值到3个Xshell会话。

第3步:确保各个节点的cookie文件使用的是同一个值。在node1上执行远程操作命令:

scp /var/lib/rabbitmq/.erlang.cookie root@node2:/var/lib/rabbitmq/.erlang.cookie
scp /var/lib/rabbitmq/.erlang.cookie root@node3:/var/lib/rabbitmq/.erlang.cookie

第4步:启动RabbitMQ服务,顺带启动Erlang虚拟机和RabbitMQ应用服务(在三台节点上分别执行下命令) :rabbitmq-server -detached

第5步:在节点2执行:

rabbitmqctl stop_app
rabbitmqctl reset
rabbitmqctl join_cluster rabbit@node1
rabbitmqctl start_app

第6步:在节点3执行:

rabbitmqctl stop_app
rabbitmqctl reset
rabbitmqctl join_cluster rabbit@node2
rabbitmqctl start_app

第7步:查看集群状态:rabbitmqctl cluster_status

第8步:重新设置用户:创建账号:rabbitmqctl add_user admin 123。设置用户角色:rabbitmqctl set_user_tags admin administrator。设置用户权限:rabbitmqctl set_permissions -p "/" admin ".*" ".*" ".*"

第9步:解除集群节点(node2和node3机器分别执行) 

镜像队列:

镜像是备份,接收到的消息不应该只在一个节点上存在,否则一个节点宕机,消息就消失了。

ha-mode:备机模式。ha-param:填写备份数量。ha-sync-mode备份模式。

实验:在1号机上创建1个队列,然后会自动备份一份在2号或3号机上。现在节点1关闭,备份的数据会被存储到另外

实现高可用负载均衡:

VIP连接主机,如果主机宕机了,会自动将连接漂移到备机。备机还会时不时询问主机的存在。需要Haproxy以及keepalive软件。

高可用主机宕机备机接管。

十四、Federation

1.首先要开启多个节点,然后让每台节点单独运行。

2.在每台机器上开启federation插件:先输入:rabbitmq-plugins enable rabbitmq_federation再输入:rabbitmq-plugins enable rabbitmq_federation_management

Exchange实现:

下面是部分代码:

public static final String FED_EXCHANGE="fed_exchange";
channel.exchangeDeclare(FED_EXCHANGE,BuiltinExchangeType.DIRECT);
channel.queueDeclare("node2_queue",true,false,false,null);
channel.queueBind("node2_queue",FED_EXCHANGE,"routeKey");

下面是具体的配置:

 

检查是否成功,如果成功出现如下:

Queue实现:

Shovel:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/150831.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

MyCat安装文档

JDK安装 JDK具体安装步骤如下&#xff1a; 1. 上传安装包 使用FinalShell自带的上传工具将jdk的二进制发布包上传到Linux 由于上述在进行文件上传时&#xff0c;选择的上传目录为根目录 /&#xff0c;上传完毕后&#xff0c;我们执行指令 cd / 切换到根目录下&#xff0c;查…

六款Linux常用远程连接工具

1、Xshell 介绍&#xff1a; xshell是一个非常强大的安全终端模拟软件&#xff0c;它支持SSH1, SSH2, 以及Windows平台的TELNET 协议。Xshell可以在Windows界面下用来访问远端不同系统下的服务器&#xff0c;从而比较好的达到远程控制终端的目的。&#xff08;也是我目前使用的…

15-自动化测试——理论知识

目录 1.什么是自动化测试&#xff1f; 2.常见的自动化测试分类 2.1.单元测试&#xff08;Java、Python&#xff09; 2.2.接口测试&#xff08;Java、Python&#xff09; 2.3.UI测试&#xff08;移动端、网站&#xff09; 3.如何实施自动化测试&#xff1f; 4.自动化测试…

力扣第572题 另一棵树的子树 c++深度(DFS)注释版

题目 572. 另一棵树的子树 简单 给你两棵二叉树 root 和 subRoot 。检验 root 中是否包含和 subRoot 具有相同结构和节点值的子树。如果存在&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 二叉树 tree 的一棵子树包括 tree 的某个节点和这个节点的所有…

(高阶) Redis 7 第21讲 IO多路复用模型 完结篇

🌹 以下分享 Redis IO多路复用模型,如有问题请指教。🌹🌹 如你对技术也感兴趣,欢迎交流。🌹🌹🌹 如有对阁下帮助,请👍点赞💖收藏🐱‍🏍分享😀 IO多路复用模型是什么 I/O:网络IO 多路:多个客户端连接(连接即套接字描述符,即socket或channel),指…

hive 常用函数

1.分位数 percentile_approx(DOUBLE col, p [, B]) Returns an approximate pth percentile of a numeric column (including floating point types) in the group 含义: 在col列中返回p%的分位数 select percentile_approx( arr_id , 0.5 )from (selectarr_idfrom(selecta…

【赠书活动】Excel透视表的简单应用

&#x1f449;博__主&#x1f448;&#xff1a;米码收割机 &#x1f449;技__能&#x1f448;&#xff1a;C/Python语言 &#x1f449;公众号&#x1f448;&#xff1a;测试开发自动化【获取源码商业合作】 &#x1f449;荣__誉&#x1f448;&#xff1a;阿里云博客专家博主、5…

【网络】路由器和交换机的区别

&#x1f341; 博主 "开着拖拉机回家"带您 Go to New World.✨&#x1f341; &#x1f984; 个人主页——&#x1f390;开着拖拉机回家_Linux,大数据运维-CSDN博客 &#x1f390;✨&#x1f341; &#x1fa81;&#x1f341; 希望本文能够给您带来一定的帮助&#x1…

微服务技术栈-Nacos配置管理和Feign远程调用

文章目录 前言一、统一配置管理1.添加配置文件2.微服务拉取配置3.配置共享 三、Feign远程调用总结 前言 在上篇文章中介绍了微服务技术栈中Nacos这个组件的概念&#xff0c;Nacos除了可以做注册中心&#xff0c;同样可以做配置管理来使用。同时我们将学习一种新的远程调用方式…

【Linux】信号屏蔽与信号捕捉的原理与实现(附图解与代码)

这一篇的篇幅可能有点长&#xff0c;如果已经了解了以下两个知识点的同学可以自行跳到第三部分——信号屏蔽的实现。 不太了解的同学希望你们能够静下心来看完&#xff0c;相信一定会有不小的收获。那么话不多说&#xff0c;我们这就开始啦&#xff01;&#xff01;&#xff0…

git与github的交互(文件与文件夹的上传)

git与github的交互&#xff08;文件与文件夹的上传&#xff09; 准备&#xff1a;gitHub账号&#xff08;创建一个新项目&#xff09;与Git软件的安装 一&#xff1a;开启公钥SSH登录&#xff08;之前配置过就跳过&#xff09; 1.安装SSH 在本地新创建文件夹负责装载项目&a…

(c语言)经典bug

#include<stdio.h> //经典bug int main() { int i 0; int arr[10] {1,2,3,4,5,6,7,8,9,10}; for (i 0; i < 12; i) //越界访问 { arr[i] 0; printf("hehe\n"); } return 0; } 注&#xff1a;输出结果为死循…

[论文工具] LaTeX论文SVG和EPS矢量图转换方法详解

祝大家中秋国庆双节快乐&#xff01; 回过头来&#xff0c;我们在编程过程中&#xff0c;经常会遇到各种各样的问题。然而&#xff0c;很多问题都无法解决&#xff0c;网上夹杂着各种冗余的回答&#xff0c;也缺乏系统的实战技巧归纳。为更好地从事科学研究和编程学习&#xff…

螺杆支撑座有什么优势?

螺杆支撑座是机械设备中重要的支撑部件&#xff0c;其主要作用是支撑和固定螺杆&#xff0c;以确保机械设备的正常运行。以下是螺杆支撑座的使用优势&#xff1a; 1、支撑稳定&#xff1a;螺杆支撑座采用高品质钢材制作而成&#xff0c;具有较高的强度和刚度&#xff0c;能够为…

FR问题记录

1. 问题&#xff1a;下拉框搜索查询时&#xff0c;出现所有的搜索信息 解决方法&#xff1a;使用数据集sql进行数据筛选 在数据库查询中使用where条件筛选&#xff0c;如 ${IF(LEN(所属省份) 0,"","AND province in (" 所属省份 ")")}参考…

预测性人工智能会彻底改变SIEM行业吗?

网络安全行业具有高度的活力&#xff0c;始终能够将最新和最优秀的技术融入其系统中。这背后有两个主要原因&#xff1a;首先&#xff0c;网络攻击不断演化&#xff0c;因此组织需要拥有先进技术以便检测复杂的攻击&#xff1b;其次&#xff0c;许多组织的网络架构非常复杂。 …

FREERTOS内容解惑与综合应用(基于STM32F103)

本文基础内容参考的是正点原子的FREERTOS课程。 这是基于HAL库的 正点原子手把手教你学FreeRTOS实时系统 这是基于标准库的 正点原子FreeRTOS手把手教学-基于STM32 基础知识&#xff0c;直接参考正点原子《FreeRTOS开发指南V1.1》基于标准库的&#xff0c;此处不再赘述。 本文…

清算、结算、南北卡支付行业概念一次说清

一&#xff0c;第三方支付 第三方支付是指具备一定实力和信誉保障的独立机构&#xff0c;通过与银联或网联对接而促成交易双方进行交易的网络支付模式。 在第三方支付模式&#xff0c;买方选购商品后&#xff0c;使用第三方平台提供的账户进行货款支付&#xff08;支付给第三方…

在字节跳动做了6年软件测试,4月无情被辞,想给划水的兄弟提个醒

先简单交代一下背景吧&#xff0c;某不知名 985 的本硕&#xff0c;17 年毕业加入字节&#xff0c;以“人员优化”的名义无情被裁员&#xff0c;之后跳槽到了有赞&#xff0c;一直从事软件测试的工作。之前没有实习经历&#xff0c;算是6年的工作经验吧。 这6年之间完成了一次…

PowerShell 命令窗口执行 pnpm 命令报错 无法加载文件 pnpm.ps1,因为在此系统上禁止运行脚本

目录 问题解决验证附&#xff1a;开源项目微服务商城项目前后端分离项目 问题 在 PowerShell 命令行窗口使用 pnpm run dev 启动 vue3-element-admin 报错&#xff1a; pnpm : 无法加载文件 C:\Users\youlai\AppData\Roaming\npm\pnpm.ps1&#xff0c;因为在此系统上禁止运行脚…