英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论