张 杰 司维超 王丽娜 石春玲
(1.海军航空大学航空基础学院 烟台 264001)(2.海军航空大学岸防兵学院 烟台 264001)(3.烟台市人力资源考试中心 烟台 264001)
随着企业级应用的业务复杂度和规模的不断扩大,传统的单体应用系统在维护、部署、扩展以及稳定性、并发性等[1]各个方面,普遍存在难以逾越瓶颈,这也导致各种相对独立的传统软件系统在集成时面临的困难,如系统堆砌、问题定位难、扩展性差、可靠性不高、维护成本高等[2],1996年由Gartner提出SOA,并于2002年12月指出SOA是现代应用开发领域最重要的课题,将成为占有绝对优势的软件工程实践方法,后来引入了SOA服务化,SOA开发需要相应的体系支撑:ESB(Enterprise Service Bus)企业服务总线[3]。通过总线将多个系统连接起来,但是这种总线模式在移植性和扩展性方面存在不足,此外,SOA仍然没有从根本上解决遗留系统对接难度较大、切换时间长、成本高、性能降低等问题,致使SOA难以在软件中普及使用。
为适应移动互联网高速发展以及在项目开发敏捷、精益、持续交付等应用需求背景,系统前端展示已经不再局限于单一的Web、Win-Form、APP(原生App和WebAPP)形式,传统的单体应用系统面临功能重复开发、功能监控与评估(性能)难以进行,由于软件构件复用效率低[4],当面对业务需求变更时,使得应用系统臃肿、维护困难,频繁部署,甚至给软件测试也带来了更多不确定性,导致系统无法持续工作[5~6],此外高并发性是单体应用难以逾越的鸿沟,为了解决上述问题,基于微服务(MicroService)实现组件化成为系统设计的新选择,并得到飞速的发展和应用,在微服务架构中,通过将系统按服务组件化分解,各个服务之间通过Http等通信协议进行协作,并且各个服务都可以单独开发、部署,最终通过服务之间组合与调用对外完成系统功能[7]。
本文采用Spring Cloud微服务架构对通用考核系统进行重构,通过Spring Boot构建服务组件,服务之间采用HTTP协议的RESTful API方式完成服务调用与数据交互(SON格式),使用Spring Cloud核心组件Netflix完成服务组件注册管理,API网关关封装了系统内部微服务架构,为每个服务调用者提供一个定制的API,统一完成如身份验证、监控、负载均衡、缓存、请求分片与管理、静态响应处理,通过服务调用限流、熔断机制、负载均衡等措施,实际应用表明:该系统在高并发客户访问的情况下,在响应迅速和稳定性等方面,较传统的单体模式的系统提升明显[8]。
通用考核系统主要功能包括考核试题库管理、考核过程管理、考核成绩评定、考核数据分析、考生注册等,其中,考核过程管理功能中在线考核部分涉及多种前端显示形式,如Web网页、移动终端APP、桌面程序Win-Form等多种形式,并且存在高并发访问情况出现,稳定性与安全性要求高,为了提升系统扩展性和降低耦合度,系统实现时将前端显示和后端服务调用分离。
通过将系统功能按微服务设计思想:服务组件化,功能拆分成多个小型服务,这些小型服务都在各自独立的进程中运行,服务之间通过基于HTTP的 RESTful API进行通信协作[9~10]。被拆分成的每一个小型服务都围绕着系统中的某一项或一些耦合度较高的业务功能进行构建,并且每个服务都维护着自身的数据存储、业务开发、自动化测试案例以及独立部署机制[11],由于采用轻量级的通信协作基础,所以这些微服务甚至可以使用多种编程语言来实现[12],系统微服务划分为
图1 系统微服务组件化
图2 系统微服务组成
考生注册微服务主要提供考生在线报名服务,并后续考核过程提供考生数据,试题库微服务提供考核题库服务,并为考核试卷微服务提供试题数据,在线考核微服务主要提供在线考核,通过部署多个微服务以及负载均衡、熔断等机制,具备高并发、稳定性,数据分析微服务提供整个系统的分析和数据统计支持,不仅可以通过RESTful API访问其他服务数据,还可以通过分布式消息方式获取考核过程实时数据。
当前微服务框架主要有Seneca(一种基于Node.js的服务框架)、Dubbo、Dropwizard等,其中:Spring Cloud是一个基于Spring Boot实现一些列框架的集合,为开发者提供了在分布式系统的配置管理、服务发现、断路器、智能路由、微代理、控制总线等一些列微服务架构生态链,与Dubbo框架采用的RPC通信方式相比,Spring Boot采用HTTP的REST方式,尽管从一定程度上牺牲了服务调用的性能,但也避免了RPC带来的服务提供方与调用方在代码上的强依赖的缺点,REST相比RPC更为灵活,服务提供方和调用方的依赖更少,这在强调快速演化的微服务环境下,适用性更强[13]。
Spring Cloud是一系列框架的有序集合,如服务发现注册、配置中心、负载均衡、断路器、数据监控等微服务基础设施,通过Spring Boot进行再封装屏蔽掉了复杂的配置和实现原理,提供了整套易于部署和维护的分布式系统开发工具包,可快速进行微服务架构模式应用的开发,实现微服务架构模式的应用。
Spring Cloud框架集成Netflix框架中相关微服务基础设施组件,提供高可用的微服务基础设施组件,主要包括:
1)Netflix Eureka是一个RESTful服务,是微服务框架中的服务注册中心组件,由Eureka Server和Eureka Client组成,Eureka Server分用作服务注册服务器,Eureka Client是一个java客户端,用来简化与服务器的交互、作为轮询负载均衡器,并提供服务的故障切换支持。
2)Netflix Zuul该组件是公共网关入口组件,负责微服务集群中服务的路由,通过配置映射指定服务URL分发请求,也可与服务注册中心结合通过服务的ID分发请求[14]。
3)Netflix Hystrix是微服务框架中的服务断路器,防止一个应用程序多次试图执行一个操作失败时,允许它继续而不等待故障恢复或者浪费CPU周期,负责服务的调用熔断控制、降级处理,通过配置熔断和降级规则,实现服务调用故障的快速处理,保障服务调用快速响应,避免雪崩效应的产生。
4)Netflix Ribbon主要提供客户侧的软件负载均衡算法,分为随机、轮训、加权等负载均衡算法,结合服务注册中心实现服务间调用的软负载。
5)Spring Cloud Config是微服务框架中的公共配置组件,使用该组件可实现微服务集群的参数的统一配置,该组件可通过GIT SVN或本地文件存储,实现公共信息配置。
图3 Spring Cloud技术架构图
通用考核系统前端作为一个(客户端)服务消费者,有实现有多种形式,以Spring Boot框架开发应用为例,构建一个通用考核系统前端,通过调用按照微服务组件划分好的一系列服务,完成整个系统的业务流程,如图4所示。
图4 基于Spring Cloud架构系统微服务设计
通过使用Netflix开源服务发现Eureka组件完成微服务注册和发现,该组件包括Server和Client两部分,Eureka Server提供服务发现的能力,微服务部署后将在Eureka Server注册自身信息,微服务启动后,会周期性往Server发送心跳信息,当Eureka Server在既定的时间内没有收到某个微服务实例的心跳,Eureka Server将注销该实例,每个Eureka Client相当于一个服务请求客户端,调用在Server上注册的服务。
首先部署Eureka Server服务,通过微服务基础设施组件Spring Boot,建立Maven工程,并添加spring-cloud-starter-eureka-server依赖,在启动类添加注解@EnableEurekaServer。在配置文件application.yml中配置Eureka Server服务;同样,使用Spring Boot建立微服务提供者,添加spring-cloud-starter-eureka依赖,启动类添加@EnableDiscoveryClient注解,在 application.yml中配置Eureka Server信息。
依次启动Eureka Server服务、微服务提供者,访问Eureka Server即可查看微服务注册成功,实际应用中单节点的Eureka Server如果发生宕机情况,尽管Client端会将服务注册信息缓存到本地[15],不会影响服务的调用,但是当服务提供者不可用时,由于Eureka Client端没能及时更新,会影响系统的可靠性,此时可通过建立Eureka Server集群的方式解决此类问题,只需在Client端配置多个Server地址,并在多个Server上实现微服务相互注册的配置即可。
本系统中在线考核微服务与在线学习微服务需具备应对高并发、高稳定性的能力,为了解决高并发的问题,通过部署多个微服务实例实现,并且在调用该微服务时通过Netflix Ribbon实现服务负载均衡,在Spring Cloud中,Ribbon可与Eureka服务注册中心配合使用,Ribbon客户端可从Eureka Server获取服务提供者列表,并基于设定的负责均衡算法,请求其中一个服务实例,此外,Netflix Ribbon可以脱离Eureka服务注册中心,独立完成多个服务实例之间的负载均衡策略[16]。
在微服务架构中,完成一个业务处理通常需要多个服务组合与调用,微服务之间难免存在依赖关系,现实中微服务不可能保证100%可用,假定某个基础服务出现故障,会导致一系列级联故障,这种现象称为雪崩效应,雪崩效应描述的是服务提供方不可用时,导致服务消费者,并将不可用逐渐放大的过程,例如本系统中当同时在线考核人数过多,导致某在线考核微服务实例出现响应过慢现象,如果继续陆续有更多的请求访问该实例时,将会出现越来越多的请求得不到及时处理,且对应的线程占据的资源也越来越多得不到释放,最终导致该服务实例不可用。为了解决上述问题,采用Netflix Hystrix实现服务请求超时机制和断路器模式,用于隔离访问远程系统、服务等,放置服务访问或请求级联失败,从而提升系统的可用性和容错性。
微服务网关的功能是封装各个微服务的内部结构,介于客户端请求(服务消费者)和微服务提供之间的中间层,外部请求只需要与服务网关进行交互即可,而不是直接调用特定的微服务接口[17],此外微服务网关还完成以下工作:
1)统一在服务网关层完成认证,然后再将请求调用服务提供者,避免了在每个微服务中多次认证。
2)易于监控微服务的运行及调用状态,在服务网关完成对微服务统一监控和分析。
Zuul是Netflix开源微服务网关,与Eureka、Ribbon和Hystrix等组件配合使用,用来提供动态路由、监控、鉴权、安全、调度等功能,将权限控制等一些业务逻辑抽离出来,单独放到Zuul里,使得服务组件更简单,具有更好的可复用性。
通过组件Spring Boot,建立Maven工程,并添加spring-cloud-starter-zuul依赖,在启动类添加注解@EnableZuulProxy。在配置文件application.yml中配置Eureka Server服务;在application.yml中配置Eureka Server、微服务ID等信息,即可通过路由访问微服务。
spring.application.name=zuul-service
server.port=8877
eureka.client.serviceUrl.defaultZone=http:∕localhost:8888∕eureka∕
#注册服务,通过微服务ID进行路由
zuul.routes.exam-online.path=∕exam-online∕**
zuul.routes.exam-online.serviceId=exam-online
依次可以完成其他微服务路由,或按默认情况Zuul会代理所有注册到eureka的服务,路由规则:http:∕<ZUUL_HOST>∕<ZUUL_PORT>∕<ServiceID>转到ServiceID对应的微服务。
本系统建立使用Spring Cloud框架组件完成通用考核系统核心业务的微服务设计实现,针对在线考核(exam-online)微服务与在线学习(learn-online)微服务并发量大、稳定性要求高的特点,通过部署多个服务实例,采用Netflix Ribbon和Hystrix组件实现服务访问的负载均衡、超时机制和断路器模式,实验测试中exam-online和learn-online微服务各部署2个实例。
通过 Zuul网关服务,多次访问 http:∕<IP>:8877∕exam-online∕1,设定服务请求客户端负载均衡为轮询机制,exam-online微服务实例运行后台显示依次交叉调用,当微服务并发请求量大,可通过部署更多微服务实例的方法提升服务响应速度;当微服务实例部署的服务器硬件性能差异较大时,建议采用加权的负载均衡算法。
图5 微服务实例部署
通过建立Eureka Server集群的方式可以解决单个Eureka Server宕机带来的服务注册信息无法及时更新的问题,此外,由于使用Zuul组件实现统一的微服务访问路由转发,当并发量过高时,单节点的Zuul服务将成为整个系统运行的一个瓶颈,可以通过部署多个Zuul节点并注册到Eureka Server,即建立Zuul集群方式实现网关服务的高可用,并且此时Zuul客户端可使用Ribbon负载均衡地请求Zuul集群。
通过将系统核心业务升级微服务组件化,与传统的业务系统构建方法相比,面对实时性、并发量、可靠性要求的更高情况下,采用Spring Cloud框架构建微服务优势明显,尤其性能、扩展性提升明显,系统完全能适应高并发访问,通过微服务运行监控系统运行状态,便于定位系统运行中的瓶颈和对系统进行评估(性能),从而能有针对性实施系统组件升级,达到系统运行最优状态[18]。
本文分析传统的单体应用软件的不足,总结了使用微服务框架应在应对扩展性差、可靠性不高、维护成本高等问题的优势,提出了采用Spring Cloud微服务架构完成通用考核系统的设计与实现,在介绍Spring Cloud核心组件功能基础上,重点分析使用微服务架构完成微服务注册与发现、服务负载均衡与容错处理和构建Zuul服务网关的方法,实验表明通过建立Eureka Server集群、Zuul集群、多微服务实例(负载均衡)等措施,使用全微服务架构升级的系统具备适应超大规模的并发访问能力,并且基于微服务RESTful API数据交互方式,各个微服务模块可以单独开发和部署,极大提高系统的可维护性和扩展性,本文采用的微服务构建方法在对传统单体应用系统升级改造具有一定的通用性和借鉴作用。