Spring Cloud

Spring Cloud:

官网地址:官网地址:https://spring.io/projects/spring-cloud

概述:

Spring Cloud 是 一个全家桶式技术栈,内部包含了很多组件:

核心组件:

  • Eureka(注册中心)
  • Hystrix(断流器,熔断器)
  • Feign
  • Ribbon(负载均衡)
  • Gateway(网关)Zuul

Spring Cloud Eureka

概述:

负责管理,记录服务提供者信息,服务调用则无需自己寻找服务,而是把自己的需求告诉Eureka,然后Eureka会把符合你需求的服务告诉你。

同时,服务提供方与Eureka之间通过“心跳”机制进行监控,当某个服务提供方出现问题,Eureka自然会把它从服务列表中剔除

原理图:

原理图

eureka介绍:
  • Eureka-Server:就是服务注册中心(可以是一个集群),对外暴露自己的地址。
  • 提供者:启动后向Eureka注册自己信息(地址,服务名称等),并且定期进行服务续约
  • 消费者:服务调用方,会定期去Eureka拉取服务列表,然后使用负载均衡算法选出一个服务进行调用。
  • 心跳(续约):提供者定期通过http方式向Eureka刷新自己的状态
使用 Eureka Server 步骤:
  • 导入依赖:
<!-- eureka服务端 -->
	<dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
    </dependencies>
  • 在启动类上添加 @EnableEurekaServer
  • 在yaml配置文件 配置eureka 地址
eureka:
  client:
    service-url:  # 如果是集群,每个地址需要使用逗号隔开
      defaultZone: http://  "EurekaServer地址"  /eureka/ 
    # 当只有一个eurekaServer 时 可使用以下配置
    register-with-eureka: false # 不注册自己
    fetch-registry: false #不拉取服务
服务注册:(EurekaClient)
  • 导入eureka client 依赖
<!-- Eureka客户端 -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
  • 在yaml配置文件配置eurekaServer 地址
eureka:
  client:
    service-url: 
      defaultZone: http://  "EurekaServer地址"  /eureka/
  • 手动拉取服务提供者地址
    – 注入DiscoveryClient 对象
    – 根据 服务id 获取服务实例列表

服务注册原理:
服务提供者在启动时,会检测配置属性中的:eureka.client.register-with-erueka=true参数是否正确,事实上默认就是true。如果值确实为true,则会向EurekaServer发起一个Rest请求,并携带自己的元数据信息,Eureka Server会把这些信息保存到一个双层Map结构中。
一个服务,可以同时启动多个不同实例,形成集群。

通过修改yaml配置文件eureka 配置,可以自定义实例id 防止使用主机名,实例id冲突

eureka:
  instance:
    ip-address: 127.0.0.1 # ip地址
    prefer-ip-address: true # 更倾向于使用ip,而不是host名
    instance-id: ${eureka.instance.ip-address}:${server.port} 
    # 自定义实例的id
服务续约:

在注册服务完成以后,服务提供者会维持一个心跳(定时向EurekaServer发起Rest请求)
默认情况下每个30秒服务会向注册中心发送一次心跳,证明自己还活着。如果超过90秒没有发送心跳,EurekaServer就会认为该服务宕机,会从服务列表中移除,

  • 可以通过修改yaml文件配置来修改心跳时间
eureka:
  instance:
    lease-expiration-duration-in-seconds: 90 # 服务失效时间,默认值90秒
    lease-renewal-interval-in-seconds: 30 # 服务续约(renew)的间隔,默认为30秒
获取服务列表:

当服务消费者启动是,会检测eureka.client.fetch-registry=true参数的值,如果为true,则会从Eureka Server服务的列表只读备份,然后缓存在本地。并且每隔30秒会重新获取并更新数据。

eureka:
  client:
    registry-fetch-interval-seconds: 30 # 获取更新数据 默认间隔时间
失效剔除:

服务中心在启动时会创建定时任务,默认每隔60秒将超时(默认90秒)没有续约的服务剔除,

由于非正常关闭不会执行主动下线动作,所以才会出现失效剔除机制,该机制主要是应对非正常关闭服务的情况,如:内存溢出、杀死进程、服务器宕机等非正常流程关闭服务节点时。

可以通过eureka.server.eviction-interval-timer-in-ms参数对其进行修改,单位是毫秒。

自我保护机制:

触发Eureka的自我保护机制。当服务未按时进行心跳续约时,Eureka会统计服务实例最近15分钟心跳续约的比例是否低于了85%。在生产环境下,因为网络延迟等原因,心跳失败实例的比例很有可能超标,但是此时就把服务剔除列表并不妥当,因为服务可能没有宕机。Eureka在这段时间内不会剔除任何服务实例,直到网络恢复正常。生产环境下这很有效,保证了大多数服务依然可用,不过也有可能获取到失败的服务实例,因此服务调用者必须做好服务的失败容错。

需要使用到容错机制,和熔断机制来进行处理;

eureka:
  server:
    enable-self-preservation: false # 关闭自我保护模式(缺省为打开)

Spring Cloud Hystrix

概述:

Netflix开源的一个延迟和容错库,用于隔离访问远程服务、第三方库,防止出现级联失败
作用:

  • 对通过第三方客户端访问的依赖项的延迟和故障进行保护和控制。
  • 在复杂的分布式系统中组织级联故障。
  • 快速失败,快速恢复。
  • 回退,尽可能优雅地降级
  • 启用近实时监控、警报和操作控制。

复杂的分布式体系结构中,应用程序都有很过依赖项,每个依赖项在,某些时候发生不可避免的失败时,主机应用程序没有能隔离这些外部故障的失败依赖,应用程序就会被拖垮

雪崩问题:
服务之间相互调用时或者用户发送请求时,当某个服务发送故障或者宕机,那么其他服务调用故障服务,就会发生阻塞,一直得不到响应,就会一直阻塞,线程一直的不到释放,当越来越多的服务调用,用户请求到来,就会有越来越多的线程阻塞,服务器支持的线程和并发数有限,请求一直阻塞,会导致服务器资源耗尽,从而导致所有其它服务都不可用,形成雪崩效应。

可以使用 "线程隔离"和"服务熔断"方式解决雪崩问题;

使用步骤:

  • 导入依赖:
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
  • 启动类上添加注解@EnableCircuitBreaker 或者 @SpringCloudApplication 此注解中包含: @EnableCircuitBreake @EnableDiscoveryClient ``@SpringBootApplication 等注解
线程隔离

用户的请求将不再直接访问服务,而是通过线程池中的空闲线程来访问服务,如果线程池已满,或者请求超时,则会进行降级处理:返回给用户一个错误提示

服务降级:

当服务请求发生故障,快速处理失败,使用服务降级,返回友好提示;
在请求方法上使用@HystixCommond(fallbackMethod = )指定降级处理方法,然后编写降级处理逻辑
熔断的降级逻辑方法必须跟正常逻辑方法保证:相同的参数列表和返回值声明

超时设置:
hystrix 的默认请求超时时间为1s,请求一旦超时,会立马执行降级处理逻辑

hystrix:
  command:
    default: # 设置 hystrix 请求超时时间
      execution.isolation.thread.timeoutInMilliseconds: 2000
服务熔断

尽管线程隔离可以避免出现级联失败,但是对于其他服务访问故障服务,每次访问处理请求都要等待超时,非常浪费系统资源,

服务熔断可以解决这一问题
当Hystix判断一个依赖服务失败比例较高时,就会对其做熔断处理:拦截对故障服务的请求,快速失败,不再阻塞等待

熔断器(断路器)原理:

服务调用方可以判断某些服务反应慢或者存在大量超时情况, 主动熔断,防止系统崩溃, hystrix 可以实现弹性容错,当情况好转,可以自动重连,允许部分请求通过,如果调用成功回到关闭状态,否则继续断开;

熔断器(断路器)状态:
  • Closed:关闭状态(断路器关闭),所有请求都正常访问。
  • Open:打开状态(断路器打开),所有请求都会被降级。Hystix会对请求情况计数,当一定时间内失败请求百分比达到阈值,则触发熔断,断路器打开。默认失败比例的阈值是50%,请求次数最少不低于20次。
  • Half Open:半开状态,open状态不是永久的,打开后会进入休眠时间(默认是5S)。随后断路器会自动进入半开状态。此时会释放1次请求通过,若这个请求是健康的,则会关闭断路器,否则继续保持打开,再次进行5秒休眠计时。

Spring Cloud Ribbon

概述:

Eureka 中已经集成 Ribbon 所以不需要导入依赖

  • 在spring cloud 中Ribbon负载均衡 和 Feign , Eureka 之间互相协作处理;

    • 首先,ribbon会根据 服务id 从 eurekaServer注册中心获对应的所有服务实例相关信息,ip ,端口号等,
    • Ribbon 使用 默认的 Round Robin (轮询算法) 服务实例中获取一个
    • Feign 根据获取到的服务实例,构造http请求并发送
  • 单独使用 Ribbon

// 启动类中声明 Bean 
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
    return new RestTemplate();
}
-----------------------------------------
// controller 层
@GetMapping("{id}")
public User queryById(@PathVariable("id") Long id){
	// 这里不是直接使用ip:端口 而是使用服务id
    String url = "http://user-service/user/" + id;
    User user = restTemplate.getForObject(url, User.class);
    return user;
}

根据服务id(user-service)去eureka拉取服务列表,返回列表后,Ribbon的负载均衡策略会从列表从选择一个实例,向实例发送请求

源码跟踪:

LoadBalancerInterceptor,这个类会在对RestTemplate的请求进行拦截,然后从Eureka根据服务id获取服务列表,随后利用负载均衡算法得到真实的服务地址信息,替换服务id。

  • LoadBalancerInterceptor类中方法

    request.getURI():获取请求uri
    originalUri.getHost():获取uri路径的主机名,就是服务id user-service
    this.loadBalancer.execute():处理服务id,和用户请求。

  • 继续跟入this.loadBalancer.execute()execute方法
    在这里插入图片描述
    getLoadBalancer(serviceId):根据服务id 获取负载均衡器(loadBalancer),然后负载均衡器会根据服务id 去Eureka中获取服务列表并保存
    getServer(loadBalancer):利用内置负载均衡算法,从服务列表选择一个服务实例

  • 底层通过实现IRule 接口(负载均衡规则) 来指定负载均衡规则,默认使用RoundRobinRule实现类(轮询规则)

    • 可以通过修改yaml配置文件来指定规则(一般使用默认规则轮询)
    • 格式是:{服务名称}.ribbon.NFLoadBalancerRuleClassName,值就是IRule的实现类。
  • Ribbon 默认懒加载 即第一次访问时才会去创建负载均衡客户端

ribbon:
  eager-load:
    enabled: true # 开启饥饿加载
    clients: user-service #指定服务id 

Spring Cloud Gateway

概述:
流程图:

在这里插入图片描述

Spring Cloud Feign

概述:

是一个http请求调用的轻量级框架,可以以Java接口注解的方式调用Http请求,而不用像Java中通过封装HTTP请求报文的方式直接调用。Feign通过处理注解,将请求模板化,当实际调用的时候,传入参数,根据参数再应用到请求上,进而转化成真正的请求

使用步骤:

  • 导入依赖:
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
  • 在启动类上 添加@EnableFeignClients
  • 定义客户端接口,使用@FeignClient注解 指定服务id
  • 接口中定义的方法,使用springMVC注解,feign会根据注解自动生成url,并获取访问结果,

原理:

  • 启动时,程序会进行包扫描,扫描所有包下所有@FeignClient注解的类,并将这些类注入到spring的IOC容器中。当定义的Feign中的接口被调用时,通过JDK的动态代理来生成RequestTemplate。
  • RequestTemplate中包含请求的所有信息,如请求参数,请求URL等。
  • RequestTemplate声明Request,然后将Request交给client处理,这个client默认是JDK的HTTPUrlConnection,也可以是OKhttp、Apache的HTTPClient等。
  • 最后client封装成LoadBaLanceClient,结合ribbon负载均衡地发起调用。
负载均衡:

feign 本身集成了ribbon依赖和自动配置
不需要导入依赖,也不需要注册restTemplate

  • 可以通过修改yaml文件修改配置
ribbon:
  ConnectTimeout: 500 # 连接超时时长
  ReadTimeout: 2000 # 数据通信超时时长
  MaxAutoRetries: 0 # 当前服务器的重试次数
  MaxAutoRetriesNextServer: 1 # 重试多少次服务
  OkToRetryOnAllOperations: false # 是否对所有的请求方式都重试
  
  Hystix的超时时间,应该比重试的总时间要大,
整合Hystrix:

Feign默认对Hystrix 也做了集成;默认情况下是关闭的

  • 开启hystrix
feign:
  hystrix:
    enabled: true # 开启Feign的熔断功能

但是在Feign中Hystrix的降级处理逻辑比较复杂;

  • 实现带有@FeignClient 注解的接口
  • 编写降级处理逻辑
  • 在 @FeignClient注解 的接口中指定实现类的字节码文件
日志级别:
  • yaml文件配置日志
logging:
  level:
   包名: debug # 级别
	
  • 编写配置类
@Configuration
public class FeignConfig {
    @Bean
    Logger.Level feignLoggerLevel(){
        return Logger.Level.FULL; #设置日志级别
    }
}

级别:

  • NONE:不记录任何日志信息,这是默认值。
  • BASIC:仅记录请求的方法,URL以及响应状态码和执行时间
  • HEADERS:在BASIC的基础上,额外记录了请求和响应的头信息
  • FULL:记录所有请求和响应的明细,包括头信息、请求体、元数据。
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值