MSMQ 大文件发送

在默认情况下msmq 3.0(windows xp ,windows 2003)最大单个消息(Message size)大小4M;(包括正文和全部指定属性的消息的大小不能超过 4 MB。 来自windows 2003帮助文件的说明。)
    4M的限制对于一些普通的应用来说已经足够,而且作为消息传递,报文交换,我们推荐的是不要使用超过1M大小的报文。这样可以很好的利用网络带宽,和提高系统的处理性能。
    但对于一些特别少数的应用仍然存在大报文的需求,而msmq作为一个消息中间件有很多优势。所以我们还是要想办法使用他,或是扩展他的功能。
    下面就我在网上和通过一些网友的帮助整理了一些突破这个4M限制方法。
    
    1.通过修改注册表(regedit)HKLM\SOFTWARE\Microsoft\MSMQ\Parameters\ 加添一个MaxMessageSize DWORD值大小默认4M(0x00400000)最大16M(x00F00000),通过试验发现最大只能是16M左右,如果在改大,再调用程序的是否会报错

using (System.Messaging.MessageQueue mq = new System.Messaging.MessageQueue(".\\private$\\mq3"))
            
{
                System.Messaging.Message msg 
= new System.Messaging.Message();
                msg.BodyStream 
= new FileStream("e:\\CodeSmithProfessional-40.msi", FileMode.Open);
                mq.Send(msg);
            }

    2.消息分段发送,通过Message.ID,Message.CorrelationId关联,分割多个固定大小的消息.

private  void SendFile(string fileName, string queuePath)
        
{
            
int i;
            
int count = 0;
            
int msgNumber = 0;
            
int chunkSize = 4194000;
            
//Open an existing queue
            MessageQueue queue = new MessageQueue(queuePath);
            System.Messaging.Message msg 
= new System.Messaging.Message();
            MessageQueueTransaction t 
= new MessageQueueTransaction();
            t.Begin();
            
try
            
{
                
//Open the file for reading
                using (FileStream fs = File.OpenRead(fileName))
                
{
                    
// while there are bytes
                    while ((i = fs.ReadByte()) != -1)
                    
{
                        
// if count has reached size, send message
                        if (count >= chunkSize)
                        
{
                            msgNumber
++;
                            msg.AppSpecific 
= msgNumber;
                            
//Send the messsage
                            queue.Send(msg,t);
                            
string nextMsgId = msg.Id;
                            count 
= 0;
                            
//Create a new message
                            msg = new System.Messaging.Message();
                            msg.CorrelationId 
= nextMsgId;
                        }

                        msg.BodyStream.WriteByte((
byte)i);
                        count
++;            // from the original file
                    }

                    msgNumber
++;
                    msg.AppSpecific 
= msgNumber;
                    
//Send the last message
                    queue.Send(msg,  t);
                    t.Commit();
                }

            }

            
catch (Exception ex)
            
{
                Console.WriteLine(ex);
            }

            
finally
            
{
                
//release queue resources
                queue.Close();
            }

        }


private void ReceiveFile(string fileName, string queuePath)
        
{
            
byte[] data;
            
int length;

            
//Open an existing queue
            MessageQueue queue = new MessageQueue(queuePath);
            
try
            
{
                
//Open file for writing
                using (FileStream fs = File.OpenWrite(fileName))
                
{
                    
//Receive the first message
                    System.Messaging.Message msg = queue.Receive(new TimeSpan(0001));
                    
while (msg != null)
                    
{
                        
//Get the Lenght of the message body stream
                        length = Convert.ToInt32(msg.BodyStream.Length);
                        
//Create a buffer to hold the stream in memory
                        data = new byte[length];
                        
//Read the body stream
                        msg.BodyStream.Read(data, 0, length);
                        
//Write the buffer into the file
                        fs.Write(data, 0, length);
                        
//Receive following message
                        msg = queue.Receive(new TimeSpan(0001));
                    }

                }

            }

            
catch (Exception ex)
            
{
                Console.WriteLine(ex);
            }

            
finally
            
{
                
//release queue resources
                queue.Close();
            }

        }

    3.使用BizTalk MSMQ Adapter,支持消息分段(segmentationSupport=true),前提队列必须是事务性(transactional=true),MaxMessageSize最大可以4G,试验证实一个通过passthru方式处理一个200M的文件,处理占用大量cpu和IO外,BizTalk MessageBox数据也更大400M(200M日志文件,200M数据文件)。注意:通过方法2实现的分段,在用BizTalk接收会存在问题,BizTalk不会帮组合成一个大文件处理。

    4.使用BizTalk提供的一个LargeMessage api可以以编成方式实现对大报文的处理,处理方式和方法3类似。并且可以实现和BizTalk兼容。

Code
posted @ 2010-03-21 15:29  边缘凉风  阅读(905)  评论(0编辑  收藏  举报