Wir verarbeiten Nachrichten über eine Vielzahl von Diensten (eine Nachricht wird wahrscheinlich 9 Dienste berühren, bevor sie erledigt sind, von denen jeder eine bestimmte E / A-bezogene Funktion ausführt). Im Moment haben wir eine Kombination aus Worst-Case (XML-Datenvertragsserialisierung) und Best-Case (In-Memory-MSMQ) für die Leistung.
Die Art der Nachricht bedeutet, dass unsere serialisierten Daten ungefähr 12-15 Kilobyte lang sind und wir ungefähr 4 Millionen Nachrichten pro Woche verarbeiten. Permanente Nachrichten in MSMQ waren für uns zu langsam, und mit zunehmenden Datenmengen spüren wir den Druck durch MSMQs speicherabgebildete Dateien. Der Server hat 16 GB Arbeitsspeicher und wächst, nur für Warteschlangen. Die Leistung leidet auch, wenn die Speichernutzung hoch ist und der Computer mit dem Auslagern beginnt. Wir führen bereits die MSMQ-Selbstbereinigung durch.
Ich habe das Gefühl, dass wir hier einen Teil falsch machen. Ich habe versucht, RavenDB zu verwenden, um die Nachrichten beizubehalten und nur einen Bezeichner in die Warteschlange zu stellen, aber die Leistung dort war sehr langsam (bestenfalls 1000 Nachrichten pro Minute). Ich bin mir nicht sicher, ob dies auf die Verwendung der Entwicklungsversion zurückzuführen ist oder nicht, aber wir brauchen definitiv einen höheren Durchsatz [1]. Das Konzept funktionierte theoretisch sehr gut, aber die Leistung war nicht der Aufgabe gewachsen.
Das Verwendungsmuster besteht aus einem Dienst, der als Router fungiert und alle Lesevorgänge durchführt. Die anderen Dienste hängen Informationen basierend auf dem Hook ihres Drittanbieters an und leiten sie an den Router weiter. Die meisten Objekte werden 9-12 Mal berührt, obwohl ungefähr 10% gezwungen sind, in diesem System eine Weile herumzuschleifen, bis die 3. Partei angemessen reagiert. Die Dienste berücksichtigen dies derzeit und weisen ein angemessenes Schlafverhalten auf, da wir aus diesem Grund das Prioritätsfeld der Nachricht verwenden.
Meine Frage ist also, was ist ein idealer Stapel für die Nachrichtenübermittlung zwischen Computern mit diskreten LANs in einer C # / Windows-Umgebung? Normalerweise würde ich mit BinaryFormatter anstelle der XML-Serialisierung beginnen, aber das ist ein Hasenloch, wenn es besser ist, die Serialisierung in einen Dokumentenspeicher auszulagern. Daher meine Frage.
[1]: Je schneller wir Nachrichten verarbeiten, desto mehr Geld verdienen wir. Wir haben empirisch bewiesen, dass es weniger wahrscheinlich ist, dass wir mit der Verarbeitung einer Nachricht später in der Woche Geld verdienen. Während die Leistung von "1000 pro Minute" sehr schnell klingt, brauchen wir diese Zahl wirklich ab 10k / Minute. Nur weil ich Nummern in Nachrichten pro Woche gebe, heißt das nicht, dass wir eine ganze Woche Zeit haben, um diese Nachrichten zu verarbeiten.
=============== Bearbeiten:
Zusätzliche Information
Basierend auf den Kommentaren werde ich einige Klarstellungen hinzufügen:
Ich bin nicht sicher, ob Serialisierung unser Engpass ist. Ich habe die Anwendung einem Benchmarking unterzogen, und obwohl die Serialisierung im Heatgraph angezeigt wird, ist sie nur für etwa 2,5 bis 3% der CPU-Auslastung des Dienstes verantwortlich.
Ich bin hauptsächlich besorgt über die Beständigkeit unserer Nachrichten und den möglichen Missbrauch von MSMQ. Wir verwenden nicht-transaktionale, nicht persistente Nachrichten, um die Leistung in der Warteschlange aufrechtzuerhalten, und ich hätte wirklich gerne persistente Nachrichten, damit sie einen Neustart überstehen.
Das Hinzufügen von mehr RAM ist eine Notlösung. Die Maschine hat bereits 4 GB -> 16 GB RAM verloren und es wird immer schwieriger, sie herunterzufahren, um weitere hinzuzufügen.
Aufgrund des Stern-Routing-Musters der Anwendung ändert sich die Hälfte der Zeit, in der ein Objekt abgelegt und dann in eine Warteschlange verschoben wird, überhaupt nicht. Dies bietet sich erneut an (IMO), um es in einer Art Schlüsselwertspeicher an einer anderen Stelle zu speichern und einfach Nachrichtenkennungen zu übergeben.
Das Stern-Routing-Muster ist ein wesentlicher Bestandteil der Anwendung und ändert sich nicht. Wir können es nicht auf die Hundertfünfzigste Anwendung anwenden, da jedes Teil auf dem Weg asynchron (abrufend) arbeitet und wir das Wiederholungsverhalten an einem Ort zentralisieren möchten.
Die Anwendungslogik ist in C # geschrieben, die Objekte sind unveränderliche POCOs, die Zielbereitstellungsumgebung ist Windows Server 2012, und wir dürfen zusätzliche Computer hochfahren, wenn eine bestimmte Software nur unter Linux unterstützt wird.
Meine Ziele sind die Beibehaltung des aktuellen Durchsatzes bei gleichzeitiger Reduzierung des Speicherbedarfs und Erhöhung der Fehlertoleranz bei minimalem Kapitalaufwand.