从 Python 客户端发送的 GRPC 请求未被高浪服务器正确接收

我已经编写了一个Python GRPC客户端,可以连接到许多GRPC高浪服务。我已经能够像这样完成这项工作:


from alphausblue.connection.conn import grpc_client_connection

from alphausblue.iam.v1.iam_pb2 import WhoAmIRequest

from alphausblue.iam.v1.iam_pb2_grpc import IamStub


async def main():

    conn = grpc_client_connection(svc = "blue")

    stub = IamStub(conn)

    resp = await stub.WhoAmI(WhoAmIRequest())

    print(resp)

其中服务名称为 。但是,如果我尝试连接到其他服务来请求如下数据:blue


from alphausblue.connection.conn import grpc_client_connection

from alphausblue.cost.v1.cost_pb2 import ListAccountsRequest

from alphausblue.cost.v1.cost_pb2_grpc import CostStub


async def main():

    conn = grpc_client_connection(svc = "cost")

    stub = CostStub(conn)

    account = await stub.GetAccount(GetAccountRequest(vendor = 'aws', id = '731058950257'))

    print(account)

我得到一个未实现的响应。如果该服务不存在,这将是有道理的,但它确实存在,并且我的Golang客户端可以很好地连接到它。此外,当我检查服务器的日志时,我可以清楚地看到请求已到达服务器。做了更多的研究,我在我的服务器上发现了这段代码:


type service struct {

    UserInfo *blueinterceptors.UserData


    cost.UnimplementedCostServer

}


func (s *service) GetAccount(ctx context.Context, in *cost.GetAccountRequest) (*api.Account, error) {

    switch in.Vendor {

    case "aws":

        // Do stuff

    default:

        return status.Errorf(codes.Unimplemented, "not implemented")

    }

}

这告诉我的是,正在调用函数,但正在反序列化的有效负载缺少该字段。但是,在调试时,我可以看到这行:vendor


src/核心/库/安全/传输/secure_endpoint.cc:296] 写 0000018E2C62FB80: 00 00 00 13 0a 03 61 77 73 12 0c 37 33 31 30 35 38 39 35 30 32 35 37 '......哇.731058950257'


因此,数据通过 GRPC 发送到服务器,但被反序列化为缺少字段的对象。那么,这是什么原因呢?


更新


我查看了Python和Golang客户端的定义,正如@blackgreen所建议的那样。GetAccountRequest


高浪客户端代码:


// Request message for the Cost.GetAccount rpc.

type GetAccountRequest struct {

    state         protoimpl.MessageState

    sizeCache     protoimpl.SizeCache

    unknownFields protoimpl.UnknownFields


    Vendor string `protobuf:"bytes,1,opt,name=vendor,proto3" json:"vendor,omitempty"`

    Id string `protobuf:"bytes,2,opt,name=id,proto3" json:"id,omitempty"`

}

很明显,这里的字段顺序相同,因此我认为除非GRPC使用而不是.,否则这不是问题所在。indexnumber


函数式编程
浏览 76回答 1
1回答

千巷猫影

在确保您在 Python 字段中设置的字符串不包含不可见字符后,在 Python 客户端中导入的生成代码与 Go 服务器导入的代码中可能存在版本不匹配。version特别是,如果两个版本实际上都有一个字段,但Go代码以某种方式无法“识别”它,则可能是由字段标记编号不匹配引起的。version您显示的字节有效负载(hexa,base64)确实在proto字段中发送带有标签号的字符串(我怎么知道0a 03 61 77 73 12 0c 37 33 31 30 35 38 39 35 30 32 35 37CgNhd3MSDDczMTA1ODk1MDI1Nw==aws1)因此,让我们考虑一个人为的示例,Python客户端中使用的原始架构可能是GetAccountRequestmessage GetAccountRequest {    string version = 1; // field tag number 1}Go服务器中使用的那个可能是:message GetAccountRequest {    string version = 3; // field tag number 3}在这种情况下,您将在网络上看到具有版本字段的消息,但是在根据具有不同标记号的 Go 结构反序列化它时,它最终将为空。客户端使用 标记发送它,服务器期望它带有 标记 。13您可以通过检查 Go 结构来验证此假设。它应如下所示:GetAccountRequesttype GetAccountRequest struct {    // unexported fields    // other fields, in order    Version string `protobuf:"bytes,3,opt,name=version,proto3" json:"version,omitempty"`}反引号之间的部分是结构标记,其中 是标记号。`3我不知道Python中的gRPC代码是什么样的,但你应该能够以某种方式比较标签号。如果它们确实不同,请确保使用生成的具有相同标记号的结构更新客户端或服务器代码。
打开App,查看更多内容
随时随地看视频慕课网APP