我们是怎么实现Grpc CodeFirst

简介:

我们是怎么实现Grpc CodeFirst
前言:

Grpc默认是ProtoFirst的,即先写 proto文件,再生成代码,需要人工维护proto,生成的代码也不友好,所以出现了Grpc CodeFirst,下面来说说我们是怎么实现Grpc CodeFirst

目录:

实现和WCF一样的CodeFirst

(1). 实现Grpc CodeFirst,  简化WCF一定要抽取接口的问题

(2). 通过代码生成proto和注释,给第三方语言使用

(3). 实现Grpc DashBoard,用于Http远程调用和管理

(4). 实现服务注册与发现

(5). 实现分布式日志跟踪

(6). 日志监控等等

我们是怎么实现Grpc CodeFirst

1.要实现CodeFirst先要了解ProtoFirst生成的代码,下面我截了部分生成代码

(1).关键是这个BindService,用于把实现的Grpc方法绑定到GrpcServiceDefinition

public static partial class Greeter
{

static readonly string __ServiceName = "helloworld.Greeter";

static readonly grpc::Marshaller<global::Helloworld.HelloRequest> __Marshaller_helloworld_HelloRequest = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Helloworld.HelloRequest.Parser.ParseFrom);
static readonly grpc::Marshaller<global::Helloworld.HelloReply> __Marshaller_helloworld_HelloReply = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Helloworld.HelloReply.Parser.ParseFrom);

static readonly grpc::Method<global::Helloworld.HelloRequest, global::Helloworld.HelloReply> __Method_SayHello = new grpc::Method<global::Helloworld.HelloRequest, global::Helloworld.HelloReply>(
    grpc::MethodType.Unary,
    __ServiceName,
    "SayHello",
    __Marshaller_helloworld_HelloRequest,
    __Marshaller_helloworld_HelloReply);

static readonly grpc::Method<global::Helloworld.HelloRequest, global::Helloworld.HelloReply> __Method_SayHelloStream = new grpc::Method<global::Helloworld.HelloRequest, global::Helloworld.HelloReply>(
    grpc::MethodType.ClientStreaming,
    __ServiceName,
    "SayHelloStream",
    __Marshaller_helloworld_HelloRequest,
    __Marshaller_helloworld_HelloReply);

/// <summary>Creates service definition that can be registered with a server</summary>
/// <param name="serviceImpl">An object implementing the server-side handling logic.</param>
public static grpc::ServerServiceDefinition BindService(GreeterBase serviceImpl)
{
  return grpc::ServerServiceDefinition.CreateBuilder()
      .AddMethod(__Method_SayHello, serviceImpl.SayHello)
      .AddMethod(__Method_SayHelloStream, serviceImpl.SayHelloStream).Build();
}

/// <summary>Register service method with a service binder with or without implementation. Useful when customizing the  service binding logic.
/// Note: this method is part of an experimental API that can change or be removed without any prior notice.</summary>
/// <param name="serviceBinder">Service methods will be bound by calling <c>AddMethod</c> on this object.</param>
/// <param name="serviceImpl">An object implementing the server-side handling logic.</param>
public static void BindService(grpc::ServiceBinderBase serviceBinder, GreeterBase serviceImpl)
{
  serviceBinder.AddMethod(__Method_SayHello, serviceImpl == null ? null : new grpc::UnaryServerMethod<global::Helloworld.HelloRequest, global::Helloworld.HelloReply>(serviceImpl.SayHello));
  serviceBinder.AddMethod(__Method_SayHelloStream, serviceImpl == null ? null : new grpc::ClientStreamingServerMethod<global::Helloworld.HelloRequest, global::Helloworld.HelloReply>(serviceImpl.SayHelloStream));
}

}

(2).__Marshaller_helloworld_HelloRequest这个是实现protobuffer的序列化和反序列化的一个委托

服务的请求参数和返回参数,我们使用Protobuf-net来实现序列化和反序列化,和 WCF一样需要给类打上标签

/// <summary>
/// 加法请求参数
/// </summary>
[ProtoContract]
public class AddRequest
{
    /// <summary>
    /// 第一个数字
    /// </summary>
    [ProtoMember(1)]
    public int Num1 { get; set; }

    /// <summary>
    /// 第二个数字
    /// </summary>
    [ProtoMember(2)]
    public int Num2 { get; set; }
}

2.要实现CodeFirst需要实现这个BindService,把我们的Grpc方法添加到ServerServiceDefinition

(1).我们让Grpc服务实现IGrpcService空接口,用于标识是GrpcService

/// <summary>
/// MathGrpc
/// </summary>
public class MathGrpc : IGrpcService
{
    /// <summary>
    /// 加法
    /// </summary>
    /// <param name="request"></param>
    /// <param name="context"></param>
    /// <returns></returns>
    public Task<IntMessage> Add(AddRequest request, ServerCallContext context)
    {
        var result = new IntMessage();
        result.Value = request.Num1 + request.Num2;
        return Task.FromResult(result);
    }

}

(2).获取实现了IGrpcService接口的类,然后反射获取方法,再添加到ServerServiceDefinition即可

    /// <summary>
/// 注入IGrpcService
/// </summary>
/// <param name="grpcServices"></param>
/// <returns></returns>
private ServerBuilder UseGrpcService(IEnumerable<IGrpcService> grpcServices)
{
    var builder = ServerServiceDefinition.CreateBuilder();
    grpcServices.ToList().ForEach(grpc => GrpcMethodHelper.AutoRegisterMethod(grpc, builder));
    _serviceDefinitions.Add(builder.Build());
    return this;
}

未完,待续,欢迎评论拍砖

这些功能早在2018年就已经实现并运行在生产,感兴趣的同学可以去 github上查看,你要的都有,欢迎提issue

作  者: 易   磊(Rabbit_Yi)
出  处: http://www.cnblogs.com/rabbityi/

相关文章
|
机器学习/深度学习 人工智能 安全
平均每天有一个隐私计算专利在提交,他们是怎么做到的?
平均每天有一个隐私计算专利在提交,他们是怎么做到的?
348 0
|
Linux 测试技术 Docker
Linux系统:第十三章:centos误删文件如何恢复文件数据
Linux系统:第十三章:centos误删文件如何恢复文件数据
992 0
Linux系统:第十三章:centos误删文件如何恢复文件数据
|
8月前
|
数据采集 监控 API
加密货币 Pump 监测刮刀工具开发原理及实现路径
开发Pump监测刮刀工具需综合运用高频数据采集、波动率建模、跨平台对冲三大核心技术,2025年的技术瓶颈已从基础数据获取转向超低延迟执行与合规适配。建议采用模块化开发策略,优先实现核心监控功能,再逐步接入AI决策与链上套利模块。代码示例需根据最新交易所API文档动态调整,并严格遵守所在地监管法规。
|
存储 安全 数据管理
python如何批量创建文件与文件夹
python如何批量创建文件与文件夹
498 0
|
9月前
|
数据采集 Web App开发 负载均衡
代理IP:数据抓包中的"隐形斗篷"与"加速器"
本文深入解析代理IP在数据抓包中的五大核心作用。一是突破反爬机制,通过IP轮换、请求头伪装和流量混淆隐藏身份;二是突破地理限制,实现城市级或国家级精准定位;三是提升分布式抓取效率,支持并行采集与负载均衡;四是保障数据安全,提供加密传输与匿名防护;五是应对潜在风险,如速度损耗与法律问题。文章结合实际案例,展示代理IP如何从简单中转进化为智能指挥工具,助力开发者高效获取网络信息。
236 4
|
自然语言处理 JavaScript Java
Spring 实现 3 种异步流式接口,干掉接口超时烦恼
本文介绍了处理耗时接口的几种异步流式技术,包括 `ResponseBodyEmitter`、`SseEmitter` 和 `StreamingResponseBody`。这些工具可在执行耗时操作时不断向客户端响应处理结果,提升用户体验和系统性能。`ResponseBodyEmitter` 适用于动态生成内容场景,如文件上传进度;`SseEmitter` 用于实时消息推送,如状态更新;`StreamingResponseBody` 则适合大数据量传输,避免内存溢出。文中提供了具体示例和 GitHub 地址,帮助读者更好地理解和应用这些技术。
2427 122
|
运维 监控 Linux
推荐几个不错的 Linux 服务器管理工具
推荐几个不错的 Linux 服务器管理工具
959 6
|
前端开发 JavaScript 搜索推荐
前端懒加载:提升页面性能的关键技术
前端懒加载是一种优化网页加载速度的技术,通过延迟加载非首屏内容,减少初始加载时间,提高用户访问体验和页面性能。
|
JavaScript 前端开发 Java
JavaScript中的面向对象编程(OOP) - 终极指南
本文介绍了 JavaScript 的面向对象编程 (OOP) 概念,包括继承、多态、封装和抽象等关键要素,并通过代码示例帮助开发者理解和应用 OOP 思维。
270 5
|
前端开发 图形学 开发者
【独家揭秘】那些让你的游戏瞬间鲜活起来的Unity UI动画技巧:从零开始打造动态按钮,提升玩家交互体验的绝招大公开!
【9月更文挑战第1天】在游戏开发领域,Unity 是最受欢迎的游戏引擎之一,其强大的跨平台发布能力和丰富的功能集让开发者能够迅速打造出高质量的游戏。优秀的 UI 设计对于游戏至关重要,尤其是在手游市场,出色的 UI 能给玩家留下深刻的第一印象。Unity 的 UGUI 系统提供了一整套解决方案,包括 Canvas、Image 和 Button 等组件,支持添加各种动画效果。
1008 3