infrastructure-integrations

基础设施集成

内容服务依赖三块共享基础设施:服务间鉴权、一层 Redis 读缓存、以及 S3/MinIO 对象存储。每一块都被包在各自的适配器里,业务代码只面对一个很小的接口,而不直接面对厂商 SDK。

服务鉴权

每一个进来的 HTTP 请求,都被当作来自另一个内部服务的调用,而不是来自浏览器。一个 Fastify 插件注册了在路由处理器之前运行的 onRequest 钩子。钩子要求带 Authorization: Bearer … 头;没有 bearer token、或 token 无法通过校验的请求,一律以 401 Unauthorized 加一个简短的原因码(missing_token / invalid_token)拒绝。通过校验的 token 会在请求上挂一份小小的鉴权上下文——调用方的服务名加上它的 claims——供处理器读取。

这个 token 是一个紧凑的 HMAC 签名 JWT,携带 service 名以及标准的签发时间 / 过期时间,用服务环境里的一把对称密钥来验证。验证会检查签名,并检查 token 未过期。同一个模块既能签发也能验证,于是一个服务铸造一个短期 token(默认一小时),它的对端来核验。

健康检查路由默认被豁免,注册插件时调用方还可以再传入额外的忽略路径。匹配是带前缀的:一个被忽略的路由同时覆盖它的子路径与带 query 的变体。

Redis 内容缓存

ContentCache 包住 Redis 客户端,只缓存公开读取——已发布的文章(按 id、按 slug、按 alias)以及分类树 / 分类列表。草稿从不缓存;文章的写入方法在条目未发布时直接短路返回,所以未发布内容永远不会从缓存里泄漏出去。键按用途分命名空间(文章用按查询方式区分的前缀,分类树与列表用固定键)。文章缓存五分钟过期,分类十分钟过期。

一致性规则被有意设计成不对称的:

  • 读取失败则软降级。 Redis 报错或超时,在几次短重试之后返回 null,让调用方回落到数据库。缓存宕机损失的是延迟,不是正确性。
  • 写入失败则硬报错。 缓存的 set 与失效操作在重试用尽后抛错,好让"缓存只写了一半"的状态暴露出来,而不是被藏起来。

每一次改动都会失效它所触及的东西:创建、更新、删除、发布、取消发布一篇文章,都会删掉该文章的 id/slug/alias 键;任何分类变更都会清掉分类键。缓存是派生副本;数据库始终是唯一真相来源,写时失效让这份副本不至于变陈旧。

Redis 客户端本身是一个从环境里的连接 URL 惰性创建的单例,带有生命周期日志(连接、就绪、重连、关闭、结束)以及一条干净的关停路径。

S3 / MinIO 存储

媒体文件存放在对象存储里,背后是一个实现了小接口 StoragePortS3StorageAdapter——应用依赖这个 port,而不是 AWS SDK。适配器用 endpoint、bucket、region、公开基础 URL 和一组凭据来配置,并以 path-style 寻址运行,于是同一份代码在开发期跑 MinIO、在生产跑兼容 S3 的存储都成立。

它自己处理供给:ensureBucket 在 head 请求发现 bucket 不存在时创建它;ensurePublicReadPolicy 把公开读取的语句合并进 bucket 策略——只针对存放公开资产的前缀,且只补上尚不存在的语句。上传落在带前缀、抗碰撞的路径下——特色图片在 images/ 前缀下,附件在 attachments/ 下,每个都带一段随机 id——并同时返回存储用的 key 与由配置基础 URL 拼出的公开 URL。下载与删除按这个 key 寻址,找不到的对象会读回 null 而不是报错。

三者如何拼合

这三个适配器共享同一种形状:一个厂商特定的实现藏在一个窄接口后面,各自按任务选择失败语义。鉴权失败即关闭(没 token,不放行)。缓存在读上失败即打开、在写上失败即关闭。存储对自己的初始化是幂等的。服务自身的逻辑对 Fastify 钩子、Redis 重试、S3 bucket 策略一概无感。

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 →

infrastructure-integrations