1

私は2つのAWS Beanstalk envを作成しました。それぞれに独自のバージョンのアプリケーションがあります。これらのURLのURLはhttps://beta.myserver.com/v1073https://beta.myserver.com/v1084です。これらのURLは、ロードバランサを指します。Spring Cloudでプログラム的にルートを設定するNetflix Zuul

私は以下の設定を持つZuulの実装もあります。

zuul: 
     routes: 
     beta: 
      path: /api/** 
      serviceId: beta-root 
      strip-prefix: false 
      sensitive-headers: Cookie,Set-Cookie 

    ribbon: 
     eureka: 
     enabled: false 

    hystrix: 
     command: 
     default: 
      execution: 
      isolation: 
       thread: 
       timeoutInMilliseconds: 5000 

    beta-root: 
     ribbon: 
     listOfServers: https://beta.myserver.com 

私のアプリケーションのリクエストにはバージョンヘッダーが必要です。私はこのヘッダ値を検査するZuul "pre"フィルタを持っています。目標はヘッダー値に基づいて要求をルーティングすることです。

リクエストを傍受できましたが、フィルタからルーティングできませんでした。コードスニペットは次のとおりです。コードを実行した後、要求はまだhttps://beta.myserver.com/api/ ...

@Override 
public Object run() { 
    /* Logic to get version header etc */ 

    /* Set the new route */ 
    Map<String, ZuulRoute> routes = zuulProps.getRoutes(); 
    ZuulRoute currentRoute = routes.get("beta-root"); 
    currentRoute.setLocation("https://beta.myserver.com/v1073"); 

    /* Refresh the route */ 
    routeLocator.getRoutes(); 

    logger.warn("Current Route:" + currentRoute.getLocation()); 
    return null; 
} 

にこの問題を解決する方法の任意の提案を行くことにしようか?

答えて

1

実際に行う必要があるのは、requestURIを変更することです。サーバーの場所は変更しないでください。以下のように簡単に行うことができます。

まず、フィルタのオーダーは、ダルストンのリリースで現在5であるPreDecorationFilterのオーダーより大きくする必要があります。 (使用しているリリースの値を確認する必要があります)。 PreDecorationFilterは、リクエストヘッダーを処理し、必要な情報をRequestContextに入力します。このRequestContextは、リクエストの実際のURLを定義するために使用されます。 requestURIは、変更が必要なキーです。あなたの場合、ヘッダーに基づいてrequestURIを追加または変更できます。以下は、プレフィルターのスニペットです。

@Override 
public int filterOrder() { 
    return 6; 
} 

@Override 
public Object run() { 
    RequestContext ctx = RequestContext.getCurrentContext(); 
    // override request URI 
    ctx.set("requestURI", "/v1073" + ctx.get("requestURI")); 
    return null; 
} 

オリジナルの実装にはいくつか問題があるようです。まず、ZuulPropertiesルートの場所を変更しようとしています。このオブジェクトはすべての要求で共有されます。特定の要求に対してのみ変更すると、異なるヘッダーを持つ可能性がある別の要求が間違った場所にルーティングされる可能性があります。

次に、ロケーションプロパティをZuulRouteオブジェクトに設定しています(下のように)。

currentRoute.setLocation("https://beta.myserver.com/v1073"); 

もともとの場所のプロパティの値は、あなたのサービスIDである - beta-root - あなたの設定で。 'http'または 'https prefix, original RibbonRoutingFilter will not work. Instead, SimpleRoutingHostFilter will process your request. It means that your not-modified requests will be handled by RibbonRoutingFilter and modified requests will be handled by SimpleHostRoutingFilter`を持つ特定のURLを使用してURLを変更すると、


更新:ルート別のホストへのHTTPヘッダーに基づいて

あなたがHTTPヘッダーに基づいて、別のホストへのルートにしたい場合は、それを行うには、いくつかの方法があります。

ケース1:

あなたはリボン(およびRibbonRoutingFilter)を使用している場合は、以下の機能のみエッジウェア上で動作します。SR1およびそれ以降のバージョン。 Eddware.SR1から、FilterConstants.LOAD_BALANCER_KEYというロードバランサの指定値をRequestContextに入れることができます。この値は、リボンロードバランサに渡されます。プレフィルターに任意の値(任意のオブジェクト)を入れることができます。特別なhttpヘッダーに基づいてルートを変更する場合は、カスタム・プレフィルターで変更することができます。 リボン用に独自のIRule実装を定義します。 IRuleの実装にはLOAD_BALANCER_KEYが与えられます。したがって、設定したLOAD_BALANCER_KEYの値に基づいて、リボンが持つサーバーのリストから特定のサーバーを選択できます。

簡単な文書hereがあります。

the test case in PRのサンプルコードがあります。 (RibbonRoutingFilterLoadBalancerKeyIntegrationTests.java)

ケース2:あなたはzuulのルートプロパティでurlの代わりserviceIdを指定する場合は(リボンなし)SimpleHostRoutingFilterに

を使用している場合、要求はリボンなしSimpleHostRoutingFilterによってルーティングされます。

SimpleHostRoutingFilterは、すぐ下のコード

RequestContext.getCurrentContext().getRouteHost(); 

この値はPreDecorationFilterによって設定されたことにより、ホストアドレスを使用します。したがって、この情報をプレフィルタで変更することができます。

  1. PreDecorationFilterとSimpleHostRoutingFilterの間の順序値を持つ独自のカスタムプレフィルタを作成します。
  2. フィルタの内部で、ルートホストをチェックします。 HTTPヘッダーに基づいて変更する既知のホストの場合は、Httpヘッダーに基づいてRequestContext.getCurrentContext().setRouteHost経由でルートホストを変更します。

2番目のアプローチの場合、私は自分でそれをやろうとしませんでした。私が考える理論的な解決策です。 2番目の方法の問題は、SimpleHostRoutingFilterを使用していることです。 SimpleHostRoutingFilterは要求に対してHystrixCommandを作成しないため、Zuul内のHystrixによって提供されるサーキットブレーカ機能は使用できません。あなたがEdgwareのリリースを使用している場合、私が思うように、最初のアプローチが優れています。

+0

ありがとう@ yonsung.yoon。私たちは今envを設定しています。テストの後に私はさらにコメントを追加します – bostonjava

+0

上記のアプローチを試しました。それはうまくいくだろうが、私の解決策は変わった。私たちはBeanStalkを使用しており、各バージョンは不変のインスタンスにデプロイされているため、同じサーバーに2つのコンテキストを持つ代わりに、アプリケーションのバージョンが異なる2つのサーバーがあります。たとえば、https://beta.v1.myserver.comおよびhttps://beta.v2.myserver.comです。コード内でserviceIdが指し示す場所を更新するにはどうすればよいですか? – bostonjava

+1

@ yongsung.yoon答えを見つけましたか?我々は同様の問題があります。私たちはリダイレクトする必要のあるヘッダ値に基づいてbrand1.server.comとbrand2.server.comを持っています。しかし、再び特定の要求のみ。グローバルではありません –

関連する問題