现阶段分布式这块在面试的过程中一般情况下是始终绕不开的,今天我们就来谈一谈常见的分布式当中出现的一些面试题。
Spring Boot + Spring Cloud应该是众多小伙伴儿常见的分布式框架,当然也有很多其他优秀的实现方式解决方法,毕竟程序员的存在就是为了发现问题、解决问题、完善问题。Spring Cloud全家桶给我们提供了丰富的组件,以快速构建分布式系统中的一些常见模式(例如,配置管理,服务发现,断路器,智能路由,微代理,控制总线,一次性令牌,全局锁,领导选举,分布式会话,群集状态)。分布式系统的协调导致样板式样,并且使用Spring Cloud开发人员可以快速建立实现这些样板的服务和应用程序。它们可以在任何分布式环境中正常工作,包括自己的笔记本电脑,裸机数据中心以及Cloud Foundry等托管平台。下面让我们一同揭开Spring Cloud这神秘的面纱
Eurake 实现注册中心 (统一协调和管理所有的服务)
Eureka 是 Netflix 开发的,一个基于 REST 服务的,服务注册与发现的组件它主要包括两个组件:Eureka Server 和 Eureka Client
Eureka Client:一个Java客户端,用于简化与 Eureka Server 的交互(通常就是微服务中的客户端和服务端)
Eureka Server:提供服务注册和发现的能力(通常就是微服务中的注册中心)

各个微服务启动时,会通过 Eureka Client 向 Eureka Server 注册自己,Eureka Server 会存储该服务的信息.也就是说,每个微服务的客户端和服务端,都会注册到 Eureka Server,这就衍生出了微服务相互识别的话题
同步:每个 Eureka Server 同时也是 Eureka Client(逻辑上的),多个 Eureka Server 之间通过复制的方式完成服务注册表的同步,形成 Eureka 的高可用
识别:Eureka Client 会缓存 Eureka Server 中的信息(本地缓存)即使所有 Eureka Server 节点都宕掉,服务消费者仍可使用缓存中的信息找到服务提供者(笔者已亲测)
续约:微服务会周期性(默认30s)地向 Eureka Server 发送心跳以Renew(续约)信息(类似于heartbeat)
续期:Eureka Server 会定期(默认60s)执行一次失效服务检测功能,它会检查超过一定时间(默认90s)没有Renew的微服务,发现则会注销该微服务节点
常用注解:@EnableEurekaServer 标记这是一个注册中心
@EnableEurekaClient 标记这是一个客户端(服务提供者)
@EnableDiscoveryClient 发现服务(服务消费者)
如果一个消费者需要使用同一个提供者的多个服务,则需要在application.properties / application.yml文件中设置(很多设置都是在application中完成的)
spring.main.allow-bean-definition-overriding=true
高可用注册中心示意图

Eureka Server的高可用实际上就是将自己作为服务向其他服注册中心注册自己,形成一组互相注册的服务注册中心,以实现服务清单的互相同步,达到高可用的效果。Eureka server 1, Eureka server 2相互感应,当有服务注册时,多个Eureka-server是对等的,它们都存有相同的信息,这就是通过服务器的冗余来增加可靠性,当有一台服务器宕机了,服务并不会终止,因为另一台服务存有相同的数据。注意:Eureka互相注册要求各个Eureka实例的eureka.instance.hostname不同,如果相同,则会被Eureka标记为unavailable-replicas
Hytrix 熔断器(服务降级、链路监控、防治服务雪崩)
在微服务架构中,通常会有很多层的服务调用。如果一个底层服务出现问题,故障会被向上传播给用户。我们需要一种机制,当底层服务不可用时,可以阻断故障的传播。这就是断路器的作用。他是系统服务稳定性的最后一重保障。当对某个服务的调用在一定的时间内(默认10s,由metrics.rollingStats.timeInMilliseconds配置),有超过一定次数(默认20次,由circuitBreaker.requestVolumeThreshold参数配置)并且失败率超过一定值(默认50%,由circuitBreaker.errorThresholdPercentage配置),该服务的断路器会打开。返回一个由开发者设定的fallback。
Hystrix遵循的设计原则:
防止任何单独的依赖耗尽资源(线程)
过载立即切断并快速失败,防止排队
尽可能提供回退以保护用户免受故障
使用隔离技术(例如隔板,泳道和断路器模式)来限制任何一个依赖的影响
通过近实时的指标,监控和告警,确保故障被及时发现
通过动态修改配置属性,确保故障及时恢复
防止整个依赖客户端执行失败,而不仅仅是网络通信
Hystrix如何实现这些设计目标?
使用命令模式将所有对外部服务(或依赖关系)的调用包装在HystrixCommand或HystrixObservableCommand对象中,并将该对象放在单独的 线程中执行
每个依赖都维护着一个线程池(或信号量),线程池被耗尽则拒绝请求(而不是让请求排队)
记录请求成功,失败,超时和线程拒绝
服务错误百分比超过了阈值,熔断器开关自动打开,一段时间内停止对该服务的所有请求
请求失败,被拒绝,超时或熔断时执行降级逻辑
近实时地监控指标和配置的修改
Zuul 网管路由(实现url过滤链处理,智能识别)
zuul使用一系列的filter实现以下功能:
认证和安全 - 对每一个resource进行身份认证
追踪和监控 - 实时观察后端微服务的TPS、响应时间,失败数量等准确的信息
日志 - 记录所有请求的访问日志数据,可以为日志分析和查询提供统一支持
动态路由 - 动态的将request路由到后端的服务上去
压力测试 - 逐渐的增加访问集群的压力,来测试集群的性能
限流
静态响应 - 直接在网关返回一些响应,而不是通过内部的服务返回响应
主要核心就是filter、filter流与核心架构。作为网关这么重要的角色,高可用是非常有必要的。但是通常来讲网关所面对的请求应该的是来于外部,所以虽然说网关可以注册到Eureka Server上,但是外部客户端的数量众多,是不可能向Eureka Server注册的。那么要想实现高可用我们可以在网关前面再架一个前置代理(如Nginx),或者让客户端从Eureka Server处获取Zuul网关地址实现客户端负载均衡。
Rubbon 负载均衡
Spring Cloud Ribbon是一个基于HTTP和TCP的客户端负载均衡工具,它基于Netflix Ribbon实现。通过Spring Cloud的封装,可以让我们轻松地将面向服务的REST模版请求自动转换成客户端负载均衡的服务调用。Spring Cloud Ribbon只是一个工具类框架不需要独立部署,但是它却几乎存在每一个Spring Cloud构建的微服务和基础设施中。微服务间的调用,API网关的请求转发等内容,实际上都是通过Ribbon来实现的,包括后续我们将要介绍的Feign,它也是基于Ribbon实现的工具。足以可见Rubbon的强大

负载均衡模块都会维护一个下挂且可用的服务端清单,通过心跳检测来剔除故障的服务端节点以保证清单中都是可以正常访问的服务端节点。当客户端发送请求到负载均衡设备的时候,该设备则会按照某种算法从维护可用的服务端清单中取出一台服务端端地址然后进行转发(比如线性轮询、按权重负载、按流量负载等实现方式)
Feign 声明式服务消费 (进行服务消费)
Feign的存在让微服务之间的调用变得更简单了,类似controller调用service。Spring Cloud集成了Ribbon和Eureka,可在使用Feign时提供负载均衡的http客户端。feign底层是使用了ribbon作为负载均衡的客户端,而ribbon的负载均衡也是依赖于eureka 获得各个服务的地址,所以要引入eureka-client。SpringbootApplication启动类加上@FeignClient注解,以及@EnableDiscoveryClient
原理:
启动时,程序会进行包扫描,扫描所有包下所有@FeignClient注解的类,并将这些类注入到spring的IOC容器中。当定义的Feign中的接口被调用时,通过JDK的动态代理来生成RequestTemplate。RequestTemplate中包含请求的所有信息,如请求参数,请求URL等。RequestTemplate声场Request,然后将Request交给client处理,这个client默认是JDK的HTTPUrlConnection,也可以是OKhttp、Apache的HTTPClient等。最后client封装成LoadBaLanceClient,结合ribbon发起调用
Bus 控制总线 (实现消费通信)
感觉这块没有什么特别好介绍的,在此附上官网网址https://www.springcloud.cc/spring-cloud-bus.html