4

Spring Cloud之Finchley版学习(十一)-Feign常见问题总结

 3 years ago
source link: https://www.wencst.com/archives/1376
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

本文总结Feign常见问题及解决方案。

一、FeignClient接口如使用@PathVariable ,必须指定value属性

代码示例:

@FeignClient("microservice-provider-user")
public interface UserFeignClient {
  @RequestMapping(value = "/simple/{id}", method = RequestMethod.GET)
  public User findById(@PathVariable("id") Long id);
  ...
}@FeignClient("microservice-provider-user")

其中的@PathVariable("id") 中的”id”,也就是value属性,必须指定,不能省略。

二、构造多参数请求

详见:如何使用Feign构造多参数的请求

三、如需产生Hystrix Stream监控信息,需要做一些额外操作

Feign本身已经整合了Hystrix,可直接使用@FeignClient(value = "microservice-provider-user", fallback = XXX.class) 来指定fallback类,fallback类继承@FeignClient所标注的接口即可。

但是假设如需使用Hystrix Stream进行监控,默认情况下,访问http://IP:PORT/actuator/hystrix.stream 是会返回404,这是因为Feign虽然整合了Hystrix,但并没有整合Hystrix的监控。如何添加监控支持呢?需要以下几步:

第一步:添加依赖,示例:

<!-- 整合hystrix,其实feign中自带了hystrix,引入该依赖主要是为了使用其中的hystrix-metrics-event-stream,用于dashboard -->
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>

第二步:在启动类上添加@EnableCircuitBreaker 注解,示例:

@SpringBootApplication
@EnableFeignClients
@EnableDiscoveryClient
@EnableCircuitBreaker
public class MovieFeignHystrixApplication {
  public static void main(String[] args) {
    SpringApplication.run(MovieFeignHystrixApplication.class, args);
  }
}

第三步:在application.yml中添加如下内容,暴露hystrix.stream端点:

management:
  endpoints:
    web:
      exposure:
        include: 'hystrix.stream'

这样,访问任意Feign Client接口的API后,再访问http://IP:PORT/actuator/hystrix.stream ,就会展示一大堆Hystrix监控数据了。

四、Java代码自定义Feign Client的注意点与坑

代码示例:

@FeignClient(name = "microservice-provider-user", configuration = UserFeignConfig.class)
public interface UserFeignClient {
  @GetMapping("/users/{id}")
  User findById(@PathVariable("id") Long id);
}
/**
 * 该Feign Client的配置类,注意:
 * 1. 该类可以独立出去;
 * 2. 该类上也可添加@Configuration声明是一个配置类;
 * 配置类上也可添加@Configuration注解,声明这是一个配置类;
 * 但此时千万别将该放置在主应用程序上下文@ComponentScan所扫描的包中,
 * 否则,该配置将会被所有Feign Client共享,无法实现细粒度配置!
 * 个人建议:像我一样,不加@Configuration注解
 *
 * @author zhouli
 */
class UserFeignConfig {
  @Bean
  public Logger.Level logger() {
    return Logger.Level.FULL;
  }
}
  • 配置类上也可添加@Configuraiton 注解,声明这是一个配置类;但此时千万别将该放置在主应用程序上下文@ComponentScan 所扫描的包中,否则,该配置将会被所有Feign Client共享(相当于变成了通用配置,其实本质还是Spring父子上下文扫描包重叠导致的问题),无法实现细粒度配置!
  • 个人建议:像我一样,不加@Configuration注解,省得进坑。
  • 最佳实践:尽量用配置属性自定义Feign的配置!!!详见:跟我学Spring Cloud(Finchley版)-10-Feign深入

五、首次请求失败

详见:Spring Cloud中,如何解决Feign/Ribbon第一次请求失败的问题?

六、@FeignClient 注解属性

@FeignClient(name = "microservice-provider-user")

在早期的Spring Cloud版本中,无需提供name属性,从Brixton版开始,@FeignClient必须提供name属性,否则应用将无法正常启动!

另外,name、url等属性支持占位符。例如:

@FeignClient(name = "${feign.name}", url = "${feign.url}")

七、类级别的@RequestMapping会被Spring MVC加载

@RequestMapping("/users")
@FeignClient(name = "microservice-user")
public class TestFeignClient {
    // ...
}

类上的@RequestMapping 注解也会被Spring MVC加载。该问题现已经被解决,早期的版本有两种解决方案:

方案1:不在类上加@RequestMapping 注解;

方案2:添加如下代码:

@Configuration
@ConditionalOnClass({ Feign.class })
public class FeignMappingDefaultConfiguration {
    @Bean
    public WebMvcRegistrations feignWebRegistrations() {
        return new WebMvcRegistrationsAdapter() {
            @Override
            public RequestMappingHandlerMapping getRequestMappingHandlerMapping() {
                return new FeignFilterRequestMappingHandlerMapping();
            }
        };
    }
    private static class FeignFilterRequestMappingHandlerMapping extends RequestMappingHandlerMapping {
        @Override
        protected boolean isHandler(Class<?> beanType) {
            return super.isHandler(beanType) && !beanType.isInterface();
        }
    }
}

相关Issue:https://github.com/spring-cloud/spring-cloud-netflix/issues/466


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK