Spring Cloud系列(三):Feign

简介

Feign是一个声明式的http客户端,它的目的和作用就是让 Java HTTP 客户端编写和使用更方便。 Feign GitHub 项目地址

Feign的关注点在于简化开发人员使用工具包的复杂度,以最少的代码编写代码从而提供java http客服端。通过定制解码器和异常处理,开发人员可以任意编写文本化的HTTP API。

一般来说,Feign(关注http请求) + Ribbon(关注负载均衡等)是较好的组合。

使用Feign访问服务端API

如果要使用的话,创建一个接口然后加上注解就行,它还整合Ribbon和Eureka,同时还支持SpringMVC的一些注解。

第一步添加依赖:

<!-- feign client -->
<dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-feign</artifactId>
</dependency>

启动类注解:

@EnableFeignClients

客户端接口:

/**
 * Feign
 *
 * @author: uncle
 * @apdateTime: 2017-12-12 19:28
 */
@FeignClient("service-user") // 服务端的 service Id
public interface UserFeignClient {
    /**
     * 请求的服务端的API
     *
     * @param id
     * @return
     */
    @GetMapping("/user/{id}")
    User findById(@PathVariable(value = "id") Long id);
}

Feign的一些默认配置:

  • 解码器:Decoder : ResponseEntityDecoder
  • 编码器:Encoder : SpringEncoder
  • 日志:Logger : Slf4jLogger
  • 契约:Contract : SpringMvcContract(Contract组件就是用于检查request相关的约定,在Contract内部提供了抽象类BaseContract(模板方法),它主要检查Target的相关信息及其类注解、方法注解和参数注解等)
  • Feign.Builder : HystrixFeign.Builder

自定义配置

跟Ribbon那很像,第一步还是写好配置类:

/**
 * 他这跟Ribbon的注意事项相同,参考Ribbon即可
 * @author: uncle
 * @apdateTime: 2017-12-14 09:50
 */
@Configuration
public class CustomConfig {

    @Bean
    public Contract feignContractg() {
        return new feign.Contract.Default();
    }
}

在FeignClient注解上,指定自己的配置类:

/**
 * Feign
 *      这个注解创建一个ApplicationContext,也就是Spring的子容器
 * 这里就是此客户端要访问的服务端的实例名称和Controller路径
 * 
 * @author: uncle
 * @apdateTime: 2017-12-12 19:28
 */
@FeignClient(name = "service-user", configuration = CustomConfig.class)
public interface UserFeignClient {
    /**
     * 请求的服务端的API
     *
     * @param id
     * @return
     */
    @RequestLine("GET /user/{id}") // 这里要使用此注解
    User findById(@Param(value = "id") Long id); // 并且这里不再是@PathVariable
}

日志文件

A logger is created for each Feign client created. By default the name of the logger is the full class name of the interface used to create the Feign client. Feign logging only responds to the DEBUG level.

注意看,是Feign client,也就是客户端的完整的全限定名。假如要添加日志的话,看下面:

logging:
  level:
    net.imain.cloud.feign.UserFeignClient: DEBUG

如果要自定义日志输出的级别,官方也提供了一些案例(这段代码必须加载配置文件CustomConfig里,否则日志不会生效):

@Bean
Logger.Level feignLoggerLevel() {
    // NONE BASIC HEADERS FULL
    return Logger.Level.FULL;
}

效果如下

psb.jpg

bug

如果出现了一个timeout的异常,说明hystrix的超时时间没有设置好,可以进行如下配置

hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds: 5000

或者

hystrix.command.default.execution.timeout.enabled: false

或者干脆禁用feign的hystrix:

feign.hystrix.enabled: false

使用Feign根据实例ID获取实例信息

/**
 * @author: uncle
 * @apdateTime: 2017-12-09 18:41
 */
@RestController
@RequestMapping(value = "/movie/")
public class MovieController {

    @Autowired
    private UserFeignClient userFeignClient;

    @Autowired
    private GeneralFeignClient generalFeignClient; // 重点

    @GetMapping(value = "{id}")
    public User findById(@PathVariable(value = "id") Long id) {
        // 消费另外一个微服务的API
        return userFeignClient.findById(id);
    }

    // 重点
    @GetMapping("/feign/{serviceName}")
    public String findEurekaByServiceName(@PathVariable(value = "serviceName") String serviceName) {
        return generalFeignClient.findEurekaByServiceName(serviceName);
    }
}
/**
 * 根据实例名称获取实例信息
 *
 * @author: uncle
 * @apdateTime: 2017-12-14 10:21
 */
// 请求的URL是Eureka,当有这个URL的时候,name这是一个简单的名字,但是如果没有URL的话,name则是service id
@FeignClient(name = "xxx", url = "http://localhost:8761/", configuration = BasicAuthConfig.class)
public interface GeneralFeignClient {
    @RequestMapping("/eureka/apps/{serviceName}")
    String findEurekaByServiceName(@PathVariable("serviceName") String serviceName);
}
/**
 * 权限认证
 *
 * @author: uncle
 * @apdateTime: 2017-12-14 10:38
 */
@Configuration
public class BasicAuthConfig {
    @Bean
    public BasicAuthRequestInterceptor basicAuthRequestInterceptor() {
        return new BasicAuthRequestInterceptor("user", "password");
    }
}

推荐文章

深入Feign源码

Feign介绍

Last modification:January 11th, 2018 at 10:50 am
If you think my article is useful to you, please feel free to appreciate

Leave a Comment