中间件想必大家不陌生,今天给大家介绍如何实现中间件以及实现gRPC的客户端中间件。

什么是中间件?

https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/middleware/index?view=aspnetcore-2.1&tabs=aspnetcore2x

中间件管道

先定义管道Pipeline

/// <summary>
/// Built pipeline for gRPC
/// </summary>
public class Pipeline
{
private PipelineDelagate processChain; internal Pipeline(PipelineDelagate middlewareChain)
{
processChain = middlewareChain;
} internal Task RunPipeline(MiddlewareContext context)
{
return processChain(context);
}
}

然后实现PipelineBuilder

/// <summary>
/// PipelineBuilder
/// </summary>
public class PipelineBuilder
{
private List<Func<PipelineDelagate, PipelineDelagate>> middlewares = new List<Func<PipelineDelagate, PipelineDelagate>>(); /// <summary>
/// Add a middleware
/// </summary>
public PipelineBuilder Use(Func<PipelineDelagate, PipelineDelagate> middleware)
{
middlewares.Add(middleware);
return this;
} /// <summary>
/// Use
/// </summary>
public PipelineBuilder Use<T>(params object[] args)
{
middlewares.Add(d => WrapClass<T>(d, args));
return this;
} /// <summary>
/// UseWhen
/// </summary>
public PipelineBuilder UseWhen<T>(Func<MiddlewareContext, bool> condition, params object[] args)
{
middlewares.Add(d =>
{
return async ctx => { if (condition(ctx)) { await WrapClass<T>(d, args)(ctx); } };
});
return this;
} /// <summary>
/// Use
/// </summary>
public PipelineBuilder Use(Func<MiddlewareContext, PipelineDelagate, Task> middleware)
{
middlewares.Add(d =>
{
return ctx => { return middleware(ctx, d); };
});
return this;
} private PipelineDelagate WrapClass<T>(PipelineDelagate next, params object[] args)
{
var ctorArgs = new object[args.Length + 1];
ctorArgs[0] = next;
Array.Copy(args, 0, ctorArgs, 1, args.Length);
var type = typeof(T);
var instance = Activator.CreateInstance(type, ctorArgs);
MethodInfo method = type.GetMethod("Invoke");
return (PipelineDelagate)method.CreateDelegate(typeof(PipelineDelagate), instance);
} /// <summary>
/// Build
/// </summary>
public Pipeline Build()
{
PipelineDelagate pipeline = ExecuteMainHandler;
middlewares.Reverse();
foreach (var middleware in middlewares)
{
pipeline = middleware(pipeline);
}
return new Pipeline(pipeline);
} internal static Task ExecuteMainHandler(MiddlewareContext context)
{
return context.HandlerExecutor();
}
}
MiddlewareContext 和 委托定义
/// <summary>
/// MiddlewareContext
/// </summary>
public class MiddlewareContext
{
public IMethod Method { get; set; } public object Request { get; set; } public object Response { get; set; } public string Host { get; set; } public CallOptions Options { get; set; } internal Func<Task> HandlerExecutor { get; set; }
} public delegate Task PipelineDelagate(MiddlewareContext context);

到这里管道建设完成,那个如何在gRPC中使用呢?

首先实现自己的客户端拦截器MiddlewareCallInvoker

 public sealed class MiddlewareCallInvoker : DefaultCallInvoker
{
private readonly Channel grpcChannel; private Pipeline MiddlewarePipeline { get; set; } public MiddlewareCallInvoker(Channel channel) : base(channel)
{
this.grpcChannel = channel;
} public MiddlewareCallInvoker(Channel channel, Pipeline pipeline) : this(channel)
{
this.MiddlewarePipeline = pipeline;
} private TResponse Call<TResponse>(Func<MiddlewareContext, TResponse> call, MiddlewareContext context)
{ TResponse response = default(TResponse);
if (MiddlewarePipeline != null)
{
context.HandlerExecutor = async () =>
{
response = await Task.FromResult(call(context));
context.Response = response;
};
MiddlewarePipeline.RunPipeline(context).ConfigureAwait(false);
}
else
{
response = call(context);
}
return response; } public override TResponse BlockingUnaryCall<TRequest, TResponse>(Method<TRequest, TResponse> method,
string host, CallOptions options, TRequest request)
{
return Call((context) => base.BlockingUnaryCall((Method<TRequest, TResponse>)context.Method, context.Host, context.Options, (TRequest)context.Request), new MiddlewareContext
{
Host = host,
Method = method,
Options = options,
Request = request,
Response = null
});
} public override AsyncUnaryCall<TResponse> AsyncUnaryCall<TRequest, TResponse>(
Method<TRequest, TResponse> method, string host, CallOptions options, TRequest request)
{
return Call((context) => base.AsyncUnaryCall((Method<TRequest, TResponse>)context.Method, context.Host, context.Options, (TRequest)context.Request), new MiddlewareContext
{
Host = host,
Method = method,
Options = options,
Request = request,
Response = null
});
} public override AsyncServerStreamingCall<TResponse> AsyncServerStreamingCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options,
TRequest request)
{
return Call((context) => base.AsyncServerStreamingCall((Method<TRequest, TResponse>)context.Method, context.Host, context.Options, (TRequest)context.Request), new MiddlewareContext
{
Host = host,
Method = method,
Options = options,
Request = request,
Response = null
});
} public override AsyncClientStreamingCall<TRequest, TResponse> AsyncClientStreamingCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options)
{
return Call((context) => base.AsyncClientStreamingCall((Method<TRequest, TResponse>)context.Method, context.Host, context.Options), new MiddlewareContext
{
Host = host,
Method = method,
Options = options,
Request = null,
Response = null
});
} public override AsyncDuplexStreamingCall<TRequest, TResponse> AsyncDuplexStreamingCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options)
{
return Call((context) => base.AsyncDuplexStreamingCall((Method<TRequest, TResponse>)context.Method, context.Host, context.Options), new MiddlewareContext
{
Host = host,
Method = method,
Options = options,
Request = null,
Response = null
});
}
}
到这里基于管道的中间件基本完成。接下来就是在客户端使用了
 var pipeline = new PipelineBuilder()
//.Use<ExceptionMiddleware>()
//.Use<TimerMiddleware>()
//.Use<LoggingMiddleware>()
//.Use<TimeoutMiddleware>()
.Use<PolicyMiddleware>(new PolicyMiddlewareOptions
{
RetryTimes = 2,
TimoutMilliseconds = 100
})
;
//pipeline.Use<LoggingMiddleware>();// pipeline.UseWhen<LoggingMiddleware>(ctx => ctx.Context.Method.EndsWith("SayHello"));
//pipeline.Use<TimeoutMiddleware>(new TimeoutMiddlewareOptions { TimoutMilliseconds = 1000 });
//console logger
pipeline.Use(async (ctx, next) =>
{
Console.WriteLine(ctx.Request.ToString());
await next(ctx);
Console.WriteLine(ctx.Response.ToString());
}); Channel channel = new Channel("127.0.0.1:50051", ChannelCredentials.Insecure);
MiddlewareCallInvoker callInvoker = new MiddlewareCallInvoker(channel, pipeline.Build()); var clientApi = new Get.GetClient(callInvoker); var replyApi = clientApi.SayHello(new ContractsSample1.HelloApiDemo.HelloRequest { Name = " APII" });
Console.WriteLine("Greeting: " + replyApi.Message);

  Middleware

 public class LoggingMiddleware
{
private PipelineDelagate _next; public LoggingMiddleware(PipelineDelagate next)
{
_next = next;
} public async Task Invoke(MiddlewareContext context)
{
//Before
await _next(context);
//End
}
}

  至此已完成所有工作。希望能够帮助到大家。

如果有机会将给大家介绍gRPC跨平台网关,该网关能够实现自动将下游的gRPC服务转化成http api,只需要你的proto文件即可。如果你使用consul,甚至无需你做任务配置。

gRPC Client Middleware.的更多相关文章

  1. gRPC Client的负载均衡器

    一.gRPC是什么? gRPC是一个高性能.通用的开源RPC框架,其由Google主要面向移动应用开发并基于HTTP/2协议标准而设计,基于ProtoBuf(Protocol Buffers)序列化协 ...

  2. Building gRPC Client iOS Swift Note Taking App

    gRPC is an universal remote procedure call framework developed by Google that has been gaining inter ...

  3. yoyogo v1.7.4 发布,支持 grpc v1.3.8 & etcd 3.5.0

    YoyoGo (Go语言框架)一个简单.轻量.快速.基于依赖注入的微服务框架( web .grpc ),支持Nacos/Consoul/Etcd/Eureka/k8s /Apollo等 . https ...

  4. gRPC源码分析1-SSL/TLS

    引子 前几天看到微信后台团队分享了TLS相关文章,正好gRPC里TLS数据加密是很重要的一块,于是整理出了这篇文章. 在gRPC里,如果仅仅是用来做后端微服务,可以考虑不加密.本文太长,先给个大纲. ...

  5. gRPC .NET Core跨平台学习

    前些天发布gRPC C# 学习,在.NET Framework 中使用gRPC ,今天来学习 .NET Core gRPC. gRPC 的.NET Core 包在NuGet 上发布了,结合.NET C ...

  6. gRPC helloworld service, RESTful JSON API gateway and swagger UI

    概述 本篇博文完整讲述了如果通过 protocol buffers 定义并启动一个 gRPC 服务,然后在 gRPC 服务上提供一个 RESTful JSON API 的反向代理 gateway,最后 ...

  7. 开始食用grpc(之一)

    开始食用grpc(之一) 转载请注明出处:https://www.cnblogs.com/funnyzpc/p/9501353.html ```   记一次和一锅们压马路,路过一咖啡厅(某巴克),随口 ...

  8. gRPC 在 Python中的应用

    python -m grpc_tools.protoc --proto_path=. --python_out=. --grpc_python_out=. hello.proto 简介 在python ...

  9. Abp + gRpc 如何实现用户会话状态传递

    0.背景 在实际项目当中,我们采用的是 Abp 框架,但是 Abp 框架官方并没有针对 Grpc 进行模块封装.基于此我结合 Abp 与 MagicOnion 封装了一个 Abp.Grpc 模块,它包 ...

随机推荐

  1. Spring Boot(一):环境搭建,建立简单项目

    一.基本环境搭建 1.下载IntelliJ IDEA :http://www.jetbrains.com/idea/ 2.拖到页面最下面下载旗舰版 3.新建项目 4.设置本地Maven 5.删除多于文 ...

  2. STM32 内部flash的读写程序

    ​ /* Base address of the Flash sectors */ #define ADDR_FLASH_SECTOR_0 ((uint32_t)0x08000000) /* Base ...

  3. 2018-2019-2 20165236 《网络对抗技术》Exp4 恶意代码分析

    2018-2019-2 20165236 <网络对抗技术>Exp4 恶意代码分析 一.1.实践目标 1.1是监控你自己系统的运行状态,看有没有可疑的程序在运行; 1.2是分析一个恶意软件, ...

  4. 2019春第六周作业Compile Summarize

    这个作业属于那个课程 C语言程序设计II 这个作业要求在哪里 在这里 我在这个课程的目标是 能够熟练掌握指针的用法 这个作业在那个具体方面帮助我实现目标 对指针的使用更加得心应手 参考文献与网址 C语 ...

  5. Python socket的客户端

    做一个socket客户端1.声明一个实例2.绑定端口号和地址3.循环发送和接收响应其中要注意粘包的产生,为了防止粘包的产生,应该在服务器端先测出要发送信息的大小,然后发送响应至客户端,等到服务器上一条 ...

  6. 大兄dei,早点看清this吧

    说道this,可以说是前端中很重要的问题之一了,也是面试或者笔试常考的问题.所以还是早点看清this吧,大兄dei. this是什么?为什么要存在? this关键字是js中最最复杂的机制之一.他被自动 ...

  7. 【速读】——Shangxuan Tian——【ICCV2017】WeText_Scene Text Detection under Weak Supervision

    Shangxuan Tian——[ICCV2017]WeText_Scene Text Detection under Weak Supervision 目录 作者和相关链接 文章亮点 方法介绍 方法 ...

  8. RocketMQ基本概念

    RocketMQ基本概念 一.生产者 生产者发送业务系统产生的消息给broker.RocketMQ提供了多种发送方式:同步的.异步的.单向的. 1.1 生产者组 具有相同角色的生产者被分到一组.假如原 ...

  9. 使用Configuration Extensions读取配置

    使用Configuration Extensions读取配置 Configuration Extensions 是微软基于Configuration的扩展,能够很好的解析系统遇到各种配置文件,包括js ...

  10. 【javascript】随机颜色

    调用该方法则会返回一个#xxx的rgb随机颜色 function color1(){ var sum=""; var shuzu2=['a','b','c','d','e','f' ...