I have a sample NServiceBus application to test the waters.. All is going well, sending and handling is working correctly.
I have deliberately thrown an exception within a certain message handler to see what happens - but nothing does. The exception is logged correctly to the console, yet the message is pulled off the queue and NOT placed in the error queue as I'd expect. Also, the 5 times retry didn't occur either. Is this correct behaviour?
Also, the queue was created correctly at startup when first specified.
the config and bootstrap code for the server (where the handler resides are below)
config:
<MsmqTransportConfig
InputQueue="SiteServer1"
NumberOfWorkerThreads="1"
MaxRetries="5"
ErrorQueue="SiteServer1Errors"
/>
program.cs:
var bus = NServiceBus.Configure.With()
.Log4Net()
.CastleWindsorBuilder(container)
.XmlSerializer()
.MsmqTransport()
.UnicastBus()
.LoadMessageHandlers()
.CreateBus()
.Start();
Am I missing anything here?
I modified the bootstrapper code to include
.IsTransactional(true)
on the bus config and now it is working! It seems that non-transactional messages are disposable. Makes sense!
Are you running Windows Server 2008? If so you will find an event log in the event viewer, under the Application event logs -> windows -> MSMQ - End2End. This will record every action taken by the MSMQ subsystem on your machine.
I am guessing that NSB has tried to send the message to the error queue. However, what is really hapenning is that the MSMQ subsystem on your machine has consumed the message, but not been able to deliver it to the error queue for some reason.
I would look in the MSMQ log for an idea of what is going on.
Related
I'm running an NServiceBus endpoint on an Azure Workerrole. I send all diagnostics to table storage at the moment. I was getting messages in my DLQ, and I couldn't figure out why I wasn't getting any exceptions logged in my table storage.
It turns out that NSB logs the exceptions as INFO, which is why I couldn't easily spot them in between all the actual verbose logging.
In my case, a command handler's dependencies couldn't be resolved so Autofac throws an exception. I totally get why the exception is thrown, I just don't understand why they're logged as INFO. The message ends up in my DLQ, and I only have a INFO-trace to understand why.
Is there a reason why exceptions are handled this way in NSB?
NServiceBus is not logging container issue as an error because it's happening during an attempt to process a message. First Level Retry and Second Level Retry will be attempted. When SLR is executed, it will log a WARN about the retry. Ultimately, a message will fail processing and an ERROR message will be logged. NSB and Autofac sample can be used to reproduce this.
When endpoint is running with a scaled out role and MadDeliveryCount is not big enough to accommodate all the role instances and retry count that each instance would hold, this will result in DeliveryCount reaching it's max while NServiceBus endpoint instance still thinks it has attempts before sending message to an error queue and logging an error. Similar to the question here I'd recommend to increase MaxDeliveryCount.
There is an open NServiceBus issue to have a native support for SLR counter. You can add your voice to the issue. The next version of NServiceBus (V6) will be logging message id along with the exception so that you at least could correlate between message in DLQ and log file.
I have a rather simple Pub/sub setup which works fine on our developer machines but when I deploy to our test serveres it throws this error for all messages:
System.NullReferenceException: Object reference not set to an instance of an object.
at NServiceBus.Unicast.UnicastBus.HandleTransportMessage(IBuilder childBuilder, TransportMessage msg) in c:\BuildAgent\work\nsb.master_6\src\unicast\NServiceBus.Unicast\UnicastBus.cs:line 1328
at NServiceBus.Unicast.UnicastBus.TransportMessageReceived(Object sender, TransportMessageReceivedEventArgs e) in c:\BuildAgent\work\nsb.master_6\src\unicast\NServiceBus.Unicast\UnicastBus.cs:line 1247
at System.EventHandler`1.Invoke(Object sender, TEventArgs e)
at NServiceBus.Unicast.Transport.Transactional.TransactionalTransport.OnTransportMessageReceived(TransportMessage msg) in c:\BuildAgent\work\nsb.master_6\src\impl\unicast\transport\NServiceBus.Unicast.Transport.Transactional\TransactionalTransport.cs:line 480
We allready have other SendOnly, Distributors and workers running on the same servers, so msmq etc. should be installed corretly. This is the first time however we are using Pub/Sub on these servers.
If i use the exact same binaries and config on a developer machine it runs smoothly, but not on the servers which are 2008R2, Powershell V3.
We are using a fluent configuration for the subscriber:
return NServiceBus.Configure.With()
.DefineEndpointName(queuePrefix)
.Log4Net(_serviceBusLog.Build())
.StructureMapBuilder()
.JsonSerializer()
.License(ConfigTable.GetConfigString(ConfigTableKeys.NServiceBus, "License"))
.MsmqTransport()
.IsTransactional(true)
.RunTimeoutManagerWithInMemoryPersistence()
.EnablePerformanceCounters()
.UnicastBus()
.CreateBus()
.Start(() => NServiceBus.Configure.Instance.ForInstallationOn<NServiceBus.Installation.Environments.Windows>().Install());
We also have our own UnicastBus config which scans for message handlers (they're message types) and then automatically creates the endpoint mappings. This was my first concern so I disabled it and used the app.config way of setting up endpoints, but the error still occurs.
Note the error occours for every single message.
Note we are running version 3.3.5 of NSB.
Im still travering the server settings as I believe there must be some difference that makes it tick but i have not found it yet.
Anyone has any recommendations as for what to look for?
Kind regards
It appears that I have found the error.
After testing a raw simple console Pub/Sub on the server I added a try catch in the handler and caught... My own exception....
Im embrassed.
But it appears that the exception is not forwarded correctly to the log in NSB and i was therefore completely thrown of from the real problem.
I do not know if this is something that is fixed in later versions of NSB, but i hope so.
Until then Im using my own try catch logic to add a custom log entry.
Kind regards.
Perhaps I'm missing something here and this question is maybe the same as this one so sorry for any duplication.
I have an MVC4 site that quite happily Sends() commands to my NServiceBus server. I now want the same MVC site to be able to subscribe to IEvents Publish()ed from the same NServiceBus server. But I just can't get it to work.
Messages are being published from the server and are showing in MSMQ but I can't get the MVC site to pick them up.
Is this possible with NServiceBus 3.3.5? And if so, how do I have to set up my MVC site to make it work?
Thanks in advance!
Edit: Here's the config I have in the MVC app:
Configure.With()
.Log4Net()
.StructureMapBuilder()
.MsmqTransport()
.IsTransactional(false)
.PurgeOnStartup(false)
.UnicastBus()
.LoadMessageHandlers()
.ImpersonateSender(false)
.JsonSerializer()
.CreateBus()
.Start(() => Configure.Instance.ForInstallationOn<NServiceBus.Installation.Environments.Windows>().Install());
I don't have an EndpointConfig class that implements the IConfigureThisEndpoint or and AsA_ interfaces. I've tried adding one but it never gets called and I can't work out what the host would be or how to start the NServiceBus host application from the web app. Or even what context the host would run under if the code sits inside IIS (if that makes sense!).
My guess is you're missing the .LoadMessageHandlers() line in your fluent config after .UnicastBus() - that's the most common error that leads to self-hosted applications not processing messages sent to them.
If that's not the case, add your fluent config block to your question and we'll take a look.
Edit: After fluent config posted
My next guess is that you're declaring your serializer too late. The .UnicastBus() step is one of the last stops before "Let's start this thing!" I'm thinking perhaps by the time you've hit this point, the config has made the assumption you're going with the default XmlSerializer. Could you try moving the serializer line to right after .StructureMapBuilder() and see if that works better?
If that doesn't work I might consider using the .DefaultBuilder() momentarily just to rule out an problem with your IoC container.
In regards to your other comments, a self-hosted bus will never have an EndpointConfig. That's a pointer for endpoints hosted by the NServiceBus.Host.exe only.
I also suppose it's not completely obvious where you're calling this fluent config from. This code needs to be called once when the webapp is started up - usually from the application start method in the Global.asax. Because the webapp is in control, there's no automatic assembly scanning to find and wire up your NServiceBus pipeline like in the NServiceBus Host.
I have a queue named log on a remote machine. When I call that queue locally, I specify a custom dead-letter queue by modifying my NetMsmqBinding:
_binding.DeadLetterQueue = DeadLetterQueue.Custom;
_binding.CustomDeadLetterQueue = new Uri(
"net.msmq://localhost/private/Services/Logging/LogDeadLetterService.svc");
This works fine; when I force my message to fail to get to its destination, it appears in this queue.
Now, I have a service hosted in IIS/WAS to read the dead-letter queue. It it hosted in a site called Services, at Services/Logging/LogDeadLetterService.svc. Here's the service in my config:
<service name="Me.Logging.Service.LoggingDeadLetterService">
<endpoint binding="netMsmqBinding"
bindingNamespace="http://me.logging/services/2012/11"
contract="Me.Logging.Service.Shared.Service.Contracts.ILog" />
</service>
And here's my activation:
<add relativeAddress="LogDeadLetterService.svc"
service="Me.Logging.Service.LoggingDeadLetterService" />
My actual service is basically this:
[ServiceBehavior(AddressFilterMode = AddressFilterMode.Any, // Pick up any messages, regardless of To address.
InstanceContextMode = InstanceContextMode.Single, // Singleton instance of this class.
ConcurrencyMode = ConcurrencyMode.Multiple, // Multiple callers at a time.
Namespace = "http://me.logging/services/2012/11")]
public class LoggingDeadLetterService : ILog
{
public void LogApplication(ApplicationLog entry)
{
LogToEventLog(entry);
}
}
My queue is transactional and authenticated. I have net.msmq included as enabled protocols both on the Services site and on the Logging application, and I added a net.msmq binding to the Services site. If I have the binding information as appdev.me.com, I get the following error when browsing to http://appdev.me.com/Logging/LogDeadLetterService.svc (appdev.me.com is setup in my HOSTS file):
An error occurred while opening the queue:Access is denied. (-1072824283, 0xc00e0025).
If I have the binding information as localhost, I get the following error:
An error occurred while opening the queue:The queue does not exist or you do not have sufficient permissions to perform the operation. (-1072824317, 0xc00e0003).
No matter which way I have it set up, the service isn't picking up the dead letter, as it's still in the queue and not in my event log.
Now, I realize that both of these reference a permissions issue. However, in the interest of getting the code part of this tested before figuring out the authentication piece, I have given Full Control to everyone I could think of - to include Everyone, Authenticated Users, NETWORK SERVICE, IIS_USERS, ANONYMOUS LOGON, and myself. (The app pool is running as me.)
Any help as to how to get my service to be able to pull from this queue would be phenomenal. Thanks!
EDIT: According to this MSDN blog entry, 0xC00E0003 corresponds to MQ_ERROR_QUEUE_NOT_FOUND, and 0xc00e0025 corresponds to MQ_ERROR_ACCESS_DENIED, so it looks like I want to have the binding information as appdev.me.com. However, that still doesn't resolve the apparent permissions issue occurring.
EDIT2: It works if I host the service in a console app and provide the following endpoint:
<endpoint address="net.msmq://localhost/private/Services/Logging/LogDeadLetterService.svc"
binding="netMsmqBinding"
bindingNamespace="http://me.logging/services/2012/11"
contract="Me.Logging.Service.Shared.Service.Contracts.ILog" />
So what's going on differently in the console app than is going on in IIS? I'm pretty confident, due to EDIT above, that I'm hitting the queue. So why can't I get into it?
EDIT3: Changed Services/Logging/LogDeadLetterService.svc to Logging/LogDeadLetterService.svc per the advice given here, but no change.
//
[Bonus question: Do I need to handle poison messages in my dead letter queue?]
So, three things needed to be changed:
The binding does have to be localhost.
The queue has to be named Logging/LogDeadLetterService.svc to be found - it's the application and the service, not the site, application, and service.
I had something messed up with the application pool - I have no idea what it was, but using a different app pool worked, so I backed out all of my service-related changes and then recreated everything, and it works.
Well, that was a lot of banging my head against my desk for something as simple as "don't mess up your app pool."
I am using MsmqSubscriptionStorage in a pub/sub scenario and the first message is lost when the subscriptions has not been stored. If I watch the debug messages, while running in the GenericHost, I see that all the subscriptions are setup but the first message is never sent to the subscribers. If more messages are sent, then they are successfully sent to the subscribers (as indicated in the logs)
I am using version 2.0.0.0.
Here is the bus configuration I'm using.
var bus = Configure.With(
new List<Assembly>
{
typeof(Configure).Assembly,
typeof(IBus).Assembly
})
.DefaultBuilder()
.Log4Net()
.XmlSerializer()
.MsmqTransport()
.IsTransactional(true)
.PurgeOnStartup(false)
.UnicastBus()
.ImpersonateSender(false)
.LoadMessageHandlers()
.MsmqSubscriptionStorage()
.CreateBus()
.Start();
I'm answering my own post so no one sees this issue and draws the conclusion that there is something wrong with NServiceBus. This was a GCE - (Gross Conceptual Error) on my part. My hosting environment was deferring resolution of a static reference to the Bus. Changing the initialization of my process to setup the static Bus reference at start up solve the problem.
If you Publish before any subscription has been registered those messages won't have a destination and will be ignored. You may want to look into the DB subscription storage to have something less transient.