首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >.NET容错StateServer

.NET容错StateServer
EN

Stack Overflow用户
提问于 2013-12-24 19:18:31
回答 2查看 451关注 0票数 2

我们使用StateServer来为已知的好处(web场、IIS回收)处理会话。

然而,我正试图弄清楚如何使这种容错。我们在会话中存储的任何东西都是关键的,它只是用于性能。因此,如果StateServer不可用,我们很乐意从磁盘重新加载。

但是,似乎无法检测StateServer是否联机,因此,即使StateServer关闭,下面的代码也可以正常运行

代码语言:javascript
复制
try
{
    //It is not NULL as it has been configured
    if (HttpContext.Current.Session != null)
        Session["Test"] = "value";
}
// No exception is thrown
catch (Exception)
{
    throw new Exception();
}

现在对我来说,没有例外是有道理的。如果会话处理必须检查每次写入的状态,则会话处理将不是很好的性能。因此,我猜想,当写入响应时,它会写入所有的会话变量。

这就是问题所在,当它试图编写会话时,它失败了,出现了500个错误,我不知道如何拦截这个错误并处理它。

无法向会话状态服务器发出会话状态请求。请确保启动了ASP.NET状态服务,并确保客户端和服务器端口相同。

我想要发生的是,写入只是默默地失败(或者记录一个错误),并且客户端没有受到影响。就像现在写的一样,由于这个单一的故障点,整个站点都会崩溃。

有什么主意吗-我是不是遗漏了一些明显的东西?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-12-24 19:51:29

我愿意接受tgolisch的答案,作为一个对我有用的解决方案。

  • 在Global.asax中,我们将查找Application_Error事件中缺少的StateServer错误
  • 如果我们找到它,我们将使用Server.ClearError()并记录错误
  • 我们还将使用它来记录错误,并可能发出警报。

谢谢大家!

票数 0
EN

Stack Overflow用户

发布于 2013-12-24 19:27:49

嗯,这可能很难。Asp.net紧密地使用会话,因此如果会话存储失败,它的asp.net也将在会话模块初始化期间失败。您可以编写自己的会话状态提供程序,这将包装现有的会话项,如果失败,它将返回空的会话项,但是很难使用它,因为会话行为可能是不可预测的。

您可以查看内置于SQL会话状态提供程序中的内容,如果您的server有复制的话,这就有故障转移了。

UPDATE1

下面是用于默认会话提供程序的包装器示例

代码语言:javascript
复制
public class SessionProviderWrapper : SessionStateStoreProviderBase
{
    private readonly SessionStateStoreProviderBase _provider;

    private static Func<SessionStateStoreProviderBase> _createProvider;

    static SessionProvider()
    {
        _createProvider = InitializerProvider();
    }

    private static Func<SessionStateStoreProviderBase> InitializerProvider()
    {
        if (_createProvider != null)
            return _createProvider;

        var sessionType = "stateserver"; // you can switch to another session provider

        Type type;
        switch (sessionType)
        {
            case "inproc":
                type = Type.GetType("System.Web.SessionState.InProcSessionStateStore, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");
                break;

            case "sql":
                type = Type.GetType("System.Web.SessionState.SqlSessionStateStore, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");
                break;

            case "stateserver":
                type = Type.GetType("System.Web.SessionState.OutOfProcSessionStateStore, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");
                break;

            default:
                throw new ConfigurationErrorsException("Unknow session type: " + sessionType);
        }

        if (type == null)
        {
            throw new InvalidOperationException("Failed to find session provider for " + sessionType);
        }

        _createProvider = GenerateConstructorCall(type);

        return _createProvider;
    }

    private static Func<SessionStateStoreProviderBase> GenerateConstructorCall(Type type)
    {
        // we are searching for public constructor
        var constructor = type.GetConstructors().FirstOrDefault(c => c.GetParameters().Length == 0);
        if (constructor == null)
        {
            // otherwise for internal. SQL session provider has internal constructor, but we don't care
            constructor = type.GetConstructors(BindingFlags.NonPublic | BindingFlags.Instance).FirstOrDefault(c => c.GetParameters().Length == 0);
        }

        var node = Expression.New(constructor);
        var lambda = Expression.Lambda<Func<SessionStateStoreProviderBase>>(node, null);
        var func = lambda.Compile();
        return func;
    }

    public SessionProvider()
    {
        var createProvider = InitializerProvider();

        _provider = createProvider();
    }

    public override void Initialize(string name, NameValueCollection config)
    {
        _provider.Initialize(name, config);
    }

    public override string Name
    {
        get { return _provider.Name; }
    }

    public override string Description
    {
        get { return _provider.Description; }
    }

    public override void Dispose()
    {
        _provider.Dispose();
    }

    public override bool SetItemExpireCallback(SessionStateItemExpireCallback expireCallback)
    {
        return _provider.SetItemExpireCallback(expireCallback);
    }

    public override void InitializeRequest(HttpContext context)
    {
        _provider.InitializeRequest(context);
    }

    public override SessionStateStoreData GetItem(HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId,
                                         out SessionStateActions actions)
    {
        try
        {
            return _provider.GetItem(context, id, out locked, out lockAge, out lockId, out actions);
        }
        catch (Exception ex)
        {
            locked = false;
            lockAge = TimeSpan.Zero;
            lockId = null;
            actions = SessionStateActions.None;
            // log ex
            return new SessionStateStoreData(new SessionStateItemCollection(), new HttpStaticObjectsCollection(), 10);
        }
    }

    public override SessionStateStoreData GetItemExclusive(HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId,
                                                  out SessionStateActions actions)
    {
        return _provider.GetItemExclusive(context, id, out locked, out lockAge, out lockId, out actions);
    }

    public override void ReleaseItemExclusive(HttpContext context, string id, object lockId)
    {
        _provider.ReleaseItemExclusive(context, id, lockId);
    }

    public override void SetAndReleaseItemExclusive(HttpContext context, string id, SessionStateStoreData item, object lockId, bool newItem)
    {
        _provider.SetAndReleaseItemExclusive(context, id, item, lockId, newItem);
    }

    public override void RemoveItem(HttpContext context, string id, object lockId, SessionStateStoreData item)
    {
        _provider.RemoveItem(context, id, lockId, item);
    }

    public override void ResetItemTimeout(HttpContext context, string id)
    {
        _provider.ResetItemTimeout(context, id);
    }

    public override SessionStateStoreData CreateNewStoreData(HttpContext context, int timeout)
    {
        return _provider.CreateNewStoreData(context, timeout);
    }

    public override void CreateUninitializedItem(HttpContext context, string id, int timeout)
    {
        _provider.CreateUninitializedItem(context, id, timeout);
    }

    public override void EndRequest(HttpContext context)
    {
        _provider.EndRequest(context);
    }
}

基本上,您可以像在GetItem方法中那样对每个方法进行try\catch,如果出现错误,您可以返回空的session对象。如果try\catch应用程序失败,它仍将处于活动状态。但是性能会下降,因为对于每个请求,它将在Get\Release上抛出一些异常,这些异常将在catch部分中处理。但是无论如何,这些异常都会降低性能。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20765817

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档