2015-11-04 58 views
1

我想弄清楚從Web-API使用服務總線的最佳做法是什麼。服務總線 - 單身連接類?

我讀過像QueueClient,SubscriptionClient等重新創建對象'是錯誤的方法,所以我需要重用工廠和客戶端。

服務總線客戶對象,如Microsoft.ServiceBus.Messaging.QueueClient或Microsoft.ServiceBus.Messaging.MessageSender,通過一個MessagingFactory對象,它也提供了連接的內部管理創建。發送郵件後,您不應關閉郵件工廠或隊列,主題和訂閱客戶端,然後在發送下一條郵件時重新創建它們。關閉消息傳送工廠會刪除與服務總線服務的連接,並在重新創建工廠時建立新的連接。建立連接是一項昂貴的操作,可以通過爲多個操作重複使用相同的工廠和客戶機對象來避免。

reference

我需要執行一個特殊的類,將堅持服務總線的連接,我在想這會持有特定操作(功能類似EnqueueJobToArchiveQueue(Job job)和構造將初始化一個單例類這將是由‘具體操作功能’使用QueueClient,和的MessageFactory等」。

我的問題是,我需要關閉的對象(QueueClient.Close()),什麼時候需要關閉對象?

這裏是我的課至今:

public class ServiceBusHelper 
{ 
    private static readonly ServiceBusHelper instance = new ServiceBusHelper(); 

    private static MessagingFactory msgFactory; 

    private static NamespaceManager namespaceManager; 

    private const string jobQueueName = "job"; 

    private const string responseTopicName = "jobResult"; 

    private const string archiveQueueName = "jobArchive"; 

    private static QueueClient archiveQueue; 

    private static QueueClient jobQueue; 

    private static TopicClient responseTopic; 

    private ServiceBusHelper() 
    { 

    } 

    static ServiceBusHelper() 
    { 

      msgFactory = MessagingFactory.CreateFromConnectionString(ConfigurationManager.AppSettings["ServiceBusCS"]); 
      namespaceManager = NamespaceManager.CreateFromConnectionString(ConfigurationManager.AppSettings["ServiceBusCS"]); 

      if (!namespaceManager.QueueExists(jobQueueName)) 
      { 
       namespaceManager.CreateQueue(jobQueueName); 
      } 

      filteringQueue = QueueClient.CreateFromConnectionString(ConfigurationManager.AppSettings["ServiceBusCS"], jobQueueName); 

      if (!namespaceManager.QueueExists(archiveQueueName)) 
      { 
       namespaceManager.CreateQueue(archiveQueueName); 
      } 

      archiveQueue = QueueClient.CreateFromConnectionString(ConfigurationManager.AppSettings["ServiceBusCS"], archiveQueueName); 

      if (!namespaceManager.TopicExists(responseTopicName)) 
      { 
       namespaceManager.TopicExists(responseTopicName); 
      } 

      responseTopic = TopicClient.CreateFromConnectionString(ConfigurationManager.AppSettings["ServiceBusCS"],responseTopicName); 


    } 

    public static ServiceBusHelper Instance 
    {   
     get 
     { 
      return instance; 
     } 
    } 


    public void EnququeJobToDo(Job job, string corrId) 
    { 

     // Compose the message 
     BrokeredMessage msg = new BrokeredMessage(job); 

     msg.CorrelationId = corrId; 

     // Send the message 
     filteringQueue.Send(msg); 
    } 
} 

正如你看到的,我不關閉連接(QueueClient.Close()),我應該在哪裏關閉連接?用Dispose()實現一個IDisposable?

如果有更好的方法,我很感激你能否與我分享。

此代碼來自具有體面工作負載的Web-API(Azure Cloud Service)。

更新

我已經更新我的類Dispose()如下:

 public void Dispose() 
    { 
     if (msgFactory != null) 
     { 
      msgFactory.Close(); 
     } 

    } 
+0

當你說「關閉連接」,它是http連接? – mecek

+0

@mecek「關閉連接」指的是關閉連接對象(QueueClient,MessageFactory等)。 據我所知,有一個基於MessageFactory的TCP連接。 – Ron

+0

您應該儘可能重用連接以獲得更好的性能,關閉每個請求中的連接會損害性能,同時併發請求的數量也在增加。 – mecek

回答

2

通過服務總線SDK默認使用的基礎協議是專有SBMP(服務總線通訊協議)在關閉工廠時關閉的TCP/IP連接上工作。 如果您選擇使用TransportType = Amqp(在連接字符串中),則可以切換到AMQP協議。在這種情況下,工廠處理與總線的唯一TCP連接,QueueClient,TopicClient類(由工廠創建)實例化上述TCP連接中的會話和鏈接。會話和鏈接是用於在單個TCP連接上進行多路複用的兩個AMQP概念。 如果僅關閉QueueClient和TopicClient,則關閉操作僅會關閉相關的會話和鏈接,而不會關閉關閉工廠對象時關閉的TCP連接。 當然,我不知道SBMP如何在內部工作,因爲它是專有協議。 但是,在配置中,您可以關閉工廠和相關的隊列/主題對象。 你的問題是什麼?

+1

我的問題是我使用的方法是否安全;將保持QueueClient的單個實例處於打開狀態,並且在應用程序運行時不會關閉它? 並且有這樣的問題這樣的性能問題http://stackoverflow.com/questions/17998291/reusing-connections-in-azure-service-bus/ – Ron

+0

性能問題與開放更多的連接有關,但作爲阿布舍克拉爾(Abhishek Lal)他之前曾在微軟的Service Bus團隊工作過),他說(我也說過),你只能使用一個工廠並實例化一個或多個隊列客戶端。但是,即使只有一個隊列客戶端可以有一個始終打開的連接。這就像服務總線運作良好。 – ppatierno

+0

已完成實施IDispose並且所有工作正常。謝謝:) – Ron