让 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,一经查实,立即删除!

相关文章

AGC024E - Sequence Growing Hard

AGC024E - Sequence Growing Hard 题目描述 Solution 我们可以把问题看成如下形式&#xff1a; 你有一个空序列&#xff0c;每次要加入一个元素xxx,x∈[1,k]x \in [1,k]x∈[1,k]&#xff0c;使得新的序列字典序比上一个序列的字典序大。 显然如果我们加入一个数xxx&#xf…

Xamarin中国峰会2019

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

博弈论练习1

博弈论练习1 \;1.ProjectEuler306 Paper-strip Game 题目描述 Solution 令SG[i]SG[i]SG[i]表示连续iii个格子的SGSGSG值。 SG[0]SG[1]0SG[i]mexj0n−2{SG[j]xorSG[i−j−2]}SG[0]SG[1]0 \\ SG[i]mex_{j0}^{n-2}\{SG[j]\;\;xor\;\;SG[i-j-2]\} SG[0]SG[1]0SG[i]mexj0n−2​{S…

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

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

圆方树

圆方树 单纯贴个板子。。。 https://loj.ac/problem/2587 #include <vector> #include <list> #include <map> #include <set> #include <deque> #include <queue> #include <stack> #include <bitset> #include <algor…

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

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

单位根反演题单

单位根反演题单 LOJ#6485. LJJ 学二项式定理 单位根反演。 bzoj 3328 PYXFIB 单位根反演矩阵乘法。 POJChallengeRound2 Guideposts 求图上路径长度为k的倍数的方案数。 单位根反演矩阵乘法。 #include <vector> #include <list> #include <map> #inc…

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

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

AGC026E - Synchronized Subsequence

AGC026E - Synchronized Subsequence 题目描述 Solution 定义cnt[x][0],cnt[x][1]cnt[x][0],cnt[x][1]cnt[x][0],cnt[x][1]表示在前xxx个数中0的个数和1的个数分别是多少。 然后把整个串sss划分为若干个子串&#xff0c;划分点在所有cnt[i][0]cnt[i][1]cnt[i][0]cnt[i][1]c…

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

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

AGC027D - Modulo Matrix

AGC027D - Modulo Matrix 题目描述 Solution 有一个显然的想法是先填一部分格子&#xff0c;剩下的格子的即为相邻格子的LCM1LCM1LCM1&#xff0c;但这样填写的数呈指数级增长&#xff0c;并不优秀。 我们发现一个格子的数是否可以填写只和相邻的四个格子有关系&#xff0c…

DDD该怎么学

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

博弈论练习2

博弈论练习2 \;1.AGC010F - Tree Game 题目描述 Solution 一道简单博弈题&#xff08;不知道为啥能作为AGC的F题&#xff09;。 考虑树形dpdpdp&#xff0c;设f[x]f[x]f[x]表示以xxx为根的子树中是否先手必胜。 则f[x]1f[x]1f[x]1当且仅当能找到xxx的子节点vvv满足f[v]0f[v…

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

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

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

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

后缀数组SA

后缀数组SA 模板 花了不少时间才理解倍增求SASASA的实现方法&#xff0c;我还是太菜了。 定义sa[i]sa[i]sa[i]表示排名为iii的后缀的起始位置。 定义rank[i]rank[i]rank[i]表示起始位置为iii的后缀的排名。 显然两者之前互逆。 void solve() {int m122;for (int i1;i<m;…

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

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

Manacher

Manacher(马拉车算法) Manacher算法主要用于求解回文串问题&#xff0c;能够统计出以每一个位置为中心的回文串的个数&#xff0c;效率极高。 模板 题目描述 Manacher算法的实现过程&#xff1a; 1.在字符串每两个字符之间插入一个分隔符。 2.iii从111到nnn求解P[i]P[i]P[i…

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

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

P4548 [CTSC2006]歌唱王国

P4548 [CTSC2006]歌唱王国 题目描述 Solution 这一题在《具体数学&#xff08;混泥土数学&#xff09;》里讲得很详细了啊&#xff0c;这里相当于总结一下&#xff0c;想具体了解的直接看书吧。 我们先考虑字符集为222的情况&#xff0c;设硬币正面朝上(H)(H)(H)的概率为pp…