ping测试

Fortio的gRPC ping测试

整体看一下 gRPC ping 的实现。

proto 定义

fgrpc/ping.proto 文件定义了 PingServer 服务和 Ping 方法:

syntax = "proto3";
package fgrpc;

message PingMessage {
  int64 seq      = 1; // sequence number
  int64 ts       = 2; // src send ts / dest receive ts  //这个是timestamp
  string payload = 3; // extra packet data
  int64 delayNanos = 4; // delay the response by x nanoseconds
}

service PingServer {
  rpc Ping (PingMessage) returns (PingMessage) {}
}

生成的对应的 go 代码在 fgrpc/ping.pb.go 中。

这是一个非常简单的方法,参数也足够简单。

客户端发起 ping 测试请求

ts := time.Now().UnixNano()
// 创建 PingServerClient
grpcstate[i].clientP = NewPingServerClient(conn)
if grpcstate[i].clientP == nil {
  return nil, fmt.Errorf("unable to create ping client %d for %s", i, o.Destination)
}
// 组装请求的message
grpcstate[i].reqP = PingMessage{Payload: o.Payload, DelayNanos: o.Delay.Nanoseconds(), Seq: int64(i), Ts: ts}
if o.Exactly <= 0 {
  // 调用 ping 方法
  _, err = grpcstate[i].clientP.Ping(context.Background(), &grpcstate[i].reqP)
}

很正统的 gRPC 调用方式。

疑虑:为什么要为每个线程都建立一个 gRPC 连接?其实可以多线程共用一个 gRPC 连接的。

服务器端接收并响应 ping 测试请求

fgrpc/pingsrv.go 中实现了一个简单的 ping 方法:

func (s *pingSrv) Ping(c context.Context, in *PingMessage) (*PingMessage, error) {
	log.LogVf("Ping called %+v (ctx %+v)", *in, c)
	out := *in // copy the input including the payload etc
	out.Ts = time.Now().UnixNano()
	if in.DelayNanos > 0 {
		s := time.Duration(in.DelayNanos)
		log.LogVf("GRPC ping: sleeping for %v", s)
		time.Sleep(s)
	}
	return &out, nil
}