RabbitMQ 中的六大工作模式介绍与使用
文章目录
- 简单队列(Simple Queue)模式
- 配置类定义
- 消费者定义
- 发送消息测试消费
- 工作队列(Work Queues)模式
- 配置类定义
- 消费者定义
- 发送消息测试消费
- 负载均衡调优
- 发布/订阅(Publish/Subscribe)模式
- 配置类定义
- 消费者定义
- 发送消息测试消费
- 路由(Routing)模式
- 配置类定义
- 消费者定义
- 发送消费测试消费
- 主题(Topics)模式
- 配置类定义
- 消费者定义
- 发送消息测试消费
- RPC(Remote Procedure Call)模式
- 配置类定义
- 请求与响应实体类
- 消费者定义
- 发送消息测试消费
简单队列(Simple Queue)模式
- 结构:一个生产者对应一个消费者,生产者将消息发送到指定队列,消费者从该队列获取消息。
- 工作流程:生产者创建一个消息并发送到 RabbitMQ 的队列中,消费者从这个队列里取出消息进行处理。
- 应用场景:适用于任务处理逻辑简单,对消息处理速度要求不高,且消息处理顺序要求不严格的场景,比如简单的日志收集系统。
以下是简单队列(Simple Queue)模式的使用案例。
配置类定义
package test;import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class SimpleQueueConfig {@Beanpublic DirectExchange simpleQueueExchange() {return ExchangeBuilder// 指定名称为simple-queue-exchange的交换机.directExchange("simple-queue-exchange")// 声明为持久化交换机.durable(true).build();}@Beanpublic Queue simpleQueue() {return QueueBuilder// 指定一个名称为simple-queue的持久化队列.durable("simple-queue").build();}@Beanpublic Binding simpleQueueToSimpleQueueExchangebinding() {// 绑定队列给交换机,根据队列名为路由键return BindingBuilder.bind(simpleQueue()).to(simpleQueueExchange()).withQueueName();}}
消费者定义
package test;import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;@Component
@Slf4j
public class SimpleQueueConsumer {@RabbitListener(queues = "simple-queue")public void consumer(String message) {log.info("消费者接收消息:{}", message);}}
发送消息测试消费
package test;import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;@SpringBootApplication
public class SpringBootApp {public static void main(String[] args) {ApplicationContext context = SpringApplication.run(SpringBootApp.class, args);RabbitTemplate rabbitTemplate = context.getBean(RabbitTemplate.class);rabbitTemplate.convertAndSend("simple-queue", "hello world!");}}
控制台输出:
工作队列(Work Queues)模式
- 结构:一个生产者对应多个消费者,多个消费者共同从一个队列中获取消息进行处理。
- 工作流程:生产者将消息发送到队列,多个消费者从该队列中获取消息(默认采用轮询的负载均衡策略),一条消息只会被一个消费者处理。
- 应用场景:适用于需要将大量任务分发给多个工作者并行处理的场景,例如订单处理、图片处理等。
以下是工作队列(Work Queues)模式的使用案例。
配置类定义
定义一个 DirectExchange
类型的交换机与两个队列,通过队列名作为 RoutingKey
进行绑定。
package test;import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class WorkQueueConfig {@Beanpublic DirectExchange workQueueExchange(){return ExchangeBuilder.directExchange("work-queue-exchange").durable(true).build();}@Beanpublic Queue workQueue(){return QueueBuilder.durable("work-queue").build();}@Beanpublic Binding workQueueToWorkQueueExchangeBinding(){return BindingBuilder.bind(workQueue()).to(workQueueExchange()).withQueueName();}}
消费者定义
定义两个消费者,分别监听两个不同的队列。
消费者 1:
package test;import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Service;@Slf4j
@Service
public class WorkQueueConsumer01 {@RabbitListener(queues = "work-queue")public void receive(String message){log.info("WorkQueueConsumer01 receive a message:{}",message);}}
消费者 2:
package test;import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Service;@Slf4j
@Service
public class WorkQueueConsumer02 {@RabbitListener(queues = "work-queue")public void receive(String message){log.info("WorkQueueConsumer02 receive a message:{}",message);}}
发送消息测试消费
向 work-queue-exchange
交换机中发送 10 条消息。
package test;import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;@SpringBootApplication
public class SpringBootApp {public static void main(String[] args) {ApplicationContext context = SpringApplication.run(SpringBootApp.class, args);RabbitTemplate rabbitTemplate = context.getBean(RabbitTemplate.class);for (int i = 0; i < 10; i++) {rabbitTemplate.convertAndSend("work-queue-exchange", "work-queue", "hello world!" + i);}}}
控制台输出:
在上例结果,消费者 1 与消费者 2 对消息进行了轮询处理。
负载均衡调优
在工作队列模式下,多个消费者处理消息默认按照轮询的规则进行处理。但是如果其中某个消费者的处理能力比其他消费者更为强大,那么它实际上可以处理更多的消息,如果此时还是按照轮询规则来处理消息,这样是对该消费者能力的一种浪费。
对于上述情况,在 RabbitMQ 中支持调整消费者处理消息时的负载均衡策略,具体而言,即通过设置预取数量(prefetch count)参数,以实现更灵活的消息分发策略,即让处理能力更强大的消费者处理更多的消息。
在 Spring Boot 中,可以通过设置 spring.rabbitmq.listener.simple.prefetch
参数来控制消费者的预取数量:
spring:rabbitmq:listener:simple:prefetch: 1
将预取数量设置为 1,则每个消费者在处理完当前消息并确认(ACK)之后才会接收下一条消息,从而避免了某个消费者负载过重的情况。
模拟当某个消费者处理能力较弱:
package test;import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Service;@Slf4j
@Service
public class WorkQueueConsumer01 {@RabbitListener(queues = "work-queue")public void receive(String message) throws InterruptedException {// 模拟WorkQueueConsumer01处理能力较弱Thread.sleep(1);log.info("WorkQueueConsumer01 receive a message:{}",message);}}
再次向交换机发送 10 条消息,控制台输出:
在上述结果中,由于 WorkQueueConsumer01
处理消息的能力更弱,所以更多的消息被分摊到了 WorkQueueConsumer02
处理。
发布/订阅(Publish/Subscribe)模式
- 结构:包含一个生产者、一个交换机(Exchange)和多个队列,多个消费者分别监听不同的队列。
- 工作流程:生产者将消息发送到交换机,交换机将消息广播到绑定到它的所有队列,每个绑定的队列对应的消费者都能收到消息。
- 应用场景:适用于一个消息需要被多个不同的服务或模块接收和处理的场景,如系统的通知功能。
以下是发布/订阅(Publish/Subscribe)模式的使用案例。
配置类定义
定义一个 FanoutExchange
类型的交换机与三个队列,让三个队列绑定到该交换机。
FanoutExchange 交换机不需要指定 RoutingKey。因为 FanoutExchange 交换机会将消息统一发送给与其绑定的所有队列,指定 RoutingKey 实际上没有任何意义。
package test;import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class PublishSubscribeConfig {@Beanpublic Queue publishSubscribeQueue1() {return new Queue("publish-subscribe-queue-1");}@Beanpublic Queue publishSubscribeQueue2() {return new Queue("publish-subscribe-queue-2");}@Beanpublic Queue publishSubscribeQueue3() {return new Queue("publish-subscribe-queue-3");}@Beanpublic FanoutExchange publishSubscribeFanoutExchange() {return new FanoutExchange("publish-subscribe-fanout-exchange");}@Beanpublic Binding publishSubscribeBinding1() {return BindingBuilder.bind(publishSubscribeQueue1()).to(publishSubscribeFanoutExchange());}@Beanpublic Binding publishSubscribeBinding2() {return BindingBuilder.bind(publishSubscribeQueue2()).to(publishSubscribeFanoutExchange());}@Beanpublic Binding publishSubscribeBinding3() {return BindingBuilder.bind(publishSubscribeQueue3()).to(publishSubscribeFanoutExchange());}}
消费者定义
定义三个消费者,分别监听三个不同的队列。
第一个消费者:
package test;import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Service;@Slf4j
@Service
public class PublishSubscribeConsumer01 {@RabbitListener(queues = "publish-subscribe-queue-1")public void receive(String message) {log.info("PublishSubscribeConsumer 01 receive a Message:{}",message);}}
第二个消费者:
package test;import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Service;@Slf4j
@Service
public class PublishSubscribeConsumer02 {@RabbitListener(queues = "publish-subscribe-queue-2")public void receive(String message) {log.info("PublishSubscribeConsumer 02 receive a message:{}",message);}}
第三个消费者:
package test;import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Service;@Slf4j
@Service
public class PublishSubscribeConsumer03 {@RabbitListener(queues = "publish-subscribe-queue-3")public void receive(String message) {log.info("PublishSubscribeConsumer 03 receive a message:{}",message);}}
发送消息测试消费
向 publish-subscribe-fanout-exchange
发送一条消息。
package test;import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;@SpringBootApplication
public class SpringBootApp {public static void main(String[] args) {ApplicationContext context = SpringApplication.run(SpringBootApp.class, args);RabbitTemplate rabbitTemplate = context.getBean(RabbitTemplate.class);rabbitTemplate.convertAndSend("publish-subscribe-fanout-exchange","","hello world!");}}
控制台输出:
路由(Routing)模式
- 结构:同样包含生产者、交换机和多个队列,但交换机类型为直连交换机(Direct Exchange),队列通过路由键(routing key)绑定到交换机。
- 工作流程:生产者发送消息时指定路由键,交换机根据路由键将消息路由到与之绑定的队列,只有绑定了对应路由键的队列才能收到消息。
- 应用场景:适用于根据不同的业务规则将消息路由到不同队列的场景,如根据日志的级别(info、error 等)将日志消息路由到不同的队列。
以下是路由(Routing)模式的使用案例。
配置类定义
定义一个 DirectExchange
,因为 DirectExchange
可以通过 RoutingKey
精确匹配消息,当然也可以使用其他类型的交换机,如 ToppicExchange
。
定义三个不同名称的队列,其中两个队列绑定相同的 RoutingKey
,而另外一个单独绑定一个队列。
package test;import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class RoutingConfig {@Beanpublic DirectExchange routingExchange() {return ExchangeBuilder.directExchange("routing-exchange").durable(true).build();}@Beanpublic Queue routingQueue1() {return QueueBuilder.durable("routing-queue-1").build();}@Beanpublic Queue routingQueue2() {return QueueBuilder.durable("routing-queue-2").build();}@Beanpublic Queue routingQueue3() {return QueueBuilder.durable("routing-queue-3").build();}@Beanpublic Binding routingQueue1ToRoutingExchangeBinding() {return BindingBuilder.bind(routingQueue1()).to(routingExchange()).with("routing-key-1");}@Beanpublic Binding routingQueue2ToRoutingExchangeBinding() {return BindingBuilder.bind(routingQueue2()).to(routingExchange()).with("routing-key-2");}@Beanpublic Binding routingQueue3ToRoutingExchangeBinding() {return BindingBuilder.bind(routingQueue3()).to(routingExchange()).with("routing-key-2");}}
消费者定义
定义三个消费者,分别监听三个不同的队列。
第一个消费者:
package test;import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Service;@Slf4j
@Service
public class RoutingQueueConsumer01 {@RabbitListener(queues = "routing-queue-1")public void receive(String message){log.info("RoutingQueueConsumer01 receive a message:{}",message);}}
第二个消费者:
package test;import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Service;@Slf4j
@Service
public class RoutingQueueConsumer02 {@RabbitListener(queues = "routing-queue-2")public void receive(String message){log.info("RoutingQueueConsumer02 receive a message:{}",message);}}
第三个消费者:
package test;import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Service;@Slf4j
@Service
public class RoutingQueueConsumer03 {@RabbitListener(queues = "routing-queue-3")public void receive(String message){log.info("RoutingQueueConsumer03 receive a message:{}",message);}}
发送消费测试消费
向交换机发送消息,并指定 RoutingKey
为其中的两个。
package test;import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;@SpringBootApplication
public class SpringBootApp {public static void main(String[] args) {ApplicationContext context = SpringApplication.run(SpringBootApp.class, args);RabbitTemplate rabbitTemplate = context.getBean(RabbitTemplate.class);rabbitTemplate.convertAndSend("routing-exchange", "routing-key-1", "hello world by routing-key-1!");rabbitTemplate.convertAndSend("routing-exchange", "routing-key-2", "hello world by routing-key-2!");}}
控制台输出:
上述结果中,三个消费者都接受到了消息并成功处理。但实际上发送消息时,交换机只向两个 RoutingKey
发送消息,而另外一个 RoutingKey
并没有发送。这样的情况下,三个消息者监听三个不同队列仍然能够接受消息并处理,这是因为它们监听的队列所绑定的 RoutingKey
都被交换机投递了消息。
主题(Topics)模式
- 结构:包含生产者、主题交换机(Topic Exchange)和多个队列,队列通过绑定键(binding key)绑定到交换机,绑定键可以使用通配符。
- 工作流程:生产者发送消息时指定路由键,交换机根据绑定键和路由键的匹配规则将消息路由到相应的队列。
- 应用场景:适用于需要根据消息的主题进行灵活路由的场景,如新闻分类订阅,用户可以根据不同的主题订阅不同的新闻。
生产者发送包含主题的消息,主题由一个或多个单词组成,单词之间使用点号 .
进行分隔。消费者可以使用通配符 *
和 #
对主题进行模糊匹配:
*
:匹配一个单词,可以代表任意一个词。#
:匹配零个或多个单词,可以代表一个或多个词。
以下是主题(Topics)模式的使用案例。
配置类定义
定义一个 TopicExchange
,分别通过 log.info.*
与 log.error.#
的 RoutingKey
绑定到两个不同的队列。
package test;import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class TopicConfig {@Beanpublic Queue topicQueue1() {return new Queue("topic-queue-1");}@Beanpublic Queue topicQueue2() {return new Queue("topic-queue-2");}@Beanpublic TopicExchange topicExchange() {return new TopicExchange("topic-exchange");}@Beanpublic Binding bindingExchange() {return BindingBuilder.bind(topicQueue1()).to(topicExchange()).with("log.info.*");}@Beanpublic Binding bindingExchange2() {return BindingBuilder.bind(topicQueue2()).to(topicExchange()).with("log.error.#");}}
消费者定义
定义两个消费者分别监听两个不同队列。
第一个消费者:
package test;import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Service;@Slf4j
@Service
public class TopicQueueConsumer01 {@RabbitListener(queues = "topic-queue-1")public void receive(String message){log.info("TopicQueueConsumer01 receive a message:{}",message);}}
第二个消费者:
package test;import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Service;@Slf4j
@Service
public class TopicQueueConsumer02 {@RabbitListener(queues = "topic-queue-2")public void receive(String message){log.info("TopicQueueConsumer02 receive a message:{}",message);}}
发送消息测试消费
向 topic-exchange
交换机发送六条消息,通过不同的 RoutingKey
。
package test;import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;@SpringBootApplication
public class SpringBootApp {public static void main(String[] args) {ApplicationContext context = SpringApplication.run(SpringBootApp.class, args);RabbitTemplate rabbitTemplate = context.getBean(RabbitTemplate.class);rabbitTemplate.convertAndSend("topic-exchange", "log.info.base", "log.info.base message!");rabbitTemplate.convertAndSend("topic-exchange", "log.info.customer", "log.info.customer message!");rabbitTemplate.convertAndSend("topic-exchange", "log.info.shop.goods", "log.info.shop.goods message!");rabbitTemplate.convertAndSend("topic-exchange", "log.error.base", "log.error.base message!");rabbitTemplate.convertAndSend("topic-exchange", "log.error.customer", "log.error.customer message!");rabbitTemplate.convertAndSend("topic-exchange", "log.error.shop.goods", "log.error.shop.goods message!");}}
控制台输出:
RPC(Remote Procedure Call)模式
- 结构:包含客户端(生产者)、服务端(消费者)、请求队列和响应队列。
- 工作流程:客户端发送请求消息到请求队列,并设置一个回调队列用于接收响应;服务端从请求队列获取请求消息,处理后将响应消息发送到回调队列,客户端从回调队列获取响应。
- 应用场景:适用于需要在分布式系统中进行远程过程调用的场景,如微服务之间的调用。
以下是主题(Topics)模式的使用案例。
配置类定义
定义一个交换机与一个队列,通过队列名进行绑定。
package test;import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class RpcConfig {@Beanpublic Queue rpcQueue() {return new Queue("rpc-queue", true);}@Beanpublic DirectExchange rpcExchange() {return new DirectExchange("rpc-exchange");}@Beanpublic Binding rpcQueueToRpcExchangeBinding() {return BindingBuilder.bind(rpcQueue()).to(rpcExchange()).withQueueName();}@Beanpublic Jackson2JsonMessageConverter jackson2JsonMessageConverter() {return new Jackson2JsonMessageConverter();}}
请求与响应实体类
创建 RPC 请求与响应实体类。
package test;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.io.Serializable;@Data
@AllArgsConstructor
@NoArgsConstructor
public class RpcRequest implements Serializable {private String message;}
package test;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.io.Serializable;@Data
@AllArgsConstructor
@NoArgsConstructor
public class RpcResponse implements Serializable {private int result;}
消费者定义
定义一个消费者从队列中接收消息。
package test;import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Service;@Service
@Slf4j
public class RpcServer {@RabbitListener(queues = "rpc-queue")public RpcResponse handleRpcRequest(RpcRequest request) {log.info("RPC接收的消息:{}", request);return new RpcResponse(0);}}
发送消息测试消费
测试 RPC 消息的发送。
package test;import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;@SpringBootApplication
@Slf4j
public class SpringBootApp {public static void main(String[] args) {ApplicationContext context = SpringApplication.run(SpringBootApp.class, args);RabbitTemplate rabbitTemplate = context.getBean(RabbitTemplate.class);String exchange = "rpc-exchange";String routingKey = "rpc-queue";RpcRequest rpcRequest = new RpcRequest("Rpc message!");RpcResponse rpcResponse = (RpcResponse) rabbitTemplate.convertSendAndReceive(exchange, routingKey, rpcRequest);log.info("RPC返回的结果:{}", rpcResponse);}}
控制台输出:
相关文章:
RabbitMQ 中的六大工作模式介绍与使用
文章目录 简单队列(Simple Queue)模式配置类定义消费者定义发送消息测试消费 工作队列(Work Queues)模式配置类定义消费者定义发送消息测试消费负载均衡调优 发布/订阅(Publish/Subscribe)模式配置类定义消…...
一种基于重建前检测的实孔径雷达实时角超分辨方法——论文阅读
一种基于重建前检测的实孔径雷达实时角超分辨方法 1. 专利的研究目标与实际问题意义2. 专利提出的新方法、模型与公式2.1 重建前检测(DBR)与数据裁剪2.1.1 回波模型与检测准则2.1.2 数据裁剪效果2.2 数据自适应迭代更新2.2.1 代价函数与迭代公式2.2.2 矩阵递归更新2.3 正则化…...
代购平台如何“说本地话,穿本地衣”
当海外消费者点开一个代购商城,看到满屏机械翻译的中式文案,他们大概率会默默关闭页面。还有数据显示,不符合本地审美的页面设计会导致70%的潜在客户流失,而专业的本地化改造能让订单转化率提升3倍以上。 01 AI翻译:让…...
C++调试(叁):编译qBreakpad并使用其生成Dump文件
目录 1.前言 2.生成Dump文件的第三方库 3.第三方库下载链接 4.编译qBreakpad 5.VS中使用qBreakpad 6.qBreakpad测试程序 前言 在第二篇文章中,我主要讲解了如何使用SetUnhandledExceptionFilter函数设置程序的异常回调,在设置的回调函数中调用MiniDumpWr…...
0基础 | STM32 | TB6612电机驱动使用
TB6612介绍及使用 单片机通过驱动板连接至电机 原因:单品机I/O口输出电流I小 驱动板:从外部引入高电压,控制电机驱动 电源部分 VM:电机驱动电源输入,输入电压范围建议为3.7~12V GND:逻辑电…...
Cycleresearcher:通过自动化评审改进自动化研究
1、引言 迄今为止,整个科学发现过程自动化的挑战在很大程度上仍未解决,特别是在生成和改进符合同行评审工作高标准的研究成果方面。此外,很少有工作涉及迭代反馈的整合,这对保持学术的健全性和新奇至关重要。当前的模型往往难以适…...
深入理解Redis SDS:高性能字符串的终极设计指南
📍 文章提示 10分钟掌握Redis核心字符串设计 | 从底层结构到源码实现,揭秘SDS如何解决C字符串七大缺陷,通过20手绘图示与可运行的C代码案例,助你彻底理解二进制安全、自动扩容等核心机制,文末附实战优化技巧ÿ…...
【tcp连接windows redis】
tcp连接windows redis 修改redis.conf 修改redis.conf bind * -::*表示禁用保护模式,允许外部网络连接 protected-mode no...
【AI平台】n8n入门6:调用MCP服务(非社区节点)
前言 前边用n8n搭建一个MCP服务,现在,用n8n调用其他服务商提供的MCP服务。本文以高德地图服务为例,记录一下操作过程。 实现案例功能 MCP是啥 MCP(Model Context Protocol,模型上下文协议)是由Anthropi…...
C++负载均衡远程调用学习之 Dns-Route关系构建
目录 1.LARS-DNS-MYSQL环境搭建 2.LARSDNS-系统整体模块的简单说明 3.Lars-Dns-功能说明 4.Lars-Dns-数据表的创建 5.Lars-Dns-整体功能说明 6.Lars-DnsV0.1-Route类的单例实现 7.Lars-DnsV0.1-Route类的链接数据库方法实现 8.Lars-DnsV0.1-定义存放RouteData关系的map数…...
Linux53 百度网盘运行(下载devtoolset11后仍提示stdc++3.0.29缺失 计划用docker容器隔离运行,计划后续再看)
算了 放弃 都用到docker了 计划先看看系统服务后续再研究吧 百度网盘运行(下载devtoolset11后仍提示stdc3.0.29缺失 计划用docker容器隔离运行 但是由于系统服务未扎实,计划后续再看 重新下了el7的版本 刚才已启动成功 单输入xlock不启动 切换用户也不启动 …...
ASP.NET MVC 入门与提高指南八
45. 神经形态计算与 MVC 应用性能革新 45.1 神经形态计算概念 神经形态计算是借鉴生物神经系统的结构和工作原理来设计计算系统。它模仿人脑神经元和突触的工作方式,具备低功耗、高并行性和自适应学习等特性,能在处理复杂感知和认知任务时展现出卓越的…...
Python刷题:流程控制(下)
今天刷的是PythonTip的Python 入门挑战中的题,整体难度不高,适合小白练手以及巩固知识点。下面会进行详细讲解。 每日一句 在无人问津的角落里, 默默努力的人独自发光, 孤独是他们奋斗路上的常客, 却也是成就他们的…...
【Bootstrap V4系列】学习入门教程之 组件-徽章(Badge)和面包屑导航(Breadcrumb)
Bootstrap V4系列 学习入门教程之 组件-徽章(Badge)和面包屑导航(Breadcrumb) 徽章(Badge)一、示例二、根据情境改变外观三、胶囊式徽章(Pill badges)四、链接 面包屑导航࿰…...
结合强化学习RL和SFT各自训练优势,让模型边学边练,从而平衡Zero-RL训练中的模仿和探索!!
摘要:最近在大型推理模型(LRMs)方面的进展表明,通过简单的基于规则的奖励进行强化学习(RL),可以涌现出复杂的行为,例如多步推理和自我反思。然而,现有的零强化学习&#…...
ai之paddleOCR 识别PDF python312和paddle版本冲突 GLIBCXX_3.4.30
这里写自定义目录标题 问题一**解决方案****方法 1:使用符号链接将系统库链接到 Conda 环境** **补充说明****验证修复结果** 问题二:**问题根源****解决方案****1. 确认 TensorRT 安装状态****2. 安装 TensorRT 并配置环境变量****3. 验证 TensorRT 与 …...
C++ 单例模式详解
单例模式是一种创建型设计模式,它确保一个类只有一个实例,并提供一个全局访问点来访问该实例。 概念解析 单例模式的核心思想是: 限制类的实例化次数,确保在整个应用程序中只有一个实例存在 提供对该实例的全局访问点 控制共享…...
生成器模式(Builder Pattern)
好问题!生成器模式(Builder Pattern)在现实生活和程序开发中非常常见,它适合创建**“一步一步搭建起来的复杂对象”**。 🧠 一句话定义 生成器模式(Builder Pattern)是一种将复杂对象的构建过程…...
计算机网络八股文--day4 --传输层TCP与UDP
这是面试中最常考到的一层:端到端(也就是进程之间)的透明数据传输服务,差错控制和流量控制 该层呈上启下,像上面的资源子网提高服务,并使用下面通信子网的服务 端口,用于唯一标识主机上进程的&…...
大型语言模型个性化助手实现
大型语言模型个性化助手实现 目录 大型语言模型个性化助手实现PERSONAMEM,以及用户资料和对话模拟管道7种原位用户查询类型关于大语言模型个性化能力评估的研究大型语言模型(LLMs)已经成为用户在各种任务中的个性化助手,从提供写作支持到提供量身定制的建议或咨询。随着时间…...
步进电机中断函数解释
STM32 motor111.c 中 HAL_TIM_PeriodElapsedCallback 函数逐行解释 下面我们对 STM32 项目中 motor111.c 文件里的 HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) 函数进行逐行解析,帮助初学者理解每一行代码的作用。此函数是在定时器产生更新中断时被调…...
多把锁以及线程死锁问题
在 Java 中,每一个对象都可以作为一把锁,synchronized 通过获取对象头中的锁标志位来实现同步。当一个线程获取到对象的锁后,其他线程就无法再获取该锁,只能等待获取到锁的线程释放锁之后才能继续执行被 synchronized 修饰的代码块…...
Vue 3 Element Plus 浏览器使用例子
Element Plus 是一个基于 Vue 3 的流行开源 UI 库,提供了一系列的组件,帮助开发者快速构建现代化的用户界面。它的设计简洁、现代,包含了许多可定制的组件,如按钮、表格、表单、对话框等,适合用于开发各种 Web 应用。 …...
NoxLucky:个性化动态桌面,打造独一无二的手机体验
在数字时代,手机桌面的个性化设置已经成为许多人表达自我和展示个性的重要方式。今天,我们要介绍的 NoxLucky,就是这样一款功能强大的动态桌面手机应用。它不仅提供了独家的动态壁纸素材库,还支持将抖音、INS等平台的短视频直接设…...
如何在WORD WPS中输入英语音标 批量给英语标注音标
在我国,英语的学习,已经是贯穿小学到大学的课程,英语学习,关键是听说读写,而听说读,都离不开一个字--音,这就涉及到了英语的音标了。音标(Phonetics)是表示单词发音的一种…...
RUST变量学习笔记
1,作用域概念 捕获环境 2,所有权概念 Rust则是通过所有权和借用来保证内存安全。很多人不理解为啥说Rust是内存安全的,其实就是在默认情况下,你是写不出内存不安全的代码的。 Rust的所有权并不难理解,它有且只有如下…...
n8n工作流自动化平台的实操:本地化高级部署
一、本地高级部署 1.下载 docker pull docker.n8n.io/n8nio/n8n 2.运行 docker volume create n8n_data docker run -dit --name n8n -p 5678:5678 -v n8n_data:/home/node/.n8n -e N8N_SECURE_COOKIEfalse -e N8N_RUNNERS_ENABLEDtrue -e N8N_ENFORCE_SETTINGS_FIL…...
【Ansible自动化运维实战:从Playbook到负载均衡指南】
本文是「VagrantVirtualBox虚拟化环境搭建」的续篇,深入探索Ansible在自动化运维中的核心应用: ✅ Ansible核心技能:Playbook编写、角色(Roles)模块化、标签(Tags)精准控制 ✅ 实战场景覆盖&a…...
数据赋能(210)——质量管理——可靠性原则
概述 数据可靠性原则确保数据的准确性、完整性、一致性和可信性,是决策和业务活动对数据质量的基本要求。在信息化和数字化快速发展的今天,数据已成为企业的重要资产,数据可靠性直接影响到企业的决策质量和业务活动效果。数据可靠性是数据质…...
二、机器学习中Python变量基础
二、Python变量基础 像C语言和Matlab一样,变量名由字母、数字、下划线组成(但不能以数字开头,字母区分大小写)变量名不能与内置的函数同名。 根据变量是否可以充当容器,将变量类型分为基本类型和高级类型。 基本变量…...
有机玻璃材质数据采集活性炭吸附气体中二氧化硫实验装置
JGQ112Ⅱ有机玻璃材质数据采集活性炭吸附气体中二氧化硫实验装置 一.实验目的 1.熟悉活性炭吸附剂的特性和在SO2气体净化方面的应用。 2.掌握活性炭吸附法的流程和实验过程中各参数的控制方法。 3.了解主要参数变化对吸附效率的影响。 4.掌握吸附等温线概念和测定方法。 二.技术…...
Javase 基础入门 —— 07 接口
本系列为笔者学习Javase的课堂笔记,视频资源为B站黑马程序员出品的《黑马程序员JavaAI智能辅助编程全套视频教程,java零基础入门到大牛一套通关》,章节分布参考视频教程,为同样学习Javase系列课程的同学们提供参考。 01 概述 接…...
LangChain:重构大语言模型应用开发的范式革命
2022年10月22日,Harrison Chase在GitHub上提交了名为LangChain的开源项目的第一个代码版本。这个看似普通的代码提交,却悄然开启了一场重塑大语言模型(LLM)应用开发范式的技术革命。彼时,距离ChatGPT引爆全球人工智能浪…...
【现代深度学习技术】现代循环神经网络04:双向循环神经网络
【作者主页】Francek Chen 【专栏介绍】 ⌈ ⌈ ⌈PyTorch深度学习 ⌋ ⌋ ⌋ 深度学习 (DL, Deep Learning) 特指基于深层神经网络模型和方法的机器学习。它是在统计机器学习、人工神经网络等算法模型基础上,结合当代大数据和大算力的发展而发展出来的。深度学习最重…...
重塑数学边界:人工智能如何引领数学研究的新纪元
目录 一、人工智能如何重新定义数学研究的边界 (一)数学与AI的关系:从基础理论到创新思维的回馈 (二)AI的创造力:突破传统推理的局限 (三)AI对数学研究的潜在贡献:创…...
链表的回文结构题解
首先阅读题目: 1.要保证是回文结构 2.他的时间复杂度为O(n)、空间复杂度为O(1) 给出思路: 1.首先利用一个函数找到中间节点 2.利用一个函数逆置中间节点往后的所有节点 3.现在有两个链表,第一个链表取头节点一直到中间节点、第二个链表取头结点到尾…...
xLua笔记
Generate Code干了什么 肉眼可见的,在Asset文件夹生成了XLua/Gen文件夹,里面有一些脚本。然后对加了[CSharpCallLua]的变量寻找引用,发现它被XLua/Gen/DelegatesGensBridge引用了。也可以在这里查哪些类型加了[CSharpCallLua]。 public over…...
【Hive入门】Hive与Spark SQL深度集成:通过Spark ThriftServer高效查询Hive表
目录 引言 1 Spark ThriftServer架构解析 1.1 核心组件与工作原理 1.2 与传统HiveServer2的对比 2 Spark ThriftServer部署指南 2.1 环境准备与启动流程 2.1.1 前置条件检查 2.1.2 服务启动流程 2.2 高可用部署方案 2.2.1 基于ZooKeeper的HA架构 3 性能优化实战 3.…...
快速掌握--cursor
Cursor - The AI Code Editor 官网下载安装 详细教程:cursor 下载安装使用(保姆教程)_cursor下载-CSDN博客 不知道为啥,第一次给我用的是繁体回答 然后改了一下询问方式 codebase就是告诉ai可以从整个项目中找答案࿰…...
Linux之基础开发工具(yum,vim,gcc,g++)
目录 一、软件包管理器 1.1、什么是软件包 1.2、yum具体操作 1.2.1、查看软件包 1.2.2、安装软件 1.2.3、卸载软件 1.2.4、安装源 二、编辑器vim 2.1、vim的基本概念 2.2、vim的基本操作 2.3、vim正常模式命令集 2.4、vim末行模式命令集 2.5、替换模式 2.6、视图…...
【计算机视觉】三维重建: OpenMVS:工业级多视图立体视觉重建框架
深度解析OpenMVS:工业级多视图立体视觉重建框架 技术架构与核心算法1. 系统架构设计2. 核心算法解析稠密点云重建表面重建网格优化 实战全流程指南环境配置硬件要求编译安装(Ubuntu) 数据处理流程输入准备(OpenMVG输出)…...
C++负载均衡远程调用学习之异步消息任务功能与连接属性
目录 1.LarV0.11-异步消息机制的event_loop增添属性分析 2.LARS 3.LarV0.11异步消息发送机制的实现及测试 4.LarV0.11异步消息任务机制bug修复和效果演示 5.LarV0.12链接参数属性的绑定 1.LarV0.11-异步消息机制的event_loop增添属性分析 ## 4) 事件触发event_loop …...
内存性能测试方法
写于 2022 年 6 月 24 日 内存性能测试方法 - Wesley’s Blog dd方法测试 cat proc/meminfo console:/ # cat proc/meminfo MemTotal: 3858576 kB MemFree: 675328 kB MemAvailable: 1142452 kB Buffers: 65280 kB Cached: 992252 …...
游戏引擎学习第256天:XBox 控制器卡顿和修复 GL Blit 伽玛问题
回顾并为今天定下基调 今天的主要任务是让我们的性能分析工具正常工作,因为昨天已经完成了结构性工作。现在,剩下的工作大部分应该是调试和美化。性能分析工具现在应该已经基本可用了。昨天我们在这个方面取得了很大的进展。 接下来,我们将…...
4.29-4.30 Maven+单元测试
单元测试: BeforeAll在所有的单元测试方法运行之前,运行一次。 AfterAll在所有单元测试方法运行之后,运行一次。 BeforeEach在每个单元测试方法运行之前,都会运行一次 AfterEach在每个单元测试方法运行之后,都会运行…...
Android 端如何监控 ANR、Crash、OOM 等严重问题
在移动互联网时代,Android 应用已经成为我们生活中不可或缺的一部分。从社交聊天到在线购物,从娱乐消遣到办公学习,几乎每个人的手机里都装满了各式各样的应用。然而,作为开发者,咱们得面对一个残酷的现实:…...
Spring Boot 微服务打包为 Docker 镜像并部署到镜像仓库实战案例
案例项目素材可以拉取我github上的: https://github.com/AcademicTECHNERD/SpringCoudEurekaDemo 下面的案例将把我的product-service(也就是提供者)打包为镜像 执行maven命令: mvn clean package -DskipTests在根目录加一个dock…...
springAop代理责任链模式源码解析
目录 两次匹配 Bean 后置处理器中的匹配 方法调用时的匹配 Bean后置处理器中Advisor匹配流程 方法调用时的匹配 Jdk cglib 小小总结 Advisor 收集与排序 责任链执行过程 两次匹配 Bean 后置处理器中的匹配 在 Bean 初始化过程中,Spring 会通过 Bean 后置…...
ElasticSearch深入解析(九):Object、Nested、Flattened类型
文章目录 一、Object 类型:默认的嵌套对象处理方式核心原理典型场景关键限制 二、Nested 类型:解决嵌套数组的关联查询核心原理典型场景使用示例注意事项 三、Join 类型:跨文档的父子关联核心原理典型场景使用示例注意事项 四、Flattened 类型…...
list的迭代器详讲
1.list的迭代器就是封装了节点指针的类 2.迭代器失效 迭代器失效即迭代器封装的节点指针无效 。因为 list 的底层结构为带头结点的双向循环链表 ,因此 在 list 中进行插入时是不会导致 list 的迭代 器失效的,只有在删除时才会失效,并且失效的…...