【问题标题】:How to inspect clients that are connected to a GRPC server如何检查连接到 GRPC 服务器的客户端
【发布时间】:2019-12-05 07:42:06
【问题描述】:

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

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

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

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

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

【问题讨论】:

  • grpc.io/blog/a_short_introduction_to_channelz 是否满足您的要求?
  • @ZhouyihaiDing 这是我最有希望的领导,但是当我进行研究时,我几乎找不到有关 channelz 的 python API 的信息,grpc.github.io/grpc/python/grpc_channelz.html 上的源代码信息量不是很大。似乎如果我安装 pip 包grpc-channelz,那么我将能够从“C-Core”中提取 channelz 统计信息,但是没有关于如何在 Python 中以编程方式执行此操作的文档或示例。虽然如果有人确实有这个文档,我很乐意在回答中讨论它!

标签: python-3.x grpc grpc-python


【解决方案1】:

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

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

这是unit test that uses channelz, 哪些测试可能与 GetTopChannels API 相关的 API。

【讨论】:

  • 谢谢!这就是我要找的东西! Richard 和 Zhouyihai 都建议使用 channelz,但这些例子让我想出了一个解决方案。我会用一些代码编辑这个答案。
  • 自从我的编辑被拒绝后,我无法在 channelz 解决方案的代码示例中进行编辑,但我能够在同一进程中通过复制和访问 GRPC 服务器的 channelz 统计信息从grpc.github.io/grpc/python/_modules/grpc_channelz/v1/… 粘贴例如GetServerSockets 的存根实现。具体来说,访问 grpc._cython.cygrpc.channelz_get_server_sockets 将返回一个 protobuf 代表连接到客户端的服务器套接字。
【解决方案2】:

没有用于此的本机 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 可能也很适合你。

【讨论】:

  • 感谢理查德的代码示例!正如您所建议的,我已经在使用context.peer(),但这仅跟踪当前执行的RPC,而不是我的代码和您的解决方案中的活动通道。很抱歉没有澄清我的context.peer() 解决方案。 channelz 工作,但根据我对 Ding 的回复(特别是如何从 Python 中的“C-Core”读取 channelz 统计信息),我几乎找不到关于其 python API 的文档。如果没有其他公共 Python channelz 文档,我将只破解一个长期存在的“心跳”RPC 来检测通道何时从服务器端关闭。
【解决方案3】:

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

grpcdebug 是一个命令行界面,专注于简化 gRPC 应用程序的调试过程。 grpcdebug 通过 gRPC 协议从应用程序中获取 gRPC 库的内部状态,并提供人性化的用户体验来浏览它们。目前,它支持 Channelz/Health Checking/CSDS(又名管理服务)

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.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-11-12
    • 2015-12-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多