简体   繁体   English

如何处理长时间运行的订阅线程中的异常并从中恢复

[英]How to handle and recover from exceptions within long running subscription thread

I'm using ServiceStack.Redis within several ASP.NET MVC applications in order to facilitate basic messaging between those applications. 我在几个ASP.NET MVC应用程序中使用ServiceStack.Redis,以便于这些应用程序之间的基本消息传递。 Within one application I have a class which sets up a subscription and handles any messages that the application is interested in, for example: 在一个应用程序中,我有一类可以设置订阅并处理该应用程序感兴趣的任何消息,例如:

public MessageBus(IRedisClientsManager redisClientsManager)
{
    Thread subscriptionThread = new Thread(() => {
        try
        {
            using (var redisClient = redisClientsManager.GetClient())
            using (var subscription = redisClient.CreateSubscription())
            {
                subscription.OnMessage = (channel, message) =>
                {
                    handleMessage(message);
                };
                subscription.SubscribeToChannels("MyChannel");
            }
        }
        catch (Exception ex)
        {
            ErrorLog.GetDefault(null).Log(new Error(ex));
        }
    });
    subscriptionThread.Start();
}

Since "SubscribeToChannels" is blocking, I have it running in a separate thread. 由于“ SubscribeToChannels”正在阻止,因此我在单独的线程中运行它。 I want this thread to stay alive the entire time the MVC application is running and I'm concerned that the thread will just die or the connection to Redis will stop if any sort of exception occurs. 我希望该线程在MVC应用程序运行的整个过程中一直保持活动状态,并且我担心如果发生任何异常,该线程将死掉或与Redis的连接将停止。

My question is: are there any examples out there of how to recover from exceptions (connection failures, timeouts, etc) that may occur while the subscription is open? 我的问题是:是否有任何示例可以说明如何从订阅打开状态下发生的异常(连接失败,超时等)中恢复?

Regarding exceptions killing a thread, use a long-running loop: 关于杀死线程的异常,请使用长时间运行的循环:

while(!ShutdownRequested) {
    try{...}
    catch(Exception e) {/*Log and probably do some rate-limiting in case of terminal issue*/}
}

Bear in mind that the catch will swallow everything, including OutOfMemory exceptions so you'll want some sanity checking like a fail count / delay so that you don't always retry immediately. 请记住,捕获将吞没所有内容,包括OutOfMemory异常,因此您将需要进行一些检查(例如失败计数/延迟),以确保您不必总是立即重试。

Don't forget that you can retain a reference to the background thread from the parent and check the ThreadState too. 不要忘记,您可以保留来自父级的对后台线程的引用,也可以检查ThreadState

As to hosting in ASP, this is a bad idea (See this answer ). 对于在ASP中托管,这是一个坏主意(请参阅此答案 )。 When the worker pool is recycled (will happen eventually) the thread will die and won't respawn until a new page is requested (at the earliest). 当工作池被回收(最终会发生)时,线程将死掉,直到请求新页面(最早)后才会重生。

You should put this into a windows service so it runs when the server starts and if it has to communicate with your site, it should do so over WCF (2-way) or by hitting a Url (for push from service to site). 您应该将其放入Windows服务中,以便它在服务器启动时运行,并且如果它必须与您的站点进行通信,则应通过WCF(2路)或点击一个Url(将其从服务推送到站点)进行通信。

That way, it will only die when the service is stopped (hopefully only reboots). 这样,它将仅在服务停止时(希望仅重新启动)而消失。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM