zoukankan      html  css  js  c++  java
  • 让 gRPC 提供 REST 服务

    让 gRPC 提供 REST 服务

    Intro

    gRPC 是一个高性能、开源和通用的 RPC 框架,面向移动和 HTTP/2 设计。

    gRPC 基于 HTTP/2 标准设计,带来诸如双向流、流控、头部压缩、单 TCP 连接上的多复用请求等特。这些特性使得其在移动设备上表现更好,更省电和节省空间占用。

    gRPC 是一个很流行的现代化 RPC 框架,它以 HTTP/2 为通信协议基础,gRPC 默认使用 protocol buffers 作为接口定义语言,来描述服务接口和有效载荷消息结构。

    尽管 gRPC 有很多应用,但是更为常用的还是基于 HTTP/1.1 的 REST 服务,应用更广,那么能否让 gRPC 同时提供 REST 服务呢?答案是肯定的,现在有一个实验性的项目(gRPC HTTP API )正在进行,如果觉得这个项目不错,欢迎在 Github 上进行反馈,将你的意见反馈给 gRPC 团队或者去点个赞以提升项目的优先级 https://github.com/grpc/grpc-dotnet/issues/167

    gRPC loves REST

    Sample

    Proto

    首先我们来看一下 proto file:

    syntax = "proto3";
    //
    import "google/api/annotations.proto";
    
    package greet.v1;
    
    service Greeter {
      rpc SayHello (HelloRequest) returns (HelloReply) {
        option (google.api.http) = {
          get: "/v1/greeter/{name}"
        };
      }
      rpc SayHelloFrom (HelloRequestFrom) returns (HelloReply) {
        option (google.api.http) = {
          post: "/v1/greeter"
          body: "*"
        };
      }
    }
    
    message HelloRequest {
      string name = 1;
    }
    
    message HelloRequestFrom {
      string name = 1;
      string from = 2;
    }
    
    message HelloReply {
      string message = 1;
    }
    

    和之前相比的变化就是引入了 google/api/annotations.proto,然后在声明方法的地方声明了 http 请求的方式和路由

    Project update

    除了 proto file 变化之外,我们还需要引用 Microsoft.AspNetCore.Grpc.HttpApi 这个包,为了更好的和 swagger 整合,也可以引用 Microsoft.AspNetCore.Grpc.Swagger 这是一个 swagger 的扩展

    Startup 中注册服务:

    services.AddGrpcHttpApi();
    

    如果引用了 swagger,也要注册相应的服务:

    services.AddSwaggerGen(c =>
        {
            c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" });
        })
        .AddGrpcSwagger();
    

    这样就可以了

    Client Sample

    客户端调用示例如下:

    using var client = new HttpClient()
    {
        DefaultRequestVersion = HttpVersion.Version20,
        DefaultVersionPolicy = HttpVersionPolicy.RequestVersionOrHigher,
    };
    await InvokeHelper.TryInvokeAsync(async () =>
    {
        var responseText = await client.GetStringAsync("https://localhost:5001/v1/greeter/test");
        Console.WriteLine($"Response from https endpoint: {responseText}");
    });
    await InvokeHelper.TryInvokeAsync(async () =>
    {
        var responseText = await client.GetStringAsync("http://localhost:5000/v1/greeter/test");
        Console.WriteLine($"Response from http endpoint: {responseText}");
    });
    
    //
    await InvokeHelper.TryInvokeAsync(async () =>
    {
        var responseText = await client.GetStringAsync("http://localhost:5000/v1/todo");
        Console.WriteLine($"Response from todo endpoint: {responseText}");
    });
    

    客户端输出示例:

    服务器端输出示例:

    完整的测试代码可以在 Github 获取 https://github.com/WeihanLi/SamplesInPractice/tree/master/GrpcSample

    Known Issues

    JSON Serialization

    现在的 JSON 序列化是基于Google.Protobuf,这个实现有两个问题:

    • 它是线程阻塞的(非 async
    • 没有做过性能优化

    Http proto file

    需要在最终用户的源代码中添加 google / api / annotations.protogoogle / api / http.proto,以便Protobuf编译器可以将它们与用户的proto文件一起加载。 如果以某种方式用户不必关心这些文件,那将是更好的开发人员体验。

    More

    这个项目使用下来感觉还是挺方便的,相当于在 proto 文件中加了 http 请求相关的注解,就可以自动提供 REST 服务,这样对于 gRPC 和 REST 服务的整合就很方便了

    唯一让我觉得有一些美中不足的地方就是 http 只支持 Http2,如果 http 协议要支持 http1.1 的话,http请求 必须要 https,如果是 http2 就可以比较好的支持 http,但是大部分的客户端都是 httpClient 都是直接请求的,大多没有设置过 Http Version,要手动设置 http2 才可以

    如果觉得还不错,记得去 GitHub 上反馈哈 https://github.com/grpc/grpc-dotnet/issues/167

    References

    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    文件工具类之FileUtils
    JAVA8日期工具类
    mybatis模糊查询匹配汉字查询不出来数据,匹配字符和数字却可以的问题解决
    问到ConcurrentHashMap不要再提Segment了
    开发中常用工具
    Spring 如何解决循环依赖?
    JVM8基础概念总结
    String字符串相等判断
    面试再也不怕问到HashMap(二)
    面试再也不怕问到HashMap(一)
  • 原文地址:https://www.cnblogs.com/weihanli/p/14414396.html
Copyright © 2011-2022 走看看