百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程网 > 正文

面试不再慌!跟着老司机吃透Spring Cloud

yuyutoo 2024-10-12 00:15 1 浏览 0 评论

【51CTO.com原创稿件】最近和朋友聊天,提到他前几天面试的时候被问到:“能否描述一下Spring Cloud?”他当场就懵了,不知道从何说起。



图片来自 Unsplash

是啊,Spring Cloud 是知名的微服务架构,包含了很多组件,每个组件又有各自的分工。

怎么才能理解 Spring Cloud 架构并且说清楚它到底做了些什么呢?我们今天一起来看一下。

从一个例子开始

对于这样的“大”问题,通常需要拆解成小问题来回答。要说明 Spring Cloud 做了什么,就要说清楚它包含的组件都做了些什么?

如果一个个把组件罗列出来,似乎太过独立,没有关联性,缺少逻辑感。我们就从一个简单的例子开始,把这些组件像串珍珠一样串起来。

假设有一个项目,这个项目有两个服务,分别是“A”和“B”:

  • “A”和“B”的关系是,“A”调用“B”。
  • 然后,有一个客户端“C”调用“A”。



客户端“C”调用服务“A”,服务“A”调用服务“B”

Eureka 服务之间互相认识

在服务端我们已经有了两个服务,“A”和“B”。他们的关系是“A”调用“B”,“B”被“A”调用。

当只有两个服务的时候我们是知道这种关系,并且可以把这种关系记录下来的,但是如果服务一多,我们如何记录这种关系呢?

于是,Eureka 就登场了,它负责“服务注册,服务发现”的工作。Eureka 分成 Eureka Server 和 Eureka Client。

每个微服务架构都会有一个或者多个 Eureka Server 用来保存注册服务的信息。

每个服务都会包含一个Eureka Client,其中会配置Eureka Server的信息,这样当服务启动的时候就能够把自己注册到 Eureka Server 中去了。

同时每个服务也可以通过 Eureka Client 从 Eureka Server 中获取其他服务的信息(Get Registry)。



“A”服务与“B”服务的调用关系

“A”服务和“B”服务首先通过自身集成的 Eureka Client 到 Eureka Server 上注册自身的信息,包括:服务名,地址,端口号等等。

注册完毕以后,“A”服务通过 Eureka Client 从 Eureka Server 获取(Get Registry)服务“B”的信息。

由于,“A”服务调用“B”服务,所以“A”服务称之为“消费者”,“B”服务称之为“生产者”。

Feign 服务之间信息传递

既然“A”“B”两个服务互相认识了,接下来就要轮到“A”服务调用“B”服务了。

由于两个是单独的服务,并且两个服务都在一个网络内,通常会通过 HTTP 请求进行调用。

传统的做法是,“A”服务写好请求的消息,序列化成二进制的串传递给“B”服务,“B”服务收到消息以后反序列化消息进行解析,接着以同样的方式应答“A”服务。

从传统意义上完成这些代码需要大量的工作,而且需要考虑很多编码上面的问题。为了简化上面的过程,Feign 组件就诞生了,它方便了服务之间的调用。

引入 Feign 了以后,在“A”服务中只需要填写简单的 URL,参数,请求方式,就可以调用“B”服务了。调用“B”服务就好像调用本地的一个方法一样简单。



通过 Feign 调用服务的代码片段

我们需要做的就是在“A”服务(消费者)中建立一个 Feign Client,填写我们需要调用的 URL,参数和方式就可以了,其他的事情就交给 Feign 来完成了。

Feign Client 工作流

从上图可以看出,“消费者”开始只需要提供“生产者”的 URL,参数等信息。

Feign Client 会根据这些信息生成对应的 HTTP 请求头和报文,然后发送给生产者。

生产者返回信息以后,Feign Client 同样会返回“消费者”能够读懂的 JavaBean 的信息。

Ribbon 搞定负载均衡

好了,现在“A”“B”服务互相认识了,并且“A”服务可以调用“B”服务了。

假设“B”服务的业务量增大,一个“B”服务无法满足现在的要求,另外又复制了两个“B”服务,连同原来的一个“B”服务,现在一共有三个“B”服务。

虽然三个提供的服务都是一样的,但是“A”服务应该调用哪个“B”服务的复制呢?

这时 Ribbon 就登场了,它用来做负载均衡。“A”服务无需知道调用三个复制中的哪一个,它只用告诉 Ribbon 我要调用“B”服务,Ribbon 会根据策略去调用三个复制中的某一个。



Ribbon 充当负载均衡器的角色

在 Ribbon 的几种负载均衡策略中,随机策略是用的比较多的。例如:“B1”,“B2”,“B3”分别是“B”服务的三个复制。

“A”服务第一次,调用的是“B1”服务,根据随机策略,第二次就访问“B2”服务,第三次访问“B3”服务,第四次又访问“B1”服务,依次类推,循环往复。

下面列出其他几个服务仅供参考,篇幅有限不做赘述:

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

Hystrix 服务出现故障

现在“A”服务知道如何调用“B1”,“B2”,“B3”三个“B”服务的复制了。

假如“B2”服务出现故障,“A”服务还可以访问它吗?为了避免单个服务的故障影响到其他服务,Hystrix 就应运而生了。



调用“B1”服务失败

Hystrix 俗称熔断器(断路器),当服务不可用或者出现故障时,它提供了响应的处理机制。

在微服务架构中,每个服务都有可能依赖其他服务,也有可能多个服务同时依赖一个服务,又或者存在服务之间的连环依赖(A 依赖 B,B 依赖 D)。

一旦被依赖的服务出现故障,Hystrix 可以通过预设的处理机制,调整服务的响应。例如:返回错误信息,用缓存或者兜底信息替代服务返回信息。



单个服务依赖多个服务,依赖服务中有一个出现问题,对整体产生影响。



多个服务依赖单个服务,单个服务出现故障,影响多个服务。

应用 Hystrix 只需要两步:

第一步,在“A”服务(消费者)上定义,调用“B”服务(生产者)出现故障时的处理方法。



调用“B”服务故障处理的方法,代码片段。

第二步,在“A”服务(消费者)调用“B”服务的方法的 Annotation 上面标注调用失败需要执行的“第一步”的这个方法。



声明调用失败方法,代码片段


在“A”服务中加入 Hystrix

Zuul 如何访问到微服务

上面把服务端的事情说的差不多了,如果“C”客户端需要访问“A”服务,系统通过什么方式告诉它哪个服务是“A”呢?

实际上这里缺少一个网关,把“C”客户端与“A”服务链接起来的网关。

Zuul 就是这个网关,它的责任是过滤和路由。



Zuul 是链接客户端和服务端的网关

还记得上面提到的 Eureka 服务注册和服务发现吗?Zuul 可以和 Eureka 一起合作,完成服务路由的工作。

首先,“A”服务在 Eureka 进行注册,然后“C”客户端向 Zuul 发起请求,访问“A”服务。Zuul 向 Eureka 获取“A”服务的地址,之后访问“A”服务。



Zuul 与 Eureka 协同工作

Zuul 除了可以做路由,还可以做过滤器,针对权限验证,金丝雀测试都可以用到它。这里简单说说 Zuul 内部的运行机制。

Zuul 收到 HTTP 请求以后,会通知 Zuul Servlet 处理,与此同时会生成一个 Request Context 用来记录请求的上下文信息,它会一直保持直到路由结束。

Zuul Filter Runner 接到 Zuul Servlet 的通知以后,会从 Request Context 中取请求的信息,并且交给 Filter Processer 处理,它会维护一套过滤和路由的规则,根据这些规则将请求发送到目标的服务。



Zuul 内部工作原理图

Spring Cloud 微服务架构总结

说完了上面这些是不是对 Spring Cloud 理解更加深了。让我们来回顾一下,Spring Cloud 是一个微服务架构,它为微服务开发提供了丰富的组件。

其中比较重要的五大组件分别是:

  • Eureka:服务发现,服务注册。
  • Feign:服务调用请求。
  • Ribbon:服务之间负载均衡。
  • Hystrix:熔断器。
  • Zuul:服务网关。

如果,用我们上面 ABC 的例子来记忆就是,A 调用 B(Eureka),A 发送请求(Feign),B 做横向扩展以后,A 通过(Ribbon)找到 B,B 出现问题 A 通过熔断机制(Hystrix)保证服务调用正常,C 通过 Zuul 找到 A。

用一张大图来总结一下:



通过 ABC 理解 Spring Cloud 的五大组件

还可以把整个流程总结一下,客户端请求→Zuul→Eureka 获取服务→Feign 通信→Ribbon 负载均衡→Hystrix 熔断:

  • 用户请求会最先发送给 Zuul,Zuul 是用来做 API 网关的。同时它也可以作为过滤器。
  • 微服务的注册操作需要通过 Eureka,作为服务发现和注册中心,一方面记录服务的注册以及健康情况,一方面会协同 Zuul 做好服务访问的工作。
  • 微服务之间通讯,需要把数据打包发送,接受以后也需要解包读取信息。这里可以使用 Feign 作为服务通讯的组件,配合 Ribbon 完成通信工作。
  • Robbin,其负责微服务集群的负载均衡工作。
  • 服务出现故障,例如:业务异常,网络异常等等。需要通过断路器 Hystrix 来实现具体的处理操作,比如通知注册中心服务异常,比如对服务进行降级处理。

这个时候服务注册发现中心会标记服务异常,再有请求过来就不会发送到有异常的服务上去了。

同时服务发现注册中心也会定期检查服务的状态,一旦服务恢复状态又把其放到访问队列中。

作者:崔皓

简介:十六年开发和架构经验,曾担任过惠普武汉交付中心技术专家,需求分析师,项目经理,后在创业公司担任技术/产品经理。善于学习,乐于分享。目前专注于技术架构与研发管理。

【51CTO原创稿件,合作站点转载请注明原文作者和出处为51CTO.com】

相关推荐

MySQL5.5+配置主从同步并结合ThinkPHP5设置分布式数据库

前言:本文章是在同处局域网内的两台windows电脑,且MySQL是5.5以上版本下进行的一主多从同步配置,并且使用的是集成环境工具PHPStudy为例。最后就是ThinkPHP5的分布式的连接,读写...

thinkphp5多语言怎么切换(thinkphp5.1视频教程)

thinkphp5多语言进行切换的步骤:第一步,在配置文件中开启多语言配置。第二步,创建多语言目录。相关推荐:《ThinkPHP教程》第三步,编写语言包。视图代码:控制器代码:效果如下:以上就是thi...

基于 ThinkPHP5 + Bootstrap 的后台开发框架 FastAdmin

FastAdmin是一款基于ThinkPHP5+Bootstrap的极速后台开发框架。主要特性基于Auth验证的权限管理系统支持无限级父子级权限继承,父级的管理员可任意增删改子级管理员及权限设置支持单...

Thinkphp5.0 框架实现控制器向视图view赋值及视图view取值操作示

本文实例讲述了Thinkphp5.0框架实现控制器向视图view赋值及视图view取值操作。分享给大家供大家参考,具体如下:Thinkphp5.0控制器向视图view的赋值方式一(使用fetch()方...

thinkphp5实现简单评论回复功能(php评论回复功能源码下载)

由于之前写评论回复都是使用第三方插件:畅言所以也就没什么动手,现在证号在开发一个小的项目,所以就自己动手写评论回复,没写过还真不知道评论回复功能听着简单,但仔细研究起来却无法自拔,由于用户量少,所以...

ThinkPHP框架——实现定时任务,定时更新、清理数据

大家好,我是小蜗牛,今天给大家分享一下,如何用ThinkPHP5.1.*版本实现定时任务,例如凌晨12点更新数据、每隔10秒检测过期会员、每隔几分钟发送请求保证ip的活性等本次分享,主要用到一个名为E...

BeyongCms系统基于ThinkPHP5.1框架的轻量级内容管理系统

BeyongCms内容管理系统(简称BeyongCms)BeyongCms系统基于ThinkPHP5.1框架的轻量级内容管理系统,适用于企业Cms,个人站长等,针对移动App、小程序优化;提供完善简...

YimaoAdminv3企业建站系统,使用 thinkphp5.1.27 + mysql 开发

介绍YimaoAdminv3.0.0企业建站系统,使用thinkphp5.1.27+mysql开发。php要求5.6以上版本,推荐使用5.6,7.0,7.1,扩展(curl,...

ThinkAdmin-V5开发笔记(thinkpad做开发)

前言为了快速开发一款小程序管理后台,在众多的php开源后台中,最终选择了基于thinkphp5的,轻量级的thinkadmin系统,进行二次开发。该系统支持php7。文档地址ThinkAdmin-V5...

thinkphp5.0.9预处理导致的sql注入复现与详细分析

复现先搭建thinkphp5.0.9环境...

thinkphp5出现500错误怎么办(thinkphp页面错误)

thinkphp5出现500错误,如下图所示:相关推荐:《ThinkPHP教程》require():open_basedirrestrictionineffect.File(/home/ww...

Thinkphp5.0极速搭建restful风格接口层

下面是基于ThinkPHPV5.0RC4框架,以restful风格完成的新闻查询(get)、新闻增加(post)、新闻修改(put)、新闻删除(delete)等server接口层。1、下载Thin...

基于ThinkPHP5.1.34 LTS开发的快速开发框架DolphinPHP

DophinPHP(海豚PHP)是一个基于ThinkPHP5.1.34LTS开发的一套开源PHP快速开发框架,DophinPHP秉承极简、极速、极致的开发理念,为开发集成了基于数据-角色的权限管理机...

ThinkPHP5.*远程代码执行高危漏洞手工与升级修复解决方法

漏洞描述由于ThinkPHP5框架对控制器名没有进行足够的安全检测,导致在没有开启强制路由的情况下,黑客构造特定的请求,可直接GetWebShell。漏洞评级严重影响版本ThinkPHP5.0系列...

Thinkphp5代码执行学习(thinkphp 教程)

Thinkphp5代码执行学习缓存类RCE版本5.0.0<=ThinkPHP5<=5.0.10Tp框架搭建环境搭建测试payload...

取消回复欢迎 发表评论: