专栏首页晏霖Spring Cloud Feign 中使用Hystrix进行请求降级和快速失败

Spring Cloud Feign 中使用Hystrix进行请求降级和快速失败

前言

微服务中经常会用到熔断器来增强服务依赖的稳定性,他可以在网络连接缓慢,资源繁忙,暂时不可用,服务脱机等情况中进行服务的快速失败,并可自我恢复,以避免请求线程的堆积造成大量资源的浪费。

相信读者看这篇文章的目的都是解决实际问题,并不是来看我分析源码的,如果对源码感兴趣的我推荐《重新定义》,所以我们直接上干货,下面我们就简单的利用Feign中集成的Hystrix进行快速失败和请求降级处理。

正文

首先准备一个父项目,里面只有各个服务所需的依赖包,下面就是父项目的pom,可以看到我这次演练的项目有三个,分别是eureka-server,consumer-service,provider-service

一、父工程

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.3.RELEASE</version>
    </parent>

    <modelVersion>4.0.0</modelVersion>
    <groupId>cn.springcloud.book</groupId>
    <artifactId>ch6-2</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>pom</packaging>

    <modules>
        <module>ch6-2-eureka-server</module>
        <module>ch6-2-consumer-service</module>
        <module>ch6-2-provider-service</module>
    </modules>

    <!-- 管理依赖 -->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Finchley.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>


    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>



    <!--注意: 这里必须要添加, 否者各种依赖有问题 -->
    <repositories>
        <repository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/libs-milestone</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
    </repositories>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

二、下面创建eureka-server服务 下面依次是pom,yml,和启动类的代码,这里不做解释了,前几个博客已经介绍过类似的内容。

<parent>
        <groupId>cn.springcloud.book</groupId>
        <artifactId>ch6-2</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <artifactId>ch6-2-eureka-server</artifactId>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {

    public static void main(String[] args) {
        SpringApplication.run(EurekaServerApplication.class, args);
    }
}

三、接下来创建一个被feign调用的服务:provider-service。 这里很简单,就是定一个请求地址,用来映射到feign接口上的URl。

下面代码依次是provider-service中的controller、启动类、pom、yml

这里其实重点就是利用了spring-cloud-starter-netflix-hystrix,别的都没什么可解释的。

@RestController
public class TestController {

    @RequestMapping(value = "/getUser",method = RequestMethod.GET)
    public String getUser(@RequestParam("username") String username){
        return "This is real user";
    }
------------------------------------------
@SpringBootApplication
@EnableDiscoveryClient
public class ProviderApplication {

    public static void main(String[] args) {
        SpringApplication.run(ProviderApplication.class, args);
    }
}
------------------------------------------
<parent>
    <groupId>cn.springcloud.book</groupId>
    <artifactId>ch6-2</artifactId>
    <version>0.0.1-SNAPSHOT</version>
  </parent>

  <artifactId>ch6-2-provider-service</artifactId>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java.version>1.8</java.version>
    </properties>

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

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

四、最后创建一个consumer-service工程

这里的代码相对上两个服务要多一些,不过我会按照一定的顺序给大家展示,

首先是controller、Feign接口,Feign的快速返回/降级方法、pom、yml,一共五块代码

@RestController
public class TestController {

    @Autowired
    private IUserService userService;

    @RequestMapping(value = "/getUser",method = RequestMethod.GET)
    public String getUser(@RequestParam("username") String username) throws Exception{
        return userService.getUser(username);
    }

@FeignClient(name = "sc-provider-service", fallback = UserServiceFallback.class)
public interface IUserService {

    @RequestMapping(value = "/getUser",method = RequestMethod.GET)
    String getUser(@RequestParam("username") String username);

}

@Component
public class UserServiceFallback implements IUserService{
    /**
      * 出错则调用该方法返回友好错误
      * @param username
      * @return
      */
    public String getUser(String username){
        return "The user does not exist in this system, please confirm username";
    }
}

<parent>
    <groupId>cn.springcloud.book</groupId>
    <artifactId>ch6-2</artifactId>
    <version>0.0.1-SNAPSHOT</version>
  </parent>

  <artifactId>ch6-2-consumer-service</artifactId>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

server:
  port: 8888
spring:
  application:
    name: sc-consumer-service
eureka:
  client:
    serviceUrl:
      defaultZone: http://${eureka.host:127.0.0.1}:${eureka.port:8761}/eureka/
  instance:
    prefer-ip-address: true
feign:
  hystrix:
    enabled: true

好了,五块代码粘贴完毕,下面是对上面代码的解释,

首先controller是我们对外暴露的请求入口,调用了当前服务的Feign接口,

重点是这句话

@FeignClient(name = "sc-provider-service", fallback = UserServiceFallback.class),

name参数代表请求映射的服务spring. application.name,

fallback参数指定的是一个类,这个类必须要实现当前的Feign接口才可以,用于feign调用sc-provider-service服务时失败的快速返回类。然后就是UserServiceFallback类一定注入spring容器。

同样,这个工程也需要spring-cloud-starter-netflix-hystrix 依赖,另外这里我用了openfeign你可以理解为feign的升级版。

还有一点需要注意的是高版本中feign的hystrix是默认关闭的,所有我们要手动打开

三个服务分别启动,首先eureka-service先启动。

我们可以看到消费者工程和生产者工程分别注册上了eureka,我们访问http://localhost:8888/getUser?username=1,当然是访问不到的了,但是返回

我们知道这句话是我fallback参数指定类的方法返回的,

这样一个简单的利用feign 集成的熔断器实现快速返回的例子。

注:对本文有异议或不明白的地方微信探讨,wx:15524579896

本文分享自微信公众号 - 晏霖(yanlin199507)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-01-11

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Spring Cloud Gateway基于内置过滤工厂实现限流

    本文使用 gateway 内置的过滤工厂 -RequestRateLimiter 实现限流的。

    胖虎
  • Spring Boot2.0 使用Lettuce 连接Redis

    上一文我们介绍了响应式编程/反应式编程到底是什么,通过案例连接了Redis,但是我们的操作都是返回 Mono 或者 Flux,那么很多小伙伴不习惯这种方式,所以...

    胖虎
  • Spring Cloud Zuul通过zuul-ratelimit实现限流

    本篇文章主要讲解 zuul-ratelimit 组件如何来作为服务限流的。并且只讲解他的默认存储类型,因为我想后期能力允许,我会单独讲解利用 redis 来做限...

    胖虎
  • 微服务综合案例-03-其他服务的创建

      上篇文章我们详细的介绍了product服务的创建,因为其他几个服务的创建过程是相似的,所以其他几个服务我们就快速创建了。

    用户4919348
  • springBoot2整合pagehelper的爬坑经历

    1、正确的pom配置,重点注意spring-boot2.2.4.RELEASE和pagehelper1.2.12的版本搭配

    用户5640963
  • Java——Spring整合Mybatis(IDEA版)

    该文主要教大家如何整合spring和mybatis,整合完成效果,可以从数据库中查询出学生信息:

    说故事的五公子
  • 实战spring自定义属性(schema)

    spring启动后,dubbo的本地运行时环境就会获取到这些信息,根据这些信息完成注册服务,今天我们实战的内容就是开发一个类似的自定义属性,然后在spring项...

    程序员欣宸
  • 学习sharding-jdbc 分库分表扩展框架

    https://gitee.com/a247292980/sharding-jdbc

    ydymz
  • ssm整合的pom.xml依赖

    用户2409797
  • Maven构建的Spring项目需要哪些依赖?

    用户2409797

扫码关注云+社区

领取腾讯云代金券