我正在使用带有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);
Cache Client初始化如下:
container.Register<ICacheClient>(new MemoryCacheClient());
(或者this guide之后的Redis。)
这是通过线路的缓存的protobuf序列化数据看起来和未缓存的数据的不同之处: Big Image
未缓存的响应似乎以不同方式编码/序列化。
我有什么办法可以解决这个编码问题,使Redis或Memory-ICacheClient与protobuf兼容?
更新:我调查了一下,这些是我的发现:
要存储在缓存提供程序中(无论是Redis os Memory),protobuf二进制流通过HttpResponseFilter-> SerializeToString中的StreamReader“转换”为字符串,使用“UTF8 without BOM” - 编码,它本身通过CacheClientExtensions-&gt; Cache()。
第一个问题:CacheClientExtensions-&gt; Cache()然后返回to-string-serialized DTO,使protobuf无法反序列化。 第一个解决方案:在CacheClientExtensions-&gt; Cache()中返回原始DTO。但这只适用于第一个非缓存响应,因为缓存的响应尚未正确反序列化。这将我们带到
第二个问题:再次从缓存中获取数据需要对protobuf的二进制数据进行正确的字符串序列化,以便首先将其放入缓存中。我知道它可以使用via base64。
第三个问题:目前似乎没有办法在运行时通过HttpResponseFilter-&gt; SerializeToString中的StreamReader替换当前的流到字符串转换,对不对?
第四个问题:从缓存中获取数据时,必须再次进行base64解码。
答案 0 :(得分:1)
我正在挖掘ServiceStack代码,但发现没有可能实现我的要求(我真的希望我没有忽略某些事情)。
所以我对ServiceStack进行了一些更改,这些更改允许使用自定义TextSerializers,然后用于序列化到字符串bevor将DTO推送到缓存客户端。
在这里看到我的差异: https://github.com/derFunk/ServiceStack/commit/93f62c7d7e44a303c88a81c3096b9757daba4c7c
它可以用于我的目的,虽然它可能没有经过全面测试,但仍然非常关注原型。
如果一些ServiceStack忍者可以审查我正在做的事情,我会很感激,也许它会以拉取请求结束。