我正在使用带有 protobuf 序列化的当前 ServiceStack。
添加 ICacheClient 以缓存我的响应时,从缓存客户端发送的二进制答案与没有任何缓存客户端的原始响应具有不同的编码/二进制序列化。
这会导致客户端出现反序列化问题,我使用的是预编译的反序列化器。
例如,在 ServiceStack 服务器端使用 ICacheClient 时,客户端会出现此 protobuf 异常:
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 缓存客户端相同。
这就是我初始化 protobuf 的方式:
ContentTypeFilters.Register(ContentType.ProtoBuf,
(reqCtx, res, stream) => ProtoBuf.Serializer.NonGeneric.Serialize(stream, res),
ProtoBuf.Serializer.NonGeneric.Deserialize);
缓存客户端初始化如下:
container.Register<ICacheClient>(new MemoryCacheClient());
(或遵循本指南的Redis )。
这就是通过网络传输的缓存的 protobuf 序列化数据的外观,并且与未缓存的数据不同: Big Image
未缓存的响应似乎以不同的方式编码/序列化。
对于这个编码问题,我可以做些什么来使 Redis 或 Memory-ICacheClient 与 protobuf 兼容?
更新:我调查了一下,这些是我的发现:
要存储在缓存提供程序中(无论是 Redis os 内存),protobuf 二进制流通过 HttpResponseFilter->SerializeToString 中的 StreamReader 使用“UTF8 without BOM”-Encoding“转换”为字符串,该编码本身通过 CacheClientExtensions 调用->缓存()。
第一个问题:CacheClientExtensions->Cache() 然后返回到字符串序列化的 DTO,使得 protobuf 已经不可能反序列化。第一个解决方案:在 CacheClientExtensions->Cache() 中返回原始 DTO。但这仅适用于第一个非缓存响应,因为缓存的响应尚未正确反序列化。这将我们带到
第二个问题:再次从缓存中取出数据需要对 protobuf 的二进制数据进行正确的字符串序列化,以便首先将其放入缓存中。我知道它将通过 base64 工作。
第三个问题:目前似乎没有办法在运行时通过 HttpResponseFilter->SerializeToString 中的 StreamReader 替换当前的流到字符串转换,对吗?
第四个问题:从缓存中取回数据时,必须再次进行base64解码。