2013-06-24 78 views
2

我正在使用服務堆棧連接到Redis並使用SubPub功能。IRedis訂閱連接

我應該保持IRedisSubscription和IRedisClient的實例化嗎?例如,我應該將它分配給一個類級別的變量?

或者我可以簡單地將其範圍在using語句中,Service Stack將處理持久性?

也就是說,它的下面的例子是正確的:

公共類RedisPubSub1:IDisposable的{

private static PooledRedisClientManager ClientPool = new PooledRedisClientManager("connectionString"); 
    private IRedisSubscription _subscription; 
    private IRedisClient _client; 

    private Action<string, string> _publish; 
    public event Action<string, string> Publish { 
     add { _publish += value; } 
     remove { _publish -= value; } 
    } 

    public RedisPubSub1() 
    {   
     Task.Factory.StartNew(() => 
      { 
       _client = ClientPool.GetClient(); 
       _subscription = _client.CreateSubscription(); 
        { 
         _subscription.OnMessage = EnqueEvent; 
         _subscription.SubscribeToChannels(new string[] { Channel }); 
        } 
     }); 
    } 

    private void EnqueEvent(string channel, string message) 
    { 
     if (_publish!= null) 
      _publish(channel, message); 
    }  

    public void Dispose() 
    { 
     _subscription.Dispose(); 
     _client.Dispose(); 


    } 
} } 

或者

公共類RedisPubSub2 {

private static PooledRedisClientManager ClientPool = new PooledRedisClientManager("connectionString"); 

    private Action<string, string> _publish; 

    public event Action<string, string> Publish { 
     add { _publish += value; } 
     remove { _publish -= value; } 
    } 

    public RedisPubSub2() 
    {   
     Task.Factory.StartNew(() => 
      { 
       using(var _client = ClientPool.GetClient()) 
       { 
        using(_subscription = _client.CreateSubscription() 
        { 
         _subscription.OnMessage = EnqueEvent; 
         _subscription.SubscribeToChannels(new string[] { Channel }); 
        } 
       } 
     }); 
    } 

    private void EnqueEvent(string channel, string message) 
    { 
     if (_publish!= null) 
      _publish(channel, message); 
    }  } 

回答

2

的SubscribeToChannels阻止,因此,如果你保持一個參考連接或沒有它不會出售,除非你最終的認購併不重要(即退訂)。

您實現某種方式認購退訂當你想,你不會想和線保持的積極認購,如RedisMqServer example看到,e.g做明智的做法:

using (var subscription = redisClient.CreateSubscription()) 
{ 
    subscription.OnUnSubscribe = channel => 
     Log.Debug("OnUnSubscribe: " + channel); 

    subscription.OnMessage = (channel, msg) => 
    { 
     if (msg == "STOP") 
     { 
      Log.Debug("UnSubscribe From All Channels..."); 
      subscription.UnSubscribeFromAllChannels(); //Un block thread. 
      return; 
     } 

     handleMessage(msg); 
    } 

    ... 

    //Unsubscribing will unblock this subscription: 
    subscription.SubscribeToChannels(QueueNames.TopicIn); //blocks thread 
} 
+0

謝謝!我想知道爲什麼這個電話被阻塞了,現在有道理。 – swestner

+0

嗨,我有一個問題,如果redis服務器重新啓動會怎麼樣,它會阻止阻塞並繼續前進?我們注意到,訂閱在redis服務器重新啓動後停止接收消息。我最初的計劃是循環訂閱,以便訂戶可以恢復丟失的連接。 – CodeLinguist

+1

@CodeLinguist該API映射接近Redis Pub/Sub命令,上面的示例不包括失敗的redis服務器實例的任何自動重試邏輯。您可以使用[ServiceStack.Redis RedisPubSubServer](https://github.com/ServiceStack/ServiceStack.Redis#managed-pubsub-server)進行託管訂閱,該託管訂閱將在失敗的連接上自動重新連接。 – mythz