【问题标题】:Plugging custom transport into gRPC将自定义传输插入 gRPC
【发布时间】:2018-04-18 00:40:52
【问题描述】:

假设我们为 gRPC 开发了一个自定义的低级传输。我们如何将它“插入”到 gRPC c++ API 中以便我们可以将它用于 Channel?

【问题讨论】:

    标签: c++ grpc


    【解决方案1】:

    我正在编写一个文档,该文档很快就会出现在 https://github.com/grpc/grpc/,但这里有一个预览:

    gRPC transports 插入到核心 API 之下(C++ API 之下一层)。你可以用 C 或 C++ 编写你的传输;目前所有的传输名义上都是用 C++ 编写的,尽管它们是惯用的 C。现有的传输是:

    其中,进程内可能是最容易理解的,尽管也可以说与“真正的”基于套接字的传输最不相似。

    在 gRPC 核心实现中,基本结构是 grpc_transport_stream_op_batch,它表示发送到传输的流操作的集合。批处理中的操作可以包括:

    • send_initial_metadata
      • 客户端:启动 RPC
      • 服务器:提供响应标头
    • recv_initial_metadata
      • 客户端:获取响应标头
      • 服务器:接受 RPC
    • send_message(零个或多个):发送数据缓冲区
    • recv_message(零个或多个):接收数据缓冲区
    • send_trailing_metadata
      • 客户端:半关闭表示不会有更多消息发送
      • 服务器:完全关闭,为 RPC 提供最终状态
    • recv_trailing_metadata:获取 RPC 的最终状态
      • 服务器额外:在服务器还发送尾随元数据以向另一方提供最终状态之前,此操作实际上不应被视为完成
    • cancel_stream:尝试取消 RPC
    • collect_stats:获取统计数据

    这些操作中的一个或多个被分组到一个批次中。应用程序可以在一个批次中启动所有调用的操作,也可以将它们分成多个批次。每个批次的结果通过完成队列异步返回。

    在内部,我们使用回调来指示完成。表面层在开始新批次时创建回调,并将其与批次一起发送到过滤器堆栈。当批处理完成时,传输必须调用此回调,然后表面层通过完成队列向应用程序返回一个事件。每个批次最多可以有 3 个回调:

    • recv_initial_metadata_ready(recv_initial_metadata 操作完成时由传输调用)
    • recv_message_ready(recv_message 操作完成时由传输调用)
    • on_complete(整个批次完成时由传输调用)

    传输的工作是对基本流操作的各种可能的交错进行排序和解释。例如,批次的示例时间表是:

    1. 客户端 send_initial_metadata:使用路径(方法)和权限发起 RPC
    2. 服务器receive_initial_metadata:接受一个RPC
    3. 客户端发送消息:为 RPC 提供输入原型
    4. 服务器接收消息:从 RPC 获取输入原型
    5. 客户端 send_trailing_metadata:这是一个半关闭状态,表示客户端将不再发送任何消息
    6. 服务器receive_trailing_metadata:服务器从客户端看到这个并且知道它不会再收到任何消息。如上所述,这还没有完成。
    7. Server send_initial_metadata、send_message、send_trailing_metadata:一个batch可以包含多个ops,这个batch提供RPC响应头、响应内容和状态。请注意,发送尾随元数据也将完成服务器对尾随元数据的接收。
    8. 客户端recv_initial_metadata:批处理一侧的操作数与批处理另一侧的操作数无关。在这种情况下,客户端只是收集响应头。
    9. 客户端recv_message、recv_trailing_metadata:获取数据响应和状态

    除了这些基本的流操作之外,传输必须随时处理流的取消并将其效果传递给另一端。传输必须执行诸如 ping 和统计之类的操作,这些操作用于塑造传输级别的特征,例如流量控制(例如,参见它们在 HTTP/2 传输中的使用)。

    【讨论】:

    • 感谢您的回答!大多数细节我已经在运输实现中找到了。问题是:如果我想挂接我的 OWN 传输来满足所有这些合同,我如何通过 C++ API 注入它...
    • 这个主题有 C++ doxygen 文档,grpc.io/grpc/core/md_doc_core_transport_explainer.html
    【解决方案2】:

    关于 C++ API:大多数现有的自定义传输都是通过创建自己的凭据 C++ 类型来完成的,并使用这些凭据来启用新的传输。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-12-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多