news 2026/9/12 2:48:11

Mosquitto监控与日志管理实战:从$SYS主题到Prometheus告警

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Mosquitto监控与日志管理实战:从$SYS主题到Prometheus告警

1. 1 先讲清楚为什么Mosquitto监控与日志管理不是可选项

干物联网、嵌入式、智能硬件运维的朋友应该都有这种感觉:设备一多,消息链路就像早高峰的地铁——谁挤上去了、谁被挤下去了、哪趟车堵在哪了,你根本看不见。MQTT Broker在这条链路里就是那个总调度室,而Mosquitto作为最主流的开源轻量级Broker,被嵌在网关、边缘盒子、树莓派、工控机里的情况实在太常见了。可越是这种“默默蹲在角落跑服务”的角色,越容易出问题之后让人抓瞎:终端侧疯狂重连、消息莫名延迟、内存悄悄涨满,等你接到用户投诉再上去看,日志已经被冲掉了一半。这时候你才会意识到,“监控与日志管理”这几个字,在Mosquitto的日常维护里到底有多重。

这篇文章想分享的就是一套从零到一给Mosquitto补上“眼睛和记忆”的完整做法:怎么把它的日志配置得又全又不占地方,怎么用$SYS主题拿到关键运行指标,怎么接进Prometheus、Grafana、Alertmanager这一套现代监控体系,以及我这些年排查Broker问题攒下来的一些现场经验。不管你是已经在生产环境跑着几十上百台网关,还是正在实验室里调一个嵌入式设备,这套思路都能直接用,能帮你少踩很多坑。

顺便说一句,主题虽然是“第13章”,但你不用觉得自己必须看到前12章才能上手。这一篇是独立成章的,前面没看过的朋友也不影响理解,核心的命令、配置、思路我都会从实操角度讲清楚。

1.2 监控与日志该从哪几个层面去搭

我发现很多朋友一上来就问我“用什么工具监控Mosquitto最屌”,这个问法本身就偏了。真正的做法不是先选工具,而是先把需求拆开。

一套完整的Mosquitto可观测体系,至少得覆盖下面三个层面。

第一层:Broker本身的健康状态。包括进程在不在、CPU和内存占用多少、文件描述符有没有耗尽、线程池有没有打满。这一层管的是“Mosquitto还活着吗、活得好不好”的问题。对单机部署的Mosquitto来说,直接看systemd状态和系统指标就够用;对跑在容器里的节点,那就是看容器资源使用率。

第二层:Broker的业务运行指标。这一层才是MQTT场景的核心,包括当前在线客户端数、每秒收发消息量、订阅总数、持久会话数量、消息丢弃数、字节流量等。这些东西Mosquitto本身没直接给出一份JSON统计文件,但它在启动后会在$SYS主题树下持续发布内部计数器,我们只需要订阅这些主题就能拿到。

第三层:行为痕迹与异常线索。也就是日志。谁连上来了、谁断线了、谁发了个非法包、ACL拒绝了什么操作、WebSocket握手失败在哪个环节,这些全部要落到日志里。平时日志可以安静躺着,一旦出问题,它就是第一手犯罪现场。

想清楚这三层之后,再去看工具选型就顺了。我的推荐组合是:

  • 系统层用Prometheus + node_exporter,覆盖面广,社区资料多。
  • Broker业务指标用mosquitto_exporter(稍后会细讲这个开源组件),它负责订阅$SYS主题并转成Metrics格式给Prometheus拉取。
  • 日志管理直接用logrotate做本地轮转,再配合Promtail + LokiFilebeat + ELK做集中式日志检索,有条件的可以上,没条件的先把本地轮转做好也完全够用。

这套组合重量最轻、数据从采集到展示的链路最短,非常契合嵌入式网关那种资源有限、网络不稳定的现实条件。


2.1 日志级别:不是越详细越好,但要先知道每个开关在干什么

Mosquitto的日志系统配置在它的主配置文件mosquitto.conf里,核心参数就两个:log_typelog_dest。你只要把这两个参数吃透,日志管理就掌握了八成。

先看log_type,它决定的是记什么。常见取值有这些:

  • error:仅记录错误,正常运行时几乎无输出。
  • warning:记录潜在隐患,比如客户端用了不推荐的协议版本。
  • notice:默认级别,记录连接断开等关键生命周期事件。
  • information:再细一档,会记录订阅、取消订阅、转发等操作。
  • subscribe:专门记录订阅和退订操作,排查某个客户端为何收到/收不到消息时非常有用。
  • unsubscribe:记录退订操作。
  • websockets:记录WebSocket连接细节,注意这个参数在编译时未启用WebSocket支持的版本里会直接报错,先确认你的版本。
  • all:打开所有日志,包括debug调试信息。
  • debug:最啰嗦的级别,会刷出协议内部状态,日常千万别开,生产环境开了基本等于把磁盘和CPU往火坑里推。

默认情况下,Mosquitto开启的是errorwarningnoticeinformation,大概相当于“不吵不闹但关键时刻不掉链子”。我的建议是:除非你在排一个特别诡异的协议兼容问题,否则别动alldebug如果真要开debug,开完立刻关掉。

再看log_dest,它决定的是记到哪里。常见取值有stdoutstderrsyslogfiletopic。这五个通道可以同时启用多个,写法是每行写一个log_dest

这里我贴一份我在边缘网关上常用的配置,注释都写清楚了:

# /etc/mosquitto/conf.d/logging.conf # 记录哪几类事件 log_type error log_type warning log_type notice log_type information # 输出到系统日志,方便用 journalctl -u mosquitto 查看 log_dest syslog # 同时落一份到独立文件,方便直接tail观察 log_dest file /var/log/mosquitto/mosquitto.log # 输出带时间戳 log_timestamp true

这个组合的好处是:syslog通道会让你在用systemd管理的发行版上直接journalctl -u mosquitto -f看到实时日志,体验非常顺滑;而file通道则保证就算journald被清理了,也有一份JSON格式友好的原始文本文件留在磁盘上。

如果你习惯用Docker部署Mosquitto,我建议把日志直接打到stdout,然后交给Docker的json-file日志驱动去统一管理,不要自己映射一个日志文件进去,否则docker logs看不到东西,排查时还得docker exec进去看文件,绕了一大圈。

2.2 日志轮转:一条logrotate配置解决磁盘跑满的隐患

日志如果不轮转,最直接的结果就是半年后/var分区被一个几十GB的单文件塞满,到时候别说监控了,系统自己先崩给你看。

Linux上管理Mosquitto日志轮转,最标准的做法是写一个logrotate规则。大部分发行版的Mosquitto安装包自带了一份,路径在/etc/logrotate.d/mosquitto,但默认配置可能比较简单,我通常都会改成下面这样:

# /etc/logrotate.d/mosquitto /var/log/mosquitto/mosquitto.log { daily rotate 14 compress delaycompress missingok notifempty copytruncate create 640 mosquitto mosquitto }

逐行解释几个关键参数:

  • daily:每天轮转一次。如果消息量大,可以改成size 100M,按文件大小触发更省心。
  • rotate 14:保留14份历史日志,也就是两周的现场数据,足够应对大多数问题回溯需求。
  • compress:轮转后压缩成gzip,省不少磁盘。
  • delaycompress:推迟到第二轮再压缩,给正在写日志的进程一点缓冲,避免压缩工具和写日志进程打架。
  • copytruncate这条是给Mosquitto用的关键。不先复制后清空原文件,而是直接把原文件截断。为什么需要它?因为Mosquitto进程会一直持有日志文件句柄,如果logrotate用rename方式把文件挪走,Mosquitto还会继续往那个已经被改名甚至删除的在inode上写,新的日志文件反而一直是空的,你就看到“日志不增长了”的假象。有了copytruncate,就能确保切完日志后文件句柄继续指向同一个文件,新日志继续写入。
  • create 640 mosquitto mosquitto:创建新日志文件时指定用户和权限,避免Mosquitto以mosquitto用户运行时因为权限不足写不进去。

还有一个容易被忽略的细节:Mosquitto日志文件路径所在目录要确保mosquitto用户有写权限。很多时候你配置了log_dest file,但进程起不来,journalctl里报的是Permission denied,原因就是目录所有者是root。

如果你想做集中式日志管理,也就是把几十台网关、几百个Broker的日志汇到一台服务器上,那我建议在logrotate之前先接日志采集器。具体方案可以是Filebeat扫/var/log/mosquitto/*.log推到Elasticsearch,也可以是Promtail扫文件推到Loki。后者我比较推荐,原因很现实:Loki对资源要求比ELK低一个量级,适合小团队玩。


3.1 原位指标:学会从$SYS主题树拿第一手数据

Mosquitto最让我喜欢的一点是它自带了“可观测性后门”——$SYS主题树。只要在配置里设置了sys_interval,Broker就会周期性往这套以$SYS开头的主题发布自己的运行状态。默认情况下sys_interval是10秒,也就是说每10秒你就能拿到一组新鲜指标,这对监控来说足够灵敏。

我实际使用中经常订阅的$SYS主题,大概有下面这些,建议你在服务器上直接跑一条命令验证一下:

mosquitto_sub -h 127.0.0.1 -t '$SYS/broker/#' -v

拿到的数据会类似下面这样:

$SYS/broker/clients/connected 0 $SYS/broker/clients/connected 3 $SYS/broker/clients/disconnected 0 $SYS/broker/clients/total 3 $SYS/broker/messages/received 12809 $SYS/broker/messages/sent 25973 $SYS/broker/messages/stored 0 $SYS/broker/messages/dropped 0 $SYS/broker/subscriptions/count 2 $SYS/broker/retained messages/count 0 $SYS/broker/load/bytes/received/1min 456732.23 $SYS/broker/load/bytes/sent/1min 892211.11 $SYS/broker/load/messages/received/1min 380.00 $SYS/broker/load/messages/sent/1min 760.00

这些指标每一个都在回答一个具体问题:

  • $SYS/broker/clients/connected:当前在线客户端数,这是最直觉的“活没活着”指标。如果业务高峰期这个数字断崖下跌,说明网络分区或认证抖动;如果持续上涨超出预期,要警惕设备异常重连风暴。
  • $SYS/broker/messages/received$SYS/broker/messages/sent:累计收发消息数,看趋势可以算出每秒吞吐量,用来做容量规划。
  • $SYS/broker/messages/dropped:被丢弃的消息数。这个数字一旦持续增长,十有八九是QoS 1/2消息超过最大队列长度或者保留消息处理出问题。
  • $SYS/broker/load/messages/received/1min:最近一分钟的消息接收速率,比累计值更适合做实时告警。
  • $SYS/broker/subscriptions/count:当前订阅总数,配合客户端数能大致估算每个客户端的平均订阅数量,排查topic设计是否合理。

有一点要重点提示:$SYS主题默认能被订阅,但如果你启用了Mosquitto的动态安全插件(mosquitto-dynamic-security)或者自定义ACL插件,需要在权限配置里显式允许readaccesssubscribe$SYS/#的通路。我见过不止一个团队升级到2.0之后突然发现监控数据全空了,最后排查下来就是ACL把$SYS给挡了。

3.2 接入Prometheus生态:让指标活起来而不是躺在订阅里

mosquitto_sub看一眼指标没问题,但你不能天天拿肉眼看几十台Broker的数据。这时候就需要一个数据采集器把这些$SYS指标转成Prometheus能采集的格式。

目前社区用的比较多的是一个叫mosquitto_exporter的开源组件,它的逻辑很简单:启动后作为一个MQTT客户端订阅$SYS/broker/#主题,把拿到的数值解析出来,以Prometheus的Metrics文本格式暴露在HTTP端口上,Prometheus定时去拉取就行。

部署方式我推荐直接下载二进制放到/usr/local/bin/,用systemd管理。下面是我在Ubuntu 22.04上实际跑通的流程:

# 1. 下载并安装 exporter wget https://github.com/kryptonbutterfly/mosquitto_exporter/releases/download/v1.0/mosquitto_exporter-linux-amd64 install -m 0755 mosquitto_exporter-linux-amd64 /usr/local/bin/mosquitto_exporter # 2. 创建 systemd 服务 cat > /etc/systemd/system/mosquitto-exporter.service <<EOF [Unit] Description=Prometheus Mosquitto Exporter After=network-online.target [Service] ExecStart=/usr/local/bin/mosquitto_exporter \ -mqtt.broker=tcp://127.0.0.1:1883 \ -mqtt.username=monitor \ -mqtt.password=your-password \ -mqtt.topic='$SYS/broker/#' \ -mqtt.qos=0 \ -listen.address=:9234 Restart=always RestartSec=5 [Install] WantedBy=multi-user.target EOF systemctl daemon-reload systemctl enable --now mosquitto-exporter

注意我在参数里特意使用了monitor这个MQTT账号。生产环境千万别直接用匿名订阅。即便是监控订阅,也应该按最小权限原则在Mosquitto里开一个只能订阅$SYS/#的低权限账号,防止监控链路反过来成为安全破口。

每个exporter默认暴露在9234端口。如果是集群部署,你还得在Prometheus的scrape_configs里把每个Broker对应的exporter都加进去。像下面这样:

scrape_configs: - job_name: 'mosquitto' static_configs: - targets: - 'gw-01:9234' - 'gw-02:9234' - 'gw-03:9234'

到这里,你的监控数据就已经进Prometheus了。Grafana里可以导入社区现成的dashboards,也可以自己在Explore里先用rate(mosquitto_messages_received_total[5m])这类PromQL验证数据在更新。我见过不少人卡在这一步——图表空白的,八成是Grafana的数据源和Dashboard里的job名对不上,把job="mosquitto"改成你自己的job_name就行。


4.1 从部署到报警:一次完整的Mosquitto监控落地实战

接下来我会带你把整个链路完整过一遍。这个方案我已经在三个项目里复用过,基本是复制粘贴就能跑的程度。

先假设我们有一台运行Mosquitto的Ubuntu服务器,IP是192.168.10.10,上面已经通过apt装好了最近的Mosquitto 2.x版本。

第一步,开启$SYS发布。编辑/etc/mosquitto/conf.d/monitor.conf

# 发布$SYS指标的间隔,单位是秒 sys_interval 10 # 为了让订阅者能收到,也确认一下允许匿名订阅设置 # 记得按实际安全策略调整 allow_anonymous false password_file /etc/mosquitto/passwd

然后用mosquitto_passwd创建一个只用于监控的低权限账号:

sudo mosquitto_passwd -b /etc/mosquitto/passwd monitor 'Your-Strong-Password'

重启Mosquitto,用订阅命令确认一下指标能收到:

sudo systemctl restart mosquitto mosquitto_sub -h 127.0.0.1 -u monitor -P 'Your-Strong-Password' -t '$SYS/broker/#' -v

这一步如果输出为空,优先检查ACL和用户名密码是否有权限,其次检查sys_interval是否被后面的include目录覆盖为0。

第二步,部署mosquitto_exporter。按上文systemd方式部署完,验证一下HTTP端点:

curl -s http://127.0.0.1:9234/metrics | grep mosquitto

如果看到以mosquitto_开头的指标输出,说明采集链路已经打通。

第三步,在Prometheus里添加抓取任务。假设Prometheus也跑在同一台机器上,编辑prometheus.yml

scrape_configs: - job_name: 'mosquitto-broker' static_configs: - targets: ['127.0.0.1:9234']

重载Prometheus,在Targets页面确认状态是UP。这一步要特别留神,Prometheus默认抓取超时是10秒,如果exporter所在网络质量差,很容易出现context deadline exceeded,这时把scrape_timeout调长一点。

第四步,配置报警规则。下面这份是我总结出来的黄金告警规则,覆盖了Broker最常见的几种故障模式。保存为/etc/prometheus/rules/mosquitto.yml

groups: - name: mosquitto-alerts rules: # 在线客户端数在5分钟内下降超过50%,大概率是网络分区或服务异常断开 - alert: MosquittoClientsDropped expr: | (delta(mosquitto_clients_connected[5m]) < 0) and (clamp_min(delta(mosquitto_clients_connected[5m]), 0) / clamp_min(mosquitto_clients_connected, 1) < -0.5) for: 2m labels: severity: critical annotations: summary: "Mosquitto在线客户端数大幅下降" description: "Broker {{ $labels.instance }} 在线客户端数5分钟内下降超过50%,当前仅剩{{ $value }}个客户端在线。" # 1分钟窗口消息接收速率为0,持续5分钟需要人工确认 - alert: MosquittoNoMessages expr: | sum by (instance) (rate(mosquitto_messages_received_total[5m])) == 0 for: 5m labels: severity: warning annotations: summary: "Mosquitto消息接收中断" description: "Broker {{ $labels.instance }} 最近5分钟没有任何消息接收,请检查发布端和网络链路。" # 消息丢弃数持续增长 - alert: MosquittoMessagesDropping expr: | increase(mosquitto_messages_dropped_total[15m]) > 0 for: 5m labels: severity: warning annotations: summary: "Mosquitto开始丢弃消息" description: "Broker {{ $labels.instance }} 在15分钟内出现消息丢弃,请检查QoS配置、队列长度和客户端消费能力。"

这几条规则我都加了for子句,用来防止瞬时抖动误报。实际运营中我吃过不少“监控半夜狂报警,起来一看啥事没有”的苦头,有了for可以过滤掉大部分毛刺。

第五步,在Grafana里搭看板。这个就比较个人审美了,我至少会放三块核心面板:在线客户端数趋势、消息收发速率、每Broker的字节吞吐量。PromQL分别是:

# 在线客户端数 mosquitto_clients_connected{job="mosquitto-broker"} # 消息接收/发送速率 rate(mosquitto_messages_received_total{job="mosquitto-broker"}[5m]) rate(mosquitto_messages_sent_total{job="mosquitto-broker"}[5m]) # 字节吞吐 rate(mosquitto_bytes_received_total{job="mosquitto-broker"}[5m]) rate(mosquitto_bytes_sent_total{job="mosquitto-broker"}[5m])

到这一步,你的页面监测体系就已经从“Broker自己不知道在干嘛”变成了“任何异常都有数有据可查”。

4.2 日志驱动的异常定位:从堆数据到破案

监控指标告诉你“出了问题”,但“为什么出问题”还得靠日志。这里我整理了三个我实际用过的日志驱动排查手段,希望能给你参考。

手段一:订阅log_dest topic实现实时日志流。Mosquitto支持把日志发布到指定的MQTT主题上,这意味着你可以远程实时订阅某个Broker的日志,不用每次SSH上去看。在Mosquitto 2.x里,这个功能的配置是:

# 在 mosquitto.conf 里加一行 log_dest topic mosquitto/logs

然后在任何一台远程机器上:

mosquitto_sub -h 192.168.10.10 -u monitor -P password -t 'mosquitto/logs'

这样远程也能看到实时日志。但要注意,这会把日志内容暴露在MQTT消息总线上,生产环境必须用TLS加密和ACL严格限制订阅权限,否则等于把敏感信息直播出去。

手段二:在网关设备上保留一份“最近N条日志”的环形缓冲。嵌入式设备资源有限,不可能存很多天的日志。我的做法是用一个轻量脚本后台订阅mosquitto/logs,把日志写到内存盘(tmpfs)里的环形队列,重启自动清空,但如果宕机前被监控系统抓到了现场,通常就够分析原因了。当然,更稳妥的做法是让日志通过MQTT消息主动推到集中日志服务器,用Loki或Elasticsearch统一存。这个方案在设备量少的时候很灵活,设备多了就还是得用Filebeat/Promtail。

手段三:用日志关键字做告警补充。Prometheus只能监控数值指标,但日志里藏着大量数值指标不包含的信息。比如Client X closed its connection反复出现,说明某个设备在频繁重连;Sending CONNACK后面的错误码可以区分是认证失败还是协议版本不支持;Socket error on client则可能泄露网线被拔了这类物理问题。

我习惯的做法是在Loki里给Promtail配置一条流水线,把日志里的关键token提取出来,再用LogQL计算错误频率。比如统计“认证失败”日志在5分钟内出现次数超过阈值就报警:

sum by (instance) (count_over_time({job="mosquitto"} |~ "Permission denied|not authorised"[5m])) > 20

有了这条规则,恶意扫描、密码错误风暴、甚至员工配错账号密码导致的连锁失败都能及时暴露。


5.1 典型问题速查表

把这些年运维Mosquitto踩过和见人踩过的坑列成一张表,方便你遇到问题时快速对照。

现象可能原因排查与解决
$SYS主题一直订阅不到sys_interval为0或被ACL拦截;插件过滤了$SYS确认sys_interval非0;检查动态安全插件是否允许订阅$SYS/#;用mosquitto_sub -t '$SYS/broker/#'验证
log_dest file配置后日志文件不生成目录不存在或目录权限不足手动创建目录并chown mosquitto:mosquitto;确认log_dest路径与目录一致
日志轮转后新文件不产生内容配置了rename方式且未用copytruncate修改logrotate配置为copytruncate;观察一周确认文件在持续增长
客户端频繁重连,日志大量出现Socket error网络不稳、心跳周期短、代理/NAT超时;或Broker线程阻塞用tcpdump抓包确认是客户端发RST还是Broker关闭;调整keepalive与max_inflight_messages;检查CPU和内存是否瓶颈
MQTT消息延迟明显网络带宽瓶颈、消息QoS等级过高、Broker持久化策略用上、swap严重$SYS/broker/load/bytes/received/1min趋势;按预期峰值扩容;把不需要持久化的topic用QoS 0发
Prometheus抓取exporter超时exporter所在网段带宽低,或scrape_timeout短调大scrape_timeout到30s;把exporter放到和Prometheus同网段;用blackbox探针先测网络连通性
日志时间与本地时间差8小时容器时区未设置,或系统时区为UTC容器添加TZ=Asia/Shanghai环境变量;宿主机timedatectl确认时区;落库时统一用UTC+时区标记
内存缓慢增长,几天后OOM订阅树膨胀;客户端不按规范退订导致占用堆积;retain消息过多分析$SYS/broker/subscriptions/count和retained messages count;限制单个client最大订阅数;清理无用retain消息
Client连接后立即CONNACK返回但随即断开认证插件配置冲突对照log_type error输出;检查password_file和ACL文件是否同时配置了冲突规则;用mosquitto_pubmosquitto_sub手工测试

5.2 我的排查经验与避坑指南

最后聊几个偏“个人向”的经验,不一定写在官方文档里,但关键时刻真能救命。

第一,永远别在生产环境开debug日志。有一次我帮朋友排查一个奇怪的客户端断连问题,他为了捕获现场直接在配了上千台设备的Broker上开启了log_type debug,结果两小时不到磁盘就被刷满,Broker自己都写不进日志了。后来我告诉他,遇到这种问题正确姿势是:先保留error/warning/notice级别的日志,然后用tcpdump在Broker网卡上抓包分析具体协议行为,这样既不影响业务,也能看到像CONNECT报文里的keepalive值这些细节。做运维,第一原则永远是“不要为了看清一个问题而制造一个更大的问题”。

第二,监控数据的采样间隔要和你业务的容忍度匹配。sys_interval默认10秒已经很快了,但如果你有那种零点几秒就要感知故障的场景,单纯靠Mosquitto的$SYS对不齐的。这种场景应该把健康探测和业务探测分开:用一个独立的MQTT客户端周期性发心跳消息并确认收到回执,比看任何指标都直接。我做嵌入式网关运维的时候,每个网关上的采集程序都会每30秒发一条/healthcheck/gateway01消息并在本地标记发送时间,监控端订阅同一个topic,一旦超过60秒没收到就说网关挂了。这个方案比单纯看指标响应快得多,也更贴近业务真实状态。

第三,别忘记监控你自己监控系统。听起来像个段子,但我确实遇到过Grafana数据源的Prometheus挂了一整天,直到用户投诉才知道。所以我现在会在每台Broker上开一条crontab,每5分钟检查一下exporter的HTTP端口能否通,不行就直接往企业微信/钉钉机器人发告警。监控账套虽然简单,但它是所有监控系统的“最后一道防线”。

第四,日志格式最好提前埋好结构化字段。Mosquitto默认日志是人读的,但机器不好读。我的习惯是在logrotate之前加一层Promtail的pipeline,把日志里的IP、client id、topic、错误码拆成结构化字段存进Loki。这样你才能在事后用一个query查“某台设备最近一小时的全部行为”,而不是靠grep慢慢捞。


说实话,Mosquitto本身的监控和日志管理在开源Broker里已经算是做得比较友好的了,$SYS主题设计得直白,日志通道灵活,社区工具也不少。但友好的工具也架不住疏忽,很多问题其实不是Broker的问题,而是我们没在早期把观测体系搭好。我个人这几年最大的体感是:监控和日志不是“等出事后才去搭”的事后补救,而是任何消息中间件上线第一天就该补好的基础设施。等你经历过一次凌晨三点因为消息堆积找不出原因被叫醒的体验,就会明白这句话的含金量。希望这篇文章能帮你把Mosquitto这层“眼睛和记忆”一次性配齐,后面少熬夜,多省心。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/12 2:47:33

ESP32蓝牙Beacon测距实战:RSSI校准与滤波工程化实现

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/12 2:47:18

MQL5直连CTP柜台:桥接DLL设计、行情订阅与下单实战

简介&#xff1a;基于MQL5语言的MT5客户端直连期货公司CTP柜台程序化交易源码&#xff0c;覆盖行情接入、交易下单、持仓查询、风险控制与数据中心等模块&#xff0c;适合有一定编程基础的期货量化交易者用于搭建或改造自动化交易客户端。压缩包共60个文件&#xff0c;约29.1MB…

作者头像 李华
网站建设 2026/9/12 2:47:15

Apple Silicon Mac 安装 MySQL 完全指南(dmg 与 Homebrew 双教程)

先把话说明白&#xff1a;这是 M 芯片系列教程的第四篇。前面几篇我陆续写了 M1/M2/M3 环境下 Homebrew、Python、Git 这些基础开发的安装折腾过程&#xff0c;这一篇终于轮到数据库了。这个系列默认你手上是一台 Apple Silicon 的 MacBook&#xff0c;也就是 M1、M2、M3 或者 …

作者头像 李华
网站建设 2026/9/12 2:46:08

IntelliJ IDEA社区版:免费轻量Java开发IDE完整指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/12 2:46:07

Java并发队列全解析:从BlockingQueue到线程池选型实战

聊到Java里的Queue&#xff0c;很多人第一反应是“这不就是个队列嘛&#xff0c;LinkedList也能用”。但真正到了并发场景&#xff0c;或者面试被问到“线程池的阻塞队列怎么选”时&#xff0c;才发现这里面水很深。我见过不少生产事故&#xff0c;明明线程池参数看着没问题&am…

作者头像 李华
网站建设 2026/9/12 2:45:46

从VSCode插件到Electron独立应用:打字游戏架构改造实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华