日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

让 Ocelot 与 asp.net core “共存”

發布時間:2023/12/4 asp.net 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 让 Ocelot 与 asp.net core “共存” 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Intro

我們的 API 之前是一個單體應用,各個模塊的服務是通過 Assembly 集成在一起,最后部署在一個 web server 下的。

我們已經在拆分服務并且在 Ocelot 的基礎上封裝了我們自己的網關,但是服務還沒有完全拆分,于是有這么一個需求,對于 Ocelot 配置的路由去交給 Ocelot 去轉發到真正的服務地址,而那些 Ocelot 沒有定義的路由則讓交給 AspNetCore 去處理。

實現原理

實現原理是讓 Ocelot 作為一個動態分支路由,只有當 Ocelot 配置了對應路由的下游地址才走 Ocelot 的分支,才把請求交給 Ocelot 處理。

我們可以使用 MapWhen 來處理,接下來就需要知道怎么樣判斷 Ocelot 是否配置了某一個路由,Ocelot 內部的處理管道,在向下游請求之前是要找到對應匹配的下游路由,所以我們去看一看 Ocelot 的源碼,看看 Ocelot 內部是怎么找下游路由的,Ocelot 找下游路由中間件源碼

  • public async Task Invoke(DownstreamContext context)

  • {

  • var upstreamUrlPath = context.HttpContext.Request.Path.ToString();


  • var upstreamQueryString = context.HttpContext.Request.QueryString.ToString();


  • var upstreamHost = context.HttpContext.Request.Headers["Host"];


  • Logger.LogDebug($"Upstream url path is {upstreamUrlPath}");


  • var provider = _factory.Get(context.Configuration);


  • // 獲取下游路由

  • var downstreamRoute = provider.Get(upstreamUrlPath, upstreamQueryString, context.HttpContext.Request.Method, context.Configuration, upstreamHost);


  • if (downstreamRoute.IsError)

  • {

  • Logger.LogWarning($"{MiddlewareName} setting pipeline errors. IDownstreamRouteFinder returned {downstreamRoute.Errors.ToErrorString()}");


  • SetPipelineError(context, downstreamRoute.Errors);

  • return;

  • }


  • var downstreamPathTemplates = string.Join(", ", downstreamRoute.Data.ReRoute.DownstreamReRoute.Select(r => r.DownstreamPathTemplate.Value));


  • Logger.LogDebug($"downstream templates are {downstreamPathTemplates}");


  • context.TemplatePlaceholderNameAndValues = downstreamRoute.Data.TemplatePlaceholderNameAndValues;


  • await _multiplexer.Multiplex(context, downstreamRoute.Data.ReRoute, _next);

  • }

  • 通過上面的源碼,我們就可以判斷 Ocelot 是否有與請求相匹配的下游路由信息

    實現

    既然找到了 Ocelot 如何找下游路由,就先給 Ocelot 加一個擴展吧,實現代碼如下,Ocelot 擴展完整代碼

  • public static IApplicationBuilder UseOcelotWhenRouteMatch(this IApplicationBuilder app,

  • Action<IOcelotPipelineBuilder, OcelotPipelineConfiguration> builderAction)

  • => UseOcelotWhenRouteMatch(app, builderAction, new OcelotPipelineConfiguration());


  • public static IApplicationBuilder UseOcelotWhenRouteMatch(this IApplicationBuilder app,

  • Action<OcelotPipelineConfiguration> pipelineConfigurationAction,

  • Action<IOcelotPipelineBuilder, OcelotPipelineConfiguration> builderAction)

  • {

  • var pipelineConfiguration = new OcelotPipelineConfiguration();

  • pipelineConfigurationAction?.Invoke(pipelineConfiguration);

  • return UseOcelotWhenRouteMatch(app, builderAction, pipelineConfiguration);

  • }


  • public static IApplicationBuilder UseOcelotWhenRouteMatch(this IApplicationBuilder app, Action<IOcelotPipelineBuilder, OcelotPipelineConfiguration> builderAction, OcelotPipelineConfiguration configuration)

  • {

  • app.MapWhen(context =>

  • {

  • // 獲取 OcelotConfiguration

  • var internalConfigurationResponse =

  • context.RequestServices.GetRequiredService<IInternalConfigurationRepository>().Get();

  • if (internalConfigurationResponse.IsError || internalConfigurationResponse.Data.ReRoutes.Count == 0)

  • {

  • // 如果沒有配置路由信息,不符合分支路由的條件,直接退出

  • return false;

  • }


  • var internalConfiguration = internalConfigurationResponse.Data;

  • var downstreamRouteFinder = context.RequestServices

  • .GetRequiredService<IDownstreamRouteProviderFactory>()

  • .Get(internalConfiguration);

  • // 根據請求以及上面獲取的Ocelot配置獲取下游路由

  • var response = downstreamRouteFinder.Get(context.Request.Path, context.Request.QueryString.ToString(),

  • context.Request.Method, internalConfiguration, context.Request.Host.ToString());

  • // 如果有匹配路由則滿足該分支路由的條件,交給 Ocelot 處理

  • return !response.IsError

  • && !string.IsNullOrEmpty(response.Data?.ReRoute?.DownstreamReRoute?.FirstOrDefault()

  • ?.DownstreamScheme);

  • }, appBuilder => appBuilder.UseOcelot(builderAction, configuration).Wait());


  • return app;

  • }

  • 使用

    在 Startup 里

    ConfigurationServices 配置 mvc 和 Ocelot

    Configure 方法里配置 ocelot 和 mvc

  • app.UseOcelotWhenRouteMatch((ocelotBuilder, pipelineConfiguration) =>

  • {

  • // This is registered to catch any global exceptions that are not handled

  • // It also sets the Request Id if anything is set globally

  • ocelotBuilder.UseExceptionHandlerMiddleware();

  • // This is registered first so it can catch any errors and issue an appropriate response

  • ocelotBuilder.UseResponderMiddleware();

  • ocelotBuilder.UseDownstreamRouteFinderMiddleware();

  • ocelotBuilder.UseDownstreamRequestInitialiser();

  • ocelotBuilder.UseRequestIdMiddleware();

  • ocelotBuilder.UseMiddleware<ClaimsToHeadersMiddleware>();

  • ocelotBuilder.UseLoadBalancingMiddleware();

  • ocelotBuilder.UseDownstreamUrlCreatorMiddleware();

  • ocelotBuilder.UseOutputCacheMiddleware();

  • ocelotBuilder.UseMiddleware<HttpRequesterMiddleware>();

  • // cors headers

  • ocelotBuilder.UseMiddleware<CorsMiddleware>();

  • });


  • app.UseMvc();

  • 新建一個 TestController

  • [Route("/api/[controller]")]

  • public class TestController : ControllerBase

  • {

  • public IActionResult Get()

  • {

  • return Ok(new

  • {

  • Tick = DateTime.UtcNow.Ticks,

  • Msg = "Hello Ocelot",

  • });

  • }

  • }

  • 具體代碼可以參考這個 網關示例項目

    示例項目的 Ocelot 配置是存在 Redis 里面的,配置的 ReRoutes 如下:

  • {

  • "ReRoutes": [

  • {

  • "DownstreamPathTemplate": "/api.php?key=free&appid=0&msg={everything}",

  • "UpstreamPathTemplate": "/api/chat/{everything}",

  • "UpstreamHttpMethod": [

  • "Get",

  • "POST",

  • "PUT",

  • "PATCH",

  • "DELETE",

  • "OPTIONS"

  • ],

  • "AddHeadersToRequest": {

  • },

  • "RequestIdKey": "RequestId",

  • "ReRouteIsCaseSensitive": false,

  • "ServiceName": "",

  • "DownstreamScheme": "http",

  • "DownstreamHostAndPorts": [

  • {

  • "Host": "api.qingyunke.com",

  • "Port": 80

  • }

  • ],

  • "DangerousAcceptAnyServerCertificateValidator": false

  • }

  • ],

  • "GlobalConfiguration": {

  • "HttpHandlerOptions": {

  • "AllowAutoRedirect": false,

  • "UseCookieContainer": false,

  • "UseTracing": false

  • }

  • }

  • }

  • 運行項目進行測試:

    訪問 Ocelot 定義的路由 http://localhost:65125/api/chat/hello ,返回信息如圖所示:

    訪問 Mvc 定義的路由 http://localhost:65125/api/test,返回信息如圖所示:

    上面正常的返回就表示我們的 Ocelot 和 Mvc 同時工作了~

    Reference

    • https://github.com/ThreeMammals/Ocelot

    • https://github.com/WeihanLi/AspNetCorePlayground/tree/master/TestGateway


    總結

    以上是生活随笔為你收集整理的让 Ocelot 与 asp.net core “共存”的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。