springCloud-day02

一:Ribbon(消费者调用多个提供者时-负载均衡)
1.实际环境中,我们往往会开启很多个service的集群。此时我们获取的服务列表中就会有多个,到底该访问哪一个呢?一般这种情况下我们就需要编写负载均衡算法,在多个实例列表中进行选择。不过Eureka中已经帮我们集成了负载均衡组件:Ribbon,简单修改代码即可使用。
2.开启负载均衡
①:因为Eureka中已经集成了Ribbon,所以我们无需引入新的依赖。直接修改代码:
②:在RestTemplate的配置方法上添加@LoadBalanced注解:

@Bean
@LoadBalanced
public RestTemplate restTemplate() {
    return new RestTemplate();
}

③:修改调用方式,不再手动获取ip和端口,而是直接通过服务名称调用:

@GetMapping("{id}")
public User queryById(@PathVariable("id") Long id){
    String url = "http://user-service/user/" + id;
    User user = restTemplate.getForObject(url, User.class);
    return user;
}

3.修改负载均衡的规则
①:SpringBoot也帮我们提供了修改负载均衡规则的配置入口:

user-service:
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule

格式是:{服务名称}.ribbon.NFLoadBalancerRuleClassName,值就是IRule的实现类。

附加:
Ribbon默认是采用懒加载,即第一次访问时才会去创建负载均衡客户端。往往会出现超时。如果需要采用饥饿加载,即项目启动即创建,可以这样配置:

ribbon:
  eager-load:
    enabled: true
    clients: user-service

4.流程图
springCloud-day02_第1张图片
5.总结
①:Eureka中已经集成了Ribbon
②:加注解即可实现ribbon
③:ribbon的主要作用-实现负载均衡(集群中的服务用某种策略算法进行访问)
④:ribbon的负载均衡算法常用俩种(1.轮询 2.随机)
⑤:ribbon底层是用拦截器原理实现的
springCloud-day02_第2张图片

二:Hystrix(服务之间的调用保护)
1.雪崩问题
①:微服务中,服务间调用关系错综复杂,一个请求,可能需要调用1个或多个微服务接口才能实现,会形成非常复杂的调用链路,
如图,一次业务请求,需要调用A、P、H、I四个服务,这四个服务又可能调用其它服务。如果此时,某个服务出现异常:
springCloud-day02_第3张图片
②:微服务I发生异常,请求阻塞,用户不会得到响应,则tomcat的这个线程不会释放,于是越来越多的用户请求到来,越来越多的线程会阻塞。
③:服务器支持的线程和并发数有限,请求一直阻塞,会导致服务器资源耗尽,从而导致所有其它服务都不可用,形成雪崩效应。

2.线程隔离,服务降级
①:Hystrix为每个依赖服务调用分配一个小的线程池,如果线程池已满调用将被立即拒绝,默认不采用排队.加速失败判定时间。用户的请求将不再直接访问服务,而是通过线程池中的空闲线程来访问服务,如果线程池已满,或者请求超时,则会进行降级处理
springCloud-day02_第4张图片
②:服务降级虽然会导致请求失败,但是不会导致阻塞,而且最多会影响这个依赖服务对应的线程池中的资源,对其它服务没有响应。
③:触发Hystix服务降级的情况:
- 线程池已满
- 请求超时

④:实战演示( 在消费者端做线程隔离)
a.引入依赖:

 <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>

b.在启动类上添加注解:@EnableCircuitBreaker(这个组合注解包含了他们@SpringCloudApplication)

@SpringBootApplication
@EnableDiscoveryClient
@EnableCircuitBreaker
public class ConsumerApplication {
	// ...
}

c.编写降级逻辑

@GetMapping("{id}")
@HystrixCommand(fallbackMethod = "queryByIdFallBack")
public String queryById(@PathVariable("id") Long id){
    String url = "http://user-service/user/" + id;
    String user = restTemplate.getForObject(url, String.class);
    return user;
}

public String queryByIdFallBack(Long id){
    log.error("查询用户信息失败,id:{}", id);
    return "对不起,网络太拥挤了!";
}

⑤:总结
a.当调用提供方出现故障,或者时间超过1秒,就会走失败降级方法。
b.超时设置:

hystrix:
  command:
    default:
      execution.isolation.thread.timeoutInMilliseconds: 2000

3.服务熔断:
①:熔断状态有3个状态

  • Closed:关闭状态(断路器关闭),所有请求都正常访问。
  • Open:打开状态(断路器打开),所有请求都会被降级。Hystix会对请求情况计数,当一定时间内失败请求百分比达到阈值,则触发熔断,断路器会完全关闭。默认失败比例的阈值是50%,请求次数最少不低于20次。
  • Half Open:半开状态,open状态不是永久的,打开后会进入休眠时间(默认是5S)。随后断路器会自动进入半开状态。此时会释放1次请求通过,若这个请求是健康的,则会关闭断路器,否则继续保持打开,再次进行5秒休眠计时。
    springCloud-day02_第5张图片
    ②:服务熔断在原来注解的基础上已经实现了(线程隔离实现的注解),只是需要触发熔断的条件:
circuitBreaker.requestVolumeThreshold=10
circuitBreaker.sleepWindowInMilliseconds=10000
circuitBreaker.errorThresholdPercentage=50

解读:

  • requestVolumeThreshold:触发熔断的最小请求次数,默认20
  • errorThresholdPercentage:触发熔断的失败请求最小占比,默认50%
  • sleepWindowInMilliseconds:休眠时长,默认是5000毫秒

③:配置(可以在方法,可以在类上,可以全局配置文件中)

hystrix:
  command:
    default:
      execution.isolation.thread.timeoutInMilliseconds: 2000

4.总结:
①:hystrix作为一种保护雪崩的机制
②:有俩种保护形势
a.线程隔离,服务降级(触发:1.服务故障 2.超时1秒)
b.熔断(触发:访问20次,超过50%访问失败)
返回友好提示,不用等待,不影响其它服务。
③:用相同注解实现(引依赖,启动类加注解,实现类加注解)
④:配置参数(方法上,类上,配置文件中都可以)

三:Feign(底层集成ribbon和集成Hystix的服务间的调用)–重要
1.Feign的理解:可以把一个远程调用的请求,伪造的像一个本地方法调用一样

2.实现
①:导入依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

②:Feign的客户端

@FeignClient("user-service")
public interface UserClient {

    @GetMapping("/user/{id}")
    User queryById(@PathVariable("id") Long id);
}

③:开启Feign功能(我们在启动类上,添加注解,开启Feign功能)

@SpringCloudApplication
@EnableFeignClients // 开启Feign功能
public class ConsumerDemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(UserConsumerDemoApplication.class, args);
    }
}

3.对ribbon集成
①:配置

ribbon:
  ReadTimeout: 2000 # 读取超时时长
  ConnectTimeout: 1000 # 建立链接的超时时长
ribbon:
  ConnectTimeout: 500 # 连接超时时长
  ReadTimeout: 2000 # 数据通信超时时长
  MaxAutoRetries: 0 # 当前服务器的重试次数
  MaxAutoRetriesNextServer: 1 # 重试多少次服务
  OkToRetryOnAllOperations: false # 是否对所有的请求方式都重试

4.对hystrix集成
①:默认情况下是关闭的。我们需要通过下面的参数来开启:

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

②:首先,我们要定义一个类,实现刚才编写的UserFeignClient,作为fallback的处理类

@Component
public class UserClientFallback implements UserClient {
    @Override
    public User queryById(Long id) {
        User user = new User();
        user.setId(id);
        user.setName("用户查询出现异常!");
        return user;
    }
}

③:然后在UserFeignClient中,指定刚才编写的实现类

@FeignClient(value = "user-service", fallback = UserFeignClientFallback.class)
public interface UserClient {

    @GetMapping("/user/{id}")
    User queryById(@PathVariable("id") Long id);
}

5.请求压缩
①:Spring Cloud Feign 支持对请求和响应进行GZIP压缩,以减少通信过程中的性能损耗。通过下面的参数即可开启请求与响应的压缩功能:

feign:
  compression:
    request:
      enabled: true # 开启请求压缩
    response:
      enabled: true # 开启响应压缩

同时,我们也可以对请求的数据类型,以及触发压缩的大小下限进行设置:

feign:
  compression:
    request:
      enabled: true # 开启请求压缩
      mime-types: text/html,application/xml,application/json # 设置压缩的数据类型
      min-request-size: 2048 # 设置触发压缩的大小下限

6.日志级别
①:设置cn.itcast包下的日志级别都为debug

logging:
  level:
    cn.itcast: debug

②:编写配置类,定义日志级别

@Configuration
public class FeignConfig {
    @Bean
    Logger.Level feignLoggerLevel(){
        return Logger.Level.FULL;
    }
}

springCloud-day02_第6张图片

③:在FeignClient中指定配置类:

@FeignClient(value = "user-service", fallback = UserClientFallback.class, configuration = FeignConfig.class)
public interface UserClient {
    @GetMapping("/user/{id}")
    User queryById(@PathVariable("id") Long id);
}

7.总结
①:feign本质的功能微服务之间的调用(佯装)
②:feign集成ribbon(负载均衡-拉取eureka上的服务列表进行算法访问)
③:feign集成hystrix(微服务调用时的保护机制)
④:请求响应(压缩)
⑤:日志(打印)

你可能感兴趣的:(java,springcloud)