Go语言 protobuf消息失败到反序列化由于消息大小

5f0d552i  于 2023-03-16  发布在  Go
关注(0)|答案(1)|浏览(170)

消息无法从bytes反序列化为any.Any,错误消息为:proto:无法解析无效的线格式数据但仅当所有消息字段都有值时,就好像消息有大小限制,空或部分空的消息可以很好地反序列化,但如果所有字段都有值,则会失败。消息来自Dapr适配器到redis流。

import (
"github.com/golang/protobuf/proto"
"github.com/golang/protobuf/ptypes/any"
)

func (h *EventHandler) instanceHandler(ctx context.Context, e *common.TopicEvent) (bool, error) {

    var anyMsg any.Any
    b := []byte(e.Data.(string))
    err := proto.Unmarshal(b, &anyMsg)
    if err != nil {
        h.logger.Error().
            Str("eventId", e.ID).
            Str("topic", e.Topic).
            Str("source", e.Source).
            Err(err).
            Msg("")

        return false, err
    }

如果所有消息字段都有值,上述操作将失败,消息示例:

message GetElementsPaginatedRequest {
  string eid = 1;
  string mediatorID = 2;
  string callerID = 3;
  string accountID = 4;
  string streamID = 5;
  int32 limit = 6;
  int32 page = 7;
  string order = 8;
  string clientID = 9;

}

在通过网络发送之前进行序列化:

err := anyMsg.MarshalFrom(&epb)
    if err != nil {
        return err
    }

    b, err := proto.Marshal(&anyMsg)
    if err != nil {
        return err
    }

如果删除一个字段(任何字段),例如GetElementsPaginatedRequest.accountID,则反序列化将成功。
测试序列化和反序列化也可以在本地测试中正常工作,这种行为似乎只发生在从Dapr适配器接收的消息中。
对于未通过Dapr和Redis接收的消息,无法复制此问题。在本地测试中,无论消息大小如何,反序列化都工作正常。

kqlmhetl

kqlmhetl1#

通过在发布者客户端上设置内容类型并将接收者更改为从TopicEvent.Data到TopicEvent.RawData的反编组(这在设置上下文类型之后是可能的),可以避免这种字节大小差异行为。
新发布者配置

opts := []dapr.PublishEventOption{
        dapr.PublishEventWithContentType("application/octet-stream"),
    }
    err = client.PublishEvent(ctx, pubsubName, topic, b, opts...)

和proto。从RawData字段解组。

err := proto.Unmarshal(e.RawData, &anyMsg)

字节匹配并且接收器可以解码。

相关问题