Spring Cloud流程图

重要声明

本文内容来源于石杉的架构笔记作者中华石杉。如果想深入了解Spring Cloud,请查询作者原著。本文仅限自己梳理Spring Cloud的流程。

五大神兽

Spring Cloud是一个全家桶式的技术栈,包含了很多组件。本文将详细讲讲Spring Cloud的五大神兽:EurekaRibbonFeignHystrixGateway

业务场景

假设现在有一个电商网站,要实现支付订单功能,流程如下:

  • 创建一个订单之后,如果用户立刻支付了这个订单,我们需要将订单状态更新为“已支付”
  • 扣减相应的商品库存
  • 通知仓储中心,进行发货
  • 给用户的这次购物增加相应的积分

针对上述流程,我们需要订单服务库存服务仓储服务积分服务

大家肯定一眼就看得懂流程是怎样运作的,那么先来讲讲Eureka

Eureka

Eureka 是 Netflix 公司开源的一个服务注册与发现的组件 。它包括两个组件,Eureka Server (注册中心)Eureka Client (服务提供者、服务消费者)

我们把Eureka加入流程图中,看看它到底起了什么作用?

在这里插入图片描述

我更觉得Eureka更像是一家婚介所。。。
在这里插入图片描述

接下来我们用图片来简单的分析一下Eureka如何使用

在这里插入图片描述

实际上为了保证Eureka的高可用性,我们通常会搭建集群。例如创建几个Eureka Server模块,在各自的配置文件中配置url。再将Eureka Client 分别注册到这几个 Eureka Server中。

讲解完Eureka后,再简单了解两个服务发布和注册服务软件,ConsulNacos

Consul

Consul 是由 HashiCorp 基于 Go 语言开发的,支持多数据中心,分布式高可用的服务发布和注册服务软件。
• 用于实现分布式系统的服务发现与配置。
• 使用起来也较为简单。具有天然可移植性(支持Linux、windows和Mac OS X);安装包仅包含一个可执行文件,方便部署 。
• 官网地址: https://www.consul.io

Consul的使用步骤:
  • 添加依赖坐标
  • 配置application.yml
  • 启动consul的安装包
  • 使用 RestTemplate 完成远程调用

Nacos

Nacos(Dynamic Naming and Configuration Service) 是阿里巴巴2018年7月开源的项目。
• 它专注于服务发现和配置管理领域 致力于帮助您发现、配置和管理微服务。Nacos 支持几乎所有主流类型的“服务”的发现、配置和管理。
• 一句话概括就是Nacos = Spring Cloud注册中心 + Spring Cloud配置中心。
• 官网:https://nacos.io/
• 下载地址: https://github.com/alibaba/nacos/releases

Nacos的使用步骤与Consul相同,很简单。

但是!!!我们每次调用服务都在代码中拼字符串url,调用RestTemplate方法,实在是很麻烦。既然如此,那怎么办呢?别急,Feign早已为我们提供好了优雅的解决方案。

Feign

Feign 是一个声明式的 REST 客户端,它用了基于接口的注解方式,很方便实现客户端配置。

  • Feign 底层依赖于 Ribbon 实现负载均衡和远程调用。
  • Ribbon默认1秒超时,因此Feign的默认超时时间也为1秒。
  • Feign 只能记录 debug 级别的日志信息。

我们来聊一聊,为什么Feign只需要用注解定义一个接口,然后调用接口,就会代替你发送请求,获得响应结果呢?很简单,Feign用到了动态代理

img

Feign通过**@FeignClient**(value = “FEIGN-PROVIDER”)、@RequestMapping("/goods/findOne/{id}")、@PathVariable(“id”) int id三个注解,拼凑成访问地址,例如http://FEIGN-PROVIDER/goods/findOne/"+id

Ribbon

现在我们已经通过feign得到了url,假如库存服务部署了五台服务器,那么feign如何选择呢?此时我们需要用到Ribbon

Ribbon是Netflix提供的一个基于HTTP和TCP的客户端负载均衡工具。主要作用是简化远程调用负载均衡。我们已经知道Feign其实是在Ribbon的基础上封装,并且在远程调用方面比Ribbon更加简单,因此我们着重讲解它的负载均衡。

负载均衡
  • 服务端负载均衡:负载均衡算法在服务器,由负载均衡器维护服务地址列表

在这里插入图片描述

  • 客户端负载均衡:负载均衡算法在客户端,客户端维护服务地址列表

在这里插入图片描述

Ribbon的负载均衡默认使用的最经典的Round Robin轮询算法。其负载均衡策略有:

  • 随机:RandomRule
  • 轮询:RoundRobinRule
  • 最小并发:BestAvailabelRule
  • 过滤:AvailabilityFilteringRule
  • 响应时间:WeightedResponseTimeRule
  • 轮询重试:RetryRule
  • 性能可用性:ZoneAvoidanceRule

此外,Ribbon是和Feign以及Eureka紧密协作,完成工作的,具体如下:

  • 首先Ribbon会从 Eureka Client里获取到对应的服务注册表,也就知道了所有的服务都部署在了哪些机器上,在监听哪些端口号。
  • 然后Ribbon就可以使用默认的Round Robin算法,从中选择一台机器
  • Feign就会针对这台机器,构造并发起请求。

对上述整个过程,再来一张图,帮助大家更深刻的理解:

img

在微服务架构里,一个系统会有很多的服务。以本文的业务场景为例:订单服务在一个业务流程里需要调用三个服务。现在假设订单服务自己最多只有100个线程可以处理请求,然后呢,积分服务不幸的挂了,每次订单服务调用积分服务的时候,都会卡住几秒钟,然后抛出—个超时异常。这样会导致什么问题呢

  • 如果系统处于高并发的场景下,大量请求涌过来的时候,订单服务的100个线程都会卡在请求积分服务这块。导致订单服务没有一个线程可以处理请求
  • 然后就会导致别人请求订单服务的时候,发现订单服务也挂了,不响应任何请求了

这种问题我们称之为服务雪崩。这时就轮到Hystrix闪亮登场了。

Hystrix

Hystrix是隔离、熔断以及降级的一个框架

Hystix 主要功能

  • 隔离:线程池隔离、信号量隔离
  • 降级:异常,超时
  • 熔断
  • 限流

Hystrix 熔断机制,用于监控微服务调用情况,当失败的情况达到预定的阈值(5秒失败20次),会打开
断路器,拒绝所有请求,直到服务恢复正常为止。

断路器三种状态:打开、半开、关闭

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pM1bkQ3h-1595155490260)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20200706172004863.png)]

Hystrix 提供了 Hystrix-dashboard 功能,用于实时监控微服务运行状态。但是Hystrix-dashboard只能监控一个微服务。Netflix 还提供了 Turbine ,进行聚合监控。

Hystrix起到什么作用呢?说白了,Hystrix会搞很多个小小的线程池,比如订单服务请求库存服务是一个线程池,请求仓储服务是一个线程池,请求积分服务是一个线程池。每个线程池里的线程就仅仅用于请求那个服务。

这时我们回头再看那个问题,如果积分服务挂了,会咋样呢?

如果别人请求订单服务,订单服务还是可以正常调用库存服务扣减库存,调用仓储服务通知发货。只不过调用积分服务的时候,每次都会报错。**但是如果积分服务都挂了,每次调用都要去卡住几秒钟干啥呢?有意义吗?当然没有!**所以我们直接对积分服务熔断不就得了,比如在5分钟内请求积分服务直接就返回了,不要去走网络请求卡住几秒钟,这个过程,就是所谓的熔断!

**那人家又说,兄弟,积分服务挂了你就熔断,好歹你干点儿什么啊!别啥都不干就直接返回啊?**没问题,咱们就来个降级:每次调用积分服务,你就在数据库里记录一条消息,说给某某用户增加了多少积分,因为积分服务挂了,导致没增加成功!这样等积分服务恢复了,你可以根据这些记录手工加一下积分。这个过程,就是所谓的降级。

为帮助大家更直观的理解,接下来用一张图,梳理一下Hystrix隔离、熔断和降级的全流程:

img

说完了Hystrix,接着给大家说说最后一个组件:Gateway,也就是微服务网关。这个组件是负责网络路由的。不懂网络路由?行,那我给你说说,如果没有Gateway的日常工作会怎样?

Gateway

网关就是系统的入口,封装了应用程序的内部结构,为客户端提供统一服务,一些与业务本身功能无关的公共逻辑可以在这里实现,诸如认证、鉴权、监控、缓存、负载均衡、流量管控、路由转发等网关旨在为微服务架构提供一种简单而有效的统一的API路由管理方式。在目前的网关解决方案里,有Nginx+ Lua、Netflix Zuul 、Spring Cloud Gateway等等。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-24mAwyev-1595155490261)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20200706172900449.png)]

Gateway 支持过滤器功能,对请求或响应进行拦截,完成一些通用操作。

Gateway 提供两种过滤器方式:“pre”和“post

  • pre 过滤器,在转发之前执行,可以做参数校验、权限校验、流量监控、日志输出、协议转换等。
  • post 过滤器,在响应之前执行,可以做响应内容、响应头的修改,日志的输出,流量监控等。

Gateway 还提供了两种类型过滤器

  • GatewayFilter:局部过滤器,针对单个路由(遵循约定大于配置的思想,只需要在配置文件配置局部过滤器名称,并为其指定对应的值,就可以让其生效。)
  • GlobalFilter :全局过滤器,针对所有路由(不需要在配置文件中配置,系统初始化时加载,并作用在每个路由上)

如果没有Gateway,假设你后台部署了几百个服务,现在有个前端兄弟,人家请求是直接从浏览器那儿发过来的。打个比方:人家要请求一下库存服务,你难道还让人家记着这服务的名字叫做inventory-service?部署在5台机器上?就算人家肯记住这一个,你后台可有几百个服务的名称和地址呢?难不成人家请求一个,就得记住一个?你要这样玩儿,那真是友谊的小船,说翻就翻!

上面这种情况,压根儿是不现实的。所以一般微服务架构中都必然会设计一个网关在里面,像android、ios、pc前端、微信小程序、H5等等,不用去关心后端有几百个服务,就知道有一个网关,所有请求都往网关走,网关会根据请求中的一些特征,将请求转发给后端的各个服务。

而且有一个网关之后,还有很多好处,比如可以做统一的降级、限流、认证授权、安全等等。

总结

最后再来总结一下,上述几个Spring Cloud核心组件,在微服务架构中,分别扮演的角色:

  • Eureka:各个服务启动时,Eureka Client都会将服务注册到Eureka Server,并且Eureka Client还可以反过来从Eureka Server拉取注册表,从而知道其他服务在哪里
  • Ribbon:服务间发起请求的时候,基于Ribbon做负载均衡,从一个服务的多台机器中选择一台
  • Feign:基于Feign的动态代理机制,根据注解和选择的机器,拼接请求URL地址,发起请求
  • Hystrix:发起请求是通过Hystrix的线程池来走的,不同的服务走不同的线程池,实现了不同服务调用的隔离,避免了服务雪崩的问题
  • Zuul:如果前端、移动端要调用后端系统,统一从Zuul网关进入,由Zuul网关转发请求给对应的服务

以上就是我们通过一个电商业务场景,阐述了Spring Cloud微服务架构几个核心组件的底层原理。

文字总结还不够直观?没问题! 我们将Spring Cloud的5个核心组件通过一张图串联起来,再来直观的感受一下其底层的架构原理:

img

此外,Spring Cloud Config实现配置中心

配置文件是我们再熟悉不过的了,尤其是 Spring Boot 项目,除了引入相应的 maven 包之外,剩下的工作就是完善配置文件了,例如 mysql、redis 、security 相关的配置。除了项目运行的基础配置之外,还有一些配置是与我们业务有关系的,比如说七牛存储、短信相关、邮件相关,或者一些业务上的开关。

对于一些简单的项目来说,我们一般都是直接把相关配置放在单独的配置文件中,以 properties 或者 yml 的格式出现,更省事儿的方式是直接放到 application.properties 或 application.yml 中。但是这样的方式有个明显的问题,那就是,当修改了配置之后,必须重启服务,否则配置无法生效。

目前有一些用的比较多的开源的配置中心,比如携程的 Apollo、蚂蚁金服的 disconf 等,对比 Spring Cloud Config,这些配置中心功能更加强大。有兴趣的可以拿来试一试。

Spring Cloud Config 解决了在分布式场景下多环境配置文件的管理和维护

  • 集中管理配置文件
  • 不同环境不同配置,动态化的配置更新
  • 配置信息改变时,不需要重启即可更新配置信息到服务

在这里插入图片描述

Spring Cloud Bus

如果只有一个 client 端的话,那我们设置手动刷新不算太费事,但是如果client端比较多的话呢,一个一个去手动刷新未免有点复杂。这样的话,我们可以借助 Spring Cloud Bus 的广播功能,让 client 端都订阅配置更新事件,当配置更新时,触发其中一个端的更新事件,Spring Cloud Bus 就把此事件广播到其他订阅端,以此来达到批量更新。

Spring Cloud Bus 是用轻量的消息中间件将分布式的节点连接起来,可以用于广播配置文件的更改或者服务的监控管理。关键的思想就是,消息总线可以为微服务做监控,也可以实现应用程序之间相通信。

Spring Cloud Bus 可选的消息中间件包括 RabbitMQ 和 Kafka 。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-p0ESIzyB-1595155490264)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20200711101751663.png)]

bus不是一个服务,而是一个插件。config server和config client都添加了bus的依赖坐标。bus只是将这些服务连接起来,提供广播功能。

例如当外部配置文件更改了数据,config server会强制收到修改的数据。如果没有bus,A,B,C服务不知道数据已经更改,还会按照原来的数据执行。有了bus以后,bus会通知到A,B,C服务,说:哥们,我们的数据已经更改啦,我带来了新数据,不要用原来的了~。而rabbitMQ就是携带数据的中间件。

Spring Cloud Stream

我们在项目中经常会用到消息中间件,比如我们在传统的企业中常使用ActiveMQ做异步调用和系统解耦,假如公司发展壮大了,用户非常多,这时ActiveMQ无法支撑高并发、高负载以及高吞吐的复杂场景,我们就必须切换消息中间件:RabbitMQ。换中间件就无法避免重构原先的代码,这样会非常耗费人力时间,且程序的拓展性不是很好。Spring Cloud Stream很好地解决了这种问题:

  • Spring Cloud Stream 是一个构建消息驱动微服务应用的框架。
  • Stream 解决了开发人员无感知的使用消息中间件的问题,因为Stream对消息中间件的进一步封装,可以做到代码层面对中间件的无感知,甚至于动态的切换中间件,使得微服务开发的高度解耦,服务可以关注更多自己的业务流程。
  • Spring Cloud Stream目前支持两种消息中间件RabbitMQ和Kafka

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7WpCgDjN-1595155490265)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20200711170231500.png)]

Spring Cloud Stream 构建的应用程序与消息中间件之间是通过绑定器 Binder相关联的。绑定器对于应用程序而言起到了隔离作用, 它使得不同消息中间件的实现细节对应用程序来说是透明的。

• binding 是我们通过配置把应用和spring cloud stream 的 binder 绑定在一起

• output:发送消息 Channel,内置 Source接口

• input:接收消息 Channel,内置 Sink接口

Sleuth+Zipkin

随着业务发展,系统拆分导致系统调用链路愈发复杂,一个前端请求可能最终需要调用很多次后端服务才能完成。当整个请求变慢或不可用时,我们是无法得知该请求是由某个或某些后端服务引起的,这时就需要解决如何快读定位服务故障点,以对症下药。于是Sleuth+Zipkin就闪亮登场啦。

一般的,一个分布式服务跟踪系统,主要有三部分:数据收集数据存储数据展示。根据系统大小不同,每一部分的结构又有一定变化。譬如,对于大规模分布式系统,数据存储可分为实时数据和全量数据两部分,实时数据用于故障排查(troubleshooting),全量数据用于系统优化;数据收集除了支持平台无关和开发语言无关系统的数据收集,还包括异步数据收集(需要跟踪队列中的消息,保证调用的连贯性),以及确保更小的侵入性;数据展示又涉及到数据挖掘和分析。虽然每一部分都可能变得很复杂,但基本原理都类似。

服务追踪的追踪单元是从客户发起请求(request)抵达被追踪系统的边界开始,到被追踪系统向客户返回响应(response)为止的过程,称为一个“trace”。每个 trace 中会调用若干个服务,为了记录调用了哪些服务,以及每次调用的消耗时间等信息,在每次调用服务时,埋入一个调用记录,称为一个“span”。这样,若干个有序的 span 就组成了一个 trace。在系统向外界提供服务的过程中,会不断地有请求和响应发生,也就会不断生成 trace,把这些带有span 的 trace 记录下来,就可以描绘出一幅系统的服务拓扑图。附带上 span 中的响应时间,以及请求成功与否等信息,就可以在发生问题的时候,找到异常的服务;根据历史数据,还可以从系统整体层面分析出哪里性能差,定位性能优化的目标。

Spring Cloud Sleuth

Spring Cloud Sleuth 其实是一个工具,它在整个分布式系统中能跟踪一个用户请求的过程,捕获这些跟踪数
据,就能构建微服务的整个调用链的视图,这是调试和监控微服务的关键工具。
• 耗时分析
• 可视化错误
• 链路优化

Zipkin

Zipkin 是 Twitter 的一个开源项目,它致力于收集服务的定时数据,以解决微服务架构中的延迟问题,包
括数据的收集、存储、查找和展现。

题的时候,找到异常的服务;根据历史数据,还可以从系统整体层面分析出哪里性能差,定位性能优化的目标。

Spring Cloud Sleuth

Spring Cloud Sleuth 其实是一个工具,它在整个分布式系统中能跟踪一个用户请求的过程,捕获这些跟踪数
据,就能构建微服务的整个调用链的视图,这是调试和监控微服务的关键工具。
• 耗时分析
• 可视化错误
• 链路优化

Zipkin

Zipkin 是 Twitter 的一个开源项目,它致力于收集服务的定时数据,以解决微服务架构中的延迟问题,包
括数据的收集、存储、查找和展现。

spring cloud sleuth结合zipkin,将信息发送到zipkin,利用zipkin的存储来存储信息,利用zipkin ui来展示数据。

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐