使用protobuf-net的ASP.NET SessionState模式SQLServer序列化

Jos*_*ker 3 asp.net session session-state protocol-buffers protobuf-net

问题背景

我一直在考虑优化SQL Server内会话的状态存储的方法,我遇到的几种方法是:

  • 在不需要会话的页面上禁用会话状态。另外,在未写入会话的页面上使用只读。
  • 在ASP.NET 4.0中,使用gzip压缩选项。
  • 尝试使会话中存储的数据量最少。
  • 等等

现在,我在会话中存储了一个对象(称为SessionObject的类)。好消息是,它是完全可序列化的。

使用protobuf-net进行优化

我认为另一种优化会话存储的好方法可能是使用协议缓冲区(protobuf-net)序列化/反序列化而不是标准BinaryFormatter。我知道我可以让所有对象继承ISerializable,但是我不想创建DTO或使用序列化/反序列化逻辑使我的Domain层混乱。

将protobuf-net与会话状态SQL Server模式一起使用的任何建议都很棒!

Mar*_*ell 5

如果现有的会话状态代码使用BinaryFormatter,那么您可以通过仅在您的根对象上BinaryFormatter实现protobuf-net作为其内部代理来作弊:ISerializable

[ProtoContract]
class SessionObject : ISerializable {
    public SessionObject() { }
    protected SessionObject(SerializationInfo info, StreamingContext context) {
        Serializer.Merge(info, this);
    }
    void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) {
        Serializer.Serialize(info, this);
    }

    [ProtoMember(1)]
    public string Foo { get; set; }
    ...
}
Run Code Online (Sandbox Code Playgroud)

笔记:

  • 只有根对象才需要这样做;任何封装的对象将由protobuf-net自动处理
  • 它仍然会为最外层的对象添加少量类型的元数据,但不会太多
  • 您将需要相应地装饰成员(和封装的类型)(最好是对每个成员进行显式装饰;有一个隐式的“自己弄清楚”模式,但是如果添加新成员则很脆弱)
  • 这将破坏现有状态 ; 从根本上改变序列化机制是一项重大突破

如果要从对象中删除类型元数据,则必须实现自己的状态提供程序(我认为MSDN上有一个示例);因此,

  • 优点:产量较小
  • 优点:无需ISerializable在根对象上实现
  • 缺点:您需要维护自己的状态提供程序; p

(以上提出的所有其他观点仍然适用)

还请注意,此处的protobuf-net的有效性将在某种程度上取决于您要存储的数据。它应该更小,但是如果您有很多巨大的字符串,它就不会小,因为protobuf仍然使用UTF-8作为字符串。

如果您确实有很多字符串,则可以考虑另外使用gzip-我为最后一个尝试gzip的雇主编写了一个状态提供程序,并存储了最小的那个(原始的或gzip的)(显然有一些检查),例如:

  • 如果小于[某些值],请不要gzip
  • 如果gzip超过原始压缩值,请尽早将其压缩

上面的代码可以很高兴地与protobuf-net 结合使用-如果您正在编写状态提供程序,则可以删除ISerializableetc以实现最佳性能。

如果您确实想要的话,最后一个选择就是将“压缩模式”属性添加到[ProtoContract(..., CompressionMode = ...)];哪一个:

  • 仅适用于ISerializable用法(出于技术原因,更改主要布局没有任何意义,但是这种情况很好)
  • 在上面的序列化/反序列化过程中自动应用gzip [也许与我上面提到的检查相同]
  • 意味着您不需要添加自己的状态提供程序

但是,这是我只想真正申请“ v2”的东西(我对v1中的错误修正非常残酷,这样我才能保持理智)。

让我知道是否有兴趣。