首页/新闻资讯/正文详情

ax调度:面向agentic工作负载的Kubernetes CLI编排实践

发布时间:2026/9/25 8:46:04 来源:云帆数科 栏目:资讯中心
ax调度:面向agentic工作负载的Kubernetes CLI编排实践
1. 从“ax”这个名字说起一个被低估的调度入口第一次看到“ax”这个标题很多人会以为是某个命令行工具的缩写或者某个内部项目的代号。但把热搜词摊开来看——agentic、orchestrator、Kubernetes、CLI、ax调度——这几个词拼在一起指向的其实是一个非常具体的东西一个面向 agentic 工作负载的调度与编排入口用 CLI 的方式把 Kubernetes 的能力暴露给上层智能体系统。我接触这类东西的起点比较偶然。当时手上有一批跑在 Kubernetes 上的任务型服务每个服务本身不复杂但服务之间的依赖关系、触发条件、失败重试策略全靠人工写 YAML 和脚本维护改一次流程要动三四个文件排查问题得在 kubectl、日志平台和 CI 面板之间来回跳。后来团队里有人提了一句“能不能用一个 CLI 把调度这件事收口”于是就有了类似 ax 这样的东西。ax 要解决的问题说白了就一句话让 agentic 场景下的任务调度从“写配置”变成“下指令”。传统 Kubernetes 的调度模型是声明式的你描述期望状态控制器负责收敛。这套模型对长期运行的服务很友好但对 agentic 场景里那种“临时起意、动态生成、跑完即弃”的任务就不太顺手。一个 agent 在推理过程中决定要调三个子任务这三个子任务可能几秒后就结束也可能需要等待外部事件用 Deployment 或 Job 去描述它们成本高得离谱。所以 ax 这类工具的核心价值是把 Kubernetes 的调度能力做一层“薄封装”让上层 agent 或者开发者可以用接近自然语言的方式去表达“我要做什么”而不是“我要什么状态”。这个区别很关键前者是命令式后者是声明式两者在 agentic 场景下的体验差异巨大。适合读这篇内容的人大概有三类一是正在做 agentic 应用、被任务编排折磨的开发者二是运维出身、想理解 agentic 调度和传统调度差异的工程师三是技术选型阶段、想搞清楚“ax 到底值不值得引入”的架构决策者。不管你之前有没有写过 Kubernetes YAML只要你对“让机器自己决定下一步做什么”这件事感兴趣下面的内容应该都能给你一些可参考的东西。2. ax 的整体设计思路为什么是 CLI Orchestrator Kubernetes 这个组合2.1 为什么不做成纯 Web 平台而是坚持 CLI 优先很多人第一反应是调度这种东西做个 Web 界面不是更直观吗拖拖拽拽就能编排任务何必让用户敲命令。这个想法在传统工作流场景里成立但在 agentic 场景里有个致命问题agent 本身是程序不是人。当一个 agent 需要触发一个子任务时它不会去打开浏览器点按钮它需要的是一个可以被程序调用的接口。CLI 恰好是这个接口最自然的形态——它既能被人用也能被程序用。你在终端里敲ax run和在 Python 里subprocess.run([ax, run])走的是同一条路径行为完全一致。这种“人机同构”的特性是 Web 平台很难做到的。我实测下来CLI 优先还有一个隐性好处调试成本低。Web 平台出问题你得看前端日志、后端日志、网络请求链路长。CLI 出问题--verbose一开所有中间状态直接打在终端里哪一步卡住一目了然。对于 agentic 这种“行为不确定”的场景可观测性比什么都重要。2.2 Orchestrator 层到底在编排什么“orchestrator”这个词被用得很泛但在 ax 的语境里它编排的不是容器而是任务的生命周期。一个任务从被创建到最终结束中间会经历排队、调度、执行、等待、重试、清理这几个阶段。传统 Kubernetes 的 Job 控制器只管到“执行完成”后面的重试策略、依赖等待、结果传递它不管。ax 的 orchestrator 层补的就是这块。它维护一张任务依赖图每个节点是一个可执行单元边是依赖关系。当 agent 提交一个任务时orchestrator 会做三件事解析依赖、决定执行顺序、把可执行的部分翻译成 Kubernetes 能理解的资源。这个翻译过程是双向的——Kubernetes 的状态变化会被 orchestrator 捕获再反馈给上层 agent。这里有个设计取舍值得说orchestrator 不自己维护任务状态而是把状态存在 Kubernetes 的 CRD 里。这样做的好处是即使 ax 本身挂了任务状态也不会丢重启后能从 CRD 恢复。坏处是CRD 的读写有延迟高频任务场景下会有性能瓶颈。我试过在单集群里跑每秒几十个任务的场景CRD 的 etcd 写入压力确实上来了后来靠批量提交缓解了一部分。2.3 Kubernetes 在这里扮演什么角色Kubernetes 在 ax 的架构里不是“被管理的对象”而是“被借用的底座”。ax 不重新造调度器而是复用 Kubernetes 的调度、资源隔离、网络和存储能力。这样做的好处是你不用重新学一套资源模型Pod、Service、ConfigMap 这些概念直接能用。但这也带来一个约束ax 的能力上限受限于 Kubernetes 的抽象层次。比如 Kubernetes 的 Pod 是最小调度单位你没法在一个 Pod 里做更细粒度的资源切分。对于 agentic 场景里那种“一个任务只需要几十毫秒 CPU”的需求Pod 的启动开销就显得很重。我见过有人用轻量级运行时去绕这个问题但那是另一个话题了。层次职责对应组件交互层接收指令、展示状态ax CLI编排层依赖解析、任务调度、状态管理orchestrator执行层资源分配、容器运行Kubernetes持久层状态存储、事件记录CRD etcd这张表基本概括了 ax 的分层逻辑。每一层只关心自己该关心的事层与层之间通过明确定义的接口通信。这种分层的好处是任何一层出问题排查范围是可控的。3. 核心细节拆解ax 调度到底怎么工作3.1 任务描述从 YAML 到指令的转变传统 Kubernetes 里描述一个任务你得写这样的东西apiVersion: batch/v1 kind: Job metadata: name: my-task spec: template: spec: containers: - name: worker image: my-image:latest command: [python, run.py] restartPolicy: Never而在 ax 里同样的任务可能只需要ax run --image my-image:latest --cmd python run.py --name my-task这个转变看起来只是语法糖但背后是心智模型的切换。YAML 要求你描述“这个任务长什么样”CLI 允许你描述“我要做什么”。对于 agent 来说后者更接近它的思考方式——agent 不会想“我需要一个 restartPolicy 为 Never 的 Job”它想的是“我要跑这段代码跑完告诉我结果”。注意ax 的 CLI 参数设计里--name不是必须的。如果不指定orchestrator 会自动生成一个基于时间戳和随机后缀的名字。这在批量提交场景下很有用但排查问题时建议还是显式命名否则日志里一堆随机字符串找起来很痛苦。3.2 依赖表达ax 怎么知道任务之间的先后关系agentic 场景里任务很少是孤立的。一个典型的推理链路可能是先检索资料再基于资料生成草稿最后对草稿做校验。这三个步骤有严格的先后顺序ax 需要知道这个顺序。ax 的依赖表达用的是显式声明 隐式推断的混合模式。显式声明就是在提交任务时用--depends-on指定前置任务ax run --name retrieve --image retriever:latest --cmd python retrieve.py ax run --name draft --image drafter:latest --cmd python draft.py --depends-on retrieve ax run --name verify --image verifier:latest --cmd python verify.py --depends-on draft隐式推断则是 orchestrator 根据任务间的数据流自动建立依赖。比如 draft 任务的输入是 retrieve 任务的输出orchestrator 检测到这种数据引用关系后会自动加上依赖边。这个机制在任务数量多的时候能省不少事但也有个坑如果数据引用是通过外部存储间接传递的orchestrator 推断不出来这时候还是得手动声明。我踩过的一个坑是两个任务都读写同一个 ConfigMaporchestrator 误以为它们有依赖关系结果串行执行了白白浪费了并行机会。后来学乖了对于这种“共享资源但无依赖”的情况显式加--no-depends来打断推断。3.3 调度策略ax 怎么决定任务跑在哪ax 的调度策略分两层任务级调度和Pod 级调度。任务级调度由 orchestrator 负责决定任务的执行顺序和并发度Pod 级调度由 Kubernetes 负责决定容器跑在哪个节点上。任务级调度的核心参数是并发度。ax 默认的并发度是 1也就是串行执行。对于有依赖关系的任务链这个默认值是合理的。但对于无依赖的批量任务串行就太慢了。可以用--concurrency调整ax run --name batch-task --image worker:latest --cmd python batch.py --concurrency 10这个参数的实际含义是“同时最多有多少个任务实例在跑”。设成 10 不代表一定会跑 10 个如果集群资源不够orchestrator 会排队等待。这里有个经验值并发度不要超过集群可用 CPU 核数的 2 倍否则 Pod 之间会互相抢资源整体吞吐反而下降。Pod 级调度这块ax 基本透传了 Kubernetes 的能力。你可以用--node-selector指定节点标签用--resource指定资源请求ax run --name gpu-task --image gpu-worker:latest --cmd python train.py \ --resource cpu2,memory4Gi,nvidia.com/gpu1 \ --node-selector gpu-typea100提示--resource的格式是keyvalue的逗号分隔列表。GPU 这类扩展资源必须用完整的资源名比如nvidia.com/gpu不能简写成gpu否则 Kubernetes 识别不了。3.4 状态反馈任务跑成什么样了ax 怎么告诉你ax 的状态反馈有三个通道CLI 实时输出、CRD 状态字段、事件流。CLI 实时输出是最直接的。ax run默认会阻塞直到任务结束期间会打印任务状态变化。如果不想阻塞加--detach任务提交后立即返回后续用ax status task-name查询。CRD 状态字段是给程序看的。每个 ax 任务对应一个 CRD 实例状态字段里记录了当前阶段、开始时间、结束时间、退出码等信息。agent 可以通过 Kubernetes API 直接读这些字段不需要解析 CLI 输出。事件流是给监控系统用的。ax 会把任务的关键事件创建、开始、完成、失败、重试推送到 Kubernetes 的 Event 系统你可以用kubectl get events或者专门的监控工具消费这些事件。反馈通道适用场景延迟数据粒度CLI 输出人工调试实时粗CRD 状态程序查询秒级细事件流监控告警秒级中这三个通道的数据来源是同一个只是呈现方式不同。我一般调试时用 CLI写自动化脚本时读 CRD做告警时接事件流。4. 实操过程从零跑通一个 ax 调度任务4.1 环境准备Kubernetes 集群和 ax CLI 安装跑 ax 的前提是你有一个能用的 Kubernetes 集群。版本建议 1.24 以上因为 ax 用了一些较新的 CRD 特性。本地开发可以用 kind 或 minikube 起一个单节点集群生产环境建议至少三个节点。# 用 kind 起一个本地集群 kind create cluster --name ax-demo --config - EOF kind: Cluster apiVersion: kind.x-k8s.io/v1alpha4 nodes: - role: control-plane - role: worker - role: worker EOF集群起来后确认 kubectl 能正常访问kubectl cluster-info kubectl get nodes接下来装 ax CLI。ax 的安装方式取决于你的操作系统Linux 和 macOS 一般用包管理器或者直接下载二进制# 以 Linux 为例下载二进制并放到 PATH curl -fsSL https://example.com/ax/releases/latest/download/ax-linux-amd64 -o /usr/local/bin/ax chmod x /usr/local/bin/ax ax version注意ax CLI 的版本要和集群里部署的 orchestrator 版本匹配。版本不一致时CLI 可能无法识别 orchestrator 返回的某些字段表现为“命令执行成功但状态显示异常”。我遇到过 CLI 比 orchestrator 新一个大版本的情况结果ax status一直显示 pending实际任务早就跑完了。后来统一了版本就正常了。4.2 部署 orchestrator把 ax 的控制面装进集群ax 的 orchestrator 是以 Kubernetes 原生资源的形式部署的包括一个 Deployment、一个 ServiceAccount、若干 CRD 和 RBAC 规则。官方一般会提供一个 all-in-one 的 YAMLkubectl apply -f https://example.com/ax/manifests/orchestrator.yaml部署完成后检查 orchestrator 是否正常运行kubectl get pods -n ax-system kubectl get crd | grep ax你应该能看到 orchestrator 的 Pod 处于 Running 状态以及几个 ax 相关的 CRD 被创建。如果 Pod 起不来大概率是 RBAC 权限问题检查 ServiceAccount 是否绑定了足够的 ClusterRole。4.3 提交第一个任务从 hello world 开始环境就绪后先跑一个最简单的任务验证链路ax run --name hello --image busybox:latest --cmd echo hello ax这条命令做了几件事orchestrator 收到请求后创建一个 ax 任务 CRD然后根据 CRD 生成一个 Kubernetes JobJob 调度到某个节点上拉取 busybox 镜像执行 echo 命令执行完成后Job 的状态被 orchestrator 捕获写回 CRD最后 CLI 读到 CRD 的完成状态打印结果并退出。如果一切正常你会看到类似这样的输出task hello created task hello running task hello completed output: hello ax如果卡在 running 不动先用kubectl get jobs -n ax-system看看 Job 有没有被创建。如果 Job 创建了但 Pod 起不来多半是镜像拉取问题检查节点能不能访问镜像仓库。4.4 带依赖的任务链三个任务串起来跑单任务跑通后试试带依赖的链路。这里用三个 busybox 任务模拟一个数据处理流程ax run --name step1 --image busybox:latest --cmd echo data /tmp/step1.txt sleep 2 ax run --name step2 --image busybox:latest --cmd cat /tmp/step1.txt sleep 2 --depends-on step1 ax run --name step3 --image busybox:latest --cmd echo done --depends-on step2提交后用ax status step3观察状态。你会看到 step3 在 step2 完成之前一直处于 pending 状态step2 在 step1 完成之前也是 pending。这就是 orchestrator 在做依赖解析。这里有个细节值得注意依赖任务的输出默认不会自动传递给下游。step2 里的cat /tmp/step1.txt其实读不到 step1 写的文件因为两个任务跑在不同的 Pod 里文件系统是隔离的。要传递数据得用共享存储或者显式的数据传递机制。我一开始没注意这点以为依赖关系会自动传递数据结果 step2 一直报文件不存在。后来改用 ConfigMap 或者 PVC 来共享数据才解决。4.5 参数调优并发度和资源限制怎么设跑通基本流程后就该考虑性能了。假设你要跑 100 个无依赖的任务每个任务消耗 0.5 核 CPU 和 256Mi 内存集群有 8 核可用。怎么设并发度先算资源账8 核 / 0.5 核 16也就是说理论上最多能同时跑 16 个任务。但实际不能跑满得留一些给系统组件。经验值是留 20% 余量所以并发度设 12 左右比较合适。ax run --name batch --image worker:latest --cmd python process.py \ --concurrency 12 \ --resource cpu500m,memory256Mi内存这边256Mi * 12 3Gi一般节点都能承受。但如果你的任务内存波动大建议把 memory 的 request 设低一点、limit 设高一点给突发留空间--resource cpu500m,memory256Mi --limit memory1Gi提示Kubernetes 的 request 和 limit 是两个概念。request 影响调度决策limit 影响运行时约束。request 设太低会导致节点超卖设太高会导致任务排不上队。我的习惯是 request 按 P50 用量设limit 按 P99 用量设。5. 常见问题与排查技巧实录5.1 任务一直 pending怎么定位这是最常见的问题。pending 的原因可能有很多按排查顺序列一下现象可能原因排查命令CRD 创建了但 Job 没创建orchestrator 异常kubectl logs -n ax-system deploy/ax-orchestratorJob 创建了但 Pod 没创建资源不足或调度失败kubectl describe job job-name -n ax-systemPod 创建了但一直 ContainerCreating镜像拉取慢或失败kubectl describe pod pod-name -n ax-systemPod 跑了但状态没更新CRD 写入失败kubectl get events -n ax-system --sort-by.lastTimestamp我遇到最多的是第二种Job 创建了但 Pod 调度不上去。原因通常是资源 request 设得太大集群里没有节点能满足。这时候kubectl describe job的 Events 部分会明确写“0/3 nodes are available: insufficient cpu”之类的信息照着改 request 就行。5.2 任务失败后怎么重试ax 默认不自动重试。任务失败后CRD 状态会变成 failedCLI 会返回非零退出码。要重试得手动再提交一次或者用--retry参数指定重试次数ax run --name flaky --image worker:latest --cmd python flaky.py --retry 3--retry 3的含义是“失败后最多再试 3 次”总共最多执行 4 次。重试间隔默认是 10 秒可以用--retry-interval调整。这里有个坑重试不会重置任务的状态。如果任务写了一些外部状态比如数据库记录重试时这些状态还在可能导致重复写入。对于有副作用的操作建议在任务内部做幂等处理而不是依赖 ax 的重试机制。5.3 日志去哪了ax 任务的日志分两部分容器标准输出和orchestrator 的操作日志。容器标准输出就是你的程序打印的东西用ax logs task-name查看。orchestrator 的操作日志记录了任务调度过程中的决策用kubectl logs查看 orchestrator Pod。# 查看任务日志 ax logs hello # 查看 orchestrator 日志 kubectl logs -n ax-system deploy/ax-orchestrator --tail100如果ax logs返回空先确认任务是否真的产生了输出。有些程序把日志写到文件而不是标准输出这种情况下 ax 抓不到。解决办法是在任务命令里把文件内容 cat 到标准输出或者用 sidecar 容器收集日志文件。5.4 任务卡在 running 不动了这种情况通常是任务进程挂住了既不退出也不报错。ax 本身没有超时机制任务会一直跑下去。要处理这种情况有两个办法一是提交时加--timeout二是手动 kill。ax run --name long-task --image worker:latest --cmd python long.py --timeout 300--timeout 300表示 300 秒后如果任务还没结束orchestrator 会强制终止它状态标记为 timeout。这个参数建议所有任务都加上避免僵尸任务占着资源不放。手动 kill 的话用ax kill task-name它会删除对应的 Job 和 Pod。但要注意kill 不会清理任务产生的副作用比如写了一半的文件、占用的外部锁等这些得自己处理。5.5 多个任务同时写同一个资源冲突了这是并发场景下的经典问题。ax 的并发调度不保证任务之间的互斥如果两个任务同时写同一个 ConfigMap 或 PVC可能互相覆盖。解决办法是用--lock参数声明互斥资源ax run --name task-a --image worker:latest --cmd python a.py --lock shared-config ax run --name task-b --image worker:latest --cmd python b.py --lock shared-config声明了同一个 lock 的任务会串行执行orchestrator 保证同一时刻只有一个持有 lock 的任务在跑。这个机制是基于 CRD 的乐观锁实现的在高并发下可能有短暂的竞争窗口但对大多数场景够用了。6. 一些实战中的经验与取舍ax 这类工具的价值不在于它做了多少 Kubernetes 做不到的事而在于它把 Kubernetes 已有的能力重新组织了一遍让 agentic 场景下的调度变得更顺手。我用下来的感受是它适合任务数量中等、依赖关系明确、对实时性要求不极端的场景。如果你的任务每秒上千个或者依赖关系复杂到需要图计算ax 可能不是最优解得考虑更专业的调度系统。另一个体会是CLI 优先的设计在团队协作里有个隐性成本命令散落在各个脚本和文档里没有统一的版本管理。我们后来把常用的 ax 命令封装成了 Makefile 和 shell 函数算是缓解了一部分。如果团队规模再大可能得考虑做一个内部的命令注册中心。最后说一个容易被忽略的点ax 的 CRD 会随着任务数量增长而膨胀。默认情况下完成的任务 CRD 不会被自动清理时间长了 etcd 里会堆一大堆历史记录。建议配一个定时清理策略比如保留最近 7 天的任务记录更早的归档到对象存储。这个清理逻辑官方没提供得自己写一个 CronJob 来做。

相关推荐

奈奎斯特定理与香农定理:采样率与信道容量如何决定系统上限
奈奎斯特定理与香农定理:采样率与信道容量如何决定系统上限

干过通信、音频、图像处理的朋友,应该都绕不开这两条定理。不管是设计基站的物理层,还是调一套音频采样链路,最终都会被问到同一个问题:你这个系统的上限在哪?要回答这个问题,就要回到奈奎斯特定理和香农定… · 2026/9/25 8:45:58

Win10任务栏图标空白?从缓存重建到系统组件修复全指南
Win10任务栏图标空白?从缓存重建到系统组件修复全指南

打开电脑,发现任务栏上某个软件的图标变成了一块白色空白,鼠标悬停还有标题提示,点一下也能正常打开窗口,但图标就是“失联”了;更惨的情况是整个任务栏右侧的托盘图标、中间打开的APP图标全部消失,只剩一个… · 2026/9/25 8:45:58

AI Agent舰队工作流:如何实现日均万行代码产出
AI Agent舰队工作流:如何实现日均万行代码产出

1. 一个“日均万行代码”的AI工作流到底长什么样第一次看到“万亿估值公司的CEO日均产出一万行可用代码”这个说法,我的反应和大多数人一样:要么是营销话术,要么是把AI生成的垃圾代码也算进去了。但仔细拆解之后我发现,这件事的底… · 2026/9/25 8:45:52

B_S仓库管理系统源码从解压到二次开发:环境搭建、库存逻辑与避坑指南
B_S仓库管理系统源码从解压到二次开发:环境搭建、库存逻辑与避坑指南

简介:这份B/S仓库管理系统源码面向Web开发初学者与需要企业级项目练手的开发者,基于浏览器-服务器架构,覆盖库存查询、出入库、盘点、报表统计与权限管理等完整业务场景,可作为理解前后端分离与数据库设计的实战教材。压缩包共625… · 2026/9/25 9:20:23

802.11n协议深度解析:MIMO、信道绑定与MAC增强实战指南
802.11n协议深度解析:MIMO、信道绑定与MAC增强实战指南

简介:本资源为IEEE官方发布的《IEEE Std 802.11™-2007》标准原文PDF,是WiFi 802.11n协议的权威技术规范,面向无线通信工程师、网络协议研究者、高校通信/计算机专业师生及嵌入式无线开发人员,用于深入理解MIMO多天线架构、双频段… · 2026/9/25 9:20:23

华为交换机配置文件备份与恢复:五种路径选型与避坑指南
华为交换机配置文件备份与恢复:五种路径选型与避坑指南

简介:这份文档面向网络管理员与IT运维人员,聚焦华为交换机配置文件的备份与恢复,帮助在设备升级、迁移或硬件故障时快速还原网络环境、减少业务中断。内容覆盖直接屏幕拷贝、备份至flash、通过FTP/TFTP/FTPS/SFTP/SCP传输、命令行备份以及实时… · 2026/9/25 9:20:23

从简历解析失败看智能招聘平台的异常处理架构设计
从简历解析失败看智能招聘平台的异常处理架构设计

做智能招聘AI平台,第一步往往不是算法模型,而是简历解析。这个模块看着只是“把PDF转成文字再抽字段”,实际上平台的解析成功率直接影响整个推荐链路的可用性。我见过太多团队在简历解析上栽跟头:有的把解析服务写成同步调用&… · 2026/9/25 9:20:17

体育赛事管理系统JavaWeb毕设全攻略:数据库设计到部署避坑
体育赛事管理系统JavaWeb毕设全攻略:数据库设计到部署避坑

1. 为什么体育赛事管理系统是JavaWeb毕设的稳妥选择每年到选题季,各种"求推荐一个毕设题目"的消息就没断过。我最常见到的情况是:基础一般的同学题目偏偏往互联网大厂方向凑,什么秒杀系统、微服务商城,最后卡在环境配置… · 2026/9/25 9:20:17

LaTeX空格完全指南:从原理到实战的间距控制技巧
LaTeX空格完全指南:从原理到实战的间距控制技巧

1. 先搞清楚LaTeX为什么"吞"空格1.1 TeX的空白字符设计哲学我当年从Word转LaTeX的时候,第一个崩溃的瞬间就是在正文里敲了十几个空格,编译出来跟没敲一样。这不是软件坏了,也不是你操作不对,而是TeX这套排版系统的底层逻… · 2026/9/25 9:20:04

数值优化(Numerical Optimization)学习系列-03-共轭梯度方法(Conjugate Gradient)
数值优化(Numerical Optimization)学习系列-03-共轭梯度方法(Conjugate Gradient)

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

创维E900V22D刷机全攻略:S905L3SB芯片兼容性解析与救砖实战
创维E900V22D刷机全攻略:S905L3SB芯片兼容性解析与救砖实战

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

MQTT协议原理与Broker服务器搭建实战:从Mosquitto到EMQX
MQTT协议原理与Broker服务器搭建实战:从Mosquitto到EMQX

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

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码