网站做外链的技巧,wordpress 安装后梅花,网页广告拦截怎么设置,全球人口多少亿Ocelot是ASP.NET Core下的API网关的一种实现#xff0c;在微服务架构领域发挥了非常重要的作用。本文不会从整个微服务架构的角度来介绍Ocelot#xff0c;而是介绍一下最近在学习过程中遇到的一个问题#xff0c;以及如何使用中间件#xff08;Middleware#xff09;来解决… Ocelot是ASP.NET Core下的API网关的一种实现在微服务架构领域发挥了非常重要的作用。本文不会从整个微服务架构的角度来介绍Ocelot而是介绍一下最近在学习过程中遇到的一个问题以及如何使用中间件Middleware来解决这样的问题。问题描述在上文中我介绍了一种在Angular站点里基于Bootstrap切换主题的方法。之后我将多个主题的boostrap.min.css文件放到一个ASP.NET Core Web API的站点上并用静态文件的方式进行分发在完成这部分工作之后调用这个Web API就可以从服务端获得主题信息以及所对应的样式文件。例如12345678910111213141516171819202122232425262728// GET http://localhost:5010/api/themes{ version: 1.0.0, themes: [ { name: 蔚蓝 (Cerulean), description: Cerulean, category: light, cssMin: http://localhost:5010/themes/cerulean/bootstrap.min.css, navbarClass: navbar-dark, navbarBackgroundClass: bg-primary, footerTextClass: text-light, footerLinkClass: text-light, footerBackgroundClass: bg-primary }, { name: 机械 (Cyborg), description: Cyborg, category: dark, cssMin: http://localhost:5010/themes/cyborg/bootstrap.min.css, navbarClass: navbar-dark, navbarBackgroundClass: bg-dark, footerTextClass: text-dark, footerLinkClass: text-dark, footerBackgroundClass: bg-light } ]}当然整个项目中不仅仅是有这个themes API还有另外2-3个服务在后台运行项目是基于微服务架构的。为了能够让前端有统一的API接口我使用Ocelot作为服务端的API网关以便为Angular站点提供API服务。于是我定义了如下ReRoute规则12345678910111213141516{ ReRoutes: [ { DownstreamPathTemplate: /api/themes, DownstreamScheme: http, DownstreamHostAndPorts: [ { Host: localhost, Port: 5010 } ], UpstreamPathTemplate: /themes-api/themes, UpstreamHttpMethod: [ Get ] } ]}假设API网关运行在http://localhost:9023那么基于上面的ReRoute规则通过访问http://localhost:9023/themes-api/themes即可转发到后台的http://localhost:5010/api/themes完成API的调用。运行一下调用结果如下12345678910111213141516171819202122232425262728// GET http://localhost:9023/themes-api/themes{ version: 1.0.0, themes: [ { name: 蔚蓝 (Cerulean), description: Cerulean, category: light, cssMin: http://localhost:5010/themes/cerulean/bootstrap.min.css, navbarClass: navbar-dark, navbarBackgroundClass: bg-primary, footerTextClass: text-light, footerLinkClass: text-light, footerBackgroundClass: bg-primary }, { name: 机械 (Cyborg), description: Cyborg, category: dark, cssMin: http://localhost:5010/themes/cyborg/bootstrap.min.css, navbarClass: navbar-dark, navbarBackgroundClass: bg-dark, footerTextClass: text-dark, footerLinkClass: text-dark, footerBackgroundClass: bg-light } ]}看上去一切正常但是每个主题设置的css文件地址仍然还是指向下游服务的URL地址比如上面的cssMin中还是使用的http://localhost:5010。从部署的角度外部是无法访问除了API网关以外的其它服务的于是这就造成了css文件无法被访问的问题。解决这个问题的思路很简单就是API网关在返回response的时候将cssMin的地址替换掉。如果在Ocelot的配置中加入以下ReRoute设置123456789101112{ DownstreamPathTemplate: /themes/{name}/bootstrap.min.css, DownstreamScheme: http, DownstreamHostAndPorts: [ { Host: localhost, Port: 5010 } ], UpstreamPathTemplate: /themes-api/theme-css/{name}, UpstreamHttpMethod: [ Get ]}那么只需要将下游response中cssMin的值比如http://localhost:5010/themes/cyborg/bootstrap.min.css替换为Ocelot网关中设置的上游URL比如http://localhost:9023/themes-api/theme-css/cyborg然后将替换后的response返回给API调用方即可。这个过程可以使用Ocelot中间件完成。使用Ocelot中间件Ocelot中间件是继承于OcelotMiddleware类的子类并且可以在Startup.Configure方法中通过app.UseOcelot方法将中间件注入到Ocelot管道中然而简单地调用IOcelotPipelineBuilder的UseMiddleware方法是不行的它会导致整个Ocelot网关不可用。比如下面的方法是不行的这是因为没有将Ocelot的其它Middleware加入到管道中Ocelot管道中只有ThemeCssMinUrlReplacer中间件。要解决这个问题我目前的方法就是通过使用扩展方法将所有Ocelot中间全部注册好然后再注册自定义的中间件比如12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758public static IOcelotPipelineBuilder BuildCustomOcelotPipeline(this IOcelotPipelineBuilder builder, OcelotPipelineConfiguration pipelineConfiguration){ builder.UseExceptionHandlerMiddleware(); builder.MapWhen(context context.HttpContext.WebSockets.IsWebSocketRequest, app { app.UseDownstreamRouteFinderMiddleware(); app.UseDownstreamRequestInitialiser(); app.UseLoadBalancingMiddleware(); app.UseDownstreamUrlCreatorMiddleware(); app.UseWebSocketsProxyMiddleware(); }); builder.UseIfNotNull(pipelineConfiguration.PreErrorResponderMiddleware); builder.UseResponderMiddleware(); builder.UseDownstreamRouteFinderMiddleware(); builder.UseSecurityMiddleware(); if (pipelineConfiguration.MapWhenOcelotPipeline ! null) { foreach (var pipeline in pipelineConfiguration.MapWhenOcelotPipeline) { builder.MapWhen(pipeline); } } builder.UseHttpHeadersTransformationMiddleware(); builder.UseDownstreamRequestInitialiser(); builder.UseRateLimiting(); builder.UseRequestIdMiddleware(); builder.UseIfNotNull(pipelineConfiguration.PreAuthenticationMiddleware); if (pipelineConfiguration.AuthenticationMiddleware null) { builder.UseAuthenticationMiddleware(); } else { builder.Use(pipelineConfiguration.AuthenticationMiddleware); } builder.UseClaimsToClaimsMiddleware(); builder.UseIfNotNull(pipelineConfiguration.PreAuthorisationMiddleware); if (pipelineConfiguration.AuthorisationMiddleware null) { builder.UseAuthorisationMiddleware(); } else { builder.Use(pipelineConfiguration.AuthorisationMiddleware); } builder.UseClaimsToHeadersMiddleware(); builder.UseIfNotNull(pipelineConfiguration.PreQueryStringBuilderMiddleware); builder.UseClaimsToQueryStringMiddleware(); builder.UseLoadBalancingMiddleware(); builder.UseDownstreamUrlCreatorMiddleware(); builder.UseOutputCacheMiddleware(); builder.UseHttpRequesterMiddleware(); return builder;}然后再调用app.UseOcelot即可123456app.UseOcelot((builder, config) { builder.BuildCustomOcelotPipeline(config) .UseMiddlewareThemeCssMinUrlReplacer() .Build();});这种做法其实听起来不是特别的优雅但是目前也没找到更合适的方式来解决Ocelot中间件注册的问题。以下便是ThemeCssMinUrlReplacer中间件的代码可以看到我们使用正则表达式替换了cssMin的URL部分使得css文件的地址可以正确被返回执行结果如下12345678910111213141516171819202122232425262728// GET http://localhost:9023/themes-api/themes{ version: 1.0.0, themes: [ { name: 蔚蓝 (Cerulean), description: Cerulean, category: light, cssMin: http://localhost:9023/themes-api/theme-css/cerulean, navbarClass: navbar-dark, navbarBackgroundClass: bg-primary, footerTextClass: text-light, footerLinkClass: text-light, footerBackgroundClass: bg-primary }, { name: 机械 (Cyborg), description: Cyborg, category: dark, cssMin: http://localhost:9023/themes-api/theme-css/cyborg, navbarClass: navbar-dark, navbarBackgroundClass: bg-dark, footerTextClass: text-dark, footerLinkClass: text-dark, footerBackgroundClass: bg-light } ]}总结本文介绍了使用Ocelot中间件实现下游服务response body的替换任务在ThemeCssMinUrlReplacer的实现代码中我们使用了context.DownstreamReRoute.DownstreamPathTemplate.Value来判断当前执行的URL是否需要由该中间件进行处理以避免不必要的中间件逻辑执行。这个设计可以再优化一下使用一个简单的框架让程序员可以通过Ocelot的配置文件来更为灵活地使用Ocelot中间件下文介绍这部分内容。