RabbitMQ安装配置,封装工具类,发送消息及监听

news2024/11/30 2:24:45

1. Get-Started

docker安装rabbitmq

  1. 拉取镜像
[root@heima ~]# docker pull rabbitmq:3.8-management
3.8-management: Pulling from library/rabbitmq
7b1a6ab2e44d: Pull complete 
37f453d83d8f: Pull complete 
e64e769bc4fd: Pull complete 
c288a913222f: Pull complete 
13adc5da62c6: Pull complete 
bd67e639afcb: Pull complete 
9a48b5ad2519: Pull complete 
1cdfc59624be: Pull complete 
8f5ad79f0ad6: Pull complete 
Digest: sha256:543f7268600a27a39e2fdd532f8df479636fc0cf528aadde88d5fe718bed71e4
Status: Downloaded newer image for rabbitmq:3.8-management
docker.io/library/rabbitmq:3.8-management
  1. 创建目录
mkdir -p /home/apps/rabbitmq/data
  1. 运行容器
docker run \
-d \
--name rabbitmq \
--restart=always \
--privileged=true \
-p 5672:5672 \
-p 15672:15672 \
-v /home/apps/rabbitmq/data:/var/lib/rabbitmq \
-e RABBITMQ_DEFAULT_VHOST=vhost0 \
-e RABBITMQ_DEFAULT_USER=admin \
-e RABBITMQ_DEFAULT_PASS=admin123 \
rabbitmq:3.8-management
  1. 启用web界面管理插件
docker exec -it rabbitmq rabbitmq-plugins enable rabbitmq_management
或
-- 进入容器
docker exec -it rabbitmq /bin/bash
-- 安装插件
rabbitmq-plugins enable rabbitmq_management

  1. 浏览器访问 http://虚拟机ip:15672/出现以下界面说明安装成功。

在这里插入图片描述
输入上面在初始化Rabbitmq容器时我们自己指定了默认账号和密码:admin/admin123,如果没有指定的话那么rabbitmq的默认账号密码是:guest/guest

扩展安装延迟队列

  • 去官网下载插件(v3.8.17)
  • 地址:https://github.com/rabbitmq/rabbitmq-delayed-message-exchange/releases
# 将下载好的插件复制到mq容器内部
docker cp rabbitmq_delayed_message_exchange-3.8.17.8f537ac.ez rabbitmq:/plugins

# 进入mq容器
docker exec -it rabbitmq /bin/bash

# 开启插件支持 
rabbitmq-plugins enable rabbitmq_delayed_message_exchange

# 查看插件列表
rabbitmq-plugins list

2. 生产者模块

2.1 项目引入依赖:

rabbitmq依赖包,使用RabbitMq这2个依赖就够了。

<dependency>
    <groupId>org.springframework.amqp</groupId>
    <artifactId>spring-amqp</artifactId>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>org.springframework.amqp</groupId>
    <artifactId>spring-rabbit</artifactId>
    <scope>provided</scope>
</dependency>

封装工具类用到的包

<!--hutool工具包-->
<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.7.17</version>
</dependency>

2.2 工具类

  • RabbitMqHelper
import cn.hutool.core.lang.UUID;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;
import org.springframework.amqp.core.MessagePostProcessor;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.time.Duration;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;
@Slf4j
public class RabbitMqHelper {

    public static final String REQUEST_ID_HEADER = "requestId";
    private final RabbitTemplate rabbitTemplate;
    private final MessagePostProcessor processor = new BasicIdMessageProcessor();
    private final ThreadPoolTaskExecutor executor;

    public RabbitMqHelper(RabbitTemplate rabbitTemplate) {
        this.rabbitTemplate = rabbitTemplate;
        executor = new ThreadPoolTaskExecutor();
        //配置核心线程数
        executor.setCorePoolSize(10);
        //配置最大线程数
        executor.setMaxPoolSize(15);
        //配置队列大小
        executor.setQueueCapacity(99999);
        //配置线程池中的线程的名称前缀
        executor.setThreadNamePrefix("mq-async-send-handler");

        // 设置拒绝策略:当pool已经达到max size的时候,如何处理新任务
        // CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        //执行初始化
        executor.initialize();
    }

    /**
     * 根据exchange和routingKey发送消息
     */
    public <T> void send(String exchange, String routingKey, T t) {
        log.debug("准备发送消息,exchange:{}, RoutingKey:{}, message:{}", exchange, routingKey, t);
        // 1.设置消息标示,用于消息确认,消息发送失败直接抛出异常,交给调用者处理
        String id = UUID.randomUUID().toString(true);
        CorrelationData correlationData = new CorrelationData(id);
        // 2.设置发送超时时间为500毫秒
        rabbitTemplate.setReplyTimeout(500);
        // 3.发送消息,同时设置消息id
        rabbitTemplate.convertAndSend(exchange, routingKey, t, processor, correlationData);
    }

    /**
     * 根据exchange和routingKey发送消息,并且可以设置延迟时间
     */
    public <T> void sendDelayMessage(String exchange, String routingKey, T t, Duration delay) {
        // 1.设置消息标示,用于消息确认,消息发送失败直接抛出异常,交给调用者处理
        String id = UUID.randomUUID().toString(true);
        CorrelationData correlationData = new CorrelationData(id);
        // 2.设置发送超时时间为500毫秒
        rabbitTemplate.setReplyTimeout(500);
        // 3.发送消息,同时设置消息id
        rabbitTemplate.convertAndSend(exchange, routingKey, t, new DelayedMessageProcessor(delay), correlationData);
    }


    /**
     * 根据exchange和routingKey 异步发送消息,并指定一个延迟时间
     *
     * @param exchange   交换机
     * @param routingKey 路由KEY
     * @param t          数据
     * @param <T>        数据类型
     */
    public <T> void sendAsync(String exchange, String routingKey, T t, Long time) {
        String requestId = MDC.get(REQUEST_ID_HEADER);
        CompletableFuture.runAsync(() -> {
            try {
                MDC.put(REQUEST_ID_HEADER, requestId);
                // 发送延迟消息
                if (time != null && time > 0) {
                    sendDelayMessage(exchange, routingKey, t, Duration.ofMillis(time));
                } else {
                    send(exchange, routingKey, t);
                }
            } catch (Exception e) {
                log.error("推送消息异常,t:{},", t, e);
            }
        }, executor);
    }

    /**
     * 根据exchange和routingKey 异步发送消息
     *
     * @param exchange   交换机
     * @param routingKey 路由KEY
     * @param t          数据
     * @param <T>        数据类型
     */
    public <T> void sendAsync(String exchange, String routingKey, T t) {
        sendAsync(exchange, routingKey, t, null);
    }
}
  • MqConfig
import cn.hutool.core.util.StrUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.MDC;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.config.ContainerCustomizer;
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.amqp.rabbit.retry.MessageRecoverer;
import org.springframework.amqp.rabbit.retry.RepublishMessageRecoverer;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.amqp.SimpleRabbitListenerContainerFactoryConfigurer;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;


@Configuration
@ConditionalOnClass(value = {MessageConverter.class, AmqpTemplate.class})
public class MqConfig implements EnvironmentAware{

    public static final String REQUEST_ID_HEADER = "requestId";
    public static final String ERROR_EXCHANGE = "error.topic";
    public static final String ERROR_KEY_PREFIX = "error.";
    public static final String ERROR_QUEUE_TEMPLATE = "error.{}.queue";
    private String defaultErrorRoutingKey;
    private String defaultErrorQueue;

    @Bean(name = "rabbitListenerContainerFactory")
    @ConditionalOnProperty(prefix = "spring.rabbitmq.listener", name = "type", havingValue = "simple",
            matchIfMissing = true)
    SimpleRabbitListenerContainerFactory simpleRabbitListenerContainerFactory(
            SimpleRabbitListenerContainerFactoryConfigurer configurer, ConnectionFactory connectionFactory,
            ObjectProvider<ContainerCustomizer<SimpleMessageListenerContainer>> simpleContainerCustomizer) {
        SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
        configurer.configure(factory, connectionFactory);
        simpleContainerCustomizer.ifUnique(factory::setContainerCustomizer);
        factory.setAfterReceivePostProcessors(message -> {
            Object header = message.getMessageProperties().getHeader(REQUEST_ID_HEADER);
            if(header != null) {
                MDC.put(REQUEST_ID_HEADER, header.toString());
            }
            return message;
        });
        return factory;
    }

    @Bean
    public MessageConverter messageConverter(ObjectMapper mapper){
        // 1.定义消息转换器
        Jackson2JsonMessageConverter jackson2JsonMessageConverter = new Jackson2JsonMessageConverter(mapper);
        // 2.配置自动创建消息id,用于识别不同消息
        jackson2JsonMessageConverter.setCreateMessageIds(true);
        return jackson2JsonMessageConverter;
    }

    /**
     * <h1>消息处理失败的重试策略</h1>
     * 本地重试失败后,消息投递到专门的失败交换机和失败消息队列:error.queue
     */
    @Bean
    @ConditionalOnClass(MessageRecoverer.class)
    @ConditionalOnMissingBean
    public MessageRecoverer republishMessageRecoverer(RabbitTemplate rabbitTemplate){
        // 消息处理失败后,发送到错误交换机:error.direct,RoutingKey默认是error.微服务名称
        return new RepublishMessageRecoverer(
                rabbitTemplate, ERROR_EXCHANGE, defaultErrorRoutingKey);
    }

    /**
     * rabbitmq发送工具
     *
     */
    @Bean
    @ConditionalOnMissingBean
    @ConditionalOnClass(RabbitTemplate.class)
    public RabbitMqHelper rabbitMqHelper(RabbitTemplate rabbitTemplate){
        return new RabbitMqHelper(rabbitTemplate);
    }

    /**
     * 专门接收处理失败的消息
     */
    @Bean
    public DirectExchange errorMessageExchange(){
        return new DirectExchange(ERROR_EXCHANGE);
    }

    @Bean
    public Queue errorQueue(){
        return new Queue(defaultErrorQueue, true);
    }

    @Bean
    public Binding errorBinding(Queue errorQueue, DirectExchange errorMessageExchange){
        return BindingBuilder.bind(errorQueue).to(errorMessageExchange).with(defaultErrorRoutingKey);
    }

    @Override
    public void setEnvironment(Environment environment) {
        String appName = environment.getProperty("spring.application.name");
        this.defaultErrorRoutingKey = ERROR_KEY_PREFIX + appName;
        this.defaultErrorQueue = StrUtil.format(ERROR_QUEUE_TEMPLATE, appName);
    }
}
  • Processor
import cn.hutool.core.lang.UUID;
import org.slf4j.MDC;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessagePostProcessor;

public class BasicIdMessageProcessor implements MessagePostProcessor {
    public static final String REQUEST_ID_HEADER = "requestId";
    @Override
    public Message postProcessMessage(Message message) throws AmqpException {
        String requestId = MDC.get(REQUEST_ID_HEADER);
        if (requestId == null) {
            requestId = UUID.randomUUID().toString(true);
        }
        // 写入RequestID标示
        message.getMessageProperties().setHeader(REQUEST_ID_HEADER, requestId);
        return message;
    }
}

----------------------------------------------------------------------

import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.Message;
import java.time.Duration;

public class DelayedMessageProcessor extends BasicIdMessageProcessor {

    private final long delay;

    public DelayedMessageProcessor(Duration delay) {
        this.delay = delay.toMillis();
    }

    @Override
    public Message postProcessMessage(Message message) throws AmqpException {
        // 1.添加消息id
        super.postProcessMessage(message);
        // 2.添加延迟时间
        message.getMessageProperties().setHeader("x-delay", delay);
        return message;
    }
}

2.3 配置

通常mq是放在common模块中,别的模块需要mq时就引入该模块,因此需要把MqConfig放在IOC容器里加载。

  • resources/META-INF/spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
 com.tianji.common.autoconfigure.mq.MqConfig

配置rabbitmq的地址等信息

  • boostrap.yml
spring:
  rabbitmq:
    host: ${mydemo.mq.host:192.168.150.101}
    port: ${mydemo.mq.port:5672}
    virtual-host: ${mydemo.mq.vhost:/vhost0}
    username: ${mydemo.mq.username:admin}
    password: ${mydemo.mq.password:admin123}
    listener:
      simple:
        retry:
          enabled: ${mydemo.mq.listener.retry.enable:true} # 开启消费者失败重试
          initial-interval: ${mydemo.mq.listener.retry.interval:1000ms} # 初始的失败等待时长为1秒
          multiplier: ${mydemo.mq.listener.retry.multiplier:2} # 失败的等待时长倍数,下次等待时长 = multiplier * last-interval
          max-attempts: ${mydemo.mq.listener.retry.max-attempts:3} # 最大重试次数
          stateless: ${mydemo.mq.listener.retry.stateless:true} # true无状态;false有状态。如果业务中包含事务,这里改为false

2.4 测试文件

TestController

@RestController
public class TestController {

    @Autowired
    RabbitMqHelper rabbitMqHelper;

    @GetMapping("/hello")
    public String hello(){
        return "hello";
    }

    @GetMapping("/sendMsg")
    public String sendMsg(){
        rabbitMqHelper.send(
                "order.topic", // "order.topic"
                "order.pay", // "order.pay"
                UserDto.builder()
                        .id(10001)
                        .name("gz")
                        .age(23)
                        .phone("15500000001")
                        .email("123@qq.com")
                        .build()
        );
        return "success";
    }
}

UserDto

import lombok.Builder;
import lombok.Data;

@Data
@Builder
public class UserDto {
    private Integer id;
    private String name;
    private String phone;
    private Integer age;
    private String email;
}

2.5 生产者测试

生产者模块目录结构
在这里插入图片描述

启动生产者服务,访问http://127.0.0.1:8080/sendMsg
在这里插入图片描述报错了,原因是没有消费者消费消息
但是发现创建了新的错误消息exchange和queue
在这里插入图片描述
因此,接下来创建消费者监听消息。

3. 消费者

3.1 引入通用模块

由于消费者也需要使用刚刚的工具类和UserDto用来接收消息。
在这里插入图片描述
而这些工具类和UserDto都在模块rabbitmq-demo中。因此,在消费者模块中引入该生产者模块(如果这些通用的配置和实体类dto都在一个通用的模块common中,哪些模块需要发送消息,哪些模块需要监听消息,就都引入common模块就行了)

    <groupId>com.gzdemo</groupId>
    <artifactId>rabbitmq-demo</artifactId>
    <version>1.0-SNAPSHOT</version>

因为rabbitmq-demo模块中已经引入了RabbitMq相关依赖,因此消费者模块不需要重复引入RabbitMq相关的依赖。只需要把依赖包添加到classpath下,再import就行了
在这里插入图片描述
在这里插入图片描述

3.2 配置yml

与生产者的配置相同,通常只有消费者才需要配置listener,生产者不需要。
在这里插入图片描述

3.3 编写listener

import com.gzdemo.rabbitmq.pojos.UserDto;

import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

@Component
public class UserListener {
    /**
     * 监听消息
     */
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = "learning.lesson.pay.queue", durable = "true"),
            exchange = @Exchange(name = "order.topic", type = ExchangeTypes.TOPIC),
            key = "order.pay"
    ))
    public void listenLessonPay(UserDto userDto){
        System.out.println(userDto);
    }
}

3.4 消费者目录结构

这里是随便找了个同工程中的子模块作为消费者测试,在UserListener类中监听消息
在这里插入图片描述

4 测试消息发送、监听

启动这两个服务,浏览器访问http://127.0.0.1:8080/sendMsg,多访问几次后发现消费者接收到了消息
在这里插入图片描述生产者console

2024-06-14 05:46:39.187  INFO 106168 --- [nio-8080-exec-1] o.s.a.r.c.CachingConnectionFactory       : Attempting to connect to: [192.168.150.101:5672]
2024-06-14 05:46:39.210  INFO 106168 --- [nio-8080-exec-1] o.s.a.r.c.CachingConnectionFactory       : Created new connection: rabbitConnectionFactory#399d82:0/SimpleConnection@1673b17 [delegate=amqp://admin@192.168.150.101:5672/vhost0, localPort= 61317]

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

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

相关文章

VD1011 单节锂离子充电电池保护 2.8V过放保护 SOT-23小封装芯片

VD1011&#xff0c;内置高精度电压检测电路和延迟电路以及内置MOSFET&#xff0c;是用于单节锂离子/锂聚合物可再充电 电池的保护IC。 本IC适合干对1节锂离子/锂聚合物可再充电电池的过充电、过放电和过电流进行保护。 VD1011具备如下特点 高精度电压检测电路 过充电检测电压 …

PyTorch计算机视觉入门:使用自己的数据集训练神经网络

前言 计算机视觉&#xff0c;作为人工智能领域的一个重要分支&#xff0c;近年来在图像识别、物体检测、图像生成等应用上取得了显著的进步。PyTorch&#xff0c;作为一款灵活且强大的深度学习框架&#xff0c;为开发者提供了便捷的工具来构建和训练计算机视觉模型。本文将指导…

【面试干货】ArrayList、Vector、LinkedList的存储性能和特性比较

【面试干货】ArrayList、Vector、LinkedList的存储性能和特性比较 1、ArrayList1.1 存储性能1.2 特性1.3 示例用法 2、Vector2.1 存储性能2.2 特性2.3 示例用法 3、LinkedList3.1 存储性能3.2 特性3.3 示例用法 4、ArrayList、Vector、LinkedList用法总结 &#x1f496;The Beg…

如何在 Windows 10/11 上编辑 PDF [4 种简单方法]

PDF 在大多数设备上都易于查看&#xff0c;但由于其设计用于查看&#xff0c;因此编辑起来可能比较棘手。编辑 PDF 可能比编辑 Microsoft Office 文档更具挑战性。 不用担心&#xff0c;我们已经为你做好了准备。无论你是想添加、删除还是插入文本或图片&#xff0c;你都可以使…

操作系统复习-线程同步

互斥量 两个线程的指令交叉执行互斥量可以保证先后执行称为原子性 原子性是指一系列操作不可被中断的特性这一系列操作要么全部执行完成&#xff0c;要么全部没有执行不存在部分执行部分未执行的情况 互斥锁 互斥量是最简单的线程同步的方法互斥锁&#xff0c;处于两态之一的…

环保绩效评级:ABCD四个等级,你的企业处于哪个水平?

在当下社会&#xff0c;环保问题越来越受到人们的关注和重视。企业作为经济活动的重要参与者&#xff0c;其环保绩效评级直接关系到环境保护的成效。朗观视觉将详细解析环保绩效评级的ABCD四等级&#xff0c;帮助读者了解不同等级的特点和评判标准&#xff0c;进而引导企业提高…

利用钉钉机器人和PHP开发一款免费的网站可用性检测工具,单节点版

前言 手里有几套系统正在运维&#xff0c;需要保障正常运行&#xff0c;所以可用性检测就必不可少啦&#xff0c; 以前本来是用的阿里官方的云监控&#xff0c;但现在价格感觉太贵了&#xff0c;不划算 那就自己手搓一个简易版的监控吧。 成品效果展示 代码展示 <?php …

远程桌面端口,怎么修改远程桌面端口

修改注册表 打开注册表编辑器&#xff1a; 按下 Windows键R 或者从开始菜单选择“运行”&#xff0c;打开运行窗口。 输入 regedit 命令&#xff0c;然后点击“确定”打开注册表编辑器。 定位到远程桌面服务的端口设置&#xff1a; 在注册表编辑器中&#xff0c;按照以下路径找…

Postman接口调用详情用法Postman 的作用-测试 API帮助开发者发送各种类型的请求

本人详解 作者:王文峰,参加过 CSDN 2020年度博客之星,《Java王大师王天师》 公众号:JAVA开发王大师,专注于天道酬勤的 Java 开发问题中国国学、传统文化和代码爱好者的程序人生,期待你的关注和支持!本人外号:神秘小峯 山峯 转载说明:务必注明来源(注明:作者:王文峰…

铝壳电阻的安装和使用注意事项有哪些?

铝壳电阻是一种常见的电子元件&#xff0c;广泛应用于各种电子设备中。为了确保铝壳电阻的正常工作和使用寿命&#xff0c;安装和使用过程中需要注意以下几点&#xff1a; 1. 选择合适的铝壳电阻&#xff1a;根据电路的实际需求&#xff0c;选择合适的阻值、功率和尺寸的铝壳电…

【仿真建模-anylogic】Statechart原理解析

Author&#xff1a;赵志乾 Date&#xff1a;2024-06-15 Declaration&#xff1a;All Right Reserved&#xff01;&#xff01;&#xff01; 1. 类图 2. 原理解析 2.1 核心函数 Statechart的核心函数如下&#xff1a; 函数功能Statechart(Agent owner, short maxat)构造函数&…

【算法专题--链表】反转链表II--高频面试题(图文详解,小白一看就会!!!)

目录 一、前言 二、题目描述 三、解题方法 ⭐迭代法 --- 带哨兵位&#xff08;头节点&#xff09; &#x1f95d; 什么是哨兵位头节点&#xff1f; &#x1f34d; 解题思路 四、总结与提炼 五、共勉 一、前言 反转链表II这道题&#xff0c;可以说是--链表专题--&am…

《书生·浦语大模型实战营》第4课 学习笔记:XTuner 微调 LLM:1.8B、多模态、Agent

文章大纲 1. 大模型微调简介2 快速上手2.1 环境安装2.2 前期准备2.2.1 数据集准备2.2.2 模型准备2.2.3 配置文件选择2.2.4 小结 2.3 配置文件修改2.4 模型训练2.4.1 常规训练2.4.2 使用 deepspeed 来加速训练2.4.3 训练结果2.4.4 小结 2.5 模型转换、整合、测试及部署2.5.1 模型…

消费者消费数据时报错:INVALID_REPLICATION_FACTOR

今天部署了kafka集群&#xff0c;三台服务器&#xff0c;启动后&#xff0c;生产者发送数据&#xff0c;消费者接收数据的时候报错&#xff0c;INVALID_REPLICATION_FACTOR。 查了很多资料&#xff0c;说是要改kafka下config目录的server.properties,可能是副本数太小&#xff…

Java17 --- RabbitMQ搭建集群

目录 一、使用docker搭建集群 二、使用docker安装Haproxy 三、使用springboot进行测试 3.1、创建交换机与队列关系 四、仲裁队列替代镜像队列 4.1、创建交换机与队列关系 一、使用docker搭建集群 由于contos7环境不能装rabbitmq3.13版本的&#xff0c;采用docker安装避…

Qt MaintenanceTool.exe使用镜像源更新Qt

环境&#xff1a;Windows11&#xff0c;Qt6.5&#xff0c;新版的MaintenanceTool.exe linux环境类似&#xff0c;mac环境可以看官方文档。 cmd命令窗口&#xff1a;切换到MaintenanceTool.exe所在目录&#xff0c;可以用“D:”切换到D盘&#xff0c;“cd xxxx”切换到xxxx目录…

欢乐钓鱼大师通关必备秘籍!云手机游戏辅助!

《欢乐钓鱼大师》是一款让玩家沉浸在放松钓鱼乐趣中的手机游戏。不同于传统钓鱼游戏&#xff0c;它融合了收集、升级和竞技等元素&#xff0c;让每位玩家可以根据自己的喜好和目标来发展钓鱼技艺。本攻略将为您详细介绍如何在游戏中迅速提升实力&#xff0c;达到通关的最高境界…

upload-labs第十二关教程

upload-labs第十二关教程 一、源代码分析代码审计 二、绕过分析截断绕过magic_quotes_gpc函数介绍关闭magic_quotes_gpc上传eval.png文件使用burpsuite进行抓包修改放包&#xff0c;查看是否上传成功使用中国蚁剑进行连接 一、源代码分析 代码审计 $is_upload false; $msg …

k8s快速上手实操

前言 Kubernetes&#xff08;简称K8s&#xff09;是由Google开源的一个用于自动化部署、扩展和管理容器化应用程序的系统。自2014年发布以来&#xff0c;Kubernetes已经迅速成长为容器编排领域的标准&#xff0c;并在全球范围内得到了广泛的采用和认可。 Kubernetes作为现代容…

最新情侣飞行棋高阶羞羞版,解锁私密版情侣小游戏,文末有福利!

今天要跟大家聊聊一种特别有意思的游戏——情侣飞行棋羞羞版。别急着脸红&#xff0c;这可是专为情侣设计的游戏&#xff0c;让你们在轻松愉快的氛围中&#xff0c;增进了解&#xff0c;加深感情。 谈恋爱&#xff0c;不就是两个人在一起&#xff0c;做些有趣的事情吗&#xf…