我們在使用 ASP 程序時常常會遇到這些情況:某個進程花費了過長的時間而導致在客戶端過期、訪問者已經放棄了對你的網站的訪問而離開去了別的網站、或你的服務器上阻塞了大量的死隊列時,系統出現 "Server is too busy" 錯誤信息。
當你在設計網站的過程中碰到這些問題時,一個有效的解決辦法就是使用 Microsoft Message Queue (MSMQ) 來結束這些進程,讓網站恢復正常!
到底 MSMQ 是個什么樣的東西呢?我們下面作一下了解:
一、 Microsoft Message Queue 的基本介紹:
MSMQ ( 代號又叫 "Falcon") 是運行在 Windows NT 的服務 , 它提供運用程序之間的異步通訊。你可以在 NT4 Option Pack 中找到它。 MSMQ 的基本概念非常的簡單:它可以被看成是運用程序之間的 email :一個消息被打包到一個特定類型的容器中,并把這個消息保存到一個用與特別作用的隊列中直到收信者接受該消息為止。這些隊列能夠確保 MSMQ 的傳送,而不管當前網絡連接的狀況如何。
象所有的電子郵件一樣, MSMQ 消息有一個發送者和一個接收者 , 其中的接收者應該能夠訪問隊列。一個單一隊列中的一個單獨消息,它擁有多個接受者例如 respinder 。而消息的發送者通常是 Web Server(IIS) 。
MSMQ 也能夠和其他消息系統進行通訊。例如: Sun Solaris, HP-UNIX,OS/2, VMS, AS/400 平臺。像其他的 BackOffice 服務一樣, MSMQ 有一個 COM API ( mqoa.dll ) 提供給開發者開發程序。其中最常用的三個類為: MSMQQueueInfo, MSMQQueue, MSMQMessage 。
( 1 )、 MSQMQueueInfo
MSMQQueueInfo 允許你新建,打開,刪除隊列中的消息 . 要和隊列建立聯系首先需要設置 PathName ,這是一個命名隊列的屬性,它告訴 MSQM 是哪臺機器上的隊列。 < % Dim objQueueInfo Dim objQueue Set objQueueInfo=Server.CreateObject("MSMQ.MSMQQueueInfo") objQueue.PathName = ".\MyQu" Set objQueue = objQueueInfo.Open(MQ_SEND_ACCESS, MQ_DENY_NONE) %>
上面的代碼打開一個叫 MyQueue 的本地隊列。如果隊列在另外一臺服務器上,代碼應該是這樣的:
objQueue.PathName = "SomeOtherComputer\MyQu"
打開隊列中有兩個參數: Access 和 ShareMode 。 Access 表示將要對隊列執行什么操作。一般有三個操作:
MQ_PEEK_ACCESS (32), MQ_RECEIVE_ACCESS (1), MQ_SEND_ACCESS (2) 。
MQ_PEEK_ACCESS 用來在特定的隊列中查找消息。但對該消息不進行操作。
MQ_RECEIVE_ACCESS 用來在讀取隊列中的消息后刪除它。
MQ_SEND_ACCESS 用來在隊列中發送消息 , 但不接收消息。
需要注意的是在使用打開操作后返回了一個 MSMQQueue 對象。下面是一個典型的新建和刪除操作例子: < % Dim objQueue Set objQueue = Server.CreateObject("MSMQ.MSMQQueueInfo") objQueue.PathName = ".\MyQu" objQueue.Create %>
< % Dim objQueue Set objQueue = Server.CreateObject("MSMQ.MSMQQueueInfo") objQueue.PathName = ".\MyQu" objQueue.Delete %>
( 2 )、 MSMQQueue
MSMQQueue 類用來描述一個在 MSMQ 服務中打開的隊列。該類提供了一個用來在指針隊列中的消息進行循環的功能。你不能夠打開一個使用了 MSMQQueue 類的隊列要這么干只能夠使用 MSQMQueueInfo (見上例),雖然許多 ASP 運用程序通常使用 MSMQ 來發消息,但是很多時候也需要 ASP 來顯示這個消息的具體內容。
獲取消息的方式有兩種:同步方式,異步方式,但是 ASP 只能夠使用同步方式。這是因為 ASP 不能夠在服務端申明一個 WithEvents 變量。
下面先舉一個異步方式使用 MSMQ 的例子(僅 VB 中) Option Explicit Dim m_objQueueInfo As New MSMQQueueInfo Dim m_objQueue As MSMQQueue Dim WithEvents m_objMSMQEvent As MSMQEvent
Private Sub Form_Load() m_objQueueInfo.PathName = ".\MyQu" m_objQueueInfo.Label = "My Sample Queue" On Error Resume Next m_objQueueInfo.Create On Error GoTo 0 Set m_objQueue = m_objQueueInfo.Open(MQ_RECEIVE_ACCESS, MQ_DENY_NONE)
Set m_objMSMQEvent = New MSMQEvent m_objQueue.EnableNotification m_objMSMQEvent, MQMSG_CURRENT, 1000 End Sub
Private Sub m_objMSMQEvent_Arrived(ByVal Queue As Object, ByVal Cursor As Long) Dim m_objMessage As MSMQMessage Set m_objMessage = Queue.PeekCurrent MsgBox "Message Received: " & m_objMessage.Label m_objQueue.EnableNotification m_objMSMQEvent, MQMSG_NEXT, 10000 End Sub
Private Sub m_objMSMQEvent_ArrivedError(ByVal Queue As Object, ByVal ErrorCode As Long, ByVal Cursor As Long) MsgBox "Error accorded: " & ErrorCode End Sub
這段代碼首先建立一個隊列(如果它還不存在的話)。然后 m_objMSMQEvent 對象通過調用 EnableNotification 連接到 MSMQQueue 對象。一旦連接到 MSMQEvent 對象 , 接下來需做的僅僅是完成 Arrived 和 Arrived_Error ( 可選的 ) 事件。 Arrived 事件當一個新的消息到達隊列時將被觸發該事件返回兩個指針 , 一個是指向隊列中應該從來開始讀消息的位置,另外一個是當前的位置。如果發生錯誤,將觸發 ArrivedError 事件當同步獲取消息時,會一直等到消息可獲取或則超時時程序才會不被掛起。代碼如下: Public Sub DisplayMessages() Dim objQueueInfo As New MSMQQueueInfo Dim objQueue As MSMQQueue Dim objMessage As MSMQMessage objQueueInfo.PathName = ".\MyQu" objQueueInfo.Label = "My Sample Queue"
On Error Resume Next objQueueInfo.Create On Error GoTo 0 Set objQueue = objQueueInfo.Open(MQ_RECEIVE_ACCESS, MQ_DENY_NONE) Do While True Set objMessage = objQueue.Peek(, , 1000) If objMessage Is Nothing Then Exit Do MsgBox "Message: " & objMessage.Label Loop MsgBox "No more new messages." objQueue.Close Set objMessage = Nothing Set objQueue = Nothing Set objQueueInfo = Nothing End Sub
( 3 )、 MSMQMessage
MSMQMessage 類支持隊列中消息的所有屬性。 MSMQ 消息有兩個方法和繁多的屬性。其中兩個最主要的屬性是: Body 和 LabeL 。最主要的方法有 Send 。有兩種方法來獲取消息: opening , peeking 。當使用 opening 方式后,該消息將會被刪除掉;當使用 peeking 方式后,該消息仍然保存在隊列中直到它過期。它們的返回值都是指向該消息的指針。下例的代碼將打開一個消息,并顯示其 Body 和 Label Private Sub LookForMessage() Dim objQInfo As New MSMQQueueInfo Dim objQReceive As MSMQQueue Dim objMessage As MSMQMessage objQInfo.PathName = ".\test" Set objQReceive = objQInfo.Open(MQ_RECEIVE_ACCESS, MQ_DENY_NONE) Set objMessage = objQReceive.Receive(, , , 1000) If Not objMessage Is Nothing Then MsgBox objMessage.Label & " - " & objMessage.Body Else Msgbox "Nothing in the queue" End If objQReceive.Close Set objQInfo = Nothing Set objQReceive = Nothing Set objMessage = Nothing End Sub
這段代碼打開一個隊列并在該隊列中查找消息,使用 Receive 方法,主要是設置一個 1000 微秒的超時 , 它告訴 MSMQ1000 微秒后停止查找設置一個非常段的超時的功能主要是用來檢查是否存在消息而不是等候一個消息。也就是說如果你知識想看看是否有消息可以使用該方法。如果無消息,返回的指針為空 (If Not objMessage Is Nothing) 。下面是發送一個消息的代碼: < % Dim objQInfo Dim objQSend Dim objMessage Set objQInfo = Server.CreateObject("MSMQ.MSMQQueueInfo") objQInfo.PathName = ".\test" Set objQSend = objQInfo.Open(MQ_SEND_ACCESS, MQ_DENY_NONE) Set objMessage = Server.CreateObject("MSMQ.MSMQMessage") objMessage.Label = "This is the label." objMessage.Body = "This is the body." objMessage.Send objQSend objQSend.Close Set objQInfo = Nothing Set objQSend = Nothing Set objMessage = Nothing %>
對于 MSMQ 的有關基本知識我們已做了舉例介紹,下面將就它的具體運用進行的了解及探討!
|