2026-09-23·by Sijie Wang#lucerna#software#architecture

backends-three-services

三服务后端拆分

上级:key-designs

三个可以分别独立部署的服务,按职责和语言拆分:

auth(Go/echo,约 2.7k 行代码)——只管身份。 这是一个独立的微服务,包装了 AppwritePOST /api/v1/auth/{login,register,logout,guest,recovery,recovery/reset}GET/PUT/DELETE /me,以及一个清理游客账号的定时任务(/cron/cleanup-guests,清理超过 24 小时的游客)。会话用 HttpOnly cookie(internal/cookie);编排逻辑把 Appwrite REST 调用和一次 MainBackend 用户清除调用组合在一起,所以删除账号会级联清除。它被刻意与领域 API 分开。

mainbackend(Go/echo + pgx + google/wire,约 12.6k 行代码)——领域 API 与持久化层。 15 个路由组:booksbookmarksnotesvocabulary(外加处理全部词形的 PATCH /:id/forms)、reading_prefsbook_settingscatalog/catalog_bytes/coversdictionary(L2 共享词条缓存)、reviewclient_logsinternal_purgehealth。它是离线优先 outbox 的服务端对应物offline-first-outbox)——对重复写入是幂等的,所以被重放的 outbox 条目是安全的——并且它拥有 SRS:SM-2 调度器就在这里(internal/domain/review/srs.go),而不在客户端,这样 web/desktop 之间的复习计划才能保持一致、无法被作弊(vocabulary-loop)。

nlp-api(Python/FastAPI + spaCy,约 3.6k 行代码)——确定性的语言学处理 + 重型摄取。 /tokenize/lookup/structure(依存句法分析语法)、/translate 引擎(linguistic-two-engines)——再加上处理客户端处理不了的扫描版书籍的 PDF/OCR 摄取路由/parse-pdf/ocr-images,用 Tesseract)(upload-ingestion)。

为什么这样拆分: 身份认证的安全性与生命周期需求和领域逻辑不同(所以独立成服务);语言学处理需要 Python 的 NLP 生态(spaCy、Tesseract、NLLB),没法放进 Go 层;这样 Go 领域 API 就能保持是一个干净的、用 wire 做依赖注入的持久化层。@lucerna/core 中的依赖反转(cross-platform-seams)意味着各个 shell 只把这三者看成基于 HTTP 的仓储接口。

(i18n 说明:产品发布了 11 种语言—— en, de, es, fr, ja, ko, nl, pt, zh, zh-HK ——作为 core/src/i18n/ 中的完整翻译词典,通过 core 以 UI 无关的方式被使用;机制上很简单,但覆盖面很广。)

about this entry

One of sijie's wiki entries. The AI on this site is grounded in the same corpus and answers in sijie's voice, with citations back to entries like this one — answering costs sijie money, so it waits behind a code: enter an access code →