我对MSMQ很新.我们有一个使用MSMQ的关键系统,由于资源不足,它无法启动.似乎MSMQ有能力.我试图清除消息(甚至删除不必要的队列),但在清除时收到以下错误:
无法删除队列中的所有邮件.错误:拒绝访问消息队列系统.
我有什么选择?有没有办法在服务关闭时删除队列?
我们正在使用Queue来完成少数WCF服务.我们对使用私有MSMQ的WCF服务使用NetMSMQ绑定.系统在我们的QA环境中正常运行.我不确定私有或公共队列之间是否存在任何真正的区别.客户端应用程序在单独的机器上仍然能够访问其他盒子上的WCF服务的专用队列.我不确定这是否是正确的做法.私人和公共MSMQ之间是否存在安全相关的差异?有人可以说明何时使用私人或公共MSMQ.
我有这种情况:一个客户端将消息发送到msmq队列实例,并且有3个进程侦听此队列.我希望能够让这些实例中的每一个都选择不同的消息并进行处理.
我知道这是队列的常见使用场景,我已经使用MSMQ,.NET和C#为此工作了代码.
但是我想知道msmq是否是我最好的选择 - 文档明确指出MSMQ是用于"一对一"通信,这意味着不应该有多个监听器.
这让我感到疑惑,我正在为我的用例做正确的解决方案吗?或者反过来说,我是否必须为每个侦听器创建一个队列并在工作流的前一部分中分发消息?
将非常感谢在此类场景中演示MSMQ用法的工作示例的链接.
谢谢
我正在运行NServiceBus 3.0.0 rc2但是当我启动应用程序(作为本地管理员)而没有预先创建MSMQ时,它出错了:
队列不存在或您没有足够的权限来执行操作.
使用NServiceBus 2.6没有发生这种情况.
以下是我的配置:
var bus = Configure.With()
.Log4Net()
.NinjectBuilder()
.XmlSerializer()
.DefiningCommandsAs(t => typeof(ICommand).IsAssignableFrom(t))
.DefiningEventsAs(t => typeof(IEvent).IsAssignableFrom(t))
.DefiningMessagesAs(t => typeof(IMessage).IsAssignableFrom(t))
.MsmqTransport()
.DefineEndpointName("subscriber.input")
.IsTransactional(true)
.PurgeOnStartup(false)
.UnicastBus()
.LoadMessageHandlers()
.ImpersonateSender(false)
.CreateBus()
.Start();
Run Code Online (Sandbox Code Playgroud)
和
<configuration>
<configSections>
<section name="MsmqTransportConfig" type="NServiceBus.Config.MsmqTransportConfig, NServiceBus.Core" />
<section name="UnicastBusConfig" type="NServiceBus.Config.UnicastBusConfig, NServiceBus.Core" />
</configSections>
<MsmqTransportConfig ErrorQueue="error" NumberOfWorkerThreads="1" MaxRetries="5" />
<UnicastBusConfig>
<MessageEndpointMappings>
<add Messages="MyEvents" Endpoint="publisher.input" />
</MessageEndpointMappings>
</UnicastBusConfig>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
</startup>
</configuration>
Run Code Online (Sandbox Code Playgroud)
我可以看到一个配置扩展方法来禁用自动创建队列但没有启用它.
如果我预先创建队列,它工作正常.
我刚才的原始问题是MSMQ Slow Queue Reading,但是我已经提出了这个问题,现在我觉得我知道这个问题更清楚了.
我的代码(实际上是我正在使用的开源库的一部分)看起来像这样:
queue.Receive(TimeSpan.FromSeconds(10), MessageQueueTransactionType.Automatic);
Run Code Online (Sandbox Code Playgroud)
哪个使用Messaging.MessageQueue.Receive函数和队列是MessageQueue.问题如下.
将使用指定的超时(10秒)调用上面的代码行.该Receive(...)函数是一个阻塞函数,并且应该阻塞,直到消息到达队列,此时它将返回.如果在超时之前没有收到任何消息,它将在超时时返回.如果在调用函数时消息在队列中,它将立即返回该消息.
然而,正在发生的Receive(...)是正在调用函数,看到队列中没有消息,因此等待新消息进入.当新消息进入时(超时之前),它没有检测到这条新消息并继续等待.最终会超时超时,此时代码会继续并Receive(...)再次调用,然后它会获取消息并对其进行处理.
现在,此问题仅在数天/周后发生.通过删除和重新创建队列,我可以再次正常工作.它发生在不同的计算机和不同的队列上.因此,似乎某些东西正在积累,直到它打破了该Receive(...)函数使用的触发/通知能力.
我检查了很多不同的东西,一切看起来都很正常,与正常工作的队列没什么不同.有足够的磁盘空间(13gig免费)和RAM(从我可以告诉的1GB大约350MB空闲).我检查了所有看起来与其他队列相同的注册表项,并且性能监视器没有显示任何异常.我也运行了TMQ工具,看不出任何明显的错误.
我在所有机器上都使用Windows XP,它们都安装了Service Pack 3.我没有向队列发送大量消息,最多每2秒发送一次,但通常不会那么频繁.这些消息也很小,远不及4MB的限制.
我刚刚注意到的唯一事情是C:\ WINDOWS\system32\msmq\storage中的p0000001.mq和r0000067.mq文件都是4,096KB,但是在其他计算机上它们的大小也是当前没有遇到问题的.问题不会立即发生在计算机上的每个队列中,因为我可以在计算机上重新创建1个问题队列,而其他队列仍然会遇到问题.
我对MSMQ不是很有经验,所以如果你发布可能要检查的东西,请解释如何检查它们或在哪里可以找到你所谈论的更多细节.
目前的情况是:
所以我有大量的计算机/队列来比较和测试.
我试图通过从不同的命名空间向不同的端点发送消息来配置我的NServiceBus配置中的消息端点映射.
因此,我在web.config中配置了以下内容:
<MessageEndpointMappings>
<add Messages="Company.Messages.Accounts" Endpoint="ServiceInput" />
<add Messages="Company.Messages.Payments" Endpoint="ServiceInput" />
<add Messages="Company.Messages.Cancellations" Endpoint="ServiceInput" />
<add Messages="Company.Messages.Notifications" Endpoint="ServiceInput" />
</MessageEndpointMappings>
Run Code Online (Sandbox Code Playgroud)
但是,当我的应用程序启动时,我收到以下异常:
Spring.Objects.PropertyAccessExceptionsException:PropertyAccessExceptionsException(1个错误); 嵌套的PropertyAccessExceptions是:[Spring.Core.TypeMismatchException:无法将类型[System.Collections.Hashtable]的属性值转换为属性'MessageOwners'所需的类型[System.Collections.IDictionary].,内部异常:System.ArgumentException:问题加载消息程序集:Company.Messages.Payments ---> System.IO.FileNotFoundException:无法加载文件或程序集"Company.Messages.Payments"或其依赖项之一.该系统找不到指定的文件.文件名称:'Company.Messages.Payments'
我觉得有趣的是它似乎找到了Company.Messages.Accounts但在第二个配置的行上失败了.我想也许它不喜欢让它们全部转到同一个端点,但更改此配置以使它们进入不同的端点并没有改变我收到的错误消息.
我究竟做错了什么?是不是可以通过命名空间来分割消息(我所见过的只是按类型和汇编)?
谢谢,史蒂夫
我有一个分布式系统,其中将有1个SQL Server,1-n处理服务器和1-n数据供应商(网络中的硬件设备).提供的数据需要在进入关系数据库结构之前进行处理 - 由处理服务器执行(作为Windows服务 - .net代码来解析数据,处理数据并将其插入关系结构中.)
处理潜力加载而不是减慢数据供应商的速度,我想实现一个队列,但我不确定我是否想要将MSMQ服务器的复杂性添加到混合中.是否有一个很好的MSMQ替代方案,例如使用DB(平面表)作为队列?.NET是否为DB队列提供了任何开箱即用的支持,还是有另一种可靠的排队选项?
谢谢
编辑:(11月29日,晚上11:30)
听起来像SQL Service Broker(SSB)可能会这样做.
http://www.netframeworkdev.com/windows-communication-foundation/service-broker-vs-msmq-as-reliable-queueing-mechanism-63981.shtml
编辑:(11月30日,上午7:45)
发现另一个非常有用的链接:
http://social.msdn.microsoft.com/Forums/en-US/sqlservicebroker/thread/52687510-0852-44f3-bfcd-83610d1c1b9a
我也在研究将要提供的数据的最大/最小尺寸.在他们的头顶,有谁知道MSMQ和/或SSB容纳的最大尺寸?
MSMQ:4MB消息大小
SSB:2GB消息大小
编辑:(30 nov,8; 15am)
MSMQ和SSB之间的比较:
消息队列的良好策略?
我一直在尝试使用WCF进行MSMQ,但我似乎无法让它正常工作.通过使用WCF和服务引用,我得到了客户端(它向队列发送消息).执行此操作的代码或多或少是这样的:
static void Main(string[] args)
{
var client = new MsmqServiceReference.MsmqContractClient();
client.SendMessage("TEST");
client.Close();
Console.ReadKey();
}
Run Code Online (Sandbox Code Playgroud)
其中MsmqContractClient是我添加服务引用时由visual studio生成的代理.app.config中的端点指向msmqueue:
<client>
<endpoint
address="net.msmq://localhost/private/MsmqService/MsmqService.svc"
binding="netMsmqBinding"
bindingConfiguration="MsmqBindingNonTransactionalNoSecurity"
contract="MsmqServiceReference.IMsmqContract" name="MsmqService" />
</client>
Run Code Online (Sandbox Code Playgroud)
这样可以将消息发布到队列中.
现在我试图让服务真正起作用,但我一直收到这个错误:
绑定验证失败,因为绑定的MsmqAuthenticationMode属性设置为WindowsDomain但安装了MSMQ且禁用了Active Directory集成.无法打开通道工厂或服务主机.
我尝试过的事情是:
为每个人提供对队列的完全访问权限(包括匿名登录)
使用以下命令配置应用程序以使用配置文件中的特定绑定:
<bindings>
<netMsmqBinding>
<binding name="MsmqBindingNonTransactionalNoSecurity"
deadLetterQueue="Custom"
exactlyOnce="false">
<security mode="None" />
</binding>
</netMsmqBinding>
</bindings>
Run Code Online (Sandbox Code Playgroud)我尝试在我自己的帐户和管理员帐户下运行IIS(7)中的应用程序池
让我感到困惑的是,它一直试图说服我,我正在尝试使用WindowsDomain身份验证来运行它.我声明我不想在安全模式设置为none的情况下这样做,对吗?
我的应用程序目前只是一个webforms asp.net网站,其中添加了WCF服务.
如果有人能够至少指出我正确的方向,我将非常感激,因为我已经花了太多时间在这上面.
看起来似乎忽略或覆盖了配置.完整的错误消息:
WebHost failed to process a request.
Sender Information: System.ServiceModel.Activation.HostedHttpRequestAsyncResult/63721755
Exception: System.ServiceModel.ServiceActivationException: The service '/MsmqService/MsmqService.svc' cannot be activated due to an exception during compilation. The exception message is: Binding validation …Run Code Online (Sandbox Code Playgroud) 我开发了一个WCF服务,它作为Windows服务托管并公开了一个MSMQ端点.
我在SERVER1上有客户端应用程序,在SERVER2上有MSMQ和WCF服务.
当SERVER1/ClientApp尝试将消息推送到SERVER2 MSMQ时,我得到以下错误:
System.TypeInitializationException: The type initializer for 'System.ServiceModel.Channels.Msmq' threw an exception. ---> System.DllNotFoundException: Unable to load DLL 'mqrt.dll': The specified module could not be found. (Exception from HRESULT: 0x8007007E)
at System.ServiceModel.Channels.UnsafeNativeMethods.MQGetPrivateComputerInformation(String computerName, IntPtr properties)
at System.ServiceModel.Channels.MsmqQueue.GetMsmqInformation(Version& version, Boolean& activeDirectoryEnabled)
at System.ServiceModel.Channels.Msmq..cctor()
--- End of inner exception stack trace ---
at System.ServiceModel.Channels.Msmq.EnterXPSendLock(Boolean& lockHeld, ProtectionLevel protectionLevel)
at System.ServiceModel.Channels.MsmqOutputChannel.OnSend(Message message, TimeSpan timeout)
at System.ServiceModel.Channels.OutputChannel.Send(Message message, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
at …Run Code Online (Sandbox Code Playgroud) 我试图找到C#服务器应用程序的瓶颈在哪里未充分利用CPU.我认为这可能是由于磁盘I/O性能不佳而与应用程序本身无关,但我无法从这个假设中得出一个事实.
应用程序从本地MSMQ队列中读取消息,对每条消息进行一些处理,并在处理完消息后,将响应消息发送到另一个本地MSMQ队列.
我正在使用异步循环从队列中读取消息,尽可能快地将它们出列并使用Task.Run调度它们进行处理以启动每个消息的处理(并且不要等待此Task.Run ..只是附加一个延续只记错了记录错误).每个消息被同时处理,即在处理下一个消息之前不需要等待消息被完全处理.
在处理消息的最后,我使用MessageQueue的Send方法(不知何故异步但不是真的因为它必须等待磁盘写入才能返回-see System.Messaging - 为什么MessageQueue不提供异步版本的Send).
对于基准测试,我在队列中排队100K消息(100K消息的总大小约为100MB)然后我启动程序.在我的两台个人计算机上(一台SSD HD和另一台SATA2 HD,i7 CPU四核-8逻辑处理器)我在程序生命周期内达到~95%的CPU使用率(将100K消息出列,处理它们和发送回复).消息尽可能快地出列,尽可能快地处理(这里涉及的CPU),然后对发送到不同本地队列的每个消息进行响应.
现在在运行非HT双核CPU的虚拟机上(不知道什么是底层磁盘,但似乎远不如地雷......在基准测试期间,使用Perfmon我可以看到avg disk sec/write arround 10-15 ms on this虚拟机,而在我的个人计算机上大约2ms)当我运行相同的工作台时,我只能达到~55%的CPU(当我在机器上运行相同的工作台而不向队列发送响应消息时我达到~90%CPU ).
我真的不明白这里有什么问题.似乎很清楚,向队列发送消息是问题并且减慢了程序的全局处理(以及要处理的消息的队列化),但为什么会考虑我使用Task.Run来启动每个出列消息的处理并最终响应发送,我不希望CPU未被充分利用.除非当一个线程正在发送消息时它阻止其他线程在等待返回(磁盘写入)时在同一个核心上运行,在这种情况下,考虑到延迟远远高于我的个人计算机,它可能是有意义的,但是一个线程等待I/O不应该阻止其他线程运行.
我真的想了解为什么我没有达到这台机器至少95%的CPU使用率.我盲目地说这是由于较差的磁盘I/O性能,但我仍然不明白为什么它会导致CPU利用不足,因为我正在使用Task.Run同时运行处理.它也可能是一些与磁盘完全无关的系统问题,但考虑到MessageQueue.Send似乎是问题,并且此方法最终将消息写入内存映射文件+磁盘,我看不出性能问题可能来自何处除了磁盘.
当然,由于程序最大限度地提高了我自己计算机上的CPU使用率,因此确实存在系统性能问题,但我需要找到VM系统上的瓶颈,以及为什么它会影响我的应用程序的并发/速度.
任何的想法 ?
msmq ×10
c# ×5
.net ×4
nservicebus ×2
wcf ×2
async-await ×1
dll ×1
iis ×1
messaging ×1
performance ×1
private ×1
sql-server ×1
timeout ×1