解決|進程|問題 在ASP中使用MSMQ
當ASP程式因為某個進程花費了過長的時間而導致在用戶端到期時,
當訪問者已經放棄了對你的網站的訪問而離開去了別的網站時。
或則你的伺服器上阻塞了大量的死隊列時,錯誤"Server is too busy"
發生了。
當你在設計網站的過程中碰到這些問題時,一個解決辦法就是使用
Microsoft Message Queue (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.
MSQMQueueInfo
MSMQQueueInfo允許你建立,開啟,刪除隊列中的訊息.要和隊列建立聯絡首先需要設定
PathName,這是一個命名隊列的屬性,它告訴MSQM是哪台機器上的隊列。
<%
Dim objQueueInfo
Dim objQueue
Set objQueueInfo=Server.CreateObject("MSMQ.MSMQQueueInfo")
objQueue.PathName = ".\MyQueue"
Set objQueue = objQueueInfo.Open(MQ_SEND_ACCESS, MQ_DENY_NONE)
%>
上面的代碼開啟一個叫MyQueue的本地隊列.如果隊列在另外一台伺服器上,代碼應該是這樣的
objQueue.PathName = "SomeOtherComputer\MyQueue"
開啟隊列中有兩個參數:Access和ShareMode. Access表示將要對隊列執行什麼操作。
一般有三個操作:
MQ_PEEK_ACCESS (32), MQ_RECEIVE_ACCESS (1), MQ_SEND_ACCESS (2).
MQ_PEEK_ACCESS用來在特定的隊列中尋找訊息。但對該訊息不進行操作。
MQ_RECEIVE_ACCESS 用來在讀取隊列中的訊息後刪除它。
MQ_SEND_ACCESS is 用來在隊列中發送訊息,但不接收訊息.
注意的是使用開啟操作後返回了一個MSMQQueue對象.
下面是一個典型的建立和刪除操作:
<%
Dim objQueue
Set objQueue = Server.CreateObject("MSMQ.MSMQQueueInfo")
objQueue.PathName = ".\MyQueue"
objQueue.Create
%>
<%
Dim objQueue
Set objQueue = Server.CreateObject("MSMQ.MSMQQueueInfo")
objQueue.PathName = ".\MyQueue"
objQueue.Delete
%>
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 = ".\MyQueue"
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事件
當同步擷取訊息時,會一直等到訊息可擷取或則逾時時程式才會不被掛起。
代碼如下: