Multithreading eines datenbankgesteuerten Dienstes
Zunächst einige Hintergrundinformationen zum Problem: Wir haben einen Windows-Dienst (C Sharp), der neue Nachrichten empfängt und verarbeitet. Er ist datenbankgesteuert, überprüft eine Tabelle auf unverarbeitete Datensätze, verarbeitet sie und aktualisiert sie dann. Dies alles geschieht innerhalb von zwei gespeicherte Prozeduren, eine zum Abrufen unverarbeiteter Nachrichten und eine zum Verarbeiten.
Der Dienst wurde in unserem System als Flaschenhals identifiziert. Wenn wir mehr unverarbeitete Nachrichten erhalten, dauert es immer länger, bis der Dienst die hintere Warteschlange durchläuft.
Ich wurde gebeten, diesen Dienst neu zu schreiben, um die Parallelität zu nutzen. Die Tatsache, dass es sich um Single-Threaded handelt, wird als Grund für die schlechte Leistung bei großen Volumes angesehen. Ich habe jedoch einige Vorbehalte gegen diese Annahme.
Überblick über die Verarbeitung einer Nachricht (einzeln ausgeführt):
- Rufen Sie getMessage sproc auf und speichern Sie relevante Daten im Speicher
- Rufen Sie processMessage sproc auf, indem Sie zuvor abgerufene Daten übergeben. Die Nachricht wird verarbeitet und validiert und dann als in der Quelltabelle verarbeitet markiert
Die Tatsache, dass der Dienst 90% der Verarbeitung in der DB-Schicht ausführt, zeigt mir, dass alle Probleme im Zusammenhang mit der Leistung an die Verwendung der Datenbank gebunden sind. Ich sehe keinen Vorteil darin, diesen Service multithreaded zu machen, und denke, dass die Bemühungen darauf gerichtet sein sollten, entweder die Geschäftslogik von den Sprocs auf den Service zu migrieren oder zumindest die Sprocs so zu optimieren, dass sie gleichzeitig aufgerufen werden können, ohne Tabellensperren oder andere Probleme mit Ressourcenkonflikten zu verursachen .
Ich würde mich über jeden professionellen Beitrag zu diesem Ansatz freuen, da das Ergebnis der Leistung dieses Dienstes bei mir liegt und ich mit den besten Erwartungen führen möchte.
Antworten
Die Erfahrung zeigt mir, dass Sie zu 100% richtig raten. Die Erfahrung sagt mir jedoch auch, dass ich niemals den Mund über etwas öffnen soll, bis ich es bewiesen habe.
Hier sollte es einfach genug sein, einige Metriken hinzuzufügen, die die Zeit aufzeichnen, die zum Verarbeiten einer Nachricht benötigt wird, und wie viel dieser Zeit für jedes Bit aufgewendet wird.
Fahren Sie die Nachrichten hoch und sehen Sie, welche Bits länger dauern.
Sie können sogar noch weiter gehen, indem Sie einfach die Datenbankaufrufe in asynchron ändern und nicht warten, bis sie abgeschlossen sind, bevor Sie mit der nächsten Nachricht fortfahren, im Wesentlichen "Multithreading" (ish) Ihrer App. Wenn Sie jedoch richtig liegen, wird die Datenbank dadurch zum Stillstand gebracht, sodass sie am besten auf einem Testsystem ausgeführt werden kann.
Sobald die Schuld eindeutig bei den Sprocs liegt, können Sie sie untersuchen, um herauszufinden, warum sie langsam sind, oder einfach die Logik herausholen.