微服务架构中的重要功能% E6 G; z" @+ f3 m
一个简单的微服务架构,如图:
从0到1了解微服务架构设计及使用(下篇)
从0到1了解微服务架构设计及使用(下篇)
微服务的基础架构及功能
# h2 k; R; _/ j! F
从上述两张图中我们发现,应用被吃啊分为多个微服务进程后,进程内的方法调用变成了进程间的调用,这种变化会带来分布式系统的一系列问题,如:
/ i" y& i7 Q( ~+ f' v5 m2 E
✦服务的注册与发现
✦身份验证与授权
✦服务的伸缩控制
✦反向代理与负载均衡
✦路由控制
✦流量切换
✦日志管理
✦性能度量、监控与调优
✦分布式跟踪
✦过载保护
✦服务降级
✦服务部署与版本升级策略支持
✦错误处理
接下来我们从如下几个方面做说明解释。
' \+ }7 |6 m3 z+ e5 A4 j: N
4.1、服务注册与发现
* M- U6 x: U+ \" b
从0到1了解微服务架构设计及使用(下篇)
/ @( ~/ n! ]9 U9 n' U
在微服务架构中有一个重要的组成部分——服务注册中心(Service Registry),他负责管理各种服务功能包括服务的注册、发现、熔断、负载、降级等。
) x! F. p4 z, L9 y, u9 E
注册发现是微服务的基础。常用的做法是服务提供方启动时把自己的地址上报给“服务注册中心”,完成服务注册。这时服务调用方就可以通过“订阅”服务,动态的接收服务注册中心推送的服务地址列表,从而顺利找到正确的服务。
: c) e4 U C$ c1 q5 k1 w- W
4.2、网关:权限控制
# ^4 ?$ B9 R0 V: l; W9 \- R6 m之前我们提到过微服务架构中各个服务是通过接口进行调用,那么随着我们架构的庞大,我们很有可能会遇到搞混或者记不清调用关系的情况。
2 p, P& y* ~! i: D$ j H为了解决这种情况,微服务引入网关的概念:也就是在客户端和服务端之间加入一层网关,微服务网关是微服务架构中的核心组件,它是客户端请求的门户,它是调用具体服务端的桥梁,每次调用时进行权限的验证。API Gateway是一个服务器,也可以说是进入系统的唯一节点。
从0到1了解微服务架构设计及使用(下篇)
如上图,我们使用服务网关(APIG)来建立客户端与服务端(服务)之间的联系,当从客户端发送请求时,请求首先将进入服务网关,随后服务网关将请求路由到具体的服务端。
5 |0 }( z/ r5 A, J
在路由过程中,会涉及具体的路由算法,最简单的做法是在服务网关中解析客户端请求中的路径或请求头,从而路由到具体的服务端。
6 u0 e: R2 {, M9 u' K4 O6 k
为了确保系统具备较高的可用性,我们可部署多个相同的服务端。此时需在服务网关中设置相关路由算法,将请求随机路由到具体的服务端,当然也可以对客户端IP地址进行Hash算法,从而实现请求路由。
" n, ~, A0 a9 J8 z4.3、定位问题:链路追踪
! q( V/ l3 w' F4 z在微服务架构下,一个用户请求的实现往往会涉及到多个服务的调用。为了方便定位问题,我们需要能够记录每个用户请求时,微服务内部产生的调用次数及调用关系。这个就是链路追踪,如下图:
: x# d6 l+ [0 n
从0到1了解微服务架构设计及使用(下篇)
1 H, ?4 h ?" {5 h, p/ k4.4、服务扩容:高可靠性
9 ]$ a3 Z' o3 ]( H3 c; @" t' c
在微服务架构中,我们可以通过监控组件、日志分析组件或者服务限流、熔断、降级等策略去降低故障发生的可能性。然后故障总是有可能发生的,所以另外一个需要解决的问题就是如何降低故障的影响。
# Q: n c8 [0 t8 P: r8 `! u/ x2 [/ _
对可靠性的保障,最常用也是最有效的方法就是冗余,也就是我们对一个服务布置多个实例,一方面可以降低单个服务的访问压力,另一方面可以保障某个服务故障后还能有其他的实例继续提供访问。
2 \ j6 r. g. I- m1 h6 w! W4 {首先,需要部署一个服务发现服务,它提供所有已注册服务的地址信息的服务。
% j' p! m! F4 C& [/ N
DNS也算是一种服务发现服务。然后各个应用服务在启动时自动将自己注册到服务发现服务上。并且应用服务启动后会实时(定期)从服务发现服务同步各个应用服务的地址列表到本地。
% x# ]( i, W$ a/ L& P6 r b
服务发现服务也会定期检查应用服务的健康状态,去掉不健康的实例地址。这样新增实例时只需要部署新实例,实例下线时直接关停服务即可,服务发现会自动检查服务实例的增减。
) m) q9 f3 x/ {! O1 Y
服务发现还会跟客户端负载均衡配合使用,客户端得到可用的服务实例列表然后按照特定的负载均衡策略,分发请求到不同的服务。由于应用服务已经同步服务地址列表在本地了,所以访问微服务时,可以自己决定负载策略。
" u6 w+ \4 `& G+ Q/ J6 d! d4.5、服务容错:高可用性
( T0 n% v) X' v! z( o* N
微服务架构极大程度上避免了像紧耦合的单体架构这种一出现故障就牵一发而动全身的情况,但是另一方我们也不能保证大量服务每个都不出问题,特别是某些关键服务出现问题也可能导致系统整个停止。
( b0 g0 ]7 f o( Z& o所以为了尽可能降低故障的影响范围和周期,引入了熔断、隔离、限流、降级等措施来保障服务的持续可用性。
7 w% `" J2 U9 M5 v" R4.5.1、服务的限流
3 f6 `6 d& r0 h; S L) \8 R2 B
服务限流是指在一定时间段内限制服务的请求量以保护系统,主要用于防止突发流量而导致的服务崩溃,比如秒杀、抢购、双十一等场景,也可以用于
安全目的,比如应对外部暴力攻击。
* W* S6 H* r2 J" E7 k8 B
限流实现方案:
用户在Provider端使用限流策略,可以限制指定微服务向其发送请求的频率,达到限制每秒钟最大请求数量的效果。
7 P6 n# `6 t0 j1 N9 |
用户在Consumer端使用限流策略,可以限制发往指定微服务的请求的频率。
' w$ {5 h9 [' x- b z! b
接入端限流,通常使用负载均衡器实现。
; q9 Z* c6 S, Z$ N3 u3 u
常用的限流方法:
2 B& R2 A, r9 t1 X; E4 a& B
✦计数器法:
通过维护一个内部计数器,对一段时间的服务请求进行累计,判断计数器是否达到预先设定的阈值。
. f2 p& r* A3 [ V1 C
如果没有达到阈值,就允许请求通过,并且计数器加1;如果达到阈值,则拒绝服务,抛弃请求。进入下一个计时周期后,计数器清零,重新计数。
' K5 C4 f1 W9 p @+ L
计数器算法是限流算法中最简单的算法,缺点是有突刺现象,不仅请求通过的速率不均匀,而且请求输出的速率也不均匀,对后续处理的并发要求比较高。
0 b/ V7 _% j& _% N t$ G. K: F; x& P
比如:设定服务周期为1秒,请求的上限阈值为1000。
5 N3 T2 X: k) S. J! H0 X如果前1ms内已经收到1000个请求,那么剩下的时间都只能拒绝,而且后端服务需要并发处理1000个请求。
0 `4 W$ }% S% ^4 m* H
✦漏桶算法:
漏桶算法的原理可以这样理解,将服务请求想象成流入漏桶的水,漏桶中的水以恒定的速率从桶底流出,当流入漏桶的水速度过快,超过了漏桶容量时,则直接溢出。所以,漏桶算法能够控制服务请求按照固定速率均匀输出,平滑突发流量,实现流量整形,为后续处理提供一个稳定的流量。但是,漏桶算法无法控制请求按照一定的速率均匀输入。
8 T' G% P* |; d+ Y& W3 s: u" s✦令牌桶算法:
令牌桶算法是速率限制(Rate Limiting)和流量整形(Traffic Shaping)中最常使用的一种算法。典型情况下,令牌桶算法用来控制发送到网络上的数据的数目,并允许突发数据的发送。
; J% L6 w* Z6 j. @- G' B首先设定一个可以存放固定数量的令牌桶,使用某种机制以恒定的速度产生令牌。每次请求调用时,都必须去桶中获取令牌,只有拿到令牌,才能放行,否则只能等待可用的令牌,或者直接拒绝。如果桶中的令牌消耗的速度小于产生的速度,令牌就会不断地增多,直至填满,再产生的令牌就会从桶中溢出。
9 N- s/ q# ~" f5 [) C4.5.2、服务的熔断
9 T2 G n2 r7 v3 T- t
当一个服务因为各种原因停止响应时,调用方通常会等待一段时间,然后超时或者收到错误返回。如果调用链路比较长,可能会导致请求堆积,整条链路占用大量资源一直在等待下游响应。
B; I* t" p9 V4 r# K
所以当多次访问一个服务失败时,应熔断,标记该服务已停止工作,直接返回错误。当监控到改微服务正常工作后,再次恢复改调用链路。
7 j% [7 F6 H; Q: L" w
从0到1了解微服务架构设计及使用(下篇)
* s6 G6 g9 |% n: ~
熔断器的几种模式:
关闭状态:对应用无干涉,仅仅计算时间窗口内的失败次数。
开启状态:对服务的访问立即返回错误。
$ I+ e, L. r+ T0 [. e, A4 I
半开启状态:只允许少量请求调用服务,如果调用结果符合预期,就认为服务端问题已经修复,这样熔断器会关闭;否则认为熔断器仍然有问题,转换到开启状态,并重新计时。
4 X9 i/ t: P1 r C; j4.5.3、服务的降级
" W3 Z" L2 s( X% I& ?
降级是容错的一种特殊形式,当出现服务吞吐量巨大,资源不够用等情况,我们可使用降级机制关掉部分不重要、性能较差的服务,避免占用资源,以保证主体业务功能可正常使用。
" H2 O# m9 O* a4 h+ y# e3 Y4.5.4、服务的灰度发布
& G1 Q; B r. k; s* \! f
灰度发布是指在应用的新、旧版本间平滑过渡的一种发布方式。在应用发布与产品迭代中,通常会采用灰度发布来控制上线风险。
/ u+ y, U; ?, H; z1 ~: I* r在发布前先进行小规模的生产环境验证,让新版本的应用实例来承接、处理限定规模或范围的业务流量。
: O- u) c( m" D. r- k/ k通过收集使用体验的数据,对应用新版本的功能、性能、稳定性等指标进行评判,进而决定扩大新版本部署范围直至全量升级或回滚至老版本。
: z) R1 u. z" l- q$ G2 t! q根据业务特征在生产环境选择灰度组进行功能推广,并不断动态扩大灰度组,直至所有生产节点升级到新版本。
6 w0 Z6 y; Z* }+ S
从0到1了解微服务架构设计及使用(下篇)
1 r$ N7 ~/ ^$ c# Z ?
4.5.5、负载均衡
3 ]1 M( m, D- E# D/ X# j7 I7 E0 T; w
在微服务架构中,负载均衡是必须使用的技术,通过它来实现系统的高可用、集群扩容等功能。
6 C% V6 {4 a* N I# T! Z& i" M: ]$ b负载均衡可以分为两种:服务端负载均衡和客户端负载均衡。通常所说的负载均衡指服务器负载均衡,可通过硬件设备或软件来实现,硬件比如:F5、Array等,软件比如:LVS、Nginx等。
# N- o3 E% f$ r% k通过硬件或软件实现负载均衡均会维护一个服务端清单,利用心跳检测等手段进行清单维护,保证清单中都是可以正常访问的服务节点。
+ y* p' }2 e; K6 R$ M5 E& K
当用户发送请求时,会先到达负载均衡器(也相当于一个服务),负载均衡器根据负载均衡算法(轮训、随机、加权轮训)从可用的服务端列表中取出一台服务端的地址,接着进行转发,降低系统的压力。
4 M" B; r3 a: V* j. L7 W7 u, i6 m* B
而对于客户端负载均衡来说,与服务端负载均衡的主要区分点在于服务清单的存放位置。在客户端负载均衡中,客户端自己会存储一份服务端清单,它是通过从注册中心进行抓取得到的,同时也需要对此进行维护。
V1 A' x( `' }/ a% _ q7 }9 A
常见负载均衡策略:
7 _/ S2 ?7 C6 L
轮询:支持按照服务实例的位置信息顺序路由。
随机:提供服务实例随机路由。
响应时间权值:提供最小活跃数(时延)的权重路由,支持业务处理慢的服务实例接收较少的请求,防止系统停止响应。这种负载均衡策略适合请求量少且稳定的应用。
) d5 Z+ [$ p( ?6 w会话粘滞:会话粘滞是负载均衡器上的一种机制,在设定的会话保持时间内,会保证同一用户相关联的访问请求会被分配到同一实例上。
✦会话保持时间:会话保持的限制时间,0-86400,单位为秒。
✦失败次数阈值:访问失败次数,0-10。当微服务访问下属实例的失败次数或会话保持时间超过设定的值时,微服务不再访问该实例。
3 J$ s* h8 K, @9 }* U1 A4.5.6、监控告警
$ `1 n2 c! d( i2 h' g/ \
微服务中服务治理最终达到的效果就是系统7*24小时不间断服务,如下图为微服务常用监控指标;
从0到1了解微服务架构设计及使用(下篇)
+ L, {% J8 X& L4 Z服务治理 r% j! I4 O; _% F. m
业务的解耦使得服务化的出现,多套服务化的出现代码冗余,管理不便最终使得服务治理的出现。服务治理主要包括服务发现、负载均衡、限流、熔断、超时、重试、服务追踪。我们可以通过三种方式实现服务治理,如下图所示:
2 A. s) ~' P! ?$ v0 p; m
从0到1了解微服务架构设计及使用(下篇)
' U8 H$ Z( ^1 ^! W# e9 d" p
特点如下:
第一代优点:
✦简单使用依赖少
限制:
✦代码耦合
✦代码重复高
✦运维复杂
✦开发要求高
1 x+ ^( Q" ~. T- h: m第二代优点:
✦代码重复少
✦治理逻辑代码和业务代码分开
限制:
✦SDK语言绑定
✦代码侵入
✦基于SDK开发学习门槛高
✦在用系统改造代价大
✦治理能力升级影响用户业务
; N) S7 j* {5 H8 | u" ~2 R" Q" b" G
第三代优点:
✦独立进程,用户业务非侵入
✦语言无关
✦治理逻辑升级业务无感知
✦已有系统无需改造即可治理
✦可以渐进的微服务化
^- @- x s x7 }& U/ \/ c
限制:
✦代理的性能和资源开销
3 }6 u, E, ]1 N微服务技术选型
7 P5 |/ X: _* S4 C4 l& T8 j$ t6.1、开发语言
✦JAVA
主流编程语言,适合构建大型后台服务
✦Golang
Go语言是谷歌2009发布的第二款开源编程语言。专门针对多处理器系统应用程序的编程进行了优化,使用Go编译的程序可以媲美C或C++代码的速度,而且更加安全、支持并行进程。Google对Go寄予厚望。其设计是让软件充分发挥多核心处理器同步多工的优点,并可解决面向对象程序设计的麻烦。目前作为云计算领域的不二之选!
: O! ^+ ]. {* C2 l/ j
6.2、开发框架
✦微服务框架:
Spring Cloud / Spring Cloud alibaba : Spring Cloud是一系列框架的有序集合。它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发,提供了全套微服务解决方案。
* w4 c7 R) i* _; b- ~6 J
✦RPC:
RestTemplate / WebClient:Spring RestTemplate 是 Spring 提供的用于访问 Rest 服务的客户端
gRPC :GRPC是google开源的一个高性能、跨语言的RPC框架,基于HTTP2协议,基于protobuf 3.x的一款rpc框架。多种语言支持;支持链接复用,集群内可采用长链接;性能简单调优后,可满足多数业务场景需求。
! T) u$ q1 c9 `7 m# s# _✦ServiceComb:
Apache ServiceComb 是业界第一个Apache微服务顶级项目,由华为立项研发并致力于开源的微服务解决方案。ServiceComb是第一个实现纯异步内核的微服务框架:实现超低调用时延和高吞吐能力,高性能。ServiceComb底层基于vertx,但在vertx之上进行了进一步封装,同时支持异步及同步模型。