news 2026/9/16 4:51:13

CKA备考:PriorityClass与Pod抢占机制实战解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
CKA备考:PriorityClass与Pod抢占机制实战解析

CKA备考练到Pod调度这块时,PriorityClass(优先级)这个知识点很容易被一带而过。很多人觉得它就是给Pod分个三六九等,考试时背个yaml就完事了。但根据2025年CKA新题的走向,PriorityClass不仅单独出题,还经常跟资源配额、节点亲和、驱逐策略组合在一起考,用来考查你对调度器完整决策链路的理解。从题目变化来看,光会创建PriorityClass已经不够了,你得真正理解它什么时候生效、怎么和抢占配合、优先级数值设成多少才合理,以及当系统报出NoPreemptionVictims这类事件时该怎么收场。

这篇文章不适合零基础从头看起,更适合已经了解Pod基本调度逻辑、正在搭CKA练习环境刷题的考生。我会从机制原理讲到实操验证,再到排错经验,全程用我在练习环境里实际踩过的坑来说话,尽量把这块内容一次讲透。

1. 为什么PriorityClass突然成了CKA热门考点

先说一个观察:近几年CKA题库迭代的速度明显加快,尤其是调度相关的题目,从“能创建资源”进化到了“能控制资源如何被调度”。PriorityClass在旧题库里确实不算主角,顶多是考你kubectl apply一个yaml,然后在Pod里指定priorityClassName。但2025年新题明显变了味道——它开始考察你对抢占机制的理解,甚至要求你在集群资源紧张的情况下,通过调整优先级来触发Pod驱逐。

1.1 调度器眼中“排序”这件事到底有多重要

Kubernetes调度器本质上是一个排队系统。集群里几百上千个Pending的Pod排队等着被调度到合适的节点上,调度器不可能随机乱挑,它要按某种规则排序。这个排序规则就是优先级。没有优先级时,所有Pod在调度队列里都是平起平坐;有了PriorityClass,高优先级的Pod就能插队。

但“插队”只是表面效果,内部实际发生过两件事:

  1. 调度队列排序:高优先级Pod进入调度队列后,排到更靠前的位置。
  2. 抢占式调度:如果队列前面的Pod找不到可用节点(比如资源不够),调度器不会干等着,而是直接尝试干掉节点上低优先级的Pod,把资源腾出来给高优先级Pod用。

CKA新题考的就是这个第二点。以前的题目只要你写出“优先级高的Pod会被先调度”这种理论答案就能拿分,现在它可能给你一个资源已经占满的节点,再提交一个高优先级Pod,问你接下来会发生什么,或者让你通过kubectl describe去排查为什么这个高优先级Pod还是Pending。

1.2 题目从“会写yaml”转向“会排错”

我备考时刷到一道模拟题,创建了一个PriorityClass并指定给一个Pod,但Pod始终Pending。用kubectl describe pod查看事件,发现了No preemption victims found for incoming pod这样的错误提示。当时第一反应是“优先级设得不够高”,后来仔细排查才发现,节点上的现存Pod全是静态Pod和DaemonSet托管的Pod,根本不参与抢占。

这就是新题出题的方向:不只是问你怎么做,而是给你一个已经做好的环境,让你去发现问题并修复。这跟你实际工作中维护生产集群的场景非常接近——线上Pod调度不上去,你总不能只看一眼yaml就交差,得会看事件、查调度器日志、分析节点资源。

1.3 PriorityClass在考试大纲里对应的知识点集群

从CKA官方大纲来看,PriorityClass归属于“调度、超卖与驱逐”这一大块。涉及的子知识点包括:

  • 调度器如何根据优先级排序Pod
  • PriorityClass的定义、修改和删除
  • globalDefault的影响范围
  • 抢占机制与preemptionPolicy设置
  • 与ResourceQuota、LimitRange的协作关系
  • 节点资源压力下的驱逐顺序

这些知识点在练习环境里是可以串成一个完整实验的。下文我会从搭建环境开始,一步步带你完成从创建PriorityClass到触发抢占的完整链路。

2. PriorityClass的核心机制:优先级、抢占和调度器三者怎么配合

想练好这个实验,先得把底层机制嚼碎。PriorityClass看起来只是个简单的key-value配置,但它背后牵动着调度器、kubelet和API Server三方的协作。

2.1 PriorityClass资源的本质:一个全局的“价目表”

PriorityClass是一个集群级别的资源,不属于任何Namespace。它的yaml长这样:

apiVersion: scheduling.k8s.io/v1 kind: PriorityClass metadata: name: high-priority value: 1000000 globalDefault: false description: "用于生产环境核心业务的高优先级类" preemptionPolicy: PreemptLowerPriority

几个关键字段逐一解释:

  • value:取值范围1到1000000000(十亿),数值越大优先级越高。
  • globalDefault:布尔值,标记这个PriorityClass是否是集群默认优先级。一个集群里最多只能有一个globalDefault: true,如果创建了多个为true的,后创建的会被API Server拒绝掉。注意,当集群里不存在任何globalDefault为true的PriorityClass时,Pod如果不指定priorityClassName,优先级默认是0。
  • preemptionPolicy:默认值是PreemptLowerPriority,表示这个优先级支持抢占低优先级的Pod;改成Never则只提高调度队列位置,不触发抢占。

这里插一句,很多生产场景为了避免高优先级Pod把节点上的业务Pod全干掉,会把preemptionPolicy设为Never,只让优先级参与调度排序。这个细节在CKA新题里出过,我当时就差点写错。

2.2 调度器排队:priority只是排序规则之一

调度器为Pod打分排序时,优先级不是唯一标准,但它是第一层过滤器。有心人可以看一下调度器源码里PrioritySort这个插件,它实现了最基础的排序逻辑——把待调度的Pod按优先级从高到低排列,再一个个送入调度管线。

这里的重点是:排序发生在调度管线之前。高优先级Pod会被更早地尝试调度,但并不意味着它一定能被调度成功。如果集群没有任何节点能满足它的资源要求,它还是一样会Pending。优先级只能保证“优先尝试”,不能保证“一定成功”。

2.3 抢占:真正让优先级“硬起来”的机制

当高优先级Pod进入调度管线后,如果没有节点满足它的资源需求,调度器会尝试寻找一个节点,通过抢占该节点上低优先级Pod来腾出资源给高优先级Pod。抢占流程大致分四步:

  1. 选受害者:调度器在所有节点上找“部分Pod”可以被抢占后、剩余资源刚好满足高优先级Pod的节点。
  2. 模拟驱逐:选出受害者Pod后,调度器会先模拟一遍删除这些Pod后节点是否满足需求。
  3. 提前占坑:调度器会立刻在API Server里抢占这个节点的资源配额(通过nodebinding.kubernetes.io/taint这类污点机制),防止其他Pod“截胡”。
  4. 真正驱逐:受害者Pod被优雅终止,高优先级Pod随后完成调度。

整个过程看起来比较粗暴,但设计上有一个关键底线:不会抢占比待调度Pod优先级更高的Pod。也就是说,如果节点上有同优先级或更高优先级的Pod,这些Pod不会成为受害者。这个规则,考试里经常拿来出判断题。

写到这里就不得不提No preemption victims found for incoming pod这个报错。它的完整含义是:高优先级Pod确实尝试抢占,但当前所有节点上找不到可以被抢占的低优先级Pod。常见原因有三个:

  • 节点上的Pod都是同优先级或更高优先级
  • 节点上的Pod全是DaemonSet、静态Pod这类un-daemon的Pod,调度器默认不抢占它们
  • 抢占虽然找到了受害者,但模拟驱逐后发现资源仍然不够

遇到这个事件,你先别急着改PriorityClass的数值,应该先排查受害者的候选对象,判断是不是节点上根本没有低优先级Pod可选。

2.4 kubelet层面的驱逐:另一种“优先级”

这里还要区分清楚调度器的抢占和kubelet的驱逐。前者发生在调度阶段,解决的是“Pod还没跑起来、找不到位置”的问题;后者发生在节点运行阶段,解决的是“节点内存或磁盘资源耗尽、需要牺牲部分Pod保集群稳定”的问题。

当节点内存(或磁盘)触发驱逐阈值时,kubelet会按Pod的优先级排序,优先杀掉低优先级Pod。这个优先级也是来自Pod的.spec.priority字段,而该字段正是由Pod指定的PriorityClass换算出来的。所以你在kubectl get pod xxx -o yaml里看到的priority: 1000000,就是这么来的。

3. 练习环境准备:搭一套多节点集群来验证优先级行为

PriorityClass的很多行为,尤其是抢占,单节点minikube玩不出效果,因为抢占需要“另一个Pod占着资源不撒手”。我建议至少准备一个两节点的集群,你可以在任意一台Linux机器上用kubeadm现搭一套最简集群,或者用云厂商的托管集群都行。我自己的练习环境是:1台2C8G的控制节点,2台2C4G的工作节点,Kubernetes版本选的1.29.4稳定版。

3.1 准备两个不同优先级的PriorityClass

先把实验要用的PriorityClass一次性准备好。

# low-priority.yaml apiVersion: scheduling.k8s.io/v1 kind: PriorityClass metadata: name: low-priority value: 100 globalDefault: false description: "低优先级测试类" preemptionPolicy: PreemptLowerPriority # high-priority.yaml apiVersion: scheduling.k8s.io/v1 kind: PriorityClass metadata: name: high-priority value: 1000 globalDefault: false description: "高优先级测试类,用于CKA练习" preemptionPolicy: PreemptLowerPriority

数值差距拉开一个量级就够了,不要一上来就设成十万、百万级,虽然系统允许,但不利于观察行为差异。在练习环境里,100和1000的差值足够触发抢占。

创建并验证:

kubectl apply -f low-priority.yaml -f high-priority.yaml kubectl get priorityclasses

正常能看到两个PriorityClass加上Kubernetes自带的system-cluster-criticalsystem-node-critical,一共四个。

3.2 如何正确查看Pod绑定后的优先级

创建完PriorityClass后,写一个引用它的Pod试试:

apiVersion: v1 kind: Pod metadata: name: test-high-priority spec: priorityClassName: high-priority containers: - name: nginx image: nginx:1.25

应用后查看细节:

kubectl get pod test-high-priority -o yaml | grep -A2 'priority'

你会在spec里看到priority: 1000priorityClassName: high-priority两个字段。如果写的是describe命令,输出里也会直接显示PriorityClass名称和Priority数值。

3.3 globalDefault的认知盲区,别在这里翻车

CKA新题很喜欢把globalDefault作为一个陷阱点。我在一个练习群看到有同学问:“我创建了一个名称为high-priority的PriorityClass,设置了globalDefault为true,为什么集群里已有的Pod优先级还是0?”

原因其实很简单:globalDefault只在Pod创建时生效。已存在的Pod如果要变更优先级,只能重建,不能动态更新。另外,如果集群中本来就有globalDefault: true的Policy,你新创建的另一个globalDefault: true会被API Server直接拒绝。这道题我在模拟考试时做错过,后来自己在环境里试了两次才记住。

还有更隐蔽的一点:globalDefault为true的优先级作用于所有没有显式指定priorityClassName的Pod。但如果你同时存在globalDefault: true和Pod显式指定了某个PriorityClass,显式指定的优先级优先。这是个基本规则,但混在一起就容易出错。

4. 完整实操:创建一个被抢占的实验场景

概念说完了,进入正题。下面我在练习环境里从头走一遍“低优先级Pod占资源,高优先级Pod触发抢占”的完整实验。这套实验脚本,算是我备考CKA时觉得用途最大的一套素材。

4.1 用Deployment创造资源占用

首先创建一个能占住节点资源的低优先级Deployment,用来充当“被抢占者”。我这里用的是一个requests配置得很死板的容器镜像:

# resource-hungry.yaml apiVersion: apps/v1 kind: Deployment metadata: name: resource-hungry namespace: default spec: replicas: 2 selector: matchLabels: app: hungry template: metadata: labels: app: hungry spec: priorityClassName: low-priority containers: - name: stress image: polinux/stress command: ["stress"] args: ["--cpu", "2", "--timeout", "600s"] resources: requests: cpu: "2" memory: "4Gi"

这里有两个细节需要留意:

  1. 必须写requests:调度器只认Pod的requests,不认limits。你写limits再大,调度器也不关心,因为limits只是运行时限制。所以想要把节点的可分配资源占满,就要把requests写足。
  2. replicas数量要匹配节点资源:我这里的测试节点每台有4C8G,但这个Deployment创建在单节点上,请求2×2=4个CPU和2×4=8G内存,可以直接吞掉一个小节点的大部分资源。

我会人为指定Pod调度到某个特定节点,方便观察后续行为。操作方式是在Pod模板里加nodeSelector

nodeSelector: kubernetes.io/hostname: worker-1

如果不知道节点名,先跑一下kubectl get nodes --show-labels确认。

4.2 观察低优先级Pod的调度结果

应用Deployment后,确认Pod处于Running状态:

kubectl get pods -o wide

你会看到两个resource-hungry-xxxx都调度到了worker-1节点。这个节点剩余的可分配资源应该被压得很低。你可以用kubectl describe node worker-1 | grep -A10 "Allocated resources"来确认。

这里再分享一个我实践时用的小技巧:直接在describe node里看Allocated resources下面的CPU RequestsMemory Requests。它会显示占用的百分比,如果接近100%,说明节点的资源确实已经被吃掉了。如果百分比低于预期,检查一下是否还有其他系统组件占用了,或者你的requests数字没有写对。

4.3 提交高优先级Pod,触发抢占

接下来创建要抢占的高优先级Pod:

# winner.yaml apiVersion: v1 kind: Pod metadata: name: winner spec: priorityClassName: high-priority nodeSelector: kubernetes.io/hostname: worker-1 containers: - name: nginx image: nginx:1.25 resources: requests: cpu: "1" memory: "1Gi"

创建后立刻查看:

kubectl get pods -o wide

正常情况下,你会看到resource-hungry有一个Pod被终止(Terminating或直接消失),而winner变成了Running。这就是抢占成功的效果。

让我解释一下为什么被杀的是一个Pod而不是全部:高优先级Pod需要1个CPU和1G内存,节点上只要挤掉一个低优先级Pod就能腾出2个CPU和4G内存,调度器不会多杀。它会选择最少“牺牲”的那个Pod来驱逐。

4.4 用事件和历史记录复盘整个抢占过程

如果你想知道到底发生了什么,不要只盯get pods。要看Events:

kubectl get events --sort-by=.lastTimestamp | tail -30 kubectl describe pod winner

describe pod里会有类似这样的事件记录:

Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Preempting 3s default-scheduler Preempting other pods based on priority Normal Scheduled 3s default-scheduler Successfully assigned default/winner to worker-1 Normal Pulling 2s kubelet Pulling image "nginx:1.25" Normal Pulled 2s kubelet Successfully pulled image "nginx:1.25"

这行Preempting other pods based on priority,就是调度器替你执行抢占动作的痕迹。实际生产环境中,这种事件一旦出现在核心业务Pod上,说明集群资源已经到了相当紧张的地步,该考虑扩容或给低优先级任务降配了。

4.5 注意:抢占不是瞬时的

很多人做这个实验会有一个错觉,以为提交高优先级Pod的瞬间,低优先级Pod就立刻消失。实际上抢占过程有几步要走:

  1. API Server记录Pod更新
  2. 调度器发现无法正常调度
  3. 调度器计算抢占方案并驱逐低优先级Pod
  4. kubelet异步处理Pod删除

整个过程通常在秒级完成,但如果节点负载高或者API Server响应慢,可能会持续几十秒。我在练习时偶尔会碰到winner卡在Pending状态长达一分钟的情况。排查方法还是看事件,确认它是在等待抢占还是真的无法调度。

5. 常见报错与排查链路:NoPreemptionVictims不是世界末日

备考进入刷题模式后,我遇到最多的报错就是No preemption victims found for incoming pod。这里单独开一节讲排查链路,因为这个问题非常典型,而且CKA的新题大概率会以它作为“故障场景”来出。

5.1 完整排查链路:从事件到根因的五步走

当Pod无法被调度时,我的排查顺序固定是:

第一步:看Pod状态和事件

kubectl describe pod <pod-name>

关注Events区域有没有类似FailedSchedulingUnexpectedAdmissionError的信息。如果出现No preemption victims found for incoming pod,说明调度器已经尝试过抢占,但失败了。

第二步:看节点资源是否真的不足

kubectl describe node

重点看Allocated resources这一栏。有时候你的高优先级Pod其实只要0.1个CPU就能跑,但节点确实一丁点资源都不剩了,抢占了也没用。

第三步:看目标节点上有没有可被抢占的对象

列出节点上所有Pod,筛掉DaemonSet和静态Pod:

kubectl get pods --all-namespaces -o wide --field-selector spec.nodeName=worker-1 kubectl get daemonsets --all-namespaces

如果节点上的Pod全是kube-system里由DaemonSet管理的,调度器默认不会抢占这些Pod。原因很简单:它们是集群基础设施的一部分,优先级很高(system-cluster-criticalsystem-node-critical),普通PriorityClass设计的Priority值根本不会超过它们。

第四步:看是否因为preemptionPolicy: Never禁止了抢占

有些考生会把PriorityClass的preemptionPolicy误设成Never,然后又期望它触发抢占。这本身不矛盾,但如果你明确指定了preemptionPolicy: Never,调度器只会参与队列排序,绝不会去抢占任何Pod。这时候即使节点满负荷,高优先级Pod也只会老老实实Pending。

第五步:看调度器日志(高级排查)

如果上述步骤都查不出问题,直接去控制平面容器里看调度器日志:

kubectl logs -n kube-system $(kubectl get pods -n kube-system | grep kube-scheduler | awk '{print $1}') --tail=200

CKA考试环境一般允许你查看控制平面Pod日志,这个排错动作本身就是题目考察点之一。

5.2 我踩过的一个典型案例

有一回我在练习环境里模拟一个“高优先级Pod抢占低优先级任务”的场景。无论我PriorityClass的value调到多高,Pod始终Pending。折腾了快40分钟,最后发现问题是节点被加了一个NoSchedule污点,而我创建的Pod没有指定对应的容忍度。

这个案例特别适合作为New Question的素材,因为它把污点容忍度和优先级两个知识点混在一起考。调度器是先检查污点容忍,再检查资源,最后才轮到抢占逻辑。你优先级再高,如果容忍度不匹配,连调度管线都挤不进去。

5.3 学会看优先级类型的Owner

还有一个小细节容易被忽略——system-cluster-criticalsystem-node-critical这两个内置PriorityClass是不能删除的,强行删除会导致API Server报错。考试时有道题让我确认某核心组件的PriorityClass,我一开始以为是自己创建的,后来kubectl get priorityclass system-cluster-critical -o yaml才发现它的owner是kube-apiserver自己。这提醒我们:生产环境里动内置PriorityClass要格外谨慎,先确认owner再操作。

6. 备考建议:PriorityClass怎么和场景结合出题

单会创建PriorityClass只是入门,CKA新题更看重的是“在一个完整场景里解决问题”的能力。所以我建议在练习环境里多做这几个方向。

6.1 组合实验一:PriorityClass + ResourceQuota

在某个Namespace里创建一个ResourceQuota,单位为requests.cpu,总量设置为1。然后在同一个Namespace里分别创建三个Deployment,优先级从低到高。观察高优先级Pod能否抢占配额内的资源,还是直接被Quota拒绝。

这个实验考察的核心是:PriorityClass决定调度顺序,ResourceQuota决定能不能创建。两者不是同一个层面的机制。很多CKA考生在这个地方犯迷糊。正确的理解是:ResourceQuota在你创建Pod的时候就会校验,跟调度器的优先级排序没有直接关系。即使PriorityClass再高,如果超出该Namespace的Quota,Pod也会直接被拒绝,连调度的机会都没有。

6.2 组合实验二:PriorityClass + PodDisruptionBudget

创建一个PDB,设置minAvailable: 1,关联到某个工作负载的Pod selector。然后触发节点排水(kubectl drain),看看PDB限制下的驱逐行为,会不会因为优先级而区别对待。

CKA新题里,PDB不会阻止抢占是一个容易踩的坑。PDB定义的是“自愿驱逐”时的最低可用Pod数,但PriorityClass的抢占是一种非自愿性操作,不遵循PDB限制。举个例子:你有个低优先级Deployment,3副本,PDB设置minAvailable为2。当一个高优先级Pod要抢占时,调度器可以把这3个副本全部干掉,只为了给高优先级Pod腾地方。PDB在这时候是不提供保护的。这个设计逻辑很多人觉得不合理,但Kubernetes就是这么工作的。

6.3 组合实验三:PriorityClass + Taint与Toleration

给一个节点添加dedicated=high-priority:NoSchedule污点,同时给高优先级Pod添加对应的容忍,低优先级Pod不添加容忍。观察调度结果和抢占行为。

这个实验可以帮你建立“容忍度是第一道门槛”的直觉。如果高优先级Pod没有容忍度,它永远无法被调度到这个节点上,无论PriorityClass有多高。

6.4 从考试角度看PriorityClass的“反向出题”

2025年CKA新题还有一个趋势:反向出题。不再问“这个PriorityClass会让Pod怎么样”,而是给你一个生产环境的现象描述,让你反推需要创建什么优先级的PriorityClass。

比如:

  • 场景一:kube-system里有个核心组件经常被低优先级Pod挤掉资源,需要保证它永远优先调度。→ 解决方案:给该Pod关联system-cluster-critical或更高优先级的自定义PriorityClass。
  • 场景二:批处理任务拥进来,把节点资源全部吃光,导致有状态服务无法调度。→ 解决方案:给有状态服务设置高优先级PriorityClass。
  • 场景三:测试环境的开发Pod优先级不能太高,但也不能被别人随便抢占,还想让它们参与调度排序。→ 解决方案:优先级中等,preemptionPolicy: Never

备考到最后,我会这样检验自己:不看答案,直接在白纸上把“高优先级Pod → 调度器排队 → 资源不足 → 查找受害者 → 模拟驱逐 → 真正的驱逐 → 调度成功”这条链路画一遍,每个环节说出涉及的组件和可能的失败原因。能完整画下来,说明这部分内容是真的掌握了。

7. 最后再分享两个小技巧

实验做到这里,该掌握的知识点都过了一遍。最后补充两个我自己练习中使用频率最高的操作习惯,对CKA备考和日常排查都有用。

第一,养成看Pod最终yaml里priority字段的习惯。很多人创建了PriorityClass却不知道Pod是否真的生效,直接在kubectl get pod -o yaml里搜priority两个词就能确认,比反复看describe更直观。

第二,练习结束后记得清理环境。如果创建了globalDefault为true的PriorityClass,清理时要格外小心,直接删除PriorityClass不会影响已经运行的Pod,但新创建的未指定优先级的Pod会回到0。练习环境无所谓,生产环境就必须先在低峰期操作,确认没有Pod依赖这个默认值再动手。

PriorityClass不是什么复杂机制,但它处在Pod调度的关键路径上,值得你在练习环境里多花半个小时把抢占行为、事件日志、边界条件都摸透。CKA考试里遇到相关题目,至少能保证不慌。

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

同城一对一音视频社交系统架构与原生App开发实战

简介&#xff1a;这是一套完整的社交类直播交友系统源码&#xff0c;面向Android与iOS双端开发者、中小型社交平台创业者及二次开发需求者&#xff0c;解决从0搭建同城视贫聊天、一对一音视频约聊、主播变现等核心功能的技术落地问题。资源包含1183个文件&#xff0c;主体为494…

作者头像 李华
网站建设 2026/9/16 4:48:49

扣子chatSDK图片显示不全?从RecyclerView与scaleType排查修复

先说结论&#xff1a;这个图片显示不全的问题&#xff0c;我遇到的时候十有八九不是扣子chatSDK本身的“坏”&#xff0c;而是我们在接SDK时对消息容器高度、图片显示模式的控制没处理好。尤其是Android端&#xff0c;图片底部一整截被裁掉、长图直接消失、某些情况下甚至连右侧…

作者头像 李华
网站建设 2026/9/16 4:47:01

工业级无线控制架构:AS5013+R7KA8D2KFLCAC实现高鲁棒低延迟闭环

1. 项目概述&#xff1a;这不是“无限”&#xff0c;而是高鲁棒性、低延迟、多节点协同的工业级无线控制架构“使用AS5013和R7KA8D2KFLCAC实现无限控制”——这个标题乍看像科幻设定&#xff0c;实则指向一个在工业自动化、智能楼宇与高端测试设备中真实落地的工程方案。我第一…

作者头像 李华
网站建设 2026/9/16 4:46:42

工业数据采集实战:从现场调试到边缘网关的完整指南

工业数据采集&#xff0c;表面上看就是把设备的数据读出来、传上去、存下来&#xff0c;但干过这行的人都知道&#xff0c;这活儿远比想象中难十倍。那些刚入行觉得“不就是用个网关读Modbus嘛”的念头&#xff0c;基本在第一次到现场调试的时候就被击碎了。这篇文章我想把我这…

作者头像 李华
网站建设 2026/9/16 4:45:37

空调线控器弱电接线与蓝牙调试标准化实战指南

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

作者头像 李华
网站建设 2026/9/16 4:45:18

宁波网站推广优化公司怎么样看3个实战案例

宁波网站推广优化公司怎么样看3个实战案例 很多老板拿着预算单,心里打鼓:自己不懂代码,不会搭服务器,想找宁波本地的推广优化公司,到底靠不靠谱?别慌,这正是我干了十年建站最擅长的领域。我看过太多宁波的中小企业主,因为盲目找“大而全”的广告公司,结果网站建得像样,但搜不到、打不开、留不住客户,钱花了,效…

作者头像 李华