aba技術ブログ

ソフトウェア関係を中心にした技術ブログ

Spring Boot + Open Feignで同一インターフェイス内のメソッド単位でタイムアウトを設定する

先に結論

feignで定義したインターフェイスでメソッド単位でタイムアウトを設定したい場合はメソッドの引数にRequest.Optionsを渡すとその値が優先された採用されます。 これにより、タイムアウト値だけを変えるためにだけに個別にインターフェイスごと定義する必要が無くなります。

Spring Boot + Open Feignを使ってタイムアウトを設定する

Spring Boot + Open Feignを使ってAPIリクエストを実装する際にタイムアウトを設定する場合、application.properties(yml)ファイルに設定を記載する方法が一番シンプルかと思います。 以下にgoogleのトップページにリクエストする例をKotlinベースで示します。

Feignのinterface定義

@FeignClient(
name = "test-feign-client",
 url = "https://www.google.com"
)
interface TestFeignClient {

    @GetMapping("")
    fun getRequestToGoogle(): ResponseEntity<String>
}

application.ymlの例

feign:
  client:
    config:
      test-feign-client:
        connect-timeout: 3000
        read-timeout: 5000

TestFeignClient.getRequestToGoogle を呼び出す際に、下記タイムアウト設定でリクエストすることができます。

connect timeout 3秒
read timeout 5秒

同一Feign Clientインターフェイスで複数メソッドを定義すると同じタイムアウト値が採用される

Feign Clientインターフェイスで複数メソッドを定義すると、同じタイムアウト設定が適用されます。例えば以下のように追記分の getRequestToGoogleOnceAgain を呼び出すと上記と全く同じ値がされます。一方で実運用を考えると複数のAPIにリクエストする場合にAPIごとに個別のタイムアウト値を設定したいケースがあるかと思います。 その場合上記の方法に習うと、個別のinterfaceを定義しapplicaiton.ymlに追記する必要があります。

@FeignClient(
name = "test-feign-client",
 url = "https://www.google.com"
)
interface TestFeignClient {

    @GetMapping("")
    fun getRequestToGoogle(): ResponseEntity<String>

 // 追記
    @GetMapping("")
    fun getRequestToGoogleOnceAgain(): ResponseEntity<String>
}

同一インターフェイス内のメソッド単位でタイムアウト値を設定する

メソッド単位でタイムアウト値を設定する方法がOpen Feign 10.3.0 github.com

からサポートされ、 メソッドの引数にfeign.Request.Optionsを渡してタイムアウト値が設定できるようになりました。 以下に例を示します。

@FeignClient(name = "test-feign-client", url = "https://www.google.com")
interface TestFeignClient {

    @GetMapping("")
    fun getRequestToGoogle(): ResponseEntity<String>

    // 引数を追加
    @GetMapping("")
    fun getRequestToGoogleWithOptions(options: Request.Options): ResponseEntity<String>
}

getRequestToGoogleWithOptionsに引数としてRequest.Optionsを追加しました。このため、ここで渡された値が優先してタイムアウト値として採用されます。

呼び出し方の例としては以下になります。

                testFeignClient.getRequestToGoogleWithOptions(
                    Request.Options(
                        1000,
                        TimeUnit.MILLISECONDS,
                        2000,
                        TimeUnit.MILLISECONDS,
                        false
                    )
                )

よってこの例では以下のタイムアウト値が使われます。

connect timeout 1秒
read timeout 2秒

この方法でタイムアウト値を変えたいだけなので個別にインターフェイスファイルや設定を記述せずに済みます。