-
Notifications
You must be signed in to change notification settings - Fork 0
top constraint
leizh edited this page May 13, 2019
·
27 revisions
- 在理解的基础上,尽量遵循工业界、权威的开发社区所公认的设计原则、设计风格、最佳实践;
- 避免采用无根据的以讹传讹的经验;
- 避免重新发明轮子,避免自造山寨轮子;
- 谨慎的选择成熟的而不是过度的技术、框架、工具
下面是TL;DR版
必须(MUST),不允许(MUST NOT),应当(SHOULD),不应当(SHOULD NOT),可以(MAY)所表达的含义参照RFC 2119 定义
- 必须(MUST),不允许(MUST NOT),无条件严格遵守
- 应当(SHOULD),不应当(SHOULD NOT),原则上要严格遵守,除了文档指明的例外
- 可以(MAY),可选项,且可以自行选用替代方案
- 对http response body的约定
- 不应当 包含任何自定义状态码,仅当接口调用方要求必须有自定义状态码时,可以按具体要求设置自定义状态码
- http 状态码200时,返回json内容格式有两种,其中集合内容 必须 按分页形式返回
- 单个记录
{"content":{"name":"Taylor Swift"}} - 集合内容
{ "content":{ "resultList":[{"name":"Taylor Swift"},{"name":"Maroon 5"}], "total":100, "pageNum":1, "pageSize":10 } }
- 单个记录
- http 状态码4xx或5xx时,应当 按以下json内容格式返回,除非调用方有特殊要求
- 形如:
{"error":"this is a error message detail"}
- 形如:
- 分页请求参数为pageSize和pageNum,分别表示每页记录数和请求第几页,不传参则缺省为10和1
- 受限资源的实现,即承担OAuth2 Resource Server角色的接口,应当 按RFC 6750的要求支持 token 值放置在Authorization 头部的方式,除非其实际资源提供服务能力隐藏在具备统一鉴权识别功能的API Gateway之后,则资源服务自身可以 不考虑此一点要求,而转为对API Gateway的相关接口规格要求;形式上,参考如以下dump 的HTTP请求头 Authorization 段
GET /v1/resource HTTP/1.1 Host: server.example.com Authorization: Bearer 1bf6d543d6cc95c25eb88d88c60b406d - http 请求如果有 body ,则接口要求的请求头部的 content-type 应当 支持值设置为 application/json,除非是典型的表单提交,则 可以 使用application/x-www-form-urlencoded 或 multipart/form-data
- 租户标识参数命名为tenantId,租户一侧的服务必须 携带,平台一侧只要和特定租户相关,也应该 携带
- 无论哪一种类型(method,无论GET、POST或其他),tenantId 必须 放置于首行(或称请求行,query_string),例如:瑞尔租户id如果为cae2bb0064eb8d2f62b42afcc661cb91,形如
POST /v1/users?tenantId=cae2bb0064eb8d2f62b42afcc661cb91 HTTP/1.1 Host: server.example.com Authorization: Bearer 1bf6d543d6cc95c25eb88d88c60b406d {"name":"Taylor Swift"} - POST method 的 http 请求,目前除租户标识tenantId外所有参数及查询条件 可以 都放置在body的json定义里面
- 每一个涉及特定租户功能的后端接口都 必须 接收传递参数tenantId,用于识别被操作的租户,其他参数则按具体特定接口或相关需求设计
- VCS 必须 使用 git
- java工程构建管理应当 使用 maven,例外则可以 在工程README.md文件中列明
- 如有二方库管理需求,应当 使用git submodule进行管理,即不以任何方式导入中心库没有的jar包,例外则可以 在工程README.md文件中列明,具体指导原则:
- 严控二方库(跨服务使用的组件)的产生
- 不重复造轮子,需要一项工具功能时,应当 查找特定工具功能是否有稳定的三方库可以满足需要;例外则在可以 在工程README.md文件中列明
- 当有多个工程需要共用的类型定义时,应当 首先考虑是否设计内聚性出现了问题,除值对象外,其他情形不应当 予以接受;例外则可以 在工程README.md文件中列明
- 多个服务序列化通信时的value对象,可以 考虑冗余声明,同时 可以 使用lombok等方式减少不必要的代码量
- 严控二方库(跨服务使用的组件)的产生
- IDL式的组件,版本仓库中必须 仅保留IDL源文件,代码生成过程依赖构建工具,IDL组件被多个project共享时,采用git submodule方式管理
- 应当 使用前后端分离的方式实现,后端以API的形式向外输出能力;如果后端工程包含静态资源,仅 应当 基于调试和监控目的
-
应当 使用微服务架构风格进行设计
- java类各服务应当 选用Spring Boot来做项目基础框架,并引入actuator依赖
- 可以 使用 Spring Boot Initializer 生成项目脚手架
- 应当 保留maven/gradle wrapper文件到git仓库,除非工程骨架不是通过Spring Boot Initializer创建的
- 不应当 再使用Spring Cloud Discovery暴露自身和依赖其他的服务,而应当 使用 DNS 基础设施来管理服务间依赖,除非要集成的第二/三方服务只能通过Spring Cloud Discovery暴露其服务能力
- 和认证/授权系统对接 必须 遵循OAuth2协议的各类RFC
- 面向客户端(web或app)的接口鉴权能力 应当 由网关层统一处理,除非实施架构中不存在可编程性网关
- java类各服务应当 选用Spring Boot来做项目基础框架,并引入actuator依赖
-
应当 根据业务关联性纵向拆分服务,对于服务及服务间关系有如下设计层面的指导性原则:
- 每个服务应当 按业务特征来选用自己的持久化存储基础设施,基础设施选型可包含不限于以下选型:MySQL(业务建模、资金账号),MongoDB(trace型信息存储),Neo4j(强社交类型的用户关联关系)等,但同一类型的存储只应该选用一个,比如关系型数据库,不允许 在同一个工程中同时使用MySQL和PostgreSQL,以此类推;也不允许 在一个工程中针对一个数据库的多个实例
- 每个可以服务按项目初始的开发人员最大产能习惯或倾向性来选择持久层框架,但不应该 在一个项目中使用多个持久层框架;因为选用Spring Boot
- 必须 做到仅通过api调用来访问其他服务管理的私有数据,在此原则基础之上:
- 可以为提高效率目的在不同的服务中做数据冗余设计(持久化的物化视图,或LRU的缓存等),但不应当 直接访问其他服务的私有持久化存储地址(不共享存储),特殊情况必须 要经过设计评审并在设计文档,源代码注释中标明
- 服务间调用应该 使用Feign,注意服务名称部分也要利用 @FeignClient("${service.name:DEFAULT-NAME}") 作为spring注解的外化配置能力进行管理,同时如前所述,不依赖spring cloud eureka来做服务间依赖管理
- 服务间如有异步调用使用消息中间件选用redis、kafka或RabbitMQ
- 选用原则,OLTP相关小量数据应当 使用Redis List,大量数据应当 RabbitMQ;OLAP场景应当 选择kafka
- 不同选型可以 共存于一个服务当中
- 数据库设计 必须 支持多租户多机构数据共享存储,单租户的实现在这里属于多租户的一个运行时的特例——通过网络、路由的隔离,使得该数据库中只包含一个租户的数据
- 所有要按租户进行区分的数据表必须 包含 tenant_id 字段或有关系表记录与tenant_id关系且tenant_id设计上不允许 为空
- 其他问题参考数据库风格指南文档
- Java版本为8_u192,暂不使用JDK 11,鼓励测试兼容性(主要是第三方依赖库方面风险较大)
- Java服务开发时,需要的类库版本如果包含在Spring Boot 2.x.x.RELEASE中,则以boot的 BOM 为准,不要再另行声明版本号,这方面如有特殊需要,请文档注明
- 其他方面参考Java编程风格指南文档
- Spring Boot 2.x.x.RELEASE
- 即必须 确认主版本号是2,必须 确认是Release版,项目使用Spring Cloud组件(除feign之外,目前不应该 使用任何Spring Cloud 组件)则依赖Spring Boot Initializer生成(后续增量添加时如果不确定,可以用Spring Boot的Initializer来辅助处理pom dependency变化)
- Redis 3.2.12
- MySQL 5.7.x
- Kafka 1.1.0
- RabbitMQ 3.7.6
- Elasticsearch 6.4.2