【RabbitMQ的那点事】使用Docker/Docker Compose安装RabbitMQ,并安装Delayed Message插件

2,556 阅读4分钟

【本文内容】

  • 通过docker安装rabbitmq,并使用Spring Boot项目进行测试。
  • 通过Dockerfile安装rabbitmq_delayed_message_exchange插件实现延迟消息
  • 通过docker compose安装rabbitmq(以及delayed message插件),并同时启动Spring Boot项目进行测试。

【版本】

  • docker version: v1.0.23
  • docker compose version: v2.4.1

1. 官方镜像

hub.docker.com/_/rabbitmq

我使用的是rabbitmq:3-management,详细镜像说明请查看:链接 image.png

rabbitmq:3和3-management区别是management版本会预先安装RabbitMQ management并启动。

2. 通过docker安装并启动rabbitmq

2.1 启动rabbitmq

docker run -d --name my-rabbit -e RABBITMQ_DEFAULT_VHOST=my_vhost
-p 5672:5672 -p 15672:15672 rabbitmq:3-management

  • -d:后台运行
  • --name:docker name
  • -e RABBITMQ_DEFAULT_VHOST:声明rabbitmq的virtual host,默认为/
  • -p:暴露port,5672为amqp协议端口,即程序连接rabbitmq的端口,15672为console界面的端口。

启动后查看:image.png

2.2 Web Console界面

因为我们有设置自定义的vhost,可以看到已经创建了vhost=my_vhost:image.png

2.3 通过Spring Boot程序验证

使用的是Spring Boot v2.7.0 + Spring Cloud Stream。 关于Spring Boot parent依赖:略 加上Spring Cloud Stream依赖:

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-stream-binder-rabbit</artifactId>
            <version>3.2.4</version>
        </dependency>

application.properties中配置:

spring.rabbitmq.host=localhost
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
spring.rabbitmq.port=5672
spring.rabbitmq.virtual-host=my_vhost

创建一个Consumer:

@Configuration
public class ConsumerConfig {

    @Bean
    public Consumer<String> helloConsumer() {
        return message -> log.info("Received Message: {}", message);
    }
}

启动后,我们在Console的exchange=helloConsumer-in-0中发布一条测试消息:image.png

程序接收到消息:image.png

3. 在docker中安装rabbitmq_delayed_message_exchange插件实现延迟消息

关于本地rabbitmq安装,详细查看文件:【RabbitMQ的那点事】利用rabbitmq_delayed_message_exchange插件实现延迟消息(超详细)

3.1 下载delayed message插件:

地址:github.com/rabbitmq/ra… image.png

3.2 创建Dockerfile

目录:image.png

Dockerfile文件:

FROM rabbitmq:3-management
COPY ./plugin/rabbitmq_delayed_message_exchange-3.11.1.ez /opt/rabbitmq/plugins/
RUN rabbitmq-plugins enable rabbitmq_delayed_message_exchange
3.3 build image

Dockerfile文件所在目录build镜像:

docker build -t rabbitmq-with-plugin .

参数-t表示打上tag。

3.4 运行image

和#2.1的docker run命令相似,只不过把image换成我们自己的image:

docker run -d --name my-rabbit -e RABBITMQ_DEFAULT_VHOST=my_vhost
-p 5672:5672 -p 15672:15672 rabbitmq-with-plugin:latest

3.5 测试

进入http://localhost:15672/#/exchanges,在新建exchange的选择中看到有type=x-delayed-message选项了。

依旧使用Spring Cloud Stream进行测试,关于delayed message在Stream中的配置,详细参考:cloud.spring.io/spring-clou…

创建一个Comsumer:

    @Bean
    public Consumer<String> helloDelayedConsumer() {
        return message -> log.info("Received Delayed Message: {}", message);
    }

application.yaml配置(其中helloConsumer方法是#2.3的测试):

spring.cloud.function.definition=helloConsumer;helloDelayedConsumer
spring.cloud.stream.rabbit.bindings.helloDelayedConsumer-in-0.consumer.delayed-exchange=true

写一个发送端代码:

@SpringBootTest
public class ProducerServiceTest {
    @Autowired
    private RabbitTemplate rabbitTemplate;
 
    @Test
    public void sendMessageToDelayedExchange() throws InterruptedException {
        log.info("Start to send delayed message...");
        rabbitTemplate.convertAndSend("helloDelayedConsumer-in-0", "#", "hello delayed message!", new MessagePostProcessor() {
            @Override
            public Message postProcessMessage(Message message) throws AmqpException {
                // 设置消息延迟时间,单位 ms
                message.getMessageProperties().setHeader("x-delay", 20 * 1000);
                return message;
            }
        });
        log.info("Finished sending delayed message...");

        Thread.sleep(40000L);
    }
}

运行后log,可以看到消息在20秒后被送达:

2023-03-12 22:32:33.508 INFO 84955 --- [ main] com.config.ProducerServiceTest : Start to send delayed message... 2023-03-12 22:32:33.514 INFO 84955 --- [ main] com.config.ProducerServiceTest : Finished sending delayed message... 2023-03-12 22:32:53.540 INFO 84955 --- [vKkmI55vu0cAw-1] com.config.ConsumerConfig : Received Delayed Message: hello delayed message!


4. 通过Docker Compose安装

4.1 创建Spring Boot项目

application.properties文件,将rabbitmq配置换成从docker-compose.yml中读取,其它的配置参考上述#3.5:

spring.rabbitmq.host=${SPRING_RABBITMQ_HOST}
spring.rabbitmq.username=${SPRING_RABBITMQ_USERNAME}
spring.rabbitmq.password=${SPRING_RABBITMQ_PASSWORD}
spring.rabbitmq.port=${SPRING_RABBITMQ_PORT}
spring.rabbitmq.virtual-host=${SPRING_RABBITMQ_DEFAULT_VHOST}

依旧使用的是上述的两个Consumer测试,编写Controller用于测试:

@RestController
public class StreamBridgeController {
    @Autowired
    private StreamBridge streamBridge;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @GetMapping("message")
    public String sendMessage() {
        streamBridge.send("helloConsumer-in-0", "hello consumer...");
        return "success";
    }

    @GetMapping("delayed-message")
    public String sendMessageToDelayedExchange() throws InterruptedException {
        // 略,详细看#3.5测试用例
        return "success";
    }
}

项目pom.xml中,记得添加为可执行的jar:

<build>
        <finalName>user-create-service</finalName>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

编写项目的Dockerfile:

FROM openjdk:17-alpine
COPY target/user-create-service.jar user-create-service.jar

expose 8085
ENTRYPOINT ["java","-jar","user-create-service.jar"]
4.2 编写docker-compose.yml

这里沿用了rabbit-docker中的Dockerfile,详细参考#3.2

version: "3.7"

services:
  rabbit-test:
    build:
      context: ./rabbit-docker/
      dockerfile: Dockerfile
    image: rabbit-management:latest
    container_name: rabbit-test
    hostname: rabbit-host
    networks:
      - appnet
    ports:
      - "5672:5672"
      - "15672:15672"
    environment:
      - RABBITMQ_DEFAULT_USER=guest
      - RABBITMQ_DEFAULT_PASS=guest
      - RABBITMQ_DEFAULT_VHOST=test_vhost
    volumes:
      - rabbit-volume:/opt/rabbit/data
    restart: always

  user-create-service:
    build: user-create-service/
    image: user-create-service:latest
    container_name: user-create-service
    depends_on:
      - rabbit-test
    environment:
      - SPRING_RABBITMQ_HOST=rabbit-host
      - SPRING_RABBITMQ_USERNAME=guest
      - SPRING_RABBITMQ_PASSWORD=guest
      - SPRING_RABBITMQ_PORT=5672
      - SPRING_RABBITMQ_DEFAULT_VHOST=test_vhost
    networks:
      - appnet
    ports:
      - "8085:8085"
    restart: always

networks:
  appnet:
    driver: bridge

volumes:
  rabbit-volume:
    name: rabbit-volume
4.3 docker compose build/up

使用docker compose build来build镜像:

docker compose build

image.png

build好后使用docker compose up来启动:

docker compose up

本质上通过docker compose帮忙启动了两个container,一个是rabbitmq,一个是Spring Boot项目,所以也可以用docker ps查看正在运行的container。

4.4 测试

调用#4.1创建的两个API进行测试:

打印日志:

user-create-service | 2023-03-12 14:45:54.617 INFO 1 --- [nio-8085-exec-2] com.config.ConsumerConfig : Received Message: hello consumer...

user-create-service | 2023-03-12 14:46:02.255 INFO 1 --- [nio-8085-exec-1] com.web.StreamBridgeController : Start to send delayed message... user-create-service | 2023-03-12 14:46:02.263 INFO 1 --- [nio-8085-exec-1] com.web.StreamBridgeController : Finished sending delayed message... user-create-service | 2023-03-12 14:46:22.260 INFO 1 --- [dmwnKxEmjXUWg-1] com.config.ConsumerConfig : Received Delayed Message: hello delayed message!

4.5 docker compose stop/rm
  • 通过docker compose stop进行关闭。
  • 通过docker compose rm进行删除。