当前位置: 移动技术网 > IT编程>开发语言>.net > 我们是怎么实现gRPC CodeFirst

我们是怎么实现gRPC CodeFirst

2020年04月01日  | 移动技术网IT编程  | 我要评论

杰西达邦主演的电视剧爱的旋律,写轮眼异界逍遥,一个身份证可以开几个淘宝店

前言:

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

 

目录:

实现和wcf一样的codefirst

(1). 实现grpc codefirst,  简化wcf一定要抽取接口的问题

(2). 

(3). 实现grpc dashboard,用于http远程调用和管理

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

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

(6). 日志监控等等

 

 

我们是怎么实现grpc codefirst

 

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

(1).关键是这个bindservice,用于把实现的grpc方法绑定到serverservicedefinition

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即可

这里调用了grpcmethodhelper.autoregistermethod()方法,这是通过反射自动注册grpcmethod的方法

        /// <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

 

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网