2013-02-04 18 views
7

Ich suche nach einer Eingabe, wie ein Windows-Dienst, der derzeit in meinem Unternehmen ausgeführt wird, zu skalieren. Wir sind mit .NET 4.0 (kann und wird zu einem bestimmten Zeitpunkt in der Zukunft 4.5 aufgerüstet werden) und läuft dies auf Windows Server 2012Skalieren von Windows-Diensten

Über den Service
Die Aufgabe des Service für neue Zeilen abzufragen, ist in eine Logging-Tabelle (Wir arbeiten mit einer Oracle-Datenbank), verarbeiten die Informationen, erstellen und/oder aktualisieren eine Reihe von Zeilen in 5 anderen Tabellen (nennen wir sie Tracking-Tabellen), aktualisieren Sie die Logging-Tabelle und wiederholen.

Die Protokolltabelle enthält große Mengen an XML (bis zu 20 MB pro Zeile), die in den anderen 5 Verfolgungstabellen ausgewählt und gespeichert werden müssen. Neue Zeilen werden die ganze Zeit mit der maximalen Rate von 500.000 Zeilen pro Stunde hinzugefügt.
Der Datenverkehr der Verfolgungstabellen ist viel höher und reicht von 90.000 neuen Zeilen in der kleinsten bis zu Millionen von Zeilen in der größten Tabelle pro Stunde. Ganz zu schweigen davon, dass es auch Update-Operationen für diese Tabellen gibt.

über die verarbeiteten Daten
Ich fühle mich dieses Bit wichtig ist es, eine Lösung für die Suche basierend auf, wie diese Objekte werden gruppiert und verarbeitet werden. Die Datenstruktur sieht wie folgt aus:

public class Report 
{ 
    public long Id { get; set; } 
    public DateTime CreateTime { get; set; } 
    public Guid MessageId { get; set; } 
    public string XmlData { get; set; } 
} 

public class Message 
{ 
    public Guid Id { get; set; } 
} 
  • Bericht ist die Protokolldaten Ich brauche
  • auszuwählen und Verfahren für jede Nachricht dort im Durchschnitt 5 Reports sind. Dies kann in einigen Fällen zwischen 1 bis 100 variieren.
  • Nachricht hat eine Reihe anderer Sammlungen und andere Beziehungen, aber sie sind für die Frage irrelevant.

Heute ist der Windows Service haben wir kaum die Last auf einem Server mit 16 Kernen verwaltet (Ich erinnere mich nicht die vollen Spezifikationen, aber es ist sicher diese Maschine zu sagen, ist ein Tier). Ich habe die Aufgabe, eine Möglichkeit zu finden, mehr Maschinen zu skalieren und hinzuzufügen, die all diese Daten verarbeiten und die anderen Instanzen nicht stören.

Derzeit erhält jede Nachricht ihren eigenen Thread und behandelt die relevanten Berichte. Wir verarbeiten Berichte in Stapeln, gruppiert nach ihrer MessageId, um die Anzahl der DB-Abfragen bei der Verarbeitung der Daten auf ein Minimum zu reduzieren.

Einschränkungen

  • In dieser Phase darf ich neu schreiben dieser Service von Grund auf unter Verwendung eines beliebigen Architektur ich für richtig halten.
  • Sollte eine Instanz abstürzen, müssen die anderen Instanzen in der Lage sein, dort aufzugreifen, wo die abgestürzte Version übrig geblieben ist. Es können keine Daten verloren gehen.
  • Diese Verarbeitung muss so realitätsnah wie möglich von den Berichten sein, die in die Datenbank eingefügt werden.

Ich suche für jede Eingabe oder Ratschläge, wie man ein solches Projekt zu bauen. Ich nehme an, dass die Dienste zustandslos sein müssen, oder gibt es eine Möglichkeit, Caches für alle Instanzen irgendwie zu synchronisieren? Wie sollte ich alle Instanzen koordinieren und sicherstellen, dass sie nicht dieselben Daten verarbeiten?Wie kann ich die Last gleichmäßig zwischen ihnen verteilen? Und natürlich, wie man mit einer Instanz umgeht, die abstürzt und ihre Arbeit nicht abschließt?

EDIT
entfernt irrelevante Informationen

+0

Das * klingt * wie ein ETL-Prozess. Haben Sie darüber nachgedacht, etwas wie SQL Server Integration Services (SSIS) zu betrachten und Pakete zu schreiben, die so geplant werden, dass sie regelmäßig ausgeführt werden? –

+0

Wir verwenden Oracle und die höheren UPS wollen leider kein Wort über SQL Server hören. – Artless

+0

Ich dachte nur den SSIS-Teil davon und nicht die Datenbank-Engine :) Alternativen wären etwas wie Pentaho Data Integration (http://www.pentaho.com/explore/pentaho-data-integration/) oder Talend etl analytics (http://www.talend.com/solutions/etl-analytics) –

Antwort

0

Ich löste dies durch alle Codierung diese Skalierbarkeit und Redundanz Material auf meiner eigenen. Ich werde erklären, was ich getan habe und wie ich es gemacht habe, sollte jemals jemand das brauchen.

Ich habe in jedem Fall ein paar Prozesse erstellt, um den Überblick zu behalten und zu wissen, welche Datensätze die jeweilige Instanz verarbeiten kann. Beim Start würde sich die Instanz in der Datenbank (falls dies nicht bereits der Fall ist) in einer Tabelle namens Instances registrieren. Diese Tabelle hat die folgenden Spalten:

Id     Number 
MachineName  Varchar2 
LastActive   Timestamp 
IsMaster   Number(1) 

Nach der Registrierung und eine Zeile in dieser Tabelle zu schaffen, wenn die Instanz des MachineName nicht gefunden wurde, geht die Instanz jede Sekunde in einem separaten Thread diese Tabelle Pingen, die Aktualisierung seiner LastActive Spalte. Dann wählt es alle Zeilen aus dieser Tabelle aus und stellt sicher, dass die Master Instance (mehr dazu später) noch am Leben ist - was bedeutet, dass es LastActive Zeit in den letzten 10 Sekunden ist. Wenn die Master-Instanz nicht mehr reagiert, übernimmt sie die Kontrolle und stellt sich selbst als Master ein. In der nächsten Iteration wird es sicherstellen, dass es nur einen Master gibt (falls eine andere Instanz gleichzeitig die Kontrolle übernimmt), und wenn nicht, wird sie der Instanz mit dem niedrigsten Id nachgeben.

Was ist die Master-Instanz?
Aufgabe des Dienstes ist es, eine Logging-Tabelle zu scannen und diese Daten zu verarbeiten, so dass die Leute sie leicht filtern und lesen können. Ich habe dies in meiner Frage nicht erwähnt, aber es könnte hier relevant sein. Wir haben eine Reihe von ESB-Servern, die pro Anfrage mehrere Datensätze in die Logging-Tabelle schreiben, und die Aufgabe meines Dienstes ist es, diese in nahezu Echtzeit zu verfolgen. Da sie ihre Protokolle asynchron schreiben, könnte ich möglicherweise einen finished processing request A vor started processing request A Eintrag im Protokoll erhalten. Also habe ich einen Code, der diese Datensätze sortiert und sicherstellt, dass mein Dienst die Daten in der richtigen Reihenfolge verarbeitet. Da ich diesen Dienst skalieren musste, kann nur eine Instanz diese Logik ausführen, um viele unnötige DB-Abfragen und möglicherweise wahnsinnige Fehler zu vermeiden.
Dies ist, wo die Master Instance hereinkommt. Nur es führt diese Sortierlogik aus und speichert vorübergehend die Protokolldatensatz-IDs in einer anderen Tabelle namens ReportAssignment. Aufgabe dieser Tabelle ist es, zu verfolgen, welche Datensätze von wem verarbeitet wurden. Sobald die Verarbeitung abgeschlossen ist, wird der Datensatz gelöscht. Die Tabelle sieht folgendermaßen aus:

RecordId  Number 
InstanceId  Number Nullable 

Die Master-Instanz sortiert die Protokolleinträge und fügt hier ihre IDs ein. Alle meine Dienstinstanzen überprüfen diese Tabelle in 1-Sekunden-Intervallen auf neue Datensätze, die von niemandem verarbeitet werden oder die von einer inaktiven Instanz verarbeitet werden, und die [record's Id] % [number of isnstances] == [index of current instance in a sorted array of all the active instances] (die während des Pinging-Prozesses erfasst wurden). Die Abfrage sieht etwas wie folgt aus:

SELECT * FROM ReportAssignment 
WHERE (InstanceId IS NULL OR InstanceId NOT IN (1, 2, 3)) // 1,2,3 are the active instances 
AND RecordId % 3 == 0 // 0 is the index of the current instance in the list of active instances 

Warum muss ich dies tun?

  • Die beiden anderen Instanzen für RecordId % 3 == 1 und RecordId % 3 == 2 würde abfragen.
  • RecordId % [instanceCount] == [indexOfCurrentInstance] stellt sicher, dass die Datensätze gleichmäßig auf alle Instanzen verteilt sind.
  • InstanceId NOT IN (1,2,3) ermöglicht es den Instanzen, Datensätze zu übernehmen, die von einer abstürzenden Instanz verarbeitet wurden, und verarbeiten die Datensätze bereits aktiver Instanzen nicht, wenn eine neue Instanz hinzugefügt wird.

Sobald eine Instanz Abfragen für diese Datensätze, wird es ein Update-Befehl, die Einstellung der InstanceId auf seine eigene und fragen Sie die Logging-Tabelle für Datensätze mit diesen IDs auszuführen. Wenn die Verarbeitung abgeschlossen ist, löscht sie die Datensätze von ReportAssignment.

Insgesamt bin ich sehr zufrieden damit. Es skaliert gut, stellt sicher, dass keine Daten verloren gehen, sollte die Instanz ausfallen, und es gab fast keine Änderungen an dem bestehenden Code, den wir haben.

6

Für Ihre Arbeitsaufgaben, ist Windows Workflow wahrscheinlich die schnellste Mittel, um Ihren Dienst Refactoring.

Windows Workflow Foundation @ MSDN

Die nützlichste, was Sie aus WF bekommen ist Workflow-Persistenz, wo ein richtig konzipiert Workflow von einem Persist Punkt wieder aufgenommen werden kann, sollte etwas von dem letzten Punkt des Workflows geschehen, an dem es Gerettet.

Workflow Persistence @ MSDN

dies die Fähigkeit für einen Workflow umfasst von einem anderen Prozess sollte andere Verfahren Absturz gestellt werden, während die Workflow-Verarbeitung. Der Fortsetzungsvorgang muss nicht auf demselben Computer ausgeführt werden, wenn Sie den freigegebenen Workflowspeicher verwenden. Beachten Sie, dass alle wiederherstellbaren Workflows die Verwendung des Workflowspeichers erfordern.

Für die Arbeitsverteilung haben Sie ein paar Optionen.

  1. Ein Service-Nachrichten mit Host-basierten Last über Workflow-Aufruf Ausgleich mit WCF-Endpunkten über die WorkflowService Klasse kombiniert zu produzieren. Beachten Sie, dass Sie den Designmodus-Editor hier möglicherweise verwenden möchten, um Eingabemethoden zu erstellen, anstatt Receive und die entsprechenden SendReply-Handler manuell einzurichten (diese werden WCF-Methoden zugeordnet). Sie würden den Dienst wahrscheinlich für jede Nachricht aufrufen und vielleicht auch den Dienst für jeden Bericht aufrufen. Beachten Sie, dass die Eigenschaft CanCreateInstance hier wichtig ist. Jeder damit verbundene Aufruf erstellt eine laufende Instanz, die unabhängig ausgeführt wird.
    ~
    WorkflowService Class (System.ServiceModel.Activities) @ MSDN
    Receive Class (System.ServiceModel.Activities) @ MSDN
    Receive.CanCreateInstance Property (System.ServiceModel.Activities) @ MSDN
    SendReply Class (System.ServiceModel.Activities) @ MSDN

  2. einen Dienst-Bus, der Queue Unterstützung hat. Sie möchten mindestens etwas, das möglicherweise Eingaben von einer beliebigen Anzahl von Clients akzeptiert und deren Ausgaben eindeutig identifiziert und genau einmal behandelt werden können. Ein paar, die in den Sinn kommen, sind NServiceBus, MSMQ, RabbitMQ und ZeroMQ. Von den hier genannten Artikeln ist NServiceBus ausschließlich .NET-fähig und sofort einsatzbereit. In einem Cloud-Kontext umfassen Ihre Optionen auch plattformspezifische Angebote wie Azure Service Bus und Amazon SQS.
    ~
    NServiceBus
    MSMQ @ MSDN
    RabbitMQ
    ZeroMQ
    Azure Service Bus @ MSDN
    Amazon SQS @ Amazon AWS
    ~
    Beachten Sie, dass der Service-Bus zwischen einem Hersteller nur der Klebstoff, der Nachrichten und einem Verbraucher einleiten wird, die auf jeder existieren kann Anzahl der Maschinen, die aus der Warteschlange gelesen werden sollen. In ähnlicher Weise können Sie diese Indirektion für die Berichterstellung verwenden. Ihr Consumer erstellt Workflow-Instanzen, die dann die Workflow-Persistenz verwenden können.

  3. Windows AppFabric kann zum Hosten von Workflows verwendet werden. Dadurch können Sie viele Techniken verwenden, die für den IIS-Lastenausgleich gelten, um Ihre Arbeit zu verteilen. Ich persönlich habe keine Erfahrung damit, daher kann ich nicht viel anderes dafür sagen, als dass es eine gute Unterstützung bei der Überwachung bietet.
    ~
    How to: Host a Workflow Service with Windows App Fabric @ MSDN
+0

Vielen Dank! Ich muss etwas lesen und testen und sehen, was meine Firma bereit ist zu tun. – Artless

+1

Angesichts Ihres Kommentars zu der Berichtslösung zu Ihrer Frage sollte ich Sie warnen, dass der Persistenzspeicher, der mit WF ausgeliefert wird, auf MS SQL Server angewiesen ist, was ein Dealbreaker für Ihr Unternehmen sein kann. Es kann sich sehen lassen, wenn MSDE als Persistenzspeicher arbeiten kann, um die Einrichtung einer MSSQL-Instanz zu vermeiden. – meklarian