2026 W38-W41

临近国庆节,节奏有点乱。有四周没写周记了,W38 到 W41 合成一篇。这四周的主线还是 enx:给它取了个名字叫 Catglish,部署生产环境。最近在准备提交 Chrome Web Store,提交之前得再调整一轮 UI。 Catglish W37 里纠结的名字,最后用了 Catglish。网站和 Chrome 扩展上的名字都改成了 Catglish,仓库名还是 enx,等上线之前再找时间改。 W38 主要在调细节。跟 AI 一起重新做了一遍配色,统一了各个组件的颜色 token。在颜色这件事上,AI 比我专业多了。周五 Claude Code 赠送的 100 美元额度第二天就要过期,那两天开着 Opus 改了很多东西,也第一次往生产环境部署了一个版本。 W39 在补生产环境的链路。部署流水线从 GHCR 加 SSH 换成了 ECR 加 SSM,机器调整成 t3a.small。扩展的内容脚本改成按需注入,不再在每个页面上都注入。周五集中做了一次依赖版本升级:Next 16、Vite 8、TypeScript 6。E2E 测试改成用真实的登录流程跑。 W40 是国庆: 网站上加了 Beta 标记和 GitHub 链接 加了定价页;现在的配额都是内测阶段的数字,跑一段时间再定上线时各个等级的额度 除了按月订阅,也可以一次性付款购买 AI 积分 本地词典查不到的词,可以调用 AI 生成释义 收藏页面,以及按站点设置「在这个网站上自动开启」 另外加了 Prometheus 监控指标,homelab 和生产环境的监控面板都接上了。 W41 打好了 0.1.0 Beta 的扩展包,画了个 logo:一个带猫耳朵的 C。 ...

Created 9096-10-09 · Updated 9096-10-09 · 1 min · 173 words · -

2026 W37

这周主要在给 enx 取名字。另外 enx 接了 DeepSeek,HomeLab 的 CI/CD 加了缓存,在 YouTube 上新建了一个产品频道。 enx:取名字 enx 一直是开发代号,要做成产品发布,得有一个正式的名字。取名字是最不重要、也最纠结的一件事。 这一周一直在纠结叫什么。想了好多名字,一个个去查域名和商标,大部分都和现有的软件或者商标冲突:有的域名已经被人注册了,有的已经注册了商标,用了会有法律风险。 最后在仅有的几个不冲突的名字里来回纠结,周六选了一个,注册了域名。 enx:开发 新功能不多:Reader 页面,可以把一段英文粘贴进来阅读、查词;从浏览器扩展里发起登录,登录完会自动回到原来的页面。 另外还做了一些细节上的小调整和优化。 UI 和 API 的提示文案全部改成了英文。用这个工具的人本来就在学英文,UI 上简单的英文应该不是问题; MiniMax 的订阅过期了,DeepSeek 的账户里还有余额,所以给 enx 加了一个 DeepSeek 的 provider,HomeLab 上切到了 DeepSeek。HomeLab 是测试用的,对后端用哪个模型不是特别敏感。 HomeLab:CI/CD 提速 最近一直在测 enx,频繁调细节,也频繁往 HomeLab 上部署,CI/CD 跑的时间就成了一个比较明显的问题。 这周优化了一下:加了缓存,加了 Nexus 私有仓库。npm 和 Go 的依赖走 Nexus 代理,镜像构建的缓存也放在 Nexus 里,依赖没变的时候可以跳过安装依赖那一步。 YouTube:两个频道 打算拍一些东西放到 YouTube 上,比如 enx 的安装/使用演示, 宣传视频, 这周在准备拍摄方案,周六在自己的 YouTube 账号下新建了一个产品频道。 注册 YouTube 账号之后本来就会有一个默认的频道,每个注册用户都有,只是大多数人没有往里面发过视频。我的默认频道就当个人频道用。同一个账号下面还可以再新建别的频道,这一点我也是这周才知道的,算是一个新发现。 这样一个账号下面就有了两个频道。个人频道放我自己的内容,比如 HomeLab 的改造、有可能的未来的房车旅行,也许会有美食类的视频,主要是个人记录。产品频道只发产品相关的内容。个人频道是全集,跟 enx 相关的视频会同时发到两个频道。 ...

Created 14146-09-14 · Updated 14146-09-14 · 1 min · 90 words · -

2026 W36

enx:认证从 Cognito 换成了 Clerk,单词高亮换成了浏览器原生的 Highlight API。 enx:认证从 Cognito 换到 Clerk 当初选 Cognito 的原因是,那会儿在聊一个职位,对方公司用 Java 技术栈,也用 AWS。我想让自己更熟悉 AWS 和 Java 一些,所以 enx 选型的时候选了 Cognito,还给 enx 加了一个 Java 后端。 那个职位后来没有 Offer,见 W33。 这周把认证换成了 Clerk。换的原因是 Clerk 和 Google 登录集成得更好一些,另外它同时支持 Google 和 GitHub 两种登录。网页端和扩展的会话也能同步。两端手写的 OAuth 客户端一起下线,Cognito 那套基础设施也删掉了。 enx:单词高亮换成浏览器原生的 Highlight API 有天晚上碰到思科的前同事 Roc,聊了一会儿,发现自己的前端知识实在太匮乏了。页面上点一下要查的词,其实可以用鼠标的坐标反查到点中的是哪个词,不需要像之前那样预先改 DOM、把所有词都拆开包起来,也不用挂那么多 onClick。 以前的做法就是把匹配到的单词用元素包起来,再给这个元素加样式。这样会改动页面的 DOM,在结构复杂或者会自己重绘的页面上容易出问题。 这周换成了 CSS Custom Highlight API:高亮范围用 Range 描述,交给浏览器渲染,不再往页面里插元素。点击查词改成在容器上做事件委托,用 caretPositionFromPoint 定位点到的是哪个词。 顺带把两件事拆开了:「阅读时高亮生词」和「点击查词」现在是两个独立的开关,可以只启用其中一个。X 上切换推文时正文是原地替换的,加了自动重建。Playwright 的用例按新的实现重写了一遍。 周六:大黑石 周六老婆公司团建,在大黑石的海边烧烤,她带着女儿去了。女儿下午有英语课,我中午开车去大黑石的沙滩接她们。 据说,小朋友到了沙滩就想去海边,饭都不吃了。一开始还在岸边挖沙子,后来看妈妈下水游泳,她也要下水。下水之后就不想走了,用老婆的话说是 “血脉觉醒”。 上次带她去海边是在广鹿岛,那时候她还只是在浅水里捡海星和贝壳。 路边为啥要栽这么多树… 开车去大黑石的路上,偶尔过桥的时候能看到远处的山,景色还不错。其余大部分时间视线都被路两边的树挡着,开多久,窗外都是一样的树。 ...

Created 7076-09-07 · Updated 7076-09-07 · 1 min · 82 words · -

2026 W35

这周主要是 enx 的开发:接入 Stripe,以及上线前的一些细节调整。 enx:接入 Stripe 订阅加积分这套方案是上周那份规划里定下来的,这周把它落进代码。 周三一天,enx 里多出了一整套计费:积分账本、Stripe 的 webhook、配额、结账和账单管理入口,网页端加了定价页和账单页,扩展这边加了积分不足和需要升级的提示。方案之前讨论过,这次是把方案细化,然后由 AI 生成代码。 同一批改动里还补了一组单元测试,账本、webhook、配额、结账处理各有一份。补测试的原因是接入 Stripe 之后要开始新一轮测试,而现有代码的单元测试覆盖太小,先把底子补上。 接下来是测试。 订阅之外加了一次性充值包 周四改了一次访问规则。 前一天定的是:AI 翻译必须有订阅才能用,不能靠单独充值绕过。第二天推翻了,改成账户里有积分就能用,不限来源,订阅发放的积分和一次性购买的积分包都算。 改的原因是有了一个新想法,可以开放一次性购买的充值包。按月订阅并不是所有人都愿意,月费也不好定太高,一次性的充值包是个补充。 代价是前一天已经写进代码的那条校验现在是错的,得删掉。项目还在开发中,随时都会有变化,这些变化都是正常的。 内网域名换成 wiloon.lab wiloon.com 是公网域名,homelab 内部之前也用它,只是在内网解析。但 DNS 分流上遇到了问题,所以内网改用 wiloon.lab,专门给 homelab 用。 这周把 enx 的内网访问切了过去。 公司账本:把方法固化成一个仓库 上周写过决定自己记账,用 beancount,AI 出数、人工复核。这周把它做成了一个仓库。 促成这件事的还有几点。找代账公司有沟通成本;在 twitter 上看到有人用 AI 处理公司的账目,我也想试试;另外公司现在没有业务,都是零申报,应该不复杂。有代账公司打电话过来,我跟他们说的也是自己先试试,实在不行再找专业人士。 仓库里放的是科目表模板、余额断言、季度增值税和年终结账两份 SOP,以及法定报表的字段映射。另外把几个常用动作做成了 Claude Code 的 skill:开票申请、季度报税、出报表、报税准备。 上周是决定自己记账,这周是把记账做成一套可以重复执行的流程。 homelab 杂项 kubectl 的 logs 和 exec 一度用不了,加了一个 ClusterRoleBinding 修回来,交给 ArgoCD 管理。 路由器那边把 IPv6 的 WAN 口改成了静态接口,之前记录过的前缀委派丢失问题走到了这一步。 监控补了一批采集配置。 blog 这周写了三篇:mktemp、DuckDB,以及微信扫码查看与下载 PDF。另外给 SQLite 那篇做了修订。 ...

Created 30306-08-30 · Updated 30306-08-30 · 1 min · 83 words · -

2026 W34

这一周几乎没碰键盘。带娃在老家待了五天,只有她午睡和晚上睡了之后,才有一点时间做自己的事。 从鞍山到老四平 上周从大连出发,在鞍山住了一晚,周一走下半程。 去程走的是国道,这天改走高速。四岁的娃也感觉出来国道太慢了,是她要求走高速的,条件是全程系安全带,她答应了。 到老四平已经是下午,太阳落了山。她还是要去菜园子,非开着手电筒去摘菜。 奶奶家在一个小镇上,房子前后都有菜园子,房子后面是一条铁路,经常有火车轰隆隆地开过去。从小在城市里长大的娃,对这里的一切都新奇。 周二天一亮她又冲进菜园子,拉着奶奶东看西看,摘各种蔬菜,收获满满。 小公园 周三去了老家附近的一个小公园。 爷爷奶奶本来打算当个景点看一眼就回家,中午外面太热。没想到娃对什么都新奇,跟小树小草玩起来就不肯走了。有荷花池,有草地,有树林。 亲戚家的动物 周四去亲戚家看小动物。 老姨家养了羊,还有鸡、鹅和鸽子。娃见了鸽子,就掏出车上的玉米去喂。家里养的鸽子和城市里的广场鸽不一样,星海公园的鸽子只要见了玉米就成群结队地下来吃,家里的鸽子完全没有这个概念。据说每天下午五点才是它们觅食的时间。 又去了二舅家,二舅妈刚卖菜回来。他们也有菜园子,平时吃不掉的菜拿到市场上卖。暖棚里有葡萄,也有各种菜。临走时二舅从鸡窝里掏了一些鸡蛋,给我们带上。 娃拿到鸡蛋,第一个问题是:这个鸡蛋能孵小鸡吗? 我们解释了好一会儿,得有鸡爸爸和鸡妈妈,蛋才能孵出小鸡。她大概是因为亲眼看见鸡蛋是从鸡窝里掏出来的,才会觉得它能孵小鸡。平时从市场买回来的鸡蛋,看不到母鸡的影子,也就不会有这样的联想。 早上跑步 我每天早上跑步。老家在内陆,中午三十几度,早晚凉快,跑步只能放在早上。 小镇上很少有人把跑步当成锻炼。老年人有打太极的,有做操的,有跳广场舞的,跑步的很少。所以 Keep 的地图上,老四平一条跑步路线都没有。上次回来我开发了一条 2 公里的,这次又开发了一条 4 公里的。路上车不多,早上跑起来很舒服。 不方便的是跑完一身汗,洗澡不方便。家里没有独立的卫生间,厕所是旱厕,只能用湿毛巾擦一擦。 回大连 周五开车带娃和奶奶一起回大连。 在大连是姥姥姥爷和爷爷奶奶轮班过来帮忙带娃,这次刚好赶上换班的周期,带娃回老家,顺便把奶奶接过来。 她自己编的一个故事 周六上完英语课,我们坐在外面的长凳上休息,娃自己编了一个故事。 有一只小象,在大森林里走着走着,遇到一张蜘蛛网。网上有两只蜘蛛,一只蜘蛛国王,一只蜘蛛王后。蜘蛛王后会变成老奶奶的模样,骗小象进蜘蛛网,没有成功。后来小象打败了蜘蛛国王和蜘蛛王后,把它们装进了垃圾袋。 正讲到这里,飞过来一只麻雀,落在附近的地上。她接着说:后来来了一只鸟,把垃圾袋叼走了,用嘴啄那个蜘蛛国王和王后。 这个故事的来源能对上。上周回老四平,路上无聊的时候给她讲过孙悟空三打白骨精,白骨精先变成一个姑娘,再变成老奶奶,最后变成老爷爷。另外最近买了 Switch 2 上的《世界游戏大全 51》,和她玩过里面的国际象棋,国际象棋有国王和王后。她把三打白骨精的情节、国际象棋的棋子,还有当时飞过来的那只鸟,编进了同一个故事。 我帮她把这个故事做成了连环画,下次再找时间生成一个动画片。 还是要多带她去看不同的东西,接触各种各样的事物。她会把见过的、经历过的重新排列组合,变成自己的认知。 项目 这周项目上基本没有进展,只有她午睡和晚上睡了之后才有一点点时间。 在老家这几天不碰键盘,倒是想清楚了一件事。enx 这个项目我断断续续做了很久,一直是自己在用。做了这么久,如果最后没有真正上线,我会有遗憾。所以暂时不找工作,接下来一段时间集中精力把它部署上线。 2026 W34,老四平 — 大连。

Created 30306-08-30 · Updated 30306-08-30 · 1 min · 48 words · -

2026 W33

面试结果 上周那场第二轮面试,周二有了结果:职位不匹配。 从 4 月离职到现在同事/朋友帮推过三家公司。一家给了 offer,薪资太低,拒了;一家没有下文;这一家前后聊了四个月,两个岗位都进了二面,都没有 offer. 这一家前后接触了一位 HR 和八位面试官。感觉得出来,有的是希望我加入的,也有的对我有疑虑。anyway,最终的结论是职位不匹配。 接下来先测试 enx 独立商业化的可行性:把功能做完、部署到 AWS、接上 Stripe 订阅,先在 YouTube 和 X 上推(因为只做了 google 账号登录),看能不能有几个付费订阅用户;跑不通的话就再找工作。 enx: 划词翻译 之前选中一个短语会走词典查询,而后端判定"包含空格就是句子",直接返回一句"句子翻译功能暂未开放",短语永远拿不到释义。现在改成:选中的如果是句子中间的几个词,侧边栏显示这个短语在整句里的含义。像 “hunt down emails”,三个词单看都认识,放进上下文里是什么意思才是要查的。 另外给三个翻译 provider 各补了单测。 enx:上线还差什么 周三花了一天,把 enx 距离上线还差哪些事情列了一遍,写成两份文档,一份是商业化设计,一份是任务清单。 先定义什么叫"上线":在生产环境上,真实用户可以注册、登录、订阅、使用 AI 翻译、被限流、退订,这条链路全部跑通,才谈得上开始推广。 顺序定成三步。先在现在这套 homelab 环境里把订阅功能做完、测通,不用等基础设施迁移——然后把跑通的功能迁到 AWS。最后在生产环境完整跑一遍端到端冒烟测试,作为发布门禁。 几条已经定下来的: 计算平台继续用 EC2,不上 ECS 或 EKS。EKS 控制面每月的固定成本,在验证付费意愿这个阶段不划算 上线时数据库继续用 SQLite,先不迁 PostgreSQL。现有链路已经跑过,上线门槛越低越好,数据库迁移不是订阅功能的前置依赖 域名不换。Cognito 的 callback、CORS、证书、扩展权限都已经围绕现在这个域名配好了 全部开源,包括计费规则,继续用 AGPL-3.0 最后一条想得比较久。最初担心闭源可以防止别人用 AI 抄产品,后来推翻了:闭源只能防直接复制代码,防不了照着功能用 AI 重写一遍,而后者才是真正的风险,源码可不可见对它基本无效。定价和免费额度这些数字,用户用一遍产品就能观察到,藏代码也藏不住。真正让我决定开源的是另一件事——找工作这条退路还在,一个有真实用户、有测试和 ADR 的开源项目本身就是求职作品集,这个价值闭源换不来,而闭源换来的那点"防护"本来就是假的。 局域网域名的一秒延迟 周五在准备 enx 的测试环境,发现局域网里的域名访问都带着一段很规律的延迟。查下来是 IPv6 的 DNS 问题。 ...

Created 16166-08-16 · Updated 16166-08-16 · 1 min · 176 words · -

2026 W32

广鹿岛:彩虹滩赶海 上周末坐船去了广鹿岛。 周一换了个海滩,去彩虹滩赶海。这次出来玩时间赶得不错,退潮都在傍晚 6 点左右,太阳快落山,正好是一天里凉快下来的时候。海滩很浅,可以往前走很远,靠岸这一段脚下都是细沙,沙滩上有很多海葵,寄居蟹更是数不过来。再往深处走,细沙变成礁石,海草也多起来,水到膝盖左右。 四岁的女儿一路捡,寄居蟹、螃蟹、各种贝壳,把整个桶底铺满了。后来我们在海草附近捡到一只海星,她立刻把桶里的螃蟹和寄居蟹全倒回海里,整个桶只装这一只海星。 海星带回了民宿。到晚上它大概是缺氧,开始往桶外爬。我们商量了一下,还是放回去吧,不然会死掉。于是又把海星送到离住处最近的海里。 赶海的时候一边拍照一边让 AI 识别,认识了海葵和鱿鱼的卵鞘。海葵挺有意思,拿铲子碰一下,它整个身体缩进沙子里,同时喷出一股海水。鱿鱼的卵鞘在滩上到处都是,半透明、软软的、圆圆的一团。 周三从广鹿岛回大连。在杏树港下船之后是我开车,女儿自己坐安全座椅,全程走国道没上高速——小朋友随时可能需要我,国道方便停车。过几周我要单独带她去爷爷奶奶家,这次算是一次 dry run。 enx:遮阳伞下的 side panel 周二在岛上找了家有泳池的酒店,女儿和妈妈在泳池里泡了一下午。我没带泳衣,就在遮阳伞下写码。 这周 enx 主要在开发句子翻译的 side panel。 后端给三个翻译 provider 都加上了「按句子上下文翻译单词」的能力,配了对应的 handler 和路由,每个 provider 补了单测。前端这边,侧边栏里点击单词后的展示从单行文字改成了卡片。 卡片这块反复改了几版。一开始词、音标、上下文含义、查询次数分四行堆着,太占纵向空间,改成一行内排列、放不下才折行;有道词典的外链也删掉了,侧边栏就这么宽;「Query Count」几个字重复出现太啰嗦,换成一个放大镜图标,原文字挪到 title 属性里做悬浮提示。 加载方式也调了。以前是词典查询和 AI 上下文翻译两个请求都回来才一起渲染,现在点击的时候就先插入一张骨架卡片,两个请求各自返回后只更新自己那部分。词典那边通常更快,音标和释义会先显示出来。列表按点击时间倒序排,重复点同一个词不再发请求,只把已有的卡片挪到最前面。 第二轮面试 周三从广鹿岛回来,在杏树港排队驶出停车场的时候接到了 HR 的电话。是第二轮面试的邀请,安排在周五下午,30 分钟,听起来会是全英文。 当天下午要带娃上课,距离面试还有一天多准备时间。上一次面试因为一直在看 Spring 的资料,没准备自我介绍,英文的自我介绍讲得不太好,这次得准备一下;剩下的主要是怎么用英语把简历上的经历说清楚。周四一整天和面试当天的白天,基本都在准备这些。 周五当天出了个小插曲。我之前很少用 zoom,16:20 就打开了,输会议号、输密码、调整摄像头和麦克风,然后等面试官上线。等到 16:27 还没看见人,才注意到窗口右下角有一个 join 按钮——原来我一直在会议外面 -_- 赶紧点了 join,发现两位面试官已经在线了。 面试过程还算顺利。我的英文不是特别好,中间有问题没听清楚就麻烦面试官再讲一遍,对方会很友好地放慢语速重复。有些问题答得还好,也有因为准备不够没能表达清楚的。面试官也问到了个人项目,我讲了 enx,说计划部署到 AWS 上,或许能帮到其他人。 快结束的时候我还纠结了一下,要不要解释一句我其实一直在会议外面等着。但这么复杂的句子,我的英文暂时还撑不住,就直接 say goodbye 了。

Created 9096-08-09 · Updated 9096-08-09 · 1 min · 62 words · -

2026 W30-W31

这两周的周记合成一篇。 enx:先把功能做完,上线再说 enx 是我自己的项目,一个查词加翻译的 Chrome 扩展。这两周它是主线。 前一周主要在部署链路上:调查词性能(SQLite 相关的调整、给 words 表加索引的 migration),构建时把 version 注入镜像,Go API、Java API 和 UI 三条镜像链路陆续跑通,部署到 homelab。 后一周是功能推进: 合入本地 ECDICT 词典,查词路径不再依赖外部接口 单词弹窗迁到 React + Shadow DOM,样式不会再被宿主页面污染 加了句子翻译的 Side Panel,翻译后端做成多 provider(MiniMax、Bedrock、Kimi),用 factory 加 handler 分派 修扩展的 session 超时问题,Cognito 那边改成手写刷新逻辑 周六在岛上想清楚一件事:微信登录先不做了。现在已经有 Google 登录,把 Stripe 接上就可以上线部署。把基本功能做完先上线,不需要等到完美。 一个朋友的文档校验工具 之前写过的、给一位朋友做的文档校验工具,这两周继续往前走。 前一周主要是仓库骨架落地:架构 ADR、几个模块的 Spec、测试,周末开始写 Web UI 的 SDD 和 lint 配置。后一周把它部署进了测试环境。 另外这个项目按正常的需求分析、报价流程走一遍。因为如果以后真的在线接单,报价是绕不开的问题,正好拿它测试一下。 starlabrys 官网 公司官网这两周加了历史项目展示页,还有一个 Site Advisor 的雏形,包括意图识别、知识库、tools 和对话几个部分。ew8 帮我改的那部分周五合并进来了。 w_dashboard:一个玩具级的仓库看板 周末起了个新项目 w_dashboard,Linux 端用 Rust 加 Slint,macOS 端用 Swift 加 SwiftUI,两端各写了一版初版。 ...

Created 2026-08-02 · Updated 2026-08-02 · 1 min · 130 words · -

Pricing Software Projects in the AI Era 人天报价为什么不够用了

最近在给一个需求做报价——一个多语言文档批量 QA 校验工具,需求分析花了好几轮问答才敲定范围,接下来要报价的时候,我在想一个问题:这活基本是 AI 辅助写完的,按传统的人天/人月去算,好像已经不太对了。 问题:人天为什么在 AI 辅助场景下失灵 人天报价能成立,前提是"1 人天 ≈ 一定量的产出"这个换算关系大致稳定。AI 辅助开发把这个关系打破了: 产出和投入的人天数脱钩。同样的功能,AI 辅助下可能几小时就写完测试都带上了,人天数骤降,但功能本身的价值(能不能用、值多少钱)并没有跟着降。继续按人天报价,要么报太低把自己的溢价空间搭进去,要么硬凑人天数撑报价,两边都别扭。 计时计费本身有激励错位。如果按小时/人天计费,乙方反而有动机把项目拖久一点——多算的工时里,有多少是"AI 生成代码但按人类费率计费",这跟"用 AI 提效"的初衷是反的。这个问题不是我一个人瞎想的,查了一圈资料,行业里已经在明确讨论这一点(见文末参考链接)。 顺带想到的:按 token 成本定价,行不行 报价的时候,我最初想的是一个"看起来很公平"的方案:按这次任务实际花的 token 成本 × 一个系数,再加上需求分析、架构、管理费这些固定项。想清楚之后放弃了,原因: token 成本和交付价值脱节。这次需求如果全靠 AI 辅助实现,token 花费可能就几十到一百多美元,但业务价值(省下的人工审校时间、给客户的报价空间)可能是这个数字的几十倍。按 token 成本定价会严重低估真正值钱的部分——需求澄清、边界判断、架构决策、验收测试,这些环节 token 消耗很少,但最耗专业判断。 和计时计费一样的激励错位。按 token 成本加成收费,等于鼓励自己多跑几轮、多重试、多探索——消耗越多赚得越多,这跟"用 AI 提高效率、把省下来的时间还给客户"的初衷正好相反。 不可审计、不稳定。token 单价随模型和厂商定价经常变,客户也很难验证实际花了多少 token,容易从"怎么定价"变成"信任问题"。 token 成本定价比较适用的场景,是那种极度机械、高重复量、判断空间很小的活(批量格式转换),成本约等于工作量。判断空间大的定制开发不属于这一类。 常见的软件项目报价模式 整理下来,常见的几种模式: | 模式 | 说明 | 适合场景 | |—————————–|————————————– –|————————–| | 固定价(Fixed price) | 范围定死后报一口价,风险在乙方 | 需求已经问清楚、边界明确的项目 | | 人天/人月(Time & Materials) | 按实际投入时间 × 日费率结算,风险在甲方 | 需求会持续演进、探索性强的项目 | | 里程碑付款 | 固定价拆成几个阶段验收付款 | 周期较长、双方都想控风险的项目 | | 价值定价(Value-based) | 按项目给客户带来的业务价值定价,不看成本 | 能算清 ROI 的项目 | | 结果导向(Outcome-based) | 只在结果达成时收费(比如按处理成功的记录数) | 高度可量化、重复度高的流程 | | 订阅/维护费 | 功能上线后按月收运维/迭代费 | 长期合作、持续迭代的项目 | ...

Created 29296-07-29 · Updated 29296-07-29 · 1 min · 206 words · -

2026 W29

从 HashMap 关联到的 上周说面试复盘整理了一部分,这周继续。blog 里 Java 相关的文档以前记得有些零散,重新整理一下。 HashMap 关联的东西其实挺多的… 先是解决哈希冲突主要的两条路:开链法和开放地址法。链表长到一定程度会转成红黑树,于是又去看了红黑树。哈希值怎么来的又牵出随机数——xorshift、LCG。再往下是 CPU 层面的事:加法/乘法/除法消耗的时钟周期不一样,缓存的空间局部性会直接影响这类数据结构的实际性能。横向看,Python 的 dict、Go 的 map 用的 Swiss Table,思路各不相同。 Swiss Table 这条又牵出 SIMD,还挺有意思的。1997 年的 Pentium MMX 就带了 MMX 指令集,不过只能做整数;AMD 1998 年 K6-2 上的 3DNow! 把单精度浮点加了进来;到 1999 年 Pentium III 的 SSE,才有了独立的 128 位寄存器。早年这套指令主要是拿来做多媒体和图形的。 而 Swiss Table 用 SIMD 一次比对一组控制字节来定位槽位,Go 的 map 后来换成了这个结构——中间隔了二十多年。一个 90 年代末为了跑多媒体加进来的特性,现在被用来加速哈希表的查找。 JVM 这边也一并整理了:HotSpot 的 GC 和 JIT。中间还跑偏去看了下 Linux 的进程调度。 starlabrys:把公司的壳先搭起来 和朋友聊天,有人找到了工作但不太理想,有人还在面试。我之前注册了营业执照,就在想我们是不是可以一起做点什么。 有人建议建一个 GitHub organization,这样想贡献代码的人可以加进来。公司暂时没业务,但有件事是现在就能做的——把官网建起来。 于是注册了域名 starlabrys.com,建了 GitHub org,把仓库和权限用 OpenTofu 管起来,后来又把这部分 IaC 从我自己的配置仓库拆出去,单独放进了 starlabrys-infra。 ...

Created 19196-07-19 · Updated 19196-07-19 · 1 min · 126 words · -

2026 W28

魔法线路的一次重建 我有三条魔法线路,这周状态都不太好:炸掉了一条,另外一条流量超了配额,还有一条延迟很大。索性新建了一条顶上。 配置新线路的过程中,顺带发现之前配的延迟检测不准,干脆一起修了。这一修就牵出一串:kube-prometheus-stack 里 additionalScrapeConfigs 字段名写错了;把 R 线路上的 X 从 split-updown 架构切回了普通方案,本想验证问题是不是出在这个架构上,结果发现并不是;J 线路也重新调了一遍,接进了 Grafana 监控。 本来只是想补一条线路,结果顺手把观测这块积了一阵子的旧账清了一遍。 重新拾起 QuantDinger 重新研究 QuantDinger,顺带整理自己的 enx 项目。 隔了一段时间没跟,上游已经升了很多个版本,还有一次大版本更新——MT5 整个模块被删掉了,看代码仓库,主线现在主要在更新数字货币和股票相关的模块。我跟着更新了指标(indicator)相关的一批代码。 也跑了一单测试,赚了 0.02866,差不多两毛钱——这也算是有正向现金流了 -_-。 面试复盘 上一次面试还没有后续 比起纠结结果,我更想把遇到的问题梳理清楚。已经整理了一部分,下周找时间继续,从 blog 里挖了一些相关的文档再整理一遍,下周接着弄。 女儿的一支舞,和被传染的一家 上周提到女儿在排练一支舞,这周演出了。 她上的是小班,周五这场是幼儿园大班的毕业典礼,小班出了几个小朋友排练了一支舞蹈,去典礼上表演。表演当天她的状态不错——一周前感冒过,到那天体温已经正常一两天,算是在恢复中,只剩一点点咳嗽,不影响跳舞,整支舞完整跳完了。 感冒倒是在家里转了一圈。她把病毒传给了妈妈,周六晚上老婆开始发烧。那天我全天带娃在外面上课、玩,回到家就成了半个病房。我目前还好,没有中招的迹象——但也不敢太乐观。 周日的三件不相干的小事 周日修了三件事,彼此没什么关联,凑巧都在这天: 蓝牙:偶然发现开机后蓝牙不能自动启用,是 Linux 启动过程中的时序问题,调了一下。 时区:为了能在这台机器上用 Claude Code,把时区问题处理了。 tekton-pipelines:把 PodSecurity 放宽到 baseline,是为了能在 homelab 上部署 enx 的 Java API。 两个小工具上的调整 Running page 换了数据源:Strava 的 API 改成了订阅模式,就把数据源换成了 Keep。 装了 Squirrel(鼠须管):macOS 自带的五笔输入法没有造词功能,换成了 Squirrel。

Created 12126-07-12 · Updated 12126-07-12 · 1 min · 66 words · -

2026 W27

女儿上幼儿园的情绪课 这周女儿在排练小班毕业表演,舞蹈动作有点难,加上分离焦虑,早上去幼儿园成了每天要过的一关。周一那天她抗拒得厉害,做了近一个小时心理建设才送进去,迟到了一小时。 我试着用她熟悉的东西帮她面对情绪。她在玩《星之卡比》,一开始连第一关的兔子都怕,现在已经把卡比的装备升到四级了。我就问她:现在还怕第一关的兔子吗?她说不怕了。我说幼儿园跳舞也一样,你手里的"冰淇淋"(舞蹈道具)现在是几级装备?她说是一级。我说今天带着它去跳舞,明天就升到二级,跳舞就没那么难了。她点点头,跟妈妈说了再见,蹦蹦跳跳去幼儿园"升级装备"了。 后面几天肉眼可见地在进步。周三到门口离开妈妈还会有点不开心,安抚一会儿就自己跑进去了。周四早上我在路上问她冰淇淋几级了,她说二级;我说今天再升一级,她纠正我:不对,上午能升一级,下午还能再升一级。大概她的神经网络已经把跳舞和打怪升级关联起来了。 比起替她扛下情绪,更想让她自己有面对情绪的办法。这套比喻能不能一直管用不好说,但这周是有效的。 周六全天带娃,出门时她的"小怪兽钱包"里有些现金。到星海广场,她自己花十块买了一袋海鸥食,又花三十坐了小火车,接着想玩旋转木马,翻钱包发现只剩十三块六了。她开始琢磨:游乐场都是收费三十吗?我说我们去找找十三块能玩哪个。绕了一圈,路过一个转飞船的场地,工作人员大姐答应十三块让她上去坐一圈。让她花自己的压岁钱,她就开始比较各种东西的价格了。 求职 周二收到了一家公司的面试邀请,周五去参加,过程还算顺利,有些问题答得还好,有些答得一般。目前结果未知。 咖啡:蒸气奶测试 某天中午送老婆去公司后,我又带电脑在她楼下的星巴克找了个座位。那天出门晚,担心喝咖啡影响睡眠,又不好久占座位,翻了半天菜单,看到一项叫"蒸气奶"。跟 AI 确认了一下,蒸气奶大致等于拿铁去掉咖啡。之前喝拿铁不会触发乳糖不耐,蒸气奶应该也安全。选项里有牛奶也有燕麦奶,我选了普通牛奶——顺便测试一下:蒸气乳化的过程据说能分解一部分乳糖,气泡也可能减缓乳糖进入肠道的速度。结果跟之前喝拿铁一样,喝完没有触发乳糖不耐的症状。

Created 5056-07-05 · Updated 8086-07-08 · 1 min · 12 words · -

2026 W26

enx 加 Java 后端 最近投了 Java 方向的职位,这段时间在回忆和熟悉 Java/Spring,也在整理 blog 里之前攒下的资料。但只看文档、不动手,理解很有限。过去做 Java 项目时训练过的"生物神经网络"痕迹应该还在,细节被修剪掉了,主要的连接还在,得花点时间把细节重新接上。 enx 是我写的一个英文学习工具,也是技术栈的 playground。这周给 enx 加了一个 Spring Boot 后端,把一个简单的 API 迁了过去,依赖走 Homelab 里的 Nexus Maven 私服,构建和部署接到现有的 Tekton + k8s 流水线上:推代码后 Tekton 自动打镜像、更新到集群。这样一个最小闭环先跑起来,后面再慢慢补。 梳理 Java/Spring 文档 接着 W25 的节奏,继续整理 blog 里的 Java 文档,这周重心移到 Spring 和 JVM 周边。大脑像是索引和内存,blog 像是外部存储;脑子里的东西大概是 blog 内容的一个子集加上索引,有交叉,但也不是所有东西都写进了 blog。整理的过程就像是顺着索引把外存里的细节重新梳理一下。 这几个文档是本周动过的,方便以后自己回溯:classloader、Spring IoC 与 Spring Boot、graalvm native image、HotSpot,以及顺手补的 SPI / ServiceLoader 和 YAGNI。 公司:领照、刻章、开户 W24 注册了公司,这周把领营业执照、刻章办了,银行开户排到了下周。本来 6 月 24 日计划去领照,车启动打开导航才发现当天大连有达沃斯论坛限行,只好折回,在家准备面试和注册材料。第二天才正式跑完一圈。 ...

Created 28286-06-28 · Updated 30306-06-30 · 1 min · 150 words · -

Why the Blog Looked Quiet 一次构建失败导致的「假性停更」

本文是一条故障记录。 最近两天 wiloon.com 看起来像是“停更”,停在6月28号。但其实 blog 仓库是有更新的,也提交了,只是没能发布出来——博客有大约两天卡在一次构建失败上,而我自己一直不知道。 不是停更,是没发布出去 现象很简单:本地写好、git push 之后,wiloon.com 上看不到新内容。一开始我以为是 CDN 缓存或者部署延迟,没太在意。后来才发现是构建一直在失败——新提交根本没被发布出去。 怎么坏的 原因是文章标题里的一个冒号。 博客用 Hugo,文章开头的 front matter 是一段 YAML。我有几篇 Java/Spring 的文章标题是英中混写的,里面带了「冒号 + 空格」,比如: # breaks the build: ": " makes YAML parse it as a mapping title: Spring WebFlux: 响应式 Web 框架 在 YAML 里,: (冒号加空格)是 key/value 的分隔符。没加引号时,解析器会把这一行当成一个嵌套映射来读,于是报错、Hugo 构建中止。一篇的 front matter 解析失败,整站就一个页面都不生成。 修复其实只要把整个标题值用引号包起来: # fixed: quote the whole value so the colon is just text title: "Spring WebFlux: 响应式 Web 框架" 加上引号之后,构建立刻就恢复了。 ...

Created 30306-06-30 · Updated 30306-06-30 · 2 min · 233 words · -

裁员之后,我的一些探索 (2026)

上一份工作在一家外企。公司近期裁员,我的 last day 是 2026 年 4 月 24 日。公司给了数月赔偿,算是接下来一段时间的生活缓冲。 公司曾宣布全球裁员约 4000 人;大连这一轮是老板加员工、整个项目分批裁,我认识的就有 20 多人;其它组、其它部门也有裁员,具体人数不详。 裁员之后,我计划着继续或者回归远程工作这条路线。四年前就想找一个远程职位,但当时有朋友推荐,进了本地的这家外企;公司推行混合办公,每周有 N 天可以在家远程,也算一定程度体验过远程工作。 最近偶尔有朋友推荐大连本地职位,我也投了几家——理想的 offer 还没落定。 一个问题 早上跑完步,在回家的路上,想到一个问题: 裁员之后,下一个理想的 offer 还没落定——我是不是应该趁这段缓冲期,测试一下:我自己加上 AI,能不能创造出一些价值(赚到钱)? 不一定默认回到「找工作 / 打工」这种状态。 为什么叫 Exploration 回到家,我打开 TickTick(一个待办应用),新建了一个"倒数日"——从 last day 起,记录这段日子过去了多少天。 给这个"倒数日"取名时,直觉想填「失业」——字面上没错,指的就是「裁员到下一个 offer 之间」这段日子;但是看起来有点奇怪:它只描述 失去什么,不描述 要做什么。 后来选了 Exploration。每天打开 TickTick,能看到日期的累加;这个词中性一些,也更贴近我接下来想做的事——不是停在「没了什么」,而是试着看看「我 + AI」能做出什么。 实验要回答什么问题 我能不能在真实场景里创造价值?(不只是写 demo,而是有人愿意用、能省时间、能复用。) 这种价值能不能部分转化成收入?(工具、咨询、小产品、开源项目的可持续性等。) 若答案偏 yes,是否足够支撑日常开销? 如果几个月后数据不好看,再去找工作也不迟。 已有的小实践 帮一位朋友开发了一个文档格式和内容的批量校验工具——过去同类文档的人工核对要花几小时,现在批量跑一遍只要几秒,后续项目也可以复用。 这事说明: 几小时级别的投入,可以节省别人未来 N 个小时的时间; 场景是真实的、可交付的,不是玩具; AI 在这里是搭档,负责生成和迭代,我负责需求、验收和边界。 这是这段探索里第一个可以写进笔记的点。 接下来的方向 缓冲期有限,我会按「可演示、可复用、能记账」来排优先级,而不是散点学技术。 贴近真实需求、容易形成复用 继续找真实需求里规则清晰、重复劳动多的环节(校验、一致性检查、格式处理等),做类似「几小时 → 几秒」、可复用的小工具。 自己的长期项目 开源项目:ENX 等 —— 在 runway 内推进到能讲清「对谁有什么用」。 若干私有仓库里的想法 —— 验证能否形成稳定用法,或小规模地「创造价值」。 每周复盘 这周创造了什么?(钱、省下的时间、可演示的功能、开源进展都算,但要写实。) 哪件事离「可重复」最近? 下周只押注一件事是什么? 和「找工作」之间的关系 若这几个月能证明「自己 + AI」可以持续交付价值,甚至覆盖一部分生活成本,就多一条值得走的路线;若证明不了,履历和作品集也会更清晰,回去职场同样是加分项。 ...

Created 22226-05-22 · Updated 25256-06-25 · 1 min · 118 words · -

2026 W24

这篇周记是在 W25 补写的——W24 周末两天全天带孩子,没有空闲时间写。 咖啡店 WiFi 与 Netbird 6 月 6 日,周末,外面下雨,家里嘈杂(娃没法出去玩),早上出门找了家本地连锁咖啡店。连上 WiFi 之后发现网络有点不对——不开 WireGuard 时网页响应很快,一开 WireGuard 就开始严重丢包。初步判断是咖啡店的网络对 UDP 有限制,可能是为了防止 P2P 下载之类的流量。 这一折腾就是一整天。WireGuard 走不通,魔法工具也依赖家里 HomeLab 的出口,整个链路都受影响。换运营商热点、尝试不同连接方式,绕了一圈之后结论是:需要一条在 UDP 被封时能自动回退 TCP 的内网穿透方案。 最终选了 Netbird。P2P 优先,UDP 不通时自动走 TURN relay,可以走 TCP 443。同时支持 Subnet Router,HomeLab 里只需要一台节点宣告内网网段,不必给每台机器装 client。详细的部署记录见 Netbird 自建笔记。 另一件顺带记录的小事:不同咖啡店的拿铁,各家的成分不同,对乳糖不耐体质的影响有明显差异,这个已经单独记录了一下:星巴克拿铁 vs 独立咖啡店。 Giscus 评论区 6 月 9 日早上打开邮件,收到了一个 GitHub Issue 通知——上一家公司同项目组的前同事,给我的 blog 仓库提了个 issue,希望我加一个评论区。挺有意思的,前东家大裁员、项目解散已经将近一个月了,结果还能从老同事那收到"需求"。只不过这次没有 PID(项目 ID),让我有点恍惚,感觉像是又收到了项目上的客户反馈。 最后选了 Giscus,基于 GitHub Discussions 实现,隐私和管理都在自己手里。集成过程大部分可以自动化,只有 Giscus 的 category ID 需要手动获取。 ...

Created 14146-06-14 · Updated 25256-06-25 · 1 min · 98 words · -

2026 W25

本周一(6 月 16 日)补写了 2026 W24 周记。下面记 W25 自己的事。 投递邀请与简历准备 6 月 15 日收到一份投递简历的邀请。这周主要修改简历和可能的面试准备,homelab 改造、公司刻章之类都先往后放。 写简历时沿用平时写代码、写 blog 用的 SDD 思路:先和 AI 写一份 spec,对照旧简历与新职位描述列出差异;再按差异到个人 profile 里挖过往项目的故事;回到 spec 标注每条差异可以引用哪些素材;最后让 AI 根据 spec 生成新一版简历。因为此前投过类似方向的岗位,很多段落可以复用,这个流程既有结构又省时间。6 月 17 日跟前同事聊 AI 用法时,才突然意识到 SDD 不只适用于代码和文章——简历同样适用。 挖素材的过程中,我把一些早年做过但没在简历里展开的项目重新整理成文,例如 车联网平台第三方数据推送集成。有些事只是做过、学过,和跟别人讲过一次之后,大脑里留下的关联是不一样的;输出过一遍,需要的时候更容易想起来。 PDF 导出是另一条线。以前用 VS Code / Cursor 的 Preview 在浏览器里打开再打印 PDF,软件更新后这条路走不通了。跟 AI 聊了几轮,第一次正经用排版工具链:Markdown 经 Pandoc + XeLaTeX 出 PDF,定制了 LaTeX 模板和一键脚本。流程稳定后另写了一篇技术记录:Markdown to PDF: Pandoc + XeLaTeX 简历导出实践。 看职位描述时还记下一个概念 Speed over Perfection,顺手写进了 agile 笔记。 梳理 Java 文档 简历主体定稿后,重心转到 blog 里攒了很久的 Java 笔记。这次投的是 Java 方向,正好借机把零散文章理顺:拆大篇、补版本脉络、把 JVM 和 HotSpot 分开写。日历上这几天和简历收尾有重叠,但主线已经换成「整理文档」。 ...

Created 21216-06-21 · Updated 23236-06-23 · 1 min · 149 words · -

车联网平台第三方数据推送集成:Kafka + Go 实现记录(2020)

背景 2020 年前后,我在大连 R 公司负责车联网平台协议解析层的开发和维护。R 平台是一套部署在公有云上的 IoT 平台,接入大量在线车载设备,实时处理车辆上报的行车数据。 那时平台有一项新的合作需求:一家做共享汽车业务的公司(以下简称 M 公司)采购了 R 公司的车载设备,安装在共享汽车上,希望通过接口从 R 平台获取这些车辆的实时行车数据,再通过自己的 App 提供给用户查询车辆状态和行驶记录。 我负责这次集成的开发工作,包括改造行车数据服务的分流逻辑,以及独立开发一个面向 M 公司的数据推送服务。这也不是我第一次做类似的事,R 平台之前也有过给其他第三方提供数据接口的项目,但 M 公司是其中规模比较大的一家。 技术方案 行车数据服务本身改动不大。原来的逻辑是收到设备上报的数据后直接写入平台内部各个下游。这次只是加了一段分流逻辑:根据车辆底盘号(VIN)查询 Redis 中的客户映射关系,如果这辆车属于 M 公司,就把这条数据额外发送到一个专用的 Kafka topic。 Kafka topic 的另一侧是我新写的 Go Kafka consumer,消费消息后做数据格式转换,处理鉴权,再通过 HTTP POST 批量推送给 M 公司的接口。推送时有一个打包策略:收到 N 条数据就打包发出,或者超过一定时间没有新数据也把当前这批发出,每次 HTTP 请求可能包含多条记录。 VIN 到客户的映射关系存储在 Redis,由业务侧维护,数据服务只做读取。 工程细节 可观测性 对接第三方的接口,出问题时的排查成本比内部服务高很多——双方都需要对齐日志,搞清楚是哪一侧的问题。 我在这个服务里做了几件事: 每一批次数据带一个唯一的 trace ID,日志里记录发送时间、trace ID、完整 payload、M 公司 API 的响应时间和状态码。在调试阶段和试运行阶段,日志级别调到 debug,把 payload 全量打印出来,方便排查数据是否正确、格式是否符合对方预期。 除了日志,我还在服务里埋了监控指标,记录推送并发量和调用对方 API 的响应时间,接入 R 平台已有的 Grafana 看板,可以直观看到推送量和延迟的变化趋势。 ...

Created 17176-06-17 · Updated 17176-06-17 · 1 min · 100 words · -

2026 W23

这篇周报合并了第 22、23 两周,因为上篇 裁员之后,我的一些探索 发布后一直没写新的,正好把两周攒在一起记录一下。 W22:研究 QuantDinger,部署量化交易环境 这两周主要在折腾 QuantDinger,一个开源的量化交易平台。 为什么要改造 MT5 接入方式 QuantDinger 原本直接通过 Python 库调用 MT5,但 MT5 只能运行在 Windows 环境里,而我的 homelab 主力是跑在 k8s 上的 Linux 容器。直接依赖 MT5 Python 库意味着后端必须跑在 Windows 上,这和 k8s 部署的思路不兼容。 于是我 fork 了上游仓库,在 feat/mt5-thin-gateway 分支上做了一个改造:把后端对 MT5 的直接函数调用拆成 RESTful API——新增了一个独立的 mt5_gateway 服务(Python + Flask),部署在 Windows PC 上,和 MT5 进程跑在同一台机器;k8s 里的后端通过 HTTP 调用这个 gateway,不再直接依赖 MT5 环境。 主要改动集中在几个地方: 新增 mt5_gateway/ 目录,包含独立的 Flask 应用和访问日志模块 后端新增 gateway_client.py,封装对 gateway 的 HTTP 调用 execution.py、factory.py 等调用路径对应调整 补充了若干单元测试(test_mt5_factory_gateway.py 等) 目前 homelab 部署已经跑通,可以正常下单。策略部分还在调试——外汇交易有不少领域知识我不熟悉,接下来打算补一补这块。如果 homelab 测试稳定,计划向上游提 PR。 ...

Created 5056-06-05 · Updated 5056-06-05 · 1 min · 129 words · -

Conflict Check(2024)

此文用于记录在 AI 时代到来之前我手搓的最后一个复杂模块. 这个 conflict check 模块的重写是在 2024 年,历时约 3 个月,当时我还没有开始大规模使用 AI 辅助编程。重写的时候注意力都在功能需求上,并没有想「要用哪种设计模式」,只是在纠结怎么把问题拆清楚、用面向对象的方式把责任分开、把可能变化的部分封装起来。Redis 里的缓存数据是嵌套的树形结构,解析时写了几个递归调用——当时认为是最复杂的几个函数。 这个文档写于此后。某次和一个朋友聊天,对方问起对设计模式有没有了解,当时长期没有专门研究过,没说出个所以然。后来那个问题偶尔还会浮上来,然后有一天和 conflict check 关联到了起来, 然后用 Copilot + Claude Sonnet 4.6 分析了一下 — 有些设计模式接近标准实现,有的因业务结构或 Python 语言特性而有所偏差,还有两个(Builder 和 State)目前只是符合模式意图、需要重构才能达到标准结构。整理的过程中还发现了有性能优化空间的地方。 背景 防火墙策略在应用到设备之前,需要先在缓存中进行冲突检测。“网络编排器” 将每台设备的数据缓存在 Redis 中,每份 profile 包含三类数据:地址对象和分组、服务对象和分组,以及策略列表。 每条策略的关键字段: src:源地址数组,每个元素是一个 address object name 或 address group name dst:目标地址数组,结构与 src 相同 service:服务数组,每个元素是一个 service object name 或 service group name 地址对象和服务对象共用同一种数据结构,各自包含两种角色: object:基础对象,value 是实际 IP 地址/CIDR 网段(address)或协议/端口(service)的数组 group_object:分组对象,value 是 object name 或另一个 group_object name 的数组 group 和 object 形成嵌套结构:一个 group 的 value 列表里,既可以直接引用 object,也可以引用其他 group,形成递归树。地址对象和服务对象结构相同,因此 PolicyObject 类可以统一表达这两种类型,同时处理 src、dst、service 的解析。 ...

Created 14146-05-14 · Updated 5056-06-05 · 6 min · 1181 words · w1100n