美文网首页SpringCloudspring cloudFeign
Feign正确的使用姿势和性能优化注意事项

Feign正确的使用姿势和性能优化注意事项

作者: norai | 来源:发表于2016-09-11 23:30 被阅读46441次
P60724-115835.jpg

1. feign自定义Configuration和root 容器有效隔离。

  • 用@Configuration注解
  • 不能在主@ComponentScan (or @SpringBootApplication)范围内,从其包名上分离
  • 注意避免包扫描重叠,最好的方法是明确的指定包名

2. Spring Cloud Netflix 提供了默认的Bean类型:

  • Decoder feignDecoder: ResponseEntityDecoder (which wraps a SpringDecoder)
  • Encoder feignEncoder: SpringEncoder
  • Logger feignLogger: Slf4jLogger
  • Contract feignContract: SpringMvcContract
  • Feign.Builder feignBuilder: HystrixFeign.Builder

3. Spring Cloud Netflix没有提供默认值,但仍然可以在feign上下文配置中创建:

  • Logger.Level
  • Retryer
  • ErrorDecoder
  • Request.Options
  • Collection<RequestInterceptor>

4. 自定义feign的消息编码解码器:

不要在如下代码中getObject方法内new 对象,外部会频繁调用getObject方法。

    ObjectFactory<HttpMessageConverters> messageConvertersObjectFactory = new ObjectFactory<HttpMessageConverters>() {
    @Override
    public HttpMessageConverters getObject() throws BeansException {
        return httpMessageConverters;
    }
    };

5. 注意测试环境和生产环境,注意正确使用feign日志级别。

6. apacheHttpclient或者其他client的正确配置:

  • apacheHttpclient自定义配置放在spring root context,不要在FeignContext,否则不会起作用。
  • apacheHttpclient 连接池配置合理地连接和其他参数

7. Feign配置

#Hystrix支持,如果为true,hystrix库必须在classpath中
feign.hystrix.enabled=false
 
#请求和响应GZIP压缩支持
feign.compression.request.enabled=true
feign.compression.response.enabled=true
#支持压缩的mime types
feign.compression.request.enabled=true
feign.compression.request.mime-types=text/xml,application/xml,application/json
feign.compression.request.min-request-size=2048

# 日志支持
logging.level.project.user.UserClient: DEBUG
    

8. Logger.Level支持

必须为每一个Feign Client配置来告诉Feign如何输出日志,可选:

  • NONE, No logging (DEFAULT).
  • BASIC, Log only the request method and URL and the response status code and execution time.
  • HEADERS, Log the basic information along with request and response headers.
  • FULL, Log the headers, body, and metadata for both requests and responses.

9. FeignClient.fallback 正确的使用方法

配置的fallback class也必须在FeignClient Configuration中实例化,否则会报
java.lang.IllegalStateException: No fallback instance of type class异常。

例子:

    @FeignClient(name = "hello", fallback = HystrixClientFallback.class)
    public interface HystrixClient {
        @RequestMapping(method = RequestMethod.GET, value = "/hello")
        Hello iFailSometimes();
    }
    
    public class HystrixClientFallback implements HystrixClient {
        @Override
        public Hello iFailSometimes() {
            return new Hello("fallback");
        }
    }
    
    @Configuration
    public class FooConfiguration {
        @Bean
        @Scope("prototype")
        public Feign.Builder feignBuilder() {
            return Feign.builder();
        }
        
        @Bean
        public HystrixClientFallback fb(){
            return new HystrixClientFallback();
        }
        
    }
    

10. 使用Feign Client 和@RequestMapping时,注意事项

当前工程中有和Feign Client中一样的Endpoint时,Feign Client的类上不能用@RequestMapping注解否则,当前工程该endpoint http请求且使用accpet时会报404.

下面的例子:

有一个 Controller

@RestController
@RequestMapping("/v1/card")
public class IndexApi {

    @PostMapping("balance")
    @ResponseBody
    public Info index() {
        Info.Builder builder = new Info.Builder();
        builder.withDetail("x", 2);
        builder.withDetail("y", 2);
        return builder.build();
    }
}

有一个Feign Client

@FeignClient(
        name = "card",
        url = "http://localhost:7913",
        fallback = CardFeignClientFallback.class,
        configuration = FeignClientConfiguration.class
)
@RequestMapping(value = "/v1/card")
public interface CardFeignClient {

    @RequestMapping(value = "/balance", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
    Info info();

}

if @RequestMapping is used on class, when invoke http /v1/card/balance, like this :

如果 @RequestMapping注解被用在FeignClient类上,当像如下代码请求/v1/card/balance时,注意有Accept header:

Content-Type:application/json
Accept:application/json

POST http://localhost:7913/v1/card/balance

那么会返回 404。

如果不包含Accept header时请求,则是OK:

Content-Type:application/json
POST http://localhost:7913/v1/card/balance

或者像下面不在Feign Client上使用@RequestMapping注解,请求也是ok,无论是否包含Accept:


@FeignClient(
        name = "card",
        url = "http://localhost:7913",
        fallback = CardFeignClientFallback.class,
        configuration = FeignClientConfiguration.class
)

public interface CardFeignClient {

    @RequestMapping(value = "/v1/card/balance", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
    Info info();

}

相关文章

网友评论

  • 1a64df19c161:最近公司项目重构,web-server跟 service是分开的,需要feign来远程调用,但是页面上有很多静态数据需要缓存,想要在web-server对feign调用的返回结果进行缓存,也就是想重写feign发起请求这块,发请求之前查询缓存中是否有数据,如果有直接返回,如果没有才发起http请求,想问下这块怎么实现,比较简单,因为也想过为每个FeignClient接口创建代理类,但是接口太多 很麻烦。
  • 8324a7eda376:不错不错,收藏了。

    推荐下,分库分表中间件 Sharding-JDBC 源码解析 17 篇:http://t.cn/R0UfGFT


    12a033ef755a:写的不错,谢谢博主;已收藏~
  • ca05cdde7af7:Feign,怎么设置header参数呢
    dp_ookkakjs:@铁汤 重写decoder的意思是?
    norai: @TheodoreBagwell 需要重写decoder
  • Coder编程:Feign中传不了HttpServletRequest和HttpServletResponse怎么办?
    norai:@Coder_80b5 @FeignClient http client组件,不支持传HttpServletRequest 和resquest,HttpServletResponse; @FeignClient 不是http server端组件,HttpServletRequest 和HttpServletResponse是服务端的组件。
    Coder编程:@铁汤 我的意思是,在@FeignClient接口中,有个方法String test(HttpServletRequest resquest,HttpServletResponse response);(@RequestMapping注解没写),这样的方法传到其他服务,接收的时候resquest,response都被重置了,是不是被resquestTemplate替换了?有人说实现接口requestInterceptor,去自定义,我不是很理解。大神,能说说吗?还是说不支持httpservletrequest
    norai:@Coder_80b5 对不起feign不支持,它只是一个http client 不是http server。
  • 风雨诗轩:#Hystrix支持,如果为true,hystrix库必须在classpath中(怎么理解这句话?)
    feign.hystrix.enabled=false
    norai: @风雨诗轩 是的
    风雨诗轩:@铁汤 我就是想确定一下,hystrix库必须在classpath中是不是就是指在maven中添加hystrix的依赖
    norai:@风雨诗轩 呵呵,你是java程序猿?
  • 花屠:找了一些资料, 全是在消费者里使用FeignClient Hystrix fallback, 这样虽然能成功的使用Hystrix 容错
    这样对于消费者并不友好啊..
    对消费者来说, 还要知道生产者是哪个服务, 还要知道 请求url 和参数

    而不能依赖一个jar , 注入接口. 直接 service.method() 多方便啊

    希望有这方面的例案供参考下
    norai:@花屠 请参考http://cloud.spring.io/spring-cloud-static/Dalston.RELEASE/#_feign_logging
  • 花屠:可以帮忙看下,
    http://bbs.springcloud.cn/d/308--
    这个问题吗
  • 240b114f1cba:请问可以提供一个demo参考一下嘛?自己研究feignClient始终不如意。。
    norai:@xxxxssss12 这些都是商业项目中用到,不方便提供,谢谢!可以参考http://cloud.spring.io/spring-cloud-static/Camden.SR5/#spring-cloud-feign
  • 94869c53a212:如何在feign中添加hystrix线程池的配置和超时配置
    norai:@熬夜听雨声 请参考官方文档https://github.com/Netflix/Hystrix/wiki/Configuration#execution.isolation.strategy
  • 90586cb6fa67:SpringCloud feign 服务访问 404问题

    一、问题

    feignClient默认只能在方法的RequestMapping 上加全部url路径,

    类的RequestMapping,不能合并到方法上;

    http://www.jianshu.com/p/191d45210d16

    详见问题十

    如:访问全路径url时/sys/user/login时,导致找不到服务,出现404错误。

    @RequestMapping("/sys/user")
    public interface UserClient extends BaseFeignClient<User, Long> {
    @CustomScript
    /**
    * 根据用户名,查询用户信息
    */
    @RequestMapping(value = "/login")
    @RequiresPermissions(PermissionUtils.VIEW)
    @ResponseBody
    BaseResponse<User> login(@RequestParam("loginName")String loginName...);

    }
    二、解决方案

    合并url SpringMvcContractCustom 拷贝自SpringMvcContract,增加类和方法url合并
    增加自定义配置类 FeignClientsConfigurationCustom 拷贝自FeignClientsConfiguration 修改feignContract 方法 return new SpringMvcContractCustom
    feign客户端增加自定义配置类 @FeignClient(value = "sys-service",configuration = FeignClientsConfigurationCustom.class)

本文标题:Feign正确的使用姿势和性能优化注意事项

本文链接:https://www.haomeiwen.com/subject/zefpettx.html