ハリネズミ(マラソン)をヘビ(春の雲)と交差させます。 エピソード2

最初のエピソードでは、 Mesos MarathonからSpring Cloudビンに直接情報をプルしました。 同時に、最初の問題もありましたが、そのうちの1つをストーリーの現在の部分で分析します。 マラソン接続構成を思い出してみましょう。







spring: cloud: marathon: scheme: http #url scheme host: marathon #marathon host port: 8080 #marathon port
      
      





ここでどのような問題が見られますか? まず、接続する際に許可がありません。これは、産業用としては奇妙です。 2番目-1つのホストとポートのみを指定できます。 原則として、複数のマスターを1つのバランサーまたはDNSにプッシュしようとすることは可能ですが、この追加の障害点を回避したいと思います。 その方法は猫の下に書かれています。







頭上のパスワード



利用可能な2つの承認スキームがあります: BasicTokenです。 基本承認は非常に一般的であるため、ほとんどすべての開発者がこれを満たしています。 その本質は非常にシンプルです。 ユーザー名とパスワードを取得します。 それらを通して接着し:



Base64でエンコードします。 値Basic <Base64>



Authorization



ヘッダーを追加します。 利益







トークンはもう少し複雑です。 オープンソースの実装では利用できないため、この方法はDC / OSを使用する人に適しています。 これを行うには、わずかに異なる認証ヘッダーを追加するだけです:







 Authorization: token=<auth_token>
      
      





したがって、構成に必要ないくつかのプロパティを追加できます。







 spring: cloud: marathon: ... token: dcos_acs_token username: marathon password: mesos
      
      





そして、単純な優先順位に導かれます。 トークンが指定されている場合、それを取得します。 それ以外の場合は、ユーザー名とパスワードを取得して基本的な認証を行います。 さて、両方がない場合、「裸の」クライアントを作成します。







 Feign.Builder builder = Feign.builder() .encoder(new GsonEncoder(ModelUtils.GSON)) .decoder(new GsonDecoder(ModelUtils.GSON)) .errorDecoder(new MarathonErrorDecoder()); if (!StringUtils.isEmpty(token)) { builder.requestInterceptor(new TokenAuthRequestInterceptor(token)); } else if (!StringUtils.isEmpty(username)) { builder.requestInterceptor(new BasicAuthRequestInterceptor(username,password)); } builder.requestInterceptor(new MarathonHeadersInterceptor()); return builder.target(Marathon.class, baseEndpoint);
      
      





MarathonのクライアントFeign httpクライアントを使用して実装され、 インターセプターを簡単に追加できます。 私たちの場合、必要なhttpヘッダーをリクエストに追加します。 その後、 ビルダーは 、可能なリクエストが宣言的に宣言されているインターフェイス上にオブジェクトを構築します。







 public interface Marathon { // Apps @RequestLine("GET /v2/apps") GetAppsResponse getApps() throws MarathonException; //Other methods }
      
      





ウォームアップは終了しましたので、今度はもっと難しいタスクに取りかかりましょう。







フェイルオーバークライアント



Mesos -aおよびMarathon -aの産業用インストールを展開した場合、データを読み取ることができるマスターの数は複数になります。 さらに、一部のマスターが誤って使用できなくなったり、速度が低下したり、アップグレードが可能になったりする場合があります。 情報の取得に失敗すると、クライアントに関する情報が陳腐化するため、ある時点でミルクショットが発生します。 または、アプリケーションソフトウェアを更新するときに、インスタンスのリストをまったく受け取らず、クライアントへのサービスを拒否するとします。 これはすべて良くありません。 リクエストのクライアントバランシングが必要です。







リボンは、 Spring Cloud内のリクエストのクライアントバランシングで使用されるため、このロールの候補として選択する必要があるのは論理的です。 次のエピソードでは、クエリバランシング戦略について詳しく説明しますが、現時点では、問題を解決するために必要な最も基本的な機能に限定します。







最初に行う必要があるのは、 偽のクライアントにバランサーを実装することです。







 Feign.Builder builder = Feign.builder() .client(RibbonClient.builder().lbClientFactory(new MarathonLBClientFactory()).build()) ...;
      
      





コードを見ると、論理的な疑問が生じます。 lbClientFactoryとは何ですか。なぜ独自の処理を行うのですか? 要するに、このファクトリはクライアントリクエストバランサを設計しています。 デフォルトでは、作成されたクライアントには必要な機能が1つしかありません。最初のリクエストで問題が発生した場合のリクエストの繰り返しです。 retryを可能にするために、オブジェクトを構築するときに追加します:







 public static class MarathonLBClientFactory implements LBClientFactory { @Override public LBClient create(String clientName) { LBClient client = new LBClientFactory.Default().create(clientName); IClientConfig config = ClientFactory.getNamedConfig(clientName); client.setRetryHandler(new DefaultLoadBalancerRetryHandler(config)); return client; } }
      
      





リトライハンドラにDefaultプレフィックスが付いていることを恐れないでください。 内部には必要なものがすべて揃っています。 ここで、これらすべての構成の問題について説明します。







アプリケーションには複数のクライアントが存在する可能性があり、 Marathonのクライアントはそのうちの1つにすぎないため、設定には特定の形式のパターンがあります。







 client_name.ribbon.property_name
      
      





私たちの場合:







 marathon.ribbon.property_name
      
      





クライアントバランサーのすべてのプロパティは、構成マネージャーArchariusに保存されます。 この場合、これらの設定はオンザフライで追加されるため、メモリに保存されます。 これを行うには、変更したクライアントで、ヘルパーメソッドsetMarathonRibbonProperty



追加します。その中にプロパティ値を設定します。







 ConfigurationManager.getConfigInstance().setProperty(MARATHON_SERVICE_ID_RIBBON_PREFIX + suffix, value);
      
      





偽のクライアントを作成する前に、これらの設定を初期化する必要があります。







 setMarathonRibbonProperty("listOfServers", listOfServers); setMarathonRibbonProperty("OkToRetryOnAllOperations", Boolean.TRUE.toString()); setMarathonRibbonProperty("MaxAutoRetriesNextServer", 2); setMarathonRibbonProperty("ConnectTimeout", 100); setMarathonRibbonProperty("ReadTimeout", 300);
      
      





ここで興味深いのは。 最初はlistOfServers



です。 実際、これは、可能なすべてのhost:port



列挙です。Marathonマスターが配置されているポートペアは、カンマで区切られています。 この場合、構成でそれらを指定する機能を追加するだけです。







 spring: cloud: marathon: ... listOfServers: m1:8080,m2:8080,m3:8080
      
      





これで、ウィザードに対する新しい要求はそれぞれ、これら3つのサーバーのいずれかに送信されます。







再試行するには、 OkToRetryOnAllOperations



の値をtrue



設定する必要がありtrue









繰り返しの最大数は、 MaxAutoRetriesNextServer



オプションを使用して設定されます。 なぜNextServerの表示があるのですか? すべてがシンプルです。 MaxAutoRetries



オプションもあります。これは、最初のサーバー(最初の要求に対して選択されたサーバー)を再度呼び出す必要がある回数を示します。 デフォルトでは、このプロパティは0



設定されてい0



。 つまり、最初の失敗の後、次の候補のデータを要求します。 MaxAutoRetriesNextServer



は、試行回数から最初のサーバーにデータを要求する試行回数を引いた値を示していることも覚えてMaxAutoRetriesNextServer



があります。







さて、無期限に回線にハングアップしないように、 ConnectTimeout



プロパティとReadTimeout



プロパティを適切な制限内に設定してください。







合計



この部分では、 Marathonのクライアントをよりカスタマイズ可能でフォールトトレラントにしました。 さらに、既成のソリューションを使用して、あまり多くの庭をフェンスで囲む必要はありませんでした。 しかし、バレエの最も興味深い部分、つまりアプリケーションソフトウェアのクライアント側クエリバランシングがまだないため、作業を完了するにはまだ程遠いです。







続く




All Articles