SpringCloud(6)— RabbitMQ(消息队列)

news2024/11/25 23:14:49

SpringCloud(6)— RabbitMQ(消息队列)

一 初识MQ

1.同步通信与异步通信

1.同步通信的问题

同步调用的优点在于时效性高,可以立即得到结果

微服务之间基于Feign的调用属于同步方式,存在一些问题

在这里插入图片描述

  • 耦合性:业务较多时,扩展维护不方便
  • 性能下降:一次性调用多个Feign,会导致耗时增加,性能和吞吐量下降
  • 资源浪费:调用Feign请求响应的过程中,CPU只能等待,无法做其他操作,造成系统资源的浪费
  • 级联失败:当有一个服务宕机时,很容易造成后面的服务阻塞,从而导致级联失败

在这里插入图片描述

2.异步调用方案

异步调用常见的实现就是 事件驱动模式

在这里插入图片描述

  • 服务解耦:新增或减少业务员,通过增加或取消事件订阅即可,无需再去修改上级服务
  • 性能提升:上级服务只需发送事件,不再关注其他业务逻辑
  • 消除级联:服务没有强依赖,不担心级联失败的问题
  • 流量削峰:Broker 起到缓冲作用,根据实际情况分发业务,保护订阅服务。

异步通信的缺点:

  • 过分依赖于Broker的可靠性,安全性,吞吐能力
  • 业务复杂,业务没有明显的流程线,不好追踪管理

2.MQ介绍

MQ(MessageQueue),中文含义为消息队列,用来存放消息,也就是事件驱动模式中的 Broker

常见的MQ技术包含一下四种:

在这里插入图片描述

  • RabbitMQ:现阶段使用最多的MQ技术,优点在于消息的低延迟和可靠性
  • ActiveMQ:开发语言基于Java,可以进行深度定制
  • RocketMQ:开发语言基于Java,可以进行深度定制,阿里巴巴开发
  • Kafka:单机吞吐量很高,但消息可靠性不高。

二 RabbitMQ的使用

1.安装与运行

RabbitMQ基于Erlang语言开发的开源消息中间件。

RabbitMQ官方地址:Messaging that just works — RabbitMQ

在DockerHub上拉取RabbitMQ的镜像,然后运行。

#1.拉取RabbitMQ
docker pull rabbitmq:3
#2.运行RabbitMQ镜像,(15672 为管理UI界面的端口,5672为后期通信接口)
docker run \
 -e RABBITMQ_DEFAULT_USER=shawn \
 -e RABBITMQ_DEFAULT_PASS=123456 \
 --name rabbitmq3 \
 --hostname myrabbit \
 -p 15672:15672 \
 -p 5672:5672 \
 -d \
 rabbitmq:3
  • RABBITMQ_DEFAULT_USER :设置默认账户名
  • RABBITMQ_DEFAULT_PASS :设置默认密码

安装完成之后不能直接进行访问,需要先进入容器内部开启插件才可以访问

#1.进入 rabbitmq 容器内
docker exec -it myrabbitmq bash
#2.开启插件
rabbitmq-plugins enable rabbitmq_management
#3.如果直接拉取 management 版本的镜像,则无需以上步骤
docker pull rabbitmq:3-management
#4.运行 management 版本的rabbit
docker run \
 -e RABBITMQ_DEFAULT_USER=shawn \
 -e RABBITMQ_DEFAULT_PASS=123456 \
 --name rabbitmq3 \
 --hostname myrabbit \
 -p 15672:15672 \
 -p 5672:5672 \
 -d \
 rabbitmq:3-management

完成以后即可在浏览器中输入服务器地址+端口号访问了。

在这里插入图片描述

踩坑点:Rabbit的Web UI 中Channel模块无法打开并且提示 Stats in management UI are disabled on this node

是因为默认情况下Rabbit是禁止的。

The reason is that the default image disables metrics collector in the management_agent plugin

原因是默认图像禁用management_agent插件中的度量收集器

# 1.进入容器内部
docker exec -it myrabbitmq bash
# 2.切换至配置文件目录下
cd  /etc/rabbitmq/conf.d/
# 3.将 management_agent.disable_metrics_collector.conf 文件中的 management_agent.disable_metrics_collector 的值修改为 false
echo management_agent.disable_metrics_collector = false > management_agent.disable_metrics_collector.conf
# 4.重启 rabbit 容器
docker restart rabbitmq3

2.RabbitMQ概述

在这里插入图片描述

RabbitMQ通过 VirtualHost 进行隔离,相互不可见。

RabbitMQ中的相关概念

  • channel:操作MQ的工具
  • exchange:路由消息到队列中,将消息发送给exchange,由exchange交给队列
  • queue:缓存消息
  • virtual host:虚拟主机,是对queue,exchange等资源的逻辑分组,不同用户可以访问不同的虚拟主机

三 RabbitMQ消息模型

在这里插入图片描述

1.简单队列(Hello World)

在这里插入图片描述

1.创建项目引入依赖

创建两个项目分别为发送者和订阅者,引入RabbitMQ的maven坐标

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-amqp</artifactId>
</dependency>

或者在初始化项目时直接勾选RabbitMQ

在这里插入图片描述

2.编写测试代码示例

消息发送者示例代码:publisher

@Test
void publisher() throws IOException, TimeoutException {
    ConnectionFactory factory=new ConnectionFactory();
    factory.setHost("192.168.119.101");
    factory.setUsername("shawn");
    factory.setPassword("123456");
    factory.setPort(5672);
    factory.setVirtualHost("/");
    //建立连接
    Connection connection=factory.newConnection();
    //创建通道
    Channel channel=connection.createChannel();
    //创建队列
    String queueName="simple.queue";
    String message="贾君鹏,你妈喊你回家吃饭!";
    channel.basicPublish("",queueName,null,message.getBytes());
    System.out.println("发送消息:"+message);
    channel.close();
    connection.close();
}

消息接受者示例代码:consumer

@Test
void consumer() throws IOException, TimeoutException {
    ConnectionFactory factory = new ConnectionFactory();
    factory.setHost("192.168.119.101");
    factory.setUsername("shawn");
    factory.setPassword("123456");
    factory.setPort(5672);
    factory.setVirtualHost("/");
    //创建连接和通道
    Connection connection = factory.newConnection();
    Channel channel = connection.createChannel();
    //创建队列
    String queueName = "simple.queue";
    channel.queueDeclare(queueName, false, false, false, null);
    //订阅消息
    channel.basicConsume(queueName,true,new DefaultConsumer(channel){
        @Override
        public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
            // 处理消息
            String message=new String(body,"UTF-8");
            System.out.println("接受消息:"+message);
        }
    });
    System.out.println("等待接受消息,退出请按 CTRL+C");
}

3.基本消息队列的发送流程

  • 建立 Connection
  • 创建 Channel
  • 使用 Channel 声明队列
  • 使用 Channel 向队列发送消息 / 使用 consumer 的消费行为订阅消息

2.SpringAMQP

官方文档:https://spring.io/projects/spring-amqp

在这里插入图片描述

AMQP是消息接受与发送的协议或者标准,与语言和平台无关

1.RabbitTemplate

RabbitTemplate是一个Spring封装的用来发送消息的工具类,类似 RedisCache,RestTemplate,可以简单,高效,优雅的实现消息的发送和接收

引入 spring-boot-starter-amqp 依赖,然后在相关项目(publisher 和 consumer )的配置文件中配置相关参数。

spring:
  application:
    name: publisher
  rabbitmq:
    host: 192.168.119.101
    # 默认端口为5672,使用默认端口时可不写
    port: 5672
    username: shawn
    password: 123456
    virtual-host: /

在 publisher 项目中编写测试代码,发送消息

@Autowired
private RabbitTemplate rabbitTemplate;
@Test
void publisher() {
    String queueName="hello.world";
    String message="Hello,RabbitTemplate";
    # 这里使用 convertAndSend 进行消息的处理和发送
    rabbitTemplate.convertAndSend(queueName,message);
    System.out.println("消息发送完成");
}

在 consumer 项目中编写代码,订阅并且接受消息

/**
* 使用 Component 将当前类申明为一个 bean
* 定义一个类,使用 RabbitListener 注解订阅要接受消息的队列
*/
@Component
public class SimpleMessageRabbitListener {
    @RabbitListener(queues = "simple.queue")
    public void listenSimpleMessage(String message) {
        System.out.println("接受消息:" + message);
    }
}

注意:消息一旦消费,就会从消息队列中删除,RabbitMQ没有消息回溯

3.WorkQueue(工作队列)

工作队列模型,多个消费者绑定到一个队列,同一条消息只会被一个消费者处理。

在这里插入图片描述

工作队列,可以提高消息处理速度,避免消息堆积

@RabbitListener(queues = "simple.queue")
public void listenWorkMessage1(String message) throws InterruptedException {
    System.out.println("消费者【1】接受消息:" + message + "-" + LocalDateTime.now());
    Thread.sleep(20);
}

@RabbitListener(queues = "simple.queue")
public void listenWorkMessage2(String message) throws InterruptedException {
    System.out.println("消费者【2】接受消息:" + message + "-" + LocalDateTime.now());
    Thread.sleep(200);
}

定义两个执行效率不同的消费者,模拟一个简单的工作队列模型,发现消费者并不会因为执行效率的高低自动的增加或处理消息的处理量,而是平均分配。

可以通过消息的欲取机制来控制消息的处理量

欲取机制,即默认情况下,有多少消息就拿多少消息,并不会考虑有多少个消费者。

通过调整 prefetch 属性的值,来控制消费者的消息预取能力

spring:
  application:
    name: consumer
  rabbitmq:
    host: 192.168.119.101
    port: 5672
    username: shawn
    password: 123456
    virtual-host: /
    listener:
      simple:
        # 通过调整 prefetch 属性的值,来控制消费者的消息预取能力
        prefetch: 1

4.发布订阅模式

发布订阅模式(Publish-Subscribe)的核心是,允许将一个消息发给多个消费者。具体的实现方式是加入了exchange(交换机)。

在这里插入图片描述

注意:exchange只负责消息的转发,而不是存储。路由失败则消息丢失

1.Exchange(交换机)

交换机的作用:

  • 接受 Publisher 发送的消息
  • 将消息按照规则路由到与之绑定的队列上
  • 不存储消息,只负责消息的转发。路由失败,消息丢失
  • FanoutExchange会将消息路由到每一个和它绑定的队列上

需要使用到的 Bean:FanoutExchange Queue Binding

2.FanoutExchange

Fanout Exchange 会将接收到的消息路由到每一个跟其绑定的queue

在 Consumer 项目中定义队列(queue),交换机(exchange),并且将队列绑定到交换机上。

/**
示例: 声明一个交换机和两个队列,并且将队列与交换机进行绑定
*/
@Configuration
public class FanoutExchangeConfig {
   
    /**
    *声明一个FanoutExchange对象,并且添加到bean
    */
    @Bean
    public FanoutExchange fanoutExchange() {
        return new FanoutExchange("shawn.exchange");
    }
    /**
    *声明一个Queue对象,并且添加到bean
    */
    @Bean
    public Queue fanoutQueue1() {
        return new Queue("shawn.queue1");
    }
    /**
    * 将队列和Exchange进行绑定
    */
    @Bean
    public Binding bindingQueue1(Queue fanoutQueue1, FanoutExchange fanoutExchange) {
        // 使用 BindingBuilder 提供的方法进行绑定,最后返回Binding对象
        return BindingBuilder.bind(fanoutQueue1).to(fanoutExchange);
    }

    @Bean
    public Queue fanoutQueue2() {
        return new Queue("shawn.queue2");
    }

    @Bean
    public Binding bindingQueue2(Queue fanoutQueue2, FanoutExchange fanoutExchange) {
        return BindingBuilder.bind(fanoutQueue2).to(fanoutExchange);
    }
}

接受消息的监听器示例代码:

@Component
public class SimpleMessageRabbitListener {
    @RabbitListener(queues = "shawn.queue1")
    public void listenWorkMessage1(String message) throws InterruptedException {
        System.out.println("消费者【1】接受消息:" + message + "-" + LocalDateTime.now());
        Thread.sleep(20);
    }

    @RabbitListener(queues = "shawn.queue2")
    public void listenWorkMessage2(String message) throws InterruptedException {
        System.out.println("消费者【2】接受消息:" + message + "-" + LocalDateTime.now());
        Thread.sleep(200);
    }
}

在 Publisher 项目中编写消息发送的测试代码:

@Test
void testSendExchange() throws InterruptedException {
    String exChangeName = "shawn.exchange";
    String message = "贾君鹏,你妈喊你回家吃饭";
    // 向指定名称的Exchage(交换机)发送消息
    rabbitTemplate.convertAndSend(exChangeName, "", message);
}

测试结果:两个队列均能收到消息

在这里插入图片描述

3.DirectExchange

DirectExchange会将接受到的消息根据规则路由到指定的Queue,因此成为路由模式(routes)。

  • 每一个Queue都与DirectExchange设置一个BindingKey
  • 发布者发布消息时,指定消息的RoutingKey
  • DirectExchange会将消息路由到BindingKey与消息RoutingKey一致的队列
  • 可以为队列(queue)设置多个BindingKey,且一个BindingKey也可以设置给多个队列

在这里插入图片描述

当多个队列使用一个BindingKey时,DirectExchange会将消息发送给所有使用了这个BindingKey的队列

这种情况下,DirectExchang与FanoutExchange相同,也属于广播模式

因此可以认为 DirectExchange 可以模拟 FanoutExchang, 且比 FanoutExchange 灵活

示例:基于RabbitListener 实现 DirectExchange

编写 Consumer 项目的代码:

/**
* 使用 RabbitListener 声明要绑定的队列、BindingKey、交换机和交换机类型,BindingKey可以设置多个
*/
@RabbitListener(bindings = @QueueBinding(
        value = @Queue(name = "shawn.queue1"),
        exchange = @Exchange(name = "direct.exchange", type = ExchangeTypes.DIRECT),
        key = {"red", "blue"}
))
public void listenWorkMessage1(String message) throws InterruptedException {
    System.out.println("消费者【1】接受消息:" + message + "-" + LocalDateTime.now());
    Thread.sleep(20);
}

@RabbitListener(bindings = @QueueBinding(
        value = @Queue(name = "shawn.queue2"),
        exchange = @Exchange(name = "direct.exchange", type = ExchangeTypes.DIRECT),
        key = {"red", "yellow"}
))
public void listenWorkMessage2(String message) throws InterruptedException {
    System.out.println("消费者【2】接受消息:" + message + "-" + LocalDateTime.now());
    Thread.sleep(200);
}

在 Publuisher 项目中编写测试代码:

@Test
void testSendDirectExchange() throws InterruptedException {
    String exChangeName = "direct.exchange";
    String message = "贾君鹏,你妈喊你回家吃饭";
    String routingKey="blue";
    rabbitTemplate.convertAndSend(exChangeName,routingKey, message);
}

此时,只有包含指定的 RoutingKey 的队列,才能收到消息。

4.TopicExchange

TopicExchange 与 DirectExchange 的区别在于,routingKey必须是多个单词的列表,并且使用英文句号( . )分割

在这里插入图片描述

Queue 与 Exchange 进行绑定时支持通配符:

  • (#)表示 0个或多个单词
  • (*)表示 一个单词

示例:使用 TopicExchange 实现消息发送和接受

在 Consumer 项目中编写示例代码

@Component
public class TopicExchangeListener {
    
    /**
    * listenWorkMessage1 接收和 china.# 有关的消息
    */
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(name = "shawn.queue1"),
            exchange = @Exchange(name = "topic.exchange", type = ExchangeTypes.TOPIC),
            key = "china.#"
    ))
    public void listenWorkMessage1(String message) throws InterruptedException {
        System.out.println("消费者【1】接受消息:" + message + "-" + LocalDateTime.now());
        Thread.sleep(20);
    }
    
   /**
    * listenWorkMessage2 接收和 #.news 有关的消息
    */
   @RabbitListener(bindings = @QueueBinding(
            value = @Queue(name = "shawn.queue2"),
            exchange = @Exchange(name = "topic.exchange", type = ExchangeTypes.TOPIC),
            key = "#.news"
    ))
    public void listenWorkMessage2(String message) throws InterruptedException {
        System.out.println("消费者【2】接受消息:" + message + "-" + LocalDateTime.now());
        Thread.sleep(200);
    }
}

在 Publisher 项目中编写测试方法

@Test
void testSendTopicExchange() throws InterruptedException {
    String exChangeName = "topic.exchange";
    String message = "贾君鹏,你妈喊你回家吃饭";
    // 此处的 routingKey 需要按照TopicExchange的规则编写
    String routingKey = "china.food";
    rabbitTemplate.convertAndSend(exChangeName, routingKey, message);
}

定义的交换机和队列信息,均可以在 RabbitMQ Web UI 中看到

在这里插入图片描述

四 消息转换器

在SpringAMQP中,接受消息的类型时Object,也就是说,我们可以发送任何类型的对象给消费者,SpringAMQP会帮助我们进行序列化成字节后发送。

Spring中对消息对象的处理是由 SpringAMQP中的一个名为MessageConvert来处理的。默认实现是SimpleMessageConvert,基于JDK的ObjectOutputStream来完成。

通过重新定义一个 MessageConverter 的 Bean 来修改序列化方式。

推荐使用 JSON 方式序列化,消息体将会更加短小精悍,传输速度更快。

引入 jackson-dataformat-xml 依赖

<dependency>
    <groupId>com.fasterxml.jackson.dataformat</groupId>
    <artifactId>jackson-dataformat-xml</artifactId>
    <version>2.14.1</version>
</dependency>

定义 Bean

@Configuration
public class MessageConverterConfig {
    @Bean
    public Jackson2JsonMessageConverter messageConverter(){
        return new Jackson2JsonMessageConverter();
    }
}

编写一个传输对象的简单队列测试示例

@Test
void testSendObjectMessage() {
    String queueName = "object.queue";
    SystemLog log = new SystemLog();
    log.setAddress("陕西省西安市");
    log.setAge(29);
    log.setName("shawn");
    log.setId(1L);
    log.setPassword("123456");

    rabbitTemplate.convertAndSend("", queueName, log);
}

此时消费者接受到的消息类型将会是Json格式,将Json信息转换对应的对象就可以拿到对象消息了。

在这里插入图片描述

注意:发送消息和接收消息时注意使用相同的 MessageConverter。可直接将消息转换为发送时的对象(自定义类型需手动转换)

完结撒花。

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

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

相关文章

硅片检测半导体运动台控制器的设计

多自由度精密运动平台是半导体行业中硅片制造和检测过程里至关重要的问题&#xff0c;采用直线电机和音圈电机等先进驱动方式的精密运动平台相对传统滚珠丝杠旋转电机运动的运动平台&#xff0c;具有精度高、响应快、寿命长、免维护和结构简单等诸多优点&#xff0c;优势十分明…

为什么感觉现在很少有黑客了?

有一个词语&#xff0c;人人不是它&#xff0c;却人人都提及它&#xff0c;他就是&#xff1a;黑客&#xff01; 黑客&#xff0c;这个我们从小就接触的工种&#xff0c;总是衣服全身黑衣、眼戴墨镜、冷酷无情、超级厉害的形象&#xff0c;关键是&#xff0c;只要应用崩了/数据…

一颗芯片是怎样诞生的

目录 从沙子到单晶硅 单晶硅切片 电路实现 芯片的封装 芯片属于半导体。半导体是介于导体和绝缘体之间的一类物质&#xff0c;元素周期表中硅、锗、硒、硼的单质都属于半导体。这些单质通过掺杂其他元素生成的一些化合物&#xff0c;也属于半导体的范畴。 P型半导体是在单…

Linux安装phpstudy(无联网版)

下载install.sh Centos安装脚本&#xff0c;直接在浏览器打开https://notdocker.xp.cn/install.sh下载install.sh #官方安装命令 yum install -y wget && wget -O install.sh https://notdocker.xp.cn/install.sh && sh install.sh #命令解析 yum install -y …

AI作画,AIGC领域新的引爆点

AI作画火爆&#xff0c;一帧秒创再创惊喜 2022年渐近尾声&#xff0c;这一年小事不断&#xff0c;大事不少。当今这个时代&#xff0c;似乎注定就是一个见证历史和颠覆观念的时代。AIGC领域在人工智能、元宇宙概念兴起的背景之下&#xff0c;在今年迎来一个火爆增长。 其中的…

Github每日精选(第76期):在 Mac 状态栏上显示进程流量的监视器ITraffic-monitor-for-mac

ITraffic-monitor-for-mac ITraffic-monitor-for-mac 在 Mac 状态栏上显示进程流量的监视器&#xff0c;在windows我们的流量可以通过电脑管家或者360进行显示&#xff0c;在进行网络编程的时候&#xff0c;这个确实帮了不少忙&#xff0c;但是咱Mac下&#xff0c;显示网络状况…

oracle的trunc函数改为hive的函数

trunc函数可以截取oracle的日期 select trunc(sysdate,yyyy) from dual;--返回当年第一天 select trunc(sysdate,mm) from dual; --返回当月第一天 select trunc(sysdate,dd) from dual;--返回当前年月日 select trunc(sysdate,d) from dual; --返回当前星期的第一天(星期日) …

怎么把电脑硬盘文件恢复回来?跟着我这么做

电脑的硬盘数据丢失了&#xff0c;用了很多方法都没有办法找回来&#xff0c;电脑文件还能找回来吗&#xff1f;硬盘文件恢复要怎么操作&#xff1f;这时候就要寻求第三方数据恢复软件来恢复数据了。下面有详细的操作步骤&#xff0c;简单几步就可以找回你消失的硬盘数据&#…

leetcode90子集II-回溯-Java

说明&#xff1a; 问题描述来源leetcode 题解1&#xff1a; /*** author xin麒* date 2022/12/15 11:18* 给你一个整数数组 nums &#xff0c;其中可能包含重复元素&#xff0c;请你返回该数组所有可能的子集&#xff08;幂集&#xff09;。* 解集 不能 包含重复的子集。返回…

DPDK介绍

一、什么是DPDK&#xff1f; DPDK 全称是数据平面开发套件 (Data Plane Development Kit)&#xff0c;由 6WIND,Intel 等多家公司开发&#xff0c;主要基于 Linux 系统运行&#xff0c;用于快速数据包处理的函数库与驱动集合&#xff0c;可以极大提高数据处理性能和吞吐量&…

DGIOT边缘主机功能——6USB串口替代普通dtu/网关的设备接入

[小 迪 导读]&#xff1a; dgiot边缘主机自带6个USB口、2个RS232串口以及2个网口&#xff0c;可用组态对边缘主机上的USB口、串口和网口等上的外设进行可视化管理&#xff0c;包括如下功能&#xff1a; 通过6个USB口外接USB转485转换器模拟6个485转以太网/无线的网关/dtu2个RS…

JavaWeb——在线音乐播放器

文章目录效果演示1. 创建SpringBoot项目2. 数据库设计3. 配置数据库和xml4. 登录模块设计4.1 创建User类4.2 创建对应的Mapper和Controller5. 实现登录5.1 登录的请求和响应设计5.2 请求实现5.3 响应实现5.31 设置统一的响应体类工具类5.32 创建常量工具类5.33 优化后完整代码6…

纳米源表测试软件更新,新增太阳能电池测试、双通道脉冲扫描

源表在电测行业中应用十分广泛&#xff0c;尤其是在需求高精度的半导体、纳米器件和材料、太阳能电池、印刷电子技术等领域有着举足轻重的地位&#xff1b;而源表软件则可以实现源表的远程控制&#xff0c;通过在软件控制源表进行配置或者测量&#xff0c;也可以对测量的数据和…

大学生游戏静态HTML网页设计 (HTML+CSS+JS仿英雄联盟网站15页)

&#x1f389;精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业…

2.5.9 使用 systemd 管理 MySQL 服务器实例

2.5.9 使用 systemd 管理 MySQL 服务器实例systemd 概述为 MySQL 配置 systemd使用 systemd 配置多个 MySQL 实例从 mysqld_safe 迁移到 systemd如果在以下 Linux 平台上使用 RPM 或 Debian 软件包安装 MySQL &#xff0c;则服务器启动和关闭由 systemd 管理&#xff1a; RPM …

时间序列-预测-模型-2020:Informer【比Transformer更有效的长时间序列预测】【在对性能影响不大的前提下降低复杂度】

摘要 时序预测这个领域的工作与很多其他领域类似,我们可以按“深度学习”方法的引入作为分界线。在此之前的方法是传统的时序建模方法,比如移动平均、自回归、以及结合差分的ARIMA模型等,有着悠久的历史以及基于理论基础的可解释性。但是,这类方法一般要求时间序列是平稳的…

视频转文字怎么弄?建议收藏这些方法

小伙伴们在闲暇之余&#xff0c;会不会通过一些网课的学习&#xff0c;来提高自己呢&#xff1f;有时我们网课学习来不及做笔记&#xff0c;但是重复观看又比较麻烦&#xff0c;这时我们就可以通过将视频转换成文字&#xff0c;这样就能够清楚明了的知道视频的讲解内容了。那你…

springcloud整合Hystrix

作用 1、服务降级 触发情况&#xff1a;程序运行异常、超时、服务熔断触发服务降级、线程池/信号量打满也会触发服务降级 2、服务熔断 直接拒绝访问&#xff0c;即使有正确的访问也会短路 3、服务限流 排队有序进行 构建服务 1、建module provider-hystrix-payment8001 2、改…

mac 好用的ps修图软件 Pixelmator Pro

Pixelmator Pro Pixelmator Pro 是一款任何人都可以使用的专业图像编辑工具。Pixelmator Pro旨在使每个人都可以使用最强大的专业图像编辑工具。拥有大量用于编辑和修饰照片&#xff0c;创建图形设计&#xff0c;绘画&#xff0c;绘制矢量图形以及添加令人惊叹的效果的工具&…

sdl 渲染旋转视频的方法

文章目录前言一、如何实现&#xff1f;1、计算边框大小2、计算缩放大小3、逆运算视频宽高二、完整代码三、使用示例总结前言 一般情况下播放视频时不需要旋转&#xff0c;但是如果是移动端录制的视频有时会出现rotate参数&#xff0c;且视频宽高也是互换的&#xff0c;如果直接…