在ASP中使用MSMQ
当ASP 程序因为某个进程花费了过长的时间而导致在客户端过期时,当访问者已经放弃了对你的网
站的访问而离开去了别的网站时。或则你的服务器上阻塞了大量的死队列时,错误"Server is too bus
y"发生了。
当你在设计网站的过程中碰到这些问题时,一个解决办法就是使用Microsoft Message Queue (MSM
Q)来结束这些进程。
Microsoft Message Queue 的基本介绍:
MSMQ (代号又叫"Falcon") 是运行在 Windows NT的服务,它提供运用程序之间的异步通讯。你可以
在NT4 Option Pack中找到它。MSMQ的基本概念非常的简单:它可以被看成是运用程序之间的email。一
个消息被打包到一个特定类型的容器中,并把这个消息保存到一个用与特别作用的队列中直到收信者接
受该消息为止。这些队列能够确保MSMQ的传送,而不管当前网络连接的状况如何。象所有的电子邮件一
样,MSMQ消息有一个发送者和一个接收者,其中的接收者应该能够访问队列。一个单一队列中的一个单
独消息,它拥有多个接受者例如respinder。而消息的发送者通常是Web Server(IIS) 。
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对象通过调用EnableNo
tification连接到MSMQQueue对象.一旦连接到MSMQEvent对象,接下来需要做的仅仅是完成Arrived和rri
ved_Error (可选的)事件.Arrived 事件当一个新的消息到达队列时将被触发该事件返回两个指针,一个
是指向队列中应该从来开始读消息的位置,另外一个是当前的位置。如果发生错误,将触发ArrivedErr
or事件当同步获取消息时,会一直等到消息可获取或则超时时程序才会不被挂起。
代码如下:
Public Sub DisplayMessages()
Dim objQueueInfo As New MSMQQueueInfo
Dim objQueue As MSMQQueue
Dim objMessage As MSMQMessage
objQueueInfo.PathName = ".\MyQueue"
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
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(, , , 100)
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方法,主要是
设置一个100微秒的超时,它告诉MSMQ100微秒后停止查找
设置一个非常段的超时的功能主要是用来检查是否存在消息而不是等候一个消息。
也就是说如果你知识想看看是否有消息可以使用该方法。
如果无消息,返回的指针为空 (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的基本知识就介绍这些,下面将就它的运用少少的探讨一下:
下面是如何处理ADODB.Recordset的一个例子:
Public Sub SendRecordsetInMessage()
Dim objQInfo As New MSMQ.MSMQQueueInfo
Dim objQSend As MSMQ.MSMQQueue
Dim objMessage As New MSMQ.MSMQMessage
Dim objRS As New ADOR.Recordset
Dim a As New MSMQQueue
With objRS
.CursorLocation = adUseClient
.Fields.Append "FN", adVarChar, 25
.Fields.Append "LN", adVarChar, 25
.Open
.AddNew
.Fields("FN") = "Chris"
.Fields("LN") = "Blexrud"
.Update
.AddNew
.Fields("FN") = "Shayna"
.Fields("LN") = "Blexrud"
.Update
End With
objQInfo.PathName = ".\test"
Set objQSend = objQInfo.Open(MQ_SEND_ACCESS, MQ_DENY_NONE)
objMessage.Label = "Recordset State!!!!"
objMessage.Body = objRS
objMessage.Send objQSend
objQSend.Close
Set objQInfo = Nothing
Set objQSend = Nothing
Set objMessage = Nothing
Set objRS = Nothing
End Sub