SpringCloud(5)Hystrix+Feign

1. Hystrix 熔断器

在这里插入图片描述

1.1 什么是Hystrix

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

  • 使用熔断器Hystrix为了优化项目。

  • 主页 https://github.com/Netflix/Hystrix/
    在这里插入图片描述

熔断器的工作机制:

在这里插入图片描述

正常工作的情况下,客户端请求调用服务API接口:

在这里插入图片描述

当有服务出现异常时,直接进行失败回滚, 处理:

在这里插入图片描述

  • 当服务繁忙时,如果服务出现异常,不是粗暴的直接报错,而是返回一个友好的提示,虽然拒绝了用户的访问,但是会返回一个结果。
    这就好比去买鱼,平常超市买鱼会额外赠送杀鱼的服务。等到逢年过节,超时繁忙时,可能就不提供杀鱼服务了,这就是服务的降级。
    系统特别繁忙时,一些次要服务暂时中断,优先保证主要服务的畅通,一切资源优先让给主要服务来使用,在双十一、618时,京东天猫都会采用这样的策略。

1.2 Hystrix 入门

  • 步骤一:修改pom,添加熔断器依赖

  • 步骤二:修改启动类,添加开启熔断器注解 @EnableHystrix

  • 步骤三:改造dao,远程调用添加 熔断器的备选方案,添加注解 + 备用方法

  • 步骤四:改变服务提供方法,添加线程sleep,0~~2000随机 (测试方便)

  • 步骤一:修改pom,添加熔断器依赖

<!--熔断器-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>

在这里插入图片描述

  • 步骤二:修改启动类,添加开启熔断器注解 @EnableHystrix
package com.czxy;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;

/**
 * Created by cjc.
 */
@SpringBootApplication
@EnableEurekaClient
@EnableHystrix      //开启熔断器
public class Client4Application {
    public static void main(String[] args) {
        SpringApplication.run(Client4Application.class,args);
    }
}

在这里插入图片描述

  • 步骤三:改造client,远程调用添加 熔断器的备选方案,添加注解 + 备用方法
package com.czxy.client;

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;

/**
 * Created by cjc.
 */
@Component
public class UserClient{
    @Resource
    private RestTemplate restTemplate;
    @HystrixCommand(fallbackMethod = "dataFallback")
    public ResponseEntity<String> data(){
        String url = "http://servic/test";
        return restTemplate.getForEntity(url,String.class);
    }

    /**
     * 熔断器超时处理方法
     * @return
     */
    public ResponseEntity<String> dataFallback(){
        return ResponseEntity.ok("临时数据");
    }
}
  • 步骤四:改变服务提供方法,添加线程sleep,0~~2000随机 (测试方便)
package com.czxy.controller;

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.util.Random;

/**
 * Created by cjc.
 */
@RestController
@RequestMapping("/test")
public class TestController {
    @GetMapping
    public ResponseEntity<String> test(HttpServletRequest request) throws Exception {
        //模拟延迟
        Thread.sleep(new Random().nextInt(2000));
        return ResponseEntity.ok("测试数据" + request.getServerPort());
    }
}

在这里插入图片描述

  • 步骤五:优化client,打印耗时时间
package com.czxy.client;

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;

/**
 * Created by liangtong.
 */
@Component
public class UserClient{
    @Resource
    private RestTemplate restTemplate;
    @HystrixCommand(fallbackMethod = "dataFallback")
    public ResponseEntity<String> data(){
        //1 记录开始时间
        long start = System.currentTimeMillis();
        //2 调用
        String url = "http://servic/test";
        ResponseEntity<String> entity = restTemplate.getForEntity(url, String.class);
        //3 记录结束时间
        long end = System.currentTimeMillis();
        //4 统计耗时
        System.out.println("耗时时间:" + (end - start));
        return entity;
    }

    /**
     * 熔断器超时处理方法
     * @return
     */
    public ResponseEntity<String> dataFallback(){
        return ResponseEntity.ok("临时数据");
    }
}

1.3 面试题:熔断器 + 重试机制

  • 面试题:如果项目中同时使用熔断器和Ribbon重试机制,谁先执行?

  • 如果时间不相同,超时时间小的,先执行。

  • 如果时间相同,只执行熔断器

  • 结论:如果两个都需要配置,重试机制的超时时间 小于 熔断器

2. 远程调用

2.1 回顾

  • HttpClient:Apache提供技术,更偏向底层,步骤完善,比较繁琐。
  • RestTemplate:由Spring提供,操作比较简单。

2.2 什么是Feign

  • Feign 是spring cloud全家桶一个成员,用于远程调用。
  • 特点:声明式、模板化HTTP客户端。使远程调用,在使用时,感觉像“本地方法”

2.3 Feign 入门

  • 步骤一:修改pom文件,添加Feign依赖

  • 步骤二:修改启动类,添加开启Feign注解

  • 步骤三:编写Feign接口,完成远程调用,取代client层

  • 步骤四:修改controller, 将调用client修改成feign

  • 步骤一:修改pom文件,添加Feign依赖

<!--远程调用Feign-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
  • 步骤二:修改启动类,添加开启Feign注解
package com.czxy;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.cloud.openfeign.EnableFeignClients;

/**
 * Created by cjc.
 */
@SpringBootApplication
@EnableEurekaClient
@EnableHystrix      //开启熔断器
@EnableFeignClients //开启Feign客户端
public class Client4Application {
    public static void main(String[] args) {
        SpringApplication.run(Client4Application.class,args);
    }
}
  • 步骤三:编写Feign接口,完成远程调用,取代client层
//@FeignClient 解析
@FeignClient(value="服务名",path="controller前缀")
public interface 接口名{
    //与controller方法一致
}

在这里插入图片描述

package com.czxy.feign;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;

import javax.servlet.http.HttpServletRequest;

/**
 * Created by cjc.
 */
@FeignClient(value="servic",path="/test")
public interface UserFeifn{

    @GetMapping
    public ResponseEntity<String> test() ;
}
  • 步骤四:修改controller, 将调用client修改成feign
package com.czxy.controller;

import com.czxy.dao.DataDao;
import com.czxy.feign.DataFeign;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

/**
 * Created by cjc.
 */
@RestController
@RequestMapping("/data")
public class DataController {
    @Resource
    //private UserClient userClient;
    private DataFeign dataFeign;

    @GetMapping
    public ResponseEntity<String> data(){
        //return dataDao.data();
        return dataFeign.test();
    }
}
发布了31 篇原创文章 · 获赞 11 · 访问量 833

猜你喜欢

转载自blog.csdn.net/Eros1onz/article/details/103503510
今日推荐