Richtige Weg, um host eine *stabile* WCF-windows-MSMQ-Dienst
Ich habe eine Anwendung, die verwendet MSMQ für die asynchrone Verarbeitung von bestimmten Dingen.
Ich mit WCF setzen Sie Nachrichten auf der Warteschlange und haben einen WCF, MSMQ listener (windows-service), Nachrichten zu empfangen und mit Ihnen umzugehen.
Mein problem ist, halten diese stabil. Was ist der richtige Weg, um mit (beispielsweise) der queue-server (das ist eine separate box) hinunter? Den anderen Tag ist das passiert und der service einfach nur da saß - es werden keine Ausnahmen geworfen wurden, es gerade aufgehört Nachrichten zu empfangen.
Ich will, dass es eine Ausnahme, wenn der queue-server ging down und dann erneut versuchen, sich zu verbinden, bis es in der Lage ist.
Ich habe auch bemerkt, dass die Ausführung einer "stop" auf der service oft bewirkt, dass es hängen schon eine ganze Weile, bevor es endlich aufhört.
Jeder code, suggeriert oder Kritik wäre zu begrüßen. Natürlich habe ich Google für diese erste, aber die meisten Beispiele zeigen, die mich ziemlich viel, was ich schon habe und ich möchte mein system robuster ist als, die.
Derzeit habe ich dieses:
(Hinweis: IMyExampleServiceContract ist mein WCF-service-Vertrag und QueueHandler ist, was implementiert)
namespace xyz.MyExample.MSMQListener
{
///<summary>
///The class that handles starting and stopping of the WCF MSMQ Listener windows service.
///It will respond to start and stop commands from within the windows services administration snap-in
///It creates a WCF NetMsmqBinding that watches a particular queue for messaages defined by a contract
///in the ServiceContracts project.
///</summary>
public partial class MsmqListenerService : ServiceBase
{
///<summary>
///The WCF service host
///</summary>
private ServiceHost _serviceHost;
///<summary>
///Defines the maximum size for a WCF message
///</summary>
private const long MaxMessageSize = 1024 * 1024 * 1024; //1 gb
///<summary>
///Defines the maximum size for a WCF array
///</summary>
private const int MaxArraySize = 1024 * 1024 * 1024; //1 gb
///<summary>
///The queue name
///</summary>
private readonly string _queueName;
///<summary>
///The queue server
///</summary>
private readonly string _queueServer;
///<summary>
///Initializes a new instance of the <see cref="MsmqListenerService"/> class.
///</summary>
public MsmqListenerService()
{
InitializeComponent();
using (ConfigManager config = new ConfigManager())
{
_queueName = config.GetAppSetting("QueueName");
_queueServer = config.GetAppSetting("QueueServer");
}
}
///<summary>
///When implemented in a derived class, executes when a Start command is sent to the service by the Service Control Manager (SCM) or when the operating system starts (for a service that starts automatically). Specifies actions to take when the service starts.
///<para>
///The logic in this method creates a WCF service host (i.e. something that listens for messages) using the <see cref="IMyExampleServiceContract"/> contract.
///The WCF end point is a NetMSMQBinding to the MyExample MSMQ server/queue.
///It sets up this end point and provides a class to handle the messages received on it.
///The NetMSMQBinding is a Microsoft WCF binding that handles serialisation of data to MSMQ. It is a ms proprietary format and means that the message on the queue
///can only be read by a WCF service with the correct contract information.
///</para>
///</summary>
///<param name="args">Data passed by the start command.</param>
protected override void OnStart(string[] args)
{
try
{
Logger.Write("MyExample MSMQ listener service started.", StandardCategories.Information);
Uri serviceUri = new Uri("net.msmq://" + QueueServer + QueueName);
NetMsmqBinding serviceBinding = new NetMsmqBinding();
serviceBinding.Security.Transport.MsmqAuthenticationMode = MsmqAuthenticationMode.None;
serviceBinding.Security.Transport.MsmqProtectionLevel = System.Net.Security.ProtectionLevel.None;
serviceBinding.MaxReceivedMessageSize = MaxMessageSize;
serviceBinding.ReaderQuotas.MaxArrayLength = MaxArraySize;
//QueueHandler implements IMyExampleServiceContract
_serviceHost = new ServiceHost(typeof(QueueHandler));
_serviceHost.AddServiceEndpoint(typeof(IMyExampleServiceContract), serviceBinding, serviceUri);
_serviceHost.Open();
Logger.Write("MyExample MSMQ listener service completed OnStart method.", StandardCategories.Information);
}
catch (Exception ex)
{
ExceptionReporting.ReportException(ex, "DefaultExceptionPolicy");
throw;
}
}
///<summary>
///Gets the name of the queue to send to.
///This is retrieved from the application settings under QueueName
///</summary>
private string QueueName
{
get { return _queueName; }
}
///<summary>
///Gets the name of the queue server to send to.
///This is retrieved from the application settings under QueueServer
///</summary>
private string QueueServer
{
get { return _queueServer; }
}
///<summary>
///When implemented in a derived class, executes when a Stop command is sent to the service by the Service Control Manager (SCM). Specifies actions to take when a service stops running.
///</summary>
protected override void OnStop()
{
if (_serviceHost != null)
{
_serviceHost.Close();
_serviceHost = null;
}
}
///<summary>
///The main entry point for the application.
///</summary>
public static void Main()
{
//Code will have to be compiled in release mode to be installed as a windows service
#if (!DEBUG)
try
{
Logger.Write("Attempting to start queue listener service.", StandardCategories.Information);
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new MsmqListenerService()
};
ServiceBase.Run(ServicesToRun);
Logger.Write("Finished ServiceBase.Run of queue listener service.", StandardCategories.Information);
}
catch (Exception e)
{
ExceptionReporting.ReportException(e, "DefaultExceptionPolicy");
throw;
}
#else
//This allows us to run from within visual studio
MsmqListenerService service = new MsmqListenerService();
service.OnStart(null);
System.Threading.Thread.Sleep(System.Threading.Timeout.Infinite);
#endif
}
}
}
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ich bin mir nicht sicher, warum Ihre service-host hängen, aber ich kann definitiv denken, ein paar Dinge zu versuchen, um Sie zuverlässiger:
a) es kann senden Sie diese erfolgreich und
b), dass die Nachrichten abgeholt werden, und verarbeitet die lokale WCF health service hören auf, dass die Warteschlange. Das könnte verwendet werden, um zu erkennen, einige mögliche Fehlerzustände.
Den zugrunde liegenden WCF, MSMQ listener ist wohl eine Ausnahme zu werfen, bevor Sie jemals Ihren code. Das ist eine frustrierende situation, denn es sieht aus wie nichts passiert, und das Schlimmste Ihre Nachricht wird gelöscht. Schalten Sie WCF-tracing service in Ihrem Dienst-Konfigurations-Datei.
Wenn Sie jetzt führen Sie Ihren Dienst, es wird zu verfolgen und geben Sie weitere Details. Statt Ihre Augen zu überlasten, die durch die XML-bringen bis diese log-Datei mit dem MS-Service Trace Viewer.
Als ich dieses problem hatte war ich immer "System.ServiceModel.ProtocolException":
Obwohl WCF fügt einige Coole features, MSMQ, manchmal werden Sie Ihr Ziel erreichen, nur so leicht und mit mehr Kontrolle, wenn Sie manuell code der MSMQ-Verarbeitung.
Wenn Sie manuell Bearbeiten Sie Ihre Warteschlange werden Sie in der Lage, um zu sehen, genau was Los ist & befassen sich mit der MessageQueueExceptions, die ausgelöst werden, z.B. werden Sie in der Lage sein zu fangen MessageQueueErrorCodes wie QueueNotFound oder MachineNotFound.
Leider bedeutet dies auch, dass die Verwaltung der Warteschlange, hinzufügen von Transaktionen für die Bearbeitung, das hinzufügen eines Zeitlimits für die Warteschlange etc. All die Dinge, die WCF schön kümmert sich für Sie.
Den wichtigsten Vorteil der Verwendung von WCF ist, dass Sie dann verwenden können, WURDE ein Exemplar einer web-Anwendung, anstatt einen ständig Laufenden Windows-Dienst. Wenn Sie nicht mit dieser profitieren dann sehe ich nicht wirklich einen nutzen bringt WCF - es ist eben Abstraktion, Weg eine Menge von dem, was Sie brauchen, um zu berühren und zu sehen.
Nur als kleiner Hinweis; vielleicht könnten Sie überprüfen ob der server verfügbar ist, wenn Sie setzen die Nachrichten in der Warteschlange? Wenn der server verfügbar ist, um die Nachrichten in der Warteschlange, dann wird der Hörer in der Lage sein, sofort zu verarbeiten.