让 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

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.proto和 google / 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
- https://github.com/grpc/grpc-dotnet/issues/167
- https://docs.microsoft.com/en-us/aspnet/core/grpc/httpapi?view=aspnetcore-5.0
- http://james.newtonking.com/archive/2020/03/31/introducing-grpc-http-api
- https://github.com/aspnet/AspLabs/tree/master/src/GrpcHttpApi
- https://grpchttpapi.azurewebsites.net/
- https://github.com/WeihanLi/SamplesInPractice/tree/master/GrpcSample
让 gRPC 提供 REST 服务的更多相关文章
- grpc提供http服务
package main import ( "google.golang.org/grpc" "google.golang.org/grpc/credentials&qu ...
- .net core grpc consul 实现服务注册 服务发现 负载均衡(二)
在上一篇 .net core grpc 实现通信(一) 中,我们实现的grpc通信在.net core中的可行性,但要在微服务中真正使用,还缺少 服务注册,服务发现及负载均衡等,本篇我们将在 .net ...
- ASP.NET Core gRPC 使用 Consul 服务注册发现
一. 前言 gRPC 在当前最常见的应用就是在微服务场景中,所以不可避免的会有服务注册与发现问题,我们使用gRPC实现的服务可以使用 Consul 或者 etcd 作为服务注册与发现中心,本文主要介绍 ...
- .Net Core Grpc Consul 实现服务注册 服务发现 负载均衡
本文是基于..net core grpc consul 实现服务注册 服务发现 负载均衡(二)的,很多内容是直接复制过来的,..net core grpc consul 实现服务注册 服务发现 负载均 ...
- 微服务架构攀登之路(四)之使用gRPC构建微服务
做一个处理用户信息的微服务 客户端通过用户名,可以从服务端查询用户的基本信息 gRPC proto user.proto 定义客户端请求.服务端响应的数据格式 user.pb.go 自动生成的,为数据 ...
- 如何基于gRPC沟通微服务框架
本文我们来讲解一下如何使用 gRPC构建微服务,gRPC是一个开源框架,可用于构建可扩展且高性能的微服务并创建服务之间的通信. 背景 随着企业越来越多地转向微服务,对构建这些微服务的低延迟和可扩展框架 ...
- Windows Azure HandBook (2) Azure China提供的服务
<Windows Azure Platform 系列文章目录> 对于传统的自建数据中心,从底层的Network,Storage,Servers,Virtualization,中间层的OS, ...
- 提供RESTful服务
RESTful广泛运用于互联网服务,而在企业应用中,大部分场景仍然是RPC服务,这是由于企业应用的业务复杂性造成的.但是基于SOAP的RPC服务也存在很多的弊端,比如服务异步处理比较麻烦,大部分RPC ...
- 第13章 使用Bind提供域名解析服务
章节简述: 本章节将让您理解DNS服务程序的原理,学习正向解析与反向解析实验,掌握DNS主服务器.从服务器.缓存服务器的部署方法. 够熟练配置区域信息文件与区域数据文件,以及通过使用分离解析技术让不同 ...
随机推荐
- HTTP1.0/1.1/2.0
https://www.cnblogs.com/heluan/p/8620312.html http缓存策略 https://www.cnblogs.com/Iwillknow/archive/201 ...
- c++复习笔记(4)
这一篇是另一篇各种琐碎东西的笔记. 类型转换可以通过类型转换函数,或者构造函数来实现.但是一般来说类型转换指的是类型转换函数. 类型转换函数不需要声明输出类型(因为输出类型是固定的),也没有参数,同时 ...
- Java根据路径获取文件内容
文章目录 一.思路 二.实现 给出一个资源路径.然后获取资源文件信息,常见三种方式:①网络地址 ②本地绝对路径 ③本地相对路径 一.思路 首先,给出一个string表示资源文件的标识,如何判断是网络中 ...
- Linux系统安装时分区的选择(转)
原文地址:http://www.cnblogs.com/gylei/archive/2011/12/04/2275987.html 前言: 以前初识Linux时,对Linux系统安装时分区的选择,一点 ...
- Linux系统磁盘管理(lvm逻辑卷管理)
linux系统用户常遇到的一个问题就是如何精准的评估分区的大小,已分配合适的磁盘空间:普通的磁盘分区管理方式在逻辑分区划分好之后就无法改变其大小,当一个逻辑分区存放不下某个文件时,这个文件因为受上层文 ...
- HDOJ 1078
标准的DAG上的DP,其实之前一直不大想得明白为什么dp[i][j]为什么一定是在(i,j)状态上的局部最优解了呢? 其实仔细想想和我一般所做的DP是一个道理,因为运用dfs的方法,因此可以确定的是, ...
- HDU-3081-Marriage Match II 二分图匹配+并查集 OR 二分+最大流
二分+最大流: 1 //题目大意:有编号为1~n的女生和1~n的男生配对 2 // 3 //首先输入m组,a,b表示编号为a的女生没有和编号为b的男生吵过架 4 // 5 //然后输入f组,c,d表示 ...
- windows下进程间通信方法
摘 要 随着人们对应用程序的要求越来越高,单进程应用在许多场合已不能满足人们的要求.编写多进程/多线程程序成为现代程序设计的一个重要特点,在多进程程序设计中,进程间的通信是不可避免的.Microsof ...
- CF1400-D. Zigzags
CF1400-D. Zigzags 题意: 给出一个由\(n\)个数字构成的数组\(a\),让你在这个数组中找出有多少个符合以下要求的元组\((i,j,k,l)\): 1. \(i<j<k ...
- OpenStack Train版-11.安装horizon服务(计算节点)
OpenStack仪表板Dashboard服务的项目名称是Horizon,它所需的唯一服务是身份服务keystone,开发语言是python的web框架Django. 安装Train版本的Horizo ...