资源描述
微服务系统设计方案
1. 微服务本质
微服务架构从本质上说其实就是分布式架构,和其说是一个新架构,不如说是一个微服务架构风格。
简单来说,微服务架构风格是要开发一个由多个小服务组成应用。每个服务运行于独立进程,而且采取轻量级交互。多数情况下是一个HTTP资源API。这些服务含有独立业务能力并能够经过自动化布署方法独立布署。这种风格使最小化集中管理,从而能够使用多个不一样编程语言和数据存放技术。
对于微服务架构系统,因为其服务粒度小,模块化清楚,所以首先要做是对系统整体进行功效、服务计划,优先考虑怎样在交付过程中,从工程实践出发,组织好代码结构、配置、测试、布署、运维、监控整个过程,从而有效表现微服务独立性和可布署性。
本文将从微服务系统设计阶段、开发阶段、测试阶段、布署阶段进行综合叙述。
了解微服务架构和理念是关键。
2. 系统环境
名称
版本
说明
JDK
1.8
Spring Boot
Spring Framework
Ribbon
kafka
RabbitMQ
3. 微服务架构挑战
Ø 可靠性:
因为采取远程调用方法,任何一个节点、网络出现问题,全部将使得服务调用失败,伴随微服务数量增多,潜在故障点也将增多。
也就是没有充足保障机制,则单点故障会大量增加。
Ø 运维要求高:
系统监控、高可用性、自动化技术
Ø 分布式复杂性:
网络延迟、系统容错、分布式事务
Ø 布署依靠性强:
服务依靠、多版本问题
Ø 性能(服务间通讯成本高):
无状态性、进程间调用、跨网络调用
Ø 数据一致性:
分布式事务管理需要跨越多个节点来确保数据瞬时一致性,所以比起传统单体架构事务,成本要高得多。另外,在分布式系统中,通常会考虑经过数据最终一致性来处理数据瞬时一致带来系统不可用。
Ø 反复开发:
微服务理念崇尚每个微服务作为一个产品看待,有自己团体开发,甚至能够有自己完全不一样技术、框架,那么和其它微服务团体技术共享就产生了矛盾,反复开发工作即产生了。
没有最好,只有最适合自己。
4. 架构设计
4.1. 思维设计
微服务架构设计根本目标是实现价值交付,微服务架构只有遵照DevOps理念方可进行更顺畅,思维方法转变是最关键。
实现微服务技术架构,现有产品需要进行技术上改善和相关配套服务实现,采取分阶段实施、和试点产品优先实施策略,关键包含以下:
一、技术上改善:
1、前后端分离,web前端经过Http/Https协议调用微服务API网关,由API网关再经过路由服务调用对应微服务
2、不一样微服务之间经过REST方法相互调用
3、微服务之间经过消息中间件实现消息交互机制
二、配套服务和功效实现 :
1、需要进行对应自动化服务实现,包含自动化构建、自动化安装布署、自动化测试、自动化平台公布(Docker实现)
2、管理服务,对于微服务架构,必需配套对应监控和管理服务、日志管理服务等
3、协作服务,利用DevOps思想提升开发、测试、运维高效沟通和协作,实现开发和运维一体化
4.2. 微服务架构设计
1、我们把整个系统依据业务拆分成若干个子系统或微服务。
2、每个子系统能够布署多个应用,多个应用之间使用负载均衡。
3、需要一个服务注册中心Eureka,全部服务全部在注册中心注册,负载均衡也是经过在注册中心注册服务来使用一定策略来实现。
Eureka可布署多个,进行高可用确保。
4、全部用户端全部经过同一个网关地址访问后台服务,经过路由配置ZUUL网关来判定一个URL请求由哪个服务处理。请求转发到服务上时候使用负载均衡Ribbon。
5、服务之间采取feign进行调用。
6、使用断路器hystrix,立即处理服务调用时超时和错误,预防因为其中一个服务问题而造成整体系统瘫痪。
7、还需要一个监控功效,监控每个服务调用花费时间等。
8、使用SpringCloud Config进行统一配置管理,需要考虑和企业配置管理平台怎样配合使用。
9、Hystrix,监控和断路器。我们只需要在服务接口上添加Hystrix标签,就能够实现对这个接口监控和断路器功效。
10、Hystrix Dashboard,监控面板,她提供了一个界面,能够监控各个服务上服务调用所消耗时间等。
11、Turbine,监控聚合,使用Hystrix监控,我们需要打开每一个服务实例监控信息来查看。而Turbine能够帮助我们把全部服务实例监控信息聚合到一个地方统一查看。这么就不需要挨个打开一个个页面一个个查看。
架构可靠性确保:
在关键节点做主备、集群布署,预防单点故障。
待后续确定问题:
1、Access Control:Zuul网关提供了相关控制功效,和本企业CAS怎样结合使用
2、Config Server:Spring Cloud提供了远程配置中心,和本企业配置管理平台怎样结合使用
5. 设计阶段
5.1. 总体设计
1、功效计划:对产品功效进行拆分,拆分为若干个微服务;一个功效能够创建多个微服务并布署在多个服务器节点上,方便进行负载均衡。
2、设计原子服务层,梳理和抽取关键应用、公共应用,作为独立服务下沉到关键和公共能力层,逐步形成稳定服务中心,使应用能愈加快速响应多变用户需求。
3、为每个服务设计API接口(REST方法)
4、为不一样服务进行分类,不一样类型服务需要资源不一样,能够配置不一样资源,包含CPU、内存、存放等。
5.2. 服务拆分标准
1、粒度微小:
依据业务功效划分服务粒度,总标准是服务内部高内聚,服务之间低耦合。
2、责任单一:
每个服务只做一件事,即单一职责标准。
3、隔离性标准:
每个服务相互隔离,且不相互影响
4、业务无关优先标准:
基础服务,是部分基础组件,和具体业务无关。比如:短信服务、邮件服务。这里服务最轻易划分出来做微服务,也是我们第一优先级分离出来服务。
5.3. 服务计划
为实现负载均衡,许可相同服务在多个节点注册相同服务名,不一样端口。假如没有前期计划,不一样服务提供者可能会注册相同服务名,造成消费者调用服务时产生调用混乱。
所以,需进行服务名统一计划:
1、计划期统一制订每个服务提供者服务名或模块标示。
2、服务名命名规则:ModuleName_ServiceName,且全部字符小写,不一样单词之间以下划线分隔。如用户管理模块提供了获取用户信息服务,则命名为:user_get_info。
3、新增服务名时,需要提出申请,审批经过后方可使用,为降低审批复杂度,可只审批ModuleName,即在模块内部能够自由增加服务名,不需要进行审批。
5.4. 开发策略
总体标准:不一样微服务需进行物理隔离。
1、SVN策略:SVN上创建独立分支,不一样微服务代码提交不受相互影响;
---由配置管理员统一控制。
问题:开发分支和集成份支,全部将增加很多,维护工作量增加。
2、编译策略:代码编译时,各个微服务独立编译、打包,杜绝直接依靠;
3、工程构建:代码开发时,各微服务创建独立工程,工程之间不能产生直接依靠
4、连续集成:每个微服务独立实施连续集成。
5、版本集成:由统一集成工具,实现自动化版本集成,将全部微服务集成到统一版本公布包中。
5.5. 版本策略
每个微服务能够独立制作版本,伴伴随服务增多,SVN分支增多,版本也将增多,版本管理复杂度将成指数级增加。在服务之间依靠较多时,每个服务升级或降级全部将影响其它服务正常运行。
所以需实施以下策略:
1、全部服务版本制作交由专业版本管理员实施。
2、采取自动化版本制作策略,最大程度降低人工操作。
3、每个服务版本必需有具体版本计划、版本说明,对于版本说明要制订模板,明确需要提交内容、版本号、SVN标签等。
4、对项目经理要求提升,需对整体版本计划有严格制订,尤其是版本之间依靠关系要很明确,版本升级、降级风险评定需完全充足。
5、接口管理:严格实施接口管理制度,任何接口变更必需进行审批、发公告等步骤。
5.6. 数据库挑战和策略
每个微服务全部有自己独立数据库,那么后台管理联合查询怎么处理?这应该是大家会普遍碰到一个问题,有三种处理方案。
1)严格根据微服务划分来做,微服务相互独立,各微服务数据库也独立,后台需要展示数据时,调用各微服务接口来获取对应数据,再进行数据处理后展示出来,这是标准使用方法,也是最麻烦使用方法。
2) 将业务高度相关表放到一个库中,将业务关系不是很紧密表严格根据微服务模式来拆分,这么既能够使用微服务,也避免了数据库分散造成后台系统统计功效难以实现,是一个折中方案。
3)数据库严格根据微服务要求来切分,以满足业务高并发,实时或准实时将各微服务数据库数据同时到NoSQL数据库中,在同时过程中进行数据清洗,用来满足后台业务系统使用,推荐使用MongoDB、HBase等。
第一个方案适合业务较为简单小企业;第二种方案,适合在原有系统之上,慢慢演化为微服务架构企业;第三种适合大型高并发互联网企业。
提议,我们目前采取第二种方案。
5.7. 负载均衡
不再采取通常增加负载均衡服务器方法进行负载均衡,如F5、Nginx、LVS等,而是把负载均衡功效以库方法集成到服务消费方进程内,这种方案称为软负载均衡(Soft Load Balancing)或用户端负载均衡。在Spring Cloud中配合Eureka服务注册功效,Ribbon子项目则为REST用户端实现了负载均衡。
使用Ribbon进行负载均衡,其工作原理能够概括为下面四个步骤:
1. Ribbon首先依据其所在Zone优先选择一个负载较少Eureka Server;
2. 定时从Eureka Server更新并过滤服务实例列表;
3. 依据指定负载均衡策略,从可用服务器列表中选择一个服务实例地址;
4. 然后经过RestClient进行服务调用。
Ribbon本身提供了下面多个负载均衡策略:
· RoundRobinRule: 轮询策略,Ribbon以轮询方法选择服务器,这个是默认值。所以示例中所开启两个服务会被循环访问;
· RandomRule: 随机选择,也就是说Ribbon会随机从服务器列表中选择一个进行访问;
· BestAvailableRule: 最大可用策略,即先过滤出故障服务器后,选择一个目前并发请求数最小;
· WeightedResponseTimeRule: 带有加权轮询策略,对各个服务器响应时间进行加权处理,然后在采取轮询方法来获取对应服务器;
· AvailabilityFilteringRule: 可用过滤策略,先过滤出故障或并发请求大于阈值一部分服务实例,然后再以线性轮询方法从过滤后实例清单中选出一个;
· ZoneAvoidanceRule: 区域感知策略,先使用主过滤条件(区域负载器,选择最优区域)对全部实例过滤并返回过滤后实例清单,依次使用次过滤条件列表中过滤条件对主过滤条件结果进行过滤,判定最小过滤数(默认1)和最小过滤百分比(默认0),最终对满足条件服务器则使用RoundRobinRule(轮询方法)选择一个服务器实例。
5.8. 性能策略
1、网络优化:优化组网结构,提升网络间通讯性能;
2、配置优化:优化Spring Cloud组件集和其它组件配置信息,使得性能最大化。
5.9. 技术管理策略
微服务架构理念中指出各微服务能够独立建设,能够使用不一样技术、语言、框架等,方便能愈加快速使用新技术、新框架等响应特定用户需求,处理单体应用架构更新技术、更新框架时面临困难或阻碍。
但这也同时带来了很多问题,以下:
1、各服务是否能够任意使用自己技术、自己组件、框架呢?假如这么,势必带来更大管理困难、维护困难、技术共享困难。
2、公共方法怎样实现共享?如格式化时间一个简单方法需要共享,也需要封装为一个服务接口吗?
管理策略:
1、总体标准:仍然需要进行统筹考虑,全部组件统一管理,组件放置在产品仓库中,每个产品或服务需要共享组件时,从产品仓库获取。
2、特殊情况:特殊服务需要使用特殊组件、框架,需提出申请,统筹计划后进行决议。
6. 开发阶段
6.1. 服务调用
6.1.1. AIP网关调用
全部服务经过Zuul网关进行调用,不许可直接调用微服务提供者。
Zuul可能会成为系统瓶颈,在项目复杂时可考虑为Zuul进行主备或负载均衡处理。
6.1.2. 同时调用
采取HTTP REST方法进行调用,针对业务需求能够进行负载均衡,负载均衡调用方法有两种:
1、FeignClient
2、RestTemplate
提议使用FeignClient方法进行服务调用。
不管是什么方法,她全部是经过REST接口调用服务http接口,参数和结果默认全部是经过Jackson序列化和反序列化。因为Spring MVCRestController定义接口,返回数据全部是经过Jackson序列化成JSON数据。
6.1.3. 异步调用
rabbitMq、kafka、Spring Cloud Stream均是能够选择方案。
· Spring Cloud Stream,基于 Redis、Rabbit、Kafka 实现消息微服务,简单申明模型用以在 Spring Cloud 应用中收发消息。
6.1.4. 服务间调用权限验证
通常我们API接口全部需要某种授权才能访问,登陆成功以后,然后经过token或cookie等方法才能调用接口。
使用Spring Cloud Netfix框架话,登录时候,把登录请求转发到对应用户服务上,登陆成功后,会设置cookie或header token等。然后用户端接下来请求就会带着这些验证信息,从Zuul网关传到对应服务上进行验证。
Zuul网关在把请求转发到后台服务时候,会默认把部分header传到服务端,如:Cookie、Set-Cookie、Authorization。这么,用户端请求相关headers就能够传输到服务端,服务端设置cookie也能够传到用户端。
不过,假如你想严禁一些header透传到服务端,能够在Zuul网关application.yml配置里经过下面方法禁用:
zuul:
routes:
users:
path: /users/**
sensitiveHeaders: Cookie,Set-Cookie,Authorization
serviceId: user
刚才说了我们某个服务有时候需要调用另一个服务,这时候,这个请求不是用户端提议,她请求header里面也不会有任何验证信息。这时候,要么,经过防火墙等设置,确保服务间调用接口,只能某多个地址访问;要么,就经过某种方法设置header。
同时,假如你想在某个服务里面取得这个请求真是IP,(因为请求经过网关转发而来,你直接经过request取得ip得到是网关IP),就能够从headerX-Forwarded-Host取得。假如想禁用这个header,也能够:
zuul.addProxyHeaders = false
假如你使用RestTemplate方法调用,能够在请求里面添加一个有headerOptions。
也能够经过以下拦截器方法设置,它对RestTemplate方法和FeignClient方法全部能够起作用:
@Bean
public RequestInterceptor requestInterceptor() {
return new RequestInterceptor() {
@Override
public void apply(RequestTemplate template) {
String authToken = getToken();
template.header(AUTH_TOKEN_HEADER, authToken);
}
};
}
6.1.5. 服务编排
关键作用是降低项目中相互依靠。比如现在有项目a调用项目b,项目b调用项目c...一直到h,是一个调用链,那么项目上线时候需要先更新最底层h再更新g...更新c更新b最终是更新项目a。这只是这一个调用链,在复杂业务中有很多调用,假如要记住每一个调用链对开发运维人员来说就是灾难。
有这么一个好措施能够尽可能降低项目标相互依靠,就是服务编排,一个关键业务处理项目,负责和各个微服务打交道。比如之前是a调用b,b掉用c,c调用d,现在统一在一个关键项目W中来处理,W服务使用a时候去调用b,使用b时候W去调用c。
其实能够了解为面向对象设计,降低方法之间一层层嵌套调用,而采取一个方法进行业务步骤串联,如方法W实现一个完整业务处理,则采取下面方法:
function w()
{
1、调用方法a;
2、调用方法b;
3、调用方法c;
}
6.2. 服务熔断处理
在服务之间进行调用时,因为多种原因会造成远程服务不可用或压力过载等异常造成故障蔓延,此时需要有一个机制进行保护处理。Spring Cloud经过NetflixHystrix组件实现熔断和降级处了处理此问题。断路器(Cricuit Breaker)是一个能够在远程服务不可用时自动熔断(打开开关),并在远程服务恢复时自动恢复(闭合开关)设施,Spring Cloud经过NetflixHystrix组件提供断路器、资源隔离和自我修复功效。
Spring cloud Hystrix 熔断器
6.3. 统一日志管理
不一样微服务布署在不一样节点上,登录每个节点查看日志是比较麻烦,同时对于需要关联多个微服务日志联合查看分析情况将愈加麻烦。伴随节点数量增加,假如没有适宜管理机制和工具,定位问题、发觉问题复杂性将越来越大,将成指数级增加,所以需要进行统一日志管理。
1、建立统一日志管理规范;
2、开发并使用统一日志组件,为全部微服务提供统一日志服务,由log4j或Blitz4j封装;
3、在每个服务节点上布署日志采集Agent组件,由此Agent进行日志采集和转发;
4、建立统一日志中心,全部日志写入日志中心。
说明:上述日志实现由企业“日志管理平台”进行实现,采取是ELK集合框架。
6.4. 统一监控管理
使用Hystrix组件进行服务监控,使用Nagios进行服务器等资源监控。
1、Hystrix,监控和断路器。我们只需要在服务接口上添加Hystrix标签,就能够实现对这个接口监控和断路器功效。
2、Hystrix Dashboard,监控面板,她提供了一个界面,能够监控各个服务上服务调用所消耗时间等。
3、Turbine,监控聚合,使用Hystrix监控,我们需要打开每一个服务实例监控信息来查看。而Turbine能够帮助我们把全部服务实例监控信息聚合到一个地方统一查看。这么就不需要挨个打开一个个页面一个个查看。
6.5. 统一配置管理
实现各微服务统一参数配置和版本管理,可采取企业配置管理平台或Spring Cloud Config配置中心。
Spring Cloud Config配置中心
Spring Cloud Config就是我们通常意义上配置中心。Spring Cloud Config-把应用原本放在当地文件配置抽取出来放在中心服务器,本质是配置信息从当地迁移到云端。从而能够提供愈加好管理、公布能力。
Spring Cloud Config分服务端和用户端,服务端负责将git(svn)中存放配置文件公布成REST接口,用户端能够从服务端REST接口获取配置。但用户端并不能主动感知到配置改变,从而主动去获取新配置,这需要每个用户端经过POST方法触发各自/refresh。
为处理配置信息能立即通知到各服务,同时降低每个微服务处理配置信息更新复杂度,为此我们经过消息总线来处理此问题,方案以下:
1. Git仓库、Config Server、和微服务“Service A”、 “Service B”实例中全部引入了Spring Cloud Bus,所以她们全部连接到了RabbitMQ消息总线上。
2. 从Git仓库中配置修改到提议/bus/refreshPOST请求这一步能够经过Git仓库Web Hook来自动触发。
3. /bus/refresh请求不再发送到具体服务实例上,而是发送给Config Server,并经过destination参数来指定需要更新配置服务或实例。
4. 因为全部连接到消息总线上应用全部会接收到更新请求,所以在Web Hook中就不需要维护全部节点内容来进行更新,从而处理了经过Web Hook来逐一进行刷新问题。
6.6. 分布式session
采取Redis作为缓存组件和session共享组件。
6.7. REST资源响应结构
制订规范和解析方法。
6.8. API调用链追踪
微服务架构上经过业务来划分服务,经过REST调用,对外暴露一个接口,可能需要很多个服务协同才能完成这个接口功效,假如链路上任何一个服务出现问题或网络超时,全部会形成造成接口调用失败。伴随业务不停扩张,服务之间相互调用会越来越复杂。
Spring Cloud Sleuth 关键功效就是在分布式系统中提供追踪处理方案,而且兼容支持了 zipkin,你只需要在pom文件中引入对应依靠即可。
6.9. 单元测试
做微服务架构,进行系统测试复杂度较大,为确保产品质量和开发、测试效率,单元测试是必不可少。
可采取Mock方法进行测试模拟,由连续集成进行自动化单元测试实施和结果输出。
6.10. 代码调试
对于单体架构系统,可直接当地化调试,但对于微服务架构,接口间调用需采取远程通讯方法,也就是说被调用服务必需开启后方可被调用,所以当微服务增多时,你可能需要开启大量微服务或web服务器,这给当地化调用和调试带来了困难。
处理方案待研究。
7. 测试
7.1. 自动化测试
Ø 单元测试:
由开发人员实现。
采取Mock方法进行测试模拟,由连续集成进行自动化单元测试实施和结果输出。
Ø 业务测试:
开发进行实现,测试也需考虑怎样实现。
将多个服务或业务单元进行串联,测试一个完整业务,甚至是不一样业务之间组成系统测试,需要采取相关自动化测试框架实施,如RobotFramework自动化测试框架。
7.2. 依靠测试
也能够称为接口测试或契约测试,在微服务逐步增多情况下,怎样有效确保服务之间能够根据接口约定正常工作,即符合契约,成为微服务实施过程中,测试面临关键挑战。
一、开发自动化接口测试工具,
1、检测接口是否满足约定
2、检测接口是否发生改变
3、检测接口是否能够正常被调用。
二、测试方法:
采取基于消费者驱动契约测试,测试架构以下:
其优势以下:
Ø 从价值实现角度定义契约
从消费者使用契约角度出发,首先确保消费者基于此契约是能够实现价值,有了这个前提,再使用契约来验证提供者,假如提供者提供契约同定义契约一致,则证实提供者提供契约是能够实现服务消费者。经过这种方法,使得更聚焦于怎样从价值实现出发。
Ø 隔离消费者和提供者测试
对于契约消费者和提供者能够分开独立测试,有效处理传统集成测试服务架构弊端,将微服务接口测试成本降到最低。
三、测试工具:
Pact、Janus、Pacto等。
7.3. 系统测试
7.4. 熔断测试
1、经过停止微服务方法测试服务路由正确性
2、经过压力测试,将某个微服务产生过载等异常,测试服务熔断或降级
3、经过压力测试,测试负载均衡策略正确性
7.5. 性能测试
原有当地化api调用将会变成REST远程调用,调用速度势必受到影响,所以需要对系统性能进行考虑和性能测试,关键影响原因以下:
1、网络:远程调用时受到网络通讯速度影响,这包含到网络速度、网络布署和系统架构,有相互依靠服务应采取就近布署标准。
2、服务器:受到远程服务所在服务器性能影响。
3、数据量:数据量这里指是数据大小和数据传输次数和频率,此时REST调用方法会产生瓶颈,当然,最好方法是避免此种情况发生,此种场景采取消息中间件方法异步通讯。
8. 连续集成
1、连续集成:每个微服务独立实施连续集成。
2、版本集成:由统一集成工具,实现自动化版本集成,将全部微服务集成到统一版本公布包中。
3、连续集成可制作多个场景版本,包含测试环境、开发环境、生产环境。
4、统计测试覆盖率等指标数据。
5、工具:Jenkins、Sonar等。
9. 连续布署
1、经过连续集成自动制作公布版本Docker镜像;
2、将docker镜像自动上传到docker容器中。
10. 运维阶段
10.1. 远程升级
微服务不停增加后,意味着布署容器也在同时增加,对于后续升级维护工作量将会逐步增加,开发统一管理中心,支持远程维护和升级将可降低运维复杂度。
10.2. 统一配置中心
使用Spring Cloud Config或配置管理平台进行统一配置管理。
10.3. 统一日志中心
使用日志管理平台进行统一日志采集、日志分析。
展开阅读全文