SpringCloud学习第五篇:Hystrix熔断器(Greenwich-SR1版本)

一、Hystrix介绍

  Hystrix是一个延迟容错库。在分布式环境中,许多服务依赖项中的一些不可避免地会失败。如果这时候有大量的请求请求这个故障的服务,由于服务之间的依赖关系,故障会进行蔓延,这时候会导致调用服务自身也出现不可用的情况,使用Hystrix可以解决这个问题。当某个服务发生故障(类似用电器发生短路)之后,通过断路器的故障监控(类似熔断保险丝),向调用方返回一个错误响应,而不是长时间的等待。这样就不会使得线程因调用故障服务被长时间占用不释放,避免了故障在分布式系统中的蔓延。

二、实现服务提供方短路

2.1Api工程搭建

  • maven
 <parent>
        <groupId>com.yk</groupId>
        <artifactId>cloud-parent</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <artifactId>springcloud-api</artifactId>
  • Entity
@Data
public class User {

    /**
     * ID
     */
    private Long id;

    /**
     * 用户名称
     */
    private String name;

}
  • Service
public interface UserService {
    /**
     * 保存用户
     * @param user
     */
    boolean saveUser(User user);
    /**
     * 查询所有的用户列表
     */
    List<User> findAll();
}

2.2服务提供方工程搭建

  • Maven
 <parent>
        <groupId>com.yk</groupId>
        <artifactId>cloud-parent</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <artifactId>springcloud-api-provider</artifactId>
    <dependencies>
        <!-- 依赖 API -->
        <dependency>
            <groupId>com.yk</groupId>
            <artifactId>springcloud-api</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
        <!-- 依赖 Spring Cloud Netflix Hystrix -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>
    </dependencies>
  • application.properties配置
## 用户服务提供方应用信息
spring.application.name = spring-cloud-api-provider

## 服务端口
server.port = 801
  • 启动入口
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
@EnableHystrix  //服务端实现
public class ApiProviderApplication {
    public static void main(String[] args) {
        SpringApplication.run(ApiProviderApplication.class, args);
    }

}
  • 服务实现类
@Service
public class UserServiceImpl implements UserService {

    private Map<Long, User> repository = new ConcurrentHashMap<>();
    @Override
    public boolean saveUser(User user) {
        return repository.put(user.getId(), user) == null;
    }

    @Override
    public List<User> findAll() {
        return new ArrayList(repository.values());
    }
}
  • Controller
@RestController
public class UserController {
    @Autowired
    private UserService userService;
    private final static Random random = new Random();
    @GetMapping("/user/save")
    public boolean getUser(){
        User user=new User();
        user.setId(1L);
        user.setName("张三");
        return userService.saveUser(user);
    }
    /**
     * 获取所有用户列表
     * @return
     */
    @HystrixCommand(
        // Command 配置,设置操作时间为 100 毫秒
        commandProperties = {@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "100")},
            // 设置 fallback 方法
        fallbackMethod = "fallbackForGetUsers" 
    )
    @GetMapping("/user/list")
    public Collection<User> getUsers() throws InterruptedException {
        // 通过休眠来模拟执行时间
        long executeTime = random.nextInt(200);
        System.out.println("Execute Time : " + executeTime + " ms");
        Thread.sleep(executeTime);
        return userService.findAll();
    }
    /**
     * 超过100毫秒就返回空集合
     * @return
     */
    public Collection<User> fallbackForGetUsers() {
        return Collections.emptyList();
    }
}

2.3Demo演示
先调用/user/save增加一个用户
在这里插入图片描述
在这里插入图片描述

三、实现服务调用方短路

服务调用方工程

  • Maven
 <parent>
        <groupId>com.yk</groupId>
        <artifactId>cloud-parent</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <artifactId>springcloud-ribbon-client</artifactId>
    <dependencies>
        <!-- 依赖API -->
        <dependency>
            <groupId>com.yk</groupId>
            <artifactId>springcloud-api</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
        <!-- 依赖 Ribbon -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
        </dependency>
        <!-- 依赖 Spring Cloud Netflix Hystrix -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>
    </dependencies>

  • application.properties
## 用户 Ribbon 客户端应用
spring.application.name = spring-cloud-api-client
## 服务端口
server.port = 802

## 提供方服务名称
provider.service.name = spring-cloud-api-provider
## 提供方服务主机
provider.service.host = 192.168.0.102
## 提供方服务端口
provider.service.port = 801

## 定义 spring-cloud-ribbon-provider Ribbon 的服务器地址
## 为 RibbonLoadBalancerClient 提供服务列表
spring-cloud-api-provider.ribbon.listOfServers = \
  http://${provider.service.host}:${provider.service.port}

  • 入口
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
@RibbonClient("spring-cloud-api-provider") // 指定目标应用名称
@EnableCircuitBreaker // 使用客户端短路
public class ClientApplication {

    public static void main(String[] args) {
        SpringApplication.run(ClientApplication.class, args);
    }
    /**
     * 负载均衡
     */
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

  • 使用编程方式实现服务短路
public class UserHystrixCommand extends HystrixCommand<Collection> {
    private final String providerServiceName;
    private final RestTemplate restTemplate;

    public UserHystrixCommand(String providerServiceName, RestTemplate restTemplate) {
        super(//组名称
                HystrixCommandGroupKey.Factory.asKey(
                "spring-cloud-api-client"),
                //超时时间
                100);
        this.providerServiceName = providerServiceName;
        this.restTemplate = restTemplate;
    }
    /**
     *  具体实现
     */
    @Override
    protected Collection run() throws Exception {
        return restTemplate.getForObject("http://" + providerServiceName + "/user/list", Collection.class);
    }
    /**
     * Fallback 实现 返回空集合
     */
    protected Collection getFallback() {
        return Collections.emptyList();
    }
}

  • Controller
package com.yk.client.controller;

import com.yk.api.entity.User;
import com.yk.client.hystrix.UserRibbonClientHystrixCommand;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.io.IOException;
import java.util.Collection;

@RestController
public class UserController {

    @Value("${provider.service.name}")
    private String providerServiceName;

    @Autowired
    private RestTemplate restTemplate;
    /**

     * 调用 /spring-cloud-api-provider服务的 /user/list REST 接口,并且直接返回内容
     * 增加 短路功能
     */
    @GetMapping("/user/list")
    public Collection<User> getUsersList() {
        return new UserRibbonClientHystrixCommand(providerServiceName, restTemplate).execute();
    }
}

  • Demo演示
    先打断点,然后在释放断点就可以看到服务调用方的短路效果了
    在这里插入图片描述

猜你喜欢

转载自www.cnblogs.com/yangk1996/p/12663510.html