Channelz简介

 

Channelz是一个工具,可提供有关gRPC中不同级别的连接的全面运行时信息。它旨在帮助调试可能受到网络,性能,配置问题等困扰的实时程序 。gRFC提供有关channelz设计的详细说明,并且是跨语言的所有channelz实现的规范参考。本博客的目的是使读者熟悉channelz服务以及如何使用它解决调试问题。这篇文章的上下文是在 gRPC-Go中设置的,但总体思路应适用于多种语言。在撰写本文时,channelz可用于 gRPC-Go和 gRPC-Java支持 C ++ 包装语言即将推出。

让我们通过一个简单的示例来学习channelz,该示例使用channelz来帮助调试问题。的 HelloWorld的 我们的仓库中的示例进行了稍微修改以设置越野车场景。您可以在此处找到完整的源代码: 客户端, 服务器

客户端设置: 客户端将使100个SayHello RPC到达指定的目标,并使用循环策略负载均衡工作负载。每个呼叫都有150毫秒的超时时间。记录RPC响应和错误是为了进行调试。

运行该程序,我们在日志中注意到存在间歇性错误,错误代码为DeadlineExceeded,如图1所示。

但是,没有什么原因导致超出期限的错误,并且存在很多可能性:

  • 网络问题,例如:连接丢失
  • 代理问题,例如:中间的请求/响应被丢弃
  • 服务器问题,例如:请求丢失或响应缓慢

图1.程序日志屏幕截图

让我们打开grpc INFO日志以获取更多调试信息,看看是否可以找到有用的信息。

图2. gRPC INFO日志

如图2所示,信息日志指示到服务器的所有三个连接均已连接,并准备传输RPC。日志中未显示可疑事件。从信息日志中可以推断出的一件事是所有连接一直都处于打开状态,因此可以排除丢失的连接假设。

为了进一步缩小问题的根本原因,我们将向channelz寻求帮助。

Channelz通过gRPC服务提供gRPC内部联网机制统计信息。要启用channelz,用户只需在其程序中将channelz服务注册到gRPC服务器并启动服务器即可。下面的代码段显示了将channelz服务注册到grpc.Server的API 请注意,我们的示例客户端已经完成了此操作。

import "google.golang.org/grpc/channelz/service"

// s is a *grpc.Server
service.RegisterChannelzServiceToServer(s)

// call s.Serve() to serve channelz service

一个名为grpc-zpages的网络工具  已开发出可通过网页方便地提供channelz数据的工具。首先,将Web应用程序配置为连接到为channelz服务提供服务的gRPC端口(请参阅上一个链接中的说明)。然后,在浏览器中打开channelz网页。您应该看到一个如图3所示的网页。现在我们可以开始查询channelz!

图3. Channelz主页

由于错误是在客户端,因此我们首先单击 TopChannelsTopChannels是没有父母的根频道的集合。在gRPC-Go中,主要渠道是 ClientConn由用户通过Dial创建或 DialContext,用于进行RPC调用。顶部通道的 通道 在channelz中键入,这是可以发布RPC的连接的抽象。

图4. TopChannels结果

因此,我们单击TopChannels,然后会出现一个如图4所示的页面,其中列出了所有实时直播频道以及相关信息。

如图5所示,只有一个顶部通道的id = 2(请注意,方括号中的文本是内存通道对象的参考名称,可能会因语言而异)。

查看“数据”部分,我们可以看到在此通道中有15个呼叫失败(总共100个)。

图5.顶部通道(id = 2)

在右侧,它显示该通道没有子Channel,3个 Subchannel(如图6中突出显示)和0 Sockets

图6.通道拥有的子通道(id = 2)

一个 子信道 是对连接的抽象,用于负载平衡。例如,您要将请求发送到“ google.com”。解析器将“ google.com”解析为多个为“ google.com”服务的后端地址。在此示例中,为客户端设置了循环负载均衡器,因此向所有活动后端发送了相等的流量。然后,到每个后端的(逻辑)连接表示为子通道。在gRPC-Go中, SubConn 可以看作是子渠道

父通道拥有的三个子通道意味着与三个不同的后端有三个连接,用于将RPC发送到该后端。让我们查看它们的内部以了解更多信息。

因此,我们单击列出的第一个子通道ID(即“ 4 []”),然后显示如图7所示的页面。我们可以看到该子通道上的所有调用均已成功执行,因此该子通道不太可能与我们遇到的问题有关有。

图7.子通道(id = 4)

因此,我们返回并单击子频道5(即“ 5 []”),该网页再次表明,子频道5也从未发生过任何失败的呼叫。

图8.子通道(id = 6)

最后,我们单击Subchannel6。这一次有所不同。如图8所示,此子通道上的34个RPC调用中有15个失败。请记住,父通道也有15个失败的呼叫。因此,子渠道6是问题所在。子通道的状态为READY,这意味着它已连接并准备传输RPC。那排除了网络连接问题。要了解更多信息,我们来看一下此子通道拥有的Socket。

一个 插座 大致相当于文件描述符,通常可以视为两个端点之间的TCP连接。在grpc-go中, http2Client 和 http2Server 对应于Socket。请注意,网络侦听器也被认为是套接字,并将显示在channelz服务器信息中。

图9.子通道(id = 6)拥有套接字(id = 8)

我们单击页面底部的Socket 8(请参见图9)。现在,我们看到如图10所示的页面。

该页面提供有关套接字的全面信息,例如正在使用的安全性机制,流计数,消息数,keepalive,流控制编号等。套接字选项信息未显示在屏幕快照中,因为其中有很多套接字选项且不相关我们正在调查的问题。

远程地址”字段表明我们遇到问题的后端是“ 127.0.0.1:10003”这里的流计数与父子信道的呼叫计数完全对应。由此,我们可以知道服务器没有主动发送DeadlineExceeded错误。这是因为如果服务器返回DeadlineExceeded错误,则流将全部成功。客户端流的成功与调用是否成功无关。根据是否已收到设置了EOS位的HTTP2帧来确定(请参阅 gRFC 有关更多信息)。此外,我们可以看到发送的消息数为34,等于呼叫数,它排除了客户端以某种方式卡住并导致超过期限的可能性。总之,我们可以将问题缩小到服务器上127.0.0.1:10003上。服务器可能响应缓慢,或者服务器前面的某些代理正在丢弃请求。

图10.套接字(id = 8)

如您所见,channelz只需单击几下就可以帮助我们查明问题的潜在根本原因。现在,您可以集中精力使用精确服务器。同样,channelz也可以帮助加快服务器端的调试速度。

我们将在这里停止,让读者探索比客户端更简单的服务器端channelz。在channelz中,一台 服务器 还是类似于Channel的RPC入口点,传入的RPC到达并得到处理。在grpc-go中,一个 grpc.Server对应于channelz服务器。与Channel不同,Server仅将套接字(侦听套接字和正常连接的套接字)作为其子代。

以下是给读者的一些提示:

  • 查找地址为(127.0.0.1:10003)的服务器。
  • 查看通话次数。
  • 转到服务器拥有的套接字。
  • 查看Socket流计数和消息计数。

您应该注意到,服务器套接字接收到的消息数量与客户端套接字(套接字8)发送的消息数量相同,这排除了中间出现代理行为异常(丢弃请求)的情况。并且服务器套接字发送的消息数等于客户端接收到的消息数,这意味着服务器无法在截止日期之前发回响应。您现在可以看一下 服务器 代码以验证是否确实是原因。

服务器设置: 服务器端程序启动三台GreeterServer,其中两台使用实现(服务器)响应客户端时没有延迟,并且使用了一种实现(slowServer)会在发送响应之前注入100ms-200ms的可变延迟。

正如您在本演示中所看到的,channelz帮助我们快速缩小了问题的可能原因,并且易于使用。有关更多资源,请参见详细的channelz gRFC。在GitHub上找到我们,网址github.com/grpc/grpc-go

下一个
 
原文地址:https://www.cnblogs.com/a00ium/p/14158585.html