1. 程式人生 > >Spring Cloud Feign 使用方法與性能優化

Spring Cloud Feign 使用方法與性能優化

http請求 tail 解碼器 param 生產 例子 nbu llb col

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

4. 自定義feign的消息編碼解碼器:

不要在如下代碼中getObject方法內new 對象,外部會頻繁調用getObject方法。

1

2
3
4
5
6

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配置

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

#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異常。

例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

@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

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

@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

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

@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:

1
2
3
4

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

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

那麽會返回 404。

如果不包含Accept header時請求,則是OK:

1
2

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

或者像下面不在Feign Client上使用@RequestMapping註解,請求也是ok,無論是否包含Accept:

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

@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();

}

Spring Cloud Feign 使用方法與性能優化