duanjiao8007
2018-10-25 15:39
采纳率: 100%
浏览 2.2k
已采纳

gRPC设置问题。 出现间歇性RPC不可用错误

我有一个grpc服务器和客户端,大部分时间都能正常运行,但是偶尔会收到“传输正在关闭”错误:

rpc error: code = Unavailable desc = transport is closing

我想知道我的设置是否有问题。 客户端很基础

connection, err := grpc.Dial(address, grpc.WithInsecure(), grpc.WithBlock())
pb.NewAppClient(connection)
defer connection.Close()

并以类似超时的方式拨打电话

ctx, cancel := context.WithTimeout(ctx, 300*time.Millisecond)
defer cancel()

client.MyGRPCMethod(ctx, params)

我正在做的另一件事是检查连接来查看它是处于打开,空闲还是正在连接状态,如果有则重新使用该连接。 否则,请重拨。 p>

服务器没有任何特殊配置

grpc.NewServer()

设置grpc客户端/服务器时是否会遇到一些常见错误?

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

3条回答 默认 最新

  • douwen0647 2018-10-31 20:33
    已采纳

    One other thing I'm doing is checking the connection to see if it's either open, idle or connecting, and reusing the connection if so. Otherwise, redialing.

    grpc will manage your connections for you, reconnecting when needed, so you should never need to monitor it after creating it unless you have very specific needs.

    "transport is closing" has many different reasons for happening; please see the relevant question in our FAQ and let us know if you still have questions: https://github.com/grpc/grpc-go#the-rpc-failed-with-error-code--unavailable-desc--transport-is-closing

    点赞 打赏 评论
  • doudou20145 2018-10-25 16:51

    I had about the same issue earlier this year . After about 15 minuets I had servers close the connection.

    My solution which is working was to create my connection with grpc.Dial once on my main function then create the pb.NewAppClient(connection) on each request. Since the connection was already created latency wasn't an issue. After the request was done I closed the client.

    点赞 打赏 评论
  • dpg98445 2019-02-15 05:36

    After much search, I have finally come to an acceptable and logical solution to this problem.

    The root-cause is this: The underlying TCP connection is closed abruptly, but neither the gRPC Client nor Server are 'notified' of this event.

    The challenge is at multiple levels:

    • Kernel's management of TCP sockets
    • Any intermediary load-balancers/reverse-proxies (by Cloud Providers or otherwise) and how they manage TCP sockets
    • Your application layer itself and it's networking requirements - whether it can reuse the same connection for future requests not

    My solution turned out to be fairly simple:

    server = grpc.NewServer(
        grpc.KeepaliveParams(keepalive.ServerParameters{
            MaxConnectionIdle: 5 * time.Minute,           // <--- This fixes it!
        }),
    )
    

    This ensures that the gRPC server closes the underlying TCP socket gracefully itself before any abrupt kills from the kernel or intermediary servers (AWS and Google Cloud Load Balancers both have larger timeouts than 5 minutes).

    The added bonus you will find here is also that any places where you're using multiple connections, any leaks introduced by clients that forget to Close the connection will also not affect your server.

    My $0.02: Don't blindly trust any organisation's (even Google's) ability to design and maintain API. This is a classic case of defaults-gone-wrong.

    点赞 打赏 评论

相关推荐 更多相似问题