【发布时间】:2017-01-22 10:50:37
【问题描述】:
使用gRPC创建服务器时,如果我在主进程中启动gRPC服务器,它可以处理来自客户端的请求(数千个)。但是,如果我将服务器作为 goroutine 启动,它只能处理一些请求(数百个)并且在卡住之后。我已经通过一个非常简单的示例 google.golang.org/grpc/examples/helloworld 测试并确认了这一点。
是不是因为派生的 goroutine 堆栈大小非常小(2Kbytes),而主 goroutine 大得多? main goroutine 和 spawned goroutine 有什么区别?
例如link。修改部分示例如下。
greeter_server/main.go
func main() {
go func() {
lis, err := net.Listen("tcp", port)
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
s := grpc.NewServer()
pb.RegisterGreeterServer(s, &server{})
s.Serve(lis)
}()
for {
}
}
greeter_client/main.go
func main() {
// Set up a connection to the server.
for i := 0; i < 500; i++ {
conn, err := grpc.Dial(address, grpc.WithInsecure())
if err != nil {
log.Fatalf("did not connect: %v", err)
}
defer conn.Close()
c := pb.NewGreeterClient(conn)
for i := 0; i < 500; i++ {
// Contact the server and print out its response.
name := defaultName
if len(os.Args) > 1 {
name = os.Args[1]
}
r, err := c.SayHello(context.Background(), &pb.HelloRequest{Name: name})
if err != nil {
log.Fatalf("could not greet: %v", err)
}
log.Printf("%d's Greeting: %s", i, r.Message)
}
}
}
【问题讨论】:
-
它们是一样的。你能举个例子说明你在做什么吗?
-
@JimB 感谢您的回复。我已经包含了示例链接和修改后的代码。
-
@Amd 这是go1.7 linux/amd64
-
您在 main 中有一个繁忙的循环。不要那样做。
-
繁忙的循环总是错误的。没有理由为了阻塞而以 100% 的速度旋转 CPU。根本不要使用 for 循环,等待阻塞的东西。在这个例子中没有理由使用 goroutine,只需内联调用该代码。如果确实需要不进行任何操作的阻塞,可以使用空的
select{},但一般情况下不需要。