让 Ocelot 与 asp.net core “共存”

Intro

我们的 API 之前是一个单体应用,各个模块的服务是通过 Assembly 集成在一起,最后部署在一个 web server 下的。

我们已经在拆分服务并且在 Ocelot 的基础上封装了我们自己的网关,但是服务还没有完全拆分,于是有这么一个需求,对于 Ocelot 配置的路由去交给 Ocelot 去转发到真正的服务地址,而那些 Ocelot 没有定义的路由则让交给 AspNetCore 去处理。

实现原理

实现原理是让 Ocelot 作为一个动态分支路由,只有当 Ocelot 配置了对应路由的下游地址才走 Ocelot 的分支,才把请求交给 Ocelot 处理。

我们可以使用 MapWhen 来处理,接下来就需要知道怎么样判断 Ocelot 是否配置了某一个路由,Ocelot 内部的处理管道,在向下游请求之前是要找到对应匹配的下游路由,所以我们去看一看 Ocelot 的源码,看看 Ocelot 内部是怎么找下游路由的,Ocelot 找下游路由中间件源码

  1. public async Task Invoke(DownstreamContext context)

  2. {

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


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


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


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


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


  8. // 获取下游路由

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


  10. if (downstreamRoute.IsError)

  11. {

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


  13. SetPipelineError(context, downstreamRoute.Errors);

  14. return;

  15. }


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


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


  18. context.TemplatePlaceholderNameAndValues = downstreamRoute.Data.TemplatePlaceholderNameAndValues;


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

  20. }

通过上面的源码,我们就可以判断 Ocelot 是否有与请求相匹配的下游路由信息

实现

既然找到了 Ocelot 如何找下游路由,就先给 Ocelot 加一个扩展吧,实现代码如下,Ocelot 扩展完整代码

  1. public static IApplicationBuilder UseOcelotWhenRouteMatch(this IApplicationBuilder app,

  2. Action<IOcelotPipelineBuilder, OcelotPipelineConfiguration> builderAction)

  3. => UseOcelotWhenRouteMatch(app, builderAction, new OcelotPipelineConfiguration());


  4. public static IApplicationBuilder UseOcelotWhenRouteMatch(this IApplicationBuilder app,

  5. Action<OcelotPipelineConfiguration> pipelineConfigurationAction,

  6. Action<IOcelotPipelineBuilder, OcelotPipelineConfiguration> builderAction)

  7. {

  8. var pipelineConfiguration = new OcelotPipelineConfiguration();

  9. pipelineConfigurationAction?.Invoke(pipelineConfiguration);

  10. return UseOcelotWhenRouteMatch(app, builderAction, pipelineConfiguration);

  11. }


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

  13. {

  14. app.MapWhen(context =>

  15. {

  16. // 获取 OcelotConfiguration

  17. var internalConfigurationResponse =

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

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

  20. {

  21. // 如果没有配置路由信息,不符合分支路由的条件,直接退出

  22. return false;

  23. }


  24. var internalConfiguration = internalConfigurationResponse.Data;

  25. var downstreamRouteFinder = context.RequestServices

  26. .GetRequiredService<IDownstreamRouteProviderFactory>()

  27. .Get(internalConfiguration);

  28. // 根据请求以及上面获取的Ocelot配置获取下游路由

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

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

  31. // 如果有匹配路由则满足该分支路由的条件,交给 Ocelot 处理

  32. return !response.IsError

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

  34. ?.DownstreamScheme);

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


  36. return app;

  37. }

使用

在 Startup 里

ConfigurationServices 配置 mvc 和 Ocelot

Configure 方法里配置 ocelot 和 mvc

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

  2. {

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

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

  5. ocelotBuilder.UseExceptionHandlerMiddleware();

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

  7. ocelotBuilder.UseResponderMiddleware();

  8. ocelotBuilder.UseDownstreamRouteFinderMiddleware();

  9. ocelotBuilder.UseDownstreamRequestInitialiser();

  10. ocelotBuilder.UseRequestIdMiddleware();

  11. ocelotBuilder.UseMiddleware<ClaimsToHeadersMiddleware>();

  12. ocelotBuilder.UseLoadBalancingMiddleware();

  13. ocelotBuilder.UseDownstreamUrlCreatorMiddleware();

  14. ocelotBuilder.UseOutputCacheMiddleware();

  15. ocelotBuilder.UseMiddleware<HttpRequesterMiddleware>();

  16. // cors headers

  17. ocelotBuilder.UseMiddleware<CorsMiddleware>();

  18. });


  19. app.UseMvc();

新建一个 TestController

  1. [Route("/api/[controller]")]

  2. public class TestController : ControllerBase

  3. {

  4. public IActionResult Get()

  5. {

  6. return Ok(new

  7. {

  8. Tick = DateTime.UtcNow.Ticks,

  9. Msg = "Hello Ocelot",

  10. });

  11. }

  12. }

具体代码可以参考这个 网关示例项目

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

  1. {

  2. "ReRoutes": [

  3. {

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

  5. "UpstreamPathTemplate": "/api/chat/{everything}",

  6. "UpstreamHttpMethod": [

  7. "Get",

  8. "POST",

  9. "PUT",

  10. "PATCH",

  11. "DELETE",

  12. "OPTIONS"

  13. ],

  14. "AddHeadersToRequest": {

  15. },

  16. "RequestIdKey": "RequestId",

  17. "ReRouteIsCaseSensitive": false,

  18. "ServiceName": "",

  19. "DownstreamScheme": "http",

  20. "DownstreamHostAndPorts": [

  21. {

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

  23. "Port": 80

  24. }

  25. ],

  26. "DangerousAcceptAnyServerCertificateValidator": false

  27. }

  28. ],

  29. "GlobalConfiguration": {

  30. "HttpHandlerOptions": {

  31. "AllowAutoRedirect": false,

  32. "UseCookieContainer": false,

  33. "UseTracing": false

  34. }

  35. }

  36. }

运行项目进行测试:

访问 Ocelot 定义的路由 http://localhost:65125/api/chat/hello ,返回信息如图所示:

640?wx_fmt=png

访问 Mvc 定义的路由 http://localhost:65125/api/test,返回信息如图所示:

640?wx_fmt=png

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

Reference

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

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

640?wx_fmt=jpeg


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/315787.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Xamarin中国峰会2019

Xamarin跨平台技术中国峰会将讨论Xamarin技术的国内最新发展和实践情况&#xff0c;在会议中领略现代化的开发模式、应用基础架构、企业应用转型和案例交流。本月26日&#xff0c;Xamarin中国峰会将以线上直播的形式和大家见面&#xff01;直播时间:2019年5月26日 8:00—17:00直…

.NET Core IoT 入门指南:(三)使用 I2C 进行通信

什么是 I2C 总线I2C 总线&#xff08;Inter-Integrated Circuit Bus&#xff09;是设备与设备间通信方式的一种。它是一种串行通信总线&#xff0c;由飞利浦公司在1980年代为了让主板、嵌入式系统或手机用以连接低速周边设备而发展[1]。I2C 总线包含两根信号线&#xff0c;一根…

浅淡Kubernetes 与容器技术体系的最佳方法

我们已经进入到容器化时代&#xff0c;Kubernetes成为了市场上容器编排的事实标准&#xff0c;而且k8S 同样具备了微服务所需要的服务注册与发现、负载均衡、配置中心。Spring cloud 的核心是Netflix微服务框架&#xff0c;非常成熟&#xff0c;但是在netflix oss开发初期&…

.NET Core 批量重置 Azure Blob Storage 的 mime type

点击上方蓝字关注“汪宇杰博客”我的博客使用 Azure Blob Storage 存储文章配图&#xff0c;结果今天玩 Azure CDN 的时候爆了&#xff0c;原因是图片mime type不对。我们来看看如何在 .NET Core 里批量重置 Azure Blob Storage 中文件的mime type吧。起因使用编程方式&#xf…

[NewLife.XCode]实体工厂(拦截处理实体操作)

NewLife.XCode是一个有10多年历史的开源数据中间件&#xff0c;支持nfx/netcore&#xff0c;由新生命团队(2002~2019)开发完成并维护至今&#xff0c;以下简称XCode。整个系列教程会大量结合示例代码和运行日志来进行深入分析&#xff0c;蕴含多年开发经验于其中&#xff0c;代…

DDD该怎么学

2006年&#xff0c;国内的互联网才刚刚萌芽&#xff0c;人们甚至还不习惯网购&#xff0c;大多数在校生都在宿舍里刷魔兽世界副本。但企业软件开发却得到了蓬勃发展&#xff0c;各种公司和事业单位都纷纷进行信息化转型。然而人们很快发现&#xff0c;企业应用业务逻辑的复杂度…

Net Core下使用RabbitMQ比较完备两种方案(虽然代码有点惨淡,不过我会完善)

一、前言上篇说给大家来写C#和Java的方案&#xff0c;最近工作也比较忙&#xff0c;迟到了一些&#xff0c;我先给大家补上C#的方案。二、使用的插件HangFire一个开源的.NET任务调度框架&#xff0c;最大特点在于内置提供集成化的控制台,方便后台查看及监控&#xff0c;支持多种…

利用ASP .NET Core的静态文件原理实现远程访问Nlog日志内容及解决遇到的坑

最近项目上试运行发现&#xff0c;很多时候网站出了问题或者某个功能不正常&#xff0c;常常需要运维人员去服务器里面查看一下日志&#xff0c;看看日志里面会产生什么异常&#xff0c;这样导致每次都要去远程服务器很不方便&#xff0c;有时服务器是客户保管的不能让我们随意…

使用.NET Core 编写端到端测试

什么是端到端测试端到端测试也称E2E,与单元测试、集成测试、组件测试、契约测试相比&#xff0c;端到端测试的目的是验证整个系统是否满足业务目标&#xff0c;而不管使用的组件架构如何&#xff0c;为了实现这一点&#xff0c;系统被视为一个黑盒子&#xff0c;测试尽可能多地…

.NET/C# 使用 ConditionalWeakTable 附加字段(CLR 版本的附加属性,也可用用来当作弱引用字典 )...

如果你使用过 WPF/UWP 等 XAML UI 框架&#xff0c;那么应该了解到附加属性的概念。那么没有依赖属性支持的时候如何做附加属性的功能呢&#xff1f;你可能会想到弱引用。但这需要做一个弱引用字典&#xff0c;要写的代码还是非常麻烦的。本文介绍 .NET 的 ConditionalWeakTabl…

在C#中使用Json.Net进行序列化和反序列化及定制化

序列化&#xff08;Serialize&#xff09;是将对象转换成字节流&#xff0c;并将其用于存储或传输的过程&#xff0c;主要用途是保存对象的状态&#xff0c;以便在需要时重新创建该对象&#xff1b;反序列化&#xff08;Deserialize&#xff09;则是将上面的字节流转换为相应对…

知乎个人精选 | 绝版的专业书到哪里找最快最高效?

估计书到用时方恨少是很多软件开发人员的苦恼&#xff0c;当然我这里提到的"少"表示稀少&#xff0c;买不到之意~比如你加入一家政府机构或给为政府机构服务的公司做开发&#xff0c;主要做传统软件&#xff0c;对方需要使用 Win Forms做开发&#xff0c;你打算系统性…

正反案例介绍SOLID原则

一.概述SOLID五大原则使我们能够管理解决大多数软件设计问题。由Robert C. Martin在20世纪90年代编写了这些原则。这些原则为我们提供了从紧耦合的代码和少量封装转变为适当松耦合和封装业务实际需求的结果方法。使用这些原则&#xff0c;我们可以构建一个具有整洁&#xff0c;…

ASP.NET Core 中的静态文件

1.前言当我们创建Core项目的时候&#xff0c;Web根目录下会有个wwwroot文件目录&#xff0c;wwwroot文件目录里面默认有HTML、CSS、IMG、JavaScript等文件&#xff0c;而这些文件都是Core提供给客户端使用的静态文件。但是这些静态文件需要在Core里面配置才可以对外公开访问。2…

基于Kebernetes 构建.NET Core技术中台

今天下午在腾讯云社区社区分享了《基于Kubernetes 构建.NET Core技术中台》&#xff0c;下面是演讲内容的文字实录。我们为什么需要中台我们现在处于企业信息化的新时代。为什么这样说呢&#xff1f;过去企业信息化的主流重心是企业内部信息化。但现在以及未来的企业信息化的主…

RedLock 实现分布式锁

并发是程序开发中不可避免的问题&#xff0c;根据系统面向用户、功能场景的不同&#xff0c;并发的重视程度会有不同。从程序的角度来说&#xff0c;并发意味着相同的时间点执行了相同的代码&#xff0c;而有些情况是不被允许的&#xff0c;比如&#xff1a;转账、抢购占库存等…

[翻译] NumSharp的数组切片功能 [:]

原文地址&#xff1a;https://medium.com/scisharp/slicing-in-numsharp-e56c46826630翻译初稿&#xff08;英文水平有限&#xff0c;请多包涵&#xff09;&#xff1a;由于Numsharp新推出了数组切片这个牛逼的功能&#xff0c;所以.NET社区距离拥有强大的开源机器学习平台又近…

Visual Studio 2019 16.1发布,更快更高效

Visual Studio 2019 16.1 已正式发布&#xff0c;可以看到&#xff0c;新版本的启动速度有了显著的提升&#xff0c;还节省了不少的内存空间。主要更新如下&#xff1a;IDE现已公开发布 Visual Studio IntelliCode&#xff0c;并且可以随任何支持 C#、C、TypeScipt/JavaScript …

.NET Core 3.0之创建基于Consul的Configuration扩展组件

经过前面三篇关于.NET Core Configuration的文章之后&#xff0c;本篇文章主要讨论如何扩展一个Configuration组件出来。如果前面三篇文章没有看到&#xff0c;可以点击如下地址访问.NET Core 3.0之深入源码理解Configuration(一).NET Core 3.0之深入源码理解Configuration(二)…

Mono 和 .NET Core比翼双飞

大家好&#xff0c;今天给大家分享.NET 蓝图之下的Mono和.NET Core 话题&#xff0c;微软在Build 2019 大会上给.NET 做了一个五年规划&#xff0c;所以分享的主题就是《Mono和.NET Core 比翼双飞》&#xff0c;将在完成这个五年规划的时候合体。在开始这个主题之前&#xff0c…