新闻详情

新闻详情

首页 / 资讯中心 / 详情

Spring Boot优雅关闭全攻略:从原理到K8s部署实践

发布时间:2026/10/1 17:45:11来源:尧图网络
Spring Boot优雅关闭全攻略:从原理到K8s部署实践
1. 应用关闭的基础原理1.1 关闭场景比你想的更多我最初接触 Spring Boot 关闭这个话题是在一次压测环境里发现服务进程怎么也杀不掉。当时运维同事用kill -9 PID把进程结束了结果下游的 MQ 消息大量堆积业务方反馈数据丢失严重。排查了很久发现问题不是出在压测脚本里而是这个 Spring Boot 应用根本没有正确处理关闭流程。很多人会觉得关闭不就是停掉进程吗但在生产环境里关闭过程直接决定了你在途请求能否处理完、缓存数据会不会丢、连接池是否被正确释放。Spring Boot 应用关闭主要分三种场景手工停止CtrlC、发送信号kill PID或者kill -15 PID、代码里主动调用SpringApplication.exit()。每种场景触发 JVM 退出机制走的是同一条关闭路径但对业务的影响完全不同。先讲 JVM 退出的大框架。JVM 对 SIGKILLkill -9是直接放弃抵抗连关闭钩子都不执行而对 SIGTERMkill -15或者 CtrlC 会触发所谓的 shutdown hook也就是 JVM 向所有注册过的关闭钩子线程发起执行请求。Spring Boot 的关闭逻辑就挂在这样一个钩子线程里。所以说kill -9是最粗暴的关闭方式能不用就尽量别用否则连PreDestroy都不会被调用。这里有个容易被忽略的细节JVM 的 shutdown hook 是在所有非守护线程结束后才执行吗不是。JVM 收到 SIGTERM 后它开始并发运行所有 shutdown hooks但不会等待普通业务线程自行结束。如果你在业务线程里做大量清理JVM 可能已经退出了。这也是为什么我们后来给 Spring Boot 开启了优雅关闭就是为了让框架在 JVM 真正退出前多给业务留一段处理时间。1.2 关闭路径的核心组件Spring Boot 应用关闭的核心入口是SpringApplication.run()返回的ConfigurableApplicationContext。你拿到它之后可以调用close()方法也可以调用SpringApplication.exit(applicationContext)后者多做了一步返回一个退出码可以手动传给System.exit()。实际部署中这两种方式用的相对少因为大多数场景是外部信号触发。Spring Boot 关闭路径上有三层东西层级组件负责内容容器层ApplicationContext管理 Bean 生命周期触发销毁逻辑框架层ShutdownHookJVM 信号触发后调用容器关闭业务层PreDestroy / DisposableBean释放连接、清缓存、通知上下游如果你只是简单地把 Spring Boot 应用跑起来就完事不管这三层那遇到流量高峰期关闭服务掉数据、连接泄漏这些问题迟早会找上门。下面我具体拆解实际配置。2. 优雅关闭的完整配置与实现2.1 Spring Boot 2.3 之后的配置方式Spring Boot 从 2.3 开始内置了优雅关闭支持。在这之前我们通常用的招数是PreDestroy 自定义线程池等待或者引入第三方组件代码量不算大但要照顾的点非常多。Spring Boot 2.3 把这件事收敛成了两行配置spring.lifecycle.timeout-per-shutdown-phase30s server.shutdowngraceful这个配置的含义是应用收到关闭信号后先停止接收新的 HTTP 请求然后给正在处理的请求留 30 秒时间处理完。超过 30 秒还没结束的请求框架不会继续等直接进入 Bean 销毁阶段。如果你用的是 Spring Boot 2.2 或者更老版本这个配置不生效你得升级或者用后面我讲的SmartLifecycle手工方案。为什么 Spring Boot 要让配置升级核心原因是WebServerGracefulShutdown和NettyWebServer等组件实现优雅关闭需要用ServerShutdown枚举控制行为老版本里 Tomcat 的连接器没有暴露连接的优雅停止接口没法做到等待在途请求完成这个语义。配置server.shutdowngraceful后Spring Boot 在底层对 Tomcat、Jetty、Reactor Netty 都做了适配。以我们最常用的 Tomcat 为例框架会调用TomcatConnectorCustomizer改写连接器的关闭行为当收到关闭信号连接器会把内部状态标记为暂停接新连接已有的 keep-alive 连接会被逐一关闭正在处理的请求则等待。这个逻辑在源码里面对应TomcatConnector里的close()配合AbstractProtocol的暂停操作。2.2 超时时间设置的取舍spring.lifecycle.timeout-per-shutdown-phase30s这个参数我建议不要拍脑袋写死要根据你服务里的最大请求耗时来定。假设你的接口最慢需要 20 秒返回那你至少要给 20 秒以上再留出 10 秒给 Bean 销毁阶段。如果设置得太短比如 5 秒那长请求直接被中断客户端得到连接重置优雅关闭就形同虚设。但是也不要设置太长因为关闭阶段所有线程都在等待如果等 60 秒后进程还在Kubernetes 集群可能会把节点标记为不健康直接强杀kill -9。在我经历过的项目里通常是 30 秒到一个分钟之间。特别是部署到 Kubernetes 时有个联动问题preStop钩子如果阻塞时间超过terminationGracePeriodSeconds节点会强制杀容器。所以你在 Spring Boot 层面的超时时间至少要比terminationGracePeriodSeconds小几秒留出缓冲。另外要留意这个超时时间是每个阶段的超时时间不是总时间。lifecycle对多个阶段的处理是顺序执行的比如先等执行中的请求完成再触发PreDestroy阶段每个阶段都可以消耗掉一部分超时时间。所以实际总等待时间可能接近两倍配置值。我们当时的做法是设置 30 秒但是 K8s 的terminationGracePeriodSeconds配置到了 45 秒这样每个阶段最多 30 秒整体大概率在 45 秒内完成。2.3 优雅关闭做了哪些事配置开启后关闭流程可以分为几大步骤停止接收新请求。对于 HTTP 入口Tomcat 进入暂停状态新连接会直接被拒绝或等待。等待在途请求完成。此时链路里正在跑的线程会继续执行但不会创建新的线程来处理新任务。释放 Web 容器资源。比如 Netty 的 event loop group、Tomcat 的线程池这些资源如果不释放后续 Bean 销毁时可能还会被使用。执行 Bean 销毁逻辑。包括PreDestroy、DisposableBean、SmartLifecycle.stop()等。关闭 ApplicationContext。这五步不是互相独立的实际执行顺序和 Bean 的依赖关系、Order注解等因素都有关联。我在实践里发现一个比较隐蔽的坑如果你开启了 Feign、Ribbon 这类 HTTP 客户端组件它们内部的连接池在 Bean 销毁阶段如果去访问已经关闭的注册中心可能导致关闭过程变慢甚至抛出异常。这时候最好把连接池的释放时间放到PreDestroy之前或者给相关 Bean 设置较高的启动顺序。3. 自定义关闭逻辑的几种手段3.1 PreDestroy 的边界PreDestroy是 JSR-250 标准接口Spring 容器在销毁单例 Bean 之前会调用它。用法很简单Component public class CacheWarmer { PreDestroy public void close() { System.out.println(释放本地缓存连接); redisConnection.close(); } }但是注意PreDestroy不保证执行顺序除非你实现了DisposableBean接口或者设置DependsOn。我在一个服务里写了六个带PreDestroy的 Bean结果有一次关闭时某个依赖数据库的 Bean 先执行了数据库连接池已经关了导致另外几个 Bean 的清理逻辑直接报No dataSource错误。后来统一改成用SmartLifecycle管理。另外PreDestroy只在容器正常关闭时执行。如果进程被kill -9或者 JVM 崩溃那这段逻辑就是废的。所以不要把关键状态持久化比如标记当前节点正在下线放在PreDestroy里要放在数据库或者配置中心的独立状态位里由外部检查。3.2 SmartLifecycle 实现更可控的关闭当你有多个资源需要按顺序关闭时SmartLifecycle是正解。Component public class DatabaseResourceSupervisor implements SmartLifecycle { private boolean running false; private final DatabaseConnectionPool pool new DatabaseConnectionPool(); Override public void start() { running true; pool.initialize(); } Override public void stop() { if (running) { pool.releaseAll(); running false; } } Override public boolean isRunning() { return running; } Override public int getPhase() { return Integer.MAX_VALUE; // 最后执行 } }getPhase()方法控制多个SmartLifecycleBean 的启动顺序数值越小越先启动对应的stop()调用顺序是反过来的——启动顺序最晚的 Bean其stop()会最先执行。这就是为什么我们把释放外部连接池这个操作放在Integer.MAX_VALUE因为它要最后启动但销毁时它反而是第一步。实际生产里我用SmartLifecycle管理过三类资源数据库连接池、MQ 生产者的 channel、本地内存缓存。关闭顺序从后启动者先停的规则推出来先停掉本地缓存启动顺序最晚防止后面还有线程从缓存里拿数据。再停 MQ producer停止往外发消息。最后停数据库连接池保证还有线程做清理时能拿到连接。对应地三个 Bean 的getPhase()依次是0、-100、100。注意如果你不在stop()里把running置为 falseSpring 容器可能认为这个 Bean 还在运行导致关闭过程卡住。我见过有人忘记置 false结果应用退出前花了 3 分钟才反应过来就是因为LifecycleProcessor在等待一个永不结束的 stop 回调。3.3 手动触发关闭有些场景不能用信号关闭比如你的应用是一个在 JVM 内跑的子模块比如用 Spring Boot 做嵌入式组件这时候你可以通过代码手动触发关闭。public class ShutdownController { private final ConfigurableApplicationContext context; public ShutdownController(ConfigurableApplicationContext context) { this.context context; } public void doShutdown() { int exitCode SpringApplication.exit(context, () - 0); System.exit(exitCode); } }SpringApplication.exit会发布ExitCodeEvent你可以通过ExitCodeGeneratorBean 自定义退出码。这套机制在单元测试里也常用比如你测试一个 Spring Boot 应用的关闭流程不想真的把测试 JVM 杀掉就可以直接调用applicationContext.close()来验证PreDestroy逻辑。但有一点我踩过坑System.exit()会终止整个 Java 进程。如果你的应用是和其他模块共享同一个 JVM 进程的比如作为一个嵌入式库被调用直接System.exit()会把宿主进程一起关了。正确做法是只调用SpringApplication.exit()然后根据返回值决定是否需要退出避免不经意的强杀。3.4 Actuator 提供的关闭端点Spring Boot Actuator 2.x 里默认不开放shutdown端点因为风险太高。你如果想要通过 HTTP 控制关闭需要在配置里显式打开management.endpoint.shutdown.enabledtrue management.endpoints.web.exposure.includeshutdown然后发送POST /actuator/shutdown。这背后调用的是ShutdownEndpoint它会触发容器关闭流程相当于手动调用close()。很多老项目用它来做灰度下线时的服务摘除配合负载均衡器先摘流量再调用下线接口。但我不建议在生产环境把shutdown端点暴露到公网至少要用内网访问控制或者绑定在管理端口上。这个端点在现代 Kubernetes 部署中反而用得更少了因为 K8s 有专门的preStop钩子。你自己实现preStop时逻辑比直接kill进程要柔和得多可以把节点从配置中心标记为下线再等待几秒钟让注册中心刷新。这个 Ill 后面详细讲。4. 关闭过程中的典型问题和排查4.1 数据库连接被强杀我曾经见过一个关闭现场服务收到了 SIGTERM日志显示 Tomcat 正常开始优雅停止但紧接着数据库连接池报了一堆Connection is closed然后任务线程集体失败。排查后发现这个服务配置了 HikariCP 的最小空闲连接数为 2但spring.lifecycle.timeout-per-shutdown-phase5s。由于在途请求处理超过了 5 秒Spring Boot 直接进入 Bean 销毁阶段HikariCP 的close()方法把所有连接都释放了。而之前没处理完的请求线程还在继续使用这些连接自然就报错了。这个问题的根子在于优雅关闭超时时间必须大于最长在途请求时间。我们后来把超时拉到 30 秒并且调研了 HikariCP 的close()实现。HikariCP 的连接池关闭是先从池里借用连接然后逐个标记关闭期间如果有线程尝试从池里获取连接会拿到SQLTransientConnectionException。你不可能完全避免这类报错但可以尽量缩小窗口。如果你非常在意关闭阶段不出现任何连接错误还有一个方案不依赖 Spring Boot 的自动销毁而是实现SmartLifecycle它的stop(boolean timeout)方法会接收一个信号你可以根据剩余时间决定是否需要提前断开连接池。当然这种做法复杂度高生产环境一般用不上。4.2 线程池未清理导致进程不退出这是比关闭过程中报错更恶心的问题进程明明触发了关闭逻辑但怎么等都退不出去。最常见原因是线程池里的非守护线程没有关闭。默认情况下Executors.newFixedThreadPool 创建的线程是非守护线程。Spring Boot 关闭流程能否彻底退出取决于 JVM 是否还有非守护线程在跑。如果你在某个Component里直接new了一个线程池但没有把它声明为 Bean那 Spring 完全不知道它的存在自然也不会关闭它。正确的做法是把线程池定义为 BeanBean(destroyMethod shutdown) public ExecutorService taskExecutor() { return Executors.newFixedThreadPool(10); }destroyMethod shutdown是关键它让 Spring 容器在销毁 Bean 时调用线程池的shutdown()方法线程池里的任务处理线程会收到中断信号。如果你用的是ThreadPoolTaskExecutor那它会自动实现DisposableBean不需要额外配置。另一个坑是自定义线程的thread.setDaemon(true)用得不好也会导致问题。监控数据采集线程如果设置为守护线程JVM 可能不等待它执行清理逻辑导致最后几个数据点没入库。但如果设置成非守护线程又在关闭时忘记关闭那 JVM 就挂住。我的建议是采集线程尽量交给框架管理自己new Thread的同时要注册一个关闭钩子把线程interrupt()掉。排查进程不退出的方法很简单拿到 PID 后执行jstack PID查找 RUNNABLE 状态的线程重点看ThreadPoolExecutor下的 worker 线程。如果看到类似pool-3-thread-1卡在awaitTask说明线程池没有收到shutdown()或者shutdownNow()的中断没有被正确处理。4.3 Spring Boot 版本差异对关闭行为的影响Spring Boot 版本默认关闭行为可配置优雅关闭2.2及以下不等待在途请求直接销毁 Bean不支持2.3立即关闭需配置server.shutdowngraceful支持2.6支持spring.main.lazy-initialization特性但关闭行为不变支持3.x默认依然是 immediate但部分 WebServer 实现默认优雅关闭支持如果你还在用 2.1.x我建议认真考虑升级。不只是因为优雅关闭功能还因为 Spring Boot 2.2 之后才有spring.lifecycle.timeout-per-shutdown-phase。从 2.3 开始优雅关闭的 API 才稳定。Spring Boot 3.x 的最终表现我测试下来和 2.7 差别不大主要多了虚拟线程的调整空间。4.4 Kubernetes 场景下的优雅终止K8s 里终止 Pod 的流程是先发 SIGTERM然后再等terminationGracePeriodSeconds默认 30 秒超时后强制 SIGKILL。Spring Boot 应用要在这个流程里优雅退出需要注意两个时间Spring Boot 优雅关闭的完成时间terminationGracePeriodSeconds如果你的 Spring Boot 配置是 30 秒K8s 的终止宽限期也是 30 秒那很危险。K8s 从发送 SIGTERM 开始计算时间不假但发送 SIGTERM 之前还有一个preStop钩子执行期。如果preStop里睡眠了 5 秒那留给 Spring Boot 的只有 25 秒超时就被强杀。所以terminationGracePeriodSeconds必须大于 Spring Boot 优雅关闭时间我一般加 15 秒缓冲。一个常见的preStop写法lifecycle: preStop: exec: command: - /bin/sh - -c - sleep 5这段代码的目的是给请求从负载均衡器上摘除留时间避免新流量在优雅关闭期间还打到这个 Pod。但要注意如果你开启了 Spring Boot Actuator 的shutdown端点也可以在这里先调它再 sleep。不过有些团队直接把preStop设置为调用 Kubernetes API 去 remove endpoint我建议你按团队运维能力来选择不要为了优雅而优雅调不好反而延长下线时间。5. 实操建议与调试技巧5.1 关闭日志和监控想要真正看清关闭过程发生了什么单靠INFO日志是不够的。我们当时做了一次全链路压测下的优雅关闭演练用jstack和jstat采集了关闭瞬间的线程状态、堆内存变化还开启了 Spring Boot 的TRACE日志logging.level.org.springframework.bootTRACE logging.level.org.springframework.context.supportTRACETRACE 级别下你可以看到DefaultLifecycleProcessor对每个 Bean 的stop()调用记录能直观地看到哪个 Bean 耗了多少时间。实测中我发现有个数据清洗模块的PreDestroy要跑差不多 12 秒原因是在循环里逐条删除数据后来改成批量删除后降到 2 秒。推荐大家把下面的日志加上关闭时重点关注o.s.b.w.e.tomcat.GracefulShutdown : Commencing graceful shutdown. Waiting for active requests to complete o.s.b.l.DirectoryBasedJarFile : Stopping service [Tomcat] o.s.c.s.DefaultLifecycleProcessor : Stopping bean dataSource看到Commencing graceful shutdown说明优雅关闭真的进入了等待阶段。如果关闭日志里没有这行说明你没有配置成功或者 Tomcat 容器根本没被 Spring Boot 接管比如你用了TomcatServletWebServerFactory做了特殊定制。5.2 退出码和等待机制我记得有一次做发布系统改动发现服务停止以后退出码不是 0导致发布失败提示进程异常。后来查了 JVM 的退出码返回规则如果SpringApplication.run()返回的 context 被普通close()关闭它不会主动调用System.exit()退出码可能是 143表示被 SIGTERM 终止。如果你的发布脚本拿退出码做判断要注意这个坑。更稳的机制是使用SpringApplication.shutdown()或者自己注册 JVM hook 来等待异步资源释放。比如有一段CountDownLatch等待所有缓存刷新完毕再退出Component public class CacheFlushHook { private final CountDownLatch latch new CountDownLatch(1); PreDestroy public void waitForFlush() throws InterruptedException { if (!latch.await(5, TimeUnit.SECONDS)) { throw new IllegalStateException(缓存刷新超时); } } public void markFlushed() { latch.countDown(); } }不建议在关闭逻辑里使用Thread.sleep()来等待如果你需要等待某个异步操作完成用CountDownLatch、CompletableFuture.get(timeout)等带超时机制的组件。否则关闭线程卡死整个进程就永远停不下来了。5.3 关闭阶段的测试方法测试优雅关闭不只是启动服务然后 CtrlC 看日志。我整理了一套针对性的测试路径用curl -N发起一个持续 20 秒的请求。执行kill -15 PID触发优雅关闭。观察日志里请求是否成功完成新请求是否被拒绝。检查进程退出时间是否在配置的超时窗口内。如果你的服务有负载均衡器比如 Nginx在关闭阶段应该观察到该节点在 upstream 里被标记为 down。如果是 K8s 部署还可以在preStop阶段故意 sleep 几秒验证终止宽限期的整体配合。这里我建议把手动关闭演练加入上线检查清单。我们在一次演练里就发现很多服务可以优雅关闭 HTTP 请求但 MQ 消费者的线程池完全没停下来原因是没有给 RabbitMQ 的SimpleRabbitListenerContainerFactory设置autoStartupfalse。当你关闭 Spring Boot 服务时RabbitMQ listener container 不会自动停止除非你实现了SmartLifecycle并把它注册进去。这个坑在 Spring Boot 2.3 之后虽然有所改善但自定义的 listener container 还是需要单独处理。5.4 配置模板分享最后分享一个我目前项目里的配置模板适用于 Spring Boot 2.3 部署在 K8s 的场景server.shutdowngraceful spring.lifecycle.timeout-per-shutdown-phase25s management.endpoint.shutdown.enabledfalse management.endpoints.web.exposure.includehealth如果确实需要 HTTP 触发关闭比如你的上线流程不方便发 SIGTERM我建议单独开一个server.port或management.server.port的管理端口避免生产流量占用同一连接器。同时把management.endpoint.shutdown.enabledtrue加上认证不然任何人 POST 一下/actuator/shutdown服务就下线了。关于 K8s YAML 里对应的配置spec: terminationGracePeriodSeconds: 45 containers: - name: app lifecycle: preStop: exec: command: [/bin/sh, -c, sleep 10]这个组合的效果是Pod 下线时先等 10 秒让流量摘干净然后 SIGTERM 触发 Spring Boot 优雅关闭Spring Boot 最多等 25 秒最终整体在 35 秒内完成45 秒的宽限够用。6. 我在实际项目里踩过的几个坑其实这个主题能讲的还有很多但更值钱的是那些只有跑过生产才知道的细节。我想再啰嗦几句帮大家少走弯路。第一不要在关闭逻辑里访问外部服务。分布式环境下关闭期间依赖的网络服务可能已经不可用了你的PreDestroy如果还去调 Redis 或者 Apollo 配置中心大概率会超时抛异常异常又可能导致后续销毁流程中断。关闭逻辑应该严格遵守只清理本地资源的原则比如关闭文件句柄、释放线程池、刷写日志缓冲这些不依赖网络。第二注意 Spring Cloud 组件的关闭连带效应。如果你用了 Spring Cloud Gateway关闭时它会尝试从注册中心取消注册这个操作用户是感知不到的但如果你在PreDestroy里手动调用了DiscoveryClient.getInstances()那可能因为客户端已经停止而出现空指针。最好的做法是让 Spring Cloud 自身的生命周期处理器管理注册中心状态别的业务代码只处理内部资源。第三留出强制关闭的后路。即使你配置了优雅关闭我还是建议在运维脚本里留一个兜底逻辑比如关闭流程最多等待 60 秒之后如果进程还在就发送kill -9。当然这会留下一些未清理的资源但总比发布时吊死一个进程强得多。兜底逻辑要清楚地记录在文档里让值班的人知道这不是一个错误而是优雅关闭超时后的强制手段。第四关闭时的日志尽量不要用异步输出。如果你配置了 Logback 的 AsyncAppender关闭阶段日志事件不一定会完全刷盘因为异步队列可能还积压着之前的日志。在关闭阶段建议同时输出到同步 appender 或者关闭前强制执行LoggerContext.stop()。这个细节虽然不直接影响业务但排查线上问题时少了最后一段日志会非常难受。我自己现在写 Spring Boot 项目几乎每加一个 Bean 都会问一句话这个 Bean 在进程退出时需要做什么如果答案是不需要释放那我也会确保它不会意外持有非守护线程。很多服务卡住不退根本原因就是某个 Bean 悄悄地启动了一个线程池但从来没有关过它。希望这篇文章能帮你把 Spring Boot 应用的关闭过程从黑盒变成灰盒至少。下次再遇到进程杀不掉或者发布时数据丢失你可以先从这些维度排查一遍HTTP 在途请求有没有被等待线程池有没有被关闭连接池的释放顺序对不对注册中心有没有及时摘流量只要把这些点都跑通了线上发布时的安全感会提升一个档次。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

MarkItDown: 把 Office、PDF、图片一口气转成 Markdown——Windows 直接跑 + 四款同类工具横评 2026/10/1 18:35:51

MarkItDown: 把 Office、PDF、图片一口气转成 Markdown——Windows 直接跑 + 四款同类工具横评

一个 Python 库覆盖 14 种格式,专为喂给大模型而生的轻量转换器。 手头一堆 PDF 论文、Word 报告、Excel、PPT,外加截图和录音,想一次性喂给 LLM 做 RAG 或问答——市面上的工具要么只支持单一格式,要么装一堆依赖报红字&#xff…

阅读更多 →
【leetcode】(八)暴力递归 2026/10/1 18:35:51

【leetcode】(八)暴力递归

(一)暴力递归暴力递归就是尝试1,把问题转化为规模缩小了的同类问题的子问题 2,有明确的不需要继续进行递归的条件(base case) 3,有当得到了子问题的结果之后的决策过程 4,不记录每一…

阅读更多 →
/health 和 /health/ready 的分工:探针接进告警之前该知道什么 2026/10/1 18:35:51

/health 和 /health/ready 的分工:探针接进告警之前该知道什么

Kubernetes 的 liveness 和 readiness 配错了,后果远不止"少了一个健康检查"这么简单:Pod 可能被反复重启,或者流量被发给一个根本没在服务的实例。RustFS 把这两个概念拆成了两个端点,分别对应文档里说的存活性和就绪性…

阅读更多 →
SolidWorks许可降本增效:不增购,也能让现有 许可发挥更大价值 2026/10/1 18:35:44

SolidWorks许可降本增效:不增购,也能让现有 许可发挥更大价值

一、SolidWorks许可模式 SolidWorks是达索系统旗下核心的三维CAD软件,广泛应用于机械设计、模具制造、汽车零部件、电子机电等领域。凭借操作友好、功能全面、性价比高等优势,SolidWorks已成为国内中小制造企业广泛采用的主流三维CAD软件之一。 SolidWor…

阅读更多 →
回迁社区配套隔墙工程复盘:漯河朱王庄社区(召陵区珠江路 22 号)狭小场地 + 潮湿储物间的选材与施工管控* 2026/10/1 18:35:44

回迁社区配套隔墙工程复盘:漯河朱王庄社区(召陵区珠江路 22 号)狭小场地 + 潮湿储物间的选材与施工管控*

摘要:本文记录漯河朱王庄回迁社区配套隔墙工程,项目地点召陵区珠江路 22 号,实施单位漯河市庆林建材商贸有限公司。项目难点:小区通行受限需二次转运,储物间通风差湿度偏高,同时要兼顾已入住社区文明施工。…

阅读更多 →
Hindsight:打造实时日志流分析系统的架构与实践 2026/10/1 18:35:44

Hindsight:打造实时日志流分析系统的架构与实践

做日志分析这行当久了,你会听到一个有点反直觉的词汇:hindsight。英文里它叫"后见之明",俚语常说 hindsight is 20/20——事情发生后,一切都看得清清楚楚。可在一个做基础设施的工程师眼里,这个词还有另一层…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉