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

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > asp.net >内容正文

asp.net

让 Ocelot 与 asp.net core “共存”

發(fā)布時(shí)間:2023/12/4 asp.net 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 让 Ocelot 与 asp.net core “共存” 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Intro

我們的 API 之前是一個(gè)單體應(yīng)用,各個(gè)模塊的服務(wù)是通過(guò) Assembly 集成在一起,最后部署在一個(gè) web server 下的。

我們已經(jīng)在拆分服務(wù)并且在 Ocelot 的基礎(chǔ)上封裝了我們自己的網(wǎng)關(guān),但是服務(wù)還沒(méi)有完全拆分,于是有這么一個(gè)需求,對(duì)于 Ocelot 配置的路由去交給 Ocelot 去轉(zhuǎn)發(fā)到真正的服務(wù)地址,而那些 Ocelot 沒(méi)有定義的路由則讓交給 AspNetCore 去處理。

實(shí)現(xiàn)原理

實(shí)現(xiàn)原理是讓 Ocelot 作為一個(gè)動(dòng)態(tài)分支路由,只有當(dāng) Ocelot 配置了對(duì)應(yīng)路由的下游地址才走 Ocelot 的分支,才把請(qǐng)求交給 Ocelot 處理。

我們可以使用 MapWhen 來(lái)處理,接下來(lái)就需要知道怎么樣判斷 Ocelot 是否配置了某一個(gè)路由,Ocelot 內(nèi)部的處理管道,在向下游請(qǐng)求之前是要找到對(duì)應(yīng)匹配的下游路由,所以我們?nèi)タ匆豢?Ocelot 的源碼,看看 Ocelot 內(nèi)部是怎么找下游路由的,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);

  • }

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

    實(shí)現(xiàn)

    既然找到了 Ocelot 如何找下游路由,就先給 Ocelot 加一個(gè)擴(kuò)展吧,實(shí)現(xiàn)代碼如下,Ocelot 擴(kuò)展完整代碼

  • 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)

  • {

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

  • return false;

  • }


  • var internalConfiguration = internalConfigurationResponse.Data;

  • var downstreamRouteFinder = context.RequestServices

  • .GetRequiredService<IDownstreamRouteProviderFactory>()

  • .Get(internalConfiguration);

  • // 根據(jù)請(qǐng)求以及上面獲取的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();

  • 新建一個(gè) TestController

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

  • public class TestController : ControllerBase

  • {

  • public IActionResult Get()

  • {

  • return Ok(new

  • {

  • Tick = DateTime.UtcNow.Ticks,

  • Msg = "Hello Ocelot",

  • });

  • }

  • }

  • 具體代碼可以參考這個(gè) 網(wǎng)關(guān)示例項(xiàng)目

    示例項(xiàng)目的 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

  • }

  • }

  • }

  • 運(yùn)行項(xiàng)目進(jìn)行測(cè)試:

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

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

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

    Reference

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

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


    總結(jié)

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

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。