<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>后端开发规范 on Macula</title><link>https://macula.dev/docs/latest/03_devrules/%E5%90%8E%E7%AB%AF%E5%BC%80%E5%8F%91%E8%A7%84%E8%8C%83/</link><description>Recent content in 后端开发规范 on Macula</description><generator>Hugo</generator><language>zh-cn</language><atom:link href="https://macula.dev/docs/latest/03_devrules/%E5%90%8E%E7%AB%AF%E5%BC%80%E5%8F%91%E8%A7%84%E8%8C%83/index.xml" rel="self" type="application/rss+xml"/><item><title>API规约</title><link>https://macula.dev/docs/latest/03_devrules/%E5%90%8E%E7%AB%AF%E5%BC%80%E5%8F%91%E8%A7%84%E8%8C%83/api%E8%A7%84%E7%BA%A6/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://macula.dev/docs/latest/03_devrules/%E5%90%8E%E7%AB%AF%E5%BC%80%E5%8F%91%E8%A7%84%E8%8C%83/api%E8%A7%84%E7%BA%A6/</guid><description>&lt;blockquote&gt;&#10;&lt;p&gt;本章沿用 5.x 的文档内容，尚未按 latest（当前） 分支核对。涉及依赖、配置或 API 时，请以 &lt;a href="https://github.com/macula-projects/macula-boot/tree/main"&gt;main 分支源码&lt;/a&gt; 为准。&lt;/p&gt;&#10;&lt;/blockquote&gt;&#10;&lt;h2 id="概述"&gt;概述&lt;/h2&gt;&#10;&lt;p&gt;所有软件的UI功能都依赖于后端的API能力输出，规范的API设计以及版本管理对软件功能交付的质量与效率都至关重要。&lt;/p&gt;&#10;&lt;blockquote&gt;&#10;&lt;p&gt;说明：这里的API是指Restful API&lt;/p&gt;&#10;&lt;/blockquote&gt;&#10;&lt;h2 id="设计原则"&gt;设计原则&lt;/h2&gt;&#10;&lt;h3 id="api根url"&gt;API根URL&lt;/h3&gt;&#10;&lt;p&gt;如果预期系统非常庞大，则建议尽量将API部署到独立专用子域名（例如：“api.”）下；如果确定API很简单，不会进一步扩展，则可以考虑放到应用根域名下面（例如，“/api/”）。&lt;/p&gt;&#10;&lt;pre&gt;&lt;code&gt; 独立子域名：https://api.example.com/api/v1/*&#10; 共享应用根域名：https://example.org/[xxx]/api/v1/* （微服务平台一般都是通过网关的统一域名对外）&#10;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;h3 id="api各模块url"&gt;API各模块URL&lt;/h3&gt;&#10;&lt;p&gt;建议每个领域或者Controller统一一个URL根，一般的形式是：/api/v1/[xxx]，xxx表示某个领域模块名称&lt;/p&gt;&#10;&lt;h3 id="uri末尾不要添加"&gt;URI末尾不要添加“/”&lt;/h3&gt;&#10;&lt;p&gt;多一个斜杠，语义完全不同，究竟是目录，还是资源，还是不确定而多做一次301跳转？尽量保持URI结构简洁、语义清晰。&lt;/p&gt;&#10;&lt;pre&gt;&lt;code&gt; 负面case：http://api.canvas.com/api/v1/shapes/&#10; 正面case：http://api.canvas.com/api/v1/shapes&#10;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;h3 id="禁止在url中使用_"&gt;禁止在URL中使用“_”&lt;/h3&gt;&#10;&lt;p&gt;目的是提高可读性，“&lt;em&gt;”可能被文本查看器中的下划线特效遮蔽。建议使用连字符“-”替代下划线“&lt;/em&gt;”,使用“-”提高URI的可读性。&lt;/p&gt;&#10;&lt;pre&gt;&lt;code&gt; 负面case：http://api.example.com/api/v1/blogs/my_first_post&#10; 正面case：http://api.example.com/api/v1/blogs/my-first-post&#10;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;h3 id="禁止使用大写字母"&gt;禁止使用大写字母&lt;/h3&gt;&#10;&lt;p&gt;RFC 3986中规定URI区分大小写，但别用大写字母来为难程序员了，既不美观，又麻烦，同样的原则：建议使用连字符“-”连接不同单词。&lt;/p&gt;&#10;&lt;pre&gt;&lt;code&gt; 负面case：http://api.example.com/api/v1/My-Folder/My-Doc&#10; 正面case：http://api.example.com/api/v1/my-folder/my-doc&#10;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;h3 id="不要在uri中包含扩展名"&gt;不要在URI中包含扩展名&lt;/h3&gt;&#10;&lt;p&gt;应鼓励REST API客户端使用HTTP提供的格式选择机制Accept request header。&lt;/p&gt;&#10;&lt;pre&gt;&lt;code&gt; 负面case：http://api.example.com/api/v1/my-doc/hello.json&#10; 正面case：http://api.example.com/api/v1/my-doc/hello&#10;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;h3 id="建议uri中的名称使用复数"&gt;建议URI中的名称使用复数&lt;/h3&gt;&#10;&lt;p&gt;为了保持URI格式简洁统一，资源在URI中应统一使用复数形式，如需访问资源的一个实例，可以通过资源ID定位（@PathVariable）。&lt;/p&gt;&#10;&lt;pre&gt;&lt;code&gt; 负面case：http://api.college.com/api/v1/student/3248234&#10; 正面case：http://api.college.com/api/v1/students/3248234&#10;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;p&gt;如何处理关联关系？&lt;/p&gt;&#10;&lt;pre&gt;&lt;code&gt; http://api.college.com/api/v1/students/3248234/courses - 检索学生3248234所学习的所有课程&#10; http://api.college.com/api/v1/students/3248234/courses/physics - 检索学生3248234的所学习的物理课程&#10;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;h3 id="建议uri设计时只包含名词"&gt;建议URI设计时只包含名词&lt;/h3&gt;&#10;&lt;p&gt;每个URI代表一种资源或者资源集合，因此，建议只包含名词，不包含动词。&lt;/p&gt;&#10;&lt;pre&gt;&lt;code&gt; 负面case：http://api.example.com/api/v1/get-all-employees&#10; 正面case：http://api.example.com/api/v1/employees&#10;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;p&gt;那么，如何告诉服务器端我们需要进行什么样的操作？CRUD？&lt;/p&gt;</description></item><item><title>应用分层</title><link>https://macula.dev/docs/latest/03_devrules/%E5%90%8E%E7%AB%AF%E5%BC%80%E5%8F%91%E8%A7%84%E8%8C%83/%E5%BA%94%E7%94%A8%E5%88%86%E5%B1%82/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://macula.dev/docs/latest/03_devrules/%E5%90%8E%E7%AB%AF%E5%BC%80%E5%8F%91%E8%A7%84%E8%8C%83/%E5%BA%94%E7%94%A8%E5%88%86%E5%B1%82/</guid><description>&lt;h2 id="分层与依赖方向"&gt;分层与依赖方向&lt;/h2&gt;&#10;&lt;p&gt;业务服务可以采用经典三层作为基础组织方式：&lt;code&gt;Controller → Service → Mapper → 数据库&lt;/code&gt;。Macula 不强制所有业务采用同一种架构；需要领域建模时，可在 Service 内进一步划分应用服务与领域能力，并保持接口和持久化边界清晰。&lt;/p&gt;&#10;&lt;h3 id="分层架构图"&gt;分层架构图&lt;/h3&gt;&#10;&lt;p&gt;&lt;a data-fancybox="gallery" href="../images/model-small.png"&gt;&#10; &lt;img src="../images/model-small.png" alt="经典三层架构" /&gt;&#10;&lt;/a&gt;&#10;&lt;/p&gt;&#10;&lt;h3 id="工程目录"&gt;工程目录&lt;/h3&gt;&#10;&lt;p&gt;&lt;a data-fancybox="gallery" href="../images/structure.png"&gt;&#10; &lt;img src="../images/structure.png" alt="应用工程目录" /&gt;&#10;&lt;/a&gt;&#10;&lt;/p&gt;&#10;&lt;h3 id="各层职责"&gt;各层职责&lt;/h3&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;层次&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;负责什么&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;约束&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Controller&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;HTTP 适配、输入校验、调用 Service&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;不直接访问 Mapper，不放复杂业务规则&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Service / impl&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;业务规则、操作编排、事务&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;需要原子性时在公开方法声明事务，明确回滚条件&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Mapper&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;数据访问与查询条件&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;使用参数绑定，限定分页、租户与数据范围&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Converter&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;各层模型转换&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;沿用 MapStruct，减少手工字段复制&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;Controller 返回业务对象，由 Web Starter 统一封装 Result；不要重复包装或吞掉应交给统一异常处理的异常。查询与写操作分别验证权限，不能依靠前端隐藏按钮控制访问。&lt;/p&gt;&#10;&lt;h2 id="模型对象约定"&gt;模型对象约定&lt;/h2&gt;&#10;&lt;p&gt;各层模型的传递关系如下：&lt;/p&gt;&#10;&lt;p&gt;&lt;a data-fancybox="gallery" href="../images/layer-model.png"&gt;&#10; &lt;img src="../images/layer-model.png" alt="各层模型对象传递关系" /&gt;&#10;&lt;/a&gt;&#10;&lt;/p&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;模型&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;用途&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;边界&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Query&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;查询条件、分页与排序&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;可传递至 Service、Mapper；限制任意排序与无限结果集&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Form&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;新增、更新等写入请求&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;接入 Bean Validation，不直接作为数据库实体&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;DTO&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;跨层或跨服务传输&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;只暴露调用方需要的字段&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;VO&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;面向调用方的展示结果&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;避免泄漏数据库字段与内部实现&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;BO&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;组合查询或业务处理对象&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;用于业务层与组合查询，不默认成为公共接口&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Entity&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;数据库表映射&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;留在持久化边界内，不作为新增 REST / Feign 公共契约&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;不要直接将客户端提供的租户、角色或身份字段当作可信上下文。身份来自已验证的认证信息，数据范围在服务端查询中落实。&lt;/p&gt;</description></item><item><title>微服务规约</title><link>https://macula.dev/docs/latest/03_devrules/%E5%90%8E%E7%AB%AF%E5%BC%80%E5%8F%91%E8%A7%84%E8%8C%83/%E5%BE%AE%E6%9C%8D%E5%8A%A1%E8%A7%84%E7%BA%A6/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://macula.dev/docs/latest/03_devrules/%E5%90%8E%E7%AB%AF%E5%BC%80%E5%8F%91%E8%A7%84%E8%8C%83/%E5%BE%AE%E6%9C%8D%E5%8A%A1%E8%A7%84%E7%BA%A6/</guid><description>&lt;blockquote&gt;&#10;&lt;p&gt;本章沿用 5.x 的文档内容，尚未按 latest（当前） 分支核对。涉及依赖、配置或 API 时，请以 &lt;a href="https://github.com/macula-projects/macula-boot/tree/main"&gt;main 分支源码&lt;/a&gt; 为准。&lt;/p&gt;&#10;&lt;/blockquote&gt;&#10;&lt;h2 id="概述"&gt;概述&lt;/h2&gt;&#10;&lt;p&gt;一个微服务平台由多个模块组成，我们经过长期实践总结出一套各模块的命名规范。&lt;/p&gt;&#10;&lt;h2 id="微服务架构"&gt;微服务架构&lt;/h2&gt;&#10;&lt;p&gt;&lt;a data-fancybox="gallery" href="../images/microservice3.png"&gt;&#10; &lt;img src="../images/microservice3.png" alt="架构" /&gt;&#10;&lt;/a&gt;&#10;&lt;/p&gt;&#10;&lt;h2 id="工程目录"&gt;工程目录&lt;/h2&gt;&#10;&lt;p&gt;&lt;a data-fancybox="gallery" href="../images/mca-archetype.png"&gt;&#10; &lt;img src="../images/mca-archetype.png" alt="工程结构" /&gt;&#10;&lt;/a&gt;&#10;&lt;/p&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;模块名称&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;说明&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;macula-samples-parent&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;父工程，定义maven依赖&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;macula-samples-gateway&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;微服务网关&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;macula-samples-admin-bff&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;管理控制台的API，聚合微服务层的接口，不会作为微服务给其他模块访问&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;macula-samples-openapi&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;给第三方平台访问的开放API&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;macula-samples-xxx-bff&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;其他前端的API层，不同前端不同的BFF模块&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;macula-samples-basic&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;微服务模块，用于基础的服务，可选项&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;macula-samples-thirdparty&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;微服务模块，用于集中访问第三方系统，防腐&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;macula-samples-[service1]…&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;具体各个业务的微服务模块，按照领域命名&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;macula-samples-api&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;微服务模块的对外SDK，其中定义了其他模块访问该模块的接口以及POJO类。&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;macula-samples-basic-api&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;basic模块的sdk&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;macula-samples-[service1]-api&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;[service1]模块的sdk&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;</description></item><item><title>环境与配置</title><link>https://macula.dev/docs/latest/03_devrules/%E5%90%8E%E7%AB%AF%E5%BC%80%E5%8F%91%E8%A7%84%E8%8C%83/%E7%8E%AF%E5%A2%83%E4%B8%8E%E9%85%8D%E7%BD%AE/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://macula.dev/docs/latest/03_devrules/%E5%90%8E%E7%AB%AF%E5%BC%80%E5%8F%91%E8%A7%84%E8%8C%83/%E7%8E%AF%E5%A2%83%E4%B8%8E%E9%85%8D%E7%BD%AE/</guid><description>&lt;p&gt;后端配置以 Macula Samples 当前的 &lt;code&gt;application.yml&lt;/code&gt; 组织方式为例：公共段定义应用结构与配置导入，local 提供 IDE 本地值，docker 覆盖容器差异，共享环境通过 Nacos 管理业务配置。&lt;/p&gt;&#10;&lt;p&gt;完整约定、可复制的 YAML 骨架、认证地址与变量说明统一维护在&lt;a href="https://macula.dev/docs/latest/04_devmanual/%E5%BA%94%E7%94%A8%E9%85%8D%E7%BD%AE/"&gt;application.yml 配置规范&lt;/a&gt;。&lt;/p&gt;&#10;&lt;p&gt;重点区分 Gateway 验证 IAM Token、BFF 访问 Cloud System、非网关服务验证 Samples Gateway JWT 三个方向。Java / IDE、Compose 和 Vite 对 &lt;code&gt;.env&lt;/code&gt; 的读取方式也分别按该页说明配置。&lt;/p&gt;</description></item><item><title>Redis规约</title><link>https://macula.dev/docs/latest/03_devrules/%E5%90%8E%E7%AB%AF%E5%BC%80%E5%8F%91%E8%A7%84%E8%8C%83/redis%E8%A7%84%E7%BA%A6/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://macula.dev/docs/latest/03_devrules/%E5%90%8E%E7%AB%AF%E5%BC%80%E5%8F%91%E8%A7%84%E8%8C%83/redis%E8%A7%84%E7%BA%A6/</guid><description>&lt;blockquote&gt;&#10;&lt;p&gt;本章沿用 5.x 的文档内容，尚未按 latest（当前） 分支核对。涉及依赖、配置或 API 时，请以 &lt;a href="https://github.com/macula-projects/macula-boot/tree/main"&gt;main 分支源码&lt;/a&gt; 为准。&lt;/p&gt;&#10;&lt;/blockquote&gt;&#10;&lt;h2 id="概述"&gt;概述&lt;/h2&gt;&#10;&lt;p&gt;Redis目前已经是应对高并发、高性能场景系统设计的标配了，以下主要从键值设计、命令使用两方面对Redis的开发规范进行说明。&lt;/p&gt;&#10;&lt;h2 id="键值设计"&gt;键值设计&lt;/h2&gt;&#10;&lt;h3 id="key名设计"&gt;key名设计&lt;/h3&gt;&#10;&lt;p&gt;(1)【建议】: 可读性和可管理性&lt;/p&gt;&#10;&lt;pre&gt;&lt;code&gt;以业务名(或数据库名)为前缀(防止key冲突)，用冒号分隔，例如：&#10;&#10;业务名:表名:id&#10;ugc:video:1&#10;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;p&gt;(2)【建议】：简洁性&lt;/p&gt;&#10;&lt;pre&gt;&lt;code&gt;保证语义的前提下，控制key的长度，当key较多时，内存占用也不容忽视，例如：&#10;&#10;user:{uid}:friends:messages:{mid}简化为u:{uid}:fr:m:{mid}&#10;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;p&gt;(3)【强制】：不要包含特殊字符&lt;/p&gt;&#10;&lt;pre&gt;&lt;code&gt;反例：包含空格、换行、单双引号以及其他转义字符&#10;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;h3 id="value值设计"&gt;value值设计&lt;/h3&gt;&#10;&lt;p&gt;(1)【强制】：拒绝bigkey(防止网卡流量、慢查询)&lt;/p&gt;&#10;&lt;pre&gt;&lt;code&gt;string类型控制在10KB以内，hash、list、set、zset元素个数不要超过5000。&#10;&#10;反例：一个包含200万个元素的list。&#10;&#10;非字符串的bigkey，不要使用del删除，使用hscan、sscan、zscan方式渐进式删除，同时要注意防止bigkey过期时间自动删除问题(例如一个200万的zset设置1小时过期，会触发del操作，造成阻塞，而且该操作不会不出现在慢查询中(latency可查))，查找方法和删除方法&#10;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;p&gt;(2)【推荐】：选择适合的数据类型&lt;/p&gt;&#10;&lt;pre&gt;&lt;code&gt;例如：实体类型(要合理控制和使用数据结构内存编码优化配置,例如ziplist，但也要注意节省内存和性能之间的平衡)&#10;&#10;反例：&#10; set user:1:name tom&#10; set user:1:age 19&#10; set user:1:favor football&#10; &#10;正例:&#10; hmset user:1 name tom age 19 favor football&#10;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;p&gt;(3)【推荐】：控制key的生命周期，redis不是垃圾桶&lt;/p&gt;&#10;&lt;pre&gt;&lt;code&gt; 建议使用expire设置过期时间(条件允许可以打散过期时间，防止集中过期)，不过期的数据重点关注idletime&#10;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;h2 id="命令使用"&gt;命令使用&lt;/h2&gt;&#10;&lt;p&gt;1.【推荐】 O(N)命令关注N的数量&lt;/p&gt;&#10;&lt;pre&gt;&lt;code&gt;例如hgetall、lrange、smembers、zrange、sinter等并非不能使用，但是需要明确N的值。有遍历的需求可以使用hscan、sscan、zscan代替。&#10;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;p&gt;2.【推荐】：禁用命令&lt;/p&gt;&#10;&lt;pre&gt;&lt;code&gt;禁止线上使用keys、flushall、flushdb等，通过redis的rename机制禁掉命令，或者使用scan的方式渐进式处理。&#10;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;p&gt;3.【推荐】合理使用select&lt;/p&gt;&#10;&lt;pre&gt;&lt;code&gt;redis的多数据库较弱，使用数字进行区分，很多客户端支持较差，同时多业务用多数据库实际还是单线程处理，会有干扰。&#10;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;p&gt;4.【推荐】使用批量操作提高效率&lt;/p&gt;</description></item><item><title>RocketMQ规约</title><link>https://macula.dev/docs/latest/03_devrules/%E5%90%8E%E7%AB%AF%E5%BC%80%E5%8F%91%E8%A7%84%E8%8C%83/rocketmq%E8%A7%84%E7%BA%A6/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://macula.dev/docs/latest/03_devrules/%E5%90%8E%E7%AB%AF%E5%BC%80%E5%8F%91%E8%A7%84%E8%8C%83/rocketmq%E8%A7%84%E7%BA%A6/</guid><description>&lt;blockquote&gt;&#10;&lt;p&gt;本章沿用 5.x 的文档内容，尚未按 latest（当前） 分支核对。涉及依赖、配置或 API 时，请以 &lt;a href="https://github.com/macula-projects/macula-boot/tree/main"&gt;main 分支源码&lt;/a&gt; 为准。&lt;/p&gt;&#10;&lt;/blockquote&gt;&#10;&lt;h2 id="命名规范"&gt;命名规范&lt;/h2&gt;&#10;&lt;p&gt;1、【强制】Topic命名：topic+下划线+业务名，例如：订单领域topic命名为：topic_order。&lt;/p&gt;&#10;&lt;p&gt;2、【强制】tag命名：tag+下划线+业务动作，比如：订单创建的tag为：tag_create；订单关闭的tag为：tag_close。&lt;/p&gt;&#10;&lt;p&gt;3、【强制】生产者分组命名：pg+下划线+业务名,例如：订单创建生产者发送订单创建消息，那么生产者分组名为：pg_order&lt;/p&gt;&#10;&lt;p&gt;4、【强制】消费者分组命名：cg+下划线+业务名+下划线+订阅topic名称+下划线+订阅tag名称。&lt;/p&gt;&#10;&lt;p&gt;例如：订单创建消息topic为topic_order，tag为tag_create，消息生产者为订单服务，用户服务和支付服务需要消费这条消息，那么用户服务的消费者分组命名为cg_user_order_create，支付服务的消费者分组命名为cg_payment_order_create。&lt;/p&gt;&#10;&lt;h2 id="使用规范"&gt;使用规范&lt;/h2&gt;&#10;&lt;h3 id="生产者"&gt;生产者&lt;/h3&gt;&#10;&lt;p&gt;2.1【强制】一个领域服务只能有一个topic。&lt;/p&gt;&#10;&lt;p&gt;2.2【强制】领域服务发送消息时必须根据业务动作设置tag。&lt;/p&gt;&#10;&lt;p&gt;2.3【强制】在Producer发送消息时必须设置keys。&lt;/p&gt;&#10;&lt;p&gt;2.4【强制】​消息发送成功或者失败要打印消息日志，务必要打印SendResult和key字段。&lt;/p&gt;&#10;&lt;p&gt;2.5【建议】消息发送失败后建议将消息存储到db，然后由定时器类线程进行定时重试，确保消息达到broker。&lt;/p&gt;&#10;&lt;p&gt;2.6【建议】对于可靠性要求不高的业务场景可以使用oneway消息。&lt;/p&gt;&#10;&lt;p&gt;2.7 【强制】新建生产者时必须指定生产者分组。&lt;/p&gt;&#10;&lt;h3 id="消费者"&gt;消费者&lt;/h3&gt;&#10;&lt;p&gt;2.8【强制】新建消费者时必须指定消费者分组。&lt;/p&gt;&#10;&lt;p&gt;2.9【强制】消息消费者无法避免消息重复，所以需要业务服务来保证消息消费幂等。&lt;/p&gt;&#10;&lt;p&gt;2.10【建议】为了提高消费并行度，可以在同一个ConsumerGroup下启动多个Consumer实例或者通过修改ConsumeThreadMin和consumeThreadMax来提高单个Consumer的并行消费能力。&lt;/p&gt;&#10;&lt;p&gt;2.11【建议】为了增加业务吞吐量，可以通过设置consumer的consumeMessageBatchMaxSize来批量消费消息。&lt;/p&gt;&#10;&lt;p&gt;2.12 【建议】发生消息堆积时，如果业务对数据要求不高时，可以选择丢弃不重要的消息。&lt;/p&gt;&#10;&lt;p&gt;2.13【建议】如果消息量较少，建议在消费入口打印消息、消费耗时等，方便后续排查问题。&lt;/p&gt;&#10;&lt;h2 id="申请规范"&gt;申请规范&lt;/h2&gt;&#10;&lt;p&gt;3.1 【强制】在新建topic时必须进行申请，申请形式为：填写申请表，评审通过方可使用&lt;/p&gt;&#10;&lt;h2 id="参考"&gt;参考&lt;/h2&gt;&#10;&lt;p&gt;4.1 &lt;a href="https://github.com/apache/rocketmq/blob/master/docs/cn/best_practice.md"&gt;RocketMQ最佳实践&lt;/a&gt;&lt;/p&gt;</description></item></channel></rss>