grpc reflect grpcurl源码分析

2022-08-03 13:58:37 浏览数 (1)

proto生成的代码中,有一个byte数组,这个数组是干嘛的呢?

代码语言:javascript复制
var file_reflection_grpc_reflection_v1alpha_reflection_proto_rawDesc = []byte{
  0x0a, 0x33, 0x72, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x67, 0x72, 0x70,
  0x63, 0x5f, 0x72, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x76, 0x31, 0x61,
  0x6c, 0x70, 0x68, 0x61, 0x2f, 0x72, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e,
  0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x17, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x72, 0x65, 0x66, 0x6c,
  0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x22, 0xf8,
  0x02, 0x0a, 0x17, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74,
  0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x6f,
  0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x12, 0x2a,
  0x0a, 0x10, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x62, 0x79, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61,
  0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0e, 0x66, 0x69, 0x6c, 0x65,
  0x42, 0x79, 0x46, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x36, 0x0a, 0x16, 0x66, 0x69,
  0x6c, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x79,
  0x6d, 0x62, 0x6f, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x14, 0x66, 0x69,
  0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x53, 0x79, 0x6d, 0x62,
  0x6f, 0x6c, 0x12, 0x67, 0x0a, 0x19, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61,
  0x69, 0x6e, 0x69, 0x6e, 0x67, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x18,
  0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x72, 0x65, 0x66,
  0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e,
  0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
  0x48, 0x00, 0x52, 0x17, 0x66, 0x69, 0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x69,
  0x6e, 0x67, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x42, 0x0a, 0x1d, 0x61,
  0x6c, 0x6c, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x6e, 0x75, 0x6d,
  0x62, 0x65, 0x72, 0x73, 0x5f, 0x6f, 0x66, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x06, 0x20, 0x01,
  0x28, 0x09, 0x48, 0x00, 0x52, 0x19, 0x61, 0x6c, 0x6c, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69,
  0x6f, 0x6e, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x4f, 0x66, 0x54, 0x79, 0x70, 0x65, 0x12,
  0x25, 0x0a, 0x0d, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73,
  0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0c, 0x6c, 0x69, 0x73, 0x74, 0x53, 0x65,
  0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x42, 0x11, 0x0a, 0x0f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67,
  0x65, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x66, 0x0a, 0x10, 0x45, 0x78, 0x74,
  0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x27, 0x0a,
  0x0f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x5f, 0x74, 0x79, 0x70, 0x65,
  0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x69,
  0x6e, 0x67, 0x54, 0x79, 0x70, 0x65, 0x12, 0x29, 0x0a, 0x10, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73,
  0x69, 0x6f, 0x6e, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05,
  0x52, 0x0f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x4e, 0x75, 0x6d, 0x62, 0x65,
  0x72, 0x22, 0xc7, 0x04, 0x0a, 0x18, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x66, 0x6c,
  0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1d,
  0x0a, 0x0a, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01,
  0x28, 0x09, 0x52, 0x09, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x48, 0x6f, 0x73, 0x74, 0x12, 0x5b, 0x0a,
  0x10, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73,
  0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x72,
  0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68,
  0x61, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69,
  0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x0f, 0x6f, 0x72, 0x69, 0x67, 0x69,
  0x6e, 0x61, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x6b, 0x0a, 0x18, 0x66, 0x69,
  0x6c, 0x65, 0x5f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x5f, 0x72, 0x65,
  0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x67,
  0x72, 0x70, 0x63, 0x2e, 0x72, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76,
  0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72,
  0x69, 0x70, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x00, 0x52,
  0x16, 0x66, 0x69, 0x6c, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x52,
  0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x77, 0x0a, 0x1e, 0x61, 0x6c, 0x6c, 0x5f, 0x65,
  0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x73,
  0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32,
  0x30, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x72, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f,
  0x6e, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73,
  0x69, 0x6f, 0x6e, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
  0x65, 0x48, 0x00, 0x52, 0x1b, 0x61, 0x6c, 0x6c, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f,
  0x6e, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
  0x12, 0x64, 0x0a, 0x16, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
  0x73, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b,
  0x32, 0x2c, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x72, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69,
  0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53,
  0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x00,
  0x52, 0x14, 0x6c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65,
  0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4f, 0x0a, 0x0e, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f,
  0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26,
  0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x72, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e,
  0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x65,
  0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x00, 0x52, 0x0d, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x52,
  0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x12, 0x0a, 0x10, 0x6d, 0x65, 0x73, 0x73, 0x61,
  0x67, 0x65, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x4c, 0x0a, 0x16, 0x46,
  0x69, 0x6c, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73,
  0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x32, 0x0a, 0x15, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x64, 0x65,
  0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x18, 0x01,
  0x20, 0x03, 0x28, 0x0c, 0x52, 0x13, 0x66, 0x69, 0x6c, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69,
  0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x6a, 0x0a, 0x17, 0x45, 0x78, 0x74,
  0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70,
  0x6f, 0x6e, 0x73, 0x65, 0x12, 0x24, 0x0a, 0x0e, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x74, 0x79, 0x70,
  0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x62, 0x61,
  0x73, 0x65, 0x54, 0x79, 0x70, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x29, 0x0a, 0x10, 0x65, 0x78,
  0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x02,
  0x20, 0x03, 0x28, 0x05, 0x52, 0x0f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x4e,
  0x75, 0x6d, 0x62, 0x65, 0x72, 0x22, 0x59, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x72,
  0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x42, 0x0a, 0x07,
  0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e,
  0x67, 0x72, 0x70, 0x63, 0x2e, 0x72, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e,
  0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52,
  0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
  0x22, 0x25, 0x0a, 0x0f, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f,
  0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
  0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x53, 0x0a, 0x0d, 0x45, 0x72, 0x72, 0x6f, 0x72,
  0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x65, 0x72, 0x72, 0x6f,
  0x72, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x65, 0x72,
  0x72, 0x6f, 0x72, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x65, 0x72, 0x72, 0x6f, 0x72,
  0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c,
  0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x32, 0x93, 0x01, 0x0a,
  0x10, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f,
  0x6e, 0x12, 0x7f, 0x0a, 0x14, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x66, 0x6c, 0x65,
  0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x30, 0x2e, 0x67, 0x72, 0x70, 0x63,
  0x2e, 0x72, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x61, 0x6c,
  0x70, 0x68, 0x61, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x66, 0x6c, 0x65, 0x63,
  0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x67, 0x72,
  0x70, 0x63, 0x2e, 0x72, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31,
  0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x66, 0x6c,
  0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x28, 0x01,
  0x30, 0x01, 0x42, 0x3b, 0x5a, 0x39, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x67, 0x6f, 0x6c,
  0x61, 0x6e, 0x67, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x72, 0x65, 0x66,
  0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x5f, 0x72, 0x65, 0x66,
  0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x62,
  0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}

相信很多人都有疑问。我们使用grpc reflection的时候,用到的proto元信息来自哪里呢,会不会和这个奇怪的数组有关?下面我们从源码来一探究竟。

反射概念最早出现于人工智能领域,20 世纪 70 年代末被引入到程序语言设计中。1982 年 MIT 的 Smith, Brian Cantwell 在他的博士论文中最早提出了程序反射的概念:

既然我们可以构造“有关某个外部世界表示”的计算过程, 并通过它来对那个外部世界进行推理; 那么我们也可以构造能够对自身表示和计算进行推理的计算过程 ,它包含负责管理有关自身的操作和结构表示的内部过程。

如何使用grpc reflection呢,很简单,直接注册就行了:

代码语言:javascript复制
reflection.Register(grpcServer)

Register函数定义在google.golang.org/grpc@v1.41.0/reflection/serverreflection.go

代码语言:javascript复制
func Register(s GRPCServer) {
  rpb.RegisterServerReflectionServer(s, &serverReflectionServer{
    s: s,
  })
}

其中serverReflectionServer定义如下:

代码语言:javascript复制
type serverReflectionServer struct {
  rpb.UnimplementedServerReflectionServer
  s GRPCServer

  initSymbols  sync.Once
  serviceNames []string
  symbols      map[string]*dpb.FileDescriptorProto // map of fully-qualified names to files
}

它内嵌了GRPCServer

代码语言:javascript复制
type GRPCServer interface {
  grpc.ServiceRegistrar
  GetServiceInfo() map[string]grpc.ServiceInfo
}

其中ServiceRegistrar 是一个接口,定义如何把服务的元信息注入的方法:

代码语言:javascript复制
func RegisterServerReflectionServer(s grpc.ServiceRegistrar, srv ServerReflectionServer) {
  s.RegisterService(&ServerReflection_ServiceDesc, srv)
}
代码语言:javascript复制
type ServiceRegistrar interface {
  // RegisterService registers a service and its implementation to the
  // concrete type implementing this interface.  It may not be called
  // once the server has started serving.
  // desc describes the service and its methods and handlers. impl is the
  // service implementation which is passed to the method handlers.
  RegisterService(desc *ServiceDesc, impl interface{})
}

grpc reflection 本质上依然是个grpc服务,它也有proto:reflection/grpc_reflection_v1alpha/reflection.proto定义如下:

代码语言:javascript复制
syntax = "proto3";

option go_package = "google.golang.org/grpc/reflection/grpc_reflection_v1alpha";

package grpc.reflection.v1alpha;

service ServerReflection {
  // The reflection service is structured as a bidirectional stream, ensuring
  // all related requests go to a single server.
  rpc ServerReflectionInfo(stream ServerReflectionRequest)
      returns (stream ServerReflectionResponse);
}


// The message sent by the client when calling ServerReflectionInfo method.
message ServerReflectionRequest {
    string host = 1;
    // To use reflection service, the client should set one of the following
    // fields in message_request. The server distinguishes requests by their
    // defined field and then handles them using corresponding methods.
    oneof message_request {
      // Find a proto file by the file name.
      string file_by_filename = 3;
  
      // Find the proto file that declares the given fully-qualified symbol name.
      // This field should be a fully-qualified symbol name
      // (e.g. <package>.<service>[.<method>] or <package>.<type>).
      string file_containing_symbol = 4;
  
      // Find the proto file which defines an extension extending the given
      // message type with the given field number.
      ExtensionRequest file_containing_extension = 5;
  
      // Finds the tag numbers used by all known extensions of extendee_type, and
      // appends them to ExtensionNumberResponse in an undefined order.
      // Its corresponding method is best-effort: it's not guaranteed that the
      // reflection service will implement this method, and it's not guaranteed
      // that this method will provide all extensions. Returns
      // StatusCode::UNIMPLEMENTED if it's not implemented.
      // This field should be a fully-qualified type name. The format is
      // <package>.<type>
      string all_extension_numbers_of_type = 6;
  
      // List the full names of registered services. The content will not be
      // checked.
      string list_services = 7;
    }
  }
  
  // The type name and extension number sent by the client when requesting
  // file_containing_extension.
  message ExtensionRequest {
    // Fully-qualified type name. The format should be <package>.<type>
    string containing_type = 1;
    int32 extension_number = 2;
  }
  
  // The message sent by the server to answer ServerReflectionInfo method.
  message ServerReflectionResponse {
    string valid_host = 1;
    ServerReflectionRequest original_request = 2;
    // The server sets one of the following fields according to the
    // message_request in the request.
    oneof message_response {
      // This message is used to answer file_by_filename, file_containing_symbol,
      // file_containing_extension requests with transitive dependencies.
      // As the repeated label is not allowed in oneof fields, we use a
      // FileDescriptorResponse message to encapsulate the repeated fields.
      // The reflection service is allowed to avoid sending FileDescriptorProtos
      // that were previously sent in response to earlier requests in the stream.
      FileDescriptorResponse file_descriptor_response = 4;
  
      // This message is used to answer all_extension_numbers_of_type requests.
      ExtensionNumberResponse all_extension_numbers_response = 5;
  
      // This message is used to answer list_services requests.
      ListServiceResponse list_services_response = 6;
  
      // This message is used when an error occurs.
      ErrorResponse error_response = 7;
    }
  }
  
  // Serialized FileDescriptorProto messages sent by the server answering
  // a file_by_filename, file_containing_symbol, or file_containing_extension
  // request.
  message FileDescriptorResponse {
    // Serialized FileDescriptorProto messages. We avoid taking a dependency on
    // descriptor.proto, which uses proto2 only features, by making them opaque
    // bytes instead.
    repeated bytes file_descriptor_proto = 1;
  }
  
  // A list of extension numbers sent by the server answering
  // all_extension_numbers_of_type request.
  message ExtensionNumberResponse {
    // Full name of the base type, including the package name. The format
    // is <package>.<type>
    string base_type_name = 1;
    repeated int32 extension_number = 2;
  }
  
  // A list of ServiceResponse sent by the server answering list_services request.
  message ListServiceResponse {
    // The information of each service may be expanded in the future, so we use
    // ServiceResponse message to encapsulate it.
    repeated ServiceResponse service = 1;
  }
  
  // The information of a single service used by ListServiceResponse to answer
  // list_services request.
  message ServiceResponse {
    // Full name of a registered service, including its package name. The format
    // is <package>.<service>
    string name = 1;
  }
  
  // The error code and error message sent by the server when an error occurs.
  message ErrorResponse {
    // This field uses the error codes defined in grpc::StatusCode.
    int32 error_code = 1;
    string error_message = 2;
  }

它定义了一个ServerReflectionInfo一个接口。看下它生成的go文件

google.golang.org/grpc@v1.44.0/reflection/grpc_reflection_v1alpha/reflection_grpc.pb.go

代码语言:javascript复制
func RegisterServerReflectionServer(s grpc.ServiceRegistrar, srv ServerReflectionServer) {
  s.RegisterService(&ServerReflection_ServiceDesc, srv)
}

注入服务引用了ServerReflection_ServiceDesc这个变量

代码语言:javascript复制
// ServerReflection_ServiceDesc is the grpc.ServiceDesc for ServerReflection service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var ServerReflection_ServiceDesc = grpc.ServiceDesc{
  ServiceName: "grpc.reflection.v1alpha.ServerReflection",
  HandlerType: (*ServerReflectionServer)(nil),
  Methods:     []grpc.MethodDesc{},
  Streams: []grpc.StreamDesc{
    {
      StreamName:    "ServerReflectionInfo",
      Handler:       _ServerReflection_ServerReflectionInfo_Handler,
      ServerStreams: true,
      ClientStreams: true,
    },
  },
  Metadata: "reflection/grpc_reflection_v1alpha/reflection.proto",
}

仔细看看,它包含了服务名,方法名(StreamName),对应的处理方法(Handler),这是每个proto service都会生成的描述service 的元信息

代码语言:javascript复制
var xxxx_ServiceDesc grpc.ServiceDesc{}
代码语言:javascript复制
func _ServerReflection_ServerReflectionInfo_Handler(srv interface{}, stream grpc.ServerStream) error {
  return srv.(ServerReflectionServer).ServerReflectionInfo(&serverReflectionServerReflectionInfoServer{stream})
}

handler仅仅通过类型推断,调用了对应的方法,也是每个proto都会生成的代码,格式如下:xxx_xxx_Handler,当然也会生成一个默认实现了我们定义的接口的struct

代码语言:javascript复制
// UnimplementedServerReflectionServer should be embedded to have forward compatible implementations.
type UnimplementedServerReflectionServer struct {
}
func (UnimplementedServerReflectionServer) ServerReflectionInfo(ServerReflection_ServerReflectionInfoServer) error {
  return status.Errorf(codes.Unimplemented, "method ServerReflectionInfo not implemented")
}

生成的客户端代码中会调用上述方法:

代码语言:javascript复制
func (c *serverReflectionClient) ServerReflectionInfo(ctx context.Context, opts ...grpc.CallOption) (ServerReflection_ServerReflectionInfoClient, error) {
  stream, err := c.cc.NewStream(ctx, &ServerReflection_ServiceDesc.Streams[0], "/grpc.reflection.v1alpha.ServerReflection/ServerReflectionInfo", opts...)
  if err != nil {
    return nil, err
  }
  x := &serverReflectionServerReflectionInfoClient{stream}
  return x, nil
}

reflect server的真实实现代码位于

google.golang.org/grpc@v1.44.0/reflection/serverreflection.go定义了一个结构体serverReflectionServer实现了前面定义的proto的接口

代码语言:javascript复制
type serverReflectionServer struct {
  rpb.UnimplementedServerReflectionServer
  s GRPCServer

  initSymbols  sync.Once
  serviceNames []string
  symbols      map[string]*dpb.FileDescriptorProto // map of fully-qualified names to files
}

具体如下:

代码语言:javascript复制
func (s *serverReflectionServer) ServerReflectionInfo(stream rpb.ServerReflection_ServerReflectionInfoServer) error {
       switch req := in.MessageRequest.(type) {
       case *rpb.ServerReflectionRequest_FileByFilename:
        
       case *rpb.ServerReflectionRequest_FileContainingSymbol:
              b, err := s.fileDescEncodingContainingSymbol(req.FileContainingSymbol, sentFileDescriptors)
      
       case *rpb.ServerReflectionRequest_FileContainingExtension:

       case *rpb.ServerReflectionRequest_AllExtensionNumbersOfType:

       case *rpb.ServerReflectionRequest_ListServices:
          svcNames, _ := s.getSymbols()
}

介绍完服务端核心代码后,我们从客户端开始详细介绍一个grpc reflect请求的详细过程。我们知道grpcurl 是基于grpc reflection实现的,它本质上是对grpc reflection 的client的一个包装。那么我们就从grpcurl 的源码入手开始分析:cmd/grpcurl.go 在main方法里面,首先初始化了一个grpc连接,用这个链接初始化了refletionClient,然后根据我们传入的命令后参数选项,分别调用了不同的方法,比如list 命令调用了grpcurl.ListMethods(descSource, symbol) list调用了 grpcurl.GetDescriptorText(dsc, descSource),decription调用了descSource.FindSymbol(s)

代码语言:javascript复制
dial := func() *grpc.ClientConn {
    cc, err := grpcurl.BlockingDial(ctx, network, target, creds, opts...)
}
    
refClient = grpcreflect.NewClient(refCtx, reflectpb.NewServerReflectionClient(cc))
reflSource := grpcurl.DescriptorSourceFromServer(ctx, refClient)

svcs, err := grpcurl.ListServices(descSource)
methods, err := grpcurl.ListMethods(descSource, symbol)

svcs, err := descSource.ListServices()
txt, err := grpcurl.GetDescriptorText(dsc, descSource)

dsc, err := descSource.FindSymbol(s)
fqn := dsc.GetFullyQualifiedName()
var elementType string
switch d := dsc.(type) {
case *desc.MessageDescriptor:
    elementType = "a message"
    parent, ok := d.GetParent().(*desc.MessageDescriptor)

descriptionSource定义在desc_source.go,核心有三个方法

代码语言:javascript复制
func DescriptorSourceFromServer(_ context.Context, refClient *grpcreflect.Client) DescriptorSource {
return serverSource{client: refClient}
}
代码语言:javascript复制
type DescriptorSource interface {
// ListServices returns a list of fully-qualified service names. It will be all services in a set of
// descriptor files or the set of all services exposed by a gRPC server.
ListServices() ([]string, error)
// FindSymbol returns a descriptor for the given fully-qualified symbol name.
FindSymbol(fullyQualifiedName string) (desc.Descriptor, error)
// AllExtensionsForType returns all known extension fields that extend the given message type name.
AllExtensionsForType(typeName string) ([]*desc.FieldDescriptor, error)
}

serverSource是上述接口的一个实现:

代码语言:javascript复制
type serverSource struct {
  client *grpcreflect.Client
}

func (ss serverSource) ListServices() ([]string, error) {
  svcs, err := ss.client.ListServices()
  return svcs, reflectionSupport(err)
}

func (ss serverSource) FindSymbol(fullyQualifiedName string) (desc.Descriptor, error){
      file, err := ss.client.FileContainingSymbol(fullyQualifiedName)
        d := file.FindSymbol(fullyQualifiedName)
}

它其实仅仅对grpc reflect 的client的一个封装,代码位于:

github.com/jhump/protoreflect@v1.10.3/grpcreflect/client.go

代码语言:javascript复制
func (cr *Client) ListServices() ([]string, error) {
  req := &rpb.ServerReflectionRequest{
    MessageRequest: &rpb.ServerReflectionRequest_ListServices{
      // proto doesn't indicate any purpose for this value and server impl
      // doesn't actually use it...
      ListServices: "*",
    },
  }
  resp, err := cr.send(req)
  if err != nil {
    return nil, err
  }

  listResp := resp.GetListServicesResponse()
  if listResp == nil {
    return nil, &ProtocolError{reflect.TypeOf(listResp).Elem()}
  }
  serviceNames := make([]string, len(listResp.Service))
  for i, s := range listResp.Service {
    serviceNames[i] = s.Name
  }
  return serviceNames, nil
}
代码语言:javascript复制
func (cr *Client) FileContainingSymbol(symbol string) (*desc.FileDescriptor, error) {
      req := &rpb.ServerReflectionRequest{
    MessageRequest: &rpb.ServerReflectionRequest_FileContainingSymbol{
      FileContainingSymbol: symbol,
    },
  }
}

我们回到server端,可以看到list,对应的是

代码语言:javascript复制
 case *rpb.ServerReflectionRequest_ListServices:
          svcNames, _ := s.getSymbols()

它调用了

代码语言:javascript复制
func (s *serverReflectionServer) getSymbols() (svcNames []string, symbolIndex map[string]*dpb.FileDescriptorProto) 

  serviceInfo := s.s.GetServiceInfo()

      for svc, info := range serviceInfo {
      s.serviceNames = append(s.serviceNames, svc)
      fdenc, ok := parseMetadata(info.Metadata)

            fd, err := decodeFileDesc(fdenc)
            s.processFile(fd, processed)

其中的s是接口s GRPCServer它的实现位于

google.golang.org/grpc@v1.44.0/server.go

代码语言:javascript复制
// ServiceRegistrar wraps a single method that supports service registration. It
// enables users to pass concrete types other than grpc.Server to the service
// registration methods exported by the IDL generated code.
type ServiceRegistrar interface {
  // RegisterService registers a service and its implementation to the
  // concrete type implementing this interface.  It may not be called
  // once the server has started serving.
  // desc describes the service and its methods and handlers. impl is the
  // service implementation which is passed to the method handlers.
  RegisterService(desc *ServiceDesc, impl interface{})
}

上述接口对应的实现类如下

代码语言:javascript复制
type Server struct {
  opts serverOptions

  mu  sync.Mutex // guards following
  lis map[net.Listener]bool
  // conns contains all active server transports. It is a map keyed on a
  // listener address with the value being the set of active transports
  // belonging to that listener.
  conns    map[string]map[transport.ServerTransport]bool
  serve    bool
  drain    bool
  cv       *sync.Cond              // signaled when connections close for GracefulStop
  services map[string]*serviceInfo // service name -> service info
  events   trace.EventLog

  quit               *grpcsync.Event
  done               *grpcsync.Event
  channelzRemoveOnce sync.Once
  serveWG            sync.WaitGroup // counts active Serve goroutines for GracefulStop

  channelzID int64 // channelz unique identification number
  czData     *channelzData

  serverWorkerChannels []chan *serverWorkerData
}
代码语言:javascript复制
// GetServiceInfo returns a map from service names to ServiceInfo.
// Service names include the package names, in the form of <package>.<service>.
func (s *Server) GetServiceInfo() map[string]ServiceInfo {
     for n, srv := range s.services {
}
代码语言:javascript复制
func NewServer(opt ...ServerOption) *Server {
  s := &Server{
      services: make(map[string]*serviceInfo),
  }
}

返回的ServiceInfo定义如下:

代码语言:javascript复制
// ServiceInfo contains unary RPC method info, streaming RPC method info and metadata for a service.
type ServiceInfo struct {
  Methods []MethodInfo
  // Metadata is the metadata specified in ServiceDesc when registering service.
  Metadata interface{}
}

它提供了注册方法,把service信息注册到map里面

代码语言:javascript复制
func (s *Server) RegisterService(sd *ServiceDesc, ss interface{}){
    s.register(sd, ss)
}
代码语言:javascript复制
func (s *Server) register(sd *ServiceDesc, ss interface{}) {
   if _, ok := s.services[sd.ServiceName]; ok {
    logger.Fatalf("grpc: Server.RegisterService found duplicate service registration for %q", sd.ServiceName)
  }
  
  info := &serviceInfo{
    serviceImpl: ss,
    methods:     make(map[string]*MethodDesc),
    streams:     make(map[string]*StreamDesc),
    mdata:       sd.Metadata,
  }
   
   s.services[sd.ServiceName] = info
}

其中servicedesc如下:

代码语言:javascript复制
// ServiceDesc represents an RPC service's specification.
type ServiceDesc struct {
  ServiceName string
  // The pointer to the service interface. Used to check whether the user
  // provided implementation satisfies the interface requirements.
  HandlerType interface{}
  Methods     []MethodDesc
  Streams     []StreamDesc
  Metadata    interface{}
}

主要作用就是把我们前面提到的ServerReflection_ServiceDesc对象注入到ServiceDesc供后面使用。

接着我们看下desc它对应的代码是

代码语言:javascript复制
case *rpb.ServerReflectionRequest_FileContainingSymbol:
              b, err := s.fileDescEncodingContainingSymbol(req.FileContainingSymbol, sentFileDescriptors)
代码语言:javascript复制
func (s *serverReflectionServer) fileDescEncodingContainingSymbol(name string, sentFileDescriptors map[string]bool) ([][]byte, error) {
    fd, err = s.fileDescForType(st)
}
代码语言:javascript复制
func (s *serverReflectionServer) fileDescForType(st reflect.Type) (*dpb.FileDescriptorProto, error) {
  m, ok := reflect.Zero(reflect.PtrTo(st)).Interface().(protoMessage)
    enc, _ := m.Descriptor()
  return decodeFileDesc(enc)
}
代码语言:javascript复制
func decodeFileDesc(enc []byte) (*dpb.FileDescriptorProto, error) {
  raw, err := decompress(enc)
    fd := new(dpb.FileDescriptorProto)
    if err := proto.Unmarshal(raw, fd); err != nil {
}
代码语言:javascript复制
func decompress(b []byte) ([]byte, error) {
  r, err := gzip.NewReader(bytes.NewReader(b))
}

它先从m.Descriptor()拿到数据,然后decompress,Descriptor是获取原始数据的一个接口,它一般会被压缩后存储:

代码语言:javascript复制
// protoMessage is used for type assertion on proto messages.
// Generated proto message implements function Descriptor(), but Descriptor()
// is not part of interface proto.Message. This interface is needed to
// call Descriptor().
type protoMessage interface {
  Descriptor() ([]byte, []int)
}

以为ServerReflectionRequest例

代码语言:javascript复制
func (*ServerReflectionRequest) Descriptor() ([]byte, []int) {
  return file_reflection_grpc_reflection_v1alpha_reflection_proto_rawDescGZIP(), []int{0}
}
代码语言:javascript复制
func file_reflection_grpc_reflection_v1alpha_reflection_proto_rawDescGZIP() []byte {
    file_reflection_grpc_reflection_v1alpha_reflection_proto_rawDescData = protoimpl.X.CompressGZIP(file_reflection_grpc_reflection_v1alpha_reflection_proto_rawDescData)
}
代码语言:javascript复制
  file_reflection_grpc_reflection_v1alpha_reflection_proto_rawDescData = file_reflection_grpc_reflection_v1alpha_reflection_proto_rawDesc

它里面最终存储的数据是gzip后的,我们开头提到的奇怪的byte数组。

代码语言:javascript复制
var file_reflection_grpc_reflection_v1alpha_reflection_proto_rawDesc = []byte{
  0x0a, 0x33, 0x72, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x67, 0x72, 0x70,
}

解压后它会被unmarshal到FileDescriptorProto里面

代码语言:javascript复制
 fd := new(dpb.FileDescriptorProto)
    if err := proto.Unmarshal(raw, fd); err != nil {

它的定义位于

github.com/golang/protobuf@v1.5.2/protoc-gen-go/descriptor/descriptor.pb.go

代码语言:javascript复制
type FileDescriptorProto = descriptorpb.FileDescriptorProto

它其实就是grpc reflect的核心,它里面定义了proto文件的完整信息,被序列化后就是我们开头开到的奇怪的byte数组。我们简单验证下:

代码语言:javascript复制
package main

import (
  "fmt"

  dpb "github.com/golang/protobuf/protoc-gen-go/descriptor"
  "google.golang.org/protobuf/proto"
)

func main() {
  fd := new(dpb.FileDescriptorProto)
  if err := proto.Unmarshal(file_reflection_grpc_reflection_v1alpha_reflection_proto_rawDesc, fd); err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println(fd)
}
var file_reflection_grpc_reflection_v1alpha_reflection_proto_rawDesc = []byte{
  0x0a, 0x33, 0x72, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x67, 0x72, 0x70,
  0x63, 0x5f, 0x72, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x76, 0x31, 0x61,
  0x6c, 0x70, 0x68, 0x61, 0x2f, 0x72, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e,
  0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x17, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x72, 0x65, 0x66, 0x6c,
  0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x22, 0xf8,
  0x02, 0x0a, 0x17, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74,
  0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x6f,
  0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x12, 0x2a,
  0x0a, 0x10, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x62, 0x79, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61,
  0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0e, 0x66, 0x69, 0x6c, 0x65,
  0x42, 0x79, 0x46, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x36, 0x0a, 0x16, 0x66, 0x69,
  0x6c, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x79,
  0x6d, 0x62, 0x6f, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x14, 0x66, 0x69,
  0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x53, 0x79, 0x6d, 0x62,
  0x6f, 0x6c, 0x12, 0x67, 0x0a, 0x19, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61,
  0x69, 0x6e, 0x69, 0x6e, 0x67, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x18,
  0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x72, 0x65, 0x66,
  0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e,
  0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
  0x48, 0x00, 0x52, 0x17, 0x66, 0x69, 0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x69,
  0x6e, 0x67, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x42, 0x0a, 0x1d, 0x61,
  0x6c, 0x6c, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x6e, 0x75, 0x6d,
  0x62, 0x65, 0x72, 0x73, 0x5f, 0x6f, 0x66, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x06, 0x20, 0x01,
  0x28, 0x09, 0x48, 0x00, 0x52, 0x19, 0x61, 0x6c, 0x6c, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69,
  0x6f, 0x6e, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x4f, 0x66, 0x54, 0x79, 0x70, 0x65, 0x12,
  0x25, 0x0a, 0x0d, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73,
  0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0c, 0x6c, 0x69, 0x73, 0x74, 0x53, 0x65,
  0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x42, 0x11, 0x0a, 0x0f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67,
  0x65, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x66, 0x0a, 0x10, 0x45, 0x78, 0x74,
  0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x27, 0x0a,
  0x0f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x5f, 0x74, 0x79, 0x70, 0x65,
  0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x69,
  0x6e, 0x67, 0x54, 0x79, 0x70, 0x65, 0x12, 0x29, 0x0a, 0x10, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73,
  0x69, 0x6f, 0x6e, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05,
  0x52, 0x0f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x4e, 0x75, 0x6d, 0x62, 0x65,
  0x72, 0x22, 0xc7, 0x04, 0x0a, 0x18, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x66, 0x6c,
  0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1d,
  0x0a, 0x0a, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01,
  0x28, 0x09, 0x52, 0x09, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x48, 0x6f, 0x73, 0x74, 0x12, 0x5b, 0x0a,
  0x10, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73,
  0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x72,
  0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68,
  0x61, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69,
  0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x0f, 0x6f, 0x72, 0x69, 0x67, 0x69,
  0x6e, 0x61, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x6b, 0x0a, 0x18, 0x66, 0x69,
  0x6c, 0x65, 0x5f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x5f, 0x72, 0x65,
  0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x67,
  0x72, 0x70, 0x63, 0x2e, 0x72, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76,
  0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72,
  0x69, 0x70, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x00, 0x52,
  0x16, 0x66, 0x69, 0x6c, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x52,
  0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x77, 0x0a, 0x1e, 0x61, 0x6c, 0x6c, 0x5f, 0x65,
  0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x73,
  0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32,
  0x30, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x72, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f,
  0x6e, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73,
  0x69, 0x6f, 0x6e, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
  0x65, 0x48, 0x00, 0x52, 0x1b, 0x61, 0x6c, 0x6c, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f,
  0x6e, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
  0x12, 0x64, 0x0a, 0x16, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
  0x73, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b,
  0x32, 0x2c, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x72, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69,
  0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53,
  0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x00,
  0x52, 0x14, 0x6c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65,
  0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4f, 0x0a, 0x0e, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f,
  0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26,
  0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x72, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e,
  0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x65,
  0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x00, 0x52, 0x0d, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x52,
  0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x12, 0x0a, 0x10, 0x6d, 0x65, 0x73, 0x73, 0x61,
  0x67, 0x65, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x4c, 0x0a, 0x16, 0x46,
  0x69, 0x6c, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73,
  0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x32, 0x0a, 0x15, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x64, 0x65,
  0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x18, 0x01,
  0x20, 0x03, 0x28, 0x0c, 0x52, 0x13, 0x66, 0x69, 0x6c, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69,
  0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x6a, 0x0a, 0x17, 0x45, 0x78, 0x74,
  0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70,
  0x6f, 0x6e, 0x73, 0x65, 0x12, 0x24, 0x0a, 0x0e, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x74, 0x79, 0x70,
  0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x62, 0x61,
  0x73, 0x65, 0x54, 0x79, 0x70, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x29, 0x0a, 0x10, 0x65, 0x78,
  0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x02,
  0x20, 0x03, 0x28, 0x05, 0x52, 0x0f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x4e,
  0x75, 0x6d, 0x62, 0x65, 0x72, 0x22, 0x59, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x72,
  0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x42, 0x0a, 0x07,
  0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e,
  0x67, 0x72, 0x70, 0x63, 0x2e, 0x72, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e,
  0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52,
  0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
  0x22, 0x25, 0x0a, 0x0f, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f,
  0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
  0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x53, 0x0a, 0x0d, 0x45, 0x72, 0x72, 0x6f, 0x72,
  0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x65, 0x72, 0x72, 0x6f,
  0x72, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x65, 0x72,
  0x72, 0x6f, 0x72, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x65, 0x72, 0x72, 0x6f, 0x72,
  0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c,
  0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x32, 0x93, 0x01, 0x0a,
  0x10, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f,
  0x6e, 0x12, 0x7f, 0x0a, 0x14, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x66, 0x6c, 0x65,
  0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x30, 0x2e, 0x67, 0x72, 0x70, 0x63,
  0x2e, 0x72, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x61, 0x6c,
  0x70, 0x68, 0x61, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x66, 0x6c, 0x65, 0x63,
  0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x67, 0x72,
  0x70, 0x63, 0x2e, 0x72, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31,
  0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x66, 0x6c,
  0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x28, 0x01,
  0x30, 0x01, 0x42, 0x3b, 0x5a, 0x39, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x67, 0x6f, 0x6c,
  0x61, 0x6e, 0x67, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x72, 0x65, 0x66,
  0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x5f, 0x72, 0x65, 0x66,
  0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x62,
  0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}

真的和我们预期的一样,输出如下:

代码语言:javascript复制
name:"reflection/grpc_reflection_v1alpha/reflection.proto" package:"grpc.reflection.v1alpha" message_type:{name:"ServerReflectionRequest" field:{name:"host" number:1 label:LABEL_OPTIONAL type:TYPE_STRING json_name:"host"} field:{name:"file_by_filename" number:3 label:LABEL_OPTIONAL type:TYPE_STRING oneof_index:0 json_name:"fileByFilename"} field:{name:"file_containing_symbol" number:4 label:LABEL_OPTIONAL type:TYPE_STRING oneof_index:0 json_name:"fileContainingSymbol"} field:{name:"file_containing_extension" number:5 label:LABEL_OPTIONAL type:TYPE_MESSAGE type_name:".grpc.reflection.v1alpha.ExtensionRequest" oneof_index:0 json_name:"fileContainingExtension"} field:{name:"all_extension_numbers_of_type" number:6 label:LABEL_OPTIONAL type:TYPE_STRING oneof_index:0 json_name:"allExtensionNumbersOfType"} field:{name:"list_services" number:7 label:LABEL_OPTIONAL type:TYPE_STRING oneof_index:0 json_name:"listServices"} oneof_decl:{name:"message_request"}} message_type:{name:"ExtensionRequest" field:{name:"containing_type" number:1 label:LABEL_OPTIONAL type:TYPE_STRING json_name:"containingType"} field:{name:"extension_number" number:2 label:LABEL_OPTIONAL type:TYPE_INT32 json_name:"extensionNumber"}} message_type:{name:"ServerReflectionResponse" field:{name:"valid_host" number:1 label:LABEL_OPTIONAL type:TYPE_STRING json_name:"validHost"} field:{name:"original_request" number:2 label:LABEL_OPTIONAL type:TYPE_MESSAGE type_name:".grpc.reflection.v1alpha.ServerReflectionRequest" json_name:"originalRequest"} field:{name:"file_descriptor_response" number:4 label:LABEL_OPTIONAL type:TYPE_MESSAGE type_name:".grpc.reflection.v1alpha.FileDescriptorResponse" oneof_index:0 json_name:"fileDescriptorResponse"} field:{name:"all_extension_numbers_response" number:5 label:LABEL_OPTIONAL type:TYPE_MESSAGE type_name:".grpc.reflection.v1alpha.ExtensionNumberResponse" oneof_index:0 json_name:"allExtensionNumbersResponse"} field:{name:"list_services_response" number:6 label:LABEL_OPTIONAL type:TYPE_MESSAGE type_name:".grpc.reflection.v1alpha.ListServiceResponse" oneof_index:0 json_name:"listServicesResponse"} field:{name:"error_response" number:7 label:LABEL_OPTIONAL type:TYPE_MESSAGE type_name:".grpc.reflection.v1alpha.ErrorResponse" oneof_index:0 json_name:"errorResponse"} oneof_decl:{name:"message_response"}} message_type:{name:"FileDescriptorResponse" field:{name:"file_descriptor_proto" number:1 label:LABEL_REPEATED type:TYPE_BYTES json_name:"fileDescriptorProto"}} message_type:{name:"ExtensionNumberResponse" field:{name:"base_type_name" number:1 label:LABEL_OPTIONAL type:TYPE_STRING json_name:"baseTypeName"} field:{name:"extension_number" number:2 label:LABEL_REPEATED type:TYPE_INT32 json_name:"extensionNumber"}} message_type:{name:"ListServiceResponse" field:{name:"service" number:1 label:LABEL_REPEATED type:TYPE_MESSAGE type_name:".grpc.reflection.v1alpha.ServiceResponse" json_name:"service"}} message_type:{name:"ServiceResponse" field:{name:"name" number:1 label:LABEL_OPTIONAL type:TYPE_STRING json_name:"name"}} message_type:{name:"ErrorResponse" field:{name:"error_code" number:1 label:LABEL_OPTIONAL type:TYPE_INT32 json_name:"errorCode"} field:{name:"error_message" number:2 label:LABEL_OPTIONAL type:TYPE_STRING json_name:"errorMessage"}} service:{name:"ServerReflection" method:{name:"ServerReflectionInfo" input_type:".grpc.reflection.v1alpha.ServerReflectionRequest" output_type:".grpc.reflection.v1alpha.ServerReflectionResponse" client_streaming:true server_streaming:true}} options:{go_package:"google.golang.org/grpc/reflection/grpc_reflection_v1alpha"} syntax:"proto3"

0 人点赞