C# 在ServiceStack中使用ICacheClient和protobuf时的编码/序列化问题
我正在使用带有protobuf序列化的当前ServiceStack 添加ICacheClient以缓存我的响应时,从缓存客户端发送的二进制应答与没有任何缓存客户端的原始响应具有不同的编码/二进制序列化 这导致了客户端的反序列化问题,在客户端,我使用的是预编译的反序列化程序 例如,在ServiceStack服务器端使用ICacheClient时,此protobuf异常在客户端发生:C# 在ServiceStack中使用ICacheClient和protobuf时的编码/序列化问题,c#,serialization,character-encoding,protobuf-net,
servicestack,C#,Serialization,Character Encoding,Protobuf Net,
servicestack,我正在使用带有protobuf序列化的当前ServiceStack 添加ICacheClient以缓存我的响应时,从缓存客户端发送的二进制应答与没有任何缓存客户端的原始响应具有不同的编码/二进制序列化 这导致了客户端的反序列化问题,在客户端,我使用的是预编译的反序列化程序 例如,在ServiceStack服务器端使用ICacheClient时,此protobuf异常在客户端发生: OverflowException: Number overflow. ProtoBuf.ProtoReader.T
OverflowException: Number overflow.
ProtoBuf.ProtoReader.TryReadUInt32VariantWithoutMoving (Boolean trimNegative, System.UInt32& value)
ProtoBuf.ProtoReader.ReadUInt32Variant (Boolean trimNegative)
ProtoBuf.ProtoReader.ReadUInt32 () MyModelSerializer.Read (My.Models.MyDataModel , ProtoBuf.ProtoReader )
(我相信这是一个随机的异常,可以肯定还会发生其他异常。以此为例。)
此行为与MemoryCacheClient和Redis cache client相同
这是我初始化protobuf的方式:
ContentTypeFilters.Register(ContentType.ProtoBuf,
(reqCtx, res, stream) => ProtoBuf.Serializer.NonGeneric.Serialize(stream, res),
ProtoBuf.Serializer.NonGeneric.Deserialize);
缓存客户端的初始化方式如下:
container.Register<ICacheClient>(new MemoryCacheClient());
container.Register(newmemorycacheclient());
(或Redis following)
这就是缓存的protobuf序列化数据(通过连接)与未缓存的数据的外观和区别:
未缓存响应的编码/序列化方式似乎有所不同
我能为这个编码问题做些什么使Redis或内存ICacheClient与protobuf兼容
更新:我进行了一些调查,以下是我的发现:
- 为了存储在缓存提供程序中(无论是Redis os内存),protobuf二进制流通过HttpResponseFilter->SerializeToString中的StreamReader使用“UTF8无BOM”编码“转换”为字符串,该编码本身通过CacheClientExtensions->cache()调用
- 第一个问题:CacheClientExtensions->Cache()然后返回字符串to serialized DTO,使得protobuf无法反序列化第一个解决方案:在CacheClientExtensions->Cache()中返回原始DTO。但这只适用于第一个非缓存响应,因为缓存响应尚未正确反序列化。这把我们带到了
- 第二个问题:再次从缓存中取出数据需要对protobuf的二进制数据进行正确的字符串序列化,以便首先将其放入缓存中。我知道使用via base64会起作用
- 第三个问题:目前似乎无法在运行时通过HttpResponseFilter->SerializeToString中的StreamReader替换当前流到字符串的转换,对吗
- 第四个问题:从缓存中取回数据时,必须再次对其进行base64解码
如果一些ServiceStack忍者能够回顾我正在做的事情,我将不胜感激,也许它最终会成为一个请求。这听起来主要是ServiceStack;我相信Mythz或其他人很快就会出现,但一如既往:如果我能从protobuf网络方面提供帮助,请有人喊我一声。谢谢@MarcGravel。你同意我的观点,屏幕截图中缓存的(屏幕截图右侧)二进制格式对于protobuf是无效的?老实说,我还没有尝试过分析它(我不是在电脑上),压缩之类的东西可能是一个因素,但是:这听起来像是protobuf net所做的事情之外的东西。不过,有一件事我并不清楚:为什么调用
ContentTypeFilters.Register
时stacktrace会提到MyModelSerializer
?呵呵,我以为你会记住字节码:)关于MyModelSerializer:那是客户端。很抱歉,我会添加这些信息。如果能使用十六进制计算器和记事本,我可以检查一下。在while循环中更容易启动ProtoReader
,但是:while(reader.ReadFieldHeader()>0){reader.SkipField();}
-这将不考虑任何servicestack包装,尽管mythz确认了这个问题,我接受了自己的答案。