Spring Cloud OpenFeign の特長
宣言的な REST クライアント: フェイグ
フェイグ [GitHub] (英語) は宣言型 Web サービスクライアントです。これにより、Web サービスクライアントの作成が容易になります。Feign を使用するには、インターフェースを作成し、それにアノテーションを付けます。Feign アノテーションや JAX-RS アノテーションなどのプラグイン可能なアノテーションサポートが備わっています。Feign は、プラグ可能なエンコーダとデコーダもサポートしています。Spring Cloud では、Spring MVC アノテーションと、Spring Web でデフォルトで使用されるのと同じ HttpMessageConverters
の使用のサポートが追加されます。Spring Cloud は、Eureka、Spring Cloud CircuitBreaker、および Spring Cloud LoadBalancer を統合し、Feign の使用時に負荷分散された http クライアントを提供します。
ふりを含める方法
Feign をプロジェクトに含めるには、グループ org.springframework.cloud
およびアーティファクト ID spring-cloud-starter-openfeign
のスターターを使用します。現在の Spring Cloud リリーストレインを使用したビルドシステムのセットアップの詳細については、Spring Cloud プロジェクトページを参照してください。
spring boot アプリの例
@SpringBootApplication
@EnableFeignClients
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
@FeignClient("stores")
public interface StoreClient {
@RequestMapping(method = RequestMethod.GET, value = "/stores")
List<Store> getStores();
@GetMapping("/stores")
Page<Store> getStores(Pageable pageable);
@PostMapping(value = "/stores/{storeId}", consumes = "application/json",
params = "mode=upsert")
Store update(@PathVariable("storeId") Long storeId, Store store);
@DeleteMapping("/stores/{storeId:\\d+}")
void delete(@PathVariable Long storeId);
}
@FeignClient
アノテーションでは、文字列値 (上記の "stores" ) は任意のクライアント名であり、Spring Cloud LoadBalancer クライアント [GitHub] (英語) の作成に使用されます。url
属性 (絶対値またはホスト名のみ) を使用して URL を指定することもできます。アプリケーションコンテキスト内の Bean の名前は、インターフェースの完全修飾名です。独自のエイリアス値を指定するには、@FeignClient
アノテーションの qualifiers
値を使用できます。
上記のロードバランサクライアントは、"stores" サービスの物理アドレスを検出する必要があります。アプリケーションが Eureka クライアントの場合は、Eureka サービスレジストリ内のサービスを解決します。Eureka を使用したくない場合は、SimpleDiscoveryClient
を使用して外部構成でサーバーのリストを構成できます。
Spring Cloud OpenFeign は、Spring Cloud LoadBalancer のブロッキングモードで利用可能なすべての機能をサポートします。詳細については、プロジェクトのドキュメントを参照してください。
@Configuration アノテーション付きクラスで @EnableFeignClients アノテーションを使用するには、クライアントが配置されている場所 (例: @EnableFeignClients(basePackages = "com.example.clients") ) を指定するか、明示的にリストします (例: @EnableFeignClients(clients = InventoryServiceFeignClient.class) )。 |
マルチモジュール設定で Spring Feign クライアント Bean をロードするには、パッケージを直接指定する必要があります。
FactoryBean オブジェクトは、初期コンテキストのリフレッシュが行われる前にインスタンス化される可能性があり、Spring Cloud OpenFeign クライアントのインスタンス化によってコンテキストのリフレッシュがトリガーされるため、FactoryBean クラス内で宣言しないでください。 |
偽のデフォルトを上書きする
Spring Cloud の Feign サポートの中心的な概念は、名前付きクライアントの概念です。各 Feign クライアントは、オンデマンドで リモートサーバーに接続するために連携して動作するコンポーネントのアンサンブルの一部であり、アンサンブルには、アプリケーション開発者が @FeignClient
アノテーションを使用して指定する名前があります。Spring Cloud は、オンデマンドで FeignClientsConfiguration
を使用して、名前付きクライアントごとに新しいアンサンブルを ApplicationContext
として作成します。これには、(特に) feign.Decoder
、feign.Encoder
、feign.Contract
が含まれます。@FeignClient
アノテーションの contextId
属性を使用して、そのアンサンブルの名前をオーバーライドできます。
Spring Cloud を使用すると、@FeignClient
を使用して ( FeignClientsConfiguration
の上に) 追加の構成を宣言することで、Feign クライアントを完全に制御できます。例:
@FeignClient(name = "stores", configuration = FooConfiguration.class)
public interface StoreClient {
//..
}
この場合、クライアントは、FeignClientsConfiguration
にすでに存在するコンポーネントと FooConfiguration
のコンポーネントから構成されます (後者は前者をオーバーライドします)。
FooConfiguration に @Configuration のアノテーションを付ける必要はありません。ただし、そうである場合は、指定すると feign.Decoder 、feign.Encoder 、feign.Contract などのデフォルトのソースになるため、この構成を含めるすべての @ComponentScan からそれを除外するように注意してください。これは、@ComponentScan または @SpringBootApplication とは別の重複しないパッケージに入れることで回避できます。あるいは、@ComponentScan で明示的に除外することもできます。 |
ApplicationContext アンサンブルの名前の変更に加えて、@FeignClient アノテーションの contextId 属性を使用すると、クライアント名のエイリアスがオーバーライドされ、そのクライアント用に作成された構成 Bean の名前の一部として使用されます。 |
以前は、url 属性を使用していましたが、name 属性は必要ありませんでした。name の使用が必須になりました。 |
プレースホルダーは、name
および url
属性でサポートされています。
@FeignClient(name = "${feign.name}", url = "${feign.url}")
public interface StoreClient {
//..
}
Spring Cloud OpenFeign は、デフォルトで feign (BeanType
beanName: ClassName
) に次の Bean を提供します。
Decoder
feignDecoder:ResponseEntityDecoder
(SpringDecoder
をラップするもの)Encoder
feignEncoder:SpringEncoder
Logger
feignLogger:Slf4jLogger
MicrometerObservationCapability
micrometerObservationCapability:feign-micrometer
がクラスパス上にあり、ObservationRegistry
が使用可能な場合MicrometerCapability
micrometerCapability:feign-micrometer
がクラスパス上にある場合、MeterRegistry
は使用可能ですが、ObservationRegistry
は使用できませんCachingCapability
cachingCapability:@EnableCaching
アノテーションが使用されている場合。spring.cloud.openfeign.cache.enabled
経由で無効にできます。Contract
feignContract:SpringMvcContract
Feign.Builder
feignBuilder:FeignCircuitBreaker.Builder
Client
feignClient: Spring Cloud または LoadBalancer がクラスパス上にある場合は、FeignBlockingLoadBalancerClient
が使用されます。いずれもクラスパス上にない場合は、デフォルトの Feign クライアントが使用されます。
spring-cloud-starter-openfeign は spring-cloud-starter-loadbalancer をサポートします。ただし、オプションの依存関係であるため、使用する場合はプロジェクトに追加されていることを確認する必要があります。 |
OkHttpClient ベースの Feign クライアントと Http2Client Feign クライアントを使用するには、使用するクライアントがクラスパス上にあることを確認し、それぞれ spring.cloud.openfeign.okhttp.enabled
または spring.cloud.openfeign.http2client.enabled
を true
に設定します。
Apache HttpClient 5 をサポートする Feign クライアントの場合、HttpClient 5 がクラスパス上にあることを確認するだけで十分ですが、spring.cloud.openfeign.httpclient.hc5.enabled
を false
に設定することで、Feign クライアントでの使用を無効にすることができます。Apache HC5 を使用するときは、Bean に org.apache.hc.client5.http.impl.classic.CloseableHttpClient
のいずれかを指定して、使用する HTTP クライアントをカスタマイズできます。
spring.cloud.openfeign.httpclient.xxx
プロパティに値を設定することで、HTTP クライアントをさらにカスタマイズできます。プレフィックスが httpclient
のみのクライアントはすべてのクライアントで機能し、プレフィックスが httpclient.hc5
のクライアントは Apache HttpClient 5 に、プレフィックスが httpclient.okhttp
のクライアントは OkHttpClient に、プレフィックスが httpclient.http2
のクライアントは Http2Client に機能します。カスタマイズできるプロパティの完全なリストは付録に記載されています。プロパティを使用して Apache HttpClient 5 を構成できない場合は、プログラムによる構成用の HttpClient5FeignConfiguration.HttpClientBuilderCustomizer
インターフェースがあります。
Apache HTTP コンポーネント 5.4 は、HTTP/1.1 TLS アップグレードに関連する HttpClient のデフォルトを変更しました。ほとんどのプロキシサーバーは課題なくアップグレードを処理しますが、Envoy または Istio では問題が発生する可能性があります。以前の動作を復元する必要がある場合は、以下の例に示すように、HttpClient5FeignConfiguration.HttpClientBuilderCustomizer を使用して復元できます。 |
@Configuration
public class FooConfiguration {
@Bean
public HttpClient5FeignConfiguration.HttpClientBuilderCustomizer httpClientBuilder() {
return (httpClientBuilder) -> {
RequestConfig.Builder requestConfigBuilder = RequestConfig.custom();
requestConfigBuilder.setProtocolUpgradeEnabled(false);
httpClientBuilder.setDefaultRequestConfig(requestConfigBuilder.build());
};
}
}
Spring Cloud、OpenFeign 4 以降、Feign Apache HttpClient 4 はサポートされなくなりました。代わりに Apache HttpClient 5 を使用することをお勧めします。 |
Spring Cloud OpenFeign は、デフォルトでは feign に次の Bean を提供しませんが、アプリケーションコンテキストからこれらの型の Bean を検索して、Feign クライアントを作成します。
Logger.Level
Retryer
ErrorDecoder
Request.Options
Collection<RequestInterceptor>
SetterFactory
QueryMapEncoder
Capability
(MicrometerObservationCapability
およびCachingCapability
がデフォルトで提供されます)
型 Retryer
の Retryer.NEVER_RETRY
の Bean がデフォルトで作成され、再試行が無効になります。この再試行動作は、一時的なネットワーク関連例外および ErrorDecoder からスローされた RetryableException として扱われる IOExceptions を自動的に再試行する Feign のデフォルト動作とは異なることに注意してください。
これらの型のいずれかの Bean を作成し、それを @FeignClient
構成 (上記の FooConfiguration
など) に配置すると、説明されている Bean のそれぞれをオーバーライドできます。例:
@Configuration
public class FooConfiguration {
@Bean
public Contract feignContract() {
return new feign.Contract.Default();
}
@Bean
public BasicAuthRequestInterceptor basicAuthRequestInterceptor() {
return new BasicAuthRequestInterceptor("user", "password");
}
}
これにより、SpringMvcContract
が feign.Contract.Default
に置き換えられ、RequestInterceptor
が RequestInterceptor
のコレクションに追加されます。
@FeignClient
は、構成プロパティを使用して構成することもできます。
application.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
を指し、これは @FeignClient
name
、@FeignClient
contextId
の別名でもあります。負荷分散シナリオでは、インスタンスの取得に使用されるサーバーアプリの serviceId
にも対応します。デコーダー、リトライアー、その他のクラスに指定されたクラスは、Spring コンテキストに Bean を持つか、デフォルトのコンストラクターを持つ必要があります。
デフォルト設定は、上記と同様の方法で @EnableFeignClients
属性 defaultConfiguration
に指定できます。違いは、この設定がすべての Feign クライアントに適用されることです。
構成プロパティを使用してすべての @FeignClient
を構成する場合は、default
仮名を使用して構成プロパティを作成できます。
spring.cloud.openfeign.client.config.feignName.defaultQueryParameters
および spring.cloud.openfeign.client.config.feignName.defaultRequestHeaders
を使用して、feignName
という名前のクライアントのすべてのリクエストで送信されるクエリパラメーターとヘッダーを指定できます。
application.yml
spring:
cloud:
openfeign:
client:
config:
default:
connectTimeout: 5000
readTimeout: 5000
loggerLevel: basic
@Configuration
Bean と構成プロパティの両方を作成すると、構成プロパティが優先されます。@Configuration
値をオーバーライドします。ただし、優先順位を @Configuration
に変更したい場合は、spring.cloud.openfeign.client.default-to-properties
を false
に変更できます。
同じ名前または URL を持つ複数の Feign クライアントを作成し、それらが同じサーバーを指すようにしながらも、それぞれ異なるカスタム構成を持つようにする場合は、これらの構成 Bean の名前の衝突を回避するために、@FeignClient
の contextId
属性を使用する必要があります。
@FeignClient(contextId = "fooClient", name = "stores", configuration = FooConfiguration.class)
public interface FooClient {
//..
}
@FeignClient(contextId = "barClient", name = "stores", configuration = BarConfiguration.class)
public interface BarClient {
//..
}
親コンテキストから Bean を継承しないように FeignClient を構成することもできます。これを行うには、FeignClientConfigurer
Bean の inheritParentConfiguration()
をオーバーライドして false
を返します。
@Configuration
public class CustomConfiguration {
@Bean
public FeignClientConfigurer feignClientConfigurer() {
return new FeignClientConfigurer() {
@Override
public boolean inheritParentConfiguration() {
return false;
}
};
}
}
デフォルトでは、Feign クライアントはスラッシュ / 文字をエンコードしません。この動作は、spring.cloud.openfeign.client.decode-slash の値を false に設定することで変更できます。 |
デフォルトでは、Feign クライアントはリクエストパスから末尾のスラッシュ / 文字を削除しません。この動作は、spring.cloud.openfeign.client.remove-trailing-slash の値を true に設定することで変更できます。リクエストパスから末尾のスラッシュを削除する動作は、次のメジャーリリースでデフォルトの動作になる予定です。 |
タイムアウト処理
デフォルトと指定されたクライアントの両方でタイムアウトを構成できます。OpenFeign は 2 つのタイムアウトパラメーターで動作します。
connectTimeout
は、サーバーの処理時間が長いために呼び出し元がブロックされることを防ぎます。readTimeout
は接続確立時から適用され、レスポンスを返すのに時間がかかりすぎる場合にトリガーされます。
サーバーが実行中でないか利用できない場合、パケットにより接続が拒否されます。通信はエラーメッセージまたはフォールバックで終了します。connectTimeout が非常に低く設定されている場合、これは connectTimeout の前に発生する可能性があります。ルックアップの実行とそのようなパケットの受信にかかる時間が、この遅延の大きな部分を引き起こします。これは、DNS ルックアップを伴う リモートホストに基づいて変更される可能性があります。 |
偽のクライアントを手動で作成する
場合によっては、上記の方法では不可能な方法で Feign Client をカスタマイズすることが必要になる場合があります。この場合、フェーンビルダー API [GitHub] (英語) を使用してクライアントを作成できます。以下は、同じインターフェースを持つ 2 つの Feign Client を作成し、それぞれを別のリクエストインターセプターで構成する例です。
@Import(FeignClientsConfiguration.class)
class FooController {
private FooClient fooClient;
private FooClient adminClient;
@Autowired
public FooController(Client client, Encoder encoder, Decoder decoder, Contract contract, MicrometerObservationCapability micrometerObservationCapability) {
this.fooClient = Feign.builder().client(client)
.encoder(encoder)
.decoder(decoder)
.contract(contract)
.addCapability(micrometerObservationCapability)
.requestInterceptor(new BasicAuthRequestInterceptor("user", "user"))
.target(FooClient.class, "https://PROD-SVC");
this.adminClient = Feign.builder().client(client)
.encoder(encoder)
.decoder(decoder)
.contract(contract)
.addCapability(micrometerObservationCapability)
.requestInterceptor(new BasicAuthRequestInterceptor("admin", "admin"))
.target(FooClient.class, "https://PROD-SVC");
}
}
上記の例では、FeignClientsConfiguration.class は Spring Cloud OpenFeign によって提供されるデフォルト構成です。 |
PROD-SVC は、クライアントがリクエストを行うサービスの名前です。 |
Feign Contract オブジェクトは、インターフェースで有効なアノテーションと値を定義します。オートワイヤーされた Contract Bean は、デフォルトの Feign ネイティブアノテーションの代わりに、SpringMVC アノテーションのサポートを提供します。Spring MVC アノテーションとネイティブ Feign アノテーションを混在させることは推奨されません。 |
Builder`to configure FeignClient not to inherit beans from the parent context. You can do this by overriding calling `inheritParentContext(false)
を Builder
で使用することもできます。
Spring Cloud CircuitBreaker サポートを装う
Spring Cloud CircuitBreaker がクラスパス上にあり、spring.cloud.openfeign.circuitbreaker.enabled=true
である場合、Feign はすべてのメソッドをサーキットブレーカーでラップします。
クライアントごとに Spring Cloud CircuitBreaker サポートを無効にするには、「プロトタイプ」スコープを持つバニラ Feign.Builder
を作成します。例:
@Configuration
public class FooConfiguration {
@Bean
@Scope("prototype")
public Feign.Builder feignBuilder() {
return Feign.builder();
}
}
サーキットブレーカー名は、このパターン <feignClientClassName>#<calledMethod>(<parameterTypes>)
に従います。FooClient
インターフェースを使用して @FeignClient
を呼び出し、パラメーターを持たない呼び出されたインターフェースメソッドが bar
である場合、サーキットブレーカー名は FooClient#bar()
になります。
2020.0.2 以降、サーキットブレーカー名のパターンが <feignClientName>_<calledMethod> から変更されました。2020.0.4 で導入された CircuitBreakerNameResolver を使用すると、サーキットブレーカー名に古いパターンを保持できます。 |
Bean または CircuitBreakerNameResolver
を指定すると、サーキットブレーカー名のパターンを変更できます。
@Configuration
public class FooConfiguration {
@Bean
public CircuitBreakerNameResolver circuitBreakerNameResolver() {
return (String feignClientName, Target<?> target, Method method) -> feignClientName + "_" + method.getName();
}
}
Spring Cloud CircuitBreaker グループを有効にするには、spring.cloud.openfeign.circuitbreaker.group.enabled
プロパティを true
(デフォルトでは false
) に設定します。
構成プロパティを使用した CircuitBreakers の構成
CircuitBreakers は構成プロパティを通じて構成できます。
例: この Feign クライアントがいた場合
@FeignClient(url = "http://localhost:8080")
public interface DemoClient {
@GetMapping("demo")
String getDemo();
}
次のように構成プロパティを使用して構成できます
spring:
cloud:
openfeign:
circuitbreaker:
enabled: true
alphanumeric-ids:
enabled: true
resilience4j:
circuitbreaker:
instances:
DemoClientgetDemo:
minimumNumberOfCalls: 69
timelimiter:
instances:
DemoClientgetDemo:
timeoutDuration: 10s
Spring Cloud 2022.0.0 より前に使用されていたサーキットブレーカー名に戻したい場合は、spring.cloud.openfeign.circuitbreaker.alphanumeric-ids.enabled を false に設定します。 |
Spring Cloud CircuitBreaker フォールバックを装う
Spring Cloud CircuitBreaker は、フォールバックの概念をサポートしています。フォールバックとは、回線が開いているとき、またはエラーが発生したときに実行されるデフォルトのコードパスです。特定の @FeignClient
のフォールバックを有効にするには、fallback
属性をフォールバックを実装するクラス名に設定します。また、実装を Spring Bean として宣言する必要があります。
@FeignClient(name = "test", url = "http://localhost:${server.port}/", fallback = Fallback.class)
protected interface TestClient {
@GetMapping("/hello")
Hello getHello();
@GetMapping("/hellonotfound")
String getException();
}
@Component
static class Fallback implements TestClient {
@Override
public Hello getHello() {
throw new NoFallbackAvailableException("Boom!", new RuntimeException());
}
@Override
public String getException() {
return "Fixed response";
}
}
フォールバックトリガーを作成した原因にアクセスする必要がある場合は、@FeignClient
内の fallbackFactory
属性を使用できます。
@FeignClient(name = "testClientWithFactory", url = "http://localhost:${server.port}/",
fallbackFactory = TestFallbackFactory.class)
protected interface TestClientWithFactory {
@GetMapping("/hello")
Hello getHello();
@GetMapping("/hellonotfound")
String getException();
}
@Component
static class TestFallbackFactory implements FallbackFactory<FallbackWithFactory> {
@Override
public FallbackWithFactory create(Throwable cause) {
return new FallbackWithFactory();
}
}
static class FallbackWithFactory implements TestClientWithFactory {
@Override
public Hello getHello() {
throw new NoFallbackAvailableException("Boom!", new RuntimeException());
}
@Override
public String getException() {
return "Fixed response";
}
}
フェイグと @Primary
Feign を Spring Cloud CircuitBreaker フォールバックで使用する場合、ApplicationContext
内に同じ型の Bean が複数存在します。これにより、Bean が 1 つだけ、またはプライマリとしてマークされた 1 つが存在しないため、@Autowired
が機能しなくなります。これを回避するために、Spring Cloud OpenFeign はすべての Feign インスタンスを @Primary
としてマークし、Spring Framework がどの Bean を注入するかを認識できるようにします。場合によっては、これが望ましくない場合もあります。この動作をオフにするには、@FeignClient
の primary
属性を false に設定します。
@FeignClient(name = "hello", primary = false)
public interface HelloClient {
// methods here
}
偽装相続サポート
Feign は、単一継承インターフェースを介してボイラープレート API をサポートしています。これにより、一般的な操作を便利な基本インターフェースにグループ化できます。
public interface UserService {
@GetMapping("/users/{id}")
User getUser(@PathVariable("id") long id);
}
@RestController
public class UserResource implements UserService {
}
@FeignClient("users")
public interface UserClient extends UserService {
}
@FeignClient インターフェースはサーバーとクライアント間で共有すべきではなく、クラスレベルでの @RequestMapping による @FeignClient インターフェースへのアノテーション付けはサポートされなくなりました。 |
リクエスト / レスポンスの圧縮を装う
Feign リクエストに対してリクエストまたはレスポンスの GZIP 圧縮を有効にすることを検討してください。これを行うには、次のいずれかのプロパティを有効にします。
spring.cloud.openfeign.compression.request.enabled=true
spring.cloud.openfeign.compression.response.enabled=true
偽のリクエスト圧縮により、Web サーバーに設定するものと同様の設定が得られます。
spring.cloud.openfeign.compression.request.enabled=true
spring.cloud.openfeign.compression.request.mime-types=text/xml,application/xml,application/json
spring.cloud.openfeign.compression.request.min-request-size=2048
これらのプロパティを使用すると、圧縮メディア型と最小リクエストしきい値の長さを選択できます。
リクエストが spring.cloud.openfeign.compression.request.mime-types
で設定された MIME 型と spring.cloud.openfeign.compression.request.min-request-size
で設定されたサイズに一致する場合、spring.cloud.openfeign.compression.request.enabled=true
によって、リクエストに圧縮ヘッダーが追加されます。ヘッダーの機能は、クライアントが圧縮された本文を期待していることをサーバーに通知することです。クライアントによって提供されたヘッダーに基づいて圧縮された本文を提供するのは、サーバー側アプリのロールです。
OkHttpClient は「透過的」圧縮を使用するため、content-encoding ヘッダーまたは accept-encoding ヘッダーが存在する場合は無効になります。クラスパス上に feign.okhttp.OkHttpClient が存在し、spring.cloud.openfeign.okhttp.enabled が true に設定されている場合は圧縮を有効にしません。 |
偽装伐採
ロガーは、作成された Feign クライアントごとに作成されます。デフォルトでは、ロガーの名前は、Feign クライアントの作成に使用されるインターフェースの完全なクラス名です。偽ロギングは DEBUG
レベルにのみ応答します。
logging.level.project.user.UserClient: DEBUG
クライアントごとに設定できる Logger.Level
オブジェクトは、Feign にどれくらいの量のログを記録するかを指示します。選択肢は次のとおりです。
NONE
、ログなし ( DEFAULT )。BASIC
、リクエストメソッドと URL、レスポンスステータスコードと実行時間のみをログに記録します。HEADERS
、リクエストヘッダーとレスポンスヘッダーとともに基本情報をログに記録します。FULL
、リクエストとレスポンスの両方のヘッダー、本文、メタデータをログに記録します。
例: 以下は Logger.Level
を FULL
に設定します。
@Configuration
public class FooConfiguration {
@Bean
Logger.Level feignLoggerLevel() {
return Logger.Level.FULL;
}
}
偽装機能のサポート
Feign 機能はコア Feign コンポーネントを公開し、これらのコンポーネントを変更できるようにします。例: 機能は Client
を取得し、それを修飾し、修飾されたインスタンスを Feign に返すことができます。Micrometer のサポートは、これに関する良い実際の例です。Micrometer サポートを参照してください。
1 つ以上の Capability
Bean を作成し、@FeignClient
構成に配置すると、登録し、関連するクライアントの動作を変更できるようになります。
@Configuration
public class FooConfiguration {
@Bean
Capability customCapability() {
return new CustomCapability();
}
}
Micrometer サポート
次の条件がすべて当てはまる場合、MicrometerObservationCapability
Bean が作成および登録され、Feign クライアントが Micrometer によって監視可能になります。
feign-micrometer
はクラスパス上にありますObservationRegistry
Bean が利用可能です偽の micrometer プロパティは
true
に設定されます (デフォルト)spring.cloud.openfeign.micrometer.enabled=true
(すべてのクライアントにとって)spring.cloud.openfeign.client.config.feignName.micrometer.enabled=true
(単一のクライアントの場合)
アプリケーションがすでに Micrometer を使用している場合、この機能を有効にするのはクラスパスに feign-micrometer を置くのと同じくらい簡単です。 |
次のいずれかの方法でこの機能を無効にすることもできます。
クラスパスから
feign-micrometer
を除外する偽の micrometer プロパティの 1 つを
false
に設定するspring.cloud.openfeign.micrometer.enabled=false
spring.cloud.openfeign.client.config.feignName.micrometer.enabled=false
spring.cloud.openfeign.micrometer.enabled=false は、クライアントレベルのフラグ spring.cloud.openfeign.client.config.feignName.micrometer.enabled の値に関係なく、すべての Feign クライアントに対する Micrometer サポートを無効にします。クライアントごとに Micrometer サポートを有効または無効にする場合は、spring.cloud.openfeign.micrometer.enabled を設定せず、spring.cloud.openfeign.client.config.feignName.micrometer.enabled を使用します。 |
独自の Bean を登録して、MicrometerObservationCapability
をカスタマイズすることもできます。
@Configuration
public class FooConfiguration {
@Bean
public MicrometerObservationCapability micrometerObservationCapability(ObservationRegistry registry) {
return new MicrometerObservationCapability(registry);
}
}
Feign (メトリクスのみのサポート) で MicrometerCapability
を使用することは引き続き可能ですが、Micrometer サポート (spring.cloud.openfeign.micrometer.enabled=false
) を無効にして、MicrometerCapability
Bean を作成する必要があります。
@Configuration
public class FooConfiguration {
@Bean
public MicrometerCapability micrometerCapability(MeterRegistry meterRegistry) {
return new MicrometerCapability(meterRegistry);
}
}
偽装キャッシング
@EnableCaching
アノテーションが使用されている場合は、Feign クライアントがそのインターフェース上の @Cache*
アノテーションを認識できるように、CachingCapability
Bean が作成および登録されます。
public interface DemoClient {
@GetMapping("/demo/{filterParam}")
@Cacheable(cacheNames = "demo-cache", key = "#keyParam")
String demoEndpoint(String keyParam, @PathVariable String filterParam);
}
プロパティ spring.cloud.openfeign.cache.enabled=false
を使用して機能を無効にすることもできます。
Spring @RequestMapping サポート
Spring Cloud OpenFeign は、Spring @RequestMapping
アノテーションとその派生アノテーション ( @GetMapping
、@PostMapping
など) のサポートを提供します。@RequestMapping
アノテーション ( value
、method
、params
、headers
、consumes
、produces
を含む) の属性は、リクエストの内容として SpringMvcContract
によって解析されます。
次の例を考えてみましょう。
params
属性を使用してインターフェースを定義します。
@FeignClient("demo")
public interface DemoTemplate {
@PostMapping(value = "/stores/{storeId}", params = "mode=upsert")
Store update(@PathVariable("storeId") Long storeId, Store store);
}
上記の例では、リクエスト URL は /stores/storeId?mode=upsert
に解決されます。
params 属性は、複数の key=value
または 1 つの key
のみの使用もサポートします。
params = { "key1=v1", "key2=v2" }
の場合、リクエスト URL は/stores/storeId?key1=v1&key2=v2
として解析されます。params = "key"
の場合、リクエスト URL は/stores/storeId?key
として解析されます。
偽の @QueryMap サポート
Spring Cloud OpenFeign は、同等の @SpringQueryMap
アノテーションを提供します。これは、POJO または Map パラメーターにクエリパラメーターマップとしてアノテーションを付けるために使用されます。
例: Params
クラスはパラメーター param1
および param2
を定義します。
// Params.java
public class Params {
private String param1;
private String param2;
// [Getters and setters omitted for brevity]
}
次の Feign クライアントは、@SpringQueryMap
アノテーションを使用して Params
クラスを使用します。
@FeignClient("demo")
public interface DemoTemplate {
@GetMapping(path = "/demo")
String demoEndpoint(@SpringQueryMap Params params);
}
生成されたクエリパラメーターマップをさらに制御する必要がある場合は、カスタム QueryMapEncoder
Bean を実装できます。
HATEOAS のサポート
Spring は、HATEOAS [Wikipedia] (英語) 原則、Spring ハテオアスおよび Spring Data REST に従う REST 表現を作成するための API をいくつか提供します。
プロジェクトで org.springframework.boot:spring-boot-starter-hateoas
スターターまたは org.springframework.boot:spring-boot-starter-data-rest
スターターを使用する場合、Feign HATEOAS サポートはデフォルトで有効になります。
HATEOAS サポートが有効な場合、Feign クライアントは HATEOAS 表現モデル EntityModel (Javadoc) 、CollectionModel (Javadoc) 、PagedModel (Javadoc) を直列化および逆直列化できます。
@FeignClient("demo")
public interface DemoTemplate {
@GetMapping(path = "/stores")
CollectionModel<Store> getStores();
}
Spring @MatrixVariable サポート
Spring Cloud OpenFeign は、Spring @MatrixVariable
アノテーションのサポートを提供します。
マップがメソッド引数として渡される場合、マップのキーと値のペアを =
で結合することによって @MatrixVariable
パスセグメントが作成されます。
別のオブジェクトが渡された場合、@MatrixVariable
アノテーション (定義されている場合) で提供される name
またはアノテーション付き変数名のいずれかが、=
を使用して提供されたメソッド引数と結合されます。
- IMPORTANT
サーバー側では、Spring ではユーザーがパスセグメントプレースホルダーにマトリックス変数名と同じ名前を付ける必要はありませんが、クライアント側では非常に曖昧になるため、Spring Cloud OpenFeign では、パスセグメントプレースホルダーを追加する必要があります。
@MatrixVariable
アノテーション (定義されている場合) で提供されるname
またはアノテーションが付けられた変数名のいずれかに一致する名前。
例:
@GetMapping("/objects/links/{matrixVars}")
Map<String, List<String>> getObjects(@MatrixVariable Map<String, List<String>> matrixVars);
変数名とパスセグメントプレースホルダーは両方とも matrixVars
と呼ばれることに注意してください。
@FeignClient("demo")
public interface DemoTemplate {
@GetMapping(path = "/stores")
CollectionModel<Store> getStores();
}
偽の CollectionFormat
サポート
@CollectionFormat
アノテーションを提供することで feign.CollectionFormat
をサポートします。目的の feign.CollectionFormat
をアノテーション値として渡すことで、Feign クライアントメソッド (またはすべてのメソッドに影響を与えるクラス全体) にアノテーションを付けることができます。
次の例では、メソッドを処理するためにデフォルトの EXPLODED
の代わりに CSV
形式が使用されます。
@FeignClient(name = "demo")
protected interface DemoFeignClient {
@CollectionFormat(feign.CollectionFormat.CSV)
@GetMapping(path = "/test")
ResponseEntity performRequest(String test);
}
リアクティブサポート
Spring Cloud、OpenFeign の開発が活発だった当時、OpenFeign プロジェクト [GitHub] (英語) は Spring WebClient (Javadoc) などのリアクティブクライアントをサポートしていなかったため、Spring Cloud、OpenFeign にもそのようなサポートを追加できませんでした。
Spring Cloud OpenFeign プロジェクトは現在機能が完全であると見なされているため、アップストリームプロジェクトでサポートが利用可能になったとしても、サポートを追加する予定はありません。代わりに、Spring インターフェースクライアントに移行することをお勧めします。そこでは、ブロッキングスタックとリアクティブスタックの両方がサポートされています。
Spring Data サポート
Jackson Databind と Spring Data Commons がクラスパス上にある場合、org.springframework.data.domain.Page
と org.springframework.data.domain.Sort
のコンバーターが自動的に追加されます。
この動作セットを無効にするには
spring.cloud.openfeign.autoconfiguration.jackson.enabled=false
詳細については、org.springframework.cloud.openfeign.FeignAutoConfiguration.FeignJacksonConfiguration
を参照してください。
Spring @RefreshScope
サポート
Feign クライアントのリフレッシュが有効になっている場合、各 Feign クライアントは以下を使用して作成されます。
リフレッシュスコープの Bean としての
feign.Request.Options
。これは、connectTimeout
やreadTimeout
などのプロパティを任意の Feign クライアントインスタンスに対してリフレッシュできることを意味します。org.springframework.cloud.openfeign.RefreshableUrl
でラップされた URL。これは、spring.cloud.openfeign.client.config.{feignName}.url
プロパティで定義されている場合、Feign クライアントの URL を任意の Feign クライアントインスタンスに対してリフレッシュできることを意味します。
これらのプロパティは POST /actuator/refresh
を通じてリフレッシュできます。
デフォルトでは、Feign クライアントのリフレッシュ動作は無効になっています。リフレッシュ動作を有効にするには、次のプロパティを使用します。
spring.cloud.openfeign.client.refresh-enabled=true
@FeignClient インターフェースに @RefreshScope アノテーションを付けないでください。 |
OAuth2 のサポート
OAuth2 サポートを有効にするには、spring-boot-starter-oauth2-client
依存関係をプロジェクトに追加し、次のフラグを設定します。
spring.cloud.openfeign.oauth2.enabled=true
フラグが true に設定され、oauth2 クライアントコンテキストリソースの詳細が存在する場合、クラス OAuth2AccessTokenInterceptor
の Bean が作成されます。各リクエストの前に、インターセプターは必要なアクセストークンを解決し、それをヘッダーとして含めます。OAuth2AccessTokenInterceptor
は OAuth2AuthorizedClientManager
を使用して、OAuth2AccessToken
を保持する OAuth2AuthorizedClient
を取得します。ユーザーが spring.cloud.openfeign.oauth2.clientRegistrationId
プロパティを使用して OAuth2 clientRegistrationId
を指定した場合、それがトークンの取得に使用されます。トークンが取得されない場合、または clientRegistrationId
が指定されていない場合は、url
ホストセグメントから取得された serviceId
が使用されます。
- TIP
OAuth2 クライアント registrationId として
serviceId
を使用すると、負荷分散された Feign クライアントに便利です。負荷分散されていないクライアントの場合は、プロパティベースのclientRegistrationId
が適切なアプローチです。- TIP
OAuth2AuthorizedClientManager
のデフォルト設定を使用したくない場合は、構成内でこの型の Bean をインスタンス化するだけです。
負荷分散された HTTP リクエストを変換する
選択した ServiceInstance
を使用して、負荷分散された HTTP リクエストを変換できます。
Request
の場合、次のように LoadBalancerFeignRequestTransformer
を実装して定義する必要があります。
@Bean
public LoadBalancerFeignRequestTransformer transformer() {
return new LoadBalancerFeignRequestTransformer() {
@Override
public Request transformRequest(Request request, ServiceInstance instance) {
Map<String, Collection<String>> headers = new HashMap<>(request.headers());
headers.put("X-ServiceId", Collections.singletonList(instance.getServiceId()));
headers.put("X-InstanceId", Collections.singletonList(instance.getInstanceId()));
return Request.create(request.httpMethod(), request.url(), headers, request.body(), request.charset(),
request.requestTemplate());
}
};
}
複数のトランスフォーマーが定義されている場合、Bean が定義されている順序で適用されます。または、LoadBalancerFeignRequestTransformer.DEFAULT_ORDER
を使用して順序を指定することもできます。
X 転送ヘッダーのサポート
X-Forwarded-Host
および X-Forwarded-Proto
のサポートは、次のフラグを設定することで有効にできます。
spring.cloud.loadbalancer.x-forwarded.enabled=true
偽のクライアントに URL を提供するためにサポートされている方法
次のいずれかの方法で、Feign クライアントに URL を提供できます。
ケース | サンプル | 詳細 |
---|---|---|
URL は |
| URL は、負荷分散を行わずに、アノテーションの |
URL は、 |
| URL は、負荷分散を行わずに、アノテーションの |
URL は |
| URL は、負荷分散を行わずに構成プロパティから解決されます。 |
URL は、 |
| URL は、負荷分散を使用して、アノテーションの |
AOT およびネイティブイメージのサポート
Spring Cloud OpenFeign は、Spring AOT 変換とネイティブイメージをサポートしますが、リフレッシュモードが無効、Feign クライアントのリフレッシュが無効 (デフォルト設定)、遅延 @FeignClient
属性解決が無効 (デフォルト設定) の場合にのみサポートされます。
Spring Cloud OpenFeign クライアントを AOT またはネイティブイメージモードで実行する場合は、必ず spring.cloud.refresh.enabled を false に設定してください。 |
Spring Cloud OpenFeign クライアントを AOT またはネイティブイメージモードで実行する場合は、spring.cloud.openfeign.client.refresh-enabled が true に設定されていないことを確認してください。 |
Spring Cloud OpenFeign クライアントを AOT またはネイティブイメージモードで実行する場合は、spring.cloud.openfeign.lazy-attributes-resolution が true に設定されていないことを確認してください。 |
ただし、プロパティを使用して url 値を設定した場合は、-Dspring.cloud.openfeign.client.config.[clientId].url=[url] フラグを指定してイメージを実行することで、@FeignClient url 値をオーバーライドすることができます。オーバーライドを有効にするには、ビルド時に @FeignClient 属性ではなく、プロパティを介して url 値も設定する必要があります。 |
構成プロパティ
すべての Spring Cloud OpenFeign 関連の構成プロパティのリストを確認するには、付録ページを参照してください。