SpringCloudマイクロサービスZuulゲートウェイ動的ルーティング


SpringCloudマイクロサービスZuulゲートウェイ動的ルーティング
  • zul動的ルーティング
  • 1. ゲートウェイ層動的構成ルーティングマッピング規則
  • 2. 同じリクエストをカスタムルールに従って、異なるサービスにルーティングする
  • FeignClient動的要求
  • 実現機能
  • 実現構想
  • ビジネスコード
  • まとめ
  • この文章は普通のダイナミックルーティングだけでなく、zulゲートウェイを静的ルーティングからダイナミックルーティングにアップグレードしたり、ルーティング後、カスタムルールを利用して同じURL要求を実現してユーザー(または他の属性)に基づいて異なるサービスにアクセスしたりすることができます.
    私の会社は半アウトソーシングの会社で、製品を作りたいですが、異なるお客様のニーズを満たしなければなりません.マイクロサービスを使用してすべてのビジネスモジュールを分割すると、各ビジネスモジュールは顧客によって異なるシーンがある可能性があります.フロントエンドリクエストとバックエンドサービス間の相互呼び出しでは、モジュールにビジネスシーンが追加されたため、コードを書き換えたり変更したりすることはできません.そこで、同じモジュールのすべてのシーンが同じ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に入る前に、要求コンテキストRequestContextFilterConstants.SERVICE_ID_KEYが設定されている(具体的には1.の構成に従って設定されている).ここではこのSERVICEを置き換えるだけですID_KEYはルールマッチング後の値をカスタマイズすればいいです.
    ここでは、このカスタムルーティングフィルタの位置を置くことが重要です.前処理要求パラメータやユーザー情報認証などのfilterがあれば、このfilterを後ろに置いてfilterOrderの値を構成すればいいというヒントがあります.
    /**
     * 

    *

    serviceId , {@link FilterConstants#SERVICE_ID_KEY} 。

    *

    {@link PreDecorationFilter} , * PreDecorationFilter serviceId

    *

    PreDecorationFilterPreDecorationFilterPreDecorationFilter

    * @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 cachingFactorySpringClientFactory 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);
    	}
    }
    

    まとめ
    これにより,動的ルーティングとリクエストが全体的に実現される.ソースコードを読むと、欲しいものを簡単に見つけることができます.