【问题标题】:Dynamic defined message in gRPC GOgRPC GO 中动态定义的消息
【发布时间】:2021-06-21 10:37:45
【问题描述】:

我是 Go 中 gRPC 的新用户。

我已经完成了关于客户端流 API 的代码。现在我有一个问题。

据我所知,我们必须在proto文件中定义message struct,然后protoc基于这个定义的message struct来生成代码。就我而言,protoc 生成 Go 代码。但是这个过程限制了客户端或服务器重用 API。例如,使用客户端流 API,首先,客户端使用此 API 将温度数据发送到服务器。那么客户端如果想向服务器发送GPS坐标,则必须重新定义message struct,因为温度的结构与GPS坐标的结构不同。但是为了同样的目的是向服务器发送数据。

syntax = "proto3";
package calculator;
option go_package="calculatorpb";
message TemperatureRequest{
     float num =1;
}
message TemperatureResponse{
     float result =1;
}
message CoordinatesRequest{
     float long =1;
     float lat =1;
}
message CoordinatesResponse{
     float result =1;
}
service  CalculatorService{
   rpc Temperature(stream AverageRequest) returns (AverageResponse){} //client streaming for temperature    
   rpc Coordinates(stream CoordinatesRequest) returns (CoordinatesResponse){} //client streaming  for  Coordinates
}

好像很不方便。

那么,客户端如何在 go 中使用带有 gRPC 的动态消息结构?

如果是,请给我一个客户端流 API 的示例。

【问题讨论】:

  • 动态消息结构是什么意思?服务器可以通过某种方式将 proto 文件共享给客户端吗?
  • 这没有什么动态的。您的方法正在获取和返回预定义的数据类型。
  • @sonus21 是的。我不知道如何使它变得动态。我的意思是,我如何使用一个函数将任何消息结构流式传输到服务器。

标签: go grpc grpc-go


【解决方案1】:

听起来你要求的是:

syntax = "proto3";
package calculator;
option go_package="calculatorpb";

// message TemperatureRequest, TemperatureResponse, CoordinatesRequest, CoordinatesResponse defined as in your example

message DataRequest {
  TemperatureRequest temperature_request = 1;
  CoordinatesRequest coordinates_request = 2;
}
message DataResponse {
  TemperatureResponse temperature_response = 1;
  CoordinatesResponse coordinates_response = 2;
}

service  CalculatorService{
   rpc Data(stream DataRequest) returns (DataResponse){} //client streaming for data
}

请记住,DataRequestDataResponse 是可扩展的,因此您可以在将来根据需要向它们添加字段。

【讨论】:

  • 谢谢 Doug Fawley 先生,我知道我们可以扩展消息结构,但是当我们扩展时,我们必须编辑代码,使用 protoc 再次生成代码,重新部署客户端服务。我的目标是找到跳过这些步骤的方法。例如,客户端可以在 json 文件中定义他的消息结构,然后 protoc 读取该文件并流式传输消息。在我看来,客户端仅流式传输数据,因此它不关心消息结构。
  • 我有个主意。我可以将消息结构定义为字节 []。然后,当客户端有数据(字符串、json、结构或任何东西)时,它首先将 theat 数据转换为 byte[] 并流式传输到服务器。服务器接收 []byte 流转换重新转换。这个想法合理吗?
  • 如果你想这样做,比bytes 字段更好的是使用Anydevelopers.google.com/protocol-buffers/docs/proto3#any
【解决方案2】:

使用Any 消息类型:

syntax = "proto3";

import "google/protobuf/any.proto";

message Example {
    string id = 1;
    google.protobuf.Any message = 2;
}

使用Any,您可以使用任何用户定义的原始消息,您还需要使用一些通用的存储库或注册表与客户端共享新的原始消息。

【讨论】:

    【解决方案3】:

    我不确定我是否正确理解了您的问题,但我假设我理解了。 Protobuf 是一种定义两个服务之间通信协议的方法,而不限制这些服务器的底层技术。

    protoc生成的代码只有服务之间通信的目的。如果你想在它们上面有额外的方法和存根代码,你需要两端的包装器结构。因为这是使用 protobuf 的惯用方式

    例如。

    type MyStruct{
    
    pb.Mystruct
    
    }
    
    func (m MyStruct) CalculateWeather() (int,error){
    
    ...
    
    }
    
    

    通常,您应该为每种情况定义不同的结构。我不确定你想要什么,但你可以简单地编组你的对象并发送字节,然后解组返回

    【讨论】:

    • 我已经清楚地编辑了我的问题。我的意思是,我如何使用一个函数将任何消息结构流式传输到服务器。请帮帮我。
    • 已编辑,但我真的不明白你想要实现什么
    • 我的意思是“如何使用任何消息结构制作客户端流 API”?
    猜你喜欢
    • 2016-09-23
    • 2019-07-07
    • 2015-01-27
    • 2020-08-02
    • 2017-12-06
    • 1970-01-01
    • 1970-01-01
    • 2019-01-20
    • 1970-01-01
    相关资源
    最近更新 更多