前言笔者近年来在微服务领域做了一些架构设计,对新老服务如何微服务积累了一些经验。先分享给大家,希望对大家有用。同时也欢迎今日头条小伙伴们在评论区留言讨论微服务应该如何进化。一、平台微服务改造方案1、启动方式改为spring-boot启动。需要修改pom文件,修改之前的配置文件加载方式。springboot可以打包成jar或者是包含jsp的war,但是没有研究war的打包方式。可以合并配置文件,也可以加载指定的文件。2、服务划分需要添加多个服务,比如服务发现、服务网关、配置中心服务、负载均衡等,需要用到spring-cloud。另外,如果不手动启停服务方便管理,还需要一些自动化的管理和部署工具(Docker+k8s)。平台的具体功能分为以下四种服务3.登录认证登录认证由网关和认证服务完成。还需要更改与每个服务本身的身份验证相关的配置。4、前端展示采用Angular2+Bootstrap+H5展示View层,淘汰jsp。5、代码结构6、MVC框架业务逻辑层(service)不变;数据访问层更改为JPA实现(存储库);controller层改成restful风格,所有struts改成restspringmvc。使用spring-data技术,在此基础上扩展了其基类方法。支持以下多种查询方式:在配置类上添加@enableJpaRepository注解@configuration@enableJpaRepository(basePackages={“xxx”},repositoryFactoryBeanClass=BaseRepositoryFactoryBean.calss)publicclassApplication{…}2.编写的repository接口继承自BaseRepository接口7.单元测试和集成测试目前,前端和后端是分组的。原则上前端单元测试不依赖后台数据。前后端定义json数据格式,前端可以独立测试。前端使用karma进行单元测试;后端使用mock+postman进行单元测试。8.数据库设计9.关于项目切换和数据源切换目前基本都是一个服务访问一个数据源。10.ContextAuthenticationHolder获取当前登录用户信息。11、服务之间调用服务的API实现时,都是通过rest方法实现的。通过spring-cloud-feign技术将远程http服务作为http客户端调用。服务端接口暴露方式如下:客户端调用方式如下:@AutowiredprivateLogRemoteServiceservice;//远程服务涉及到两个服务之间的API接口调用,不能使用之前的pom引入,改成服务间调用.因此,两个服务都需要引用公共实体,并且需要提取共享实体。系统参数、字典、操作日志都需要改成微服务。12.缓存框架采用redis+ehcache二级缓存。原理如下:添加数据时,缓存一份到本地进程ehcache(这里的ehcache不需要集群,避免多播带来的开销),取缓存时,会先取本地,而不会请求redis,减少应用服务器<–>缓存服务器redis之间的网络开销。(见下图,为了减少get的网络传输,我们会在每个应用服务器上添加一个本地的ehcache缓存作为二级缓存,即第一次获取的数据存储在ehcache中,输出output可以从本地的ehcache中获取,不需要访问redis,减少了以后get的网络开销,get的开销只需要一次,后面的get就不需要了,除非本地缓存过期需要重新获取13.操作日志切面处理操作日志切面处理核心包中一些用于记录操作日志的服务和当前用户的方法需要改变。第一步定义注解类annotationclassLogging第二步定义服务切面@Aspect@ComponentpublicclassLogAspect{...}第三步添加注解@RestController@RequestMapping(value="/xxx")到需要记录操作日志的方法上GET)publicResponseEntityshowData(Stringtupe){…}}14、分布式异常、事务调用其他服务异常时,需要特殊处理业务是否可以继续的问题。至于分布式事物的回滚,目前没有研究。自己写代码实现可能会比较麻烦。需要考虑各种情况,需要记录操作前的数据,以便回滚。15.统一返回码处理为了提高前后端的交互体验,后台返回的数据和异常都进行了统一封装。并且根据不同类型的返回值定义了一系列的返回码。后端返回值格式如下:{"code":"10001","message":"code重复,无法保存!","data":null}其中:code代码返回码,messagecode提示信息,data代表返回数据。以上是验证异常的示例。返回码定义列表如下:二、前端框架设计1、背景近几年,前端技术发展迅速,涌现出许多优秀的框架。新兴的前端技术主要有以下特点:随着富客户端技术的多样化,用户体验变得越来越重要。页面的美观度、响应速度、内存消耗性能成为客户选择产品非常重要的因素。组件化实现利润最大化的两个主要途径是降低部署成本和提高开发效率;而提高开发效率的两个主要途径是加快开发速度和降低变更成本。JavaScript组件化的目标是职责清晰、松散耦合、便于单元测试和复用,提高开发效率。MV*框架类似于后端的分层,前端也大致分为三层。它在发展上经历了从MVC-->MVP-->MVVM的转变。MV*代表了这三个和类似的框架。MV*框架的思想是根据职责对前端进行分层。每一层都相对独立,有自己的价值,有自己的发展空间。设计一个满足工程要求的软件系统(前端)需要包含的要素:开发规范;模块化开发;组件开发;组件仓库;性能优化;项目部署;开发过程;开发工具。2.目标搭建前端框架,制定开发规范和开发流程,选择目前使用最广泛,有良好开源社区和技术支持,并结合公司后台特点的MV*框架端管理系统进行技术选型和架构设计。编程模型确定后,制定前端开发流程和开发规范。搭建符合前端框架的开发环境和开发、打包、发布工具。根据前端开发、部署、测试的需要,建立前端开发工具、开发环境、打包、部署工具。基于界面交互风格,开发通用组件库,为了提高应用开发效率,需要建立一套满足应用开发各种场景的页面组件库。建立一套优秀的用户体验的界面交互风格和视觉效果。建立一个优秀的前端框架,可以支持更丰富的页面交互效果,提高响应速度,提升用户体验。但是如果没有好的交互和视觉效果设计,用户是很难感受到这一切的,所以前端的交互风格和视觉效果是必不可少的一环。3.技术选择基于目标,通过技术调研,结合公司实际情况,选择了以下前端技术栈:新的前端框架层出不穷,为什么最后选择Angular,主要是为了以下原因:集成(ALL-IN-ONE)。涵盖M、V、C/VM等多个层次,无需结合评估其他技术即可完成大部分前端开发任务,可有效降低决策成本,提高决策速度。组件化。Angular原生支持组件化开发,方便代码解耦和复用,提高开发效率。全生命周期支持。一个优秀的框架需要为分工提供良好的支持。大家可以从一些简单的任务开始,逐步从修改一个文件扩展到修改一个目录,从而独立实现一个功能。Angular是一个大型开源项目,得到了Google的全力支持。学习成本相对较低,可以让新人快速融入项目团队,贡献生产力。支持单元测试和端到端测试。Angular对单元测试和e2e测试更加友好,可以更快的编写测试代码,完成自动化测试。4.界面设计设计原则一个好的用户界面的最终目标是能够一眼看懂应用系统的功能,无需经过太多培训就能使用应用系统!本系统秉承图形用户界面(GUI)的设计原则:在设计时,首先关注用户及其业务,而不是技术如何实现简单美观的UI设计。视觉元素清晰,采用苹果灰配色和亲和力比较强的“橙色#ff9900”作为主色调。可理解性操作思维行为、反馈、视觉展示和信息等一系列活动在内容中要顺序合理、容易记忆、容易放置。可配置性允许轻松进行个性化、设置或新配置。界面与操作的一致性引导性术语的描述一方面引导用户行为:帮助信息、提示信息,协助用户完成操作;另一方面:用户操作结果的反馈信息(多以弹出提示框的形式)。五、设计规范六、框架结构上图为前端整体框架结构,包括:入口文件:index.html也是应用的首页。系统的全局样式可以在index.html中定义。appModule:系统的根模块。Angular应用程序是模块化的,每个应用程序至少有一个根模块。homeModule:系统界面框架模块,包括左侧菜单栏、顶部导航栏和中间内容区。sysModule:平台安全框架模块。otherModule:其他应用模块。base/constants:平台提供的基类和常量。组件库:组件库是构建在平台上的通用组件,满足应用开发的常见场景,可以作为第三方依赖包集成到应用开发中,提高应用产品开发效率。目前,组件库的开发已经完成了80%左右,可以满足应用的基本业务场景。未来需要不断的扩充、完善和优化,使组件库更加方便易用。7、工程工程的主要目的是为了提高效率和降低成本,所以前端工程也是不可或缺的一部分。上面提到工程的几个要素,针对这些要素提出我们的解决方案:Developmentspecification定义前端开发规范文档,通过TSLint和codelyzer检查代码。模块化开发利用Angular的模块功能,对不同的应用模块进行模块化开发。基于组件的开发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)实现用户统一入口接入、动态路由、安全认证等,如下图:4、持续构建和交付JenkinsJenkins与Gitlab、Docker、Sonar合作完成服务源代码的验证、构建和发布。最终组件分为两部分:Docker镜像二进制包(如jar)结果展示服务源码构建任务列表:app-cloud-cloudware-authserver(认证服务源码构建任务)app-cloud-cloudware-configserver(配置中心服务构建源码构建任务)app-cloud-cloudware-discovery(服务注册与发现源码构建任务)app-cloud-cloudware-gateway(服务网关源码构建任务)app-cloud-param-service(public参数服务源码构建任务)app-cloud-security-service(安全框架服务源码构建任务)其他服务基础框架源码构建任务列表:app-cloud-framework(基础框架源码构建任务)app-cloud-platformwork(平台框架源码构建任务)如下图所示:示例:编译服务网关源码,将服务网关制作成镜像,并上传加载到镜像库中。GitlabGitlab是一个版本控制管理系统。实现一个自托管的Git项目存储库,可以通过Web界面访问公共或私有项目。它具有与Github类似的功能,具有浏览源代码、管理错误和评论的能力。可以管理团队对存储库的访问,浏览提交的版本非常容易,并提供文件历史存储库。如下图所示:示例:安全框架服务源码我们规定一个完整的微服务,它的静态视图包括以下几个部分:1.Dockerfile文件用于创建Docker镜像,实现微服务的容器化部署。2、api目录暴露了服务的API接口访问地址。比如我们要获取张三的用户信息,可以调用用户信息的API接口,请求地址为http://localhost/security-service/user/vi/0008093。config目录用于配置数据库访问和配置服务启动时的参数加载和api接口授权访问控制。4、repository目录数据的访问层,提供访问数据库数据的接口5、实体目录(独立项目,通过pom导入)用于处理实体与数据库表的映射关系;api资源授权访问控制;为存储层提供数据封装。6.服务目录用于处理具体的业务逻辑7.启动类ApplicationMaven私服库Docker私服库镜像项目平台镜像项目安全框架服务镜像地址5.个人开发环境配置清单