Zuul、Ribbon、Feign、Hystrix使用時のタイムアウト時間設定の問題


前に書く


Feign+Hystrixコーディネートモードでのダウングレード(fallback)タイムアウト時間カスタマイズをテストする問題で、ピットを踏んだついでにZuul、Ribbon+Hystrixモードでそれぞれどのように設定するかを調べてみました
これらのものをテストするのに多くの力を費やしました.このいくつかのモジュールが組み合わせて使用されているか、内部が他のモジュールに依存しているか、他のモジュールをパッケージ化しているかのどちらかだからです.この構成項目は奇妙になります.また、ネット上のものは、バージョンが不明で、バージョン番号が異なり、解決策や構成方法が全く異なる可能性があります.多くの文章では、彼らがどのバージョンを使っているのかは言及されていません.私は頭がくらくらしています(結局、私はこれらのサービスモジュールの開発者や長期的な使用者ではありません.これらのバージョンの進化過程をよく理解していません).
だからここは多くの資料を調べて、テストはいくつかの方案に合格して、自分で総括して記録します
注意!
ここではいずれもEurekaがサービスセンターになることを前提としている

ツール

  • Eclipse Oxygen
  • Spring Boot 2.0.5.RELEASE
  • Spring Cloud Finchley.SR1
  • Eureka 1.9.3
  • Zuul 1.3.1
  • Ribbon 2.2.5
  • Feign 9.5.1
  • Hystrix 1.5.12

  • Feign + Hystrix


    この栗のソースはこちら

    0.デフォルトの基本構成


    最も基本的な構成は、Hystrix独自の長い一連の構成:hystrix.command.default.execution.isolation.thread.timeoutInMillisecondsですが、Feignモジュールでは、このタイムアウト時間を単独で設定することはできません.また、Ribbonのタイムアウト時間を追加する必要があります.例えば、次のようにします.
    hystrix:
      command:
        default:
          execution:
            isolation:
              thread:
                timeoutInMilliseconds: 5000
    
    ribbon:
      ReadTimeout: 5000
      ConnectTimeout: 5000

    Hystrixの構成については、公式の説明があります.
    Default Value
    1000
    Default Property
    hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds
    Instance Property
    hystrix.command.HystrixCommandKey.execution.isolation.thread.timeoutInMilliseconds
    How to Set Instance Default
    HystrixCommandProperties.Setter().withExecutionTimeoutInMilliseconds(int value)
    インスタンス構成でdefaultの代わりにHystrixCommandKeyが表示されます.この値は次のようになります.

    1.異なるインスタンスの構成


    さらに、タイムアウト時間を異なるサービスインスタンスに細分化することもできます.たとえば、次のようになります.
    @FeignClient(
        value = "hello-service",
        fallback = MyFeignClientHystric.class)
    public interface MyFeignClient {
        @RequestMapping("/hello")
        String sayHelloByFeign();
    
        @RequestMapping("/why")
        String sayWhyByFeign();
    }
    hystrix:
      command:
        "MyFeignClient#sayWhyByFeign()":
          execution:
            isolation:
              thread:
                timeoutInMilliseconds: 9000
        default:
          execution:
            isolation:
              thread:
                timeoutInMilliseconds: 2000
    
    ribbon:
      ReadTimeout: 5000
      ConnectTimeout: 5000

    この書き方は、デフォルトのタイムアウト時間を2秒に変更し、別のカスタムFeignクライアントのあるメソッドのタイムアウト時間を9秒に設定します(フォーマットは # ()で、メソッドにパラメータがあれば、パラメータのタイプもつづります).ここでのMyFeignClient#sayWhyByFeign()は、上記のcommandKeyを表していますが、この書き方は、Feignモジュールの特殊なものです.
    ryanjbaxter commented on 26 Jul
    If you had a Feign client called MyClient and it had a method called search that took in a single String parameter than you would use the following propertyhystrix.command.MyClient#search(String).execution.isolation.thread.timeoutInMilliseconds
    issueのSpring Cloudの公式スタッフによると、このフォーマットは彼らが行ったパッケージなので、設定するには、このように書くしかありません.

    Ribbon + Hystrix


    この栗のソースはこちら

    0.デフォルトの基本構成


    Ribbonを使用する場合、Hystrixのタイムアウト時間を設定するだけで有効になります.Ribbonのタイムアウト時間を追加する必要はありません.たとえば、次のようにします.
    hystrix:
      command:
        default:
          execution:
            isolation:
              thread:
                timeoutInMilliseconds: 9000

    1.異なるインスタンスの構成


    サービスタイムアウト時間を細分化したい場合:
    同じサービスインスタンスの異なるインタフェースである場合、異なるタイムアウト時間を使用するには、@HystrixCommandcommandKeyを異なる値として定義し、ymlでそれぞれ設定します.
    @HystrixCommand(
        commandKey = "helloService-sayHello",
        fallbackMethod = "sayHelloDefault")
    public String sayHelloByRibbon() {
        return restTemplate.getForObject("http://HELLO-SERVICE/hello", String.class);
    }
    
    public String sayHelloDefault() {
        return "hello service error, this is default say hello method";
    }
    
    @HystrixCommand(
        commandKey = "helloService-sayWhy",
        fallbackMethod = "sayWhyDefault")
    public String sayWhyByRibbon() {
        return restTemplate.getForObject("http://HELLO-SERVICE/why", String.class);
    }
    
    public String sayWhyDefault() {
        return "hello service error, this is default say why method";
    }
    hystrix:
      command:
        helloService-sayWhy:
          execution:
            isolation:
              thread:
                timeoutInMilliseconds: 5000
        default:
          execution:
            isolation:
              thread:
                timeoutInMilliseconds: 1500

    同じサービスインスタンスの各メソッドのタイムアウト時間を統一的に設定したい場合は、テストにより、異なるメソッドのcommandKeyを同じ値に設定することができ、ymlでキーをタイムアウト構成すると同時に有効になります.
    @HystrixCommand(
        commandKey = "helloService",
        fallbackMethod = "sayHelloDefault")
    public String sayHelloByRibbon() {
        return restTemplate.getForObject("http://HELLO-SERVICE/hello", String.class);
    }
    
    public String sayHelloDefault() {
        return "hello service error, this is default say hello method";
    }
    
    @HystrixCommand(
        commandKey = "helloService",
        fallbackMethod = "sayWhyDefault")
    public String sayWhyByRibbon() {
        return restTemplate.getForObject("http://HELLO-SERVICE/why", String.class);
    }
    
    public String sayWhyDefault() {
        return "hello service error, this is default say why method";
    }
    hystrix:
      command:
        helloService:
          execution:
            isolation:
              thread:
                timeoutInMilliseconds: 5000
        default:
          execution:
            isolation:
              thread:
                timeoutInMilliseconds: 1000

    Zuul


    この栗のソースコードはここを見て、Zuulの中の降格はFallbackProviderを使って、簡単な使用は私のソースコードの中のHelloFallback Providerを見ることができます.JAvaとHiFallbackProvider.JAva、私も公式のドキュメントの説明と例を参考にしました.

    0.デフォルトの基本構成


    zulでタイムアウト時間を設定するには、公式の紹介によると、2つの状況に分けられます.
  • がサービスIdでルーティングする場合、ribbon.ReadTimeoutribbon.SocketTimeout
  • が設定.
  • が指定urlでルーティングを行う場合、zuul.host.connect-timeout-milliszuul.host.socket-timeout-millisを用いる
  • を設定する.
    私のコードではサービスId方式を使用しているので、最初の構成を参照してください.例えば、
    zuul:
      routes:
        helloService:
          path: /hello-service/**
          serviceId: hello-service
        hiService:
          path: /hi-service/**
          serviceId: hi-service
    
    ribbon:
      ConnectTimeout: 5000
      ReadTimeout: 5000

    1.異なるインスタンスの構成


    Ribbonの構成項目にはClientNameを接頭辞(この方法の出典は公式のwiki)として追加することもでき、異なるクライアントの下での構成を区別することができます.このClientNameはserviceIdを直接使って、正常をテストしましたが、どの値を使うべきか、これはまだ公式の説明を見つけていません.
    zuul:
      routes:
        helloService:
          path: /hello-service/**
          serviceId: hello-service
        hiService:
          path: /hi-service/**
          serviceId: hi-service
    
    hello-service:
      ribbon:
        ConnectTimeout: 5000
        ReadTimeout: 5000
    
    hi-service:
      ribbon:
        ConnectTimeout: 500
        ReadTimeout: 500
    
    hystrix:
      command:
        default:
          execution:
            isolation:
              thread:
                timeoutInMilliseconds: 3000

    また、RibbonとHystrixのタイムアウト時間を同時に構成すると、上記の構成ではhi-serviceのインタフェース呼び出しが0.5秒を超えるとタイムアウトがトリガーされるなど、最小の基準でテストを行った.

    まとめ


    現在の学習とテストの結果を見ると、
  • 単純なRibbon+Hystrixを組み合わせて使用する場合、構成は最も柔軟であり、両者は互いに干渉することなく、commandKeyを自由に定義してタイムアウト時間の構成
  • を実現することができる.
  • Feign+Hystrixの組み合わせの場合、FeignはHystrixに必要なcommandKeyをカプセル化しているため、カスタマイズできないため、同じFeignClientでのサービスインタフェースの便利な統一構成ができず、対応するビジネスニーズがあれば、特殊なインタフェースごとに独立したタイムアウト構成(新しい方法が見つかれば更新)
  • しかできないかもしれません.
  • Zuul+Hystrixを組み合わせる場合、上記の場合とは逆に、異なるサービスインスタンスに対して異なるタイムアウト構成を行うことができるが、サービス下の具体的なインタフェース方法
  • に細分化することはできない.

    広告を出す


    記事は、個人ブログ『Zuul、Ribbon、Feign、Hystrix使用時のタイムアウト時間設定の問題』に初登場