diff --git a/content/_index.md b/content/_index.md index a87f112..0acc2ef 100644 --- a/content/_index.md +++ b/content/_index.md @@ -11,5 +11,5 @@ layout: hextra-home {{< /hextra-hero-headline >}} {{< hextra-hero-subtitle >}} - 一周更新两次,让脑袋泡泡冰浴 + 不忙就更新,忙就不更新。 {{< /hextra-hero-subtitle >}} diff --git a/content/blog/5g-thoughts.md b/content/blog/5g-thoughts.md deleted file mode 100644 index 1fd865d..0000000 --- a/content/blog/5g-thoughts.md +++ /dev/null @@ -1,50 +0,0 @@ ---- -title: "从 5G 到算力网络:通信行业的技术演进观察" -date: 2026-05-12T23:00:00+08:00 -draft: false -poet: | - 沉舟侧畔千帆过, - 病树前头万木春。 - ——刘禹锡,中国,772–842 -description: "5G 商用五年,哪些超出预期,哪些没达预期。以及下一个五年通信行业的关键方向:云网融合、通感算一体化、AI 原生网络和低空经济。运营商面临的结构性挑战和机会。" -tags: - - 通信 - - 5G - - 行业观察 ---- - -入行通信这些年,看着技术代际更迭,有些感触想记下来。 - -## 5G 的这五年 - -5G 商用五年,回头看当初的 hype 和现实之间的差距很有意思: - -**超预期**的部分: -- 网络能力和覆盖远超 4G -- 行业应用从概念走到落地 -- 切片、边缘计算等特性开始产生价值 - -**没达到预期的部分**: -- C 端杀手级应用迟迟未出现 -- 资费下降快,增量不增收 -- 数字化转型需求 vs 实际付费意愿之间的鸿沟 - -## 下一个五年:算力网络 - -行业现在提的更多的是「算力网络」—— 把通信网络和计算资源统一调度。 - -几个值得关注的方向: - -1. **云网融合** — 网络即服务,算力即服务 -2. **通感算一体化** — 通信、感知、计算在基站层面融合 -3. **AI 原生网络** — 用 AI 管网络,从辅助运维到自动运维 -4. **低空经济** — 无人机、飞行汽车对网络覆盖的新需求 - -## 运营商面临的挑战 - -- 传统语音+流量模式见顶 -- 云业务面临互联网厂商竞争 -- 组织流程迭代跟不上技术迭代速度 -- 人才结构转型压力大 - -不过换个角度看,通信基础设施作为数字经济的「水电煤」,长期价值不会消失,只是价值形态在变。关键是找到自己在价值链中的新位置。 diff --git a/content/blog/ai-assistant-first-week.md b/content/blog/ai-assistant-first-week.md index acfc7eb..a981484 100644 --- a/content/blog/ai-assistant-first-week.md +++ b/content/blog/ai-assistant-first-week.md @@ -1,116 +1,61 @@ --- -title: "善假说" +title: "养虾试玩报告" date: 2026-05-16T01:30:00+08:00 draft: false poet: | 君子生非异也, 善假于物也。 ——《荀子·劝学》 -description: "近以AI智能体为幕僚,五日亲历,颇有所得。录之以证荀子之言。" +description: "搭了个 AI 智能体,试了五天,记录一下它能干什么。" tags: - AI - 效率 - - 杂文 --- {{< figure src="/images/fusheng.jpg" caption="杜堇《伏生授经图》,明,大都会艺术博物馆藏" alt="杜堇《伏生授经图》" >}} -荀子说,君子生非异也,善假于物也。我以前读完也就过了,没细想。 +荀子有句话:"君子生非异也,善假于物也。"说白了就是,人和人差别没那么大,关键看你会不会用工具。以前我觉得这话挺对,但也没多想。 -AI 这两年用得不少,ChatGPT、Claude、DeepSeek 都试过。问问题、写代码、润文字,确实方便。但模式始终是单向的——它等你问,你问它答,问完结束。 +AI 这两年没少用,ChatGPT、Claude、DeepSeek 都试过。问问题、写代码、润文字,确实方便。但模式一直是你问它答,问完就完了。 -直到我用上一个能自己干活的智能体。它叫"爪子",跑在腾讯云一台轻量服务器上,4 核 4G,配置不高。搭起来很简单:在服务器上装了一个叫 OpenClaw 的智能体框架,绑好微信,配上 Todoist 和 Git 的 API 密钥,就能远程使唤了。这东西驻扎在服务器上,能直接执行 Shell 命令、读写文件、操作 Git 仓库、浏览网页。从有想法到跑起来,花了半晚上。 +直到最近搭了个能自己干活的 AI 智能体,体验不太一样。 -## 役物和任人 +它叫"爪子",跑在腾讯云一台轻量服务器上,4 核 4G。说起来也是薅羊毛——一百块拿下的,跑着网站、Git 仓库、密码管理一堆服务,性能还绰绰有余。在服务器上装了 OpenClaw,绑好微信、Todoist 和 Git 的 API,就能远程指挥了。这东西驻扎在服务器上,能跑 Shell 命令、读写文件、操作 Git、浏览网页。从有想法到跑起来,花了半个晚上。 -同样是 AI,心态不同,用法天差地别。 +## 它和 ChatGPT 的区别在哪 -**役物**——问一句答一句,答错了你纠,纠完再问。你是指挥,还得盯着每一步。 +以前用 AI:你问一句,它答一句。答错了你纠正,纠完继续问。你得盯着。 -**任人**——说清楚方向,交给它去做。做完验收就行,中间过程不必过问。 +现在用智能体:说清楚要干什么,剩下的它自己弄。做完告诉你一声。 -前者把你绑在操作台前,后者让你从执行中抽身。区别不在技术,在心法。 +前者把你绑在屏幕前,后者让你可以走开。区别不在技术,在用它的方式。 -## 三件事 +## 试了五天,举三个例子 -试了五天,挑三件说说。 +### 搭博客 -### 博客 +午休时突然想建个站,跟它说了一句。它自己 SSH 上服务器开始干活:装 Hugo、配 Nginx、设 HTTPS、修 404,全自己折腾完。后来换主题换了三次,都是睡前丢一句话,第二天醒来网站已经换好了。 -午间忽想建站,交代了一句。它 SSH 上服务器就开始干活。 +### 每天早上的资讯推送 -```mermaid -flowchart LR - A[我:建个博客] --> B[SSH 登录服务器] - B --> C[安装 Hugo + Nginx] - C --> D[配置 HTTPS] - D --> E{测试通过?} - E -->|否| F[自修权限问题] - F --> D - E -->|是| G[回复就绪] -``` +我让它写了个脚本,每天早上 8:30 把国际新闻、科技动态、通信消息编译成简报,推送到微信。 -装 Hugo、配 Nginx、设 HTTPS、修 404 错误,全是它自己弄的。后来主题换了三次——PaperMod、terminal、Hextra——都是半夜一句话的事。第二天醒来网站已经跑在新主题上了。 +第三天推送没来。没等我问,它自己查了日志发现 DeepSeek API 响应变慢超时了,自动调长时限重发了。 -### 资讯推送 +### 工作对话转待办 -每天早上想看国际新闻、科技动态和通信消息。我让它写了个定时脚本,每天 8:30 推送微信。 +同事发的聊天截图丢给它,说一句"入待办"。它读图、认人、提取待办事项、写入 Todoist、标优先级和截止日。原来一分钟的事,现在十秒。 -```mermaid -flowchart LR - A[Cron 8:30] --> B[拉取待办 + 新闻] - B --> C[编译简报] - C --> D[推送微信] - D --> E{成功?} - E -->|失败| F[自查超时] - F --> G[延长时限重发] - G --> D - E -->|成功| H[记入日志] -``` +## 试着放了更多权限 -第三天推送没来。没等我问,它已经查了日志,发现 DeepSeek API 响应变慢导致超时,自动调长时限重发了。 +一开始不敢给太多权限,只让它看看日志。后来发现它出错能自己修、操作有日志可查、半夜发消息秒回——慢慢就放心了。 -### 工单管理 +后来给了它邮箱权限,让它每天扫收件箱:找出只发给我没抄送下属的邮件,拆附件、正文转 markdown、写摘要、关联已有资料,归档到本地工作目录。第二天上班打开文件夹,摘要和附件已经摆好了。 -工作对话截图丢过去,说一句"入待办"。 +## 最后 -```mermaid -flowchart LR - A[我:发聊天截图] --> B[读取并提取信息] - B --> C[创建 Todoist 任务] - C --> D[标优先级 + 截止日] - D --> E[回复确认] -``` +有人问这和 ChatGPT 有什么区别。我觉得可以这么理解:ChatGPT 像字典,能查东西但不会替你干活。智能体像秘书,不一定比你懂行,但能替你跑腿。 -读图、识人、提取待办、写入 Todoist、标优先级、定截止期。原来要折腾一分钟的事,现在十秒。 +投入也不大:薅腾讯云羊毛,一百块拿下 4 核 4G,几套 API 凭证,半晚上就搭好了。 -## 信任是试出来的 - -一开始不放心,只让它看看日志、查查状态。后来发现出错能自愈、操作有日志可查、半夜发消息也能秒回——慢慢就放手了。 - -**邮件过滤。** 信任更进一步,我给了它 IMAP 权限,让它每天扫收件箱。 - -```mermaid -flowchart LR - A[每日扫描收件箱] --> B{发给我但
没给下属?} - B -->|是| C[建文件夹存档] - C --> D[附件存 / 正文转 md] - D --> E[撰写摘要] - E --> F[关联已有文件信息] - F --> G[入待办跟进] - B -->|否| H[跳过] -``` - -筛出发给我但没抄送下属的邮件,拆附件、正文转 markdown、写摘要、关联已有资料,分类归档到我本地工作目录的 inbox。第二天上班打开文件夹,摘要和附件已经摆好了。 - -## 写在最后 - -有人问:这和 ChatGPT 有什么区别? - -我说:**ChatGPT 是字典,这是秘书。** 字典再全,不会替你写材料。秘书不一定比你懂行,但会替你跑腿。 - -需要什么投入?一台低配云服务器,一套 API 凭证,花半晚上搭环境。门槛不高。 - -回头看荀子那句话——"善假于物"。最好的工具不是功能最强的,而是能让你从琐事中脱身的。用到某个程度你会发现,真正费脑子的不是"怎么问 AI",而是"什么可以交给 AI"。 - -这念头一转,效率的瓶颈就从工具变成了自己的想象力。 +回头想荀子那句话——"善假于物"。最好的工具不一定是最强的,是能让你少干杂事的。用着用着你会发现,真正要琢磨的不是"怎么问 AI",而是"什么可以交给 AI"。 diff --git a/content/blog/ai-productivity-observation.md b/content/blog/ai-productivity-observation.md index ec22b46..b4e5e5f 100644 --- a/content/blog/ai-productivity-observation.md +++ b/content/blog/ai-productivity-observation.md @@ -1,5 +1,5 @@ --- -title: "AI 生产力的唯一落点" +title: "AI 生产力现状" date: 2026-05-17T18:10:00+08:00 draft: false poet: | diff --git a/content/blog/ai-tools-2026.md b/content/blog/ai-tools-2026.md deleted file mode 100644 index 17bea19..0000000 --- a/content/blog/ai-tools-2026.md +++ /dev/null @@ -1,54 +0,0 @@ ---- -title: "2026 年 AI 工具链实用观察" -date: 2026-05-12T21:00:00+08:00 -draft: false -poet: | - The mind is its own place, and in itself - Can make a Heaven of Hell, a Hell of Heaven. - — John Milton, UK, 1608–1674 -description: "2026 年 AI 工具进入务实阶段。实测 DeepSeek V4 Flash 和 Pro 模型的不同场景表现,Agent 智能体的四个落地方向,以及怎么用更少 token 做更多事。" -tags: - - AI - - 工具 - - DeepSeek ---- - -2026 年的 AI 工具生态可以用一个词形容——**务实**。经过前两年的概念爆发,现在已经进入落地阶段。 - -## DeepSeek 实测 - -最近深度体验了 DeepSeek V4 系列模型,几点感受: - -### V4-Flash -日常使用首选。响应快、性价比高,适合: -- 代码辅助和 debug -- 文档撰写和润色 -- 信息检索和整理 -- 日常问答 - -### V4-Pro -复杂场景下表现出色,适合: -- 长文分析和总结 -- 多步推理任务 -- 代码架构设计 -- 领域专业知识问答 - -账户余额 ¥74.31,按目前用量够跑一阵子。 - -## 智能体(Agent)趋势 - -今年 Agent 是主题词。从单纯对话到能独立执行任务的智能体,有几个方向值得关注: - -1. **编码 Agent** — 从写代码到提 PR,全流程自动化 -2. **文档 Agent** — 自动生成周报、会议纪要、汇报材料 -3. **运维 Agent** — 日志分析、异常告警、故障排查 -4. **个人助理 Agent** — 日程管理、信息聚合、任务委派 - -## 怎么用更划算 - -- 大部分日常任务用 Flash 就行 -- 复杂任务才上 Pro,避免资源浪费 -- 善用上下文缓存,减少重复 token 消耗 -- 配合工具链(MCP、Function Calling)发挥更大价值 - -AI 工具的价值不在于它能做什么,而在于你用它做了什么。 diff --git a/content/blog/database-indexing.md b/content/blog/database-indexing.md deleted file mode 100644 index c7c84a0..0000000 --- a/content/blog/database-indexing.md +++ /dev/null @@ -1,52 +0,0 @@ ---- -title: "数据库索引优化实战" -date: 2026-05-10T16:00:00+08:00 -draft: false -poet: | - 众里寻他千百度, - 蓦然回首,那人却在,灯火阑珊处。 - ——辛弃疾,中国,1140–1207 -description: "慢查询分析、联合索引的最左前缀原则、覆盖索引与回表的性能差异。几个真实 SQL 优化案例,从几秒降到毫秒级。" -tags: - - 数据库 - - SQL - - 性能 ---- - -`EXPLAIN` 是 DBA 的眼睛。看 `type` 字段从 `ALL` 变成 `ref` 是最有成就感的事。 - -## 从慢查询开始 - -一切优化从定位问题开始。打开 MySQL 的慢查询日志(`slow_query_log`),设置 `long_query_time = 0.1`,跑一段时间后分析。PostgreSQL 用 `pg_stat_statements` 扩展,同样有效。 - -拿到慢查询,先 `EXPLAIN` 看执行计划。关注几个关键字段: - -| 字段 | 含义 | 目标 | -|------|------|------| -| type | 访问类型 | 至少到 range,最好到 ref/const | -| key | 使用的索引 | 不为 NULL | -| rows | 扫描行数 | 越小越好 | -| Extra | 额外信息 | 避免 Using filesort / Using temporary | - -## 最左前缀原则 - -联合索引是最容易出错的地方。假设索引是 `(a, b, c)`: - -- `WHERE a = 1` ✅ 用到索引 -- `WHERE a = 1 AND b = 2` ✅ 用到索引 -- `WHERE b = 2` ❌ 用不到 -- `WHERE a = 1 AND c = 3` ⚠️ 只用到了 a 列 - -排序也受这个规则约束。`ORDER BY a, b` 没问题,`ORDER BY b, c` 就需要额外排序。 - -## 覆盖索引 - -如果查询需要的所有列都在索引里,就不需要回表取数据。`Extra` 列显示 `Using index` 就是覆盖索引。对一个高频查询,覆盖索引能减少大量随机 I/O。 - -代价是索引变大了。不要为了覆盖索引把所有列都塞进索引——算一笔写入性能和存储空间的账。 - -## 真实案例 - -某个订单列表查询,原始 SQL 跑了 8 秒。`EXPLAIN` 一看,`type: ALL`,全表扫描 200 万行。加了 `(user_id, created_at)` 联合索引后,`type: ref`,扫描 20 行,耗时 12ms。 - -**索引不是越多越好**——每个索引都会拖慢写入速度并占用磁盘空间。建索引前问自己:这个查询的执行频率值得一个索引吗? diff --git a/content/blog/home-network-nas.md b/content/blog/home-network-nas.md deleted file mode 100644 index 1ba2005..0000000 --- a/content/blog/home-network-nas.md +++ /dev/null @@ -1,52 +0,0 @@ ---- -title: "家庭网络与 NAS 搭建方案" -date: 2026-05-17T15:00:00+08:00 -draft: false -poet: | - 此心安处是吾乡。 - ——苏轼,中国,1037–1101 -description: "软路由、Wi-Fi 6 AP、自建 NAS 的硬件选型和软件方案。Plex 媒体服务器 + Syncthing 文件同步 + Tailscale 远程访问,一套低成本高品质的家庭网络实践。" -tags: - - NAS - - 网络 - - 硬件 ---- - -折腾家庭网络的终点是克制。和 Linux 桌面美化一样,容易用力过猛。本文记录一套低成本但够用的家庭网络方案。 - -## 网络拓扑 - -``` -光猫 → 软路由(OpenWrt)→ 交换机 - ├── Wi-Fi 6 AP ×2 - ├── NAS(TrueNAS) - └── 有线设备 -``` - -软路由选 J4125 或 N100 这类低功耗 x86,刷 OpenWrt,负责拨号、DHCP、科学上网。AP 选 Wi-Fi 6 的,TP-Link XDR 系列性价比不错,刷 OpenWrt 或者用原厂固件都可以。 - -两个 AP 组 Mesh,不需要折腾 AC 控制器。家里 120 平米基本无死角覆盖。 - -## NAS 硬件与系统 - -旧电脑加几块硬盘就是一台 NAS。电费要算:不要拿老 i7 加独显当 NAS,待机功耗四五十瓦,一个月电费够买半块硬盘。 - -推荐方案:J4125 或 N100 小板 + 8GB 内存 + 2~4 块 4TB 硬盘组 RAID-Z1。系统选 TrueNAS Scale,基于 Linux,容器和虚拟机支持比 Core 版更好。待机功耗 15W 左右,一年电费不到一百块。 - -## 软件方案 - -三个核心应用: - -| 软件 | 用途 | 替代方案 | -|------|------|----------| -| **Plex** | 媒体服务器,自动刮削海报和元数据 | Jellyfin(开源免费) | -| **Syncthing** | 文件同步,多设备自动备份照片和文档 | Resilio Sync | -| **Tailscale** | 虚拟局域网,外面也能访问家里的服务 | ZeroTier、WireGuard 裸配 | - -Plex 装在 TrueNAS 的 App 里,显卡直通给 Plex 做硬件转码——手机上用较低码率看片时自动转码,画质损失不大。Syncthing 每台设备装一个,照片目录设为"仅发送",电脑上的文档文件夹设为"双向同步"。 - -Tailscale 是真正的体验质变。不需要公网 IP,不需要端口转发,不需要记 IP 地址。手机、笔记本、NAS 在同一个虚拟局域网里,出门在外访问 Plex 和 NAS 文件就像在家一样。免费版支持最多 100 台设备,个人用完全够。 - -## 总结 - -方案的核心思路:**够用即可**。不要想着一步到位,先从旧硬件开始跑起来,哪里不够补哪里。家庭网络的价值在于稳定无声地跑着,不是折腾本身。 diff --git a/content/blog/linux-customization.md b/content/blog/linux-customization.md deleted file mode 100644 index ab2068b..0000000 --- a/content/blog/linux-customization.md +++ /dev/null @@ -1,36 +0,0 @@ ---- -title: "Linux 桌面美化指北" -date: 2026-05-11T10:00:00+08:00 -draft: false -poet: | - My house, my house, though you are small, - You are a mansion to me after all. - — Robert Herrick, UK, 1591–1674 -description: "从默认 Gnome 到一套顺手的桌面环境。GTK 主题、图标包、终端配色、窗口管理器的选择与配置思路。不追求花哨,追求每天盯着看不累。" -tags: - - Linux - - 桌面 - - 效率 ---- - -Linux 桌面环境的选择很多,但真正好用的配置往往很简单。本文记录从 Ubuntu 默认桌面开始,逐步调整到一套耐看、高效的配置。 - -## 主题选择 - -白天用亮色主题降低反光,晚上切暗色保护眼睛。推荐 **Nord** 和 **Catppuccin** 两套配色——前者冷峻克制,后者柔和温暖,每天盯着看八小时不累。 - -GTK 主题建议选择维护活跃的项目,避免 Gnome 大版本升级后样式错乱。Qt 应用在 Gnome 下可以用 `qt5ct` 统一风格。 - -## 字体配置 - -终端字体一定要等宽且清晰。推荐 **Fira Code** 做编程字体,连字(ligatures)让 `=>`、`!=`、`>=` 这类符号组合更易读。中文字体用 **Noto Sans CJK**,和西文搭配自然。 - -## 终端与 Shell - -终端模拟器推荐 **Alacritty**——GPU 加速,配置文件清晰。配合 zsh + **starship** 提示符,日常使用效率提升不少。Starship 的优势在于跨 shell 兼容,换到 fish 或 nu 不用重新配置。 - -## 窗口管理 - -Gnome 默认的三指滑动切换工作区已经很好用。如果追求更极致的键盘操作,可以试试 **Pop Shell** 平铺扩展,或者直接上 **i3/sway**。但对大多数人来说,Gnome 的默认交互已经够用。 - -关键原则:**不追求花哨,追求每天盯着看不累。** diff --git a/content/blog/reading-2026.md b/content/blog/reading-2026.md deleted file mode 100644 index 72a77a9..0000000 --- a/content/blog/reading-2026.md +++ /dev/null @@ -1,49 +0,0 @@ ---- -title: "2026 上半年阅读清单与推荐" -date: 2026-05-12T16:00:00+08:00 -draft: false -poet: | - 书卷多情似故人, - 晨昏忧乐每相亲。 - ——于谦,中国,1398–1457 -description: "上半年读过值得推荐的几本书。《软件设计的哲学》讲复杂度管理,《深度工作》讲专注力训练,《凤凰项目》用小说讲 DevOps。附我的阅读节奏安排。" -tags: - - 阅读 - - 书单 - - 推荐 ---- - -上半年读了十几本书,挑几本值得推荐的记一下。 - -## 技术类 - -### 《软件设计的哲学》 -不是讲设计模式的,而是讲**复杂度管理**。核心观点:软件设计的本质是降低复杂度。写得深入浅出,适合有几年经验想突破瓶颈的开发者。 - -### 《凤凰项目》 -用小说的形式讲 DevOps 转型。IT 运维的日常在书里无比真实,读起来很有代入感。 - -## 效率类 - -### 《深度工作》 -Cal Newport 的代表作。核心论点:在这个随时被打断的时代,深度专注的能力越来越稀缺,也越来越有价值。 - -书里给了一些具体的训练方法,比如: -- 安排固定的深度工作时间段 -- 社交媒体断舍离 -- 用仪式感帮助进入状态 - -## 人文类 - -### 《你以为你以为的就是你以为的吗?》 -一本有意思的思维训练书,帮助识别日常思考中的逻辑漏洞。适合碎片时间翻几页。 - -## 阅读习惯 - -今年调整了阅读方式: - -- **早上的时间给深度阅读** — 30 分钟,不碰手机 -- **通勤时间给信息类阅读** — RSS、Newsletter、技术文章 -- **周末下午给整本书** — 泡杯茶,一次读一两章 - -读书不求多,读完、消化、能用上,一本顶十本。 diff --git a/content/blog/rest-api-design.md b/content/blog/rest-api-design.md deleted file mode 100644 index 2e35553..0000000 --- a/content/blog/rest-api-design.md +++ /dev/null @@ -1,76 +0,0 @@ ---- -title: "REST API Design: Mistakes I've Made So You Don't Have To" -date: 2026-05-13T09:00:00+08:00 -draft: false -poet: | - Form follows function. - — Louis Sullivan, US, 1856–1924 -description: "Lessons from real-world API design. Why version early, paginate everything, standardize error responses, and add idempotency keys. Plus a practical deprecation strategy with Sunset headers." -tags: - - API - - REST - - Backend ---- - -I've designed, built, and maintained enough REST APIs to have made most of the classic mistakes. Here's what I wish someone had told me upfront. - -## 1. Versioning Early - -Don't wait until you need it. Version your API from day one, either in the URL (`/v1/users`) or via the `Accept` header. Retrofitting versioning onto an unversioned API is painful for everyone involved. - -My preference: **URL-based versioning**. It's visible, impossible to forget, and trivially cacheable. - -## 2. Pagination by Default - -Every list endpoint should be paginated. Every. Single. One. - -```json -{ - "data": [...], - "pagination": { - "cursor": "eyJpZCI6MTIzfQ==", - "has_more": true, - "total": 847 - } -} -``` - -I've moved from offset-based to cursor-based pagination almost everywhere. Cursors handle real-time data changes gracefully and perform better on large datasets. - -## 3. Error Responses Should Be Consistent - -A predictable error shape means less client-side code: - -```json -{ - "error": { - "code": "INSUFFICIENT_BALANCE", - "message": "Account balance too low for this transaction", - "details": { - "required": 29.99, - "available": 12.50 - } - } -} -``` - -Never expose stack traces in production. Never leak internal IDs without intent. - -## 4. Idempotency Keys - -For any mutating endpoint, support an `Idempotency-Key` header. Your payment team will thank you, and so will your users when a retry doesn't double-charge them. - -## 5. Think in Terms of Deprecation - -Add a `Deprecation` and `Sunset` header to old endpoints: - -``` -Deprecation: true -Sunset: Sat, 01 Aug 2026 00:00:00 GMT -``` - -Give consumers time to migrate, then actually follow through on removal. Keeping deprecated endpoints around "just in case" is technical debt with interest. - ---- - -Good API design is mostly about **empathy for the consumer**. Ask yourself: would *you* enjoy integrating with this? diff --git a/content/blog/rust-error-handling.md b/content/blog/rust-error-handling.md deleted file mode 100644 index 9e5d63b..0000000 --- a/content/blog/rust-error-handling.md +++ /dev/null @@ -1,99 +0,0 @@ ---- -title: "Rust Error Handling: From unwrap to anyhow" -date: 2026-05-16T13:00:00+08:00 -draft: false -poet: | - If you can meet with Triumph and Disaster - And treat those two impostors just the same; - — Rudyard Kipling, UK, 1865–1936 -description: "The journey from panic-driven development to proper error types. When to use thiserror for library crates and anyhow for applications." -tags: - - Rust - - Error Handling - - Programming ---- - -Rust forces you to think about errors. Starting with `unwrap()` everywhere is fine for prototypes, but production code needs proper error types. - -## Stage 1: The Unwrap Phase - -```rust -let config = read_config().unwrap(); -let db = connect(&config).unwrap(); -let result = query(&db).unwrap(); -``` - -Every Rust beginner goes through this. It's fine for scripts and prototypes — if something fails, the panic message with a line number is good enough. The problem starts when you need graceful error handling or meaningful error messages for users. - -## Stage 2: Box - -The quick upgrade path: - -```rust -fn do_thing() -> Result<(), Box> { - let config = read_config()?; - let db = connect(&config)?; - query(&db)?; - Ok(()) -} -``` - -The `?` operator works with any error type that implements `From`. `Box` catches everything. But you lose type information — the caller can't match on specific error variants. - -## Stage 3: Proper Error Types with thiserror - -For libraries, define explicit error types: - -```rust -use thiserror::Error; - -#[derive(Error, Debug)] -pub enum AppError { - #[error("configuration error: {0}")] - Config(String), - #[error("database error: {0}")] - Database(#[from] sqlx::Error), - #[error("not found: {0}")] - NotFound(String), -} -``` - -The `#[from]` attribute auto-implements `From`, so `?` works seamlessly. Callers can match on variants: - -```rust -match do_thing().await { - Err(AppError::NotFound(id)) => { /* handle 404 */ } - Err(e) => { /* log and return 500 */ } - Ok(data) => { /* success */ } -} -``` - -## Stage 4: Application Errors with anyhow - -For binaries, `anyhow` provides flexible error handling without the ceremony: - -```rust -use anyhow::{Context, Result}; - -fn main() -> Result<()> { - let config = read_config() - .with_context(|| "failed to read config file")?; - let db = connect(&config) - .context("database connection failed")?; - Ok(()) -} -``` - -`context()` and `with_context()` attach human-readable messages at each fallible step. The error output is a chain of contexts, making debugging straightforward. - -## The Ecosystem Split - -| Crate | Use Case | Key Feature | -|-------|----------|-------------| -| `thiserror` | Library crates | Derive macro, typed errors | -| `anyhow` | Application binaries | Context chains, easy `?` | -| `eyre` | Applications (alternative) | Colorful error reports, custom hooks | - -The ecosystem has settled on this pragmatic split: **thiserror for libraries, anyhow for binaries**. Libraries expose typed errors so callers can react programmatically; applications benefit from rich, human-readable error chains. - -Remember: `unwrap()` and `expect()` still have their place — in tests, in examples, and when an invariant violation truly merits a panic. But for production code paths, make errors part of your type signature. diff --git a/content/blog/svelte-first-look.md b/content/blog/svelte-first-look.md deleted file mode 100644 index 10aecac..0000000 --- a/content/blog/svelte-first-look.md +++ /dev/null @@ -1,49 +0,0 @@ ---- -title: "Svelte 初体验:不一样的思路" -date: 2026-05-10T09:30:00+08:00 -draft: false -poet: | - Do not go gentle into that good night. - Rage, rage against the dying of the light. - — Dylan Thomas, UK, 1914–1953 -description: "试用了 Svelte 5 的 runes 语法和 SvelteKit 框架。没有虚拟 DOM,编译时直接把组件转成 DOM 操作代码,打包体积小得惊人。" -tags: - - Svelte - - 前端 - - JavaScript ---- - -用惯了 React 和 Vue,第一次接触 Svelte 的时候确实有种新鲜感。最直观的感受:**代码量少了很多**。 - -## Runes 语法 - -Svelte 5 引入了 runes 语法,让响应式声明更显式: - -- **`$state`** — 声明响应式变量,替代了之前靠赋值触发响应式的隐式规则。 -- **`$derived`** — 衍生值,类似 Vue 的 computed。 -- **`$effect`** — 副作用,自动追踪依赖并在变化时执行。 - -```svelte - -``` - -逻辑清晰,没有 `useEffect` 的依赖数组心智负担。 - -## 编译时魔法 - -Svelte 的核心理念:没有虚拟 DOM,编译器在构建时直接把组件转成高效的 DOM 操作代码。打包体积小得惊人,一个简单的组件可能只有几百字节。对移动端场景尤其友好。 - -## SvelteKit - -SvelteKit 是 Svelte 的全栈框架,文件路由设计简洁。约定优于配置——新建一个 `src/routes/about/+page.svelte`,就自动有了 `/about` 路由。内置 SSR、SSG、CSR 多种渲染模式,服务器端数据加载用 `load` 函数,类型安全做得不错。 - -## 总结 - -Svelte 适合想要减少样板代码、追求小打包体积的项目。React 和 Vue 的生态更成熟,但 Svelte 的思路值得关注。下一步打算用 SvelteKit 重写个人博客试试看。 diff --git a/content/blog/tailwind-v4-migration.md b/content/blog/tailwind-v4-migration.md deleted file mode 100644 index 2271b48..0000000 --- a/content/blog/tailwind-v4-migration.md +++ /dev/null @@ -1,67 +0,0 @@ ---- -title: "Migrating to Tailwind CSS v4" -date: 2026-05-13T08:00:00+08:00 -draft: false -poet: | - 苟日新,日日新,又日新。 - ——《礼记·大学》,中国 -description: "CSS-first configuration, the new @theme directive, container queries, and what actually changed from v3. A practical migration log." -tags: - - CSS - - Tailwind - - Frontend ---- - -Tailwind v4 drops the JavaScript config file in favor of CSS-based configuration. The migration is mostly mechanical but there are gotchas with the `@apply` directive and custom variants. - -## CSS-First Configuration - -The biggest change: `tailwind.config.js` is replaced by CSS. Your design tokens live in the `@theme` directive: - -```css -@import "tailwindcss"; - -@theme { - --color-primary: #2563eb; - --color-primary-dark: #1d4ed8; - --font-sans: "Inter", sans-serif; - --spacing-container: 1280px; -} -``` - -VSCode IntelliSense still works — the Tailwind CSS extension reads theme values from your stylesheet. - -## The Migration Path - -1. Install v4: `npm install tailwindcss@next` -2. Run the automatic migration tool: `npx @tailwindcss/upgrade` -3. Manually check `@apply` usages — the tool handles most cases, but deeply nested `@apply` with custom utilities sometimes breaks. -4. Replace `theme.extend` in your old config with `@theme` blocks in CSS. - -## New Features Worth Using - -### Container Queries - -No more media queries for component-level responsiveness. Tailwind v4 ships container query utilities: - -```html -
-
...
-
-``` - -### Dynamic Utility Values - -Arbitrary values are simpler: `w-(--sidebar-width)` references a CSS custom property. No more bracket syntax for common cases. - -### Native Cascade Layers - -Tailwind v4 uses `@layer` to control specificity. Base, components, and utilities are layered in the correct order — `@apply` in component layer no longer risks specificity wars. - -## Gotchas - -- Custom variants defined in old JS config need to be re-registered via `@variant` in CSS. -- The `important` config option now needs an explicit CSS strategy. -- Some plugins haven't updated yet — check compatibility before migrating production projects. - -Overall, the migration took about two hours for a mid-sized project. The CSS-first approach feels more natural, and the build is noticeably faster thanks to the new Oxide engine. diff --git a/content/blog/terraform-aws-ecs.md b/content/blog/terraform-aws-ecs.md deleted file mode 100644 index 6493dc0..0000000 --- a/content/blog/terraform-aws-ecs.md +++ /dev/null @@ -1,76 +0,0 @@ ---- -title: "Deploying to AWS ECS with Terraform" -date: 2026-05-14T10:00:00+08:00 -draft: false -poet: | - If you have built castles in the air, - your work need not be lost; - that is where they should be. - Now put the foundations under them. - — Henry David Thoreau, US, 1817–1862 -description: "Infrastructure as code from scratch: VPC, subnets, security groups, ECR repository, ECS service with Fargate, and an ALB in front. Every resource explained." -tags: - - AWS - - Terraform - - DevOps ---- - -ECS with Fargate is the sweet spot between managing servers and going full serverless. Terraform makes it reproducible. - -## The Stack - -Here's what we need to provision: - -| Resource | Purpose | -|----------|---------| -| VPC | Isolated network | -| Public & private subnets | Multi-AZ placement | -| Security groups | Network access control | -| ECR repository | Container image storage | -| ECS cluster + service | Run containers | -| ALB + target group | Traffic distribution | - -## Security Groups: Getting Them Right - -The key is getting the security groups right — one misconfigured rule and your containers can't talk to each other, or worse, your database is exposed to the internet. - -```hcl -resource "aws_security_group" "ecs_service" { - name = "ecs-service-sg" - vpc_id = aws_vpc.main.id - - ingress { - from_port = 3000 - to_port = 3000 - protocol = "tcp" - security_groups = [aws_security_group.alb.id] - } - - egress { - from_port = 0 - to_port = 0 - protocol = "-1" - cidr_blocks = ["0.0.0.0/0"] - } -} -``` - -The principle: **allow the minimum**. The ALB security group allows inbound from the internet on 80/443. The ECS security group only allows inbound from the ALB. The database security group only allows inbound from ECS. - -## Fargate Configuration - -Fargate abstracts the EC2 instances. You specify CPU and memory, and AWS handles the rest. For most web services, 0.25 vCPU / 512 MB is a good starting point — scale up based on load testing, not guessing. - -## CI/CD Integration - -After Terraform creates the infrastructure, your CI pipeline needs to: - -1. Build and tag the Docker image -2. Push to ECR -3. Update the ECS service with the new task definition - -Use a Terraform backend with state locking — S3 + DynamoDB is the standard approach. Without state locking, two people running `terraform apply` at the same time can corrupt your infrastructure state. - -## Cost Notes - -Fargate is more expensive per vCPU-hour than raw EC2, but you save the operational cost of patching instances and managing capacity. For small-to-medium workloads, the difference is negligible compared to the engineering time saved. diff --git a/content/blog/tool-setup.md b/content/blog/tool-setup.md deleted file mode 100644 index 8f4f67f..0000000 --- a/content/blog/tool-setup.md +++ /dev/null @@ -1,47 +0,0 @@ ---- -title: "我的效率工具链 2026" -date: 2026-05-12T18:00:00+08:00 -draft: false -poet: | - 磨刀不误砍柴工。 - ——中国谚语,中国 -description: "折腾多年终于稳定下来的工具链。子弹日记做规划,Todoist 管任务,DeepSeek V4 当主力 AI,VS Code 写代码。选工具的原则就四个字:够用就好。" -tags: - - 工具 - - 效率 - - 推荐 ---- - -持续折腾工具多年,今年终于稳定下来。记录一下目前的工具链,给想优化工作流的朋友参考。 - -## 笔记与知识管理 - -**子弹日记(纸笔)** — 每日规划和自我对话的核心载体。具体用法之前写过,不再重复。 - -**Hugo + Hextra** — 个人博客,用于对外输出。纯静态,零维护成本。 - -**GitHub** — 技术笔记和代码片段的存档。Markdown 文件 + 搜索,比任何笔记软件都好用。 - -## 任务管理 - -**Todoist** — 短期任务和提醒工具。优点是快速、跨平台、自然语言识别能力强。「今天要做的事」用它就够了。 - -## AI 工具 - -**DeepSeek V4** — 主力 AI 助手。Flash 模型日常用,Pro 模型处理复杂任务。API 接入各种场景。 - -## 开发相关 - -- **VS Code** — 主力编辑器 -- **Hugo** — 静态博客生成器 -- **Nginx** — Web 服务器 -- **Git** — 版本控制 - -## 选工具的原则 - -1. **够用就好** — 不追求功能最全,追求用得顺手 -2. **数据可控** — 优先选能导出、能自托管的方案 -3. **学习成本低** — 花在学工具上的时间要能赚回来 -4. **跨平台** — 手机和电脑都能用 - -好工具的标准不是功能多,而是让你忘记工具的存在,专注于事情本身。 diff --git a/content/blog/vim-motions.md b/content/blog/vim-motions.md deleted file mode 100644 index 41bc1fa..0000000 --- a/content/blog/vim-motions.md +++ /dev/null @@ -1,55 +0,0 @@ ---- -title: "Vim Motions That Actually Save Time" -date: 2026-05-14T14:00:00+08:00 -draft: false -poet: | - Practice does not make perfect. - Only perfect practice makes perfect. - — Vince Lombardi, US, 1913–1970 -description: "Which Vim motions are worth the muscle memory investment? A practical three-tier ranking from non-negotiable (ci, %, dot) to nice-to-have (macros, jump list), based on three years of daily use." -tags: - - Vim - - Productivity - - Editor ---- - -Everyone tells you to learn Vim, but nobody tells you *which* motions are worth the muscle memory investment. After three years of daily use, here's my honest ranking. - -## Tier 1: Non-Negotiable - -These pay for themselves within a week: - -| Motion | What it does | Why it matters | -|--------|-------------|----------------| -| `ci"` | Change inside quotes | Editing strings, attributes | -| `ci(` / `ci{` | Change inside brackets | Refactoring arguments | -| `%` | Jump to matching bracket | Navigating code blocks | -| `*` / `#` | Search word under cursor | Quick variable tracing | -| `.` | Repeat last change | The single biggest time-saver | - -## Tier 2: Worth Practicing - -These take a few weeks to internalize but compound: - -- `f{char}` / `F{char}` — find character inline. Faster than `h`/`l` spam -- `t{char}` / `T{char}` — find *until* character. Perfect for deleting `until` a comma -- `ctrl+d` / `ctrl+u` — half-page scroll. Keeps your eyes on the same spot -- `zz` — center current line. Eliminates mental reorientation - -## Tier 3: Nice to Have - -Useful but not essential for daily work: - -- `gt` / `gT` — switch tabs -- `ctrl+o` / `ctrl+i` — jump back/forward in the jumplist -- Macros (`q{register}`) — only worth it for repetitive tasks of 10+ iterations - -## What I Don't Use - -- **Line numbers as targets** (`:42`) — too slow mentally -- **Visual block mode** — I use multi-cursor in VS Code instead -- **`/` search with regex** — I just use `*` and `f` 90% of the time - ---- - -The real productivity gain isn't in any single motion — it's in **not thinking about navigation**. When your fingers just move the cursor without conscious effort, that's when the payoff arrives. diff --git a/content/blog/vps-basics.md b/content/blog/vps-basics.md deleted file mode 100644 index 6861157..0000000 --- a/content/blog/vps-basics.md +++ /dev/null @@ -1,88 +0,0 @@ ---- -title: "VPS 新手入门:从购买到上线一个网站" -date: 2026-05-12T19:00:00+08:00 -draft: false -poet: | - 路漫漫其修远兮, - 吾将上下而求索。 - ——屈原,中国,约前340–前278 -description: "买了一台云服务器之后怎么让它跑起来。从 SSH 登录、创建普通用户、配置密钥认证、设置 ufw 防火墙到用 Nginx 部署静态网站,一套完整的新手流程。" -tags: - - Linux - - VPS - - 教程 ---- - -买了一台云服务器之后,怎么让它真正跑起来?这篇文章记录基本的 VPS 初始化和安全配置流程。 - -## 购买后的第一件事 - -拿到服务器 IP 和 root 密码后: - -### 1. SSH 登录 - -```bash -ssh root@你的服务器IP -``` - -第一次登录会提示确认主机指纹,输入 `yes` 即可。 - -### 2. 创建普通用户 - -root 权限太大,日常操作应该用普通用户: - -```bash -adduser 用户名 -usermod -aG sudo 用户名 -``` - -### 3. 配置 SSH 密钥登录 - -```bash -# 在本地机器上生成密钥 -ssh-keygen -t ed25519 - -# 把公钥传到服务器 -ssh-copy-id 用户名@服务器IP -``` - -然后编辑 `/etc/ssh/sshd_config`,关闭密码登录: - -``` -PasswordAuthentication no -``` - -### 4. 防火墙配置 - -用 ufw 简单配置: - -```bash -ufw allow OpenSSH -ufw allow 80/tcp -ufw allow 443/tcp -ufw enable -``` - -### 5. 安装必要的软件 - -```bash -apt update && apt upgrade -y -apt install -y nginx curl wget git -``` - -## 部署静态网站 - -最简单的方式是用 Nginx: - -1. 把构建好的静态文件放到 `/var/www/html` 或自定义目录 -2. 配置 Nginx 站点文件指向该目录 -3. 运行 `nginx -t && systemctl reload nginx` - -## 安全底线 - -- 不要用 root 直接操作日常任务 -- 关闭 SSH 密码登录 -- 定期更新系统包 -- 非必要不开放额外端口 - -服务器就像一间屋子,基础装修做好才能住得安心。 diff --git a/hugo.yaml b/hugo.yaml index ffde0de..0eec4d3 100644 --- a/hugo.yaml +++ b/hugo.yaml @@ -91,8 +91,7 @@ params: columns: - title: FuKun.Net desc: | - 写代码,带娃,偶尔写写文章。 - 没什么大志向,踩过的坑都记在这儿了。 + 晴耕雨读 心灯不夜 - title: 站点 links: - name: 博客