1. 微服务开发规范
1.1. 前言
1.1.1. 当前架构
当前协同平台经过多年的技术及架构得沉淀,从企业应用的角度考虑具有开发技术可控性、模块插件式开发的协作性、工作流处理的灵活性等多方面的优势,但随着协同应用的不断扩展,业务复杂性逐步提升,当前单体架构模式的应用,无法通过集群服务器或者线性扩展的方式满足日渐增加的并发性能要求,无法满足需求的及时响应及快速交付,同时在稳定上存在单一插件模块影响整体服务的问题。
1.1.2. 微服务架构
微服务是一种架构模式, 它提倡将单一应用程序划分成一组小的服务,服务之间互相协调、互相配合,为用户提供最终有价值的服务。每个服务运行在独立的进程中,服务与服务之间采用轻量级的通信机制互相沟通(基于HTTP的RESTFUL API或其他的RPC方式)。每个服务都围绕特定的具体业务进行构建,并且可以独立部署到生成环境。原则上尽量避免统一、集中式的服务管理机制,每个微服务可根据自身的业务特点选择合适的技术、工具甚至编程语言进行构建。
1.2. 目标原则
1.2.1. 架构方向
鉴于单体架构和微服务架构模式之间的差异及公司产品的定位及高可用方面的需求,致远协同平台要向微服务架构逐步演进。微服务的架构有利于满足协同服务在高并发及线性扩展方面的需求,有利于服务的拆分及单项优化,同时也有利于开发团队之间的松耦合协作(基于协议或接口的协作)及服务的差异化或渐进式升级更新。
总体架构逐步演进为如下微服务架构模式,满足未来致远协同的高并发及高可用要求。
总体架构
1.2.2. 演进原则
任何产品的演进都无法一蹴而就,更不用说致远沉淀有十五年之久的协同平台。在架构演进过程中需遵循以下几方面的原则。
渐进性原则,满足当前及未来一定范围的技术要求,可做到平台的平滑过渡升级。
独立性原则,逐渐拆分的微服务要具有一定的独立性,以能力方式对上层应用服务提供特定的业务能力支持,要与其他服务保持相对无关性。比如独立的文件服务、licence授权服务、工作流服务等等。
无状态原则,微服务要保证基本无状态,便于微服务自身的集群构建及独立迭代优化。
1.3. 划分原则
把一个大系统划分为多个微服务,使模块间结构更加清晰,模块间更低耦合高内聚,有更好的扩展性和稳定性。微服务划分务必遵守以下原则:
按功能模块划分微服务,尽量做到一个功能模块一个微服务。
微服务之间减少互相调用,做到低耦合高内聚。
1.4. 规范要求
1.4.1. 技术引入
当具体的微服务需要引入某项技术解决特定问题时,需要针对相关的主流技术进行对比分析,结合实际现状确定采用的技术,技术引入需要通过评审后方可正式引入。
当前基于JAVA进行微服务开发,采用SpringBoot进行微服务的快速开发,后面章节的微服务开发指南的也是基于SringBoot进行说明的。
1.4.2. 命名规范
- 工程命名【强制】
以microservice-xxx方式对微服务工程命名,其中xxx采用英文小写方式(表示微服务的核心业务或功能)。
正例:microservice-bulletin / microservice-usermanage
反例:microservice-Bulletin / microservice-userManage
- Package命名【推荐】
命名 | 备注 |
---|---|
com.seeyon.microservice.xxx.* | 总体要求 |
com.seeyon.microservice.xxx.controller | controller的package |
com.seeyon.microservice. xxx.service | service的package |
com.seeyon.microservice. xxx.service.impl | service接口实现的package |
com.seeyon.microservice. xxx.dao | dao的package |
com.seeyon.microservice. xxx.dao .impl | dao接口实现类的package |
com.seeyon.microservice. xxx.entity | 实体类的package |
com.seeyon.microservice.xxx.bean | 业务类的package |
com.seeyon.microservice. xxx.util | 工具类的package |
类命名规则【推荐】
XxxController controller类的命名规则 XxxService service接口的命名规则 XxxServiceImpl service实现类的命名规则 XxxDao dao接口的命名规则 XxxDaoImpl dao实现类的命名规则 XxxBean 业务Bean的命名规则
其他命名【强制】
方法名、参数名、成员变量、局部变量都统一使用lowerCamelCase风格,必须遵从驼峰形式。
1.4.3. 依赖管理
统一采用Maven进行工程代码的依赖管理及构建。
继承microservice-core 实现基础依赖的简化及版本统一,如:
<parent>
<artifactId>microservice-core</artifactId>
<groupId>com.seeyon</groupId>
<version>1.0.0-SNAPSHOT</version>
</parent>
1.4.4. 注释规范
类、类属性、类方法的注释必须使用Javadoc规范,使用/*内容/格式,不得使用//xxx方式。
- 类注释
类必须增加注释说明,包括但不限于类的作用描述、创建人、创建时间,参考如下:
/**
* Demo服务XXX查询服务的入口Controller
* @author 独孤求败
* createDate: 2017年7月28日
*/
@RestController
@RequestMapping("/home")
public class ResourceController {{}
- 方法注释
除setter、getter类似的属性赋值、取值之外的方法必须增加方法的注释说明,包括但不限于方法的作用描述、参数说明、返回说明等。参考如下:
/**
* 根据用户ID获取用户对象
* @param id 用户ID
* @return {@link DemoResponseBean},其中data为用户对象{@link User}
*/
@RequestMapping(value = "{id}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public DemoResponseBean<User> getUser(@PathVariable(value = "id") long id){
}
- 流程注释
对于分支流程控制的代码必须进行分支流程的说明,包括但不限于分支条件、预期结果的说明。
- 代码注释
注释掉的代码尽量要配合说明,而不只是简单的注释掉。
说明:代码被注释掉有两种可能性:1)后续会恢复此段代码逻辑。2)永久不用。
前者如果没有备注信息,难以知晓注释动机。后者建议直接删掉(代码仓库保存了历史代码)。
1.4.5. Swagger使用规范
对于对外访问的rest服务对应的控制器必须添加swager描述。 对于提供给移动端以及pc端同时访问的控制器请求必须添加swager描述。 对于所有控制器尽可能添加swager描述。
1.4.6. swagger注释规范
在接口上声明swagger的api信息时,尽量保证维护好下列信息,以使api页面上的信息相对完善。
@ApiOperation(value = "接口说明", httpMethod = "接口请求方式", response = "接口返回参数类型", notes = "接口发布说明"; @ApiParam(required = "是否必须参数", name = "参数名称", value = "参数具体描述")
示例如下:
@ApiOperation(value = "工作流数据示例——发起流程", httpMethod = "GET", response = String.class, notes = "工作流数据示例——发起流程\n本接口是用于演示发起流程")
@ApiParam(required = false, name = "流程名称", value = "用于演示发起流程的流程名称")
@RequestMapping(value = "newWorkflow", method=RequestMethod.GET)
public void newWorkflow(String wfName) {
operWorkFlowDataService.newCreateWorkflow();
}
1.4.7. 日志规范
日志文件目录:/logs
日志文件命名:xxx.log
1.4.8. 请求响应
除涉及二进制流或渲染页面的请求响应之外,强烈建议微服务提供的接口服务统一采用RESTFUl接口。同时接口服务的响应采用JSON格式。
采用统一的响应格式JSON格式,如下:
{
“code” : 0/非0, // 0代表成功,非0代表具体错误码。
“info” : 错误描述, // code为0时,该字段不存在。
“data” : 响应数据 // 具体的响应内容,可以是任何类型,code为非0时,该字段不存在。
}
1.4.9. 单元测试约定
测试范围规范
微服务中必须编写单元测试,单元测试覆盖的范围至少为controller控制层。
测试类的命名定义规范
Junit自动生成测试类的命名如下:被测试的业务+Test、被测试的接口+Test、被测试的类+Test,例如:ResourceControllerTest、FileUploadControllerTest
测试用例的命名定义规范
测试用例的命名规则是:test+用例操作。如:testXXXOperCase, XXXOperCase是某个用例操作的名字,例如:testCmdBuildFlatCache、testCmdTransfer
测试程序的包名定义规范
测试程序包的命名和被测试代码的包名一致,只是放在src/test/java目录下。例如:src/main/java源码文件夹下的com.seeyon.microservice.xxx.controller包下对应的单元测试代码存放在:src/test/java源码文件夹下的com.seeyon.microservice.xxx.controller包下。
1.5. 开发指南
1.5.1. 工程搭建
按照命名规范创建maven工程,同时设置parent如下:
<parent>
<artifactId>microservice-core</artifactId>
<groupId>com.seeyon</groupId>
<version>1.0.0-SNAPSHOT</version>
</parent>
src/main/resources目录下创建application.properties文件作为工程默认配置,同时在工程根目录的config(自行创建)目录下创建application.properties用户提供给外部更改的配置,如监听端口等(服务优先加载该位置下的application.properties文件)。文件目录结构如下:
microservice-xxx
|--- config
|--- application.properties
|--- logs
|--- xxx.log(由log4j2自动生成)
|--- src
|--- main
|--- java
|--- 源代码位置
|--- resources
|--- application.properties(含log4j配置文件的定义)
|--- log4j2.xml(log4j2配置文件)
|--- 其他资源文件
1.5.2. Restful接口
采用SpringMVC构建Rest服务,在定义清除Rest接口后穿件相应的RestController,具体步骤如下:
1、 创建Controllers类,并给类增加@RestController及@RequestMapping的相关注解。
2、 创建Controller提供的方法,并增加相应的@RequestMapping注解及参数。
参考如下:
/**
* Demo服务XXX查询服务的入口Controller
* @author 独孤求败
* createDate: 2017年7月28日
*/
@RestController
@RequestMapping("/user")
public class UserController {
/**
* 根据用户ID获取用户对象
* @param id 用户ID
* @return {@link DemoResponseBean},其中data为用户对象{@link User}
*/
@RequestMapping(value = "{id}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public DemoResponseBean<User> getUser(@PathVariable(value = "id") long id){
}
1.5.3. 事务处理
当具体的微服务需要引入并补充完善
1.5.4. 日志处理
当具体的微服务需要引入并补充完善
1.5.5. 数据库相关
当具体的微服务需要引入并补充完善
1.5.6. 数据缓存
当具体的微服务需要引入并补充完善