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

systemd启动OpenSplice发布端无法发布数据问题排查

systemd托管OpenSplice发布端开机自启通信异常修复方案

问题概述

部署在Ubuntu 20.04上的systemd托管OpenSplice发布端存在以下固定异常:

  • 开机由systemd自动拉起时,无法正常发布数据,OpenSplice日志无任何报错
  • 命令行手动启动,或开机后手动重启systemd服务,发布端功能完全正常
    已完成的排查项:
  • 跨机器部署的发布、订阅端QoS配置完全匹配
  • 网络内无其他DDS参与者冲突,所有机器重启验证、调整重启顺序均无法解决问题
  • 2022年9月16日补充验证:普通UDP协议编写的发布程序存在完全相同的异常,确认问题与systemd启动顺序、依赖配置相关;将服务启动时机调整到用户登录前,异常仍未解决

现有配置

systemd服务单元文件

[Unit]
Description=Publisher Process
Documentation=
After=network.target
StartLimitIntervalSec=0

[Service]
Type=simple
WorkingDirectory=/opt/publisher/bin
ExecStart=/opt/publisher/bin/publisher.sh
Restart=always
RestartSec=2

[Install]
WantedBy=multi-user.target

原始启动脚本publisher.sh

#!/bin/bash
cd /opt/publisher/bin
source bashrc_local
# 程序崩溃后自动拉起保活
while true; do
  ./publisher
  sleep 15
done

当前临时规避方案

通过先启动无关进程等待30秒再拉起正式服务绕过问题:

#!/bin/bash
cd /opt/publisher/bin
source bashrc_local
timeout 30 ./remote_processor
killall remote_processor
# 程序崩溃后自动拉起保活
while true; do
  ./publisher
  sleep 15
done

根因说明

问题核心是network.target的语义不符合常规预期:Ubuntu 20.04的systemd中,network.target仅代表网络管理服务的启动流程已触发,完全不代表物理网卡链路up、IP地址分配完成、路由表生效、网络接口初始化完成。
开机阶段systemd并行启动服务的速度远快于网络栈就绪速度,此时启动的DDS/普通UDP程序会绑定到未就绪的网络接口,后续网络栈就绪后,程序默认不会重新探测网络接口状态,直接导致数据发送失败,且这类底层套接字绑定异常通常不会输出到应用层日志。手动重启服务时网络早已完全就绪,因此功能正常。
调整服务到用户登录前启动不生效的原因是,多数场景下(尤其是DHCP动态分配IP的环境)用户登录触发时机早于网络完全就绪的时间点,单纯切换启动target无法精准匹配网络可用的时机。

根本解决方法

方案1:修正systemd服务依赖,对齐网络就绪判定标准

替换原有服务单元中错误的network.target依赖,改为等待网络完全就绪的target,修改后的服务文件如下:

[Unit]
Description=Publisher Process
Documentation=
After=network-online.target
Wants=network-online.target
StartLimitIntervalSec=0

[Service]
Type=simple
WorkingDirectory=/opt/publisher/bin
ExecStart=/opt/publisher/bin/publisher.sh
Restart=always
RestartSec=2

[Install]
WantedBy=multi-user.target

执行对应命令启用网络等待服务,否则network-online.target不会主动阻塞等待网络就绪:

# 若使用NetworkManager管理网络(Ubuntu桌面版默认)
systemctl enable --now NetworkManager-wait-online.service

# 若使用systemd-networkd管理网络(Ubuntu Server精简配置默认)
# systemctl enable --now systemd-networkd-wait-online.service

提示:静态IP场景下可修改对应wait-online服务的超时参数,将默认2分钟超时调整为30秒,避免不必要的开机等待。

方案2:启动脚本内置网络探测逻辑(推荐,无全局副作用)

如果不想修改全局网络等待配置、延长整体开机时间,可以直接在启动脚本中增加业务侧的网络就绪判定,确认满足业务通信条件后再启动发布程序,替换原有publisher.sh内容如下:

#!/bin/bash
cd /opt/publisher/bin
source bashrc_local

# 网络就绪探测,将eth0替换为实际承载业务流量的网卡名
while true; do
  # 检查网卡已分配非回环IP
  ip addr show eth0 | grep -w 'inet' | grep -v '127.0.0.1' >/dev/null 2>&1
  IP_OK=$?
  # 检查对应网卡已配置默认路由
  ip route show default | grep -w 'eth0' >/dev/null 2>&1
  ROUTE_OK=$?
  if [ $IP_OK -eq 0 ] && [ $ROUTE_OK -eq 0 ]; then
    break
  fi
  sleep 2
done

# 原有保活逻辑
while true; do
  ./publisher
  sleep 15
done

该方案完全匹配业务实际需要的网络条件,不依赖systemd的target判定逻辑,也不会影响其他开机服务的启动速度。

方案3:OpenSplice侧配置接口自动重探测(DDS场景加固)

针对OpenSplice场景可额外增加配置,让服务运行过程中自动感知网络接口变化,彻底规避启动时网络未就绪的影响。在OpenSplice配置文件的NetworkService段增加如下配置:

<NetworkService>
  <!-- 保留原有其他配置 -->
  <Interface>
    <AutoDetectInterface>true</AutoDetectInterface>
    <InterfaceRefreshInterval>10</InterfaceRefreshInterval>
  </Interface>
</NetworkService>

配置后OpenSplice每10秒检查一次网络接口状态,链路恢复、IP变化后会自动重新绑定网卡,不需要重启服务。

内容的提问来源于stack exchange,提问作者Damian Dixon

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 12:21:29