我有一個服務,使用WCF響應MSMQ上的消息。當信息格式良好時,它正常運行,我們很高興。當消息針對不同的服務,並且操作不同時,消息停留在隊列中,我們獲取日誌條目,我們修復,我們很高興。MSMQ通過WCF吞嚥嚴重格式化的消息,沒有錯誤,沒有警告
但是,當消息具有正確的操作,但包含無法由服務器反序列化的XML元素時,消息從隊列中消失,我們不會獲取日誌條目,並且我們幾乎不知道發生了什麼。我們不開心。
我試着添加一個IErrorHandler。我試着添加一個Faulted事件處理程序。我唯一能做的就是使用內置於WCF中的診斷日誌記錄。有沒有什麼辦法可以用我自己的記錄器或錯誤處理程序來響應這樣的代碼錯誤?
我的隊列碰巧是事務性的,但它似乎對這個問題沒有任何區別。這發生在MSMQ 3.0版本,Windows Server 2003的
這個源代碼表現出的問題上:
class Program : IErrorHandler {
private static Uri QueueUri = new Uri("net.msmq://localhost/private/server_queue");
static void Main(string[] args) {
Program program = new Program();
if (args.Length > 0) {
if (args[0] == "server") {
program.Server();
} else if (args[0] == "bad") {
program.BadClient();
}
} else {
program.Client();
}
}
public void BadClient() {
using (var client = new BadServiceClient(QueueUri)) {
client.Do(new [] {new BadStuff { BadMessage = "hi" }});
}
}
public void Client() {
using (var client = new ServiceClient(QueueUri)) {
client.Do(new [] {new Stuff {Message = "hi"}});
}
}
public void Server() {
var serviceHost = new ServiceHost(typeof(Service));
serviceHost.AddServiceEndpoint(typeof (IService), new NetMsmqBinding(), QueueUri);
serviceHost.Open();
serviceHost.Faulted += serviceHost_Faulted;
serviceHost.UnknownMessageReceived += new EventHandler<UnknownMessageReceivedEventArgs>(serviceHost_UnknownMessageReceived);
foreach (ChannelDispatcher dispatcher in serviceHost.ChannelDispatchers) {
dispatcher.ErrorHandlers.Add(this);
}
Console.WriteLine("press the any key");
Console.ReadKey(true);
}
void serviceHost_UnknownMessageReceived(object sender, UnknownMessageReceivedEventArgs e) {
Console.WriteLine("unknown message: {0}", e);
}
private static void serviceHost_Faulted(object sender, EventArgs e) {
Console.WriteLine("fault: {0}", e);
}
public void ProvideFault(Exception error, MessageVersion version, ref Message fault) {
Console.WriteLine("handling error: {0}", error);
}
public bool HandleError(Exception error) {
Console.WriteLine("handling error: {0}", error);
return true;
}
}
[ServiceContract]
public interface IService {
[OperationContract(IsOneWay = true, Action = "do")]
void Do(IEnumerable<Stuff> stuffs);
}
[ServiceContract]
public interface IBadService {
[OperationContract(IsOneWay = true, Action = "do")]
void Do(IEnumerable<BadStuff> stuffs);
}
class ServiceClient : ClientBase<IService>, IService {
public ServiceClient(Uri uri) : base(new NetMsmqBinding(), new EndpointAddress(uri)) {}
public void Do(IEnumerable<Stuff> stuffs) {
Channel.Do(stuffs);
}
}
class BadServiceClient : ClientBase<IBadService>, IBadService {
public BadServiceClient(Uri uri) : base(new NetMsmqBinding(), new EndpointAddress(uri)) {}
public void Do(IEnumerable<BadStuff> stuffs) {
Channel.Do(stuffs);
}
}
[ServiceBehavior(TransactionTimeout = "00:5:00", InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Single)]
class Service : IService {
[OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]
public void Do(IEnumerable<Stuff> stuffs) {
foreach (var stuff in stuffs) {
Console.WriteLine("service doing stuff, message: " + stuff.Message);
}
}
}
[DataContract]
public class Stuff {
[DataMember]
public string Message;
}
[DataContract]
public class BadStuff : Stuff {
[DataMember]
public string BadMessage;
}
可以打開的每個應用程序隊列的系統隊列很少。其中之一是DeadLetterQueue和PoisonQueue。這些隊列包含失敗的消息。 – 2010-10-02 09:38:27
不幸的是,在死信隊列或中毒消息隊列中找不到消息。我在Windows Server 2003上使用MSMQ 3.0。 – 2010-10-04 10:13:01