SpringCloudマイクロサービスZuulゲートウェイ動的ルーティング
8184 ワード
SpringCloudマイクロサービスZuulゲートウェイ動的ルーティング zul動的ルーティング 1. ゲートウェイ層動的構成ルーティングマッピング規則 2. 同じリクエストをカスタムルールに従って、異なるサービスにルーティングする FeignClient動的要求 実現機能 実現構想 ビジネスコード まとめ この文章は普通のダイナミックルーティングだけでなく、zulゲートウェイを静的ルーティングからダイナミックルーティングにアップグレードしたり、ルーティング後、カスタムルールを利用して同じURL要求を実現してユーザー(または他の属性)に基づいて異なるサービスにアクセスしたりすることができます.
私の会社は半アウトソーシングの会社で、製品を作りたいですが、異なるお客様のニーズを満たしなければなりません.マイクロサービスを使用してすべてのビジネスモジュールを分割すると、各ビジネスモジュールは顧客によって異なるシーンがある可能性があります.フロントエンドリクエストとバックエンドサービス間の相互呼び出しでは、モジュールにビジネスシーンが追加されたため、コードを書き換えたり変更したりすることはできません.そこで、同じモジュールのすべてのシーンが同じURLでリクエストできるかどうか、お客様によって異なるサービスのインタフェースをリクエストできるかどうかを考えます.これにより、この2つのダイナミックルーティングとシーン選択が可能になります.
ソースコードはここにあります:ダイナミックルーティングソースコード、このプロジェクトは私のマイクロサービス足場プロジェクトで、eureka-zulに基づいて構築されています.
zulダイナミックルーティング
1.ゲートウェイ層動的構成ルーティングマッピング規則
動的構成は、
コードは次のとおりです.
カスタムルーティングルールのロードが完了したら、Beanを作成し、Springに管理してもらいます.
ZuulPropertiesはzulフレームワークに対応するBeanを作成しました.ここでは注入するだけで、これ以上作成する必要はありません.
2.同じ要求をカスタムルールに従って、異なるサービスにルーティングする
この考え方は、zulルーティングは、filterTypeがrouteのフィルタである後に実現され、実際には、最初のfilterに入る前に、要求コンテキスト
ここでは、このカスタムルーティングフィルタの位置を置くことが重要です.前処理要求パラメータやユーザー情報認証などのfilterがあれば、このfilterを後ろに置いてfilterOrderの値を構成すればいいというヒントがあります.
FeignClient動的要求
実装機能
FeignClientのリクエストは、お客様の情報に基づいて、異なるサービスに送信する必要があります.
例えば、顧客C 1-C 3、注文サービスO 1-O 3、商品サービスP.お客様は同じ商品サービスにアクセスし、商品サービスの1つのインタフェースが直接注文を作成し、要求インタフェースは/service-order/createです.現在、C 1はO 1のみ、C 2はO 2のみ、C 3はO 3のみとなっており、サービスPを変更することなく、この業務処理を行う必要がある.
実現構想.
構想は概ねzul層修正要求ルーティング経路と同様であり,要求に対する修正を達成するためにserviceIdを修正する.FeignClientのデフォルトは
ビジネスコード
LoadBalancerFeignClientを継承し、executeメソッドを書き換えればよい、最後にsuperを呼び出す.execute()でリクエストを行います.
ここで,コンストラクタがパラメトリックコンストラクタを含むため,Beanを作成する際には,この3つのパラメータを注入する必要がある.
Beanプロファイルを作成するには、次の手順に従います.
まとめ
これにより,動的ルーティングとリクエストが全体的に実現される.ソースコードを読むと、欲しいものを簡単に見つけることができます.
私の会社は半アウトソーシングの会社で、製品を作りたいですが、異なるお客様のニーズを満たしなければなりません.マイクロサービスを使用してすべてのビジネスモジュールを分割すると、各ビジネスモジュールは顧客によって異なるシーンがある可能性があります.フロントエンドリクエストとバックエンドサービス間の相互呼び出しでは、モジュールにビジネスシーンが追加されたため、コードを書き換えたり変更したりすることはできません.そこで、同じモジュールのすべてのシーンが同じURLでリクエストできるかどうか、お客様によって異なるサービスのインタフェースをリクエストできるかどうかを考えます.これにより、この2つのダイナミックルーティングとシーン選択が可能になります.
ソースコードはここにあります:ダイナミックルーティングソースコード、このプロジェクトは私のマイクロサービス足場プロジェクトで、eureka-zulに基づいて構築されています.
zulダイナミックルーティング
1.ゲートウェイ層動的構成ルーティングマッピング規則
動的構成は、
org.springframework.cloud.netflix.zuul.filters.SimpleRouteLocator
書き換えlocateRoutes
メソッドを継承し、org.springframework.cloud.netflix.zuul.filters.RefreshableRouteLocator
インタフェースを実現するrefresh
メソッドと同様である.SimpleRouteLocator
はzulベースルーティングロードクラスであり、初期化時に自動的にプロファイル内の構成されたルーティングルールをメモリにロードし、locateRoutes
メソッドを書き換えてルーティングルール構成をカスタムソースに変更する.RefreshableRouteLocator
インタフェースは、ルーティングテーブルをリフレッシュする方法のみを提供し、実現は簡単である.コードは次のとおりです.
/**
*
* @author
* @date 2018/11/15 22:05
*/
public class DynamicRouteLocator extends SimpleRouteLocator implements RefreshableRouteLocator {
/**
* 。
* :saas.routes.dynamic.enabled, false
*/
private boolean enabled;
public DynamicRouteLocator(boolean enabled, String servletPath, ZuulProperties properties) {
super(servletPath, properties);
this.enabled = enabled;
}
/**
*
*/
@Override
protected Map locateRoutes() {
if (!enabled) {
return super.locateRoutes();
}
Map routeMap = new HashMap<>();
//
//
String path = "/log/**";
String serviceId = "service-log";
// ,
if (StringUtil.isBlank(path) || StringUtil.isBlank(serviceId)) {
return super.locateRoutes();
}
// ZuulRoute
ZuulProperties.ZuulRoute zuulRoute = createZuulRoute(path, serviceId);
routeMap.put(path, zuulRoute);
String path1 = "/basedata/**";
String serviceId2 = "service-basedata";
ZuulProperties.ZuulRoute zuulRoute1 = createZuulRoute(path1, serviceId2);
routeMap.put(path1, zuulRoute1);
return routeMap;
}
/**
*
*/
@Override
public void refresh() {
super.doRefresh();
}
public boolean getEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
/**
* ZuulRoute
* @param path
* @param serviceId Id
*/
private ZuulProperties.ZuulRoute createZuulRoute(String path, String serviceId) {
ZuulProperties.ZuulRoute zuulRoute = new ZuulProperties.ZuulRoute();
zuulRoute.setId(path);
zuulRoute.setPath(path);
zuulRoute.setServiceId(serviceId);
return zuulRoute;
}
}
カスタムルーティングルールのロードが完了したら、Beanを作成し、Springに管理してもらいます.
/**
*
* @author: Overload
* @review:
* @date: 2018/11/22 9:29
*/
@Configuration
public class DynamicRouteConfig {
@Value("${saas.routes.dynamic.enabled}")
private boolean enabledDynamicRoute;
/**
*
*/
@Bean
public SimpleRouteLocator routeLocator(ZuulProperties zuulProperties) {
return new DynamicRouteLocator(enabledDynamicRoute, zuulProperties.getPrefix(), zuulProperties);
}
}
ZuulPropertiesはzulフレームワークに対応するBeanを作成しました.ここでは注入するだけで、これ以上作成する必要はありません.
2.同じ要求をカスタムルールに従って、異なるサービスにルーティングする
この考え方は、zulルーティングは、filterTypeがrouteのフィルタである後に実現され、実際には、最初のfilterに入る前に、要求コンテキスト
RequestContext
のFilterConstants.SERVICE_ID_KEY
が設定されている(具体的には1.の構成に従って設定されている).ここではこのSERVICEを置き換えるだけですID_KEYはルールマッチング後の値をカスタマイズすればいいです.ここでは、このカスタムルーティングフィルタの位置を置くことが重要です.前処理要求パラメータやユーザー情報認証などのfilterがあれば、このfilterを後ろに置いてfilterOrderの値を構成すればいいというヒントがあります.
/**
* 。
* , serviceId
, {@link FilterConstants#SERVICE_ID_KEY} 。
* {@link PreDecorationFilter} ,
* PreDecorationFilter
serviceId
。
* PreDecorationFilter
, PreDecorationFilter
。 PreDecorationFilter
。
* @author
* @date 2018/11/23 23:40
*/
@Slf4j
@Component
public class SceneSelectorFilter extends ZuulFilter {
@Override
public String filterType() {
return FilterConstants.PRE_TYPE;
}
/**
* PreDecorationFilter
*/
@Override
public int filterOrder() {
return FilterConstants.PRE_DECORATION_FILTER_ORDER + 1;
}
/**
*
*/
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() throws ZuulException {
//
RequestContext currentContext = RequestContext.getCurrentContext();
// URI
String uri = currentContext.getRequest().getRequestURI();
//
String serviceName = RequestUtil.matchServiceName(uri);
//
// serviceName user.companyId
// serviceId
currentContext.set(FilterConstants.SERVICE_ID_KEY, "service-basedata");
return null;
}
}
FeignClient動的要求
実装機能
FeignClientのリクエストは、お客様の情報に基づいて、異なるサービスに送信する必要があります.
例えば、顧客C 1-C 3、注文サービスO 1-O 3、商品サービスP.お客様は同じ商品サービスにアクセスし、商品サービスの1つのインタフェースが直接注文を作成し、要求インタフェースは/service-order/createです.現在、C 1はO 1のみ、C 2はO 2のみ、C 3はO 3のみとなっており、サービスPを変更することなく、この業務処理を行う必要がある.
実現構想.
構想は概ねzul層修正要求ルーティング経路と同様であり,要求に対する修正を達成するためにserviceIdを修正する.FeignClientのデフォルトは
org.springframework.cloud.openfeign.ribbon.LoadBalancerFeignClient
を使用してFeignClientリクエスト処理を行います.execute
の方法には2つのパラメータがあります.必要なのはfeign.Request
というパラメータです.中の対応するURLのサービスIdをカスタムルールが一致するサービスIdに置き換えればいいです.ビジネスコード
LoadBalancerFeignClientを継承し、executeメソッドを書き換えればよい、最後にsuperを呼び出す.execute()でリクエストを行います.
/**
* FeignClient
* @author
* @date 2018/11/27 22:49
*/
public class DynamicRouteFeignClient extends LoadBalancerFeignClient {
public DynamicRouteFeignClient(Client delegate, CachingSpringLoadBalancerFactory lbClientFactory, SpringClientFactory clientFactory) {
super(delegate, lbClientFactory, clientFactory);
}
/**
* , 。
* URL
*/
@Override
public Response execute(Request request, Request.Options options) throws IOException {
/*
URL
:http://service-log/operation/remote/listByTypeAndId?mappingType=asd&mappingId=12&companyId=11
*/
String url = request.url();
// serviceId
String serviceId = StringUtil.urlServiceId(url);
//
// , , return
//TODO serivceId
String nServiceId = "";
// URL serviceId serviceId
String newUrl = StringUtil.changeServiceId(url, nServiceId);
//
Request newRequest = Request.create(request.method(), newUrl, request.headers(), request.body(), request.charset());
//
return super.execute(newRequest, options);
}
}
ここで,コンストラクタがパラメトリックコンストラクタを含むため,Beanを作成する際には,この3つのパラメータを注入する必要がある.
CachingSpringLoadBalancerFactory cachingFactory
とSpringClientFactory clientFactory
はfeignフレームワークでBeanと宣言されていますが、@ConditionalOnMissingBean
注釈を使用しているだけで、IDEAのようなエディタが対応するBeanが見つからないことを示す可能性がありますが、関係なく自動的に注入できます.Beanプロファイルを作成するには、次の手順に従います.
/**
* @author
* @date 2018/11/27 23:38
*/
@Configuration
public class DynamicRouteFeignConfig {
@Bean
public Client feignClient(CachingSpringLoadBalancerFactory cachingFactory, SpringClientFactory clientFactory) {
return new DynamicRouteFeignClient(new Client.Default(null, null), cachingFactory, clientFactory);
}
}
まとめ
これにより,動的ルーティングとリクエストが全体的に実現される.ソースコードを読むと、欲しいものを簡単に見つけることができます.