Golang grpc:如何确定服务器何时开始监听?
Golang grpc: how to determine when the server has started listening?
所以我有以下内容:
type Node struct {
Table map[string]string
thing.UnimplementedGreeterServer
address string
}
func (n *Node) Start() {
lis, err := net.Listen("tcp", port)
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
s := grpc.NewServer()
thing.RegisterGreeterServer(s, n)
if err := s.Serve(lis); err != nil {
log.Fatalf("failed to serve: %v", err)
}
}
在我的主要功能中,我将启动多个节点,如下所示:
func main() {
n :=Node{Table: map[string]string{}}
go n.Start()
conn, err := grpc.Dial("localhost:50051", grpc.WithInsecure(), grpc.WithBlock())
}
问题是,因为我正在同时启动节点,所以拨号连接可能无法正常工作,因为节点可能尚未设置。
理想情况下,我想要一个 done
通道来告诉我 grpc 服务器何时真正开始监听。我该如何实现?
这与没有答案的本质上是同一个问题
s.Serve(listener)
块,所以你不能通过完成 chan 来实现你的目的,相反你必须实施 healthcheck 和准备好你的服务,并在执行任何请求之前检查这些由客户。
服务器应实现以下协议:
syntax = "proto3";
package grpc.health.v1;
message HealthCheckRequest {
string service = 1;
}
message HealthCheckResponse {
enum ServingStatus {
UNKNOWN = 0;
SERVING = 1;
NOT_SERVING = 2;
SERVICE_UNKNOWN = 3; // Used only by the Watch method.
}
ServingStatus status = 1;
}
service Health {
rpc Check(HealthCheckRequest) returns (HealthCheckResponse);
rpc Watch(HealthCheckRequest) returns (stream HealthCheckResponse);
}
例如,envoy proxy grpc_health_check 适用于上述协议。
阅读 GRPC Health Checking Protocol 了解更多信息。
只要 net.Listen returns 没有错误,就可以拨打服务器。拨号将阻塞,直到服务器调用 Accept(在这种情况下,这将发生在 s.Serve 的某处)。
将侦听器的创建移动到调用者并将其作为参数传递:
func (n *Node) Start(lis net.Listener) {
s := grpc.NewServer()
thing.RegisterGreeterServer(s, n)
if err := s.Serve(lis); err != nil {
log.Fatalf("failed to serve: %v", err)
}
}
func main() {
lis, err := net.Listen("tcp", port)
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
n := Node{Table: map[string]string{}}
go n.Start(lis)
conn, err := grpc.Dial("localhost:50051", grpc.WithInsecure(), grpc.WithBlock())
}
或者在 Listen returns:
之后发出监听器已启动的信号
func (n *Node) Start(up chan struct{}) {
lis, err := net.Listen("tcp", port)
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
if up != nil {
close(up)
}
s := grpc.NewServer()
thing.RegisterGreeterServer(s, n)
if err := s.Serve(lis); err != nil {
log.Fatalf("failed to serve: %v", err)
}
}
func main() {
n := Node{Table: map[string]string{}}
up := make(chan struct{})
go n.Start(up)
<-up
conn, err := grpc.Dial("localhost:50051", grpc.WithInsecure(), grpc.WithBlock())
}
简单的解决方案,没有第三方,listen/accept之间没有差距,没有随机超时。
func main() {
n := Node{Table: map[string]string{}}
go n.Start()
conn, err := grpc.Dial("localhost:50051", grpc.WithInsecure(), grpc.WithBlock())
if err != nil {
for i := 0; i < 10; i++ {
conn, err = grpc.Dial("localhost:50051", grpc.WithInsecure(), grpc.WithBlock())
<-time.After(time.Second)
}
}
if err != nil {
panic(err)
}
}
对于所有仍在寻找答案的人,这是另一种简单的方法。在子例程中启动服务器。这是一个代码片段:
// Start the server in a child routine
go func() {
if err := s.Serve(listener); err != nil {
log.Fatalf("Failed to serve: %v", err)
}
}()
fmt.Println("Server succesfully started on port :50051")
在我的例子中,我也在使用 MongoDB,所以当你 运行 它时,你会得到:
grpc-go-mongodb-cobra>go run server/main.go
Starting server on port :50051...
Connecting to MongoDB...
Connected to MongoDB
Server succesfully started on port :50051
我还写了一篇关于此的博客 post,工作代码在 GitHub 中。这是link:https://softwaredevelopercentral.blogspot.com/2021/03/golang-grpc-microservice.html
所以我有以下内容:
type Node struct {
Table map[string]string
thing.UnimplementedGreeterServer
address string
}
func (n *Node) Start() {
lis, err := net.Listen("tcp", port)
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
s := grpc.NewServer()
thing.RegisterGreeterServer(s, n)
if err := s.Serve(lis); err != nil {
log.Fatalf("failed to serve: %v", err)
}
}
在我的主要功能中,我将启动多个节点,如下所示:
func main() {
n :=Node{Table: map[string]string{}}
go n.Start()
conn, err := grpc.Dial("localhost:50051", grpc.WithInsecure(), grpc.WithBlock())
}
问题是,因为我正在同时启动节点,所以拨号连接可能无法正常工作,因为节点可能尚未设置。
理想情况下,我想要一个 done
通道来告诉我 grpc 服务器何时真正开始监听。我该如何实现?
这与没有答案的
s.Serve(listener)
块,所以你不能通过完成 chan 来实现你的目的,相反你必须实施 healthcheck 和准备好你的服务,并在执行任何请求之前检查这些由客户。
服务器应实现以下协议:
syntax = "proto3";
package grpc.health.v1;
message HealthCheckRequest {
string service = 1;
}
message HealthCheckResponse {
enum ServingStatus {
UNKNOWN = 0;
SERVING = 1;
NOT_SERVING = 2;
SERVICE_UNKNOWN = 3; // Used only by the Watch method.
}
ServingStatus status = 1;
}
service Health {
rpc Check(HealthCheckRequest) returns (HealthCheckResponse);
rpc Watch(HealthCheckRequest) returns (stream HealthCheckResponse);
}
例如,envoy proxy grpc_health_check 适用于上述协议。
阅读 GRPC Health Checking Protocol 了解更多信息。
只要 net.Listen returns 没有错误,就可以拨打服务器。拨号将阻塞,直到服务器调用 Accept(在这种情况下,这将发生在 s.Serve 的某处)。
将侦听器的创建移动到调用者并将其作为参数传递:
func (n *Node) Start(lis net.Listener) {
s := grpc.NewServer()
thing.RegisterGreeterServer(s, n)
if err := s.Serve(lis); err != nil {
log.Fatalf("failed to serve: %v", err)
}
}
func main() {
lis, err := net.Listen("tcp", port)
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
n := Node{Table: map[string]string{}}
go n.Start(lis)
conn, err := grpc.Dial("localhost:50051", grpc.WithInsecure(), grpc.WithBlock())
}
或者在 Listen returns:
之后发出监听器已启动的信号func (n *Node) Start(up chan struct{}) {
lis, err := net.Listen("tcp", port)
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
if up != nil {
close(up)
}
s := grpc.NewServer()
thing.RegisterGreeterServer(s, n)
if err := s.Serve(lis); err != nil {
log.Fatalf("failed to serve: %v", err)
}
}
func main() {
n := Node{Table: map[string]string{}}
up := make(chan struct{})
go n.Start(up)
<-up
conn, err := grpc.Dial("localhost:50051", grpc.WithInsecure(), grpc.WithBlock())
}
简单的解决方案,没有第三方,listen/accept之间没有差距,没有随机超时。
func main() {
n := Node{Table: map[string]string{}}
go n.Start()
conn, err := grpc.Dial("localhost:50051", grpc.WithInsecure(), grpc.WithBlock())
if err != nil {
for i := 0; i < 10; i++ {
conn, err = grpc.Dial("localhost:50051", grpc.WithInsecure(), grpc.WithBlock())
<-time.After(time.Second)
}
}
if err != nil {
panic(err)
}
}
对于所有仍在寻找答案的人,这是另一种简单的方法。在子例程中启动服务器。这是一个代码片段:
// Start the server in a child routine
go func() {
if err := s.Serve(listener); err != nil {
log.Fatalf("Failed to serve: %v", err)
}
}()
fmt.Println("Server succesfully started on port :50051")
在我的例子中,我也在使用 MongoDB,所以当你 运行 它时,你会得到:
grpc-go-mongodb-cobra>go run server/main.go
Starting server on port :50051...
Connecting to MongoDB...
Connected to MongoDB
Server succesfully started on port :50051
我还写了一篇关于此的博客 post,工作代码在 GitHub 中。这是link:https://softwaredevelopercentral.blogspot.com/2021/03/golang-grpc-microservice.html