前言
使用 grpc-gateway 将 rpc API 转成 Http 接口
库:github.com/grpc-ecosystem/grpc-gateway/v2
一、grpc-gateway是什么?
gRPC-Gateway 是 Google 协议缓冲区编译器 protoc 的插件。它读取 protobuf 服务定义并生成一个反向代理服务器,该服务器将 RESTful HTTP API 转换为 gRPC。该服务器是根据google.api.http您的服务定义中的注释生成的。
这有助于您同时提供 gRPC 和 HTTP/JSON 格式的 API。
二、使用步骤
先看我的目录结构
1.proto 文件编写
代码如下(示例):
syntax = "proto3";
package helloworld;
option go_package="./hello";
import "google/api/annotations.proto";
// Here is the overall greeting service definition where we define all our endpoints
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply) {
option (google.api.http) = {
post: "/v1/example/echo"
body: "*"
};
}
}
// The request message containing the user's name
message HelloRequest {
string name = 1;
}
// The response message containing the greetings
message HelloReply {
string message = 1;
}
2.使用 buf 生成 相应.go 文件
- buf.yaml 文件:
version: v1 deps: - buf.build/googleapis/googleapis
- buf.gen.yaml
version: v1 plugins: - name: go out: ../pkg opt: paths=source_relative - name: go-grpc out: ../pkg opt: paths=source_relative - name: grpc-gateway out: ../pkg opt: paths=source_relative
- 使用buf 生成
这里我使用的是Makefile 如下:buf generate
generate: cd proto; buf generate run: cd cmd; go run main.go clean: rm -rf pkg
3.grpc及http 路由注册
main.go:
实现proto 文件定义的rpc 接口
type server struct{
hello.UnimplementedGreeterServer
}
func NewServer() *server {
return &server{}
}
func (s *server) SayHello(ctx context.Context, in *hello.HelloRequest) (*hello.HelloReply, error) {
return &hello.HelloReply{Message: in.Name + " world"}, nil
}
注册 grpc 与 http
// Create a listener on TCP port
lis, err := net.Listen("tcp", ":8080")
if err != nil {
log.Fatalln("Failed to listen:", err)
}
// Create a gRPC server object
s := grpc.NewServer()
// Attach the Greeter service to the server
hello.RegisterGreeterServer(s, &server{})
// Serve gRPC server
log.Println("Serving gRPC on 0.0.0.0:8080")
go func() {
log.Fatalln(s.Serve(lis))
}()
// Create a client connection to the gRPC server we just started
// This is where the gRPC-Gateway proxies the requests
conn, err := grpc.DialContext(
context.Background(),
"0.0.0.0:8080",
grpc.WithBlock(),
grpc.WithTransportCredentials(insecure.NewCredentials()),
)
if err != nil {
log.Fatalln("Failed to dial server:", err)
}
// 注册http 接口
gwmux := runtime.NewServeMux()
// Register Greeter
err = hello.RegisterGreeterHandler(context.Background(), gwmux, conn)
if err != nil {
log.Fatalln("Failed to register gateway:", err)
}
gwServer := &http.Server{
Addr: ":8090",
Handler: gwmux,
}
log.Println("Serving gRPC-Gateway on http://0.0.0.0:8090")
log.Fatalln(gwServer.ListenAndServe())
总结
本文仅仅介绍了 grpc-gateway 简单用法,就是将grpc 接口转成http,既保证了微服务之间的调用, 也让前端能够直接调用,不需要再去写一个http接口或者 使用nodejs 作为中间层去请求后段的grpc 。后面将继续推进 多路复用 mux 中的拦截器以及注册进gin路由中。