Docker-Dockerfile讲解(二)

背景

最近同事发现线上发送的RocketMQ消息太大,同事为了节省网络带宽和存储空间,手动压缩消息然后再进行消息发送,发现磁盘也没有明显的缩减

所以我打算结合源码告诉他RocketMQ自带的消息压缩

同时听了发出了这个表情包

RocketMQ版本

  • 5.1.0

为什么需要压缩消息

首先说一下为什么需要消息压缩,原因其实很简单。就是为了节省网络带宽和存储空间。

在哪里压缩消息

我们的消息压缩可以在很多个地方进行

有两种方案

  1. 在client端进行压缩

比如我们可以在Producer发送消息的时候进行消息压缩

然后将压缩后的消息发送到Brokerbroker只管存储

等到consumer需要消息的时候,原封不动的推送给消费者,由consumer自己进行解压缩

这种方式的好处是broker不需要关心消息的压缩和解压缩,只需要存储消息即可

  1. 在broker端进行压缩

这种方式就是Producer发送消息的时候,不进行压缩

RocketMQ在存储的时候自己进行消息压缩,consumer进行消息拉取的时候,broker进行消息解压缩,然后推送给consumer

这种方式就是消耗broker cpu,也不能节省网络带宽,只能节省存储空间

所以很明显是在client端进行压缩比较好

源码分析

这里我们来具体结合源码分析下

在消息发送org.apache.rocketmq.client.impl.producer.DefaultMQProducerImpl.sendKernelImpl方法中会对消息进行压缩判断

tryToCompressMessage 消息压缩

什么消息会被压缩呢?


java

代码解读

复制代码

private boolean tryToCompressMessage(final Message msg) { if (msg instanceof MessageBatch) { //batch does not support compressing right now return false; } byte[] body = msg.getBody(); if (body != null) { if (body.length >= this.defaultMQProducer.getCompressMsgBodyOverHowmuch()) { try { byte[] data = compressor.compress(body, compressLevel); if (data != null) { msg.setBody(data); return true; } } catch (IOException e) { log.error("tryToCompressMessage exception", e); log.warn(msg.toString()); } } } return false; }

  1. 批量消息不支持压缩
  2. 消息体长度大于defaultMQProducer.getCompressMsgBodyOverHowmuch()的时候进行压缩。默认1024 * 4 = 4kb
  3. 压缩算法是什么呢?

RocketMQ目前提供三种压缩算法

  • LZ4
  • ZSTD
  • ZLIB

默认压缩算法为ZLIB


java

代码解读

复制代码

private CompressionType compressType = CompressionType.of(System.getProperty(MixAll.MESSAGE_COMPRESS_TYPE, "ZLIB"));

压缩等级为5


java

代码解读

复制代码

private int compressLevel = Integer.parseInt(System.getProperty(MixAll.MESSAGE_COMPRESS_LEVEL, "5"));

  1. 消息压缩完后会通过sysFlag进行标记,表示消息进行了压缩,方便后续解压

java

代码解读

复制代码

sysFlag |= MessageSysFlag.COMPRESSED_FLAG; sysFlag |= compressType.getCompressionFlag();

消息解压

消息解压主要是在方法org.apache.rocketmq.common.message.MessageDecoder.decode(java.nio.ByteBuffer, boolean, boolean, boolean, boolean, boolean)中进行的

client拉取到消息成功后对PullResult对象进行处理执行decodesBatch方法

消息解析decodesBatch方法会调用org.apache.rocketmq.common.message.MessageDecoder.decode(java.nio.ByteBuffer, boolean, boolean, boolean, boolean, boolean)方法

decode方法会对消息进行解压

总结

  • 消息压缩主要是为了节省网络带宽和存储空间。
  • RocketMQ提供了三种压缩算法,分别是LZ4ZSTDZLIB,默认为ZLIB
  • 消息压缩主要是在Producer发送消息的时候进行压缩,broker只管存储
  • 消息解压主要是在Consumer拉取消息的时候进行解压
  • RocketMQ消息压缩仅支持单条消息压缩,不支持批量消息压缩
  • 一般消息压缩都会选择在client端进行压缩,这样可以节省broker的cpu
<think>好的,我现在要解决用户关于docker-compose build命令的用法和功能的询问。首先,我需要回忆自己对这个命令的了解。docker-compose build主要用于根据docker-compose.yml中的配置构建或重新构建服务对应的镜像。用户可能在使用docker-compose时,需要自定义镜像或者修改了Dockerfile后重新构建,这时候就会用到build命令。 接下来,我需要确认用户的需求。他们想要详细的教程和功能详解。这意味着我需要分步骤解释如何使用这个命令,同时说明它的各个选项和适用场景。根据提供的引用内容,用户可能已经了解了一些docker-compose的基础知识,比如up -d和scale命令,但需要更深入build的具体信息。 我需要查阅相关的资料,确保信息的准确性。例如,docker-compose build命令的基本用法是构建服务,但有哪些参数可以使用?比如--no-cache选项可以避免使用缓存,这在需要全新构建时很有用。还有--pull参数可以拉取最新的基础镜像。这些参数的功能需要详细说明。 同时,用户可能想知道什么时候应该使用build命令。比如,当修改了Dockerfile或者项目文件后,需要重新构建镜像才能应用这些更改。这时候运行docker-compose build,再运行up命令就会使用新的镜像启动容器。 还要注意,docker-compose build默认只会构建那些在配置文件中指定了build上下文的服务。如果服务使用的是预构建的镜像(比如image: nginx),则不会触发构建过程。这一点需要明确说明,避免用户混淆。 另外,结合用户提供的引用内容,引用[2]提到Dockerfile的作用,而引用[3]和[4]涉及docker-compose的部署和命令使用,这可以帮助用户理解build在整个流程中的位置。比如,构建镜像是部署的前置步骤,之后才能通过up命令启动服务。 可能用户还会遇到常见问题,比如构建时缓存导致的问题,这时候需要指导他们使用--no-cache选项。或者如何同时构建多个服务,这时候需要指定服务名称作为参数。 最后,生成相关问题的时候,要考虑用户可能进一步询问的内容,比如优化构建时间、多阶段构建,或者如何结合其他命令如up一起使用。这些相关问题可以帮助用户更全面地掌握docker-compose build的应用场景和高级用法。</think>### Docker Compose Build 命令详解 #### **功能概述** `docker-compose build` 用于根据 `docker-compose.yml` 文件中定义的配置,构建或重新构建服务的镜像。此命令适用于以下场景: 1. 修改了服务的 `Dockerfile` 或构建上下文文件后,需要重新生成镜像。 2. 需要强制重新构建镜像(跳过缓存)。 3. 在部署前手动构建镜像,而非依赖远程仓库的预构建镜像[^2][^3]。 --- #### **基础用法** 1. **构建所有服务镜像**: ```bash docker-compose build ``` 默认会构建 `docker-compose.yml` 中所有包含 `build` 字段的服务。 2. **构建指定服务镜像**: ```bash docker-compose build [服务名1] [服务名2] ``` 例如 `docker-compose build web database`,仅构建 `web` 和 `database` 服务。 --- #### **核心参数详解** | 参数 | 功能描述 | |-------------------|------------------------------------------------------------------------------------------| | `--no-cache` | 构建时忽略缓存,强制重新执行所有步骤(例如修改了 `Dockerfile` 的中间步骤时使用)。 | | `--pull` | 在构建前拉取基础镜像的最新版本(确保使用最新的 `FROM` 镜像)。 | | `--build-arg` | 传递构建参数到 `Dockerfile`,格式为 `--build-arg KEY=VALUE`。 | | `--force-rm` | 构建完成后删除中间容器(优化存储空间)。 | --- #### **典型使用场景** 1. **修改代码后重新构建镜像** 假设 `web` 服务的镜像依赖项目代码: ```bash # 修改代码后执行 docker-compose build web docker-compose up -d # 重新启动服务以应用新镜像[^4] ``` 2. **多阶段构建优化** 若 `Dockerfile` 使用多阶段构建(如分离编译环境和运行环境),可通过 `build` 确保生成最小化镜像: ```dockerfile # Dockerfile 示例 FROM golang:1.19 AS builder WORKDIR /app COPY . . RUN go build -o myapp FROM alpine:latest COPY --from=builder /app/myapp /usr/local/bin/ CMD ["myapp"] ``` 执行 `docker-compose build` 后,会按阶段生成最终镜像。 --- #### **注意事项** 1. **与 `docker-compose up` 的关系** - 若直接运行 `docker-compose up`,默认会自动构建缺失的镜像。 - 使用 `docker-compose up --build` 可合并构建和启动步骤(等价于 `build` + `up`)。 2. **镜像命名规则** 若 `docker-compose.yml` 中未指定 `image` 字段,生成的镜像名称格式为 `[项目名]_[服务名]:latest`。 例如项目名为 `myapp`,服务名为 `web`,则镜像为 `myapp_web:latest`[^3]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值