互联网架构设计漫谈 (5)-搞清SpringCloud

互联网架构设计漫谈 (5)-搞清SpringCloud

 

微服务发展至今有许多公司都提供了架构来协助搭建微服务平台,比较著名的有 Dubbo,DubboX,Spring Cloud。今天带大家来了解一下Spring Cloud是如何搭建微服务平台的。

要点:

组件的分工协作

API网关: Zuul

服务负载:Ribbon

安全认证:Spring security

服务注册与发现: Eureka

链路跟踪:Sletuh与Zipkin

集群容错: Hystrix

网络调用:Feign

配置管理:Spring Config


组件的分工协作

互联网架构设计漫谈 (5)-搞清SpringCloud

 

  • 用户请求会最新发送给Zuul,Zuul是用来做API 网关的。由于,微服务会存在多个实例,所以请求被分发到哪个实例需要通过Zuul过滤器来完成。
  • 同时Zuul自带Robbin,其负责微服务集群的负载均衡工作。
  • 每个微服务的注册/注销操作通知Eureka,作为服务发现和注册中心,一方面记录服务的注册以及健康情况,一方面会协同Zuul做好服务访问的工作。
  • 服务如果自身出现问题,例如:业务异常,网络异常等等。需要通过断路器Hystrix来实现具体的处理操作,比如通知注册中心服务异常,比如对服务进行降级处理。这个时候服务注册发现中心会标记服务异常,再有请求过来就不会发送到有异常的服务上去了。同时服务发现注册中心也会定期检查服务的状态,一旦服务恢复状态又把其放到访问队列中。
  • 微服务之间是存在网络通讯的,需要把数据打包发送,接受以后也需要解包读取信息。这里可以使用Feign作为服务通讯的组件,配合Ribbon完成通信工作。
  • 微服务的数量随着业务的增常也会随之增长,用Sleuth可以做服务追踪,告诉服务管理者服务之间的调用关系。同时可以通过Zipkin UI界面查询到服务之间的关系。
  • 由于微服务众多,很多沟通方式都是通过发送和接受消息事件来完成的,所以RabbitMQ 就登场了,当然了市面上还有其他种类的MQ产品也可以替代之。这样的设计是为了让服务之间更好的解耦合。
  • 服务的参数配置需要由Spring Config 协助管理,特别是发布环境的变化,IP端口的控制等等。
  • 微服务多是分布式的,那么服务之间的同步就需要Reids 来协助完成,当然Redis 也可以用来作为分布式缓存。

API网关: Zuul

互联网架构设计漫谈 (5)-搞清SpringCloud

图片来自网络

Zuul中的请求过程,请求先传给Zuul Servlet,Zuul Servlet会维持一个Request Context,他是用来存储请求的数据并且保持Filter之间沟通的。之后Zuul Servlet 会把请求转发给 ZuulFilter Runner。ZuulRunner中有一个FilterProcessor是来管理所有的Filter,并且按照一定顺序来执行,在这里是支持filter 的热加载的,也就是说如果增加了filter的规则,可以通过加载filter 文件的方式让系统感知到。filter的处理顺序如下:

  1. Pre routing filters:在路由之前执行,在这里可以做鉴权,选择路由器,以及限流的操作,有些静态资源的响应也可以放在这里。
  2. Routing filters: 请求路由的实体。
  3. Post routing filters:在路由之后发生,用来做流量统计,监控,记录请求日志。

服务负载:Ribbon

Ribbon用来做负载均衡,一般会和Zuul配合使用,在服务之间调用的时候也会使用,其策略如下:

  • 随机 (Random)
  • 轮询 (RoundRobin)
  • 一致性哈希 (ConsistentHash)
  • 哈希 (Hash)
  • 加权(Weighted)

安全认证:Spring security

Spring security会根据不同的URL建立不同的filter 对其进行鉴权.

互联网架构设计漫谈 (5)-搞清SpringCloud

 

用户识别流程,当用户登陆的时候AuthenticationProcessingFilter去拦截请求,调用AuthenticationManager中的ProviderManager来得到用户信息,这个信息来源可以是多样的,比如说来自数据库或者服务。如果验证失败就拒绝访问,如果成功将用户的权限信息保存在User实例并放全局缓存SecurityContextHolder中保存,下次访问的时候可以继续使用。

资源访问权限流程,当请求URL的时候,AbstractSecurityInterceptor会拦截这个请求,他会调用FilterInvocationSecurityMetadataSource来获取被拦截url所需的权限,通过AccessDecisionManager获取Spring的全局缓存SecurityContextHolder的用户权限。

服务注册与发现: Eureka

互联网架构设计漫谈 (5)-搞清SpringCloud

 

Eureka用来做服务发现和服务注册,在Application Service(应用服务)上面运行Eureka Client(Eureka客户端)用来做服务的Register(注册),Cancel(取消),Renew(续约),以及Get Registry(获取其他应用服务注册信息)。Eureka Server 可以按照集群的方式来部署,每个Eureka Server 负责自己Zone(区域)的服务注册和发现工作。每个Zone(区域)的应用服务通过Eureka Client(Eureka客户端)来获取其他服务的注册信息。从而实现微服务之间的调用。

链路跟踪:Sleuth与Zipkin

互联网架构设计漫谈 (5)-搞清SpringCloud

 

Sleuth提供链路追踪。由于一个请求会涉及到多个服务的互相调用,而这种调用往往成链式结构,经过多次层层调用以后请求才会返回。常常使用Sleuth追踪整个调用过程,方便地理清服务间的调用关系。

互联网架构设计漫谈 (5)-搞清SpringCloud

 

每次请求都会生成一个Trace ID,如上图所示这个Trace ID 在整个Request 和Response 过程中都会保持一致,不论经过了多少个服务。这是为了方便记录一次调用的整个生命周期。再看每次请求的时候都会有一个Span ID,这里的Span 是Sleuth服务跟踪的最小单元,每经过一个服务,每次Request 和Response 这个值都会有所不同,这是为了区分不同的调用动作。针对每个调用的动作,Sleuth 都做了标示如下:

  • Server Received 是服务器接受,也就是服务端接受到请求的意思。
  • Client Sent 是客户端发送,也就是这个服务本身不提供响应,需要调用其它的服务提供该响应,所以这个时候是作为客户端发起请求的。
  • Server Sent 是服务端发送,看上图SERVICE 3 收到请求后,由于他是最终的服务提供者,所以作为服务端,他需要发请求发送给调用者。
  • Client Received 是客户端接受,作为发起调用的客户端接受到服务端返回的请求。

实际上Sleuth就是通过上述方式把每次请求记录一个统一的Trace ID,每个请求的详细步骤记作Span ID,每次发起请求或者接受请求的状态分别记录成, Server Received,Client Sent, Server Sent, Client Received 四种状态。来完成这个服务调用链路的跟踪的。

互联网架构设计漫谈 (5)-搞清SpringCloud

 

在调用服务的链路上每个被调用的服务节点都会通过Parent ID 来记录发起调用服务的Span ID,由于Span ID 是唯一确认最小服务单元的所以,知道了Parent 的 Span ID 也就知道了谁调用自己的了。

再来看看 Sleuth 和Zipkin 是如何协作,让服务之间的调用呈现给我们的。

互联网架构设计漫谈 (5)-搞清SpringCloud

 

Sleuth 会针对每个Trace 也就是每一个调用生成一条Trace 记录通过Instrumented Client 保存到 Instrumented Server,Zipkin 上面配置了Instrumented Server 的信息,通过自身的Collector 收集Trace 的信息,并且保存到本地的数据库。再通过API调用给前端的UI展示给最终用户使用。

集群容错: Hystrix

在分布式环境中,一个用户请求/服务会依赖其他服务,这些服务都有失效的可能。Hystrix通过隔离服务之间的访问,避免单个服务的故障影响到其他服务,并且提供回退和降级提高系统体可靠性。

会由于一个依赖服务的调用问题导致用户请求的调用被阻碍。

互联网架构设计漫谈 (5)-搞清SpringCloud

 

这些被用户请求所依赖的点都有可能因为各种原因导致故障。 比故障更糟糕的是,这些应用程序还可能导致服务之间的延迟增加,影响队列,线程和其他系统资源,从而导致整个系统出现更多级联故障。

互联网架构设计漫谈 (5)-搞清SpringCloud

 

如果我们把上图修改成下图的模式,用Hystrix 对每个依赖的服务进行包装,让这些依赖想独立于其他的服务。即是某些依赖服务发生了问题也不会影响到其他的服务。同时可以针对异常进行处理。例如:服务无法访问,可以调用本地的缓存代替返回值,还可以用一些兜底数据。或者告诉调用错误代码。甚至可以通知服务注册中心。

互联网架构设计漫谈 (5)-搞清SpringCloud

 

网络调用:Feign

Feign 一个Http请求轻量级框架,可以以Java接口注解的方式调用Http请求,而不用像Java中通过封装Http请求报文的方式调用。当我们把对象在客户端和服务器端进行传递的时候都需要面对,填写URL,参数,对象加密,对象界面,请求重试等操作。Feign帮我们把请求模板化,当实际调用的时候,传入参数即可,方便我们的Http调用。

互联网架构设计漫谈 (5)-搞清SpringCloud

图片来源于网络

基本的工作流程如下:

  1. 生成请求的实现类
  2. 生成具体的请求体
  3. 包装请求
  4. 发送之前对请求进行装饰
  5. 记录发送/接受日志
  6. 请求发送/重试处理

配置管理:Spring Config

为分布式系统中的外部配置提供服务器和客户端支持。使用Config Server,您可以为所有环境中的应用程序管理其外部属性。它非常适合spring应用,也可以使用在其他语言的应用上。随着应用程序通过从开发到测试和生产的部署流程,您可以管理这些环境之间的配置,并确定应用程序具有迁移时需要运行的一切。服务器存储后端的默认实现使用git,因此它轻松支持标签版本的配置环境,以及可以访问用于管理内容的各种工具。

Spring Cloud Config服务端特性

  • HTTP,为外部配置提供基于资源的API(键值对,或者等价的YAML内容)
  • 属性值的加密和解密(对称加密和非对称加密)
  • 通过使用@EnableConfigServer在Spring boot应用中非常简单的嵌入。

Config客户端的特性(特指Spring应用)

  • 绑定Config服务端,并使用远程的属性源初始化Spring环境。
  • 属性值的加密和解密(对称加密和非对称加密)

总结:

介绍Spring Cloud 落地微服务架构的总体设计,以及每个组件起到的作用。对于网关Zuul,注册中心Eureka,负载均衡Robbin,链路追踪Sleuth,断路器Hystrix的原理做了详细介绍。