让 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

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

让 gRPC 提供 REST 服务的更多相关文章

  1. grpc提供http服务

    package main import ( "google.golang.org/grpc" "google.golang.org/grpc/credentials&qu ...

  2. .net core grpc consul 实现服务注册 服务发现 负载均衡(二)

    在上一篇 .net core grpc 实现通信(一) 中,我们实现的grpc通信在.net core中的可行性,但要在微服务中真正使用,还缺少 服务注册,服务发现及负载均衡等,本篇我们将在 .net ...

  3. ASP.NET Core gRPC 使用 Consul 服务注册发现

    一. 前言 gRPC 在当前最常见的应用就是在微服务场景中,所以不可避免的会有服务注册与发现问题,我们使用gRPC实现的服务可以使用 Consul 或者 etcd 作为服务注册与发现中心,本文主要介绍 ...

  4. .Net Core Grpc Consul 实现服务注册 服务发现 负载均衡

    本文是基于..net core grpc consul 实现服务注册 服务发现 负载均衡(二)的,很多内容是直接复制过来的,..net core grpc consul 实现服务注册 服务发现 负载均 ...

  5. 微服务架构攀登之路(四)之使用gRPC构建微服务

    做一个处理用户信息的微服务 客户端通过用户名,可以从服务端查询用户的基本信息 gRPC proto user.proto 定义客户端请求.服务端响应的数据格式 user.pb.go 自动生成的,为数据 ...

  6. 如何基于gRPC沟通微服务框架

    本文我们来讲解一下如何使用 gRPC构建微服务,gRPC是一个开源框架,可用于构建可扩展且高性能的微服务并创建服务之间的通信. 背景 随着企业越来越多地转向微服务,对构建这些微服务的低延迟和可扩展框架 ...

  7. Windows Azure HandBook (2) Azure China提供的服务

    <Windows Azure Platform 系列文章目录> 对于传统的自建数据中心,从底层的Network,Storage,Servers,Virtualization,中间层的OS, ...

  8. 提供RESTful服务

    RESTful广泛运用于互联网服务,而在企业应用中,大部分场景仍然是RPC服务,这是由于企业应用的业务复杂性造成的.但是基于SOAP的RPC服务也存在很多的弊端,比如服务异步处理比较麻烦,大部分RPC ...

  9. 第13章 使用Bind提供域名解析服务

    章节简述: 本章节将让您理解DNS服务程序的原理,学习正向解析与反向解析实验,掌握DNS主服务器.从服务器.缓存服务器的部署方法. 够熟练配置区域信息文件与区域数据文件,以及通过使用分离解析技术让不同 ...

随机推荐

  1. HTTP1.0/1.1/2.0

    https://www.cnblogs.com/heluan/p/8620312.html http缓存策略 https://www.cnblogs.com/Iwillknow/archive/201 ...

  2. c++复习笔记(4)

    这一篇是另一篇各种琐碎东西的笔记. 类型转换可以通过类型转换函数,或者构造函数来实现.但是一般来说类型转换指的是类型转换函数. 类型转换函数不需要声明输出类型(因为输出类型是固定的),也没有参数,同时 ...

  3. Java根据路径获取文件内容

    文章目录 一.思路 二.实现 给出一个资源路径.然后获取资源文件信息,常见三种方式:①网络地址 ②本地绝对路径 ③本地相对路径 一.思路 首先,给出一个string表示资源文件的标识,如何判断是网络中 ...

  4. Linux系统安装时分区的选择(转)

    原文地址:http://www.cnblogs.com/gylei/archive/2011/12/04/2275987.html 前言: 以前初识Linux时,对Linux系统安装时分区的选择,一点 ...

  5. Linux系统磁盘管理(lvm逻辑卷管理)

    linux系统用户常遇到的一个问题就是如何精准的评估分区的大小,已分配合适的磁盘空间:普通的磁盘分区管理方式在逻辑分区划分好之后就无法改变其大小,当一个逻辑分区存放不下某个文件时,这个文件因为受上层文 ...

  6. HDOJ 1078

    标准的DAG上的DP,其实之前一直不大想得明白为什么dp[i][j]为什么一定是在(i,j)状态上的局部最优解了呢? 其实仔细想想和我一般所做的DP是一个道理,因为运用dfs的方法,因此可以确定的是, ...

  7. HDU-3081-Marriage Match II 二分图匹配+并查集 OR 二分+最大流

    二分+最大流: 1 //题目大意:有编号为1~n的女生和1~n的男生配对 2 // 3 //首先输入m组,a,b表示编号为a的女生没有和编号为b的男生吵过架 4 // 5 //然后输入f组,c,d表示 ...

  8. windows下进程间通信方法

    摘 要 随着人们对应用程序的要求越来越高,单进程应用在许多场合已不能满足人们的要求.编写多进程/多线程程序成为现代程序设计的一个重要特点,在多进程程序设计中,进程间的通信是不可避免的.Microsof ...

  9. CF1400-D. Zigzags

    CF1400-D. Zigzags 题意: 给出一个由\(n\)个数字构成的数组\(a\),让你在这个数组中找出有多少个符合以下要求的元组\((i,j,k,l)\): 1. \(i<j<k ...

  10. OpenStack Train版-11.安装horizon服务(计算节点)

    OpenStack仪表板Dashboard服务的项目名称是Horizon,它所需的唯一服务是身份服务keystone,开发语言是python的web框架Django. 安装Train版本的Horizo ...