如何检查连接到 GRPC 服务器的客户端

How to inspect clients that are connected to a GRPC server

为了为我的 GRPC server/client 设置提供更好的调试信息,我试图为 grpc.server 找到一个 API,它允许我检查哪些客户端连接到服务器。

我发现的最有前途的问题是 question, which gives a starting point on how to do this in Java GRPC。但是,Java API 在 Python GRPC 实现中不存在。

到目前为止,我在 grpc.ServicerContext 中使用 context.peer() 方法跟踪独特的同行。如果对等方有一段时间没有发送请求(我将超时设置为 2 秒),我认为客户端已断开连接。

我已经开始查看 python-grpc 源代码,但我没有取得任何进展。

如果有人知道 python 中的类似 API 我可以使用,那将不胜感激!即使是内部 API 也足以满足这些调试需求。

没有原生的 API,但您拥有所需的所有部分。这是 repo 中 helloworld 示例的修改版本。

class PeerSet(object):
    def __init__(self):
        self._peers_lock = threading.RLock()
        self._peers = {}

    def connect(self, peer):
        print("Peer {} connecting".format(peer))
        with self._peers_lock:
            if peer not in self._peers:
                self._peers[peer] = 1
            else:
                self._peers[peer] += 1

    def disconnect(self, peer):
        print("Peer {} disconnecting".format(peer))
        with self._peers_lock:
            if peer not in self._peers:
                raise RuntimeError("Tried to disconnect peer '{}' but it was never connected.".format(peer))
            self._peers[peer] -= 1
            if self._peers[peer] == 0:
                del self._peers[peer]

    def peers(self):
        with self._peers_lock:
            return self._peers.keys()


class Greeter(helloworld_pb2_grpc.GreeterServicer):

    def __init__(self):
        self._peer_set = PeerSet()

    def _record_peer(self, context):
        def _unregister_peer():
            self._peer_set.disconnect(context.peer())
        context.add_callback(_unregister_peer)
        self._peer_set.connect(context.peer())

    def SayHello(self, request, context):
        self._record_peer(context)
        for i in range(10):
            print("[thread {}] Peers: {}".format(threading.currentThread().ident, self._peer_set.peers()))
            time.sleep(1)
        return helloworld_pb2.HelloReply(message='Hello, %s!' % request.name)

这将使您得到如下输出:

[thread 139905506195200] Peers: [u'ipv6:[::1]:57940', u'ipv6:[::1]:57930', u'ipv6:[::1]:57926', u'ipv6:[::1]:57920', u'ipv6:[::1]:57934']

正如丁在上面评论的那样,channelz 可能也很适合您。

我找到了更多有关 channelz 的文档和示例,其他人一直在建议它,它似乎就是您想要的。

这是 pull request that gives an example of channelz being used。它仅使用 GetServer channelz API,因此您必须对其进行调整。

这里是 unit test that uses channelz, 哪些测试可能与 GetTopChannels API.

相关的 APIs

有一种工具grpcdebug,它可以检查连接到 GRPC 服务器的客户端。

grpcdebug is a command line interface focusing on simplifying the debugging process of gRPC applications. grpcdebug fetches the internal states of the gRPC library from the application via gRPC protocol and provide a human-friendly UX to browse them. Currently, it supports Channelz/Health Checking/CSDS (aka. admin services)

grpcdebug is an gRPC service admin CLI

Usage:
  grpcdebug <target address> [flags] <command>

Available Commands:
  channelz    Display gRPC states in human readable way.
  health      Check health status of the target service (default "").
  help        Help about any command
  xds         Fetch xDS related information.