远程过程调用(RPC)的通用缺点:成本与风险

副标题 / 摘要 RPC 看似像本地调用,但它的失败模式与成本完全不同。本文总结 RPC 的通用缺点与工程应对策略。 目标读者 设计微服务通信的工程师 需要评估 RPC 成本的技术负责人 想避免分布式陷阱的开发者 背景 / 动机 RPC 把“跨网络调用”伪装成本地函数。 这会导致开发者低估失败概率与性能成本,从而引发稳定性问题。 核心概念 网络不可靠性:超时、丢包、抖动 部分失败:某些节点失败,其他正常 重试风暴:错误重试导致雪崩 版本演进:接口变更与兼容性问题 实践指南 / 步骤 为 RPC 设置超时与重试策略 避免级联调用 引入熔断与降级 做好可观测性(日志/追踪) 管理版本兼容性 可运行示例 import time import random def rpc_call(): time.sleep(random.random() * 0.2) if random.random() < 0.2: raise TimeoutError("rpc timeout") return "ok" if __name__ == "__main__": try: print(rpc_call()) except TimeoutError as e: print("fail", e) 解释与原理 RPC 的本质是网络调用,失败概率远高于本地函数。 把它当作本地调用,会导致过度耦合与错误传播。 常见问题与注意事项 RPC 一定比消息队列好吗? 不一定,取决于一致性与解耦需求。 为什么重试会导致雪崩? 因为失败请求叠加更多压力。 ...

2026年1月24日 · 1 分钟 · map[name:Jeanphilo]

什么是 O/R 阻抗失衡:对象世界与关系模型的冲突

副标题 / 摘要 O/R 阻抗失衡指对象模型与关系模型的结构和语义不一致,导致映射复杂、性能问题和维护成本上升。本文给出可落地的缓解策略。 目标读者 使用 ORM 的后端工程师 负责数据建模与性能优化的开发者 想理解“为什么 ORM 不是银弹”的团队负责人 背景 / 动机 对象世界是图结构(引用、继承、聚合),关系世界是表结构(行、列、外键)。 两者语义不同,映射时必然损失与扭曲,这就是 O/R 阻抗失衡。 核心概念 对象图:一对多、多对多关系 关系模型:表与外键,依赖 JOIN 映射成本:查询复杂、N+1、延迟加载等 实践指南 / 步骤 先设计数据访问模式,再设计模型结构 为读与写设计不同模型(CQRS 思路) 控制对象图深度,避免自动级联查询 使用 DTO 作为边界,减少 ORM 泄漏 对关键路径手写 SQL 可运行示例 下面示例展示对象与关系的差异: import sqlite3 conn = sqlite3.connect(":memory:") cur = conn.cursor() cur.execute("CREATE TABLE user(id INTEGER PRIMARY KEY, name TEXT)") cur.execute("CREATE TABLE orders(id INTEGER PRIMARY KEY, user_id INTEGER, amount INTEGER)") cur.execute("INSERT INTO user VALUES (1, 'Alice')") cur.executemany("INSERT INTO orders VALUES (?, ?, ?)", [(1, 1, 100), (2, 1, 200)]) cur.execute("SELECT u.name, o.amount FROM user u JOIN orders o ON u.id = o.user_id") print(cur.fetchall()) 解释与原理 对象模型喜欢“引用”和“聚合”,而关系模型喜欢“表”和“JOIN”。 ORM 需要在两种语义之间做折中,这就产生了性能与复杂度问题。 ...

2026年1月24日 · 1 分钟 · map[name:Jeanphilo]

CSR vs SSR:取舍、性能指标与落地路径

副标题 / 摘要 CSR 与 SSR 的选择不是二选一,而是围绕性能、SEO、复杂度的权衡。本文给出可操作的决策路径与示例。 目标读者 负责前端架构选型的工程师 需要改善首屏体验与 SEO 的团队 希望理解 TTFB/TTI 的开发者 背景 / 动机 CSR(客户端渲染)强调前端灵活与交互性,SSR(服务端渲染)强调首屏体验与 SEO。 很多项目因为选型不当,出现首屏慢、SEO 差或部署复杂度过高的问题。 核心概念 TTFB:首字节时间,越小越好 TTI:可交互时间 Hydration:SSR 之后在客户端接管交互 SEO:搜索引擎对 HTML 内容的可见性 实践指南 / 步骤 先看内容属性:是否依赖 SEO、是否内容密集 评估交互复杂度:高度交互通常偏向 CSR 或 SSR+Hydration 关注性能指标:TTFB、FCP、TTI、CLS 考虑部署成本:SSR 需要服务器渲染能力 混合策略:关键页 SSR,其余 CSR 或 SSG 可运行示例 下面用一个最小 Python 服务演示 SSR 和 CSR 的差异: from http.server import BaseHTTPRequestHandler, HTTPServer import json import time class Handler(BaseHTTPRequestHandler): def do_GET(self): if self.path == "/ssr": html = f"<h1>SSR time: {time.time()}</h1>" self.send_response(200) self.send_header("Content-Type", "text/html") self.end_headers() self.wfile.write(html.encode()) elif self.path == "/csr": html = """ <div id='root'>Loading...</div> <script> fetch('/api/time').then(r => r.json()).then(d => { document.getElementById('root').innerText = 'CSR time: ' + d.time; }); </script> """ self.send_response(200) self.send_header("Content-Type", "text/html") self.end_headers() self.wfile.write(html.encode()) elif self.path == "/api/time": body = json.dumps({"time": time.time()}).encode() self.send_response(200) self.send_header("Content-Type", "application/json") self.end_headers() self.wfile.write(body) else: self.send_response(404) self.end_headers() if __name__ == "__main__": HTTPServer(("127.0.0.1", 8000), Handler).serve_forever() 启动后访问: ...

2026年1月24日 · 2 分钟 · map[name:Jeanphilo]

任务编排为什么要放后端:让流程可控、可变、可回放

任务编排为什么要放后端:让流程可控、可变、可回放 副标题 / 摘要 在多步骤、可中断、可回放的业务流程中,把“流程顺序与状态机”放在后端,是系统长期可演进的关键。本文从真实工程痛点出发,解释为什么前端不应硬编码流程顺序,并给出一套可落地的后端 Pipeline 编排思路与最小实现。 目标读者 正在设计多步骤流程 / 向导式产品的后端工程师 需要支撑 Web / App / Admin 多端一致流程的技术负责人 在 AI / LLM 产品中处理“模型自动 + 人工确认”混合流程的团队 背景 / 动机:问题通常是怎么爆出来的? 很多系统一开始都很简单: 前端:第 1 步 → 第 2 步 → 第 3 步 后端:校验 + 存数据 但随着业务演进,以下需求几乎一定会出现: 步骤 变多:从 3 步变成 10+ 步 步骤 可选:根据条件跳过 / 插入新步骤 步骤 可中断:需要用户确认、补充信息、人工审核 步骤 可重试 / 可回放:失败后从中间继续,而不是全部重来 步骤 多端一致:Web / App / 内部工具共享同一流程 如果此时流程顺序仍然写在前端: 每次流程变更 = 多端发版 出问题时无法准确回答:现在卡在哪一步? 想加监控、审计、回放,发现无从下手 根因只有一个: ...

2026年1月13日 · 2 分钟 · map[name:Jeanphilo]

算法与业务的关系:把不确定性变成可交付(以 LLM 事实抽取为例)

摘要 很多团队做 AI 应用时会陷入一种痛苦:业务逻辑写了一堆,却始终看不到“算法到底抽出了什么”。根因往往不是代码能力,而是把算法阶段的探索,过早塞进业务工程。本文用“投标写作工具里的事实抽取(FactMention)”作为例子,讲清楚算法与业务的边界、如何用 JupyterLab 快速验证、以及何时进入工程化。 目标读者 正在做 LLM/RAG/信息抽取的工程师(初级到中级) 负责 AI 产品落地的技术负责人 / 架构师 经常在“写了半天流程,结果不知道抽取效果如何”的同学 背景与动机:为什么这个问题重要? 在传统系统里,大家习惯把“算法”理解为一个函数或模型文件,把“业务”理解为接口与流程。但在 LLM 时代,这个界限变得更模糊: 算法不仅是模型,还包括 prompt、schema、抽取策略、规则归一、置信度与去重策略 算法输出往往是 不确定、需要人类直觉评估 的 如果你把这些“不确定”的东西直接嵌进业务链路(router/service/db/cache),你会遇到: 调试成本爆炸:只看到最后 response,不知道中间发生了什么 逻辑迭代极慢:改一行抽取策略,要跑完整流程 团队协作困难:大家在黑箱里争论“到底准不准” 因此,需要一个更清晰的边界:算法负责收敛中间态,业务负责稳定交付。 核心概念:算法与业务到底分别是什么? 1)算法(Algorithm)的工程定义 算法负责把“模糊世界”压缩成“可用的结构化中间态”。 关键词:不确定性、探索、需要“看结果”、需要收敛。 在投标写作场景中,算法阶段的问题长这样: LLM 抽取出来的 payload 字段应该有哪些? norm_key 怎么设计才代表“同一事实”? 同一人多条命中(mentions)要不要合并? confidence 到底有没有意义?怎么校准? 这些问题的共同特点是:你必须看中间结果才能判断对不对。 2)业务(Business)的工程定义 业务负责在中间态稳定之后,把事情编排起来:什么时候取什么数据、走哪条链路、如何返回给用户。 关键词:确定性、可维护、可测试、可复用。 在投标写作场景中,业务阶段的问题长这样: retrive_type = personnel 时走事实检索,否则走原文档检索 接口响应结构固定,前端按协议渲染 存储从 MemoryTable 换成 DB,不影响上层调用 这些问题的共同特点是:输入输出清晰,错误是边界情况,而不是“我也不知道会不会抽出来”。 一条“贴墙上”的分界线 凡是你还说不清“中间结果长什么样”的阶段 → 用 JupyterLab。 凡是你能画出输入/输出 JSON 形态并写出测试用例的阶段 → 进工程。 实践指南:什么时候用 JupyterLab,什么时候用工程代码? 阶段 1:事实抽取建模期(强制用 JupyterLab) 适用信号: ...

2026年1月7日 · 3 分钟 · map[name:Jeanphilo]