微服务平台改造落地解决方案设计

2020-07-06 18:01:07 浏览数 (1)

前言

最近几年,楼主在微服务领域做过一些架构设计,针对新老服务如何微服务化积累一定经验,现分享给大家,希望对大家有用。同时欢迎头条的朋友在评论区留言,共同讨论微服务该如何演进。

一、平台微服务改造方案

1、启动方式

启动方式改为spring-boot启动,需修改pom文件,修改之前的配置文件加载方式。

Springboot打包可以打成jar, 也可以打出包含jsp的war,但是war的打包方式目前没有研究。配置文件可以合并,也可以加载指定文件。

2、服务划分

需要新增多个服务,如服务发现、服务网关、配置中心服务、负载均衡等,需要用到spring-cloud。除此之外,如果不手动启动停止服务、方便管理,还需要一些自动化管理部署工具(Docker k8s)。

平台具体的功能被划分为以下4个服务

3、登录认证

登录认证由网关配合认证服务共同完成。各服务本身上跟认证相关的配置也需要更改。

4、前端展示

采用Angular2 Bootstrap H5展示View层,淘汰jsp。

5、代码结构

6、MVC框架

业务逻辑层(service)保持不变;数据访问层改成JPA实现(repository);controller层改成restful风格,struts的全部改成rest的springmvc。

使用spring-data技术,在此基础上扩展了其基类方法。支持以下多种查询方式:

在configuration类上添加@enableJpaRepository注解

代码语言:javascript复制
@configuration
@enableJpaRepository(basePackages={“xxx”}, repositoryFactoryBeanClass=BaseRepositoryFactoryBean.calss)
public class Application {
	…
}

2、编写的repository接口都继承自BaseRepository接口

7、单元测试与集成测试

目前前端后端分组,原则上前端单元测试不依赖于后台数据,前后端定义好json数据格式,以便前端独立测试。

前端用karma进行单元测试;后端用mock postman进行单元测试。

8、数据库设计

9、关于工程切换和数据源切换

目前基本上是一个服务访问一个数据源。

10、上下文

AuthenticationHolder来获取当前登录用户信息。

11、服务间调用

服务的api在实现时,都是通过rest方式来实现。通过spring-cloud-feign技术作为http客户端调用远程http服务。服务端接口暴露方式如下:

客户端调用方式如下:

代码语言:javascript复制
@Autowired
private LogRemoteService service; // 远程服务

凡是涉及到两个服务的之间API接口调用,不能使用之前的pom引入,改为服务间调用的方式。所以需要两个服务都引用共同的实体,共用的实体需要提取出来。系统参数和字典、操作日志都需要改成微服务

12、缓存框架

使用redis ehcache两级缓存,原理如下:

添加数据时,在缓存到远程redis的同时,缓存一份到本地进程ehcache(此处的ehcache不用做集群,避免组播带来的开销),取缓存的时候会先取本地,没有会向redis请求,这样会减少应用服务器<–>缓存服务器redis之间的网络开销。(见下图,为了减少get这几条网络传输,我们会在每个应用服务器上增加本地的ehcache缓存作为二级缓存,即第一次get到的数据存入ehcache,后面output输出即可从本地ehcache中获取,不用再访问redis了,所以就减少了以后get的网络开销。get开销只要一次,后续不需要了,除非本地缓存过期需要再get。

13、操作日志切面处理

操作日志切面处理。之前核心包有些service用到记录操作日志、和当前用户的方法都需要改。

第一步,定义注解类注解类Logging

第二步,服务定义切面

代码语言:javascript复制
@Aspect
@Component
public class LogAspect {
	…
}

第三步,在需要记录操作日志的方法上添加注解

代码语言:javascript复制
@RestController
@RequestMapping(value = "/xxx")
public class xxxController {
 @Logging(title="查询订单列表操作", data="查询类型为{0}订单")
 @RequestMapping( value="/showData", method = RequestMethod.GET)
 public ResponseEntity<String> showData(String tupe){
 …
 }
}

14、分布式异常与事务

调用其他服务异常时,该业务是否继续进行问题需要做特殊处理。而分布式事物的回滚问题,目前还没有研究,要实现可能代码写的时候要麻烦些,需要考虑各种情况,为了回滚也需要记录操作前的数据。

15、统一返回码处理

为了提高前后端的交互体验,对后台返回的数据和异常进行了统一封装。并根据不同类型的返回值定义了一系列的返回码。

后端返回值格式如下:

代码语言:javascript复制
{
 “code“: “10001“,
 “message“: “code重复,不能保存!“,
 “data“:null
}

其中:code代码返回码,message代码提示信息,data代表返回数据。以上是一个校验异常的示例。返回码定义列表如下:

二、前端框架设计

1、背景

在过去的几年,前端技术飞速发展,涌现了很多优秀的框架,新兴的前端技术主要有以下特点:

  • 用户体验

从html5产生以来,随着富客户端技术的多种多样,用户体验变得越来越重要。页面的美观性、响应速度、内存消耗性能优劣等成为客户选择产品非常重要的因素。

  • 组件化

利润最大化的两个主要途径是减少部署成本、提高开发效率;而提高开发效率的两个主要途径就是加快开发速度,减少变更代价。JavaScript组件化的目标是清晰的职责,松耦合,便于单元测试和重复利用,提高开发效率。

  • MV*框架

类似于后端的分层,前端也大致分为三层,从发展上经历了由MVC --> MVP --> MVVM的转换,MV*代表这三者及类似框架。MV*框架的理念是把前端按照职责分层,每一层都相对比较独立,有自己的价值,也有各自发挥的余地。

  • 工程化

一个符合工程化要求的软件系统(前端)需要包含的要素:

开发规范;模块化开发;组件化开发;组件仓库;性能优化;项目部署;开发流程;开发工具。

2、目标

  • 搭建前端框架,制定开发规范及开发流程

选用目前应用最广,有着良好的开源社区及技术支持的MV*框架,结合公司后台管理类系统的特点,进行技术选型及框架设计。在编程模型确定以后,制定前端开发流程及开发规范。

  • 搭建符合前端框架的开发环境及开发、打包、发布工具

根据前端开发、部署及测试等需求,建立前端的开发工具、开发环境、打包及部署等工具。

  • 基于界面交互风格,开发通用组件库

为了提高应用开发效率,需要建立一套页面组件库,满足应用开发的各个场景。

  • 建立一套优秀用户体验的界面交互风格及视觉效果

建立优秀的前端框架可以支持更加丰富的页面交互效果,提高响应速度,提升用户体验。但是没有良好的交互及视觉效果设计,这一切用户是很难感受到的,所以前端的交互风格及视觉效果是不可或缺的一部分。

3、技术选型

基于目标通过技术调研并结合公司实际情况选取如下前端技术栈:

前端新的框架层出不穷,为什么最终会选择Angular,主要有以下几方面的原因:

  • 整合性(ALL-IN-ONE)。它涵盖了M、V、C/VM等各个层面,不需要组合、评估其它技术就能完成大部分前端开发任务,可以有效降低决策成本,提高决策速度。
  • 组件化。Angular原生支持组件化开发,便于代码解耦和复用,提高开发效率。
  • 全生命周期支持。一个优秀的框架需要对分工提供良好的支持,每个人都可以先从一些简单任务开始,逐步的从修改一个文件扩大到修改一个目录再到独立实现一个特性。Angular是一个大型开源项目,并得到了Google的鼎力支持,学习成本相对较低,可以让新人快速融入项目组,贡献生产力。
  • 支持单元测试和e2e测试。Angular对单元测试和e2e测试更加友好,可以更快速地编写测试代码,完成自动化测试。

4、界面设计

设计原则

对应用系统的功能能够一目了然、不需要多少培训就可以方便使用该应用系统,一直是做好用户界面的最终目标!

本系统坚持图形用户界面(GUI)设计原则:

  • 设计时首先关注用户及其业务,而不是技术如何实现
  • UI设计简洁美观,视觉元素清晰

采用苹果灰的配色方案以及亲和力比较强的“桔色#ff9900”为主体色。

  • 可理解性操作思维

行为、反馈、可视化展现和信息等一系列活动,应该有合理的顺序,很容易记得,容易放置在内容中。

  • 可配置性

允许简单的个性化配置、设置或新配置。

  • 界面以及操作一致性
  • 引导性术语描述,引导用户行为

一方面为:帮助信息,辅助用户完成操作的提示信息;另一方面为:用户操作结果的反馈信息(多为弹出提示框形式出现)。

5、设计规范

6、框架结构

如上图为前端整体框架结构,包括:

  • 入口文件:index.html同时也是应用程序首页面。index.html中可以定义系统的全局的样式。
  • appModule:系统的根模块,Angular 应用是模块化的,每个应用至少有一个跟模块。
  • homeModule:系统界面框架模块,包括左侧菜单栏、顶部导航栏以及中间内容区。
  • sysModule:平台安全框架模块。
  • otherModule:其它应用模块。
  • base/constants:平台提供的基类以及常量。
  • 组件库:组件库为平台搭建的通用组件,满足应用开发的常用场景,可以作为第三方依赖包集成到应用开发中,提高应用产品开发效率。

目前,组件库的开发已完成80%左右,可以满足应用基本业务场景,后续还需要不断地扩充、完善和优化,让组件库更方便、易用。

7、工程化

工程化的主要目的是提高效率、降低成本,因此前端工程化也是必不可少的一部分,前面提到了工程化的几个要素,针对这几个要素提出了我们的解决方案:

  • 开发规范

定义前端开发规范文档,并通过TSLint和codelyzer对代码进行检查。

  • 模块化开发

利用Angular的module功能对不同的应用模块采用模块化开发。

  • 组件化开发

Angular原生支持组件化开发,降低代码的耦合性,提高代码可复用性。

  • 组件仓库

利用cnpm搭建私服,所有组件库在cnpm私服中统一管理。

  • 开发流程

定义开发流程,明确职责和协同,明确目标,提高开发效率。(目前,开发流程还没有完全固化下来,仍需要进一步完善)

  • 开发工具

平台组完成开发语言、开发工具、测试工具、发布工具等选型,所有应用产品按照规范统一开发工具。

  • 性能优化

页面的响应时间对于用户是非常重要的,因此前端的性能优化(按需加载、延迟加载、代码压缩、缓存等)是很重要的一部分,目前这部分考虑的比较少,后续会重点考虑前端性能优化内容。

三、后端框架设计

1、 服务拆分

公共服务

2、公共组件

3、开发静态视图

平台基础框架

平台基础框架提供公共的API供业务开发者调用,让他们关注与业务层面的代码实现,而不是平台底层框架实现。

平台基础框架包括:

1) 基础核心(app-cloud-framework-core)

提供数据库访问配置、Base基类(Service、Repository)、实体、工具、注解、切面、常量功能等

2) 控制层(app-cloud-framework-mvc)

提供控制层基类(Controller)、获取认证用户功能等。

如下图所示:

平台基础服务

平台基础服务存在的目的是为用户提供访问入口、安全认证;为服务提供注册与发现、负载均衡、熔断、配置等功能。

平台基础服务包括:

1) 认证服务(app-cloud-cloudware-authserver)

用于实现用户单点登录和退出。

2) 配置中心服务(app-cloud-cloudware-configserver)

用于管理各个服务的配置文件管理。

3) 注册与发现服务(app-cloud-cloudware-discovery)

用于管理服务的注册与发现。

4) 网关服务(app-cloud-cloudware-gateway)

实现用户统一入口访问,动态路由,安全认证等。

如下图所示:

四、持续构建与交付

Jenkins

Jenkins与Gitlab、Docker、Sonar配合完成服务源代码的校验、构建和发布。

最终构件分为两个部分:

  1. Docker镜像
  2. 二进制包(例如jar)

成果展示

服务源代码构建任务清单:

  1. app-cloud-cloudware-authserver(认证服务源代码构建任务)
  2. app-cloud-cloudware-configserver(配置中心服务构源代码建任务)
  3. app-cloud-cloudware-discovery(服务注册与发现源代码构建任务)
  4. app-cloud-cloudware-gateway(服务网关源代码构建任务)
  5. app-cloud-param-service(公用参数服务源代码构建任务)
  6. app-cloud-security-service(安全框架服务源代码构建任务)
  7. 其他服务

基础框架源代码构建任务清单:

  1. app-cloud-framework(基础框架源代码构建任务)
  2. app-cloud-platformwork(平台框架源代码构建任务)

如下图所示:

例子:编译服务网关源代码

把服务网关打成镜像,上传到镜像库。

Gitlab

Gitlab是一个版本控制管理系统。实现一个自托管的Git项目仓库,可通过Web界面进行访问公开的或者私人项目。它拥有与Github类似的功能,能够浏览源代码,管理缺陷和注释。可以管理团队对仓库的访问,它非常易于浏览提交过的版本并提供一个文件历史库。

如下图:

例子:安全框架服务源码

我们规定,一个完整的微服务,其静态视图包含如下几个部分:

1.Dockerfile文件

用于创建Docker镜像,实现微服务容器化部署。

2.api目录

对外暴露服务的api接口访问地址。例如我们想获取张三的用户信息,就可以调用用户信息的API接口,请求地址为http://localhost/security-service/user/vi/000809

3.config目录

用于配置数据库访问、服务启动时配置参数加载以及api接口授权访问控制。

4.repository目录

数据的访问层,提供访问数据库数据的接口

5. 实体目录(独立项目,通过pom引入)

用于处理实体与数据库表映射关系;api资源授权访问控制;为repository层提供数据封装体。

6. service目录

用于处理具体业务的逻辑

7. 启动类Application

Maven私服库

Docker私服库

镜像项目

平台镜像项目

安全框架服务镜像地址

五、个人开发环境配置清单

0 人点赞