Kubernetes探针配置实战:Java应用liveness、readiness与startup全解析
有一次排查线上问题某服务的 Pod 状态一直是 Running日志也没有明显报错但用户反馈接口大面积超时。查了半天发现是数据库连接池被慢查询占满整个服务其实已经假死新进来的请求全在排队等连接。而 K8s 对此毫无察觉因为容器的进程还活着CPU 和内存也都在正常范围内直到我手动重启才恢复。从那以后凡是 Java 应用上 Kubernetes我都会第一时间把 liveness 和 readiness 探针配好这大概是所有 K8s 部署实践里投入产出比最高的故障自动恢复手段没有之一。这篇文章会把探针相关的配置思路、参数取舍、Java 应用特有的坑以及排查方法完整讲一遍。适合正在把 Spring Boot 应用迁到 K8s 的后端开发、刚接手运维职责的全栈工程师以及已经被Pod 活着但服务不可用坑过的朋友。1. 容器活着不等于服务可用1.1 一次假死事故复盘先把这个事故拆开看。当时服务本身没有崩溃JVM 进程正常存在所以 K8s 认为容器健康不会触发重启。但服务对外提供的 HTTP 接口已经无法及时响应因为所有 Tomcat 工作线程都阻塞在等待数据库连接上线程池被打满之后新请求只能排队超时时间一过客户端就报错。这种状态在运维领域有个俗称叫假死进程级的健康检查和业务级的健康检查之间出现了断层。K8s 默认只关心进程是否启动不管你的业务逻辑是否正常工作。如果没有探针它就没有任何手段感知这种异常只能靠外部监控报警后人工介入。当时我们其实有健康检查接口但没人把它接到 K8s 上。接口本身也做得不够好只检查了内存和线程数没有检查数据库连接池和关键依赖状态所以即使探针去打这个接口也测不出问题。后来把健康检查改成了真实依赖检查再接上探针这个问题才算从根上解决。1.2 K8s 的三条生命线liveness、readiness、startup探针分三种很多人一开始只记得 liveness 和 readiness忽略了 startup。实际上在 Java 场景下startup 探针常常比前两条更好用。先说 liveness它的职责是判断容器要不要被杀掉重启。如果探测失败kubelet 会杀掉容器然后按照 Pod 的 restartPolicy 重新拉起。它解决的是进程卡死、死锁、内存溢出导致无法服务这一类问题。再说 readiness它的职责是判断容器要不要接流量。如果探测失败kubelet 不会杀容器而是把这个 Pod 的 Endpoint 从 Service 的负载均衡池里摘掉。它解决的是服务暂时不可用但可能自己恢复的问题比如缓存预热、数据库连接重建、依赖服务正在重启。最后是 startup它的作用是保护慢启动容器。在 startup 探测成功之前liveness 和 readiness 探测不会启动。这意味着如果你的应用启动需要 60 秒但你不想把 liveness 的 failureThreshold 调得很大就可以用 startup 来兜底。三者的关系可以类比成startup 是等它完全站起来再开始体检readiness 是体检合格才放行上岗liveness 是上岗后一旦晕倒就赶紧急救重启。理解了这个分工配置起来就不容易乱。1.3 不配探针会怎样不配探针K8s 也能正常调度和运行短时间看不出问题。但遇到下面这些场景就会很难受Java 应用发生频繁 Full GC单次停顿超过几十秒接口超时但进程没死启动时依赖了某个外部服务外部服务延迟导致应用半启动状态持续很久数据库连接池耗尽或者连接被网络策略切断服务无法处理任何请求内存泄漏导致 JVM 慢慢失能但还没有触发 OOM 被杀这些情况没有探针就是无人值守的状态。有的团队靠外部监控报警再加人工重启先不说半夜起来处理有多痛苦光是恢复时间就比自动重启慢了几个量级。K8s 的故障自动恢复能力探针是最基础也最关键的一环。2. 配置前的准备工作先有一个靠谱的健康检查端点2.1 Spring Boot Actuator 的正确打开方式Java 生态里Spring Boot 应用一般用 Actuator 暴露健康检查信息。默认配置下/actuator/health返回的是整体健康状态里面包含磁盘空间、应用状态这些基础信息。但默认的 health 只检查应用本身和 DiskSpace对于数据库、缓存、消息队列这些依赖需要手动加 Indicator。Spring Boot 2.3 之后引入了健康检查分组的概念这个设计和 K8s 的探针模型几乎是配套的。你可以把一组检查项归到 readiness 分组把另一组归到 liveness 分组然后用不同的 URL 分别给两种探针用。典型的配置思路是这样readiness 分组包含所有外部依赖的检查比如数据库连接、Redis、消息队列liveness 分组只检查应用进程自身的基本状态比如内存、线程、CPU 使用情况。这么设计是有讲究的。如果某个下游依赖挂了readiness 应该失败让 K8s 把流量摘走但此时应用进程本身还活着还有可能通过重连逻辑恢复不需要重启。而 liveness 如果也依赖了外部服务外部抖动可能会导致容器被反复重启这是很多人踩过的坑。2.2 配置健康检查分组在application.yml里可以这样配置management: endpoints: web: exposure: include: health,info,metrics endpoint: health: probes: enabled: true group: readiness: include: db, redis, rabbit liveness: include: ping, memory配完之后/actuator/health/readiness会检查数据库、Redis 和消息队列/actuator/health/liveness只检查基础状态。注意ping是内置的最简单检查永远返回 UP除非应用本身有问题。这里有几个容易踩的坑。第一probes.enabled: true这个配置要看版本Spring Boot 2.3 到 2.6 的行为不完全一样一定要以你实际用的版本文档为准。第二如果你的应用不是 Spring Boot 体系是 Spring MVC 或者纯 Servlet那就要自己在代码里实现一个健康检查接口。第三健康检查接口本身不要做太重的操作比如查询大量数据、调用耗时的外部接口否则探针请求会把应用拖得更慢。2.3 自定义健康指标健康检查要查什么我见过不少团队的健康检查就是返回一个 200 的空 JSON这基本等于没做。一个合格的健康检查端点至少要检查应用真正依赖的资源数据库是否能执行一次简单的SELECT 1缓存Redis 是否能执行PING消息队列连接是否正常关键外部服务是否有必要的连接池可用以数据库为例用 Spring Boot 的DataSourceHealthIndicator就能自动检查。但要注意默认的健康检查会包含在整体 health 里如果你没有做分组隔离等于把数据库检查同时暴露给了 liveness这就会造成外部数据库抖动时 Pod 被重启的情况。所以在设计健康检查内容时我的建议是liveness 保持最轻量最好只检查应用进程自身状态readiness 才去检查外部依赖。这样两条探针各司其职既不会误杀也能及时摘流。3. 探针参数解析每个参数背后都是一次权衡3.1 参数速查与推荐基线K8s 的 HTTP 探针支持四个核心参数不同的组合对故障恢复速度和资源消耗有直接影响。我先给一套适用于大多数 Java 应用的基线配置再逐个解释为什么这么选。livenessProbe: httpGet: path: /actuator/health/liveness port: 8080 initialDelaySeconds: 20 periodSeconds: 15 timeoutSeconds: 3 failureThreshold: 3 readinessProbe: httpGet: path: /actuator/health/readiness port: 8080 initialDelaySeconds: 20 periodSeconds: 10 timeoutSeconds: 5 failureThreshold: 3这套配置的意思是启动 20 秒后开始探测liveness 每 15 秒探测一次3 秒内没响应或者状态码非 2xx/3xx 就记为一次失败连续失败 3 次就杀掉容器重启。readiness 每 10 秒探测一次5 秒超时连续失败 3 次就把 Pod 摘出负载均衡。3.2 initialDelay 怎么定先算 JVM 启动时间这个参数最容易被拍脑袋乱填。填小了应用还没启动完成就开始探测无缘无故失败几次liveness 可能直接把容器杀了形成启动-被杀-重启的死循环。填大了在应用已经启动完毕却还没接上流量的这段时间里浪费了故障恢复的响应速度。合理的做法是先量一下应用的启动时间。可以在本地执行java -jar然后卡秒表也可以看日志里从启动到Started Application in X seconds的时间。大多数 Spring Boot 应用启动需要 10 到 30 秒加上容器镜像拉取、环境初始化的时间initialDelaySeconds 建议在 20 到 40 秒之间。不确认启动时间的情况下优先偏向填大一点。启动慢导致多等几秒问题不大但启动期被误杀导致无限重启就是事故了。如果应用启动确实很慢比如要预热缓存、加载模型那更建议用 startupProbe它可以接管这个慢启动阶段。3.3 period、timeout、failureThreshold 的配合逻辑periodSeconds决定探测频率。间隔越短发现故障越快但 kubelet 对 Pod 的探测请求就越频繁占用应用线程资源。Java 应用每个探针请求都会占用一个 HTTP 线程如果 period 太短大量探测请求会和业务请求抢线程池反而影响服务质量。15 秒的 liveness 周期、10 秒的 readiness 周期是比较稳妥的折中。timeoutSeconds决定单次探测等多久。默认值是 1 秒对 Java 应用来说有点紧张。健康检查接口如果刚好碰到 GC 停顿1 秒超时很容易失败。我一般会设成 3 到 5 秒给健康检查接口留出响应余量。但也不用设得太长否则失败检测太迟钝每轮探测要等好几秒才发现异常。failureThreshold决定连续失败几次才算真失败。这个参数的作用是容忍偶发抖动。比如你设置了 3意味着 kubelet 连续 3 次探测失败才会触发动作这中间大约就过去了 45 秒15 秒周期乘以 3 次。想更快恢复就设 2想更稳就设 3 或 4。读多写少的一致性原则是liveness 的 failureThreshold 可以大一点避免偶发 GC 导致重启readiness 的可以小一点因为摘流量不影响进程存活宁可提前摘掉也不要把坏流量放进去。3.4 startupProbe 解决慢启动问题如果你的 Java 应用启动时间不稳定或者启动阶段需要做大量初始化工作强烈建议加上 startupProbe。它的机制是只有 startupProbe 成功之后liveness 和 readiness 才开始工作。在这之前哪怕 liveness 没配 initialDelay也不会执行。一个常见的配置是这样的startupProbe: httpGet: path: /actuator/health/readiness port: 8080 initialDelaySeconds: 10 periodSeconds: 5 failureThreshold: 24这里periodSeconds5、failureThreshold24意味着最大允许启动等待时间是 120 秒。应用在 120 秒内启动完成就转由 liveness 接管超过 120 秒没起来容器会被杀掉重启。这个配置既保证了慢启动应用的存活又避免了无限等待。我实际使用中发现startupProbe 对 Java 应用迁移到 K8s 的初期特别有用。很多历史应用启动脚本里有一段加载本地配置、预热本地缓存的逻辑时间不稳定有时候 20 秒有时候 50 秒。这种情况下如果只靠 liveness 的 initialDelay 和 failureThreshold 去覆盖很容易顾此失彼。4. 实操配置从 Deployment YAML 到线上验证4.1 一个完整的 Deployment 配置示例把探针配置整合进 Deployment 之后一个完整的基础配置大概长这样apiVersion: apps/v1 kind: Deployment metadata: name: order-service labels: app: order-service spec: replicas: 3 selector: matchLabels: app: order-service template: metadata: labels: app: order-service spec: containers: - name: order-service image: registry.local/order-service:1.2.0 ports: - containerPort: 8080 name: http startupProbe: httpGet: path: /actuator/health/readiness port: 8080 initialDelaySeconds: 10 periodSeconds: 5 failureThreshold: 24 timeoutSeconds: 3 livenessProbe: httpGet: path: /actuator/health/liveness port: 8080 periodSeconds: 15 timeoutSeconds: 3 failureThreshold: 3 readinessProbe: httpGet: path: /actuator/health/readiness port: 8080 periodSeconds: 10 timeoutSeconds: 5 failureThreshold: 3 resources: requests: cpu: 500m memory: 512Mi limits: cpu: 2 memory: 2Gi注意几个细节。httpGet探针的port支持端口名所以上面定义端口时给了name: http配置里可以直接写port: http好处是容器端口变化时不需要改探针。liveness 和 readiness 探针在 startup 成功之前不会执行所以可以不用配initialDelaySeconds让 startupProbe 替你做初始等待。还有periodSeconds如果没配默认是 10 秒failureThreshold默认是 3 次。很多人在配置时只写了httpGet其余全靠默认值这不一定错但不是最优。4.2 分阶段配置策略先灰度再全量探针配置上线本身也存在风险。如果 liveness 配得太激进一个正常的服务可能刚上线就被反复重启。所以我建议遵循下面的节奏第一阶段只加 readiness 探针。readiness 失败只会摘流量不会重启容器即使配置有误最坏的情况是服务暂时不接流量人工介入改掉配置即可不会产生大规模故障。第二阶段确认 readiness 稳定后加上 startupProbe。这一步保护慢启动应用确保后面的 liveness 不会被启动期的失败误伤。第三阶段最后加 liveness 探针。上线时可以采用先更新单副本观察 10 分钟再滚动更新的方式确保 liveness 不会误杀。我见过有人在项目上线当天把所有探针一次配齐结果应用因为 startup 还没完成就被 liveness 探测失败连续重启了 20 多次最后把镜像换成了旧版本才恢复。探针配置不是越全越好而是越稳越好分阶段推进能让你在每一步都验证清楚。4.3 验证探针是否生效kubectl 状态解读配置好之后怎么确认探针在正常工作首先看 Pod 的事件kubectl describe pod pod-nameEvents 区域会显示探针的探测结果。正常情况下的输出类似Liveness probe succeeded、Readiness probe succeeded。如果出现Liveness probe failed后面会跟着失败原因比如超时、连接被拒绝、HTTP 状态码异常。注意这些事件不会一直保留一段时间后会被新事件顶掉所以发现问题要尽快看。还有一种情况是 readiness 探测失败Pod 状态会显示成NotReady。你可以在kubectl get pods里看到状态列从Running变成Running (NotReady)。如果应用本身有多个副本你会发现 NotReady 的 Pod 已经被自动摘出 Service 的 Endpoint 列表。检查当前哪些 Pod 在 Service 的后端列表里用这条命令kubectl get endpoints service-name如果某个 Pod 不在 endpoints 里说明其 readiness 探测当前失败。这个信息在排查为什么请求没有打到某副本时非常有用。4.4 HTTP 探针的实现原理kubelet 做了什么探针到底是怎么执行的很多人以为是 API Server 来做检查其实不是。每个节点上的 kubelet 会定期根据 Pod 配置对容器内 IP 的对应端口发起 HTTP 请求。探针请求的发起方是 kubelet目标 IP 是 Pod 的 IP不是 Service 的 ClusterIP。也就是说探针访问的是容器的本地端口绕过了 Service 负载均衡。这个细节的意义在于如果你设置了网络策略或者防火墙限制了 Pod 之间的访问要确保 kubelet 所在节点的网络能访问到 Pod 的 8080 端口。另外如果应用配置了 HTTPS 但探针用了httpGet它会直接失败。这时候可以用httpGet的scheme字段改成 HTTPS或者干脆在应用侧把健康检查端口单独暴露成 HTTP不承担业务流量。HTTP 探针的判定标准是响应状态码在 200 到 399 之间算成功其他都算失败。所以健康检查接口返回 404 或者 500 都会触发失败。有人图省事直接在探针里写了一个不存在的路径那这个探针从第一次探测起就会失败根据配置可能直接触发重启这是非常常见的新手失误。5. Java 应用与探针的相爱相杀5.1 GC 停顿和探针超时一个隐藏的对抗Java 应用有个特殊性JVM 在发生 Full GC 时所有应用线程都可能停顿包括处理 HTTP 请求的线程。如果 Full GC 停顿时间超过了探针的timeoutSeconds探针请求就会超时连续几次失败后kubelet 开始重启容器。而重启之后一个新的 JVM 启动又可能因为堆太大触发新一轮 GC形成恶性循环。这个问题在高内存配置下特别明显。我给一个测试服务配置过 8GB 堆内存未调优的 JVM 在启动后 Full GC 一次可能要 5 到 10 秒。探针timeoutSeconds如果保持默认的 1 秒几乎必然失败。后来把 liveness 的 timeout 调到 5 秒把 liveness 的 failureThreshold 从 3 调成 5同时去调 JVM GC 参数才算稳定下来。如果你发现 Pod 频繁重启但日志里又没有业务异常可以先看监控里的 GC 时间。只要确认了 GC 停顿和探针失败的时间点吻合就可以大胆把 timeoutSeconds 放大一点或者临时调大 failureThreshold。治标之后再治本调 GC 参数或者换垃圾回收器比如用 G1 替代 CMS能显著缩短停顿时间。5.2 线程池阻塞导致健康检查接口超时另一个 Java 特有的坑是线程池泄漏。Tomcat 默认的 max-threads 是 200如果某个上游接口变慢200 个线程全被占住新的请求包括健康检查请求就会排队。排队超过 timeoutSeconds 后探针失败应用被重启。重启后线程池干净了服务能恢复但如果你没有排查上游慢调用的问题这个过程会反复上演。这种情况下探针本身没有做错任何事情它按预期发现了容器无法响应请求的问题并触发了重启。真正的解决方向是把线程池隔离做好或者给关键外部调用设置合理的超时和熔断。但这里也要注意health 检查接口最好放在独立的线程池或者不走业务线程池这样即使业务线程池被打满探针还能响应。不过纯 Servlet 容器里改造起来比较复杂很多团队做不到那就只能让探针尽早发现问题靠快速重启恢复服务。5.3 慢启动与 startupProbe 的兜底设计Java 应用慢启动的原因很多类加载慢、Spring 上下文初始化慢、数据库连接池初始化慢、安全框架加载证书慢。有的应用启动一次要 60 秒以上而 K8s 默认期望一个容器在几十秒内启动完成并对外服务。有两个思路可以结合使用。一是给应用做启动加速比如开启 Spring Boot 的懒加载、并行初始化 Bean、跳过不必要的组件扫描。这些改动性能收益明显但有一定重构成本不建议在探针上线时顺便做。二是配置 startupProbe 兜底让 K8s 给应用留足启动时间同时不影响后续的快速故障恢复。我的建议是先把 startupProbe 配好保证应用能正常起来再慢慢优化启动速度。不要反过来在什么都不确定的时候强行优化 JVM 启动容易引入新的问题。探针的目的是保证系统可用不是逼你把启动压到 10 秒以内。5.4 数据库连接池耗尽与 readiness 联动数据库连接池耗尽是一个非常典型的场景。应用启动时连接池预创建了 20 个连接随着业务流量增长池里的连接被慢慢占满。新的请求拿不到连接SQL 执行超时Tomcat 线程被占住。这种情况下健康检查如果包含数据库状态检查会看到数据库本身是好的但连接池无法建立新连接这时候 database 的 health 会变成 DOWNreadiness 失败Pod 被摘流。摘流之后新的流量不会进来旧请求慢慢超时结束连接池逐渐释放。如果连接恢复readiness 重新成功Pod 重新加入负载均衡。这个过程在没有探针的情况下只能靠人工重启。接上探针之后这整套恢复可以自动完成。但要注意如果整个服务的所有副本都因为连接池耗尽而 readiness 失败服务对外表现为不可用探针不会帮你解决根因。服务的可用性取决于副本的恢复能力和流量编排策略探针能保证的是在异常情况下快速隔离和重启而不是让服务在依赖故障时不受影响。6. 常见问题与排查技巧实录6.1 Pod 被反复重启先看这个命令出现 Pod 反复重启时最快的定位路径是kubectl describe pod pod-name重点看两个地方。一个是Containers下面的Last State如果显示Terminated且Reason是Error或OOMKilled说明容器是被意外终止的。另一个是Events区域的Liveness probe failed能直接告诉你探针失败的时间点和失败原因。我遇到过一个很隐蔽的情况容器被 OOMKilled 杀掉了但 show 出来的 reason 是Error探针事件里根本没有 liveness 失败记录。后来查了节点的dmesg才发现确实是 OOM。所以如果探针没问题但 Pod 还是重启不要只盯着探针配置内存限制可能才是最根本的原因。6.2 探针失败但应用日志没有异常这个场景很常见kubectl describe 显示 liveness 失败但应用日志没有对应的错误堆积。因为探针请求是 kubelet 发起的如果你没有给健康检查接口加访问日志这部分请求根本不会出现在应用日志里。这不能证明探针是误报只能说明你没看到探针请求的处理情况。验证方法是可以临时在健康检查接口里加一行日志或者用kubectl exec进入容器手动 curl 一下探针路径kubectl exec -it pod-name -- curl -v http://localhost:8080/actuator/health/liveness如果手动访问也是超时或 5xx说明应用侧确实有问题比如线程池满、依赖故障。如果手动访问正常但 kubelet 探测失败则要检查节点网络、健康检查端口是否被防火墙拦截、Web 容器是否有多个连接器监听不同端口导致探针打到了错误的端口。6.3 readiness 失效的常见原因配置了检查项但没有探针还有一类问题是探针本身存在但不检查依赖。某团队在 Actuator 里配置了数据库检查但 Deployment 里的 readiness 探针直接指向/actuator/health而不是/actuator/health/readiness。如果整体 health 因为别的非关键指标降级readiness 探针也会跟着失败导致 Pod 被摘流。这也是我前面强调分组的原因。默认的/actuator/health是个大杂烩会包含所有检查项的状态。很多时候一个无关紧要的自定义 Indicator 状态变化会让整个 health 变成 DOWN进而影响探针。如果你不希望某个检查项影响 K8s 的流量调度和重启决策就不要把它放进探针使用的那个分组。利用 Actuator 的分组能力把探针关注的检查项和其余的分开是避免这类问题的最直接手段。6.4 探针配置避坑速查表问题现象常见原因推荐排查方向Pod 无限重启启动后几十秒被杀initialDelaySeconds 太小或 liveness 探测太激进调大 initialDelay或改用 startupProbe 兜底探针一直失败但业务正常探针路径写错、端口不对、健康检查接口太重kubectl exec 手动验证路径可访问性外部依赖抖动导致 Pod 被频繁重启liveness 检查了外部依赖数据库或 Redis 波动重新分组liveness 只保留最基础检查Full GC 期间探针连续失败GC 停顿时间超过 timeoutSeconds调大 timeout、调优 JVM GC 参数Pod Running 但不在 Service endpoints 里readiness 探测失败Pod 被摘流查看 readiness 探针对应健康状态的详细结果容器 OOM 但表现为探针失败内存 limit 设置过小进程被杀查节点 dmesg、调大内存限制、排查内存泄漏6.5 上线前建议做一次故障注入演练配置探针不是写完 YAML 就完事了。我建议在预发环境做一次故障注入演练验证探针确实能按预期触发自动恢复。最简单的方式是手动进容器把健康检查接口搞坏或者直接 kill 容器的业务进程。也可以更粗暴一点把容器的网络断掉看 kubelet 的表现。我做过的最实用的演练是选一个非核心服务kubectl exec进去把线程池打满然后观察 readiness 是否在 30 秒内把 Pod 摘流再观察流量切走后 Pod 是否恢复正常并被重新加回。整个链路验证完再模拟 liveness 失败看容器是否在预期时间内被重启。实际执行下来你会发现很多预想不到的问题比如探针本身把健康检查线程也占满了、kubelet 在节点负载高时探测超时、应用启动时间比你预估的更长。这些问题只有真实演练才能暴露出来光靠静态检查配置是看不出来的。最后再分享一个小经验。探针配置最怕的不是参数复杂而是你把它当成写完就不管的一次性任务。Java 应用的内存模型、启动时间、依赖状况都会随着版本迭代变化探针参数也应该跟着调。我习惯在每次上线前花一分钟过一遍最近一次 Full GC 的最大停顿时间、应用启动耗时、数据库连接池的使用率然后核对探针参数是否需要微调。这个习惯救过我很多次因为最坑的故障往往不是配置错了而是配置当初是对的后来环境变了配置过期了。

相关新闻

机器视觉测试岗必考:手写OpenCV图像处理全流程

机器视觉测试岗必考:手写OpenCV图像处理全流程

简介:本资源为上海柏楚电子科技2024秋季校招「机器视觉测试工程师」岗位笔试真题汇编,面向准备工业视觉方向技术岗求职的应届生与转岗测试人员,聚焦机器视觉系统测试能力的综合考查。内容覆盖白盒测试逻辑、2D几何变换特性、相机成像模型&…

2026/10/11 17:14:09 阅读更多 →
YOLOv5垃圾分类识别实战:从数据标注到TensorRT部署全攻略

YOLOv5垃圾分类识别实战:从数据标注到TensorRT部署全攻略

简介:基于YOLOv5的垃圾分类识别检测项目,面向深度学习初学者与计算机视觉实践者,解决居民生活垃圾自动分类与类别定位问题。压缩包内共包含九千余个文件,其中以八千多张jpg图像、六百余个txt标注文件、近两百个xml标签以及三十个y…

2026/10/11 17:14:09 阅读更多 →
OpenCV实现白底图透明:从alpha通道原理到边缘羽化完整指南

OpenCV实现白底图透明:从alpha通道原理到边缘羽化完整指南

简介:面向图像处理入门与进阶学习者,这份压缩包围绕OpenCV白色背景移除与透明贴图主题,提供可运行的C语言工程源码及样图。通过掩模创建、阈值分割与位运算,演示如何将白色背景剔除并保留清晰轮廓,进而合成四通道图像完…

2026/10/11 17:14:09 阅读更多 →

最新新闻

Linux线程同步指南:从互斥锁、条件变量到生产者消费者模型

Linux线程同步指南:从互斥锁、条件变量到生产者消费者模型

1. 一条计数器的崩溃现场:竞态条件到底怎么回事上一周我在调一个批量图片压缩工具,开了四个线程同时去处理任务队列,结果跑出来的图片里有好几张是花的,还有一次直接段错误。我排查了很久,最后定位到问题根源不在压缩算…

2026/10/11 18:05:40 阅读更多 →
测试环境搭建全攻略:CentOS 7与Ubuntu 20.04双版本一键部署与Docker化实践

测试环境搭建全攻略:CentOS 7与Ubuntu 20.04双版本一键部署与Docker化实践

做测试环境搭建这事儿,看着不难,但坑是真不少。同一个部署文档,在 CentOS 7 上执行得顺顺利利,换到 Ubuntu 20.04 上就报错,或者反过来亦然——包管理器不同、软件源格式不同、防火墙规则不同、服务管理方式也不同。我…

2026/10/11 18:05:40 阅读更多 →
1011星里有多少是「真需求」?我给爆火的技能包泼盆冷水

1011星里有多少是「真需求」?我给爆火的技能包泼盆冷水

1011星里有多少是「真需求」?我给爆火的技能包泼盆冷水 【免费下载链接】golive-skill Take your agent-built product live: hosting, database, domain, email, payments — on your own accounts. Open-source Agent Skill zero-dependency Node CLI: detect →…

2026/10/11 18:04:40 阅读更多 →
零售企业“细节标准体系“的观察样本:一位董事长的胖东来研学笔记

零售企业“细节标准体系“的观察样本:一位董事长的胖东来研学笔记

本文基于上海鼎学甄选教育科技有限公司董事长阿甘在稻百年胖东来研学(许昌)课后采访整理,提取其口述中的观察维度与参照系,供零售与连锁企业参考。1. 观察对象:非销售性投入的密度 受访人:阿甘,…

2026/10/11 18:04:40 阅读更多 →
ComfyUI+AnimateDiff+ControlNet:从零搭建可控动画工作流

ComfyUI+AnimateDiff+ControlNet:从零搭建可控动画工作流

简介:面向ComfyUI生态的动画生成实战资源包,围绕AnimateDiff与ControlNet的OpenposeDepth组合,展示从姿态与深度控制到逐帧动画输出的完整链路,适合熟悉Stable Diffusion基础、希望进阶学习可控动画生成的研究者与创作者&#xff…

2026/10/11 18:04:40 阅读更多 →
OpenCV图像处理到深度学习推理:滤波、特征匹配与轮廓分析实战指南

OpenCV图像处理到深度学习推理:滤波、特征匹配与轮廓分析实战指南

简介:面向计算机视觉开发者和入门学员,这份PDF系统梳理了OpenCV从基础图像处理到深度学习集成的完整知识路径。文档以core、imgproc、objdetect等核心模块为线索,具体介绍图像读取与保存、颜色空间转换、几何变换等基础操作;滤波部…

2026/10/11 18:04:40 阅读更多 →

日新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/11 0:00:27 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/11 0:00:27 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

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

2026/10/11 10:45:37 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

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

2026/10/11 14:36:53 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

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

2026/10/11 14:36:54 阅读更多 →