NET Core微服务之路:基于Ocelot的API网关Relay实现--RPC篇

前言

我们都知道,API网关是工作在应用层上网关程序,为何要这样设计呢,而不是将网关程序直接工作在传输层、或者网络层等等更底层的环境呢?让我们先来简单的了解一下TCP/IP的五层模型。

 

640?wx_fmt=png

 

(图片出自http://www.cnblogs.com/qishui/p/5428938.html)

 

具体的每一层的工作原理想必大家都已经滚瓜烂熟了,笔者也不在重复的复述这内容。回到上面的问题,为何API网关需要工作在应用层上的问题就变得一目了然,物理层面的网关是交给物理设备进行的,例如物理防火墙,而HTTP是网络通信中已经完全规范化和标准化的应用层协议,随处可见的通信协议,当然,你把网关集成到FTP上面也可以,增加相应的协议转换处理即可。

回过头来,RPC是什么,是一个协议吗?不是。确切的说它只是“远程调用”的一个名称的缩写,并不是任何规范化的协议,也不是大众都认知的协议标准,我们更多时候使用时都是创建的自定义化(例如Socket,Netty)的消息方式进行调用,相比http协议,我们省掉了不少http中无用的消息内容,例如headers消息头。本一个简单的GET请求,返回一个hello world的请求和响应,元数据就10个字节左右,但是加上headers消息头等等http的标准内容,估计会膨胀到25~30个字节,下面是一个常见的http的headers消息头。

640?wx_fmt=png

因此很多系统内部调用仍然采用自定义化的RPC调用模式进行通信,毕竟速度和性能是内网的关键指标之一,而标准化和语义无关性在外网中举足轻重。所以,为何API网关无法工作在RPC上,因为它没有一个像HTTP/HTTPS那样的通用标准,需要我们将标准化的协议转为为自定义协议的处理,通常称为Relay,如图所示。

 

 

640?wx_fmt=png

 

上一篇中,我们已经简单的介绍了Ocelot在Http中的网关实现,无需任何修改,全都可以在配置文件中完成,相当方便。但是,我们需要实现自定义的RPC协议时,应该怎么办呢?

这里,感谢张队在上一篇中提供建议和思路https://www.cnblogs.com/SteveLee/p/Ocelot_Api_http_and_https.html#4171964,可以通过增加(或扩展)OcelotMiddleware来处理下游协议的转换。

 

640?wx_fmt=png

 

(图片出自https://www.cnblogs.com/shanyou/p/7787183.html)

 

Ocelot下游中间件扩展

我们知道,在Ocelot网关中,所有操作均通过中间件来进行过滤和处理,而多个中间件之间的相互迭代通信便形成了Ocelot的通信管道,源码中使用OcelotPipelineConfiguration来扩展和配置更多的Ocelot中间件,见源码所示:

 

640?wx_fmt=png

 

在源码中,我们可以看到,所有的中间件对应操作对象的均是DownstreamContext下游上下文对象。而MapWhenOcelotPipeline正好可以满足我们扩展中间件的需求,它提供List<Func<IOcelotPipelineBuilder, Func<DownstreamContext, bool>>>委托以供我们配置多个下游处理中间件并映射到Ocelot管道构建器中。我们查看DownstreamContext的源码,可以看到,构建下游上下文的时候,默认就传递了HttpContext对象,而通过DownstreamRequest和DownstreamResponse完成对下游的请求和响应接收。

 

640?wx_fmt=png

 

这样,我们便可以通过对OcelotPipelineConfiguration的扩展来添加自定义中间件,我们把它扩展名称定义为OcelotPipelineConfigurationExtensions吧。

640?wx_fmt=png

当有了DownstreamContext的扩展定义,而且在下游配置中,我们需要指定的配置协议是tcp,那么我们便可以开始实现这个扩展的中间件了,我们把中间件的名称定义为RelayRequesterMiddleware

640?wx_fmt=png

640?wx_fmt=png

上面加粗的代码便是下游拦截的主要处理地方,在这里我们便可以使用http转rpc的协议转换处理。当然,在Ocelot的使用配置中,我们需要对该Middleware中间件进行添加。

 

app.UseOcelot(pipelineConfiguration => pipelineConfiguration.AddRpcMiddleware()).Wait();

 

以上便完成了对Ocelot中DownstreamContext的扩展,

总结下来,当我们需要扩展下游协议时,我们需要手动配置OcelotPipelineConfiguration并添加到IOcelotPipelineBuilder中,然后通过扩展IOcelotPipelineBuilder实现下游中间件的自定义处理。

 

手动协议转换

其实到上面这一小节,相信很多朋友都可以实现自定义的下游拦截和处理了,而本节的介绍,只是针对在Doteasy.RPC中如何进行协议转换的一个参考。

 

我们先看一组http中的URL:http://127.0.0.1:8080/api/values,然后再看看tcp中的URL:tcp://127.0.0.1:8080/api/values。有什么区别吗?没有任何区别,唯一的区别是scheme从http转为tcp。而在rpc过程调用中,一般我们是没有“绝对路径+谓词”的方式去识别服务节点的,一般都是tcp://127.0.0.1:8080,而具体指定的服务节点交给注册中心去完成,也就是通常所说的服务发现。

由于Doteasy.RPC内部并未实现如“<scheme>://<username>:<password>@<host>:<port>/<path>......”这样标准化的统一定位,所以笔者的做法是将RPC的客户端集成到Ocelot宿主中,让它替代DownstreamConext下游的请求和响应,通过扩展反射的方式实现所有代理的生成,并根据谓词和参数进行方法的调用,这样,代码就不需要做太多的修改。

640?wx_fmt=png

首先需要明白这样做的一个目的

  1. 在Doteasy.RPC单次调用中,为了减少众多接口生成代理所带来的耗时,每次调用前都会检查相关接口的动态代理是否已经生成,确保每次只生成一个片段的代理。然而,作为一个网关中的中继器,这样一次生成一个代码片段显得非常无力,需要将所有的接口全部生成代理,以方便在Relay中查找和调用。

  2. 再看一个RESTful风格中的URL:http://127.0.0.1:8080/api/1/Sync,一般我们将谓词放置最后,而参数一般放置在谓词的前面,在手动转换RPC的过程中,就可以利用谓词来假设我们需要调用的RPC服务名称(但实际不一定就是Sync)。

  3. 基于Doteasy.RPC中的服务容器,可以很方便的实现参数类型转换以及后期的Headers处理。

640?wx_fmt=png

640?wx_fmt=png

笔者的转换方式是将谓词作为服务名称和参数值进行调用,虽然这种方式目前来看十分拙劣,但为自定义转换提供了一组思路,还可以不断的优化和调整,目前缺点如下:

  1. 当http中多个参数时,无法进行协议转换,因为不知道代理目标方法的参数集合是多少,只有全局假设一对一的参数目标。

  2. RPC客户端在网关中集成了大量的代理生成,无法实现动态更新,例如原来手动替换DLL,接口自动更新动态代理。

  3. 每一次调用都需要从大量的代理中查找指定(或模糊匹配)的方法名称,如果存在1KW+的接口名称,这个查找将是一个非常严重的瓶颈。

 

总结

世上没有100%完美的事物,所以才有各种各样的手段,这里笔者在Doteasy.RPC和Ocelot的基础上做了一个简单下游协议转换,有兴趣的朋友可以自行实现自己想要的协议转换。再次感谢张队提供的Ocelot手动转RPC思路。

原文地址:

https://www.cnblogs.com/SteveLee/p/Ocelot_Api_http_route_RPC.html

.NET社区新闻,深度好文,欢迎访问公众号文章汇总 http://www.csharpkit.com
640?wx_fmt=jpeg


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

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

相关文章

模板:长链剖分

所谓长链剖分&#xff0c;就是对长链进行剖分 &#xff08;逃&#xff09; 前言 很优雅的算法 利用对指针进行魔法操作将 n2n^2n2 的 dp 优化成线性 线性啊&#xff01;&#xff01;&#xff01; 解析 CF1009F Dominant Indices 给定一棵以 111 为根&#xff0c;nnn 个节点…

acwing 327. 玉米田

327. 玉米田 题意&#xff1a; m * n的土地&#xff0c;有的土地不育&#xff0c;有的可以种植&#xff0c;要求相邻的土地不能同时种植玉米&#xff0c;问有多少种种植方式 题解&#xff1a; 状压dp&#xff0c;先存每一行可能的状态&#xff0c;然后状态转移&#xff0c;…

Windows 10《描图》应用现已开源

点击上方蓝字关注“汪宇杰博客”《描图》是我最早的Windows 10应用&#xff0c;发布至今已3年多&#xff0c;积累了全球数百万用户&#xff0c;广受好评。现已开源。这款应用为不少小朋友带去了欢乐&#xff0c;体验绘画的乐趣&#xff0c;也帮助过专业用户复刻数百幅古代绘画。…

数论六之计算几何干货——计算几何模板解释全集 及 模板检验训练场

文章目录点和向量及运算直线和线段求解点到直线的距离/点在直线上求解点到线段的距离/点在线段上求解两条线段是否相交求解两直线的交点多边形求解多边形面积求解多边形重心求解判断定点与多边形的位置关系凸包graham扫描法graham扫描法加强版圆求解圆与直线的交点求解圆与圆的…

P7740-[NOI2021]机器人游戏【dp,bitset】

正题 题目链接:https://www.luogu.com.cn/problem/P7740 题目描述 题目大意摸了 小 R 有 mmm&#xff08;1≤m≤10001 \le m \le 10001≤m≤1000&#xff09;个机器人和 mmm 张纸带&#xff0c;第 iii&#xff08;1≤i≤m1 \le i \le m1≤i≤m&#xff09;个机器人负责对第 …

CodeForces:54

文章目录前言CF54A PresentsDescription\text{Description}DescriptionSolution\text{Solution}SolutionCF54B Cutting Jigsaw PuzzleDescription\text{Description}DescriptionSolution\text{Solution}SolutionCode\text{Code}CodeCF54C First Digit LawDescription\text{Desc…

[NOIP2016 提高组] 愤怒的小鸟

[NOIP2016 提高组] 愤怒的小鸟 题意&#xff1a; 有n只猪&#xff0c;给出猪的坐标(xi,yi),问最少用几个形如 yax^2bx 的曲线可以保证所有猪在曲线上&#xff0c;满足a<0,a,b为实数 n<18, 题解&#xff1a; 两个方法&#xff1a;爆搜或者状压dp 状压dp 看n<18也…

P5208-[WC2019] I 君的商店【交互,二分】

正题 题目链接:https://www.luogu.com.cn/problem/P5208 题目大意 有一个长度为nnn的010101序列aaa&#xff0c;你知道里面有奇数个111还是偶数个111。你每次可以选择两个下标集合S/TS/TS/T询问集合SSS和集合TTT位置的数字和哪个更大。 交互库只会告诉你S≤TS\leq TS≤T或者…

模板:后缀数组(SA)

文章目录前言解析后缀排序优化1&#xff1a;基数排序优化2&#xff1a;简化第一次排序优化3&#xff1a;提前break完整代码LCP与height所谓后缀数组&#xff0c;就是存储后缀的数组 &#xff08;逃&#xff09; 前言 为什么一个算法&#xff0c;如此难以理解却依然是成为一个…

P3959 [NOIP2017 提高组] 宝藏

P3959 [NOIP2017 提高组] 宝藏 题意: 额题意不好说&#xff0c;就是n个点m个边&#xff0c;选定一个点为根节点&#xff0c;构造一个最小生成树&#xff0c;边的权值为该该边起点到根节点之间的点的数量K&#xff08;不含根节点&#xff09; * 道路长度 1<n<12 0<m&…

如何在ASP.NET Core程序启动时运行异步任务(3)

原文&#xff1a;Running async tasks on app startup in ASP.NET Core (Part 3)作者&#xff1a;Andrew Lock译者&#xff1a;Lamond Lu之前我写了两篇有关在ASP.NET Core中运行异步任务的博文&#xff0c;本篇博文是对之前两篇博文中演示示例和实现方法的简短跟进。你可以通过…

CF1140G-Double Tree【最短路,矩阵乘法,树上倍增】

正题 题目链接:https://www.luogu.com.cn/problem/CF1140G 题目大意 给出一个nnn个点的树TTT&#xff0c;然后复制一份T′TT′&#xff0c;每个TTT中的点iii向T′TT′中的点iii都有连边构成一张图。 图上所有权值各不相同&#xff0c;现在qqq次询问图上两点的最短路。 1≤n≤…

数论六之计算几何——An Easy Problem,Ancient Berland Circus,Open-air shopping malls

可检验模板正确度An Easy Problem?!Ancient Berland CircusOpen-air shopping mallsAn Easy Problem?! problem 就是大讨论 #include <cmath> #include <cstdio> #include <iostream> using namespace std; #define eps 1e-6struct vec {double x, y;ve…

CodeForces:12271261(div1)1262(div2)

文章目录前言CF1227A Math ProblemDescription\text{Description}DescriptionSolution\text{Solution}SolutionCode\text{Code}CodeCF1227B BoxDescription\text{Description}DescriptionSolution\text{Solution}SolutionCode\text{Code}CodeCF1227C MessyDescription\text{Des…

【NET CORE微服务一条龙应用】应用部署

简介本章主要介绍https://github.com/q315523275/FamilyBucket上微服务一条龙应用&#xff0c;在实际使用中的应用部署&#xff0c;以原始方式部署非docker部署应用主要包括&#xff1a;1、网关应用部署2、授权认证应用部署3、配置中心查询服务端应用部署4、综合管理应用部署5、…

牛客网区间dp练习

NC13230 合并回文子串 NC16129 小小粉刷匠 NC19909 [CQOI2007]涂色PAINT NC19997 [HAOI2016]字符合并 NC20238 [SCOI2003]字符串折叠 NC20252 [SCOI2007]压缩 NC20312 [SDOI2008]SUE的小球 POJ3042 Grazing on the Run

CF516D-Drazil and Morning Exercise【树上差分,倍增】

正题 题目链接:https://www.luogu.com.cn/problem/CF516D 题目大意 给出一棵nnn个点的树&#xff0c;定义f(x)f(x)f(x)表示距离点xxx最远的点的距离&#xff0c;qqq次询问给出一个kkk&#xff0c;要求一个最大的连通块满足连通块中所有点的f(x)f(x)f(x)最大最小差值不能超过k…

容斥问卷调查反馈——Co-prime,Character Encoding,Tree and Constraints,「2017 山东一轮集训 Day7」逆序对

文章目录Co-primesourcesolutioncodeCharacter EncodingsourcesolutioncodeTree and Constraintssourcesolutioncode「2017 山东一轮集训 Day7」逆序对sourcesolutioncodeCo-prime source TTT组数据&#xff0c;给出&#x1d43f;,&#x1d445;,&#x1d441;&#x1d43f;, …

手工修复Azure DevOps无法连接到Azure的问题

点击上方蓝字关注“汪宇杰博客”今天我在为一个从TFVC迁移到Git的老项目重新配置发布到Azure App Service的CI/CD管线的时候&#xff0c;Azure DevOps竟然爆了。这是一个微软已知的bug&#xff0c;目前还未修复&#xff0c;我来带大家看看如何手工workaround这个问题。首先&…

Loj#576-「LibreOJ NOI Round #2」签到游戏【线段树】

正题 题目链接:https://loj.ac/p/576 题目大意 给出一个长度为nnn的序列aaa&#xff0c;还有一个未知序列bbb&#xff0c;你每次可以花费gcd⁡ilrai\gcd_{il}^r a_igcdilr​ai​的代价得到∑ilrbi\sum_{il}^rb_i∑ilr​bi​的值。 每次修改aaa中的一个数&#xff0c;求得到b…