Spring Cloud(五) Feign

声明式服务调用 :Spring Cloud Feign

  Spring Cloud Feign基于Netflix Feign实现,整合了Spring Cloud Ribbon和Spring Cloud Hystrix,除此之外,还提供了一种声明式的Web服务端定义方式。

快速入门

  1. 引入POM依赖

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <java.version>1.8</java.version>
    <spring-cloud.version>Edgware.SR4</spring-cloud.version>
    </properties>

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

    </dependencies>
  2. 创建启动类,并添加EnableFeignClients注释开启Spring Cloud Feign支持

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    @SpringBootApplication
    @EnableFeignClients
    @EnableDiscoveryClient
    public class FeignconsumerApplication {

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

  3. 编写HelloService接口,通过FeignClient注解指定服务名来绑定服务,然后通过SpringMVC注解来绑定具体该服务提供的REST接口

    1
    2
    3
    4
    5
    @FeignClient("hello-service")
    public interface HelloService {
    @RequestMapping("/hello")
    String hello();
    }
  4. 编写Controller层,调用HelloService接口

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    @RestController
    public class HelloController {
    private final
    HelloService helloService;


    @Autowired
    public HelloController(HelloService helloService) {
    this.helloService = helloService;
    }

    @RequestMapping(value = "/feign-consumer", method = RequestMethod.GET)
    public String helloConsumer () {
    return helloService.hello();
    }
    }
  5. 修改配置文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    server:
    port: 1401
    spring:
    application:
    name: feign-consumer
    eureka:
    client:
    serviceUrl:
    defaultZone: http://localhost:1111/eureka/
  6. 通过浏览http://localhost:1111/可以查看注册中心新增了feign-consumer,通过访问http://localhost:1401/feign-consumer查看结果

参数绑定

  与SpringMVC不同,FeignClient中绑定参数必须通过value属性指定具体的参数名,不然会抛出IllegalStateException异常,value属性不能为空。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

@FeignClient("hello-service")
public interface HelloService {

@RequestMapping("/hello")
String hello();

@RequestMapping(value = "/hello1", method = RequestMethod.GET)
String hello(@RequestParam("name") String name);

@RequestMapping(value = "/hello2", method = RequestMethod.GET)
User hello(@RequestParam("name") String name, @RequestParam("age") Integer age);

@RequestMapping(value = "/hello3", method = RequestMethod.POST)
String hello(@RequestBody User user);
}

继承特性

  可以将项目中的几个子系统的共同部分抽象出来作为一个子项目,在maven中使用依赖减少代码量,但是同时会导致项目耦合度增加,需要严格按照面向对象的开闭原则,,否则可能出现牵一发而动全身的后果,增加不必要的维护工作量。

Ribbon配置

  Spring Cloud Feign的客户端负载均衡是通过Spring Cloud Ribbon实现的,因此可以通过直接配置Ribbon客户端来实现自定义各个服务端调用的参数。

Ribbon全局配置

1
2
3
4
5

ribbon:
ConnectTimeout: 500
ReadTimeout: 500

指定服务配置

  在使用Spring Cloud Feign的时候,针对各个服务客户端进行个性化配置的方式和Ribbon一致,都是\.ribbon.key=value,client是@FeignClient(value=”value”)中的value设置值。在我们使用@FeignClient(value=”value”)的同时创建了一个名为value的Ribbon客户端。

1
2
3
4
5
6
7
8

hello-service: #对value为hello-service的客户端进行设置
ribbon:
ReadTimeout: 2000
OkToRetryOnAllOperation: true
MaxAutoRetriesNextServer: 2
MaxAutoRetries: 1

重试机制

  在Spring Cloud Feign中,默认实现了请求的重试机制,上面的配置中我们已经做了相应配置

Hystrix设置

  默认情况下,Spring Cloud Feign会将所有Feign客户端的方法都封装到Hystrix命令中进行服务保护。

Hystrix全局配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14

hystrix:
command:
default:
# execution:
# timeout:
# enabled: false #关闭熔断功能
isolation:
thread:
timeoutInMilliseconds: 5000
#feign:
# hystrix:
# enabled: false #关闭Feign对Hystrix的支持

某个客户端关闭Hystrix

  需要通过使用@Scope(“properte”)注解为指定的客户端配置Feign.Builder实例。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

//配置类 DisableHystrixConfig.java
@Configuration
public class DisableHystrixConfig {
@Bean
@Scope("prototype")
public Feign.Builder feignBuilder() {
return Feign.builder();
}
}

//对某个服务关闭Hystrix
@FeignClient(value = "hello-service",configuration = DisableHystrixConfig.class)
public interface HelloService {
...
}