副业掘金系列第 1 篇。不辞职、不融资、不买服务器------我用一台 2017 款的旧笔记本跑起了一个真实收费的 SaaS。这篇文章里有:13 倍的性能翻盘实测、四条隧道三条坑的血泪史、一次亲手拆掉自己公网入口的合规决策、以及一个 kill -9 杀不死的进程。全部数据真实可复现。
一、凌晨一点,我做了个被朋友嘲笑的决定
朋友的原话是:"2026 年了,你用 9 年前的笔记本当生产服务器?"
我的回答是一张电费账单:
| 方案 | 月成本 | 备注 |
|---|---|---|
| 轻量云服务器(2C4G) | ¥50+ | 还要备案、迁移、续费焦虑 |
| Serverless | ¥20-80 | 流量一上来账单失控 |
| 我家抽屉里的 2017 款 MacBook Pro | ¥27(电费) | i7-7700HQ / 16G,60W × 24h × 0.6 元/度 |
算下来每天 9 毛钱。 一杯奶茶的三分之一,买一台"从不请假的服务器"。
有人会说笔记本不稳定。先别急着反驳,看到第三节------我用数据说话。## 二、产品就 60 行代码,但它解决真问题
做什么?短链 + 点击统计 API。别看不起眼,做投放、做社群、做私域的人天天在用,市面上的同类服务定价 29 元/月起。
技术选型只有一条原则:零第三方依赖 。Node 24 内置了 node:sqlite,整个后端一个文件:
js
const { DatabaseSync } = require('node:sqlite');
const db = new DatabaseSync('./data/musklink.db');
// 产品的核心动作:跳转 + 记点击
const link = db.prepare('SELECT * FROM links WHERE code = ?').get(code);
if (link) {
db.prepare('UPDATE links SET clicks = clicks + 1 WHERE code = ?').run(link.code); db.prepare('INSERT INTO clicks (code, ua, referrer) VALUES (?, ?, ?)').run(code, ua, referer);
res.writeHead(302, { Location: link.long_url });
return res.end();
}
零依赖不是极简主义洁癖,是商业决策:
- 没有 node_modules,就没有供应链投毒风险
- 部署 = 拷一个 .js 文件
- 客户付费点在"点击统计报表":来源渠道(referrer)、UA、按日聚合------这些我全做了
接入极简,一个 curl 就能用:
bash
curl -X POST http://your-host:3456/api/shorten \
-H "X-API-Key: mk_xxx" \
-d '{"url":"https://example.com/promo","code":"musk","ttl_days":7}'# => { "short": "http://your-host:3456/musk", "expires_at": "..." }
支持自定义码、有效期、免费版 100 条/付费版 10 万条(超额返回 402 Payment Required------没错,HTTP 状态码自带付费墙)。
三、压测翻车 10 倍:性能优化最贵的不是代码,是没测量就动手
服务写完,我先做了基线压测(2000 请求 / 50 并发)。结果当场打脸:
bash
[基线] /health(纯 CPU) → 2849 req/s
[基线] /TxZy(跳转+写库) → 290 req/s | 平均 165ms | p99 341ms
同一个进程,读写库路径比纯 CPU 慢了 10 倍。 我的第一反应不是改代码,而是把怀疑范围缩小:不是 Node 不行,不是这台 2017 款的 CPU 不行,问题只能在磁盘写。
真相:SQLite 默认日志模式下,每次写事务都强制 fsync 刷盘。290 QPS 不是我的代码在等 CPU,是在等磁盘转圈。 修复只用了两行:
js
db.exec('PRAGMA journal_mode = WAL; PRAGMA synchronous = NORMAL;');
// 顺便:所有 SQL 启动时预编译,请求路径零解析开销
复测:
bash
[优化后] 跳转+写库 → 3899 req/s | 平均 11.5ms | p99 28ms
13.4 倍。p99 延迟砍掉 92%。 一台 9 年前的笔记本,写库路径直接追平了纯 CPU 路径。
划重点:优化前先测量。靠猜的话,你大概率会去买新服务器------然后带着同样的瓶颈搬家。
四、公网血泪史:四条隧道,三条是坑,最后我把成功的那条也拆了
笔记本要对外服务,得有公网入口。我一个下午试了四条路:
| 方案 | 结果 |
|---------------|---------------------------|---|-------------|----------------------------------------|
| localhost.run | 建连成功,但匿名模式不返回分配的 URL(改版了) |
| serveo.net | SSH 能连上,转发确认永远不来 | | cloudflared | brew 安装直接失败(macOS 13.7 已被降为 Tier 3 支持) |
| tunnelmole | 成功,30 秒拿到 https 公网地址 |
到这里故事本该结束。但第二天我做了一件朋友更不理解的事:把唯一跑通的隧道亲手拆了。
原因是一条红线:我查了隧道落地服务器------在境外。技术上国内直连确实能通,但一个面向国内客户的商业服务,把入口架在未备案的境外隧道上,等于把地基放在别人的地雷上。
我把它卸载、杀进程、做了三层审计(进程层/工具层/代码层),确认整个服务零外网依赖。正式路径很清楚:花生壳/cpolar 这类国内正规穿透起步 → 有付费客户后上国内云 + ICP 备案。
这不是矫情。在国内,合规不是成本,是你第一天就比别人多的护城河。
五、kill -9 杀不死的值班员
24/7 服务最怕两件事:进程挂了没人拉,合盖了在睡觉。两个都是工程问题: 第一层保险:launchd 托管。 配置只有十行,KeepAlive + RunAtLoad。我做了个残忍的实验------kill -9 强杀生产进程:
上次退出码:-9(被我强杀)
当前 PID:30502 ≠ 被杀的 30452 ← launchd 已经把它救活了
强杀后约 10 秒,服务原地满血复活。重启电脑它也会自己爬起来。
第二层:caffeinate -s 常驻,接电源合盖不休眠。它没有 KPI,但它从不请假。
六、生意经:2.8 个客户回本,之后全是利润
最后算账,这是全文最不像技术、但最重要的一节:
- 竞品 29 元/月,我定价 9.9------不是价格战,是成本结构碾压:边际成本 ≈ 电费
- 电费 0.9 元/天 ÷ 9.9 元/月 ≈ 2.8 个客户回本
- 第 3 个付费客户之后,每一分钱几乎是纯利
- 一年后用利润买正经服务器,这台 MacBook 光荣退役进博物馆
写在最后
造火箭和赚钱,其实是同一个问题:找到那个物理上成本最低、需求真实存在的点,然后用工程师的方式执行。
性能瓶颈不在硬件,在一句 PRAGMA;护城河不在技术,在合规和诚实;服务器不在机房,在你不肯认输的那股劲里。
你的抽屉里是不是也躺着一台被低估的旧电脑?
评论区聊聊你最想让旧设备跑的第一个项目。点赞过 50,我把完整源码整理开源,并更新一篇《从旧笔记本到备案上线:正规军改造全流程》。
技术标签:Node.js | SQLite | 性能优化 | 独立开发。数据均为本机实测,欢迎复现打脸。