Files
rikako-note/spring/Spring Cloud/Spring Cloud OpenFeign.md

162 lines
8.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

- [Spring Cloud OpenFeign](#spring-cloud-openfeign)
- [Feign](#feign)
- [引入Feign](#引入feign)
- [@FeignClient注解的属性解析模式](#feignclient注解的属性解析模式)
- [覆盖Feign的默认属性](#覆盖feign的默认属性)
- [重试](#重试)
- [通过Configuration类或配置文件来修改Feign Client的默认行为](#通过configuration类或配置文件来修改feign-client的默认行为)
- [超时处理](#超时处理)
- [Feign Caching](#feign-caching)
# Spring Cloud OpenFeign
## Feign
Feign是一个声明式的web service client其能够让编写web service client的过程更加简单。在使用Feign时只需要创建一个接口并且为其添加注解。
在使用Feign时Spring Cloud集成了Eureka、Spring Cloud CircuitBreaker和Spring Cloud LoadBalancer来向使用者提供一个负载均衡的http client。
### 引入Feign
如果要在项目中引入Feign可以添加如下启动器依赖
```xml
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
```
在使用Feign时需要为启动类添加`@EnableFeignClients`注解,示例如下所示:
```java
@SpringBootApplication
@EnableFeignClients
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
```
使用Feign时定义接口并添加注解的示例如下所示
```java
@FeignClient("stores")
public interface StoreClient {
@RequestMapping(method = RequestMethod.GET, value = "/stores")
List<Store> getStores();
@RequestMapping(method = RequestMethod.GET, value = "/stores")
Page<Store> getStores(Pageable pageable);
@RequestMapping(method = RequestMethod.POST, value = "/stores/{storeId}", consumes = "application/json")
Store update(@PathVariable("storeId") Long storeId, Store store);
@RequestMapping(method = RequestMethod.DELETE, value = "/stores/{storeId:\\d+}")
void delete(@PathVariable Long storeId);
}
```
上述示例中,@FeignClient中指定的字符串是一个任意的client name用于创建spring cloud loadbalancer client对于该注解还可以指定一个`url`属性。在spring context中该bean对象的name即是接口的全类名bean name也可以通过@FeignClient注解中的`qualifiers`属性来替换。
上述的loadbalancer client会取发现"stores" service对应的物理地址如果你的应用是一个Eureka client那么loadbalancer client会从Eureka注册中心中进行解析。
#### @FeignClient注解的属性解析模式
当创建Feign client bean对象时会解析传递给@FeignClient注解的属性值。这些值默认是立即解析的。
如果如果需要延迟这些属性值的解析时机,可以配置`spring.cloud.openfeign.lazy-attributes-resolution`的值为true。
### 覆盖Feign的默认属性
Spring Cloud Feign的核心理念是命名客户端named client。每个Feign client都是组件集合一部分组件集合协同工作并且在需要时连接远程的server。该组件集合有一个名称该值通过@FeignClient的value属性赋值。对于每个named clientSpring Cloud使用`FeignClientsConfiguration`来创建一个新的集合作为Application Client。
组件集合中包含有一个`feign.Decoder`,一个`feign.Encoder``feign.Contract`。可以通过@FeignClient注解中的`contextId`属性来覆盖集合name。
Spring Cloud允许通过声明额外的configuration来完全掌控feign client示例如下
```java
@FeignClient(name = "stores", configuration = FooConfiguration.class)
public interface StoreClient {
//..
}
```
在这种情况下client由`FeignClientsConfiguration`中已经存在的组件和`FooConfiguration`中的组件共同组成,并且后者会覆盖前者。
> FooConfiguration类在声明时不要为其添加@Configuration注解否则其会成为feign.Decoder, feign.Encoder, feign.Contract的默认来源。
对于`name``url`属性,赋值支持占位符:
```java
@FeignClient(name = "${feign.name}", url = "${feign.url}")
public interface StoreClient {
//..
}
```
#### 重试
一个`Retryer.NEVER_RETRY`的bean对象会被默认创建其会禁止重试操作。但是其会自动重试IOException将IOException看作暂时性地网络异常并且在ErrorDecoder中抛出RetryableException。
@FeignClient注解`configuration`属性指定的配置类中创建Bean对象可以允许覆盖默认的bean对象示例如下
```java
@Configuration
public class FooConfiguration {
@Bean
public Contract feignContract() {
return new feign.Contract.Default();
}
@Bean
public BasicAuthRequestInterceptor basicAuthRequestInterceptor() {
return new BasicAuthRequestInterceptor("user", "password");
}
}
```
#### 通过Configuration类或配置文件来修改Feign Client的默认行为
@FeignClient也可以通过配置文件来进行配置
```yml
spring:
cloud:
openfeign:
client:
config:
{feignName}:
url: http://remote-service.com
connectTimeout: 5000
readTimeout: 5000
loggerLevel: full
errorDecoder: com.example.SimpleErrorDecoder
retryer: com.example.SimpleRetryer
defaultQueryParameters:
query: queryValue
defaultRequestHeaders:
header: headerValue
requestInterceptors:
- com.example.FooRequestInterceptor
- com.example.BarRequestInterceptor
responseInterceptor: com.example.BazResponseInterceptor
dismiss404: false
encoder: com.example.SimpleEncoder
decoder: com.example.SimpleDecoder
contract: com.example.SimpleContract
capabilities:
- com.example.FooCapability
- com.example.BarCapability
queryMapEncoder: com.example.SimpleQueryMapEncoder
micrometer.enabled: false
```
feignName在上述配置文件中代表@FeignClient注解中的value值
> 若feignName的值为default可以将配置应用于所有的feign client。
可以在`@EnableFeignClients`注解中指定defaultConfiguration属性其可以指定一个自定义的默认配置类覆盖的行为会作用于所有的Feign Client。
可以使用`spring.cloud.openfeign.client.config.feignName.defaultQueryParameters``spring.cloud.openfeign.client.config.feignName.defaultRequestHeaders`来指定client每次请求都会发送的请求参数和请求header。
如果在创建Configuration类的同时也指定了配置文件那么配置文件的优先级更高配置文件的值会覆盖Configuration类中的值。
如果想要多个feign client拥有相同的name和url以使它们指向同一个server但不同feign client拥有不同的配置。可以为它们指定不同的`contextId`
```java
@FeignClient(contextId = "fooClient", name = "stores", configuration = FooConfiguration.class)
public interface FooClient {
//..
}
@FeignClient(contextId = "barClient", name = "stores", configuration = BarConfiguration.class)
public interface BarClient {
//..
}
```
### 超时处理
可以为named client或所有client指定超时处理。OpenFeign使用两个timeout参数
- connectTimeout该属性避免server长时间处理造成的调用方阻塞
- readTimeout该属性从连接建立时开始应用并且当返回响应过慢时被触发该参数衡量的是从建立连接到返回响应的过程
### Feign Caching
当使用@EnableCaching之后,一个`CachingCapability`的bean对象将会被配置Feign client将会识别接口上的`@Cache*`注解。
```java
public interface DemoClient {
@GetMapping("/demo/{filterParam}")
@Cacheable(cacheNames = "demo-cache", key = "#keyParam")
String demoEndpoint(String keyParam, @PathVariable String filterParam);
}
```