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

相关文章

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

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

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

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

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;本篇博文是对之前两篇博文中演示示例和实现方法的简短跟进。你可以通过…

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

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

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

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

NC14732 锁

NC14732 锁 题意&#xff1a; n个居民&#xff0c;门上有k把锁&#xff0c;每个居民有若干钥匙&#xff0c;为1到k的一个子集&#xff0c;如果几名居民的钥匙的并集是1到k&#xff0c;即他们拥有全部锁的对应钥匙。 求最小的k&#xff0c;使得可以适当地给居民们每人若干钥匙…

.NET Core实战项目之CMS 第十七章 CMS网站系统的部署

目前我们的.NET Core实战项目之CMS系列教程基本走到尾声了&#xff0c;通过这一系列的学习你应该能够轻松应对.NET Core的日常开发了&#xff01;当然这个CMS系统的一些逻辑处理还需要优化&#xff0c;如没有引入日志组件以及缓存功能&#xff0c;权限目前只支持控制到菜单&…

如何用EFCore Lazy Loading实现Entity Split

α角 与 β角支持 现实生活 的 计算机系统&#xff0c;总有着两大偏差&#xff0c;第一个是 现实生活 与 计算机系统 的α角&#xff0c;另外一个是计算机系统的 逻辑设计 与 物理设计 的β角。举个栗子&#xff1a;α角&#xff1a;假设某个公司的商业流程&#xff0c;我们在做…

.NET Core 开源项目 Anet 在路上

今天给大家介绍我刚开源的一个 .NET Core 项目&#xff1a;Anet。Anet 的目标是实现一个 .NET Core 通用库、通用框架和通用模板。我给它的定义是&#xff1a;A .NET Core Common Lib, Framework and Boilerplate.它的取名正是来自于这句话的前面四个字母&#xff1a;ANET。Ane…

模板:后缀自动机(SAM)

所谓后缀自动机&#xff0c;就是通过后缀建立的自动机 &#xff08;逃&#xff09; 请允许我先介绍一下后缀家族&#xff1a; &#xff08;又逃&#xff09; 前言 OI生涯目前为止学习的最为难以理解的算法&#xff0c;没有之一。 到现在也没有完全的理解。 qwq 概念 定义&…

.NET 开源项目 Anet 介绍

使用 Anet 有一段时间了&#xff0c;已经在我的个人网站&#xff08;如 bookist.cc&#xff09;投入使用&#xff0c;目前没有发现什么大问题&#xff0c;所以才敢写篇文章向大家介绍。GitHub 地址&#xff1a;https://github.com/anet-team/anetAnet 是一个 .NET Core 通用框架…

我的十年创业路

记十年创业的心路历程和我的创业思辨导读1 为什么写这篇文章2 详细的总结和思辨 2.01 感恩 2.02 为什么创业 2.03 十年流水账 2.04 经历了哪些失败 2.05 重要的职场基础 2.06 持续的学习和进步 2.07 创业与兴趣 2.08 价值观的碰撞和选择 2.09 合作与…

DotNetty 实现 Modbus TCP 系列 (一) 报文类

Modbus TCP/IP 报文报文最大长度为 260 byte (ADU 7 byte MBAP Header 253 byte PDU)Length Unit Identifier 长度 PDU 长度MBAP HeaderPDUPDU 由两部分构成&#xff1a;Function Code(功能码) 和 Data 组成Function Code部分功能码&#xff1a;报文类ModbusHeaderModbusHe…

专题突破三之并查集Ⅰ——Portal,parity,食物链,程序自动分析,Almost Union-Find,洞穴勘测

文章目录Portalparity[NOI2001] 食物链程序自动分析UVA11987 Almost Union-Find[SDOI2008] 洞穴勘测Portal source 百度翻译简直就是个鬼…(((m -__-)m 离线 将边和询问按权值排序&#xff0c;指针&#xff0c;将所有权值不超过当前询问iii的边全加进去 答案路径自然是不连…

C# 未来新特性:静态委托和函数指针

C# 每发布一次新版本&#xff0c;都会增加一些底层相关的新特性&#xff0c; 这些特性对大多数商业程序来说并没什么实际用处&#xff0c;主要用于那些对性能有很高要求的代码&#xff0c;如图形处理、机器学习以及数学工具包&#xff0c;等等。接下来的两个提案&#xff0c;主…

JavaWeb --第一章Web基本概念

JavaWeb --第一章Web基本概念 文章目录基本概念前言web开发&#xff1a;web应用程序静态web动态webweb服务器技术讲解web服务器基本概念 前言 web开发&#xff1a; web&#xff0c;网页的意思静态web a. html&#xff0c;css b. 提供给所有人看的数据始终不会发生改变动态we…

DotNetty 实现 Modbus TCP 系列 (二) ModbusFunction 类图及继承举例

DotNetty 实现 Modbus TCP 系列 (一) 报文类ModbusFunction 类图如下&#xff1a;如前文所述&#xff0c;所有请求/相应的 PDU 均继承自 ModbusFunction&#xff0c;其子类传入对应的 Function Code 并实现三个方法&#xff1a;CalculateLength&#xff1a;Data 部分的长度(该方…

专题突破三之并查集Ⅱ——星球大战,In Touch,方格染色,Junk-Mail Filter,关押罪犯,Silver Woods,Must Be Rectangular!

文章目录[JSOI2008]星球大战In Touch方格染色Junk-Mail Filter[NOIP2010 提高组] 关押罪犯Silver WoodsMust Be Rectangular![JSOI2008]星球大战 source 非常套路的&#xff0c;正着打击星球&#xff0c;逆着就是添加星球以及关系&#xff0c;并查集维护此时连通块个数 就是…

JavaWeb --第二章 Tomact详情

JavaWeb --第二章 Tomact详情 文章目录Tomcat安装TomcatTomcat启动和配置配置发布一个web网站Tomcat 安装Tomcat 去官方下载 https://tomcat.apache.org Tomcat启动和配置 文件夹作用&#xff1a; 启动/关闭 Tomcat&#xff1a; 文件夹bin/startup.bat 开启 网址&#x…