Golang grpc:如何确定服务器何时开始侦听?
因此,我有以下几点:Golang grpc:如何确定服务器何时开始侦听?,go,concurrency,grpc,Go,Concurrency,Grpc,因此,我有以下几点: 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
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服务器何时实际开始监听。我如何做到这一点
这与没有答案的问题本质上是相同的。Serve(listener)块,因此您无法通过完成chan来实现您的目的,相反,您必须实现和准备好您的服务,并在执行客户端的任何请求之前检查这些。
服务器应实现以下协议:
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);
}
例如,可以使用上面的proto
请阅读以了解更多信息。只要net.Listen返回零错误,就可以拨打服务器。拨号将被阻止,直到服务器呼叫为止(在这种情况下,这将发生在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())
}
或在侦听器返回后发出侦听器已启动的信号:
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())
}
func(n*节点)启动(启动chan结构{}){
lis,err:=net.Listen(“tcp”,端口)
如果错误!=零{
log.Fatalf(“未能侦听:%v”,错误)
}
如果上升!=零{
特写
}
s:=grpc.NewServer()
注册服务器(s,n)
如果错误:=s.Serve(lis);错误!=nil{
log.Fatalf(“未能送达:%v”,错误)
}
}
func main(){
n:=节点{表:映射[字符串]字符串{}
up:=make(chan结构{})
启动
简单的解决方案,没有第三方,倾听/接受之间没有间隙,没有随机超时
func main(){
n:=节点{表:映射[字符串]字符串{}
开始,开始
conn,err:=grpc.Dial(“本地主机:50051”,grpc.WithUnsecure(),grpc.WithBlock())
如果错误!=零{
对于i:=0;i<10;i++{
conn,err=grpc.Dial(“localhost:50051”,grpc.withunsecure(),grpc.WithBlock())
Start
将永远阻塞,或返回错误,因此,您无法获得通知它已成功启动的信号。您只能获得通知它失败的信号。最简单的方法是使用某个阈值重试拨号以退出。如果net.Listen返回零错误,服务器将开始侦听。您可以随后发送信号或通过将侦听器作为参数启动。实际上,如果tcp侦听没有错误,它可以启动得非常快。您可以进行延迟,例如在grpc之前进行time.Sleep(time.Second)。对于@Peter提到的点,Dial()是不正确的。service()将阻止,直到停止侦听。@HaiTH,没有任何东西可以阻止开始关闭某些信号通道或调用net.Listen和srv.Serve之间的任何东西。@Peter因为tcp在grpc实际工作之前仍然存在差距。grpc协议中的这些接口是吗?你说的更一般吗?@nz_21是的,我更新了答案,以提供r参考链接。这个健康检查协议在某种程度上是标准的,像Envegate这样的负载平衡器可以使用它。这是一个很好的答案。我想知道listen()
和accept()
之间的延迟是否足够重要,以至于它使通道信号没有看上去那么有用。