You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MQTT相关Docker容器运行时冻结延迟问题求助

问题描述

我搭建了三个Docker容器:

  • 基于Python paho-mqtt的消息发布容器:每秒通过MQTT协议发送消息
  • 消息订阅容器:接收MQTT消息
  • Mosquitto MQTT服务器容器

容器构建命令

docker image build -t publisher /path/to/dockerfile folder
docker image build -t subscriber /path/to/dockerfile folder

发布者容器Dockerfile

FROM python:3.9.7

WORKDIR /app

COPY requirements.txt requirements.txt
RUN pip3 install -r requirements.txt

EXPOSE 1883

COPY . .

CMD [ "python", "app.py" ]

Mosquitto服务器日志(运行正常)

1658502881: mosquitto version 2.0.14 running
1658502881: New connection from 172.17.0.5:53757 on port 1883.
1658502881: New client connected from 172.17.0.5:53757 as python-mqtt-29 (p2, c1, k60).
1658502881: New connection from 172.17.0.4:45437 on port 1883.
1658502881: New client connected from 172.17.0.4:45437 as python-mqtt-12 (p2, c1, k60).

异常现象

运行docker run publisher或订阅者容器时,终端会冻结2-3分钟,之后所有消息突然批量显示。

运行中的容器
2-3分钟后的发布/订阅容器


附代码

发布者应用代码

import random
import time
from paho.mqtt import client as mqtt_client

broker = '172.17.0.3'
port = 1883
topic = "python/mqtt"

client_id = f'python-mqtt-{random.randint(0, 1000)}'

def connect_mqtt():
    def on_connect(client, userdata, flags, rc):
        if rc == 0:
            print("Connected to MQTT Broker!")
        else:
            print("Failed to connect, return code %d\n", rc)

    client = mqtt_client.Client(client_id)
    client.on_connect = on_connect
    client.connect(broker, port)
    return client

def publish(client):
    msg_count = 0
    while True:
        time.sleep(1)
        msg = f"messages: {msg_count}"
        result = client.publish(topic, msg)
        # result: [0, 1]
        status = result[0]
        if status == 0:
            print(f"Send `{msg}` to topic `{topic}`")
        else:
            print(f"Failed to send message to topic {topic}")
        msg_count += 1

def run():
    client = connect_mqtt()
    client.loop_start()
    publish(client)

if __name__ == '__main__':
    run()

订阅者应用代码

import random
import pandas
from paho.mqtt import client as mqtt_client

broker = '172.17.0.3'
port = 1883
topic = "python/mqtt"
client_id = f'python-mqtt-{random.randint(0, 100)}'


def connect_mqtt() -> mqtt_client:
    def on_connect(client, userdata, flags, rc):
        if rc == 0:
            print("Connected to MQTT Broker!")
        else:
            print("Failed to connect, return code %d\n", rc)

    client = mqtt_client.Client(client_id)
    client.on_connect = on_connect
    client.connect(broker, port)
    return client


def subscribe(client: mqtt_client):
    def on_message(client, userdata, msg):
        print(f"Received `{msg.payload.decode()}` from `{msg.topic}` topic")

    client.subscribe(topic)
    client.on_message = on_message


def run():
    client = connect_mqtt()
    subscribe(client)
    client.loop_forever()


if __name__ == '__main__':
    run()

解决方案

核心原因:Python输出缓冲延迟

Python的print函数默认会缓冲输出,当容器运行时stdout不是交互式终端(TTY),缓冲会累积到一定阈值才一次性输出,这就是你看到2-3分钟后批量显示的根本原因。

具体解决方法

方法1:启动容器时分配TTY

运行容器时添加-it参数,强制Docker分配交互式终端,Python会自动禁用输出缓冲:

docker run -it publisher
docker run -it subscriber

方法2:修改代码强制刷新输出

在所有print语句后添加flush=True参数,实时刷新输出缓冲:

# 发布者代码修改
print(f"Send `{msg}` to topic `{topic}`", flush=True)
print(f"Failed to send message to topic {topic}", flush=True)

# 订阅者代码修改
print(f"Received `{msg.payload.decode()}` from `{msg.topic}` topic", flush=True)

方法3:修改Dockerfile禁用Python缓冲

在启动命令中添加-u参数,强制Python使用无缓冲输出:

CMD [ "python", "-u", "app.py" ]

额外排查点:容器网络延迟

如果以上方法无效,可检查容器间网络连通性:

  1. 进入发布者容器ping Mosquitto服务器IP:
docker exec -it <publisher-container-id> ping 172.17.0.3

若延迟过高,建议改用Docker自定义网桥替代默认bridge网络,避免IP冲突或网络拥堵。

内容的提问来源于stack exchange,提问作者m sh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 17:24:30