<?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/5.x/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/5.x/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/5.x/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/5.x/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;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;&#10;&lt;p&gt;答案是由HTTP动词表示。&lt;/p&gt;&#10;&lt;pre&gt;&lt;code&gt; GET（SELECT）：从服务器取出资源（一项或多项）。&#10; POST（CREATE）：在服务器新建一个资源。&#10; PUT（UPDATE）：在服务器更新资源（客户端提供改变后的完整资源）。&#10; PATCH（UPDATE）：在服务器更新资源（客户端提供改变的属性）。&#10; DELETE（DELETE）：从服务器删除资源。&#10;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;h3 id="禁止由第三方开发人员任意指定约束条件"&gt;禁止由第三方开发人员任意指定约束条件&lt;/h3&gt;&#10;&lt;p&gt;非常重要的一点：禁止让第三方开发人员自己任意指定排序过滤器、返回结果集的约束条件。强烈建议服务器端设置默认单页数量，如果无限制，很可能造成服务器资源及网络资源过度消耗，响应缓慢，网络丢包等异常情况。&lt;/p&gt;</description></item><item><title>应用分层</title><link>https://macula.dev/docs/5.x/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/5.x/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;关于应用的分层架构，长期以来使用最广的就是经典三层架构（UI展示层，BLL业务逻辑层，DAL数据访问层），近几年DDD的架构逐步兴起（接口层、应用服务层、领域服务层和基础设施层）。以下主要对经典三层架构及其模型对象进行说明（Macula没有强制使用哪种分层架构，看具体的场景和团队情况选择适合的分层架构即可）。&lt;/p&gt;&#10;&lt;h2 id="经典三层架构"&gt;经典三层架构&lt;/h2&gt;&#10;&lt;h3 id="架构图"&gt;架构图&lt;/h3&gt;&#10;&lt;p&gt;经典三层架构如下图所示：&lt;/p&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="image" /&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="image" /&gt;&#10;&lt;/a&gt;&#10;&lt;/p&gt;&#10;&lt;h3 id="各层规约"&gt;各层规约&lt;/h3&gt;&#10;&lt;h4 id="展示层"&gt;展示层&lt;/h4&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;【强制】Controller方法不要直接返回Result包裹类，框架会根据返回结果自动封装为Result结构返回，具体见&lt;a href="../../../../01_services/%E6%A1%86%E6%9E%B6%E5%9F%BA%E7%A1%80/web"&gt;Macula Boot Starter Web&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;【强制】Controller方法体里面不要编写业务逻辑，只做简单的Service方法的编排&lt;/li&gt;&#10;&lt;li&gt;【推荐】Controller方法参数建议添加@Validated注解，用于参数校验&lt;/li&gt;&#10;&lt;li&gt;【强制】Controller方法不要吃掉异常，如果没有特殊需要，直接抛出服务层异常即可&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;h4 id="业务逻辑层"&gt;业务逻辑层&lt;/h4&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;【强制】Service方法需要考虑事务，一个Service方法应该是事务一致的&lt;/li&gt;&#10;&lt;li&gt;【强制】Service方法需要根据错误情况抛出对应异常，抛出的异常要继承自BizException&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;h4 id="数据存取层"&gt;数据存取层&lt;/h4&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;【推荐】建议使用mybatis-plus或者jpa框架&lt;/li&gt;&#10;&lt;li&gt;【强制】不要通过拼接字符串的方式编写SQL&lt;/li&gt;&#10;&lt;li&gt;【强制】不要在Java代码中拼接SQL&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;h4 id="各层对象传递说明queryformdtovoboentity"&gt;各层对象传递说明(Query,Form,DTO,VO,BO,Entity)&lt;/h4&gt;&#10;&lt;p&gt;业内涉及分层架构的模型对象多种多样，如VO、DTO、AO、BO、PO、DO、Entity等，但大家的理解和用法各异。在此，Macula选取以下模型并明确定义其使用场景，如下图所示：&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="image" /&gt;&#10;&lt;/a&gt;&#10;&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;Query查询对象：查询的时候使用，可以透传Controller，Service，Mapper三层&lt;/li&gt;&#10;&lt;li&gt;Form表单对象和DTO传输对象：更新的时候使用&lt;/li&gt;&#10;&lt;li&gt;VO视图对象：返回结果的时候使用&lt;/li&gt;&#10;&lt;li&gt;BO业务对象：由SQL联合多表查询返回的对象，或者由多个Entity组合的对象&lt;/li&gt;&#10;&lt;li&gt;Entity实体对象：与数据库表一一对应的实体对象，与PO等价&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;以上模型对象的定义和使用，同样适用于平台内部微服务间的调用以及跨平台的openapi交互场景。如下图所示：&lt;/p&gt;&#10;&lt;p&gt;&lt;a data-fancybox="gallery" href="../images/model2.png"&gt;&#10; &lt;img src="../images/model2.png" alt="image" /&gt;&#10;&lt;/a&gt;&#10;&lt;/p&gt;&#10;&lt;p&gt;详细样例请看：https://github.com/macula-projects/macula-samples&lt;/p&gt;&#10;&lt;h2 id="ddd架构"&gt;DDD架构&lt;/h2&gt;&#10;&lt;p&gt;TODO&lt;/p&gt;</description></item><item><title>微服务规约</title><link>https://macula.dev/docs/5.x/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/5.x/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;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/5.x/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/5.x/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;h2 id="环境定义"&gt;环境定义&lt;/h2&gt;&#10;&lt;p&gt;每套系统都要经过开发、测试、准生产、性能测试等阶段，需要定义一套标准。具体见&lt;a href="../../../%E5%9F%BA%E6%9C%AC%E5%BC%80%E5%8F%91%E8%A7%84%E8%8C%83/environment"&gt;基本开发规范&lt;/a&gt;&lt;/p&gt;&#10;&lt;h2 id="pom配置"&gt;POM配置&lt;/h2&gt;&#10;&lt;p&gt;在parent模块中定义了环境&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-xml" data-lang="xml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#204a87;font-weight:bold"&gt;&amp;lt;profiles&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#204a87;font-weight:bold"&gt;&amp;lt;profile&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#204a87;font-weight:bold"&gt;&amp;lt;id&amp;gt;&lt;/span&gt;local&lt;span style="color:#204a87;font-weight:bold"&gt;&amp;lt;/id&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#204a87;font-weight:bold"&gt;&amp;lt;activation&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#204a87;font-weight:bold"&gt;&amp;lt;activeByDefault&amp;gt;&lt;/span&gt;true&lt;span style="color:#204a87;font-weight:bold"&gt;&amp;lt;/activeByDefault&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#204a87;font-weight:bold"&gt;&amp;lt;/activation&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#204a87;font-weight:bold"&gt;&amp;lt;properties&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#204a87;font-weight:bold"&gt;&amp;lt;profile.active&amp;gt;&lt;/span&gt;local&lt;span style="color:#204a87;font-weight:bold"&gt;&amp;lt;/profile.active&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#204a87;font-weight:bold"&gt;&amp;lt;/properties&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#204a87;font-weight:bold"&gt;&amp;lt;/profile&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#204a87;font-weight:bold"&gt;&amp;lt;profile&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#204a87;font-weight:bold"&gt;&amp;lt;id&amp;gt;&lt;/span&gt;dev&lt;span style="color:#204a87;font-weight:bold"&gt;&amp;lt;/id&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#204a87;font-weight:bold"&gt;&amp;lt;properties&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#204a87;font-weight:bold"&gt;&amp;lt;profile.active&amp;gt;&lt;/span&gt;dev&lt;span style="color:#204a87;font-weight:bold"&gt;&amp;lt;/profile.active&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#204a87;font-weight:bold"&gt;&amp;lt;/properties&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#204a87;font-weight:bold"&gt;&amp;lt;/profile&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#204a87;font-weight:bold"&gt;&amp;lt;profile&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#204a87;font-weight:bold"&gt;&amp;lt;id&amp;gt;&lt;/span&gt;stg&lt;span style="color:#204a87;font-weight:bold"&gt;&amp;lt;/id&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#204a87;font-weight:bold"&gt;&amp;lt;properties&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#204a87;font-weight:bold"&gt;&amp;lt;profile.active&amp;gt;&lt;/span&gt;stg&lt;span style="color:#204a87;font-weight:bold"&gt;&amp;lt;/profile.active&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#204a87;font-weight:bold"&gt;&amp;lt;/properties&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#204a87;font-weight:bold"&gt;&amp;lt;/profile&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#204a87;font-weight:bold"&gt;&amp;lt;profile&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#204a87;font-weight:bold"&gt;&amp;lt;id&amp;gt;&lt;/span&gt;pet&lt;span style="color:#204a87;font-weight:bold"&gt;&amp;lt;/id&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#204a87;font-weight:bold"&gt;&amp;lt;properties&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#204a87;font-weight:bold"&gt;&amp;lt;profile.active&amp;gt;&lt;/span&gt;pet&lt;span style="color:#204a87;font-weight:bold"&gt;&amp;lt;/profile.active&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#204a87;font-weight:bold"&gt;&amp;lt;/properties&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#204a87;font-weight:bold"&gt;&amp;lt;/profile&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#204a87;font-weight:bold"&gt;&amp;lt;profile&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#204a87;font-weight:bold"&gt;&amp;lt;id&amp;gt;&lt;/span&gt;prd&lt;span style="color:#204a87;font-weight:bold"&gt;&amp;lt;/id&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#204a87;font-weight:bold"&gt;&amp;lt;properties&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#204a87;font-weight:bold"&gt;&amp;lt;profile.active&amp;gt;&lt;/span&gt;prd&lt;span style="color:#204a87;font-weight:bold"&gt;&amp;lt;/profile.active&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#204a87;font-weight:bold"&gt;&amp;lt;/properties&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#204a87;font-weight:bold"&gt;&amp;lt;/profile&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#204a87;font-weight:bold"&gt;&amp;lt;/profiles&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;默认激活了local环境标识，打包的时候根据需要环境加上-P标识。&lt;/p&gt;&#10;&lt;h2 id="配置文件"&gt;配置文件&lt;/h2&gt;&#10;&lt;p&gt;微服务模块都是基于springboot的，本地项目的配置文件建议如下：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;bootstrap.yml&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#204a87;font-weight:bold"&gt;server&lt;/span&gt;&lt;span style="color:#000;font-weight:bold"&gt;:&lt;/span&gt;&lt;span style="color:#f8f8f8"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f8f8f8"&gt; &lt;/span&gt;&lt;span style="color:#204a87;font-weight:bold"&gt;port&lt;/span&gt;&lt;span style="color:#000;font-weight:bold"&gt;:&lt;/span&gt;&lt;span style="color:#f8f8f8"&gt; &lt;/span&gt;&lt;span style="color:#0000cf;font-weight:bold"&gt;6003&lt;/span&gt;&lt;span style="color:#f8f8f8"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f8f8f8"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#204a87;font-weight:bold"&gt;spring&lt;/span&gt;&lt;span style="color:#000;font-weight:bold"&gt;:&lt;/span&gt;&lt;span style="color:#f8f8f8"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f8f8f8"&gt; &lt;/span&gt;&lt;span style="color:#204a87;font-weight:bold"&gt;profiles&lt;/span&gt;&lt;span style="color:#000;font-weight:bold"&gt;:&lt;/span&gt;&lt;span style="color:#f8f8f8"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f8f8f8"&gt; &lt;/span&gt;&lt;span style="color:#204a87;font-weight:bold"&gt;active&lt;/span&gt;&lt;span style="color:#000;font-weight:bold"&gt;:&lt;/span&gt;&lt;span style="color:#f8f8f8"&gt; &lt;/span&gt;@&lt;span style="color:#000"&gt;profile.active@&lt;/span&gt;&lt;span style="color:#f8f8f8"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f8f8f8"&gt; &lt;/span&gt;&lt;span style="color:#204a87;font-weight:bold"&gt;application&lt;/span&gt;&lt;span style="color:#000;font-weight:bold"&gt;:&lt;/span&gt;&lt;span style="color:#f8f8f8"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f8f8f8"&gt; &lt;/span&gt;&lt;span style="color:#204a87;font-weight:bold"&gt;name&lt;/span&gt;&lt;span style="color:#000;font-weight:bold"&gt;:&lt;/span&gt;&lt;span style="color:#f8f8f8"&gt; &lt;/span&gt;&lt;span style="color:#000"&gt;macula-samples-service1&lt;/span&gt;&lt;span style="color:#f8f8f8"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f8f8f8"&gt; &lt;/span&gt;&lt;span style="color:#204a87;font-weight:bold"&gt;cloud&lt;/span&gt;&lt;span style="color:#000;font-weight:bold"&gt;:&lt;/span&gt;&lt;span style="color:#f8f8f8"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f8f8f8"&gt; &lt;/span&gt;&lt;span style="color:#204a87;font-weight:bold"&gt;nacos&lt;/span&gt;&lt;span style="color:#000;font-weight:bold"&gt;:&lt;/span&gt;&lt;span style="color:#f8f8f8"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f8f8f8"&gt; &lt;/span&gt;&lt;span style="color:#204a87;font-weight:bold"&gt;username&lt;/span&gt;&lt;span style="color:#000;font-weight:bold"&gt;:&lt;/span&gt;&lt;span style="color:#f8f8f8"&gt; &lt;/span&gt;&lt;span style="color:#000"&gt;${nacos.username}&lt;/span&gt;&lt;span style="color:#f8f8f8"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f8f8f8"&gt; &lt;/span&gt;&lt;span style="color:#204a87;font-weight:bold"&gt;password&lt;/span&gt;&lt;span style="color:#000;font-weight:bold"&gt;:&lt;/span&gt;&lt;span style="color:#f8f8f8"&gt; &lt;/span&gt;&lt;span style="color:#000"&gt;${nacos.password}&lt;/span&gt;&lt;span style="color:#f8f8f8"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f8f8f8"&gt; &lt;/span&gt;&lt;span style="color:#204a87;font-weight:bold"&gt;config&lt;/span&gt;&lt;span style="color:#000;font-weight:bold"&gt;:&lt;/span&gt;&lt;span style="color:#f8f8f8"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f8f8f8"&gt; &lt;/span&gt;&lt;span style="color:#204a87;font-weight:bold"&gt;server-addr&lt;/span&gt;&lt;span style="color:#000;font-weight:bold"&gt;:&lt;/span&gt;&lt;span style="color:#f8f8f8"&gt; &lt;/span&gt;&lt;span style="color:#000"&gt;${nacos.config.server-addr}&lt;/span&gt;&lt;span style="color:#f8f8f8"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f8f8f8"&gt; &lt;/span&gt;&lt;span style="color:#204a87;font-weight:bold"&gt;namespace&lt;/span&gt;&lt;span style="color:#000;font-weight:bold"&gt;:&lt;/span&gt;&lt;span style="color:#f8f8f8"&gt; &lt;/span&gt;&lt;span style="color:#000"&gt;${nacos.config.namespace}&lt;/span&gt;&lt;span style="color:#f8f8f8"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f8f8f8"&gt; &lt;/span&gt;&lt;span style="color:#8f5902;font-style:italic"&gt;# group:&lt;/span&gt;&lt;span style="color:#f8f8f8"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f8f8f8"&gt; &lt;/span&gt;&lt;span style="color:#204a87;font-weight:bold"&gt;refresh-enabled&lt;/span&gt;&lt;span style="color:#000;font-weight:bold"&gt;:&lt;/span&gt;&lt;span style="color:#f8f8f8"&gt; &lt;/span&gt;&lt;span style="color:#204a87;font-weight:bold"&gt;true&lt;/span&gt;&lt;span style="color:#f8f8f8"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f8f8f8"&gt; &lt;/span&gt;&lt;span style="color:#204a87;font-weight:bold"&gt;file-extension&lt;/span&gt;&lt;span style="color:#000;font-weight:bold"&gt;:&lt;/span&gt;&lt;span style="color:#f8f8f8"&gt; &lt;/span&gt;&lt;span style="color:#000"&gt;yml&lt;/span&gt;&lt;span style="color:#f8f8f8"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f8f8f8"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8f5902;font-style:italic"&gt;# 和环境有关的配置信息，不同环境覆盖此处的配置（这个是本地环境）&lt;/span&gt;&lt;span style="color:#f8f8f8"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#204a87;font-weight:bold"&gt;nacos&lt;/span&gt;&lt;span style="color:#000;font-weight:bold"&gt;:&lt;/span&gt;&lt;span style="color:#f8f8f8"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f8f8f8"&gt; &lt;/span&gt;&lt;span style="color:#204a87;font-weight:bold"&gt;username&lt;/span&gt;&lt;span style="color:#000;font-weight:bold"&gt;:&lt;/span&gt;&lt;span style="color:#f8f8f8"&gt; &lt;/span&gt;&lt;span style="color:#000"&gt;nacos&lt;/span&gt;&lt;span style="color:#f8f8f8"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f8f8f8"&gt; &lt;/span&gt;&lt;span style="color:#204a87;font-weight:bold"&gt;password&lt;/span&gt;&lt;span style="color:#000;font-weight:bold"&gt;:&lt;/span&gt;&lt;span style="color:#f8f8f8"&gt; &lt;/span&gt;&lt;span style="color:#000"&gt;nacos&lt;/span&gt;&lt;span style="color:#f8f8f8"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f8f8f8"&gt; &lt;/span&gt;&lt;span style="color:#204a87;font-weight:bold"&gt;config&lt;/span&gt;&lt;span style="color:#000;font-weight:bold"&gt;:&lt;/span&gt;&lt;span style="color:#f8f8f8"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f8f8f8"&gt; &lt;/span&gt;&lt;span style="color:#204a87;font-weight:bold"&gt;server-addr&lt;/span&gt;&lt;span style="color:#000;font-weight:bold"&gt;:&lt;/span&gt;&lt;span style="color:#f8f8f8"&gt; &lt;/span&gt;&lt;span style="color:#0000cf;font-weight:bold"&gt;127.0.0.1&lt;/span&gt;&lt;span style="color:#000;font-weight:bold"&gt;:&lt;/span&gt;&lt;span style="color:#0000cf;font-weight:bold"&gt;8848&lt;/span&gt;&lt;span style="color:#f8f8f8"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f8f8f8"&gt; &lt;/span&gt;&lt;span style="color:#204a87;font-weight:bold"&gt;namespace&lt;/span&gt;&lt;span style="color:#000;font-weight:bold"&gt;:&lt;/span&gt;&lt;span style="color:#f8f8f8"&gt; &lt;/span&gt;&lt;span style="color:#000"&gt;MACULA5&lt;/span&gt;&lt;span style="color:#f8f8f8"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f8f8f8"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#000"&gt;---&lt;/span&gt;&lt;span style="color:#f8f8f8"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#204a87;font-weight:bold"&gt;spring&lt;/span&gt;&lt;span style="color:#000;font-weight:bold"&gt;:&lt;/span&gt;&lt;span style="color:#f8f8f8"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f8f8f8"&gt; &lt;/span&gt;&lt;span style="color:#204a87;font-weight:bold"&gt;config&lt;/span&gt;&lt;span style="color:#000;font-weight:bold"&gt;:&lt;/span&gt;&lt;span style="color:#f8f8f8"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f8f8f8"&gt; &lt;/span&gt;&lt;span style="color:#204a87;font-weight:bold"&gt;activate&lt;/span&gt;&lt;span style="color:#000;font-weight:bold"&gt;:&lt;/span&gt;&lt;span style="color:#f8f8f8"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f8f8f8"&gt; &lt;/span&gt;&lt;span style="color:#204a87;font-weight:bold"&gt;on-profile&lt;/span&gt;&lt;span style="color:#000;font-weight:bold"&gt;:&lt;/span&gt;&lt;span style="color:#f8f8f8"&gt; &lt;/span&gt;&lt;span style="color:#000"&gt;dev&lt;/span&gt;&lt;span style="color:#f8f8f8"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#204a87;font-weight:bold"&gt;nacos&lt;/span&gt;&lt;span style="color:#000;font-weight:bold"&gt;:&lt;/span&gt;&lt;span style="color:#f8f8f8"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f8f8f8"&gt; &lt;/span&gt;&lt;span style="color:#204a87;font-weight:bold"&gt;username&lt;/span&gt;&lt;span style="color:#000;font-weight:bold"&gt;:&lt;/span&gt;&lt;span style="color:#f8f8f8"&gt; &lt;/span&gt;&lt;span style="color:#000"&gt;maculav5&lt;/span&gt;&lt;span style="color:#f8f8f8"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f8f8f8"&gt; &lt;/span&gt;&lt;span style="color:#8f5902;font-style:italic"&gt;#password: 请通过启动命令赋予密码&lt;/span&gt;&lt;span style="color:#f8f8f8"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f8f8f8"&gt; &lt;/span&gt;&lt;span style="color:#204a87;font-weight:bold"&gt;config&lt;/span&gt;&lt;span style="color:#000;font-weight:bold"&gt;:&lt;/span&gt;&lt;span style="color:#f8f8f8"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f8f8f8"&gt; &lt;/span&gt;&lt;span style="color:#204a87;font-weight:bold"&gt;server-addr&lt;/span&gt;&lt;span style="color:#000;font-weight:bold"&gt;:&lt;/span&gt;&lt;span style="color:#f8f8f8"&gt; &lt;/span&gt;&lt;span style="color:#0000cf;font-weight:bold"&gt;10.94.108.55&lt;/span&gt;&lt;span style="color:#000;font-weight:bold"&gt;:&lt;/span&gt;&lt;span style="color:#0000cf;font-weight:bold"&gt;8848&lt;/span&gt;&lt;span style="color:#f8f8f8"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f8f8f8"&gt; &lt;/span&gt;&lt;span style="color:#204a87;font-weight:bold"&gt;namespace&lt;/span&gt;&lt;span style="color:#000;font-weight:bold"&gt;:&lt;/span&gt;&lt;span style="color:#f8f8f8"&gt; &lt;/span&gt;&lt;span style="color:#000"&gt;MACULA5&lt;/span&gt;&lt;span style="color:#f8f8f8"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这里主要配置怎样连接配置中心，上述是以nacos配置中心为例，不同环境配置不同的配置中心&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;application.yml&lt;/p&gt;&#10;&lt;p&gt;应用的配置，本地文件主要用于本机local环境配置，其他环境建议通过配置中心定义。&lt;/p&gt;&#10;&lt;p&gt;如果不使用配置中心，则本地application配置需要携带环境标识，比如：application-dev.yml、application-prd.yml等&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;</description></item><item><title>Redis规约</title><link>https://macula.dev/docs/5.x/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/5.x/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;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;&#10;&lt;pre&gt;&lt;code&gt;原生命令：例如mget、mset。&#10;&#10;非原生命令：可以使用pipeline提高效率。&#10;&#10;但要注意控制一次批量操作的元素个数(例如500以内，实际也和元素字节数有关)。&#10;&#10;注意两者不同：&#10;&#10; (1) 原生是原子操作，pipeline是非原子操作。&#10; (2)pipeline可以打包不同的命令，原生做不到&#10; (3) pipeline需要客户端和服务端同时支持。&#10;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;p&gt;5.【建议】Redis事务功能较弱，不建议过多使用&lt;/p&gt;</description></item><item><title>RocketMQ规约</title><link>https://macula.dev/docs/5.x/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/5.x/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;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>