MoreRSS

site iconSunZhongWei | 孙仲维 修改

博客名「大象笔记」,全干程序员一名,曾在金山,DNSPod,腾讯云,常驻烟台。
请复制 RSS 到你的阅读器,或快速订阅到 :

Inoreader Feedly Follow Feedbin Local Reader

SunZhongWei | 孙仲维 的 RSS 预览

Spring Boot (RuoYi) Graceful Shutdown

2026-11-10 20:32:48

用 RuoYi (Spring Boot) 开发了一套访客管理系统,由于要频繁的更新部署,我担心重启会影响到正在处理的请求。所以查了一下 Spring Boot 是否支持 Graceful Shutdown。因为 Spring Boot 这种非常成熟的框架,不能没有这种机制的,所以问题就变成了,如何配置来启用 Graceful Shutdown.

Spring Boot 版本

这个 RuoYi 版本中的 Spring Boot 版本为 2.5.15。 Spring Boot 从 2.3.0 起就已引入

# application.yml
server:
  shutdown: graceful # 开启优雅停机,默认为 immediate

spring:
  lifecycle:
    timeout-per-shutdown-phase: 30s # 设置等待在途请求完成的最大超时时间,默认30秒

具体说明:

  • server.shutdown: graceful —— Spring Boot 2.3.0 引入(2.3 之前只有 immediate 一种行为,配了也不认)
  • spring.lifecycle.timeout-per-shutdown-phase —— 同版本引入,Duration 类型,默认就是 30s

Tomcat 9.0.106 的 NIO/NIO2/APR 连接器都支持 pause() 优雅停机(Tomcat 侧需要 9.0.33+),没有问题。应用用的是内嵌 Tomcat(spring-boot-starter-web),正好是这套配置支持的容器类型。

两个属性的实际语义

配置 作用
server.shutdown: immediate(默认) JVM 收到 SIGTERM 直接销毁上下文,在途请求被硬切
server.shutdown: graceful 先暂停 Tomcat 连接器(不再接新连接,新请求返回 503),等在途请求跑完再关上下文
spring.lifecycle.timeout-per-shutdown-phase 同一个值同时用于:① Web 服务器等待在途请求的上限;② DefaultLifecycleProcessor 每个停机 phase 的超时。超时后会打 warn 并强行继续往下走

所以不必去 Tomcat 里另找“grace period”属性 —— Spring Boot 就是复用这个 lifecycle 超时作为 Web 容器的等待上限。

怎么验证生效

重启时看日志,正常会出现类似:

o.s.b.w.e.tomcat.GracefulShutdown : Commencing graceful shutdown. Waiting for active requests to complete
o.s.b.w.e.tomcat.GracefulShutdown : Graceful shutdown complete

实测方式:起一个慢接口(sleep 10s),请求发出后立刻 kill(SIGTERM,不要 -9)进程,观察该请求是否返回正常响应、日志是否等到请求结束后才 Graceful shutdown complete。

如果当前没有线程在处理请求,是否也要等 30 秒才能完成停止进程

不会。30s 是「最长等待上限」,不是「固定等 20 秒」

timeout-per-shutdown-phase 的语义是 deadline,不是 sleep。空闲时它会在毫秒级结束。

它的实际工作机制

Spring Boot 的 GracefulShutdown(org.springframework.boot.web.embedded.tomcat.GracefulShutdown)停机过程是:

  1. 先关闸:关闭 Connector 的接收,不再接受新连接/新请求(此时新请求被拒绝)。
  2. 然后轮询:循环检查当前 ServletContext 的活跃请求计数,轮询间隔约 50ms。
  3. 归零即走:计数一旦为 0,立刻跳出循环,打印 Graceful shutdown complete,继续往下做容器销毁。
  4. 超时才是保底:把 30s 通过 Connector#setStopTimeout 交给它,只有”等满 30s 还有请求没跑完”这种情况,才会强制中断那些请求。

所以没有线程在处理请求时,它压根不进等待循环,第一个轮询周期就判定空闲走了。

空闲停机的真实耗时构成

阶段 耗时
pause + 活跃计数检查 ~0 ms(≤ 1 个轮询周期)
Context 销毁:Quartz shutdown、Druid 连接池 close、Lettuce close、ShutdownManager 等异步池(空闲立即返回) 通常 0.x ~ 2~3 s
合计 一般 1~3 秒,与 30s 无关

日志上表现为 Commencing graceful shutdown... 和 Graceful shutdown complete 两行时间戳几乎相同。

一个常见的误会:空闲 keep-alive 连接不会被等

浏览器 / 微信 webview 持有的长连接不算”活跃请求”,计数只统计正在被 Servlet 处理的请求。所以不会因为有几十个空闲长连接就多等——Tomcat 关 Connector 时会把它们直接关掉。

MES 系统的工艺路线与 BOM

2026-11-08 12:55:18

经常在 MES 中看到 BOM 和工艺路线。但是一直不清楚具体的差异是什么?而且好多教程里也没有解释清楚。
一句话概括:BOM 管“用什么料”,工艺路线管“怎么加工”。即,BOM 是产品结构数据,回答“用什么装”;工艺路线是生产过程数据,回答“怎么装、在哪装、装多久”。

什么是 BOM

BOM 是 Bill of Materials 的缩写,中文通常叫 物料清单 或 物料明细表。

它用来描述一个产品由哪些物料组成、各物料的数量/层级关系等,是生产排程、领料、投料、追溯和成本核算的重要基础数据。这里以最简单的一只中性笔为例子:

1 支中性笔 = 1 支笔芯 + 1 个笔杆 + 1 个笔帽 + 1 个弹簧 + 1 个包装袋。

如果 MES 要生产 1000 支中性笔,按这个 BOM 展开就是:

  • 笔芯 1000 支
  • 笔杆 1000 个
  • 笔帽 1000 个
  • 弹簧 1000 个
  • 包装袋 1000 个

MES 可以用它做:工单展开、齐套检查、领料发料、装配防错、批次追溯。

复杂一点的 BOM,例如笔记本电脑,一个主板还会包含两个内存条,一个 CPU 等,存在上下级关系。

什么是工艺路线

工艺路线的英文是 Routing。工艺路线在 MES 里回答三个问题:这个产品要经过哪几道工序,每道工序在哪个工作中心完成,每道工序的标准工时是多少。

Routing(工艺路线)是产品级的,只描述“经过哪些工序”。 它的结构是“物料 → 工艺路线 → 工序”,不包含具体设备、参数、资源细节。它回答的问题是:“这类产品应该做哪些事情。” 排程系统和订单工艺路径生成主要依赖这一层。

工艺路线梳理中最难的取舍是颗粒度。太细,每道工序都要报工,工人嫌麻烦,数据质量必然下降;太粗,出问题时无法定位,追溯链会断。实用的判断依据是:有质量风险的工序单独列(焊接、热处理、压装等),不同设备或不同工作中心的工序分开(直接决定排程和产能计算),同一台设备连续完成、无质量风险的工序可以合并。

需要注意,工艺路线的管理并非集中在单一系统里,它通常由 PLM(产品生命周期管理)系统负责“源头设计”,然后同步分发到ERP和MES系统。

BOM 与工艺路线的交集

BOM 和工艺路线分开管理,不意味着它们互不相干。恰恰相反,它们必须在执行层通过一个明确的关联点连起来:某一行 BOM 物料,是在哪一道工序被消耗的。

如果没有这个关联,系统会默认所有物料都在第一道工序前齐套。结果就是:仓库提前把大量物料拉到车间,堆在本来就拥挤的现场,而真正到某道工序才需要的物料反而被提前“消耗”掉了账面数量。

全球各国股市总市值排行榜

2026-11-07 10:17:24

可能人到中年对什么都提不起兴趣了,又开始炒股了。没想到买入的银行和电信,家电都表现良好,比业余折腾省心多了。但是逛雪球,和短视频,我发现大家都在骂 A 股市场,我总觉得是这没有什么逻辑,明明是买的垃圾股,纯靠赌运气,暴涨暴跌不是很正常么?买固定收益类的分红股不香么。而另一个疑问是,到底 A 股总市值是个什么概念,于是我查了一下全球各国股市总市值:

截至2026年,全球股市总市值高度集中,美国以绝对优势占据近半壁江山,前十大市场拿走了全球绝大部分份额。不同统计时点的数据略有浮动,以下基于彭博社2026年4月的数据,列出全球主要股市的市值排名。

全球股市总市值 TOP 10(2026年4月数据)

  1. 美国:约 75.04万亿美元(纽交所+纳斯达克),超过第2至第10名总和。
  2. 中国大陆:约 14.84万亿美元(沪市+深市)。
  3. 日本:约 8.19万亿美元(东京证券交易所)。
  4. 中国香港:约 7.41万亿美元(港交所)。
  5. 印度:约 4.97万亿美元(孟买/国家证券交易所)。
  6. 加拿大:约 4.49万亿美元(多伦多证券交易所)。
  7. 中国台湾:约 4.48万亿美元(台湾证券交易所)。
  8. 韩国:约 4.04万亿美元(韩国交易所)。
  9. 英国:约 3.99万亿美元(伦敦证券交易所)。
  10. 法国:约 3.45万亿美元(泛欧交易所巴黎)。

关键趋势与结构性变化

  • AI重塑排名:台湾和韩国凭借台积电、三星、SK海力士等半导体巨头,市值快速攀升并超越英国等老牌金融中心,反映出全球资本正加速向AI硬件与芯片制造集中。
  • 中国的体量:若将中国大陆(14.84万亿)、中国香港(7.41万亿)与中国台湾(4.48万亿)合并计算,中国整体股市规模合计约26.73万亿美元,稳居全球第二极,但与美国的差距依然显著。
  • 数据口径差异:部分来源将“欧盟”作为一个整体统计(2026年10月约15.5万亿美元),其体量与单独列示的中国大陆市场接近;同时,10月数据中印度市值一度升至10.6万亿美元,显示新兴市场的市值在年内存在较大波动。

全球股市的头部格局长期由美国主导,但内部排名正被AI产业链和区域金融中心的兴衰持续改写。

golang 改造 Magento 外贸站之产品详情页长链接的支持

2026-11-05 20:08:55

Magento 中的同一个产品详情页链接支持多种 URL 格式,例如:

  1. /some-sku.html
  2. /category-a/category-b/some-sku.html

但是我用 golang 重新实现的版本,只支持第一种格式。在需要从旧外贸站迁移到 golang 实现的站点时,就会丢失第二种链接格式的支持,导致 404 错误,破坏之前积累的搜索引擎收录的积累。

开始我感觉不太好支持,但是第二天早上在厕所嘘嘘时,突然想到了一个解决方案。。。

golang 中如果找不到 sku,则拆分出最后一部分,再查询一次,即可解决。即,即在查询不到时,取 / 分割的最后一部分,提取出 sku 再查询一次。为什么这么简单的解决方式,昨天晚上没有想到。看来睡眠也是思考过程。

SEO 效果

两种地址都能被访问,但对外只有一个规范地址;长地址 200 打开并声明 canonical 指向短地址,权重合并到短地址,无重复内容风险。而 Magento 的实现则是反的,canonical 指向长地址。

MES 系统的库位管理,物料库位、成品库位、线边库

2026-11-01 15:47:09

最近在开发 MES 系统的过程中,发现对一些 MES 的基础概念还是不太了解。所以买了一本书翻了翻,还是有不少收获。虽然,书是大学的那种毫无实战经验的理论书籍,但是对我这种新手来说,还是能学到不少东西。这里整理一下库位管理相关的概念。

什么是库位

库位,即物料或者生产的成品存在在仓库中的位置。

库位的英文

  • Location:最通用,MES/WMS 中常直接用
  • Storage Location:较正式,强调仓储库位

如果是 MES 界面字段,通常用 Location 最简洁;如果是仓储管理语境,用 Storage Location 更准确。

库位的类型

  • 物料库库位
  • 成品库库位。但是,很多场景下,成品库管理会从 MES 中独立出来,放到 WMS (Warehouse Management System,仓储管理系统)中管理。

库位信息

需要管理 & 展示的信息:

  • 库位编号。最好能直观的对应到库位位置
  • 库位状态。是否停用
  • 库位位置。精确到柜架层数,例如,C区-10道-8柜架-5层
  • 库位说明。例如,存放着什么物料

线边库

英文为 Line-side Storage 或 Line-side Location。线边库,指在车间设置的一个物料的缓冲区,或者临时存储区。例如,物料从库房 -> 车间线边库 -> 车间工位。

当然,这个线边库并不是必须的,也可以直接从库房直接配送到工位。例如,通过物料传送带,或者 AGV (Automated Guided Vehicle,自动导引车)

线边库通常是使用手持设备进行操作。

国内 git push 到 github 的配置

2026-10-31 19:14:57

网络异常

国内通过 git push 到 github 时,会报错:

> git push github --all
fatal: unable to access 'https://github.com/xxx/yyy.git/': Failed to connect to github.com port 443 after 21164 ms: Timed out

虽然能在浏览器里访问 github,但是命令行里却会网络超时。

git 全局配置

git config –global http.https://github.com.proxy socks5://127.0.0.1:4455

这样配置,有个好处,就是只对 github.com 采用这个配置,对于其他 git 仓库不会有影响。

Windows 的 git 配置在哪里

> cat C:\Users\zhong\.gitconfig
[user]
        name = Zhongwei Sun
        email = [email protected]
[credential]
        helper = manager
[http "https://github.com"]
        proxy = socks5://127.0.0.1:4455

没想到 powershell 下也能使用 cat 和 ~/.