每天用心去做,用行动去改变一些人的观念,或许是他们的态度,或许是他们的意识.
这样对我来说都是对这个世界的点点改变,我也对此乐此不疲
今天再次深入了MSMQ,记录如下吧
MSMQ局域网通信配置
MSMQ在不启用http桥时,或在局域网环境下我们可以使用无安全性的配置,
<security mode="None">
<transport msmqAuthenticationMode="None" msmqProtectionLevel="None" />
<message clientCredentialType="None" />
</security>
当然在安全考虑下我们还是需要域管理器或windows安全的,这个不是本节讨论的问题,略过
MSMQ调试清除队列
1.重写ServiceHost类的方法OnClosing
2.在使用。net的条件编译 [Conditional("BEGUG")]
3.调用purge()的方法
MSMQ事务回放机制
注意MSMQ特性,不能为其设置[TransactionFlow(TransactionFlowOption.Allowed)]的任何属性,在这里都是无用的。。
如果要使用事务就只能够使用操作行为的事务回放机制进行事务传递,
参与事务回放
1.单向契约
2.[OperationBehavior(TransactionScopeRequired = true)]
3.客户端开启事务
或者你也可以选择建立独立事务,当然该事务不是DTC
MSMQ非事务队列配置
在binding节点下 配置Durable,ExactlyOnce,这样你的队列将不具备消息可靠性,也是一个临时队列
MSMQ事务性客户端,与之前事务用法相似,略过..
MSMQ非事务性客户端,需要将事务属性调整为TransactionScopeOption.Suppress
MSMQ单例队列服务
1.需要配置 [ServiceContract(SessionMode=SessionMode.NotAllowed)]
2.需要配置 [ServiceBehavior(InstanceContextMode=InstanceContextMode.Single,ReleaseServiceInstanceOnTransactionComplete = false)]
ReleaseServiceInstanceOnTransactionComplete = false是为了使用易失型资源管理器
MSMQ会话型队列服务
MSMQ的会话状态可不是之前那样,而是一种会话图的方式交互。
要注意SessionMode比为Required,是因为调用一个会话型队列终结点的代理时,在客户端就必须要有一个环境事务的前提,所以才如此配置。
在会话型事务队列中我们还要注意,释放资源的顺序,先是事务范围对象,再是代理对象,否则会导致事务提前结束,那样我们的信息就不会被放入到队列中去
一个会话型队列服务还要被配置为所有操作中使用事务也就是TransactionScopeRequired = true,如果无法做到那么所有事务都将回滚,并且除了最后一个方法之外的所有方法只能为TransactionAutoComplete=false。这也是。net 3.5上存在的漏洞,4.0中已更正(实验证实)
MSMQ并发,与并发限流类型,略过
MSMQ传输故障 :超时与过期,安全性不匹配,事务不匹配,事务不匹配,网络问题,机器崩溃,清除,超出配额
DLQ的处理(Deat-Letter Queue)
由于上述的传输故障原因产生,导致了死信队列的出现
死信队列处理方案 timeToLive
DLQ服务的使用
1.配置DLQ模式为Custom
2.例外配置DLQ节点实现对当前服务的调用
3.利用操作上下获取DLQ发生的原因,重要属性 MoveCount,DeliveryStatus,DeliveryFailure
有害消息
消息系统在处理不断回放失败或ACK,NACK的消息时会降低系统的性能,对于这样的情况我们称之为有害消息。
处理方案:
1.ReceiveRetryCount 重试次数
2.MaxRetryCycles 最大循环批次
3.RetryCycleDelay 批次间重试时间间隔
4.ReceiveErrorHanding 最后一次失败处理 Fault保守处理,Drop丢弃,Reject主动拒绝,Move转交第三方处理。
HTTP桥的使用(MSMQ穿越好戏)
1 契约
[ServiceContract]
public interface IMyContract
{
[OperationContract(IsOneWay = true)]
void MyMethod();
}
[ServiceContract]
public interface IMyContractHttpBridge
{
[OperationContract]
[TransactionFlow(TransactionFlowOption.Mandatory)]
void MyMethod();
}
2.服务
public class MyService : IMyContract
{
// MSMQ传入
[OperationBehavior(TransactionScopeRequired=true)]
public void MyMethod()
{
throw new NotImplementedException();
}
}
public class MyServiceHttpBridge : IMyContractHttpBridge
{
// HTTP传入
[OperationBehavior(TransactionScopeRequired=true)]
public void MyMethod()
{
MyContractClient proxy = new MyContractClient();
// MSMQ传出
proxy.MyMethod();
proxy.Close();
}
}
3.配置文件
<system.serviceModel>
<services>
<service name="Hosting.MyService">
<endpoint address="net.msmq://localhost/private/MyServiceQueue" binding="netMsmqBinding" contract="Hosting.IMyContract"></endpoint>
</service>
</services>
<services>
<service name="Hosting.MyServiceHttpBridge">
<endpoint address="http://localhost/MyServiceHttpBridge" binding="wsHttpBinding" contract="Hosting.IMyContractHttpBridge" bindingConfiguration="ReliableTransactedHTTP"></endpoint>
</service>
</services>
<bindings>
<wsHttpBinding>
<binding name="ReliableTransactedHTTP" transactionFlow="true">
<reliableSession enabled="true" />
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="net.msmq://localhost/private/MyServiceQueue" binding="netMsmqBinding" contract="Hosting.IMyContract"></endpoint>
</client>
</system.serviceModel>
4.客户端实现
MyContractClient proxy = new MyContractClient();
// MSMQ传出
proxy.MyMethod();
proxy.Close();
class MyClientHttpBridge : IMyContract
{
[OperationBehavior(TransactionScopeRequired=true)]
public void MyMethod()
{
MyContractHttpBridgeClient proxy = new MyContractHttpBridgeClient();
// HTTP传出
proxy.MyMethod();
proxy.Close();
}
}