zoukankan      html  css  js  c++  java
  • (二) gRPC初探之代码优先方法进行 API 开发

    我们接着上一篇 (一) gRPC初探之协定优先方法进行 API 开发 来讲,基于proto协定优先的方式开发服务是在不限语言的基础上,当整个系统使用 .NET开发时,我们可以使用代码优先:

    • 可以在 .NET 服务器和客户端之间共享 .NET 服务和数据协定类型
    • 无需在 .proto 文件和代码生成过程中定义协定

    protobuf-net.Grpc

    基于 .NET版本的gRPC社区开源项目.通过属性注解的 .NET 类型来定义应用的 gRPC 服务和消息

    项目结构

    image

    创建服务和数据协定类型

    • 创建GrpcService1.Shared项目并添加 protobuf-net.Grpc 包引用
    • 创建出参/入参并定义接口
    • 添加属性批注
    namespace GrpcService1.Shared
    {
        using System.Runtime.Serialization;
        [DataContract]
        public class CreateOrderInput
        {
            [DataMember(Order = 1)]
            public int BuyerId { get; set; }
    
            [DataMember(Order = 2)]
            public string BuyerName { get; set; }
    
            [DataMember(Order = 3)]
            public int OrderId { get; set; }
    
            [DataMember(Order = 4)]
            public string OrderName { get; set; }
        }
    }
    
    
    namespace GrpcService1.Shared
    {
        using System.Runtime.Serialization;
        [DataContract]
        public class CreateOrderOutput
        {
            [DataMember(Order = 1)]
            public int BuyerId { get; set; }
    
            [DataMember(Order = 2)]
            public string BuyerName { get; set; }
    
            [DataMember(Order = 3)]
            public int OrderId { get; set; }
    
            [DataMember(Order = 4)]
            public string OrderName { get; set; }
        }
    }
    
    
    namespace GrpcService1.Shared
    {
        using ProtoBuf.Grpc;
        using System.ServiceModel;
        using System.Threading.Tasks;
    
        [ServiceContract]
        public interface IOrderService
        {
            [OperationContract]
            Task<CreateOrderOutput> CreateOrderAsync(CreateOrderInput request, CallContext context = default);
        }
    }
    
    

    创建代码优先gRPC服务

    • 创建 GrpcService1API
    • 添加protobuf-net.Grpc.AspNetCore包引用
    • 添加 GrpcService1.Shared项目引用
    • 在项目路径添加/Service/OrderService.cs代码如下
    namespace GrpcService1.Shared
    {
        using ProtoBuf.Grpc;
        using System.Threading.Tasks;
        public class OrderService : IOrderService
        {
            public async Task<CreateOrderOutput> CreateOrderAsync(CreateOrderInput request, CallContext context = default)
            {
                return await Task.FromResult(new CreateOrderOutput
                {
                    BuyerId = request.BuyerId,
                    BuyerName = request.BuyerName,
                    OrderId = request.OrderId,
                    OrderName = request.OrderName,
                });
            }
        }
    }
    
    • 配置Startup.cs
    namespace GrpcService1
    {
        using GrpcService1.Services;
    
        using Microsoft.AspNetCore.Builder;
        using Microsoft.AspNetCore.Hosting;
        using Microsoft.Extensions.DependencyInjection;
        using Microsoft.Extensions.Hosting;
        using Microsoft.Extensions.Logging;
    
        using ProtoBuf.Grpc.Server;
    
        public class Startup
        {
            // This method gets called by the runtime. Use this method to add services to the container.
            // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
            public void ConfigureServices(IServiceCollection services)
            {
                // 关键代码
                services.AddCodeFirstGrpc();//注册启用了代码优先的服务。
                // 关键代码
                
                
                services.AddLogging(options => 
                {
                    options.AddConsole();
                });
    
            }
    
            // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
            public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
            {
                if (env.IsDevelopment())
                {
                    app.UseDeveloperExceptionPage();
                }
    
                app.UseRouting();
    
                var log = app.ApplicationServices.GetService<ILoggerFactory>()?.CreateLogger(env.ApplicationName);
                log.LogInformation("Hello world");
                app.UseEndpoints(endpoints =>
                {
                     // 关键代码 
                    endpoints.MapGrpcService<OrderService>();//添加代码优先的服务终结点。
                     // 关键代码
                     
                     
                    //endpoints.MapGet("/", async context =>
                    // {
                    //    await context.Response.WriteAsync("Hello world");
                    // });
                });
            }
        }
    }
    
    

    创建代码优先gRPC客户端

    • 创建 dotnetcore 控制台应用程序
    • 添加 Grpc.Net.Client包引用
    • 添加protobuf-net.Grpc引用
    namespace GrpcClient1
    {
        using Grpc.Net.Client;
        using GrpcService1.Shared;
        using ProtoBuf.Grpc.Client;
    
        using System;
        using System.Net.Http;
        using System.Text.Json;
        using System.Text.Unicode;
        using System.Threading.Tasks;
        class Program
        {
            static async Task Main(string[] args)
            {
                //  使用不受信任/无效证书调用 gRPC 服务
                var httpHandler = new HttpClientHandler();
                httpHandler.ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
    
                using var channel = GrpcChannel.ForAddress("https://localhost:5001", new GrpcChannelOptions { HttpHandler = httpHandler });
                var client = channel.CreateGrpcService<IOrderService>();
    
                var result = await client.CreateOrderAsync(new CreateOrderInput
                {
                    BuyerId = 1,
                    BuyerName = "张小三",
                    OrderId = 1,
                    OrderName = "方便面",
                });
                var options = new JsonSerializerOptions();
                options.Encoder = System.Text.Encodings.Web.JavaScriptEncoder.Create(UnicodeRanges.All);
                Console.WriteLine(System.Text.Json.JsonSerializer.Serialize(result, options));
                Console.ReadKey();
                 
            }
        }
    }
    
    

    控制台输出:

    image

    示例已上传到本人github

  • 相关阅读:
    Hexo命令无法找到 -问题修复
    技术的本质
    java 多线程总结篇4——锁机制
    java 多线程总结篇3之——生命周期和线程同步
    java 多线程总结篇2之——Thread类及常用函数
    java 多线程总结篇1之——基本概念
    java IO流的继承体系和装饰类应用
    java IO流知识点总结
    java IO流之——File类知识总结和面试
    为什么需要学UML建模
  • 原文地址:https://www.cnblogs.com/imtudou/p/14611754.html
Copyright © 2011-2022 走看看