gRPC客户端/存根在goroutine之间的使用

huangapple go评论65阅读模式
英文:

Is a gRPC client/stub usage across goroutines

问题

我正在使用Protobuf和gRPC进行实验,并正在阅读Go基础教程:https://www.grpc.io/docs/languages/go/basics/

根据我在ClientConn文档中看到的内容,似乎可以安全地同时使用同一个ClientConn。但是关于创建的stub/client,我没有找到相关的信息...

假设我通过HTTP POST请求接收数据,并希望将该数据作为protobuf通过gRPC转发,然后响应HTTP请求。我应该在每次处理HTTP请求时创建一个client/stub,还是可以在设置HTTP服务器时创建client/stub,并在设置HTTP处理程序时传入client/stub?

例如:我认为这样是可以的

var opts []grpc.DialOption
conn, err := grpc.Dial("127.0.0.1:1234", opts...)
if err != nil {
	log.Panic(err)
}
defer conn.Close()
grpcService := service.Service{GRPC: conn}
http.HandleFunc("/", util.ValidateRequest(grpcService.HandleRoot))

// 监听端口
http.ListenAndServe(fmt.Sprintf("%s:%d", viper.GetString("server.address"), viper.GetInt32("server.port")), nil)

但是这样呢

var opts []grpc.DialOption
conn, err := grpc.Dial("127.0.0.1:1234", opts...)
if err != nil {
	log.Panic(err)
}
defer conn.Close()
client := pb.NewEventShipperClient(conn)
grpcService := service.Service{GRPC: conn, Client: client}
http.HandleFunc("/", util.ValidateRequest(grpcService.HandleRoot))

// 监听端口
http.ListenAndServe(fmt.Sprintf("%s:%d", viper.GetString("server.address"), viper.GetInt32("server.port")), nil)
英文:

I'm experimenting with Protobuf and gRPC and was going through the Go basics tutorial: https://www.grpc.io/docs/languages/go/basics/

From what I could see in the documentation about the ClientConn it seems that it is safe to use the same ClientConn concurrently. But I can't anything about the stub/client that one creates...

Say I was receiving data via HTTP POST requests and I wanted to forward that data via gRPC as protobuf and then respond to the HTTP request. Should I create a client/stub every time I process a HTTP request, or can I create the client/stub when setting up the HTTP server and pass in the client/stub when setting up HTTP Handlers?

Example: I assume this is okay

var opts []grpc.DialOption
conn, err := grpc.Dial("127.0.0.1:1234", opts...)
if err != nil {
	log.Panic(err)
}
defer conn.Close()
grpcService := service.Service{GRPC: conn}
http.HandleFunc("/", util.ValidateRequest(grpcService.HandleRoot))

// listen to port
http.ListenAndServe(fmt.Sprintf("%s:%d", viper.GetString("server.address"), viper.GetInt32("server.port")), nil)

but what about this

var opts []grpc.DialOption
conn, err := grpc.Dial("127.0.0.1:1234", opts...)
if err != nil {
	log.Panic(err)
}
defer conn.Close()
client := pb.NewEventShipperClient(conn)
grpcService := service.Service{GRPC: conn, Client: client}
http.HandleFunc("/", util.ValidateRequest(grpcService.HandleRoot))

// listen to port
http.ListenAndServe(fmt.Sprintf("%s:%d", viper.GetString("server.address"), viper.GetInt32("server.port")), nil)

答案1

得分: 2

线程安全(“是否可以安全地并发运行此代码”)在生成的代码参考中有所涵盖:

**线程安全性:**请注意,客户端的RPC调用和服务器端的RPC处理程序都是线程安全的,并且可以在并发的goroutine上运行。但是请注意,对于单个流,传入和传出的数据是双向但串行的;因此,例如,单个流不支持并发读取或并发写入(但读取与写入是安全并发的)。

因此,是的,可以同时调用pb.NewEventShipperClient(conn)返回的struct上的方法。

您还可以通过查看pb.NewEventShipperClient的实现来自行验证。目前(我猜这可能会改变),唯一的成员变量将是一个接口(cc grpc.ClientConnInterface - 由*ClientConn实现),每个方法都使用连接来Invoke一个gRPC调用。

但是,请注意,您需要在service.Service的实现中小心确保它也是线程安全的,并注意有关流的警告。

英文:

Thread safety ("is it safe to run this concurrently") is covered in the Generated-code reference:

>Thread-safety: note that client-side RPC invocations and server-side RPC handlers are thread-safe and are meant to be run on concurrent goroutines. But also note that for individual streams, incoming and outgoing data is bi-directional but serial; so e.g. individual streams do not support concurrent reads or concurrent writes (but reads are safely concurrent with writes).

So, yes, methods on the struct returned by pb.NewEventShipperClient(conn) can be called concurrently.

You can also check this yourself by looking at the implementation of pb.NewEventShipperClient. Currently (I guess this may change) the only member variable will be an interface (cc grpc.ClientConnInterface - implemented by *ClientConn) with each method using the connection to Invoke a gRPC call.

Please note, however, that you need to be careful in your implementation of service.Service to ensure it is also threadsafe and note the caveat regarding streams.

huangapple
  • 本文由 发表于 2022年7月20日 02:52:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/73042151.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定