lua-yar 设计文档

July 24, 2026 · View on GitHub

本目录记录 lua-yar 项目开发过程中做出的全部架构与实现决策。每个决策遵循 ADR(Architecture Decision Record)骨架,并辅以业界名言与经典文献,便于读者理解决策的背景、取舍与知识脉络。

设计哲学三原则

lua-yar 是 YAR RPC 协议的纯 Lua 实现,定位为协议库 / SDK,不是运行时框架。三条原则贯穿全部决策:

  1. 纯协议,不绑定运行时 — 协议核心(handle_message)无 I/O、无 yield、可重入,可被任意协程调度器调用。传输层通过 Provider 抽象注入,框架本身不引用 ngx

  2. 零依赖,纯 Lua 实现 — 二进制编解码用纯数学(math.floor / string.char),不依赖 string.pack(Lua 5.1 / LuaJIT 兼容)。JSON、MessagePack 编解码器均为手写,不依赖 cjson / cmsgpack。

  3. 安全默认,可注入扩展ssl_verify 默认 true、max_body_len 默认上限、深度限制 512。所有扩展点(Socket Provider、HTTP Provider、Packager registry、hooks、Log writer)默认关闭或使用安全实现,注入后生效。

模块大纲

41 个设计决策,按 7 个模块组织。每个决策列出驱动因素、名言(中英文对照)、经典文献/标准。看完此大纲即可掌握全貌,无需逐个阅读设计文件。

传输层(transport-layer.md,10 个决策)

#决策驱动因素名言文献
1网络层选型:纯 Lua 优先 + Provider 抽象零依赖、跨运行时"Make it work, make it right, make it fast." — Kent BeckProgramming in Lua (Ierusalimschy); The Pragmatic Programmer (Hunt & Thomas)
2Provider 抽象:socket.lua wrap() + duck typing跨运行时、可注入"Program to an interface, not an implementation." — Gang of FourDesign Patterns (GoF); Patterns of Enterprise Application Architecture (Fowler)
3三层分离:handle_message / handle_connection / run可维护性、可测试性"Separation of concerns." — Edsger DijkstraThe Mythical Man-Month (Brooks); Clean Architecture (Robert Martin)
4HTTP Provider 委托:类级 + 实例级 + 默认手动实现跨运行时、可注入"Dependency Injection is about connecting clients to services." — Martin FowlerInversion of Control (Fowler); Patterns of Enterprise Application Architecture (Fowler)
5HTTPS 支持:ssl_verify 默认 true(Breaking Change)安全性"Secure by default." — 安全工程原则Release It! (Nygard); RFC 2818 HTTP Over TLS
6resolve 选项:自定义 host→IP 映射(curl/PHP 风格)可测试性、可注入"Indirection is the root of all complexity." — Andrew KoenigRFC 7230 HTTP/1.1 Message Syntax; curl 文档
7proxy 选项:HTTP 代理 + HTTPS CONNECT 隧道兼容性"Be liberal in what you accept, conservative in what you send." — Jon PostelRFC 7230 HTTP/1.1 Message Syntax; RFC 7235 Authentication
8persistent 连接:socket 缓存 + 归池性能"The fastest I/O is no I/O." — Mythical Man-MonthRelease It! (Nygard); High Performance MySQL (Zawodny)
9Unix socket:复用 TCP 传输层代码复用"Don't repeat yourself." — Hunt & ThomasThe Pragmatic Programmer (Hunt & Thomas); POSIX Standard
10常量叶子模块:transport/constants.lua可维护性、无循环依赖"Constants should be managed by each package, not centralized." — Lua 业界惯例Programming in Lua (Ierusalimschy); lua-resty-http http_const 模式

服务端层(server-layer.md,8 个决策)

#决策驱动因素名言文献
11packager 自适应:registry + register可扩展性、兼容性"Favor object composition over class inheritance." — Gang of FourDesign Patterns (GoF); Patterns of Enterprise Application Architecture (Fowler)
12body 长度限制:双向校验(server 1MB / framing 10MB)安全性"Defense in depth." — 安全工程原则Release It! (Nygard); OWASP Input Validation
13method memoize:构造时建立方法表性能"Premature optimization is the root of all evil." — Donald KnuthThe Art of Computer Programming (Knuth); Programming in Lua (Ierusalimschy)
14pcall 保护:解析/调用/渲染全包裹健壮性"Fail fast, fail safe." — 工程原则Release It! (Nygard); Site Reliability Engineering (Google)
38服务端并发模型:run() 顺序阻塞,并发交给运行时职责单一、运行时无关"Do one thing and do it well." — Unix 哲学The Art of Unix Programming (Raymond); A Philosophy of Software Design (Ousterhout)
39HTTP 报文构建:常量管理 + table.concat 优化可维护性、性能、一致性"Make the common case fast." — 计算机体系结构原则Programming in Lua (Ierusalimschy); lua-resty-http 源码; RFC 7230 HTTP/1.1 Message Syntax
40构造器参数顺序:service 在前,opts 在后API 易用性、身份属性优先"The most important parameter should come first." — API 设计惯例The Pragmatic Programmer (Hunt & Thomas); API Design for C++ (Reddy)
41handle_message 在 Facade 上的定位:何时用 handle() vs handle_messageAPI 一致性、层次分离、Facade 封装"Program to an interface, not an implementation." — Gang of FourDesign Patterns (GoF); The Art of Unix Programming (Raymond)

协议层(protocol-layer.md,3 个决策)

#决策驱动因素名言文献
15纯数学二进制编解码:Lua 5.1 兼容,不用 string.pack兼容性、零依赖"Simplicity is prerequisite for reliability." — Edsger DijkstraProgramming in Lua (Ierusalimschy); Lua 5.1 Reference Manual
16framing 帧协议:receive_exact + receive_message + check_body_len健壮性、安全性"Validate everything. Trust nothing." — 安全工程原则RFC 6455 WebSocket Framing; RFC 7230 HTTP Message Parsing
17header 校验:82 字节 + magic_num 验证安全性、健壮性"Validate everything. Trust nothing." — 安全工程原则YAR Protocol Spec; RFC 7230 HTTP Message Parsing

打包器层(packager-layer.md,7 个决策)

#决策驱动因素名言文献
18closure 可重入解码器:OpenResty 协程安全健壮性、跨运行时"Functions are first-class citizens." — Lua 设计哲学Programming in Lua (Ierusalimschy); Lua Programming Gems
19IEEE754 双精度编解码:math.frexp/ldexp兼容性、零依赖"Floating point is not real arithmetic." — Gerald SussmanIEEE 754-2019 Standard; What Every Computer Scientist Should Know About Floating-Point Arithmetic (Goldberg 1991)
20深度限制:JSON + Msgpack max_depth 512安全性"Defense in depth." — 安全工程原则RFC 8259 JSON; MessagePack Specification; OWASP Input Validation
21registry/adapter 模式:register + get可扩展性"Favor object composition over class inheritance." — Gang of FourDesign Patterns (GoF); Patterns of Enterprise Application Architecture (Fowler)
22MessagePack str 类型完整支持:fixstr/str8/str16/str32正确性"The devil is in the details." — 工程谚语MessagePack Specification; RFC 8259 JSON
35JSON 字符串快路径:借鉴 dkjson 模式扫描性能"Make it work, make it right, make it fast." — Kent Beckdkjson 2.5 源码 (David Kolf); Programming in Lua (Ierusalimschy)
36int64 负数补码编解码:32 位分块算术避免 2642^{64} 精度丢失正确性、跨运行时"Floating point is not real arithmetic." — Gerald SussmanIEEE 754-2019; What Every Computer Scientist Should Know About Floating-Point Arithmetic (Goldberg 1991)

消息层(message-layer.md,2 个决策)

#决策驱动因素名言文献
23事务 ID 生成:多熵源 + 不自动播种健壮性、库不越权"Setting the seed is the responsibility of the application layer, the library should never set the seed." — Lua 业界惯例 (uuid.lua/Tieske)Programming in Lua (Ierusalimschy); RFC 4122 UUID
24trace_id 拒绝自动生成:应用层职责纯协议库定位"Do one thing and do it well." — Unix 哲学The Art of Unix Programming (Raymond); A Philosophy of Software Design (Ousterhout)

客户端层(client-layer.md,3 个决策)

#决策驱动因素名言文献
25结构化 Error 对象:5 个错误码 + .code 字段可调试性"Errors are values." — Rob PikeA Philosophy of Software Design (Ousterhout); Release It! (Nygard)
26客户端选项设计:对齐 PHP yar 并扩展兼容性、可维护性"Convention over configuration." — Rails 哲学YAR PHP Extension Spec; The Pragmatic Programmer (Hunt & Thomas)
27错误分类:传输层 + 协议层 + 服务端可调试性"Errors are values." — Rob PikeA Philosophy of Software Design (Ousterhout); Site Reliability Engineering (Google)

横切关注点(cross-cutting.md,8 个决策)

#决策驱动因素名言文献
28hooks 机制:on_request/on_response + pcall + 零开销可扩展性、性能"Make the common case fast." — 计算机体系结构原则The Art of Computer Programming (Knuth); Release It! (Nygard)
29日志模块:4 级别 + 可注入 writer可调试性"Logs are for humans." — 运维哲学Site Reliability Engineering (Google); Release It! (Nygard)
30LuaLS 类型标注:22 个源文件全覆盖可维护性"Code is read more often than it is written." — Guido van RossumLuaLS Documentation; The Pragmatic Programmer (Hunt & Thomas)
31跨运行时设计:纯协议核心 + 可注入传输层跨运行时"Portability is the ability to move code from one environment to another." — IEEE 1003.0The Art of Unix Programming (Raymond); POSIX Standard
32纯协议库定位:非运行时框架职责单一"Do one thing and do it well." — Unix 哲学The Art of Unix Programming (Raymond); A Philosophy of Software Design (Ousterhout)
33错误返回形式分层:内部字符串 / RPC 结果结构化 Error 对象可调试性、一致性"Make everything as simple as possible, but not simpler." — Albert EinsteinA Philosophy of Software Design (Ousterhout); Go Blog "Errors are values" (Rob Pike)
34packager 运行时错误从 error() 改为 return nil, err(方案 C)一致性、鲁棒性"Make everything as simple as possible, but not simpler." — Albert EinsteinProgramming in Lua (Ierusalimschy); dkjson 2.5 源码 (Kolf); lua-resty-redis 源码 (agentzh)
37鸭子类型接口的错误处理:对标外部函数签名(pcall 在边界不在内部)一致性、鸭子类型、性能"Program to an interface, not an implementation." — Gang of FourDesign Patterns (GoF); Programming in Lua (Ierusalimschy)

阅读指南

  • 按模块阅读:从你最关心的模块开始,每个文档自成体系。
  • 按决策追踪:每个决策有"关联决策"字段,可顺藤摸瓜理解决策间的依赖关系。
  • 按知识脉络阅读:每个决策末尾列出 2-3 篇经典文献或标准,供深入理解该领域的理论基础。
  • 名言双语对照:每个决策的"思考与取舍"节首引一句业界名言,中英文对照,标注署名。