<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>后端设计 on 飞天造物手记</title><link>https://roper.cool/tags/%E5%90%8E%E7%AB%AF%E8%AE%BE%E8%AE%A1/</link><description>Recent content in 后端设计 on 飞天造物手记</description><generator>Hugo -- gohugo.io</generator><language>zh-cn</language><lastBuildDate>Wed, 27 May 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://roper.cool/tags/%E5%90%8E%E7%AB%AF%E8%AE%BE%E8%AE%A1/index.xml" rel="self" type="application/rss+xml"/><item><title>微信小程序后端接口设计备忘：从登录态、幂等到灰度发布</title><link>https://roper.cool/posts/small-program-backend-notes/</link><pubDate>Wed, 27 May 2026 00:00:00 +0000</pubDate><guid>https://roper.cool/posts/small-program-backend-notes/</guid><description>&lt;p&gt;最近在规划一个自研微信小程序时，我把后端接口层重新梳理了一遍。项目规模不大，但越是个人项目，越容易因为“先跑起来再说”而把一些基础约定欠下来。等功能多了，再回头补登录态、幂等、审计和灰度，成本会变得很高。&lt;/p&gt;
&lt;p&gt;这篇是我给自己写的一份备忘，目标不是追求大而全，而是用适合个人开发节奏的方式，先把最容易失控的部分定住。&lt;/p&gt;
&lt;h2 id="1-登录态不要只停留在能拿到-openid"&gt;&lt;a href="#1-%e7%99%bb%e5%bd%95%e6%80%81%e4%b8%8d%e8%a6%81%e5%8f%aa%e5%81%9c%e7%95%99%e5%9c%a8%e8%83%bd%e6%8b%bf%e5%88%b0-openid" class="header-anchor"&gt;&lt;/a&gt;1. 登录态不要只停留在“能拿到 openid”
&lt;/h2&gt;&lt;p&gt;很多小程序后端的第一步，是前端调用 &lt;code&gt;wx.login()&lt;/code&gt; 拿到 code，然后服务端去微信侧换取 &lt;code&gt;openid&lt;/code&gt; 和 &lt;code&gt;session_key&lt;/code&gt;。这个流程本身没问题，但如果系统设计停在“库里有个 openid 字段”，后面就会遇到几个问题：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;无法区分设备会话。&lt;/li&gt;
&lt;li&gt;登录态刷新策略模糊。&lt;/li&gt;
&lt;li&gt;服务端日志里缺少可追踪的用户会话标识。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;我现在更倾向于把微信登录理解为“身份证明的上游输入”，而不是最终会话本身。服务端在拿到 openid 后，仍然要自己签发应用侧 session token，并且把 token 生命周期、刷新机制、失效策略设计清楚。&lt;/p&gt;
&lt;p&gt;对个人项目来说，不一定要一上来就做复杂的 OAuth 体系，但至少要做到：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;应用会话与微信 code 交换流程解耦。&lt;/li&gt;
&lt;li&gt;token 过期时间可配置。&lt;/li&gt;
&lt;li&gt;敏感接口在服务端统一校验，不依赖前端状态判断。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="2-写接口时尽早考虑幂等"&gt;&lt;a href="#2-%e5%86%99%e6%8e%a5%e5%8f%a3%e6%97%b6%e5%b0%bd%e6%97%a9%e8%80%83%e8%99%91%e5%b9%82%e7%ad%89" class="header-anchor"&gt;&lt;/a&gt;2. 写接口时尽早考虑幂等
&lt;/h2&gt;&lt;p&gt;我以前做小程序时，最容易忽视的一件事就是重复点击。移动网络环境比桌面网页更容易出现超时重试、弱网抖动和用户反复点击提交按钮的情况。如果创建订单、保存记录、发起任务这些操作没有幂等保护，就很容易出现重复数据。&lt;/p&gt;
&lt;p&gt;这次我给自己定的规则很简单：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;只要是“有副作用”的写操作，都要先问一句：它是否可能被重复提交？&lt;/li&gt;
&lt;li&gt;如果答案是可能，就给它设计幂等键。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;幂等键不一定非要上复杂中间件。个人项目起步阶段，用请求头传一个 &lt;code&gt;Idempotency-Key&lt;/code&gt;，配合数据库唯一约束和短期结果缓存，就能解决大部分问题。重点是思维上先意识到“重复请求不是边缘情况，而是默认要处理的情况”。&lt;/p&gt;
&lt;h2 id="3-返回结构统一比字段名优雅更重要"&gt;&lt;a href="#3-%e8%bf%94%e5%9b%9e%e7%bb%93%e6%9e%84%e7%bb%9f%e4%b8%80%e6%af%94%e5%ad%97%e6%ae%b5%e5%90%8d%e4%bc%98%e9%9b%85%e6%9b%b4%e9%87%8d%e8%a6%81" class="header-anchor"&gt;&lt;/a&gt;3. 返回结构统一比字段名优雅更重要
&lt;/h2&gt;&lt;p&gt;个人项目常见的演进路径是：先写一个接口，能返回数据就行；第二个接口复制前一个；第三个接口开始出现不同风格的错误码和 message 字段。等前端页面多起来，联调成本会明显上升。&lt;/p&gt;
&lt;p&gt;所以我这次先把返回包格式固定下来：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;requestId&lt;/code&gt;：用于日志追踪。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;code&lt;/code&gt;：业务状态码。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;message&lt;/code&gt;：给前端展示或记录的可读信息。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;data&lt;/code&gt;：真正业务数据。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;哪怕前期只有自己一个人开发，这种统一也很有价值。因为几周之后再回来看代码，“未来的自己”其实就已经像另一个协作者了。&lt;/p&gt;
&lt;h2 id="4-灰度和配置开关比想象中更早需要"&gt;&lt;a href="#4-%e7%81%b0%e5%ba%a6%e5%92%8c%e9%85%8d%e7%bd%ae%e5%bc%80%e5%85%b3%e6%af%94%e6%83%b3%e8%b1%a1%e4%b8%ad%e6%9b%b4%e6%97%a9%e9%9c%80%e8%a6%81" class="header-anchor"&gt;&lt;/a&gt;4. 灰度和配置开关比想象中更早需要
&lt;/h2&gt;&lt;p&gt;以前我总觉得灰度发布是大团队才需要的能力。后来发现只要产品要上线给真实用户用，即使只有几十个用户，灰度依然非常有帮助。&lt;/p&gt;
&lt;p&gt;最简单的灰度能力可以从配置中心思维开始，而不一定是完整平台：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;某个功能是否对所有用户开放。&lt;/li&gt;
&lt;li&gt;某个实验参数是否分组生效。&lt;/li&gt;
&lt;li&gt;某个接口是否暂时降级到旧逻辑。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;如果把这些判断都硬编码在业务逻辑里，后面会很难收拾。哪怕只是做一个数据库配置表，或者一份受控的远程配置，也比每次上线改代码再发版灵活很多。&lt;/p&gt;
&lt;h2 id="5-审计与日志从第一天就值得做"&gt;&lt;a href="#5-%e5%ae%a1%e8%ae%a1%e4%b8%8e%e6%97%a5%e5%bf%97%e4%bb%8e%e7%ac%ac%e4%b8%80%e5%a4%a9%e5%b0%b1%e5%80%bc%e5%be%97%e5%81%9a" class="header-anchor"&gt;&lt;/a&gt;5. 审计与日志从第一天就值得做
&lt;/h2&gt;&lt;p&gt;个人项目往往没有专门的运维体系，所以出问题时更依赖日志。我的经验是，日志不需要特别花哨，但一定要在关键链路上可串联。&lt;/p&gt;
&lt;p&gt;我现在至少会记录这些信息：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;requestId&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;用户标识或匿名会话标识&lt;/li&gt;
&lt;li&gt;接口耗时&lt;/li&gt;
&lt;li&gt;核心参数摘要&lt;/li&gt;
&lt;li&gt;下游调用结果&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;另外，对管理后台操作、配置变更、任务重试这类动作，我会额外留审计日志。原因很简单：一旦某条数据异常，先弄清“是谁在什么时候以什么方式改过它”，排查效率会高很多。&lt;/p&gt;
&lt;h2 id="6-当前阶段最适合个人项目的取舍"&gt;&lt;a href="#6-%e5%bd%93%e5%89%8d%e9%98%b6%e6%ae%b5%e6%9c%80%e9%80%82%e5%90%88%e4%b8%aa%e4%ba%ba%e9%a1%b9%e7%9b%ae%e7%9a%84%e5%8f%96%e8%88%8d" class="header-anchor"&gt;&lt;/a&gt;6. 当前阶段最适合个人项目的取舍
&lt;/h2&gt;&lt;p&gt;最后总结一下，我认为个人开发的小程序后端在第一阶段最值得优先做的是：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;登录态独立成应用会话。&lt;/li&gt;
&lt;li&gt;写操作具备基本幂等能力。&lt;/li&gt;
&lt;li&gt;返回结构统一。&lt;/li&gt;
&lt;li&gt;关键日志可追踪。&lt;/li&gt;
&lt;li&gt;留出配置开关和灰度空间。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;这些工作看起来不像业务功能那样“立刻可见”，但它们直接决定项目后面是轻松迭代，还是每加一个功能都担心把旧逻辑带崩。对长期维护的网站和后续小程序、小游戏来说，这些地基越早打，收益越大。&lt;/p&gt;</description></item></channel></rss>