現在のServiceStackをprotobufシリアル化で使用しています。
応答をキャッシュするためにICacheClientを追加すると、キャッシュクライアントから送信されたバイナリ応答は、キャッシュクライアントがない元の応答とは異なるエンコーディング/バイナリシリアル化になります。
これにより、プリコンパイルされたデシリアライザーを使用しているクライアント側でデシリアライズの問題が発生します。
たとえば、このprotobuf例外は、ServiceStackサーバー側でICacheClientを使用するときにクライアント側で発生します。
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 Memoryであるかどうかに関係なく)、protobufバイナリストリームは、HttpResponseFilter->SerializeToStringのStreamReaderを介して「BOMなしのUTF8」を使用して文字列に「変換」されます。 -> Cache()。
最初の問題:CacheClientExtensions-> Cache()は、文字列にシリアル化されたDTOを返しますが、protobufが逆シリアル化することはまだ不可能です。最初の解決策:CacheClientExtensions-> Cache()で元のDTOを返します。ただし、キャッシュされた応答はまだ適切に逆シリアル化されていないため、これはキャッシュされていない最初の応答に対してのみ機能します。これは私たちを
2番目の問題:データをキャッシュから再度取得するには、最初にデータをキャッシュに入れるために、protobufのバイナリデータの正しい文字列シリアル化が必要です。base64経由で動作することはわかっています。
3番目の問題:現在、実行時にHttpResponseFilter-> SerializeToStringでStreamReaderを介して現在のストリームから文字列への変換を置き換える方法はないようですが、私は正しいですか?
4番目の問題:データをキャッシュから取得するときは、再度base64でデコードする必要があります。