gRPC-gateway
参考资料:gRPC-Gateway使用指南
服务中,使用了gRPC gateway(代理)来将外部的http请求映射为内部rpc调用。
proto文件示例:
// 导入google/api/annotations.proto
import "google/api/annotations.proto";rpc List(ListRequest) returns (ListResponse) {option (google.api.http) = {post : "/project/Service/List"};}
接下来还需进行一些配置才能完成映射。
示例代码:
(8080端口提供gRPC API服务,8090端口提供HTTP API服务)
import ("context""log""net""net/http"helloworldpb "github.com/Q1mi/greeter/proto/helloworld""github.com/grpc-ecosystem/grpc-gateway/v2/runtime" // 注意v2版本"google.golang.org/grpc""google.golang.org/grpc/credentials/insecure"
)type server struct {helloworldpb.UnimplementedGreeterServer
}func NewServer() *server {return &server{}
}func (s *server) SayHello(ctx context.Context, in *helloworldpb.HelloRequest) (*helloworldpb.HelloReply, error) {return &helloworldpb.HelloReply{Message: in.Name + " world"}, nil
}func main() {// Create a listener on TCP portlis, err := net.Listen("tcp", ":8080")if err != nil {log.Fatalln("Failed to listen:", err)}// 创建一个gRPC server对象s := grpc.NewServer()// 注册Greeter service到serverhelloworldpb.RegisterGreeterServer(s, &server{})// 8080端口启动gRPC Serverlog.Println("Serving gRPC on 0.0.0.0:8080")go func() {log.Fatalln(s.Serve(lis))}()// 创建一个连接到我们刚刚启动的 gRPC 服务器的客户端连接// gRPC-Gateway 就是通过它来代理请求(将HTTP请求转为RPC请求)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)}gwmux := runtime.NewServeMux()// <--<--// 注册Greetererr = helloworldpb.RegisterGreeterHandler(context.Background(), gwmux, conn)if err != nil {log.Fatalln("Failed to register gateway:", err)}gwServer := &http.Server{Addr: ":8090",Handler: gwmux, // <--<-- 该endpoint接收到http请求时,会调用grpc-gateway内部的方法完成映射}// 8090端口提供gRPC-Gateway服务log.Println("Serving gRPC-Gateway on http://0.0.0.0:8090")log.Fatalln(gwServer.ListenAndServe())
}