0. 简介
gRPC-Gateway是一个protoc的插件,其读取gRPC的服务定义,并且生成一个反向代理
的服务器,用于将外界的RESTful JSON API
转换为gRPC请求。
为什么有个gRPC
,还需要gRPC-Gateway
?
gRPC-Gateway作为gRPC服务的反向代理,充当了客户端的Restful应用程序,使得相同的代码库同时支持Restful/JSON和gRPC的可能,在以下两个场景中,gRPC-Gateway是必要的:
- 旧版本的客户端可能只支持Restful/JSON接口;
- 浏览器并不支持gRPC,因此要想与Web互动,需要gRPC-Gateway。
1. 服务定义
我们以gRPC-Go基础(3)基础gRPC服务的一元RCP为例子,在其中的服务定义中加上google.api.http
,更多参考the source file documentation.
proto
message SimpleResponse {
int32 code = 1;
string data = 2;
}
message StreamRequest{
int32 id = 1;
string stream_data = 2;
}
service Route {
rpc RouteList(StreamRequest) returns (SimpleResponse){
option (google.api.http) = {
get: "/v1/simple/{id}"
};
};
}
然后再生成代码:
bash
protoc -I./proto \
--go_out=./genproto --go_opt paths=source_relative \
--go-grpc_out=./genproto --go-grpc_opt paths=source_relative \
--grpc-gateway_out=./genproto --grpc-gateway_opt paths=source_relative \
./proto/*/*.proto
2. 逻辑代码
go
package handler
import (
"context"
"grpc-gateway-demo/api/demopb"
)
type SimpleHandler struct {
demopb.UnimplementedSimpleServer
}
func NewSimpleHandler() *SimpleHandler {
return &SimpleHandler{}
}
func (s SimpleHandler) Get(ctx context.Context, request *demopb.SimpleRequest) (*demopb.SimpleResponse, error) {
return &demopb.SimpleResponse{
Code: 0,
Data: "simple",
}, nil
}
main函数:
go
func main() {
// 起grpc
lis, err := net.Listen("tcp", ":8080")
if err != nil {
log.Fatal(err)
}
s := grpc.NewServer()
demopb.RegisterSimpleServer(s, handler.NewSimpleHandler())
log.Printf("Serve Grpc on %s", ":8080")
go func() {
if err := s.Serve(lis); err != nil {
log.Fatal(err)
}
}()
// 起grpc-gateway
gwMux := runtime.NewServeMux()
err = demopb.RegisterSimpleHandlerFromEndpoint(context.Background(),
gwMux,
":8080",
[]grpc.DialOption{grpc.WithTransportCredentials(insecure.NewCredentials())})
if err != nil {
log.Fatal(err)
}
gwServer := &http.Server{
Addr: ":8081",
Handler: gwMux,
}
log.Printf("Serve Gateway on %s", ":8081")
if err = gwServer.ListenAndServe(); err != nil {
log.Fatal(err)
}
}
可以看出,grpc-gateway是起了一个tcp链接(":8080"
端口)指向grpc服务,并且在本地起一个http的服务(":8081"
端口),从而实现反向代理。
起服务后,可以在本地浏览器输入:http://localhost:8081/v1/simple/1
,会出现以下回应:
bash
{
"code": 0,
"data": "simple"
}
这就使用grpc-gateway实现了一个简单的HTTP的服务!