(三)RabbitMQ七种模式介绍与代码演示

news/2024/7/24 13:29:36/

Lison <dreamlison@163.com>, v1.0.0, 2023.06.22

七种模式介绍与代码演示

文章目录

  • 七种模式介绍与代码演示
    • 四大交换机
      • 四种交换机介绍
    • 工作模式
      • 简单模式(Hello World)
      • 工作队列模式(Work queues)
      • 订阅模式(Publish/Subscribe)
      • 路由模式(Routing)
      • 主题模式(Topics)
      • 远程过程调用(RPC)
      • 发布者确认(Publisher Confirms)
    • 代码演示
      • 简单模式
      • 工作队列模式
      • 发布订阅模式
      • 路由模式
      • 主题模式
    • SpringBoot整合RabbitMQ
      • 引入依赖基础配置
      • 生产者
      • 消费者

四大交换机

交换机概念

  • 交换机可以理解成具有路由表的路由程序,仅此而已。每个消息都有一个称为路由键(routing key)的属性,就是一个简单的字符串。
  • 最新版本的RabbitMQ有四种交换机类型,分别是Direct exchange、Fanout exchange、Topic exchange、Headers exchange。
  • 交换机的作用: 生产者向broker(rabbitmq服务器)发送消息,交换机通过生产者绑定的路由键,将消息推送到不同的消息队列中。而消费者,只绑定队列,从队列中获取消息。
  • 以上三种类型的发送精准顺序为:点对点类型 > 通配符类型 > 广播类型

四种交换机介绍

  • 直连交换机(Direct exchange): 具有路由功能的交换机,绑定到此交换机的时候需要指定一个routing_key,交换机发送消息的时候需要routing_key,会将消息发送道对应的队列
  • 扇形交换机(Fanout exchange): 广播消息到所有队列,没有任何处理,速度最快
  • 主题交换机(Topic exchange): 在直连交换机基础上增加模式匹配,也就是对routing_key进行模式匹配,*代表一个单词,#代表多个单词
  • 首部交换机(Headers exchange): 忽略routing_key,使用Headers信息(一个Hash的数据结构)进行匹配,优势在于可以有更多更灵活的匹配规则

交换机参数

  1. name: 交换机名称
  2. type: 交换机类型 direct,topic,fanout,headers
  3. durability: 是否需要持久化,true 为持久化
  4. auto delete: 当最后一个绑定到 Exchange 上的队列被删除后,Exchange 就没有绑定的队列了,自动删除该 Exchange
  5. internal: 当前 Exchange 是否为内部交换机,默认为 false,客户端无法直接发送消息到这个交换机中,只能通过交换机路由到交换机这种方式
  6. arguments: 扩展参数,用于扩展 AMQP 协议自制定化使用

工作模式

简单模式(Hello World)

在这里插入图片描述

做最简单的事情,一个生产者对应一个消费者,RabbitMQ相当于一个消息代理,负责将A的消息转发给B

应用场景: 将发送的电子邮件放到消息队列,然后邮件服务在队列中获取邮件并发送给收件人

工作队列模式(Work queues)

在这里插入图片描述

在多个消费者之间分配任务(竞争的消费者模式),一个生产者对应多个消费者,一般适用于执行资源密集型任务,单个消费者处理不过来,需要多个消费者进行处理

应用场景: 一个订单的处理需要10s,有多个订单可以同时放到消息队列,然后让多个消费者同时处理,这样就是并行了,而不是单个消费者的串行情况

订阅模式(Publish/Subscribe)

在这里插入图片描述

一次向许多消费者发送消息,一个生产者发送的消息会被多个消费者获取,也就是将消息将广播到所有的消费者中。

应用场景: 更新商品库存后需要通知多个缓存和多个数据库,这里的结构应该是:

  • 一个fanout类型交换机扇出两个个消息队列,分别为缓存消息队列、数据库消息队列
  • 一个缓存消息队列对应着多个缓存消费者
  • 一个数据库消息队列对应着多个数据库消费者

路由模式(Routing)

在这里插入图片描述

有选择地(Routing key)接收消息,发送消息到交换机并且要指定路由key ,消费者将队列绑定到交换机时需要指定路由key,仅消费指定路由key的消息

应用场景: 如在商品库存中增加了1台iphone12,iphone12促销活动消费者指定routing key为iphone12,只有此促销活动会接收到消息,其它促销活动不关心也不会消费此routing key的消息

主题模式(Topics)

在这里插入图片描述

根据主题(Topics)来接收消息,将路由key和某模式进行匹配,此时队列需要绑定在一个模式上,#匹配一个词或多个词,*只匹配一个词。

应用场景: 同上,iphone促销活动可以接收主题为iphone的消息,如iphone12、iphone13等

远程过程调用(RPC)

在这里插入图片描述

如果我们需要在远程计算机上运行功能并等待结果就可以使用RPC,具体流程可以看图。应用场景:需要等待接口返回数据,如订单支付

发布者确认(Publisher Confirms)

与发布者进行可靠的发布确认,发布者确认是RabbitMQ扩展,可以实现可靠的发布。在通道上启用发布者确认后,RabbitMQ将异步确认发送者发布的消息,这意味着它们已在服务器端处理。

应用场景: 对于消息可靠性要求较高,比如钱包扣款

代码演示

代码中没有对后面两种模式演示,有兴趣可以自己研究

简单模式

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;import java.io.IOException;
import java.util.concurrent.TimeoutException;public class SimpleQueueSender {private final static String QUEUE_NAME = "simple_queue";public static void main(String[] args) throws IOException, TimeoutException {ConnectionFactory factory = new ConnectionFactory();factory.setHost("127.0.0.1");factory.setPort(5672);factory.setUsername("admin");factory.setPassword("123456");Connection connection = factory.newConnection();Channel channel = connection.createChannel();// 声明队列// queue:队列名// durable:是否持久化// exclusive:是否排外  即只允许该channel访问该队列   一般等于true的话用于一个队列只能有一个消费者来消费的场景// autoDelete:是否自动删除  消费完删除// arguments:其他属性channel.queueDeclare(QUEUE_NAME, false, false, false, null);//消息内容String message = "simplest mode message";channel.basicPublish("", QUEUE_NAME, null, message.getBytes());System.out.println("[x]Sent '" + message + "'");//最后关闭通关和连接channel.close();connection.close();}
}
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.DeliverCallback;import java.io.IOException;
import java.util.concurrent.TimeoutException;public class SimpleQueueReceiver {private final static String QUEUE_NAME = "simple_queue";public static void main(String[] args) throws IOException, InterruptedException, TimeoutException {// 获取连接ConnectionFactory factory = new ConnectionFactory();factory.setHost("localhost");factory.setPort(5672);factory.setUsername("admin");factory.setPassword("123456");Connection connection = factory.newConnection();Channel channel = connection.createChannel();channel.queueDeclare(QUEUE_NAME, false, false, false, null);DeliverCallback deliverCallback = (consumerTag, delivery) -> {String message = new String(delivery.getBody(), "UTF-8");System.out.println(" [x] Received  '" +delivery.getEnvelope().getRoutingKey() + "':'" + message + "'");};channel.basicConsume(QUEUE_NAME, true, deliverCallback, consumerTag -> {});System.out.println("----");}
}

工作队列模式

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.DeliverCallback;import java.io.IOException;
import java.util.concurrent.TimeoutException;public class QueueWorkReceiver1 {private final static String QUEUE_NAME = "queue_work";public static void main(String[] args) throws IOException, InterruptedException, TimeoutException {// 获取连接ConnectionFactory factory = new ConnectionFactory();factory.setHost("localhost");factory.setPort(5672);factory.setUsername("admin");factory.setPassword("123456");Connection connection = factory.newConnection();Channel channel = connection.createChannel();channel.queueDeclare(QUEUE_NAME, false, false, false, null);// 同一时刻服务器只会发送一条消息给消费者channel.basicQos(1);DeliverCallback deliverCallback = (consumerTag, delivery) -> {String message = new String(delivery.getBody(), "UTF-8");System.out.println(" [x] Received '" +delivery.getEnvelope().getRoutingKey() + "':'" + message + "'");};channel.basicConsume(QUEUE_NAME, true, deliverCallback, consumerTag -> {});}
}
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.DeliverCallback;import java.io.IOException;
import java.util.concurrent.TimeoutException;public class QueueWorkReceiver2 {private final static String QUEUE_NAME = "queue_work";public static void main(String[] args) throws IOException, InterruptedException, TimeoutException {// 获取连接ConnectionFactory factory = new ConnectionFactory();factory.setHost("localhost");factory.setPort(5672);factory.setUsername("admin");factory.setPassword("123456");Connection connection = factory.newConnection();Channel channel = connection.createChannel();channel.queueDeclare(QUEUE_NAME, false, false, false, null);// 同一时刻服务器只会发送一条消息给消费者channel.basicQos(1);DeliverCallback deliverCallback = (consumerTag, delivery) -> {String message = new String(delivery.getBody(), "UTF-8");System.out.println(" [x] Received '" +delivery.getEnvelope().getRoutingKey() + "':'" + message + "'");};channel.basicConsume(QUEUE_NAME, true, deliverCallback, consumerTag -> {});}
}
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;import java.io.IOException;
import java.util.concurrent.TimeoutException;public class QueueWorkSender {private final static String QUEUE_NAME = "queue_work";public static void main(String[] args) throws IOException, InterruptedException, TimeoutException {ConnectionFactory factory = new ConnectionFactory();factory.setHost("localhost");factory.setPort(5672);factory.setUsername("admin");factory.setPassword("123456");Connection connection = factory.newConnection();Channel channel = connection.createChannel();// 声明队列channel.queueDeclare(QUEUE_NAME, false, false, false, null);for (int i = 0; i < 100; i++) {String message = "work mode message" + i;channel.basicPublish("", QUEUE_NAME, null, message.getBytes());System.out.println("[x] Sent '" + message + "'");Thread.sleep(i * 10);}channel.close();connection.close();}
}

发布订阅模式

package com.lison.upgrade.middleware.rabbitmq;import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.DeliverCallback;public class PublishSubscribeReceive1 {private static final String EXCHANGE_NAME = "logs";public static void main(String[] argv) throws Exception {ConnectionFactory factory = new ConnectionFactory();factory.setHost("localhost");factory.setPort(5672);factory.setUsername("admin");factory.setPassword("123456");Connection connection = factory.newConnection();Channel channel = connection.createChannel();channel.exchangeDeclare(EXCHANGE_NAME, "fanout");String queueName = channel.queueDeclare().getQueue();channel.queueBind(queueName, EXCHANGE_NAME, "");System.out.println(" [*] Waiting for messages. To exit press CTRL+C");// 订阅消息的回调函数DeliverCallback deliverCallback = (consumerTag, delivery) -> {String message = new String(delivery.getBody(), "UTF-8");System.out.println(" [x] Received '" + message + "'");};// 消费者,有消息时出发订阅回调函数channel.basicConsume(queueName, true, deliverCallback, consumerTag -> {});}
}
package com.lison.upgrade.middleware.rabbitmq;import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.DeliverCallback;public class PublishSubscribeReceive2 {private static final String EXCHANGE_NAME = "logs";public static void main(String[] argv) throws Exception {ConnectionFactory factory = new ConnectionFactory();factory.setHost("localhost");factory.setPort(5672);factory.setUsername("admin");factory.setPassword("123456");Connection connection = factory.newConnection();Channel channel = connection.createChannel();channel.exchangeDeclare(EXCHANGE_NAME, "fanout");String queueName = channel.queueDeclare().getQueue();channel.queueBind(queueName, EXCHANGE_NAME, "");System.out.println(" [*] Waiting for messages. To exit press CTRL+C");// 订阅消息的回调函数DeliverCallback deliverCallback = (consumerTag, delivery) -> {String message = new String(delivery.getBody(), "UTF-8");System.out.println(" [x] Received2 '" + message + "'");};// 消费者,有消息时出发订阅回调函数channel.basicConsume(queueName, true, deliverCallback, consumerTag -> {});}
}
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;public class PublishSubscribeSender {private static final String EXCHANGE_NAME = "logs";public static void main(String[] argv) throws Exception {ConnectionFactory factory = new ConnectionFactory();factory.setHost("localhost");factory.setPort(5672);factory.setUsername("admin");factory.setPassword("123456");Connection connection = factory.newConnection();Channel channel = connection.createChannel();channel.exchangeDeclare(EXCHANGE_NAME, "fanout");String message = "publish subscribe message";channel.basicPublish(EXCHANGE_NAME, "", null, message.getBytes("UTF-8"));System.out.println(" [x] Sent '" + message + "'");channel.close();connection.close();}
}

路由模式

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.DeliverCallback;import java.io.IOException;
import java.util.concurrent.TimeoutException;public class QueueRoutingReceiver1 {private final static String QUEUE_NAME = "queue_routing";private final static String EXCHANGE_NAME = "exchange_direct";public static void main(String[] args) throws IOException, TimeoutException {ConnectionFactory factory = new ConnectionFactory();factory.setHost("localhost");factory.setPort(5672);factory.setUsername("admin");factory.setPassword("123456");Connection connection = factory.newConnection();Channel channel = connection.createChannel();channel.queueDeclare(QUEUE_NAME, false, false, false, null);// 指定路由的key,接收key和key2channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "key");channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "key2");channel.basicQos(1);DeliverCallback deliverCallback = (consumerTag, delivery) -> {String message = new String(delivery.getBody(), "UTF-8");System.out.println(" [x] Received '" +delivery.getEnvelope().getRoutingKey() + "':'" + message + "'");};channel.basicConsume(QUEUE_NAME, true, deliverCallback, consumerTag -> {});}}
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.DeliverCallback;import java.io.IOException;
import java.util.concurrent.TimeoutException;public class QueueRoutingReceiver2 {private final static String QUEUE_NAME = "queue_routing2";private final static String EXCHANGE_NAME = "exchange_direct";public static void main(String[] args) throws IOException, TimeoutException {ConnectionFactory factory = new ConnectionFactory();factory.setHost("localhost");factory.setPort(5672);factory.setUsername("admin");factory.setPassword("123456");Connection connection = factory.newConnection();Channel channel = connection.createChannel();channel.queueDeclare(QUEUE_NAME, false, false, false, null);// 仅接收key2channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "key2");channel.basicQos(1);DeliverCallback deliverCallback = (consumerTag, delivery) -> {String message = new String(delivery.getBody(), "UTF-8");System.out.println(" [x] Received '" +delivery.getEnvelope().getRoutingKey() + "':'" + message + "'");};channel.basicConsume(QUEUE_NAME, true, deliverCallback, consumerTag -> {});}
}
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;import java.io.IOException;
import java.util.concurrent.TimeoutException;public class QueueRoutingSender {private final static String EXCHANGE_NAME = "exchange_direct";private final static String EXCHANGE_TYPE = "direct";public static void main(String[] args) throws IOException, TimeoutException {ConnectionFactory factory = new ConnectionFactory();factory.setHost("localhost");factory.setPort(5672);factory.setUsername("admin");factory.setPassword("123456");Connection connection = factory.newConnection();Channel channel = connection.createChannel();// 交换机声明channel.exchangeDeclare(EXCHANGE_NAME, EXCHANGE_TYPE);// 只有routingKey相同的才会消费String message = "routing mode message";channel.basicPublish(EXCHANGE_NAME, "key2", null, message.getBytes());System.out.println("[x] Sent '" + message + "'");
//        channel.basicPublish(EXCHANGE_NAME, "key", null, message.getBytes());
//        System.out.println("[x] Sent '" + message + "'");channel.close();connection.close();}
}

主题模式

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.DeliverCallback;import java.io.IOException;
import java.util.concurrent.TimeoutException;public class Receiver1 {private final static String QUEUE_NAME = "queue_topic";private final static String EXCHANGE_NAME = "exchange_topic";public static void main(String[] args) throws IOException, InterruptedException, TimeoutException {ConnectionFactory factory = new ConnectionFactory();factory.setHost("localhost");factory.setPort(5672);Connection connection = factory.newConnection();Channel channel = connection.createChannel();channel.queueDeclare(QUEUE_NAME, false, false, false, null);// 可以接收key.1channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "key.*");channel.basicQos(1);DeliverCallback deliverCallback = (consumerTag, delivery) -> {String message = new String(delivery.getBody(), "UTF-8");System.out.println(" [x] Received '" +delivery.getEnvelope().getRoutingKey() + "':'" + message + "'");};channel.basicConsume(QUEUE_NAME, true, deliverCallback, consumerTag -> {});}
}
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.DeliverCallback;import java.io.IOException;
import java.util.concurrent.TimeoutException;public class Receiver2 {private final static String QUEUE_NAME = "queue_topic2";private final static String EXCHANGE_NAME = "exchange_topic";private final static String EXCHANGE_TYPE = "topic";public static void main(String[] args) throws IOException, InterruptedException, TimeoutException {ConnectionFactory factory = new ConnectionFactory();factory.setHost("localhost");factory.setPort(5672);Connection connection = factory.newConnection();Channel channel = connection.createChannel();channel.queueDeclare(QUEUE_NAME, false, false, false, null);// *号代表单个单词,可以接收key.1channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "*.*");// #号代表多个单词,可以接收key.1.2channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "*.#");channel.basicQos(1);DeliverCallback deliverCallback = (consumerTag, delivery) -> {String message = new String(delivery.getBody(), "UTF-8");System.out.println(" [x] Received '" +delivery.getEnvelope().getRoutingKey() + "':'" + message + "'");};channel.basicConsume(QUEUE_NAME, true, deliverCallback, consumerTag -> {});}
}
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;import java.io.IOException;
import java.util.concurrent.TimeoutException;public class Sender {private final static String EXCHANGE_NAME = "exchange_topic";private final static String EXCHANGE_TYPE = "topic";public static void main(String[] args) throws IOException, TimeoutException {ConnectionFactory factory = new ConnectionFactory();factory.setHost("localhost");factory.setPort(5672);Connection connection = factory.newConnection();Channel channel = connection.createChannel();channel.exchangeDeclare(EXCHANGE_NAME, EXCHANGE_TYPE);String message = "topics model message with key.1";channel.basicPublish(EXCHANGE_NAME, "key.1", null, message.getBytes());System.out.println("[x] Sent '" + message + "'");String message2 = "topics model message with key.1.2";channel.basicPublish(EXCHANGE_NAME, "key.1.2", null, message2.getBytes());System.out.println("[x] Sent '" + message2 + "'");channel.close();connection.close();}
}

SpringBoot整合RabbitMQ

引入依赖基础配置

1、创建SpringBoot项目,引入RabbitMQ起步依赖

<!-- RabbitMQ起步依赖 -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId>
</dependency>

2、写配置文件

spring:rabbitmq:host: 127.0.0.1port: 5672username: adminpassword: 123456virtual-host: /
#日志格式
logging:pattern:console: '%d{HH:mm:ss.SSS} %clr(%-5level) --- [%-15thread] %cyan(%-50logger{50}):%msg%n'

SpringBoot整合RabbitMQ时,需要在配置类创建队列和交换机,写法如下:

@Configuration
public class RabbitConfig {private final String EXCHANGE_NAME = "boot_topic_exchange";private final String QUEUE_NAME = "boot_queue";// 创建交换机@Bean("bootExchange")public Exchange getExchange() {return ExchangeBuilder.topicExchange(EXCHANGE_NAME) // 交换机类型.durable(true) // 是否持久化.build();}// 创建队列@Bean("bootQueue")public Queue getMessageQueue() {return new Queue(QUEUE_NAME); // 队列名}// 交换机绑定队列@Beanpublic Binding bindMessageQueue(@Qualifier("bootExchange") Exchange exchange, @Qualifier("bootQueue") Queue queue) {return BindingBuilder.bind(queue).to(exchange).with("#.message.#").noargs();}
}

生产者

SpringBoot整合RabbitMQ时,提供了工具类RabbitTemplate发送消息,编写生产者时只需要注入RabbitTemplate即可发送消息。

@SpringBootTest
public class TestProducer {// 注入RabbitTemplate工具类@Autowiredprivate RabbitTemplate rabbitTemplate;@Testpublic void testSendMessage(){/*** 发送消息* 参数1:交换机* 参数2:路由key* 参数3:要发送的消息*/rabbitTemplate.convertAndSend("boot_topic_exchange","message","这个是生产者发送消息!");}
}

在这里插入图片描述

消费者

@Component
public class Consumer {// 监听队列@RabbitListener(queues = "boot_queue")public void listen_message(String message){System.out.println("发送短信:"+message);}
}

启动项目,可以看到消费者会消费队列中的消息


http://www.ppmy.cn/news/979683.html

相关文章

【JavaScript】阻止表单的默认提交行为

表单的默认提交行为是指在用户提交表单时&#xff0c;浏览器会自动将表单数据发送到服务器&#xff0c;并根据表单中的 action 属性和 method 属性来执行相应的操作。默认情况下&#xff0c;表单提交后会导致浏览器刷新页面或导航到 action 属性指定的页面&#xff0c;并且页面…

记负均正 C语言实现

记负均正 描述 首先输入要输入的整数个数n&#xff0c;然后输入n个整数。输出为n个整数中负数的个数&#xff0c;和所有正整数的平均值&#xff0c;结果保留一位小数。 0即不是正整数&#xff0c;也不是负数&#xff0c;不计入计算。如果没有正数&#xff0c;则平均值为0。 数…

如何把pdf转成word文档格式?分享三个好用方法!

PDF文件和Word文档是我们日常生活和工作中最常见的两种文档格式。尽管PDF以其稳定的格式和出色的跨平台兼容性受到人们的喜爱&#xff0c;但在文本编辑方面&#xff0c;Word文档更具有灵活性。因此&#xff0c;将PDF转换为Word文档的需求在我们日常生活中非常常见。这篇文章将为…

vue三级路由的写法

{path: "/trafficmanagement",component: Layout,redirect: "/trafficmanagement",alwaysShow: true,meta: {title: "通行模块",icon: "excel",},children: [{path: "carline",name: "carline",alwaysShow: true,…

为什么a标签无法下载,无法重命名?

《1》a 标签的 href 有很大的关系&#xff0c; href 属性的地址必须是 同源 URL&#xff0c;否则&#xff0c;download 就会不起作用。 1. 同源 URL 会进行 下载 操作 2. 非同源 URL 会进行 导航 操作 3. 非同源的资源 仍需要进行下载&#xff0c;那么可以将其转换为 blob: UR…

【LangChain】检索器之上下文压缩

LangChain学习文档 【LangChain】检索器(Retrievers)【LangChain】检索器之MultiQueryRetriever【LangChain】检索器之上下文压缩 上下文压缩 LangChain学习文档 概要内容使用普通向量存储检索器使用 LLMChainExtractor 添加上下文压缩(Adding contextual compression with an…

SQL中Partition的相关用法

使用Partition可以根据指定的列或表达式将数据分成多个分区。每个分区都是逻辑上独立的&#xff0c;可以单独进行查询、插入、更新和删除操作。Partition可以提高查询性能&#xff0c;因为它可以限制在特定分区上执行查询&#xff0c;而不是在整个表上执行。 在SQL中&#xff…

redis面试1

Redis基础面试题 1、为什么要使用Redis做缓存 缓存的好处 使用缓存的目的就是提升读写性能。而实际业务场景下&#xff0c;更多的是为了提升读性能&#xff0c;带来更好的性 能&#xff0c;带来更高的并发量。Redis 的读写性能比 Mysql 好的多&#xff0c;我们就可以把 Mysq…

PHP关于字符串的各类处理方法

判断字符串是否以指定子串开头或结尾 function startsWith($str, $prefix) {return stripos($str, $prefix) 0; }function endsWith($str, $suffix) {return substr_compare($str, $suffix, -strlen($suffix)) 0; }// 示例用法 $text "hello world"; $result st…

【N32L40X】学习笔记03-gpio输出库

gpio输出 该函数库的目的就是在统一的地方配置&#xff0c;将配置的不同项放置在一个结构体内部使用一个枚举来定义一个的别名 led.c #include <stdio.h> #include "led/bsp_led.h"static led_t leds[LED_NUM]{{GPIOB,GPIO_PIN_2,RCC_APB2_PERIPH_GPIOB},{GP…

3秒快速打开 jupyter notebook

利用 bat 脚本&#xff0c;实现一键打开 minconda 特点&#xff1a; 1、可指定 python 环境 2、可指定 jupyter 目录 一、配置环境 minconda 可以搭建不同的 python 环境&#xff0c;所以我们需要找到 minconda 安装目录&#xff0c;把对应目录添加到电脑环境 PATH 中&#…

ADCS知识点全收录! 如何利用证书服务器对域控进行多角度攻击(上)

在2021年的BlackHat大会上&#xff0c;由Will Schroeder和Lee Christensen发布了关于Active Directory Certificate Services 利用白皮书《Certified Pre-Owned - Abusing Active Directory Certificate Services》&#xff0c;其中包含了大量的针对ADCS的攻击手法&#xff0c;…

离多态更近一步

在面向对象的语言里面,封装,继承,多态可谓是在熟悉不过了,当我们每次再去重新认识它们的时候总会有新的发现,为此我也经常感到疑惑,所以在这里和大家一起探讨三个问题,让我们在向多态靠近一点点。 虚表是否真的存在静态区 经常我们都会看见一个问题&#xff0c;虚表到底是存放…

【Redis】Redis zset 实现排行榜

文章目录 前言案例程序设计score 设计 (相同积分的排序)缓存数据定时刷新当心缓存击穿 前言 排行榜是业务开发中常见的一个场景&#xff0c;如何设计一个好的数据结构能够满足高效实时的查询&#xff0c;下面我们结合一个实际例子来讨论一下。 案例 大概需求就是: 排行榜上显…

20款奔驰S350商务型加装原厂前排座椅通风系统,夏天必备的功能

通风座椅的主动通风功能可以迅速将座椅表面温度降至适宜程度&#xff0c;从而确保最佳座椅舒适性。该功能启用后&#xff0c;车内空气透过打孔皮饰座套被吸入座椅内部&#xff0c;持续时间为 8 分钟。然后&#xff0c;风扇会自动改变旋转方向&#xff0c;将更凉爽的环境空气从座…

16K个大语言模型的进化树;81个在线可玩的AI游戏;AI提示工程的终极指南;音频Transformers课程 | ShowMeAI日报

&#x1f440;日报&周刊合集 | &#x1f3a1;生产力工具与行业应用大全 | &#x1f9e1; 点赞关注评论拜托啦&#xff01; &#x1f916; LLM 进化树升级版&#xff01;清晰展示 15821 个大语言模型的关系 这张进化图来自于论文 「On the Origin of LLMs: An Evolutionary …

【C++ 进阶】继承

一.继承的定义格式 基类又叫父类&#xff0c;派生类又叫子类&#xff1b; 二.继承方式 继承方式分为三种&#xff1a; 1.public继承 2.protected继承 3.private继承 基类成员与继承方式的关系共有9种&#xff0c;见下表&#xff1a; 虽然说是有9种&#xff0c;但其实最常用的还…

无涯教程-jQuery - stopPropagation()方法函数

stopPropagation()方法停止将事件冒泡到父元素&#xff0c;从而防止任何父处理程序收到该事件的通知。 您可以使用方法 event.isPropagationStopped()来了解是否曾经在该事件对象上调用过此方法。 stopPropagation() - 语法 event.stopPropagation() stopPropagation() - …

网络安全进阶学习第七课——文件包含漏洞

文章目录 一、文件包含概念二、文件包含漏洞原理三、文件包含分类文件包含分为两种&#xff1a; 四、与文件包含相关的配置文件&#xff1a;&#xff08;php.ini文件&#xff09;五、与文件包含有关的函数1、include()2、include_once()3、require()4、require_once() 六、文件…

FCPX插件-15组金色华丽粒子特效闪耀动画 Awards Backgrounds

Awards Backgrounds是fcpx上一个很棒的电影级效果插件&#xff0c;Awards Backgrounds 包含15组金色华丽粒子特效闪耀动画&#xff0c;可以为您的作品创建豪华的背景或叠加特效&#xff01;包含各种带有可编辑颜色的下落闪闪发光粒子的场景。用于展示奖项提名者、优雅的表演、祝…