[Reprint] Spring Cloud underlying principle

Come on! Do not ask me interview underlying principle Cloud Spring

https://mp.weixin.qq.com/s/ZH-3JK90mhnJPfdsYH2yDA

 

There is no doubt, Spring Cloud is currently the leader in the field of micro-service architecture, in numerous books blog to explain this technology.

But most still remain at the level of explanation for Spring Cloud function to use, many of the principles underlying, many people may not be aware of.

Therefore, this paper through a lot of hand drawing, talk to you about the underlying principles of the Spring Cloud micro-services architecture.

In fact, Spring Cloud is a family bucket technology stack, which contains a lot of components. This paper begins with the core of several components, namely Eureka, Ribbon, Feign, Hystrix, Zuul start to analyze their underlying works.

Business Application Scenario

First to tell you that a business scenario, we assume that electricity suppliers are now developing a Web site, to realize the function of the pay orders.

Process is as follows:

  • After you create an order, if the user is immediately paid for this order, we need to update the order status to "paid."
  • Deduction of the corresponding commodity stocks.
  • Notification storage center were shipped.
  • To the user's current shopping increase the corresponding points.

In response to these processes, we need to have service orders, inventory services, warehousing services, integration services.

The general idea of ​​the whole process as follows:

  • After the user completes the payment for an order, the order will go to the service, update order status.
  • Orders Inventory service call service, complete the corresponding function.
  • Orders service calls warehousing services, complete the corresponding function.
  • Orders integral service call service, complete the corresponding function.

At this point, the entire payment orders of business processes end. The picture below clearly shows that the calling process between the various services:

Good! Once you have the business scenario, let's take a look at Spring Cloud micro-service architecture, and how these components work together, as well as the respective roles of the principles behind it.

Spring Cloud core components: Eureka

Let's consider the first question: you want to call order service inventory services, storage services, or integration services, how to call?

Order Services Inventory Service simply did not know the people on which machine ah! Even if it wants to initiate a request, do not know to whom to send, powerless!

At this time, the turn of Spring Cloud Eureka played. Eureka is a micro-service architecture in the registry, responsible for registration and discovery services.

Let's look at this chart below, with plans to carefully analyze what the entire process:

As shown above, inventory services, warehousing services, integration services have a Eureka Client component, the component responsible for the registration of the information service in the Eureka Server.

To put it plainly, it is to tell Eureka Server, which on its own machine, listening on which port.

The Eureka Server is a registration center, which has a registry, save the machine and port number for each service is located.

Order service also has a Eureka Client component, the Eureka Client Components will find Eureka Server ask: Inventory Service which machine ah ah listening on which port warehousing services it integral service it????

Then we can put them to pull information from the registry in Eureka Server to take its own local cache.

Then if you want to call to order service inventory service, you can not find your own local Eureka Client Inventory Service to ask which machine? Which port to listen for it?

After receiving the response, it can immediately send a request in the past, call the service inventory deductions that interface stock! Similarly, if you want to call to order service warehousing services, integration services, also followed suit.

in conclusion:

  • Eureka Client: This information service is responsible for registering to Eureka Server in.
  • Eureka Server: registration center, which has a registry, save the machine and port numbers for each service is located.

Spring Cloud core components: Feign

Now order service do know that inventory services, integration services, warehousing services where we are, but also listening on which port number.

But the new question again: Do you want to write your own order service a lot of code, establishing a network connection with other services, and then construct a complex request, then sends a request in the past, the final response to the results returned to write a lot of code deal with it?

This is the code snippet above-mentioned process of translation, let's take a look, understand what this hopeless and helpless feeling !!!

Tips, high-energy front:

看完上面那一大段代码,有没有感到后背发凉、一身冷汗?实际上你进行服务间调用时,如果每次都手写代码,代码量比上面那段要多至少几倍,所以这个事压根儿就不是地球人能干的。

既然如此,那怎么办呢?别急,Feign 早已为我们提供好了优雅的解决方案。来看看如果用 Feign 的话,你的订单服务调用库存服务的代码会变成啥样?

看完上面的代码什么感觉?是不是感觉整个世界都干净了,又找到了活下去的勇气!

没有底层的建立连接、构造请求、解析响应的代码,直接就是用注解定义一个 Feign Client 接口,然后调用那个接口就可以了。

人家 Feign Client 会在底层根据你的注解,跟你指定的服务建立连接、构造请求、发起请求、获取响应、解析响应,等等。这一系列脏活累活,人家 Feign 全给你干了。

那么问题来了,Feign 是如何做到这么神奇的呢?很简单,Feign 的一个关键机制就是使用了动态代理。

咱们一起来看看上面的图,结合图来分析:

首先,如果你对某个接口定义了 @FeignClient 注解,Feign 就会针对这个接口创建一个动态代理。

接着你要是调用那个接口,本质就是会调用 Feign 创建的动态代理,这是核心中的核心。

Feign的动态代理会根据你在接口上的 @RequestMapping 等注解,来动态构造出你要请求的服务的地址。

最后针对这个地址,发起请求、解析响应。

Spring Cloud 核心组件:Ribbon

说完了 Feign,还没完。现在新的问题又来了,如果人家库存服务部署在了 5 台机器上。

如下所示:

  • 192.168.169:9000
  • 192.168.170:9000
  • 192.168.171:9000
  • 192.168.172:9000
  • 192.168.173:9000

这下麻烦了!人家 Feign 怎么知道该请求哪台机器呢?这时 Spring Cloud Ribbon 就派上用场了。

Ribbon 就是专门解决这个问题的。它的作用是负载均衡,会帮你在每次请求时选择一台机器,均匀的把请求分发到各个机器上。

Ribbon 的负载均衡默认使用的最经典的 Round Robin 轮询算法。这是啥?

简单来说,就是如果订单服务对库存服务发起 10 次请求,那就先让你请求第 1 台机器、然后是第 2 台机器、第 3 台机器、第 4 台机器、第 5 台机器,接着再来—个循环,第 1 台机器、第 2 台机器。。。以此类推。

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

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

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

Spring Cloud 核心组件:Hystrix

在微服务架构里,一个系统会有很多的服务。以本文的业务场景为例:订单服务在一个业务流程里需要调用三个服务。

现在假设订单服务自己最多只有 100 个线程可以处理请求,然后呢,积分服务不幸的挂了,每次订单服务调用积分服务的时候,都会卡住几秒钟,然后抛出—个超时异常。

咱们一起来分析一下,这样会导致什么问题?如果系统处于高并发的场景下,大量请求涌过来的时候,订单服务的 100 个线程都会卡在请求积分服务这块,导致订单服务没有一个线程可以处理请求。

然后就会导致别人请求订单服务的时候,发现订单服务也挂了,不响应任何请求了。

上面这个,就是微服务架构中恐怖的服务雪崩问题,如下图所示:

如上图,这么多服务互相调用,要是不做任何保护的话,某一个服务挂了,就会引起连锁反应,导致别的服务也挂。

比如积分服务挂了,会导致订单服务的线程全部卡在请求积分服务这里,没有一个线程可以工作,瞬间导致订单服务也挂了,别人请求订单服务全部会卡住,无法响应。

但是我们思考一下,就算积分服务挂了,订单服务也可以不用挂啊!为什么?

我们结合业务来看:支付订单的时候,只要把库存扣减了,然后通知仓库发货就 OK 了。

如果积分服务挂了,大不了等它恢复之后,慢慢人肉手工恢复数据!为啥一定要因为一个积分服务挂了,就直接导致订单服务也挂了呢?不可以接受!

现在问题分析完了,如何解决?这时就轮到 Hystrix 闪亮登场了。Hystrix 是隔离、熔断以及降级的一个框架。啥意思呢?

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

打个比方:现在很不幸,积分服务挂了,会咋样?当然会导致订单服务里那个用来调用积分服务的线程都卡死不能工作了啊!

但由于订单服务调用库存服务、仓储服务的这两个线程池都是正常工作的,所以这两个服务不会受到任何影响。

这个时候如果别人请求订单服务,订单服务还是可以正常调用库存服务扣减库存,调用仓储服务通知发货。

只不过调用积分服务的时候,每次都会报错。但是如果积分服务都挂了,每次调用都要去卡住几秒钟干啥呢?有意义吗?当然没有!

所以我们直接对积分服务熔断不就得了,比如在 5 分钟内请求积分服务直接就返回了,不要去走网络请求卡住几秒钟,这个过程,就是所谓的熔断!

那人家又说,兄弟,积分服务挂了你就熔断,好歹你干点儿什么啊!别啥都不干就直接返回啊?

没问题,咱们就来个降级:每次调用积分服务,你就在数据库里记录一条消息,说给某某用户增加了多少积分,因为积分服务挂了,导致没增加成功!

这样等积分服务恢复了,你可以根据这些记录手工加一下积分。这个过程,就是所谓的降级。

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

Spring Cloud 核心组件:Zuul

说完了 Hystrix,接着给大家说说最后一个组件:Zuul,也就是微服务网关。这个组件是负责网络路由的。

不懂网络路由?行,那我给你说说,如果没有 Zuul 的日常工作会怎样?

假设你后台部署了几百个服务,现在有个前端兄弟,人家请求是直接从浏览器那儿发过来的。

打个比方:人家要请求一下库存服务,你难道还让人家记着这服务的名字叫做 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 个核心组件通过一张图串联起来,再来直观的感受一下其底层的架构原理:

中华石杉:十余年 BAT 架构经验,一线互联网公司技术总监。带领上百人团队开发过多个亿级流量高并发系统。现将多年工作中积累下的研究手稿、经验总结整理成文,倾囊相授。

【编辑推荐】

Guess you like

Origin www.cnblogs.com/jinanxiaolaohu/p/10992499.html