RabbitMQ-基础
RabbitMQ-基础
文章目录
- RabbitMQ-基础
- 1.同步调用
- 2.异步调用
- 3.技术选型
- 4.安装RabbitMQ(官方网址)https://www.rabbitmq.com/
- 5.快速入门
- 5.1收发消息
- 5.1.1交换机
- 5.1.2队列
- 5.1.3绑定关系
- 5.1.4发送消息
- 5.2数据隔离
- 5.2.1用户管理
- 5.2.2virtual host
- 6.Java客户端操作RabbitMQ
- 6.1快速入门
- 6.2work模型
- 6.3交换机
- 6.3.1Fanout交换机
- 6.3.2Direct交换机
- 6.3.3Topic交换机
- 6.4声明队列和交换机的方式一
- 6.5声明队列和交换机的方式二
- 6.6消息转换器
RabbitMQ是一个高性能的异步通讯组件,假如当们我实现一个登录的业务时,使用同步通讯来实现,那么效率会降低很多,如下图基于OpenFegin实现的就是同步通讯,发起的请求需要实时等待返回信息,登录的效率比较低,影响用户体验。
此时我们使用RabbitMQ即刻解决这个问题,用户完成登录校验后直接登录,并将相关信息提交至MQ,再由其他服务从MQ中获取信息完成业务,可以大大增加并发量,提升业务效率!
注意:并不是异步通讯就比同步通讯好,要根据业务情况分析选择合适的技术。
1.同步调用
这里我们举一个简单的同步调用的例子:
在支付业务当中,我们调起支付,需要实时的知道用户余额是否足够才能之下之后的逻辑。
同步调用存在哪些问题呢?
- 当我们需要在支付业务中添加新的需求,每一个新的需求都需要向支付服务返回处理结果,当需求越多阻塞等待时间越长,用户的满意度也就会极大地减少,性能下降。
- 我们会发现代码的扩展性很差,我们的核心业务时实现支付,为了新的需求要多次的修改支付服务的代码。
- 假设交易服务出现故障抛出异常,长时间得不到解决,也会导致支付服务出现问题,也就是级联失败问题。
2.异步调用
异步调用方式其实就是基于消息通知的方式,一般包含三个角色:
- 消息发送者:投递消息的人,可以理解为快递员。
- 消息代理:管理、暂存、转发消息,可以理解为菜鸟驿站。
- 消息接收者:接收和处理消息的人,可以理解为取快递的人。
这样支付服务不再同步调用关联度低的服务,而是发送消息到Broker(中间人)。
优势:
-
解除耦合,拓展性更强,支付服务只关心用户余额的扣减问题。
-
无需等待与支付服务关联度低的服务,性能提升。
-
故障隔离,假设交易服务故障,不会影响到支付服务,并且可以从消息代理中拿到消息进行业务重试。
-
缓存消息,流量削峰填谷。
当有大量消息通知进入消息代理(消息代理的容量很大),后边的服务可以根据自己的处理速度来一个一个处理。
缺点:
- 不能立即得到调用结果,时效性差。
- 不确定下游业务是否执行成功。
- 业务安全依赖于Broker的可靠性。
3.技术选型
MQ(MessageQueue),中文是消息队列,字面来看就是存放消息的队列。也就是异步调用中的Broker。
RabbitMQ | ActiveMQ | RocketMQ | Kafka | |
---|---|---|---|---|
公司/社区 | Rabbit | Apache | 阿里 | Apache |
开发语言 | Erlang | Java | Java | Scala&Java |
协议支持 | AMOP, XMPP, SMTP, STOMP | OpenMire, STOMP, REST, XMPP, AMOP | 自定义协议 | 自定义协议 |
可用性 | 高 | 一般 | 高 | 高 |
单机吞吐量 | 一般 | 差 | 高 | 非常高 |
消息延迟 | 微秒级 | 毫秒级 | 毫秒级 | 毫秒以内 |
消息可靠性 | 高 | 一般 | 高 | 一般 |
- 追求可用性:Kafka、 RocketMQ 、RabbitMQ
- 追求可靠性:RabbitMQ、RocketMQ
- 追求吞吐能力:RocketMQ、Kafka
- 追求消息低延迟:RabbitMQ、Kafka
据统计,目前国内消息队列使用最多的还是RabbitMQ,再加上其各方面都比较均衡,稳定性也好,所以学习RabbitMQ也是个不错的选择。
4.安装RabbitMQ(官方网址)https://www.rabbitmq.com/
这里安装使用的docker,拉取RabbitMQ镜像并执行以下语句:
docker run \-e RABBITMQ_DEFAULT_USER=(你的用户名) \-e RABBITMQ_DEFAULT_PASS=(你的密码) \-v mq-plugins:/plugins \--name mq \--hostname mq \-p 15672:15672 \-p 5672:5672 \--network hmall \-d \rabbitmq:3.8-management(这里用你拉取的镜像版本)
- 15672:RabbitMQ提供的管理控制台的端口
- 5672:RabbitMQ的消息发送处理接口
安装完成后,我们访问 http://你的虚拟机地址:15672即可看到管理控制台。首次访问需要登录,默认的用户名和密码在配置文件中已经指定了。
登录后即可看到管理控制台总览页面:
RabbitMQ架构:
其中包含几个概念:
publisher
:生产者,也就是发送消息的一方。consumer
:消费者,也就是消费消息的一方。queue
:队列,存储消息。生产者投递的消息会暂存在消息队列中,等待消费者处理。exchange
:交换机,负责消息路由。生产者发送的消息由交换机决定投递到哪个队列。virtual host
:虚拟主机,起到数据隔离的作用。每个虚拟主机相互独立,有各自的exchange、queue。可以理解为一个公司里做多套项目,每个项目使用一个虚拟主机实现项目隔离,但只使用一个MQ集群。
5.快速入门
5.1收发消息
5.1.1交换机
我们点击Exchanges
选项,可以看到存在许多交换机:
我们点击任意交换机进入交换机详情页面。利用控制台中的publish message 发送一条消息:
这里是由控制台模拟了生产者发送的消息。由于没有消费者存在,最终消息丢失了,这样也说明交换机没有存储消息的能力。
5.1.2队列
我们点击Queues
选项,并新建一个队列:
命名为hello.queue
:
再也同样的方式创建队列hello.queue2
,最终列表队列如下:
此时我们返回amq.fanout
交换机发送一条消息,会发现消息并没有到达队列:
这是因为我们还需要将交换机和队列进行绑定!
5.1.3绑定关系
点击Exchanges
选项卡,点击amq.fanout
交换机,进入交换机详情页,然后点击Bindings
菜单,绑定hello.queue1
和hello.queue2
:
结果如下:
5.1.4发送消息
再次回到exchange页面,找到刚刚绑定的amq.fanout
,点击进入详情页,再次发送一条消息:
回到Queues
页面,可以发现hello.queue
中已经有一条消息了:
点击队列名称,进入详情页,查看队列详情,这次点击get message:
可以看到消息到达队列了:
此时如果有消费者监听了MQ的hello.queue1
或hello.queue2
队列,就能接收到消息了。
5.2数据隔离
5.2.1用户管理
点击Admin
选项,会看到RabbitMQ控制台的用户管理界面:
这里的用户都是RabbitMQ的管理或运维人员。目前只有安装RabbitMQ时添加的root
这个用户。仔细观察用户表格中的字段,如下:
Name
:root
,也就是用户名Tags
:administrator
,说明root
用户是超级管理员,拥有所有权限Can access virtual host
:/
,可以访问的virtual host
,这里的/
是默认的virtual host
对于小型企业而言,通常只会搭建一套MQ集群,公司内的多个不同项目同时使用。为了避免互相干扰, 会利用virtual host
的隔离特性,将不同项目隔离。一般会做两件事情:
- 给每个项目创建独立的运维账号,将管理权限分离。
- 给每个项目创建不同的
virtual host
,将每个项目的数据隔离。
比如,我们创建一个新的用户,命名为Study
:
你会发现此时Study用户没有任何virtual host
的访问权限:
5.2.2virtual host
我们退出登录,并切换到创建的Study用户登录,然后点击Virtual Hosts
菜单,进入virtual host
管理页:
此时可以创建一个单独的virtual host
,而不是使用默认的/
:
创建后如下图:
由于我们是登录Study
账户后创建的virtual host
,因此回到users
菜单,你会发现当前用户已经具备了对/NewProject
这个virtual host
的访问权限了:
此时,点击页面右上角的virtual host
下拉菜单,切换virtual host
为 /NewProject
,然后再次查看queues选项卡,会发现之前的队列已经看不到了:
这就是基于virtual host
的隔离效果。
6.Java客户端操作RabbitMQ
这里我提供了一个简单的基础项目,大家可以使用项目一起进行之后的内容学习:https://pan.baidu.com/s/1w66gVO1xc6PaF2uWFEEW0g?pwd=6666
6.1快速入门
这里我们实现以下需求(创建队列这里不再演示):
-
引入依赖(提供的demo中已经引入过了)
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId> </dependency>
-
在发消息的yml文件配置mq
spring:rabbitmq:host: 你的虚拟机地址port: 5672virtual-host: /NewProject(刚刚创建的)username: Study(刚刚创建的用户名)password: 123(刚刚创建的密码)
-
发送消息
@SpringBootTest public class SpringAmpqTest {@Resourceprivate RabbitTemplate rabbitTemplate;@Testvoid testSendMessage2Queue(){String queueName="simple.queue";String msg="Hello,world!";rabbitTemplate.convertAndSend(queueName,msg);} }
发送结果:
-
接收消息
@Slf4j @Component public class MqListener {@RabbitListener(queues = "simple.queue")public void listenSimpleQueue(String msg){System.out.println("收到消息了:"+msg);} }
输出结果:
6.2work模型
我们创建一个新的work.queue
队列并让两个消费者来监听(我们希望处理快的多处理一些):
//Consumer
//这使用sleep来模拟每个消费者不同的处理能力@RabbitListener(queues = "work.queue")public void listenWorkQueue1(String msg) throws InterruptedException {System.out.println("消费者1收到消息了_:"+msg);Thread.sleep(20);}@RabbitListener(queues = "work.queue")public void listenWorkQueue2(String msg) throws InterruptedException {System.err.println("消费者2收到消息了_:"+msg);Thread.sleep(200);}
//publisher@Testvoid testSendMessageToWorkQueue(){String queueName="work.queue";String msg="Hello_";for(int i=1;i<=50;i++){rabbitTemplate.convertAndSend(queueName,msg+i);}}
结果:50个消息被平均分配,不符合预期。
默认情况下,RabbitMQ的会将消息依次轮询投递给绑定在队列上的每一个消费者。但这并没有考虑到消费者是否已经处理完消息,可能出现消息堆积。
#因此我们需要修改application.yml,设置preFetch值为1,确保同一时刻最多投递给消费者1条消息:
spring:rabbitmq:host: 你的虚拟机地址port: 5672virtual-host: /NewProjectusername:用户名password: 密码listener:simple:prefetch: 1 # 每次只能获取一条消息,处理完成才能获取下一个消息
这时重新运行会发现两个消费者处理的消息数量不同了。
总结一下:Work模型的使用
- 多个消费者绑定到一个队列,可以加快消息处理速度 。
- 同一条消息只会被一个消费者处理 。
- 通过设置prefetch来控制消费者预取的消息数量,处理完一条再处理下一条,实现能者多劳。
6.3交换机
真正生产环境都会经过exchange来发送消息,而不是直接发送到队列,交换机的类型有以下三种:
- Fanout:广播
- Direct:定向
- Topic:话题
6.3.1Fanout交换机
Fanout Exchange会将接收到的消息广播到每一个跟其绑定的queue,所以也叫广播模式。
这里使用其我们实现如下内容:
-
在RabbitMQ控制台中,声明队列fanout.queue1和fanout.queue2
-
在RabbitMQ控制台中,声明交换机study.fanout,将两个队列与其绑定
-
在consumer服务中,编写两个消费者方法,分别监听fanout.queue1和fanout.queue2
-
在publisher中编写测试方法,向study.fanout发送消息
//Consumer
@RabbitListener(queues = "fanout.queue1")
public void listenWorkQueue1(String msg) throws InterruptedException {System.out.println("消费者1收到消息了_:"+msg);
}@RabbitListener(queues = "fanout.queue2")public void listenWorkQueue2(String msg) throws InterruptedException {System.out.println("消费者2收到消息了_:"+msg);}
//Publisher@Testvoid testSendMessageToFanoutQueue(){String ExchangeName="study.fanout";String msg="Hello,EveryBody!";rabbitTemplate.convertAndSend(ExchangeName,null,msg);}
运行结果:
总结一下:交换机的作用是什么?
- 接受publisher发送的消息
- 将消息按照规则路由到与之绑定的队列
- FanoutExchange的会将消息路由到每个绑定的队列
6.3.2Direct交换机
Direct Exchange 会将接收到的消息根据规则路由到指定的Queue,因此称为定向路由。
- 每一个Queue都与Exchange设置一个BindingKey
- 发布者发送消息时,指定消息的RoutingKey
- Exchange将消息路由到BindingKey与消息RoutingKey一致的队列
//Consumer@RabbitListener(queues = "direct.queue1")public void listenDirectQueue1(String msg) throws InterruptedException {System.out.println("消费者1收到消息了_:"+msg);}@RabbitListener(queues = "direct.queue2")public void listenDirectQueue2(String msg) throws InterruptedException {System.out.println("消费者2收到消息了_:"+msg);}
//Publisher@Testvoid testDirect(){String ExchangeName="study.direct";String msg="红色警告!";rabbitTemplate.convertAndSend(ExchangeName,"red",msg);}
运行结果:
6.3.3Topic交换机
TopicExchange与DirectExchange类似,区别在于routingKey可以是多个单词的列表,并以.
分割。
例如:
- china.news 代表有中国的新闻消息;
- china.weather 代表中国的天气消息;
Queue与Exchange指定BindingKey时可以使用通配符:
- #:指代0个或多个单词
- *:代指一个单词
我们来实现以下需求:
-
在RabbitMQ控制台中,声明队列topic.queue1和topic.queue2
-
在RabbitMQ控制台中,声明交换机study.topic,将两个队列与其绑定
-
在consumer中,编写两个消费者方法,分别监听topic.queue1和topic.queue2
//Consumer@RabbitListener(queues = "topic.queue1")public void listenTopicQueue1(String msg) throws InterruptedException {System.out.println("消费者1收到消息了_:"+msg);}@RabbitListener(queues = "topic.queue2")public void listenTopicQueue2(String msg) throws InterruptedException {System.out.println("消费者2收到消息了_:"+msg);}
-
在publisher中编写测试方法,利用不同的RoutingKey向hmall.topic发送消息
//Publisher@Testvoid testTopic(){String ExchangeName="study.topic";String msg="小日子,我们中国是Numer One!!";rabbitTemplate.convertAndSend(ExchangeName,"Japan.news",msg);}
此时根据通配符匹配结果,应当只有消费者2收到消息:
6.4声明队列和交换机的方式一
SpringAMQP提供了几个类,用来声明队列、交换机及其绑定关系:
-
Queue:用于声明队列,可以用工厂类QueueBuilder构建
-
Exchange:用于声明交换机,可以用工厂类ExchangeBuilder构建 ,由于Exchange有多种类型,所以他有多种实现。
-
Binding:用于声明队列和交换机的绑定关系,可以用工厂类BindingBuilder构建
我们在Consumer中编写代码:
import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class FanoutConfiguration {
//声明fanout交换机@Beanpublic FanoutExchange fanoutExchange() {//return ExchangeBuilder.fanoutExchange("study.fanout2").build();return new FanoutExchange("study.fanout2");}
//声明队列@Beanpublic Queue fanoutQueue() {//return QueueBuilder.durable().build();return new Queue("fanout.queue3");}
//绑定队列和交换机@Beanpublic Binding fanoutBinding3() {return BindingBuilder.bind(fanoutQueue()).to(fanoutExchange());}/* @Beanpublic Binding fanoutBinding3(Queue fanoutQueue,FanoutExchange fanoutExchange) {return BindingBuilder.bind(fanoutQueue()).to(fanoutExchange());}*/
}
运行后可以看到已经成功绑定:
不过这里提一点这种方式的缺点,当我们需要Direct交换机
并进行绑定时,由于需要多个routingKey
,而bind()只能绑定一个key
,此时就需要创建多个Bean
,非常的麻烦,这里不演示,自行敲一遍感受一下。
6.5声明队列和交换机的方式二
SpringAMQP还提供了基于**@RabbitListener注解**来声明队列和交换机的方式。
//Consumer@RabbitListener(bindings=@QueueBinding(value=@Queue(name = "direct.queue1",durable="true"),exchange=@Exchange(name="study.direct",type= ExchangeTypes.DIRECT),key={"red","blue"}))public void listener1(String msg){log.info("收到消息:{}",msg);}@RabbitListener(bindings=@QueueBinding(value=@Queue(name = "direct.queue2",durable="true"),exchange=@Exchange(name="study.direct",type= ExchangeTypes.DIRECT),key={"red","yellow"}))public void listener2(String msg){log.info("收到消息:{}",msg);}
运行后会发现创建成功:
6.6消息转换器
我们创建一个新的队列并向其中发送Map类型的消息:
@Testvoid testMessageConvert(){String queueName="object.queue";Map<String,String> msg=new HashMap<>(2);msg.put("name","张三");msg.put("age","20");rabbitTemplate.convertAndSend(queueName,msg);}
运行结果查看发送的消息如下:
Spring的对消息对象的处理是由org.springframework.amqp.support.converter.MessageConverter来处理的。而默认实现是SimpleMessageConverter,基于JDK的ObjectOutputStream
完成序列化,感兴趣的可以去看源码。
不过存在下列问题:
- JDK的序列化有安全风险
- JDK序列化的消息太大
- JDK序列化的消息可读性差
建议采用JSON序列化代替默认的JDK序列化:
-
在Publisher和Consumer中引入jackson依赖
<!--Jsckson--><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId></dependency>
-
在Publisher和Consumer中都要配置MessageConverter
@Beanpublic MessageConverter jackaonMessageConvert(){return new Jackson2JsonMessageConverter();}
此时查看会发现消息正常:
相关文章:
RabbitMQ-基础
RabbitMQ-基础 文章目录 RabbitMQ-基础1.同步调用2.异步调用3.技术选型4.安装RabbitMQ(官方网址)https://www.rabbitmq.com/5.快速入门5.1收发消息5.1.1交换机5.1.2队列5.1.3绑定关系5.1.4发送消息 5.2数据隔离5.2.1用户管理5.2.2virtual host 6.Java客户端操作RabbitMQ6.1快速…...
第九周作业
安全专题笔记 1、文件上传 (1) 服务端白名单绕过 %00截断绕过要求虚拟机中搭建实验环境,分别实现GET、POST方法的绕过 前提条件: 1 php的版本需要在5.4以下 2 magic_quotes_gpc需要设置为off 启动phpstudy,前往php-ini将magic_quotes_gpc…...
AtCoder Beginner Contest 404 C-G(无F)题解
C. Cycle Graph? 题意 给你一个 N N N 个顶点 M M M 条边的简单(无重边、自环)无向图,第 i i i 条边连接节点 A i A_i Ai 和 B i B_i Bi,判断这个图是不是一个环。 思路 首先一个图是环,要满足点数等于边…...
Python----机器学习(模型评估:准确率、损失函数值、精确度、召回率、F1分数、混淆矩阵、ROC曲线和AUC值、Top-k精度)
一、模型评估 1. 准确率(Accuracy):这是最基本的评估指标之一,表示模型在测试集上正确 分类样本的比例。对于分类任务而言,准确率是衡量模型性能的直观标准。 2. 损失函数值(Loss)࿱…...
开上“Python跑的车”——自动驾驶数据可视化的落地之道
开上“Python跑的车”——自动驾驶数据可视化的落地之道 一、自动驾驶离不开“看得见”的智能 在智能汽车时代,自动驾驶已然不是“炫技”标签,而是一场技术实力的全面拉锯战。而在这场战役中,有一个极其关键但常被忽略的领域,叫做: 数据可视化(Data Visualization)。 为…...
Linux内核gcov修改为模块
Linux内核gcov修改为模块 Gcov 是 GNU 项目开发的代码覆盖率分析工具,与 GCC 编译器深度集成,用于统计程序运行时代码的执行情况,帮助开发者评估测试用例的完整性和代码质量。 Gcov工作原理 1. 编译插桩 编译时需添加 -fprofile-arcs -…...
【安装配置教程】linux部署AList记录
之前朋友安利给自己AList,这个工具可以很方便的管理个人的网盘内容,可以随时上传下载拉取,于是心血来潮自己部署并记录一下。 一、拉取下载脚本 在AList官网,找到安装下面的一键脚本 curl -fsSL "https://alist.nn.ci/v3.sh…...
题解:AT_abc245_e [ABC245E] Wrapping Chocolate
我绝对不会告诉你我打比赛时没做出来这道题。 题目简化:给定每个巧克力和盒子的长宽,已知每个盒子只能放一块巧克力,并且必须保证巧克力能放下,求是否所有巧克力都能放入。 思路:贪心、二分、排序、STL。 首先看到这…...
Linux 入门:操作系统进程详解(上)
目录 一.冯诺依曼体系结构 一). 软件运行前为什么要先加载?程序运行之前在哪里? 二).理解数据流动 二.操作系统OS(Operator System) 一).概念 二).设计OS的目的 三).如何理解操作系统…...
5.7/Q1,GBD数据库最新文章解读
文章题目:Global, regional, and national burden and trends of rheumatoid arthritis among the elderly population: an analysis based on the 2021 Global Burden of Disease study DOI:10.3389/fimmu.2025.1547763 中文标题:全球、区域…...
[pdf,epub]292页《分析模式》漫谈合集01-59提供下载
《分析模式》漫谈合集01-59的pdf、epub文件提供下载,地址: umlchina.com/url/ap.html,或查看本账号的CSDN资源。 已排版成适合手机阅读,pdf的排版更好一些。...
Spring MVC的工作流程, DispatcherServlet 的工作流程
Spring MVC 是一种基于Java的模型-视图-控制器(MVC)Web框架,它通过清晰的角色划分简化了Web应用开发。下面是Spring MVC的工作流程以及DispatcherServlet的具体工作流程。 Spring MVC 工作流程 请求到达:客户端发起一个HTTP请求…...
【Godot】使用 Shader 实现可配置圆角效果
文章目录 效果预览实现原理完整Shader代码关键参数详解1. 半径参数(radius)2. 角开关参数(hide_*)数学原理圆形区域判定公式坐标映射性能优化使用示例编辑器操作代码控制进阶技巧1. 添加抗锯齿2. 外发光效果3. 动画效果常见问题解决方案问题1:圆角边缘锯齿问题2:圆形变形…...
【翻译、转载】MCP 提示 (Prompts)
原文地址:https://modelcontextprotocol.io/docs/concepts/prompts#python 提示 (Prompts) 创建可重用的提示模板和工作流 提示 (Prompts) 使服务器能够定义可重用的提示模板和工作流,客户端可以轻松地将其呈现给用户和 LLM。它们提供了一种强大的方式来…...
论快乐的学习和学习的快乐
目录 一、背景二、过程1.快乐的学习:理念与实践快乐学习的理念溯源快乐学习在教育实践中的体现 2.学习的快乐:内涵与价值学习的快乐的多维内涵学习的快乐对个人成长的价值 3.快乐的学习与学习的快乐的相互关系快乐的学习是学习快乐的重要前提学习的快乐是…...
Git 命令
参考文献: Git 教程 | 菜鸟教程Git 使用教程:最详细、最正宗手把手教学(万字长文)git忽略某个目录或文件不上传 文章目录 工作原理基本命令配置使用 其他命令日志分支回退标签 忽略指定文件远程仓库 工作原理 Git 是由 Linus To…...
365打卡第R6周: LSTM实现糖尿病探索与预测
🍨 本文为🔗365天深度学习训练营中的学习记录博客 🍖 原作者:K同学啊 🏡 我的环境: 语言环境:Python3.10 编译器:Jupyter Lab 深度学习环境:torch2.5.1 torchvision0…...
新能源实验室电磁兼容设计优化方案论述
摘要:本文旨在进行新能源核心部件/系统测试实验室电磁兼容情况设计及优化方案进行论述,通过系统化梳理实验室的主流设备仪器,试验搭建典型方案。识别不同设备的电磁兼容现状,实验室基于设备布局常见设计方案不足点,故障…...
计算机图形学中的深度学习
文章目录 零、前言0.课程考核1.课程大纲2.前置知识3.教材4.课程大纲5.相关课程 Relevant Courses 一、计算机图形学1.本章学习目标2.图形学的应用3.SIG Graph papers 二、基本图形生成算法1.本章学习目标2.图形API3.OpenGL(1)什么是OpenGL(2)OpenGL 的基本组件:顶点…...
RockyLinux9.3-24小时制
在 RockyLinux 9.3 中,默认时间格式为 12 小时制,调整为 24 小时制 案例一:在 RockyLinux 9.3 中,默认时间格式为 12 小时制,调整为 24 小时制案例二:时间显示英文调整为中文endl 案例一:在 Roc…...
25.2linux中外置RTC芯片的PCF8563实验(测试)_csdn
1、硬件原理图分析 知道了这些引脚我们还是按照老习惯! 配置镜像和设备树文件! 2、修改设备树 2.1、添加或者查找 PCF8563 所使用的 IO 的 pinmux 配置 打开stm32mp15-pincrtl.dtsi 文件,查找节点I2C4: 也就是中断引脚并不需要配置pinctrl…...
高性能 WEB 服务器 Nginx:多虚拟主机实现!
Nginx 配置多虚拟主机实现 多虚拟主机是指在一台 Nginx 服务器上配置多个网站 在 Nginx 中,多虚拟主机有三种实现方式: 基于IP地址实现多虚拟主机 基于端口号实现多虚拟主机 基于域名实现多虚拟主机 1 基于域名实现多虚拟主机 在 Nginx 中配置多个…...
C++ 的类型排序
0.前言 在 C 中,我编写了一个 tuple-like 模板,这个模板能容纳任意多且可重复的类型: template<typename... Ts> struct TypeList {};// usage: using List1 TypeList<int, double, char, double>; using List2 TypeList<…...
[计算机网络]拓扑结构
拓扑结构一般会在计网教材或课程的第一章计网的分类那里接触到,但实际上计网的拓扑结构并不只是第一章提到的总线型、星型、树型、网状、混合型那几种类型那么简单,学完了后面的数链层以后对拓扑结构会有新的体会,所以特别单独总结成一篇博客…...
C#方法返回值全解析:从基础语法到实战技巧
摘要:方法返回值是C#编程的核心概念之一。本文将带你彻底掌握返回值声明、void方法特性,以及如何通过返回值实现优雅的流程控制(文末附完整示例代码)。 返回值的基础法则 类型声明原则 有返回值:必须在方法名前声明…...
修复笔记:SkyReels-V2 项目中的 torch.cuda.amp.autocast 警告和错误
#工作记录 一、问题描述 在运行项目时,出现以下警告和错误: FutureWarning: torch.cuda.amp.autocast(args...) is deprecated. Please use torch.amp.autocast(cuda, args...) instead.with torch.cuda.amp.autocast(dtypepipe.transformer.dtype), …...
【TF-BERT】基于张量的融合BERT多模态情感分析
不足:1. 传统跨模态transformer只能处理2种模态,所以现有方法需要分阶段融合3模态,引发信息丢失。2. 直接拼接多模态特征到BERT中,缺乏动态互补机制,无法有效整合非文本模态信息 改进方法:1. 基于张量的跨模…...
SONiC-OTN代码详解(具体内容待续)
SONiC-OTN代码详解 (具体内容待续) 基于AI的源代码解析工具的产生使得代码阅读和解析变得越来越高效和简洁,计划通过这样的工具对SONiC在OTN领域的应用做一个全自动的解析,大部分内容会基于AI工具的自动解析结果。这样做的目的是…...
牛客周赛90 C题- Tk的构造数组 题解
原题链接 https://ac.nowcoder.com/acm/contest/107500/C 题目描述 解题思路 数组a是不可以动的,所以我们可以把a[i]*b[i]*i分成两组,分别为a[i]*i以及b[i] 然后策略就很明显了,让更大的b[i]匹配更大的a[i]*i 详细实现见代码。 代码&am…...
[ML]通过50个Python案例了解深度学习和神经网络
通过50个Python案例了解深度学习和神经网络 摘要:机器学习 (Machine Learning, ML)、深度学习 (Deep Learning, DL) 和神经网络 (Neural Networks, NN) 是人工智能领域的核心技术。Python 是学习和实践这些技术的首选语言,因为它提供了丰富的库(如 scikit-learn、Te…...
vue3 - keepAlive缓存组件
在Vue 3中,<keep-alive>组件用于缓存动态组件或路由组件的状态,避免重复渲染,提升性能。 我们新建两个组件,在每一个组件里面写一个input,在默认情况下当组件切换的时候,数据会被清空,但…...
自由学习记录(58)
Why you were able to complete the SpringBoot MyBatisPlus task smoothly: Clear logic flow: Database → Entity → Service → Controller → API → JSON response. Errors are explicit, results are verifiable — you know what’s broken and what’s fixed. Sta…...
短信侠 - 自建手机短信转发到电脑上并无感识别复制验证码,和找手机输验证码说再见!
自建手机短信转发到电脑上并无感识别复制验证码 一、前言 项目开发语言:本项目使用PythonRedisC#开发 你是否也遇到过这样的场景: 正在电脑上操作某个网站,需要输入短信验证码手机不在身边,或者在打字时来回切换设备很麻烦验证码…...
课程10. 聚类问题
课程10. 聚类问题 聚类此类表述的难点K 均值法让我们推广到几个集群的情况如果我们选择其他起始近似值会怎样? 结论在 sklearn 中的实现 如何处理已发现的问题?层次聚类Lance-Williams 算法Lance-Williams 公式在Scipy中实现 示例DBSCANDBSCAN 算法 聚类…...
深度学习中的数据增强:提升食物图像分类模型性能的关键策略
深度学习中的数据增强:提升食物图像分类模型性能的关键策略 在深度学习领域,数据是模型训练的基石,数据的数量和质量直接影响着模型的性能表现。然而,在实际项目中,获取大量高质量的数据往往面临诸多困难,…...
QT设计权限管理系统
Qt能够简单实现系统的权限设计 首先我们需要一个登陆界面 例如这样 然后一级权限,可以看到所有的内容,不设置菜单栏的隐藏。 然后其他权限,根据登陆者的身份进行菜单栏不同的展示。 菜单栏的隐藏代码如下: ui->actionuser-…...
从上帝视角看文件操作
1.为什么使用文件? 如果没有文件,我们写的程序中的数据是存储在电脑的内存中,当程序退出时,内存被回收后,数据就丢失了,等下次运行程序,是无法看到上次程序的数据的。(比如我们在程序中写通讯录时,联系人的相关数据都是放在内存中的,当程序退出时,这些数据也会随之消…...
【51单片机6位数码管显示时间与秒表】2022-5-8
缘由数码管 keil proteus 为什么出现这种情况呢?-编程语言-CSDN问答 #include "reg52.h" unsigned char code smgduan[]{0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0,64}; //共阴0~F消隐减号 unsigned char cod…...
从头训练小模型: 4 lora 微调
1. LoRA (Low-Rank Adaptation) LoRA是一种高效的参数高效微调(Parameter-Efficient Fine-Tuning, PEFT)方法,原理是通过低秩分解的方式对预训练模型进行微调。 相比于全参数微调(Full Fine-Tuning),LoRA…...
前端开发,文件在镜像服务器上不存在问题:Downloading binary from...Cannot download...
问题与处理策略 问题描述 在 Vue 项目中,执行 npm i 下载依赖时,报如下错误 Downloading binary from https://npm.taobao.org/mirrors/node-sass//v4.14.1/win32-x64-72_binding.node Cannot download "https://npm.taobao.org/mirrors/node-sa…...
Debezium Binlog协议与事件转换详解
Debezium Binlog协议与事件转换详解 1. MySQL Binlog通信机制 1.1 连接建立流程 #mermaid-svg-eE88YFqcTG9kUWaZ {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-eE88YFqcTG9kUWaZ .error-icon{fill:#552222;}#mer…...
【PostgreSQL数据分析实战:从数据清洗到可视化全流程】4.1 日期时间标准化(时区转换/格式统一)
👉 点击关注不迷路 👉 点击关注不迷路 👉 点击关注不迷路 文章大纲 PostgreSQL数据分析实战:数据清洗之日期时间标准化(时区转换/格式统一)4.1 日期时间标准化:从混乱到有序4.1.1 数据乱象&…...
基于Hive + Spark离线数仓大数据实战项目(视频+课件+代码+资料+笔记)
精品推荐:基于Hive Spark离线数仓大数据实战项目,共23节课,供学习参考。 项目介绍项目中 docker 使用项目环境搭建项目数仓分层项目业务分析sqoop 数据采集python 数据采集项目 ODS 层创建DWD 层构建DWS 层构建项目回顾(一&…...
【深入浅出MySQL】之数据类型介绍
【深入浅出MySQL】之数据类型介绍 MySQL中常见的数据类型一览为什么需要如此多的数据类型数值类型BIT(M)类型INT类型TINYINT类型BIGINT类型浮点数类型float类型DECIMAL(M,D)类型区别总结 字符串类型CHAR类型VARCHAR(M)类型 日期和时间类型enum和set类型 …...
从入门到登峰-嵌入式Tracker定位算法全景之旅 Part 4 |IMU 死算与校正:惯性导航在资源受限环境的落地
Part 4 |IMU 死算与校正:惯性导航在资源受限环境的落地 本章聚焦 ESP32-S3 平台上如何利用 LSM6DS3 IMU 实现 死算(Dead Reckoning),并结合 零速更新(ZUPT) 或 磁力计辅助 进行 漂移校正,最终通过 EKF/UKF 融合提升定位精度。 一、传感器简介与校准 LSM6DS3 主要参数 加速…...
【iOS】 方法交换
【iOS】 方法交换 method-swizzling 文章目录 【iOS】 方法交换 method-swizzling前言什么是method-swizzling相关API方法交换的风险在load方法中保证只加载一次要在当前类的方法中进行交换如果方法依赖于cmd 方法交换的应用 前言 之前看过有关于消息转发的内容,这里我们可以简…...
PostgreSQL 的 ANALYZE 命令
PostgreSQL 的 ANALYZE 命令 ANALYZE 是 PostgreSQL 中用于收集数据库对象统计信息的关键命令,这些统计信息对于查询优化器生成高效执行计划至关重要。 一 ANALYZE 命令 1.1 基本语法 ANALYZE [ ( option [, ...] ) ] [ table_and_columns [, ...] ] ANALYZE [ …...
初识 iOS 开发中的证书固定
引言 在移动应用安全领域,HTTPS/TLS 是数据传输的第一道防线,但仅依赖系统默认的证书验证仍有被中间人(MITM)攻击的风险。Certificate Pinning(证书固定)通过将客户端信任“钉”在指定的服务器证书或公钥上…...
2025 年如何使用 Pycharm、Vscode 进行树莓派 Respberry Pi Pico 编程开发详细教程(更新中)
micropython 概述 micropython 官方网站:https://www.micropython.org/ 安装 Micropython 支持固件 树莓派 Pico 安装 Micropython 支持固件 下载地址:https://www.raspberrypi.com/documentation/microcontrollers/ 选择 MicroPython 下载 RPI_PIC…...
设计模式每日硬核训练 Day 17:中介者模式(Mediator Pattern)完整讲解与实战应用
🔄 回顾 Day 16:责任链模式小结 在 Day 16 中,我们学习了责任链模式(Chain of Responsibility Pattern): 将请求沿链传递,节点可选择处理或传递下一节点。实现了请求发送者与多个处理者的解耦…...