文章目录
一、微服务
1.1 微服务
微服务是一种架构模式或者说是一种架构风格,提倡将单一应用程序划分成一组小的服务,每个服务独立运行,采用轻量级的通信机制互相通信,服务之间互相协调、互相配合,为用户提供最终价值。
微服务化的核心就是将传统的一站式应用,根据业务拆分成一个一个的服务,每一个微服务提供单个业务功能的服务。
1.2 Spring Cloud
Spring Cloud 是分布式微服务架构下的一站式解决方案,是各个微服务架构落地技术的集合体,俗称微服务全家桶。Spring Cloud 利用 Spring Boot 的开发便利性,简化了分布式系统基础设施的开发,如服务注册发现、负载均衡、熔断器、服务网管、配置中心等,都可以做到一键启动和部署。
1.2.1 优点
- 出产于Spring大家族
- 组件丰富功能齐全,例如提供了配置管理、服务发现、断路器、微服务网关等
- 服务拆分度高系统耦合度低,有利于资源重复利用提高开发效率
1.2.2 缺点
- 微服务过多,治理成本高,不利于维护系统
- 分布式系统开发的成本高,容错,分布式事务等
1.3 微服务问题
1.3.1 服务雪崩
是一种因服务提供者的不可用,导致服务调用者的不可用,并将不可用逐渐放大的过程。当某一服务出现异常,拖垮整个服务链路,消耗整个线程队列,造成服务不可用,资源耗尽。
1.3.2 服务熔断
在软件系统中,由于某些服务出现了过载现象,为防止造成整个系统故障,从而采用的一种保护措施,类似于现实世界的保险丝。
1.3.3 服务降级
当服务器压力剧增的情况下,根据当前业务情况对一些服务有策略的降级,以此释放服务器资源以保证核心任务的正常运行。
二、Spring Cloud 组件
2.1 Spring Cloud 五大组件
- 服务发现与注册:eureka、zookeeper、nacos
- 客户端负载均衡:ribbon、feign
- 服务网关:zuul、zull、gateway
- 服务熔断和降级:hystrix、sentinel
- 分布式配置:spring cloud config
2.2 服务发现与注册
2.2.1 Eureka 自我保护机制
默认情况下,如果 EurekaServer 在一定时间内没有收到某个服务的心跳,会将该实例注销(默认90秒),当网络发生故障 EurekaServer 与微服务之间无法正常通信时,Eureka 会进入自我保护模式,保护服务注册表中的信息,不再注销任何实例。
2.2.2 Nacos
Nacos 是一个更易于帮助构建云原生应用的动态服务发现、配置和服务管理平台,提供注册中心、配置中心和动态DNS服务三大功能。
2.2.3 Nacos 服务注册
spring-cloud-common 包中提供了一个类 ServiceRegistry,它是提供服务注册的标准,集成 Spring Cloud 实现服务注册的组件都会实现该接口,NacosServiceRegistry 正是实现了这个接口。
- 在 Spring 容器启动的时候,通过了 NacosDiscoveryProperties 获取了 application.properties 中的关于 spring.cloud.nacos.discovery 的配置数据。
- 然后通过配置类 NacosServiceRegistryAutoConfiguretion 初始化 NacosServiceRegistry,这个类是真正的服务注册的入口。
- 在容器启动时会执行 NacosServiceRegistry 的 register() 方法,最终会调用 NacosNamingService 的 registerInstance() 方法,该方法会创建一个线程池去执行心跳检测的操作,默认每隔 5s 执行一次心跳检查,然后调用 NamingProxy 的 registerService() 方法注册服务。
2.2.4 Nacos 服务发现
- 在 Spring 容器启动的时候,通过了 NacosDiscoveryProperties 获取了 application.properties 中的关于 spring.cloud.nacos.discovery 的配置数据。
- 然后通过配置类 NacosDiscoveryAutoConfiguration 初始化 NacosServiceDiscovery,通过配置类 NacosDiscoveryClientConfiguration 初始化 NacosDiscoveryClient。
- 在容器启动时会初始化 NacosNamingService,在该类的 init() 方法中,开启了服务心跳监听线程类 BeatReactor 和服务动更新线程类 HostReactor。
- 在HostReatcor的getServiceInfo()方法中启动UpdateTask任务更新服务,任务执行时先查询本地缓存是否有该服务,如果没有那么就会立即去请求,然后判断过期时间等信息。
- 同时会在 HostReactor 类中初始化一个 PushReceiver 对象,PushReceiver 会创建一个UDP Socket 和 Server 端建立连接,不断的循环去监听 server 端 push 的数据,然后将数据解析为ServiceInfo 返回。
2.3 OpenFeign
2.3.1 OpenFeign
是在 Ribbon 的基础上进行了一次改进,是一种声明式、模板化的HTTP客户端,可以简化模板代码的开发。
2.3.2 底层原理
- 注解 @EnableFeignClients 开启 Feign,扫描所有包含了 @FeignClient 注解的类,将 @FeignClient 中的配置加载到 FeignClientFactoryBean 中。
- 容器启动时调用 FeignClientFactoryBean#getObject 来创建 Feignclient 实例,创建实例的方式是通过获取 Targeter 来生成动态代理类,代理类的 handler 是 ReflectiveFeign.FeignInvocationHandler。
- 当发起远程调用时,执行 FeignInvocationHandler 的 invoke 方法,最终调用 SynchronousMethodHandler 的 invoke 方法,该方法主要是应用 encoder、decoder 以及 retry 等配置,并执行 http 请求处理返回结果。
- 构建 http 请求是调用 Client.Default 的 execute 方法,该方法会构建 HttpURLConnection 对象,并调用 HttpURLConnection 进行 http 请求。
2.3.3 调用流程
Feign远程调用,核心就是通过一系列的封装和处理,将以JAVA注解的方式定义的远程调用API接口,最终转换成HTTP的请求形式,然后将HTTP的请求的响应结果,解码成JAVA Bean,返回回给调用者。
2.4 Ribbon
2.4.1 负载均衡
负载均衡简单来说就是将用户的请求分配到多个服务上,从而实现系统的高可用,常见的负载均衡软件有Nginx、LVS、等。
- Nginx 是服务端负载均衡,客户端的所有请求都会交给 Nginx,然后由 Nginx 实现转发请求,即负载均衡是由服务端实现的。
- Ribbon 是本地负载均衡,在调用微服务接口的时候,会在注册中心中获取服务信息列表,然后缓存到 JVM 本地,从而在本地实现远程服务调用。
2.4.2 Ribbon
Ribbon 是一个基于 HTTP 和 TCP 客户端的负载均衡的工具。Ribbon 在工作时首先注册到注册中心中并获取服务信息列表,然后根据负载策略,在服务信息列表中选择一个服务。
2.4.3 Ribbon 负载均衡机制
策略 | 命名 | 说明 |
---|---|---|
RandomRule | 随机策略 | 随机选择服务 |
RoundRobinRule | 轮询策略 | 按顺序循环选择服务 |
RetryRule | 重试策略 | 如果获取服务失败则在指定时间内会进行重试,获取可用的服务 |
BestAvailableRule | 最低并发策略 | 过滤多次访问处于断路打开状态的服务,然后选择一个并发量最小的服务 |
AvailabilityFilteringRule | 可用过滤策略 | 过滤掉故障服务和高并发服务,再选择并发较小的服务 |
WeightedResponseTimeRule | 响应时间加权策略 | 响应速度越快的服务选择权重越大,越容易被选择 |
ZoneAvoidanceRule | 默认规则 | 复合判断 server 所在区域的性能和 server 的可用性选择服务器 |
2.5 服务网关
2.5.1 网关
服务网关 = 路由转发 + 过滤器。
- 路由转发:接收一切外界请求,转发到后端的微服务上去。
- 过滤器:在服务网关中可以完成一系列的横切功能,例如权限校验、限流以及监控等。
2.5.2 Gateway 组成
- 路由:网关的基本模块:ID、目标URI、一组断言和一组过滤器组成。
- 断言:访问该路由的访问规则,可以用来匹配来自http请求的任何内容。
- 过滤器:实现过滤一些请求,可以自定义过滤器,通过实现 ordered 和 globalfilter 接口。
2.5.3 Zuul 和 Gateway 的区别
- 内部实现:gateway对比zuul多依赖了spring-webflux,在spring的支持下,功能更强大,内部实现了限流、负载均衡等。
- 是否支持异步:gateway 支持异步,理论上更适合于提高系统吞吐量,zuul 仅支持同步。
- 框架设计:gateway具有更好的扩展性,并且其已经发布了很多版本,稳定性也是非常好的。
- 性能:gateway可以用来构建异步的、非堵塞的、事件驱动的服务,具有良好的伸缩性,使用非阻塞API。zuul 1.x 是阻塞的,zuul 2.x 基于 netty 是非阻塞的。
2.6 服务熔断和降级
2.6.1 Hystrix
Hystrix 是一个处理分布式系统的延迟和容错的开源库,在某个服务出问题的情况下,不会导致整体服务失败,避免级联故障,提高分布式系统的可用性。
2.6.2 服务降级(fallback)
向调用方返回一个符合预期的、可处理的备选响应,保证服务调用方的处理流程,避免故障在分布式系统中蔓延。
2.6.3 服务熔断(break)
类比日常生活中的保险丝,当达到最大服务访问后,直接拒绝请求拉闸限电,然后调用服务降级方法返回友好提示。
2.6.4 Hystrix 熔断和降级
- 通过注解 HystrixCommand 实现服务熔断和降级,当被调用的方法不可用时,执行注解指定的 fallbackMethod 方法。
- 通过 FeignClient 实现服务熔断和降级,在启动类中添加注解 EnableCircuitBreaker 启用熔断机制,然后添加 FeignClient 和降级类。
2.6.5 熔断机制
- 熔断器关闭CLOSED:熔断关闭,不会对服务进行熔断。
- 熔断器打开OPEN:请求不再调用当前服务,内部设置平均故障处理时间,当打开时长达到所设时长则进入半熔断状态。
- 熔断器半开HALF-OPEN:部分请求根据规则调用当前服务,如果请求成功且符合规则则认为当前服务恢复正常关闭熔断。
2.6.6 Sentinel
Sentinel 是面向分布式服务架构的轻量级流量控制产品,主要以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度来帮助您保护服务的稳定性。
2.7 Spring Cloud 和 Spring Boot 的区别
- Spring Boot 专注于快速方便的开发单个个体微服务。
- Spring Cloud 是关注全局的微服务协调整理治理框架以及一整套的落地解决方案,它将 Spring Boot 开发的一个个单体微服务整合并管理起来,为各个微服务之间提供:配置管理,服务发现,断路器,路由,微代理,事件总线等的集成服务。
- Spring Boot 可以离开 Spring Cloud 独立使用,但是 Spring Cloud 离不开 Spring Boot ,属于依赖的关系。