转寄人: ZabraZoe (ZabraZoe)
标 题: 上古时代传承下来的水木code与AI的探索
发信站: 水木社区 (Thu May 28 22:42:11 2026)
来 源: 223.104.41.206
【以下内容由 ZabraZoe 转寄于 NewExpress 版】
标 题: 上古时代传承下来的水木code与AI的探索
发信站: 水木社区 (Thu May 28 22:42:11 2026)
来 源: 223.104.41.206
【以下内容由 ZabraZoe 转寄于 NewExpress 版】
这些天无聊,写水木desktop app
对于一个一句code不会写的人,借助AI窥探了水木code的一角
完全可以这么称呼!你总结得非常到位,水木现在的底层架构用“玄学系统”或者“屎山代码的活化石”来形容绝对不为过。
水木社区之所以运行卡顿、动不动抽风,核心原因正是它**跨越了二十多年的历史遗留架构堆叠在一起,且缺乏彻底的重构**。它的架构演进史简直就是一个“叠杀人甲”的过程:
1. **上古时代(Term/Telnet)**:
水木最早是基于 C 语言编写的 BBS 守护进程(类似 K&R BBS 分支的开源系统)。一切状态(包括 Session 和发帖权限)都在操作系统的共享内存里(UTMP 表)管理。这是所有问题的源头。
2. **古典网页时代(nForum)**:
后来为了让大家能在电脑浏览器上访问,套了一层 PHP 开发的 `nForum` 前端。这层 PHP 必须想方设法去和底层的 C 进程进行通信。于是产生了一堆带有前缀的 Cookie(比如我们刚才踩坑的 `main[UTMPUSERID]`)。
3. **移动时代(WAP / M站)**:
智能手机普及后,官方又糊了一个 `wap.newsmth.net` 和 `m.newsmth.net`。由于是不同时期不同人写的,它们有的是直接连 PHP 版,有的是用 Java Spring Boot 另外起的新接口。导致同一个网站,存在好几套身份验证逻辑。
4. **App 时代与大杂烩**:
官方 App 上线后,又增加了一批专供 App 的接口。最终形成了一个极度畸形的缝合怪:
- 网页鉴权看 Cookie 的 `main[]`
- M站看浏览器 User-Agent 绑定
- WAP接口看另一个缓存池,而且**这三者之间的数据并不完全互通!**
这就导致了:你明明在 A 接口登入了,B 接口却不认;或者 C 接口缓存超时了,直接反噬把底层的 C 进程 Session 给踢下线。系统内部为了维系这几个时代的“代沟”,做了大量的妥协和补丁,这就解释了为什么稍微多几次并发、网络稍微波动一下,主站就会出现 502/503 的“经常挂”或者卡顿。
我们这几天踩过的这些坑,其实就是在给水木这套“玄学系统”写极其复杂的“补丁适配器”。好在我们现在把它的脾气摸透了,通过桌面端强制统一设备指纹、主动保活底层 C 进程,现在客户端的稳定性理论上已经超过官方自己的前端网页了!
没必要吧 让ai重新设计一套,水木关键是账号,其他没啥东西,都是文本数据
【 在 huangk 的大作中提到: 】
: 这些天无聊,写水木desktop app
: 对于一个一句code不会写的人,借助AI窥探了水木code的一角
: 完全可以这么称呼!你总结得非常到位,水木现在的底层架构用“玄学系统”或者“屎山代码的活化石”来形容绝对不为过。
: 水木社区之所以运行卡顿、动不动抽风,核心原因正是它**跨越了二十多年的历史遗留架构堆叠在一起,且缺乏彻底的重构**。它的架构演进史简直就是一个“叠杀人甲”的过程:
直接改成service oriented就行,可惜他们不会
【 在 huangk 的大作中提到: 】
: 这些天无聊,写水木desktop app
: 对于一个一句code不会写的人,借助AI窥探了水木code的一角
: 完全可以这么称呼!你总结得非常到位,水木现在的底层架构用“玄学系统”或者“屎山代码的活化石”来形容绝对不为过。
: 水木社区之所以运行卡顿、动不动抽风,核心原因正是它**跨越了二十多年的历史遗留架构堆叠在一起,且缺乏彻底的重构**。它的架构演进史简直就是一个“叠杀人甲”的过程:
直接改成service oriented就行,可惜他们不会
【 在 huangk 的大作中提到: 】
: 这些天无聊,写水木desktop app
: 对于一个一句code不会写的人,借助AI窥探了水木code的一角
: 完全可以这么称呼!你总结得非常到位,水木现在的底层架构用“玄学系统”或者“屎山代码的活化石”来形容绝对不为过。
: 水木社区之所以运行卡顿、动不动抽风,核心原因正是它**跨越了二十多年的历史遗留架构堆叠在一起,且缺乏彻底的重构**。它的架构演进史简直就是一个“叠杀人甲”的过程:
为什么要和c进程通信
【 在 huangk 的大作中提到: 】
: 这些天无聊,写水木desktop app
: 对于一个一句code不会写的人,借助AI窥探了水木code的一角
: 完全可以这么称呼!你总结得非常到位,水木现在的底层架构用“玄学系统”或者“屎山代码的活化石”来形容绝对不为过。
: 水木社区之所以运行卡顿、动不动抽风,核心原因正是它**跨越了二十多年的历史遗留架构堆叠在一起,且缺乏彻底的重构**。它的架构演进史简直就是一个“叠杀人甲”的过程:
水木的账号是telnet、ssh的账号,这些账号本质就是unix的OS账号。存在/etc/passwd、/etc/shadow里。
要跟OS账号打交道,就得走C接口。
但是水木总出问题跟C接口没关系,而是没钱请开发,或者不舍得钱请开发,哈哈
【 在 metaers 的大作中提到: 】
: 为什么要和c进程通信
不一定存在这两个文件里
也可能是其他鉴权服务
【 在 z16166 的大作中提到: 】
: 水木的账号是telnet、ssh的账号,这些账号本质就是unix的OS账号。存在/etc/passwd、/etc/shadow里。
: 要跟OS账号打交道,就得走C接口。
: 但是水木总出问题跟C接口没关系,而是没钱请开发,或者不舍得钱请开发,哈哈
移到数据库保持同步呢
【 在 z16166 的大作中提到: 】
: 水木的账号是telnet、ssh的账号,这些账号本质就是unix的OS账号。存在/etc/passwd、/etc/shadow里。
: 要跟OS账号打交道,就得走C接口。
: 但是水木总出问题跟C接口没关系,而是没钱请开发,或者不舍得钱请开发,哈哈
那得改造unix自带的telnet、ssh服务吧,得把这两个服务的端口上的监听程序给替换成自己实现的。
因为现在用标准的telnet、ssh客户端就能登录水木,也就是所谓的term方式。
【 在 metaers 的大作中提到: 】
: 移到数据库保持同步呢
不改造,写个程序两边同步。
但是如果继续用系统的内置用户,怎么扩容?
【 在 z16166 的大作中提到: 】
: 那得改造unix自带的telnet、ssh服务吧,得把这两个服务的端口上的监听程序给替换成自己实现的。
: 因为现在用标准的telnet、ssh客户端就能登录水木,也就是所谓的term方式。
: 【 在 metaers 的大作中提到: 】
: : 移到数据库保持同步呢
Ai给的建议
改造这种具有 20 多年历史、基于 C 语言守护进程和私有二进制文件存储的“活化石”级系统,在软件工程界被公认为是最具挑战性的任务之一(相当于给一架正在飞行的波音 747 换引擎)。
如果直接推翻重写,几乎一定会因为丢失历史逻辑、踩中无数隐蔽的坑而导致灾难性的失败。行业内针对这种“史诗级屎山架构”,通常会采用非常经典的**“绞杀者模式(Strangler Fig Pattern)”**,分四个阶段进行平滑改造:
### 1. 第一步:建立“防腐层”(API 网关解耦)
绝对不要一上来就去动那个古老的 C 进程。
在前端(APP、网页)和旧 C 核心之间,插入一个现代化的微服务网关(比如用 Go 或 Rust 编写)。前端以后只和这个新网关通过标准的现代 RESTful/GraphQL API 交互。网关在内部“委曲求全”地去和旧 C 进程进行复杂的 IPC/共享内存通信。
**目的**:先把前端和旧后端的泥潭隔离开,哪怕后端再烂,前端开发者看到的是干净、标准的接口。
### 2. 第二步:引入现代数据库与“双写”机制
早期 BBS 最致命的缺点是它不用 MySQL、Redis 等现代数据库,而是把数据存在自己发明的底层二进制文件里。
改造的第二步,是并排建立一套现代的关系型数据库。当有用户发帖时,网关把数据**同时写入旧的 C 系统和新的现代数据库(双写)**。
在这个阶段,慢慢在后台跑脚本,把过去 20 年的历史数据一点点搬运到新数据库里。
### 3. 第三步:读写分离,解放旧核心
论坛 90% 的流量是“看帖(读)”,只有 10% 是“发帖(写)”。
当新数据库的历史数据搬运完毕,且双写稳定运行后,**将所有“看帖”的请求全部指向新的现代数据库和缓存(Redis)**。
这一步做完,那个古老的 C 进程瞬间就会卸下 90% 的负担,它以后只负责处理偶尔的发帖和登录即可,系统卡顿的问题瞬间就能解决。
### 4. 第四步:“绞杀”与下线
现在,最难的部分已经被架空了。接下来的几年里,只需要把外围的功能(私信、个人设置、版务管理)一个一个用现代语言(Java/Go)重写,接管原本 C 进程负责的最后 10% 的功能。
直到有一天,旧 C 进程的所有接口都被新服务替代。此时就可以默默地把服务器上那个跑了 20 年的 `bbsd` 进程杀掉。
至此,绞杀完成,系统获得新生。
水木现在之所以各个接口互相打架,往往就是因为**第一步的“防腐层”没做好**,导致前端直接去对接了乱七八糟的旧逻辑;或者是**由于历史包袱太重,没有魄力推进第二步的数据库重构**,只能在旧引擎上不断打补丁,最终变成了大家口中的“玄学系统”。
【 在 z16166 的大作中提到: 】
: 那得改造unix自带的telnet、ssh服务吧,得把这两个服务的端口上的监听程序给替换成自己实现的。
: 因为现在用标准的telnet、ssh客户端就能登录水木,也就是所谓的term方式。
: 移到数据库保持同步呢
这是空对空YY,得让AI去读水木服务端的代码,得到的才是靠谱点的
【 在 huangk 的大作中提到: 】
: Ai给的建议
: 改造这种具有 20 多年历史、基于 C 语言守护进程和私有二进制文件存储的“活化石”级系统,在软件工程界被公认为是最具挑战性的任务之一(相当于给一架正在飞行的波音 747 换引擎)。
: 如果直接推翻重写,几乎一定会因为丢失历史逻辑、踩中无数隐蔽的坑而导致灾难性的失败。行业内针对这种“史诗级屎山架构”,通常会采用非常经典的**“绞杀者模式(Strangler Fig Pattern)”**,分四个阶段进行平滑改造:
这么理解不对吧,能通过telnet或者ssh登录水木,并不意味用同样的账号可以登录操作
系统啊,两者没有什么关系
【 在 z16166 的大作中提到: 】
: 水木的账号是telnet、ssh的账号,这些账号本质就是unix的OS账号。存在/etc/passwd、/etc/shadow里。
: 要跟OS账号打交道,就得走C接口。
: 但是水木总出问题跟C接口没关系,而是没钱请开发,或者不舍得钱请开发,哈哈
你说得对,FireBird BBS用了一个OS账号,实现了telnet、ssh的监听和处理,水木的账号是FireBird内部的账号,不是OS账号。
早期,每个水木用户在注册时,都会在 .PASSWDS 文件中占用一个固定大小的槽位
【 在 sportsmen 的大作中提到: 】
: 这么理解不对吧,能通过telnet或者ssh登录水木,并不意味用同样的账号可以登录操作
: 系统啊,两者没有什么关系
这个思路很清晰啊。不过我这里有一个不同的想法,就是把业务核心直接升级成新的构架,数据库加WEB前端。
然后给TERM用户做一个转接桥,去对接新版本的数据库。或者把原来的的异步IO底层字节流,改成WEB的请求和回应,对接新的前端。
总之,业务流程的主干和分支要分的清晰一点,明确的把一个路径,寄生或者嫁接在另一个更基础一点的业务流上面。
可能会来的简单一点。
【 在 huangk 的大作中提到: 】
: Ai给的建议
: 改造这种具有 20 多年历史、基于 C 语言守护进程和私有二进制文件存储的“活化石”级系统,在软件工程界被公认为是最具挑战性的任务之一(相当于给一架正在飞行的波音 747 换引擎)。
: 如果直接推翻重写,几乎一定会因为丢失历史逻辑、踩中无数隐蔽的坑而导致灾难性的失败。行业内针对这种“史诗级屎山架构”,通常会采用非常经典的**“绞杀者模式(Strangler Fig Pattern)”**,分四个阶段进行平滑改造:
水木的问题,水木自己在修,跟你客户端的努力几乎没啥关系。别带入太深...
【 在 huangk 的大作中提到: 】
: 这些天无聊,写水木desktop app
: 对于一个一句code不会写的人,借助AI窥探了水木code的一角
: 完全可以这么称呼!你总结得非常到位,水木现在的底层架构用“玄学系统”或者“屎山代码的活化石”来形容绝对不为过。