SpringCloud微服务学习(三)——Hystrix、Feign - Go语言中文社区

SpringCloud微服务学习(三)——Hystrix、Feign


四、Hystrix

1.简述

Hystrix是Netflix开源的一个延迟和容错库,用于隔离访问远程服务、第三方库,防止出现级联失败,是一种保护机制。

2.雪崩问题

微服务中,服务之间调用关系错综复杂,一个请求,可能需要调用多个微服务接口才能实现,会形成非常复杂的调用链路。
在这里插入图片描述
如图所示,一个微服务在调用多个微服务的时候,这些服务又可能返回参数影响其他微服务的运行,但如果我们有一个微服务出现了问题,那么就会越来越阻塞,导致tomcat无法运行,从一个微服务导致更多的微服务出现异常,直至瘫痪。
在这里插入图片描述
而Hystrix解决雪崩问题的方法有两个:
1.线程隔断
2.服务熔断

3.线程隔离,服务降级

<1>简介

在这里插入图片描述
当我们使用了Hystrix之后会给每一个服务分配线程池,让每一个微服务占有的线程是有限的,也就不会占用到过量的服务器性能,令出错误的时候让服务器瘫痪。但是这个作用仅仅是不让服务器瘫痪,服务本身还是导致了阻塞,为了能让我们的程序正常的运行,所以我们就要让出错的服务进行降级,让程序正常运行,而具体方式就是设置一个相应时间,由于阻塞导致无法进行相应,这时,我们就进行服务降级。

<2>程序实现

要在服务的消费方进行降级处理,防止别人雪崩引起自己雪崩
首先先引入依赖

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

在启动类开启熔断机制

@EnableCircuitBreaker//熔断

插句话,我们已经在启动类放了很多个注解了在这里插入图片描述
其实我们是可以用一个新的注解将这三个注解进行取代的,就是@SpringCloudApplication

然后对我们的某个方法开启容错机制

	@GetMapping("{id}")
    @HystrixCommand(fallbackMethod="queryByIdFallBack")//降级
    public String queryById(@PathVariable("id") Long id) {
        //容错处理,如果此方法没有问题,就执行,如果有问题,就跳转到fallbackMethod所描述的方法内,但要求两个方法返回值一致
        String url = "http://user-Service/user/id";
        String user = restTemplate.getForObject(url, String.class);
        return user;
    }

    public String queryByIdFallback(Long id) {
        return "Sorry";
    }

最后在服务的使用方进行一下模拟超时

package itcast.user.service;

import itcast.user.POJO.User;
import itcast.user.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class UserService {

    @Autowired
    private UserMapper userMapper;

    public User queryById(Long id) {
        try {
            Thread.sleep(2000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return userMapper.selectByPrimaryKey(id);
    }

}

然后重新运行
在这里插入图片描述
我们发现会触发。
以上我们展示的仅仅是单独给某一个方法实现降级,其实也是可以给一个大类统一进行降级或者线程隔离的。
直接在类上贴上一个标签:
在这里插入图片描述
然后在想要实现线程隔离或者降级的方法上直接标记上

	@HystrixCommand
    @GetMapping("{id}")
    public String queryById(@PathVariable("id") Long id) {
        //容错处理,如果此方法没有问题,就执行,如果有问题,就跳转到fallbackMethod所描述的方法内,但要求两个方法返回值一致
        String url = "http://user-Service/user/id";
        String user = restTemplate.getForObject(url, String.class);
        return user;

不过我们如果在类上进行标记,就不能在补救的方法上填入参数了,因为是一个通用的fallBack

直接这样写即可

public String queryByIdFallback) {
        return "Sorry";
    }

然后重新运行
在这里插入图片描述
当然,如果我们想要设置一些属性也是可以的。内部封装了一些相关的方法,就像刚才我们手动设置的超时时间,也可以在这里手动更快捷的设置

@HystrixCommand(commandProperties = {
        @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "3000")
    })
    @GetMapping("{id}")
    public String queryById(@PathVariable("id") Long id) {
        //容错处理,如果此方法没有问题,就执行,如果有问题,就跳转到fallbackMethod所描述的方法内,但要求两个方法返回值一致
        String url = "http://user-Service/user/id";
        String user = restTemplate.getForObject(url, String.class);
        return user;

4.服务熔断

<1>熔断原理

在这里插入图片描述
在这里插入图片描述

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

<2>程序实现

以Key-Value的形式来实现熔断

    @HystrixCommand(commandProperties = {
        @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold",value = "10"),//设置最大重启情况,超过5次认定失败,10次就熔断
        @HystrixProperty(name = "circuitBreaker.sleepWindowInMillisecond",value = "10000"),//设置睡觉10秒不响应就会熔断
        @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage",value = "60")//错误超过60%就会失败
    })
    @GetMapping("{id}")
    public String queryById(@PathVariable("id") Long id) {
        if (id % 2 == 0) {
            throw new RuntimeException("自动报错");
        }
        //容错处理,如果此方法没有问题,就执行,如果有问题,就跳转到fallbackMethod所描述的方法内,但要求两个方法返回值一致
        String url = "http://user-Service/user/id";
        String user = restTemplate.getForObject(url, String.class);
        return user;


        //根据服务id来获取实例
//        List<ServiceInstance> list = discoveryClient.getInstances("user-Service");
//        ServiceInstance choose = ribbonLoadBalancerClient.choose("user-Service");
        //从实例中取出ip地址和port
//        ServiceInstance serviceInstance = list.get(0);
//        String url = "http://" + serviceInstance.getHost() + ":" + serviceInstance.getPort() + "/user/" + id;

//        上面缩写的ribbon是属于轮询,一个一个去试,现在我们拦截到js,去判断

//        String url = "http://user-Service/user/"+id;
//        User user = restTemplate.getForObject(url, User.class);
//        return user;
    }

    public String queryByIdFallback() {
        return "Sorry";
    }

然后重新运行程序
会发现频繁重启一个网站之后,会提示无法继续访问。

五、Feign

1.简介

在前面的学习中,我们使用了Ribbon的负载均衡功能,大大简化了远程调用时的代码:

String baseUrl = "http://user-service/user/";
User user = this.restTemplate.getForObject(baseUrl + id, User.class)

而Feign可以把Rest的请求进行隐藏,伪装成类似SpringMVC的Controller一样。你不用再自己拼接url,拼接参数等等操作,一切都交给Feign去做。
在这里插入图片描述

2.程序设计

<1>Feign的远程调用

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

然后在consumer的启动类开启Feign远程调用的注解@EnableFeignClients
接下来创建Feign客户端:

package itcast.consumer.client;

import itcast.consumer.POJO.User;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

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

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

}

然后调用我们Feign客户端,完成简化

@GetMapping("{id}")
public User queryById(@PathVariable("id") Long id) {
        return userClient.queryById(id);
}

来到启动类删除之前的底层,完成优化

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

另外,Feign内置了一个超时时常,我们也可以在配置文件中对其进行设置

ribbon:
  ConnectionTimeOut: 500  #连接超时时常
  ReadTimeOut: 2000  #读取超时时常

<2>Feign的熔断机制

首先先说一下,Hystrix默认Feign在中默认是关闭的,我们需要在配置文件中进行手动开启

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

然后写一个熔断接口

package itcast.consumer.client;

import itcast.consumer.POJO.User;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

@FeignClient(value = "user-Service",fallback = UserClientImpl.class)//标明熔断接口的实现类
public interface UserClient {//熔断接口

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

}

实现熔断的业务逻辑,写出异常出现的时候所产生的现象。

package itcast.consumer.client;

import itcast.consumer.POJO.User;
import org.springframework.stereotype.Component;

@Component//注入到容器
public class UserClientImpl implements UserClient {//熔断的业务逻辑
    @Override
    public User queryById(Long id) {
        User user = new User();
        user.setName("未知错误!");
        return user;
    }
}

重新进行测试
在这里插入图片描述
由于我们设置的超时,所以进行了报错
测试成功

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/qq_41936805/article/details/89060268
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢