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

. Accept:*/*
2. Accept-Encoding:gzip, deflate
3. Accept-Language:zh-CN,zh;q=0.9,en;q=0.8
4. Cache-Control:no-cache
5. Connection:keep-alive
6. Cookie:.AUTH=A24BADC9D552CF1157B7842F2A6C159A681CA330DBB449568896FAC839CFEE51F42973C9A5B9F632418FB82C128A8BF612D27C2EE7DABDE985E9A79DF19A955FFED9E8219853FB90574B0990DD29B2B7ED23A7C26B8AD1934870B8C0FCB4F577636E267003E6D214D9B319A4739D3716E2A8299C35E228F96EC12A29CCDE83A7D2D3B24EE6A84CF2D69D81A44E0F46EC9B112BDAA9FC0E0943DB36C1449FD79E6D5A123E5D182D2C3A03D4049CBD76947D33EB5DCCE82CB1C91ACACD83B6D07F19A6629732FA16D08443450DC2937C7CEF6A2FAE941760C79064C7A5A67E844ABDA2DE89E5B10F3B30B8A89CEDE9C00A3C79711D
7. Host:erp-dev.holderzone.cn:90
8. Pragma:no-cache
9. Referer:http://erp-dev.holderzone.cn:90/
10. User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36

Ocelot下游中间件扩展
.png)
.png)
namespace DotEasy.Rpc.ApiGateway
{
public static class OcelotPipelineConfigurationExtensions
{
public static void AddRpcMiddleware(this OcelotPipelineConfiguration config)
{
config.MapWhenOcelotPipeline.Add(builder => builder.AddRpcMiddleware());
} private static Func<DownstreamContext, bool> AddRpcMiddleware(this IOcelotPipelineBuilder builder)
{
builder.UseHttpHeadersTransformationMiddleware();
builder.UseDownstreamRequestInitialiser();
builder.UseRateLimiting();
builder.UseRequestIdMiddleware();
builder.UseDownstreamUrlCreatorMiddleware();
builder.UseRpcRequesterMiddleware();
return context => context.DownstreamReRoute.DownstreamScheme.Equals("tcp", StringComparison.OrdinalIgnoreCase);
}
}
}
using Ocelot.Middleware.Pipeline; namespace DotEasy.Rpc.ApiGateway
{
public static class RpcRequesterMiddlewareExtensions
{
public static void UseRpcRequesterMiddleware(this IOcelotPipelineBuilder builder)
{
builder.UseMiddleware<RelayRequesterMiddleware>();
}
}
}
using System;
using System.Net;
using System.Threading.Tasks;
using Ocelot.Logging;
using Ocelot.Middleware; namespace DotEasy.Rpc.ApiGateway
{
public class RelayRequesterMiddleware : OcelotMiddleware
{
private readonly OcelotRequestDelegate _next;
private readonly IOcelotLogger _logger; public RelayRequesterMiddleware(OcelotRequestDelegate next, IOcelotLoggerFactory loggerFactory) : base(loggerFactory .CreateLogger<RelayRequesterMiddleware>())
{
_next = next;
_logger = loggerFactory.CreateLogger<RelayRequesterMiddleware>();
} public async Task Invoke(DownstreamContext context)
{
var httpContent = ... // TODO:协议转换处理等操作
context.DownstreamResponse = new DownstreamResponse(httpContent, HttpStatusCode.OK, context.DownstreamRequest.Headers);
await _next.Invoke(context);
}
}
}
app.UseOcelot(pipelineConfiguration => pipelineConfiguration.AddRpcMiddleware()).Wait();
以上便完成了对Ocelot中DownstreamContext的扩展,
总结下来,当我们需要扩展下游协议时,我们需要手动配置OcelotPipelineConfiguration并添加到IOcelotPipelineBuilder中,然后通过扩展IOcelotPipelineBuilder实现下游中间件的自定义处理。
手动协议转换
var httpContent = relayHttpRouteRpc.HttpRouteRpc(ClientProxy.GenerateAll(new Uri("http://127.0.0.1:8500")),
new Uri(context.DownstreamRequest.ToUri()),
context.DownstreamRequest.Headers); // 目前尚未处理Headers消息头
- 在Doteasy.RPC单次调用中,为了减少众多接口生成代理所带来的耗时,每次调用前都会检查相关接口的动态代理是否已经生成,确保每次只生成一个片段的代理。然而,作为一个网关中的中继器,这样一次生成一个代码片段显得非常无力,需要将所有的接口全部生成代理,以方便在Relay中查找和调用。
- 再看一个RESTful风格中的URL:http://127.0.0.1:8080/api/1/Sync,一般我们将谓词放置最后,而参数一般放置在谓词的前面,在手动转换RPC的过程中,就可以利用谓词来假设我们需要调用的RPC服务名称(但实际不一定就是Sync)。
- 基于Doteasy.RPC中的服务容器,可以很方便的实现参数类型转换以及后期的Headers处理。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using DotEasy.Rpc.Core.Runtime.Client;
using DotEasy.Rpc.Core.Runtime.Communally.Convertibles;
using Newtonsoft.Json; namespace DotEasy.Rpc.Core.ApiGateway.Impl
{
public class DefaultRelayHttpRouteRpc : IRelayHttpRouteRpc
{
private IRemoteInvokeService _remoteInvokeService;
private ITypeConvertibleService _typeConvertibleService; public DefaultRelayHttpRouteRpc(IRemoteInvokeService remoteInvokeService, ITypeConvertibleService typeConvertibleService)
{
_remoteInvokeService = remoteInvokeService;
_typeConvertibleService = typeConvertibleService;
} public StringContent HttpRouteRpc(List<dynamic> proxys, Uri urlPath, HttpRequestHeaders headers)
{
foreach (var proxy in proxys)
{
Type type = proxy.GetType();
if (!urlPath.Query.Contains("scheme=rpc")) continue; var predicate = urlPath.AbsolutePath.Split('/');
var absName = predicate[predicate.Length - ];
var absPars = predicate[predicate.Length - ]; if (!type.GetMethods().Any(methodInfo => methodInfo.Name.Contains(absName))) continue; var method = type.GetMethod(absName);
if (method != null)
{
var parameters = method.GetParameters();
var parType = parameters[].ParameterType; // only one parameter
var par = _typeConvertibleService.Convert(absPars, parType); var relayScriptor = new RelayScriptor {InvokeType = type, InvokeParameter = new dynamic[] {par}}; var result = method.Invoke(
Activator.CreateInstance(relayScriptor.InvokeType, _remoteInvokeService, _typeConvertibleService),
relayScriptor.InvokeParameter); var strResult = JsonConvert.SerializeObject(result);
return new StringContent(strResult);
}
} return null;
}
}
}
- 当http中多个参数时,无法进行协议转换,因为不知道代理目标方法的参数集合是多少,只有全局假设一对一的参数目标。
- RPC客户端在网关中集成了大量的代理生成,无法实现动态更新,例如原来手动替换DLL,接口自动更新动态代理。
- 每一次调用都需要从大量的代理中查找指定(或模糊匹配)的方法名称,如果存在1KW+的接口名称,这个查找将是一个非常严重的瓶颈。
总结
NET Core微服务之路:基于Ocelot的API网关Relay实现--RPC篇的更多相关文章
- .NET Core微服务之路:文章系列和内容索引汇总 (v0.52)
微服务架构,对于从事JAVA架构的童鞋来说,早已不是什么新鲜的事儿,他们有鼎鼎大名的Spring Cloud这样的全家桶框架支撑,包含微服务核心组件如 1. Eureka:实现服务注册与发现. 2. ...
- .NET Core微服务之路:不断更新中的目录 (v0.43)
原文:.NET Core微服务之路:不断更新中的目录 (v0.43) 微服务架构,对于从事JAVA架构的童鞋来说,早已不是什么新鲜的事儿,他们有鼎鼎大名的Spring Cloud这样的全家桶框架支撑, ...
- NET Core微服务之路:实战SkyWalking+Exceptionless体验生产环境下的追踪系统
前言 当一个APM或一个日志中心实际部署在生产环境中时,是有点力不从心的. 比如如下场景分析的问题: 从APM上说,知道某个节点出现异常,或延迟过过高,却不能及时知道日志反馈情况,总不可能去相应的节点 ...
- NET Core微服务之路:实战SkyWalking+Exceptionless体验生产下追踪系统
原文:NET Core微服务之路:实战SkyWalking+Exceptionless体验生产下追踪系统 前言 当一个APM或一个日志中心实际部署在生产环境中时,是有点力不从心的. 比如如下场景分析的 ...
- .NET Core微服务之基于Ocelot实现API网关服务
Tip: 此篇已加入.NET Core微服务基础系列文章索引 一.啥是API网关? API 网关一般放到微服务的最前端,并且要让API 网关变成由应用所发起的每个请求的入口.这样就可以明显的简化客户端 ...
- .NET Core微服务之基于Ocelot实现API网关服务(续)
Tip: 此篇已加入.NET Core微服务基础系列文章索引 一.负载均衡与请求缓存 1.1 负载均衡 为了验证负载均衡,这里我们配置了两个Consul Client节点,其中ClientServic ...
- 基于.net core微服务(Consul、Ocelot、Docker、App.Metrics+InfluxDB+Grafana、Exceptionless、数据一致性、Jenkins)
1.微服务简介 一种架构模式,提倡将单一应用程序划分成一组小的服务,服务之间互相协调.互相配合,为用户提供最终价值.每个服务运行在其独立的进程中,服务与服务间采用轻量级的通信机制互相沟通(RESTfu ...
- NET Core微服务之路:自己动手实现Rpc服务框架,基于DotEasy.Rpc服务框架的介绍和集成
本篇内容属于非实用性(拿来即用)介绍,如对框架设计没兴趣的朋友,请略过. 快一个月没有写博文了,最近忙着两件事; 一:阅读刘墉先生的<说话的魅力>,以一种微妙的,你我大家都会经常遇见 ...
- .NET Core微服务之路:基于gRPC服务发现与服务治理的方案
重温最少化集群搭建,我相信很多朋友都已经搭建出来,基于Watch机制也实现了出来,相信也有很多朋友有了自己的实现思路,但是,很多朋友有个疑问,我API和服务分离好了,怎么通过服务中心进行发现呢,这个过 ...
随机推荐
- tp5.1入口文件隐藏
修改.htaccess文件 <IfModule mod_rewrite.c> Options +FollowSymlinks -Multiviews RewriteEngine On Re ...
- 先进过程控制之一:浅说APC
先进过程控制(APC)技术作为在生产装置级的信息化应用,在优化装置的控制水平和提高生产过程的管理水平的同时,还为企业创造了可观的经济效益. 1.什么是APC 先进过程控制,简称APC,并不是什么新概念 ...
- 烧写uboot和openwrt固件ARxx系列
以AR9331为例. 1.用烧录器将uboot烧写到flash中 (AR9331_U-Boot_Oolite-v1-v20170713.bin) 2.登录:192.168.1.1网页烧写uboot ...
- emacs Can't guess python-indent-offset, using defaults: 4
首先,这只是一个提示,Emacs 在打开python 文件时,如果是个空文件,会有此提示. 在python.el文件配置中,有如下代码: Python.el (defcustom python-ind ...
- html网页引用中文字体,解决加载缓慢办法
[ttf 压缩]html网页引用中文字体,文件过大,加载缓慢的解决办法[字蛛][web font] [字蛛]http://font-spider.org/ 先安装好 NodeJS,然后执行: npm ...
- docker-compose yaml mysql和wordpress 一行命令搞定~~~
version: '3.1' services: db: container_name: db image: mysql/mysql-server restart: always networks: ...
- python默认参数陷阱
对于学习python的人都有这样的困惑 def foo(a=[]): a.append(5) return a Python新手希望这个函数总是返回一个只包含一个元素的列表:[5].结果却非常不同,而 ...
- C++函数返回值为类对象但未调用复制构造函数
参考资料:https://blog.csdn.net/sxhelijian/article/details/50977946 不要迷信书本,要学会自己调试程序.
- hive中left/right join on连接中and与where的使用问题
很多同学在进行表关联的时候,and和where的使用有时候分不清,在这里实操记录下. 创建人员信息表并写入数据 create table tmp.userinfo(id string,name str ...
- USCiLab cereal json 序列化
cereal json 序列化 https://blog.csdn.net/sunnyloves/article/details/51373793?utm_source=blogxgwz8 http: ...