gRPC 服务器如何调用 REST 端点
Posted
技术标签:
【中文标题】gRPC 服务器如何调用 REST 端点【英文标题】:How can a gRPC server make calls to REST endpoints 【发布时间】:2018-07-28 14:15:36 【问题描述】:我目前是 gRPC 技术的新手,并且一直在阅读它。
我目前的理解是gRPC
只是另一个协议,就像REST
是一个一样。现在假设我启动了一个我希望客户端使用的 gRPC 服务器,但是在那个 gRPC 服务器中我希望能够从外部消费者 RESTful API 获取信息,(例如https://developer.riotgames.com/api-methods/)这仍然可能吗?
【问题讨论】:
“还有可能吗?”当然,为什么不呢? 我对服务器端的东西不是很熟悉,所以我在想,如果它是一个 gRPC 服务器,它就无法对外部端点进行 http 调用,比如 (GET, POST ) 【参考方案1】:是的,这是可能的。您可以从自己的 gRPC 服务代码调用其他 API 和服务。
只需让您的客户端调用您的 gRPC 服务即可。然后,您的服务对外部 API 进行 REST 调用(可能使用从客户端请求到您的 gRPC 服务的参数)并处理它。将结果返回给您的客户端,但您的 gRPC 服务会做出响应。
【讨论】:
所以只有当我想允许客户端向 gRPC 服务器发出 REST 请求时,才需要下面答案中的网关【参考方案2】:感谢phuongdo
,您需要使用grcp-gateway
生成go-grpc-tutorial 上可用的代理完整代码
安装部门:
$sudo apt install libprotobuf-dev
go get google.golang.org/grpc
go get -u github.com/golang/protobuf/proto,protoc-gen-go
go get -u github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway
定义服务,pb/service.proto:
syntax = "proto3";
option go_package = "echo";
package echo;
import "google/api/annotations.proto";
//Message represents a simple message sent to the Echo service.
message Message
string id = 1;
string msg = 2;
//Echo service responds to incoming echo requests.
service EchoService
//Echo method receives a simple message and returns it.
//The message posted as the id parameter will also be returned.
rpc Echo(Message) returns (Message)
option (google.api.http) =
post: "/v1/example/echo/id/msg"
;
为服务器和客户端生成存根
$ protoc -I/usr/local/include -I. \
-I$GOPATH/src \
-I$GOPATH/src/github.com/grpc-ecosystem/grpc-
gateway/third_party/googleapis \
--go_out=google/api/annotations.proto=github.com/grpc-ecosystem/grpc-
gateway/third_party/googleapis/google/api,plugins=grpc:. \
pb/service.proto
和reverse proxy
为REST API
$ protoc -I/usr/local/include -I. \
-I$GOPATH/src \
-I$GOPATH/src/github.com/grpc-ecosystem/grpc-
gateway/third_party/googleapis \
--grpc-gateway_out=logtostderr=true:. \
pb/service.proto
server/server.go:
package main
import (
"flag"
"github.com/golang/glog"
pb "github.com/go-grpc-tutorial/pb"
"golang.org/x/net/context"
"google.golang.org/grpc"
"net"
)
// Implements of EchoServiceServer
type echoServer struct
func newEchoServer() pb.EchoServiceServer
return new(echoServer)
func (s *echoServer) Echo(ctx context.Context, msg *pb.Message)
(*pb.Message, error)
glog.Info(msg)
return msg, nil
func Run() error
listen, err := net.Listen("tcp", ":50051")
if err != nil
return err
server := grpc.NewServer()
pb.RegisterEchoServiceServer(server, newEchoServer())
server.Serve(listen)
return nil
func main()
flag.Parse()
defer glog.Flush()
if err := Run(); err != nil
glog.Fatal(err)
编写rest api,server/server-rproxy.go:
package main
import (
"flag"
"net/http"
"github.com/grpc-ecosystem/grpc-gateway/runtime"
"github.com/golang/glog"
pb "github.com/go-grpc-tutorial/pb"
"golang.org/x/net/context"
"google.golang.org/grpc"
)
var (
echoEndpoint = flag.String("echo_endpoint", "localhost:50051",
"endpoint of EchoService")
)
func RunEndPoint(address string, opts ...runtime.ServeMuxOption)
error
ctx := context.Background()
ctx, cancel := context.WithCancel(ctx)
defer cancel()
mux := runtime.NewServeMux(opts...)
dialOpts := []grpc.DialOptiongrpc.WithInsecure()
err := pb.RegisterEchoServiceHandlerFromEndpoint(ctx, mux, *echoEndpoint, dialOpts)
if err != nil
return err
http.ListenAndServe(address, mux)
return nil
func main()
flag.Parse()
defer glog.Flush()
if err := RunEndPoint(":8080"); err != nil
glog.Fatal(err)
构建客户端服务器/client.go:
package main
import (
"log"
"os"
"golang.org/x/net/context"
"google.golang.org/grpc"
pb "github.com/go-grpc-tutorial/pb"
)
const (
address = "localhost:50051"
defaultName = "PhuongDV"
)
func main()
// Set up a connection to the server.
conn, err := grpc.Dial(address, grpc.WithInsecure())
if err != nil
log.Fatalf("did not connect: %v", err)
defer conn.Close()
c := pb.NewEchoServiceClient(conn)
// Contact the server and print out its response.
name := defaultName
if len(os.Args) > 1
name = os.Args[1]
r, err := c.Echo(context.Background(), &pb.MessageId: "1", Msg: name)
if err != nil
log.Fatalf("could not greet: %v", err)
log.Printf("Greeting: %s", r.Msg)
最后运行服务器、客户端、rest并调用rest:
$ go run server/server.go
$ go run client/client.go
$go run server/server-rproxy.go
$ curl -X POST "http://localhost:8080/v1/example/echo/1/PhuongDV"
1: https://github.com/phuongdo/go-grpc-tutorial 2:https://i.stack.imgur.com/C4s7s.png
【讨论】:
这仅适用于用户请求对我的 gRPC 服务器进行休息调用的情况,不是吗? 您可以使用它进行任何设计,因为您在这里拥有所有构建块,您的问题是:使用您的客户端从 REST 调用 gRCP 服务器以上是关于gRPC 服务器如何调用 REST 端点的主要内容,如果未能解决你的问题,请参考以下文章
PICE:集群环境里多异类端点gRPC Streaming - Heterogeneous multi-endpoints gRPC streaming