Wie soll ich diesen Anwendungsfall mit EventMachine behandeln?

8

Ich habe eine Anwendung, die auf Nachrichten reagiert, die von Clients gesendet werden. Eine Nachricht ist reload_credentials , die die Anwendung erhält, wenn ein neuer Client registriert wird. Diese Nachricht stellt dann eine Verbindung zu einer PostgreSQL-Datenbank her, führt eine Abfrage für alle Anmeldeinformationen durch und speichert sie dann in einem regulären Ruby-Hash (client_id = & gt; client_token).

Einige andere Nachrichten, die die Anwendung möglicherweise erhält, sind start , stop , pause , die verwendet werden, um einige Sitzungszeiten zu verfolgen. Mein Punkt ist, dass ich mir die Anwendung auf folgende Weise vorstellen kann:

  • Client sendet eine Nachricht
  • Nachricht wird in die Warteschlange gestellt
  • Warteschlange wird verarbeitet

Allerdings möchte ich zum Beispiel den Reaktor nicht blockieren. Stellen wir uns außerdem vor, dass ich eine Nachricht reload_credentials habe, die als nächstes in der Warteschlange ist. Ich möchte nicht, dass eine andere Nachricht aus der Warteschlange verarbeitet wird, bis die Anmeldeinformationen von der Datenbank neu geladen werden. Während ich eine bestimmte Nachricht verarbeite (zum Beispiel das Warten auf die Beendigung der Anmeldeinformationen-Abfrage), möchte ich zulassen, dass andere Nachrichten in die Warteschlange eingereiht werden.

Könnten Sie mir bitte helfen, ein solches Problem zu lösen? Ich denke, ich muss em-synchrony verwenden, aber ich bin mir nicht sicher.

    
Geo 06.09.2012, 19:29
quelle

2 Antworten

7

Verwenden Sie einen der Postgresql-EM-Treiber oder EM.defer, damit Sie den Reaktor nicht blockieren.

Wenn Sie die Nachricht "reload_credentials" erhalten, drehen Sie einfach ein Flag, das bewirkt, dass alle nachfolgenden Nachrichten in die Warteschlange eingereiht werden. Sobald die 'reload_credentials' beendet ist, verarbeiten Sie alle Nachrichten aus der Warteschlange. Nachdem die Warteschlange leer ist, klappen Sie das Flag um, damit Nachrichten beim Empfang verarbeitet werden.

EM-Treiber für Postgresql sind hier aufgelistet: Ссылка

%Vor%

Wenn Sie möchten, dass alle Verbindungen Nachrichten in die Warteschlange stellen, wenn eine Verbindung eine 'reload_connections'-Nachricht erhält, müssen Sie über die Eigenklasse koordinieren.

    
simulacre 08.09.2012, 13:45
quelle
4

Ich nehme an, so etwas wie Ihre aktuelle Implementierung:

%Vor%

Das obige Problem, wenn ich Sie richtig verstehe, ist, dass Sie nicht wollen, dass Mitarbeiter an neuen Jobs arbeiten (Jobs, die früher in der Producer-Zeitleiste angekommen sind) als Jobs mit reload_credentials. Folgendes sollte dies tun (zusätzliche Worte der Vorsicht am Ende).

%Vor%

Also kommt die Eingabe in das erste System in q , aber in diesem neuen System kommt es auf channel . Das queue wird immer noch für die Arbeitsverteilung unter Arbeitern verwendet, aber das queue wird nicht ausgefüllt, während eine Aktualisierung der Anmeldeinformationen ausgeführt wird. Leider habe ich, da ich nicht mehr Zeit brauchte, das LockingDispatcher nicht verallgemeinert, so dass es nicht mit dem Artikeltyp und dem Code für den Versand von CredentialsReloader gekoppelt ist. Das überlasse ich dir.

Sie sollten hier anmerken, dass während dieser Dienstleistungen, was ich von Ihrer ursprünglichen Anfrage verstehe, es im Allgemeinen besser ist, diese Art von Anforderung zu entspannen. Es gibt mehrere offene Probleme, die ohne Änderung dieser Anforderung im Wesentlichen nicht beseitigt werden können:

  • Das System wartet nicht darauf, dass die Ausführung von Jobs abgeschlossen wird, bevor Anmeldeinformationsjobs gestartet werden
  • Das System wird Bursts von Anmeldeinformationen-Jobs sehr schlecht behandeln - andere Elemente, die möglicherweise verarbeitet werden können, werden nicht.
  • Im Falle eines Fehlers im credentials-Code könnte der Backlog ram auffüllen und einen Fehler verursachen. Eine einfache Zeitüberschreitung könnte ausreichen, um katastrophale Auswirkungen zu vermeiden, wenn der Code abbricht und nachfolgende Nachrichten ausreichend verarbeitbar sind, um weitere Deadlocks zu vermeiden.

Es klingt tatsächlich so, als hätten Sie eine Vorstellung von einer Benutzer-ID im System. Wenn Sie Ihre Anforderungen durchdenken, ist es wahrscheinlich möglich, dass Sie nur Elemente zurücksetzen müssen, die sich auf eine Benutzer-ID beziehen, deren Anmeldeinformationen sich in einem Aktualisierungszustand befinden. Dies ist ein anderes Problem, das eine andere Art des Versands beinhaltet. Probieren Sie einen Hash der gesperrten Rückstände für diese Benutzer aus, mit einem Callback für die Vollendung der Anmeldeinformationen, um diese Rückstände in die Worker oder eine ähnliche Anordnung zu löschen.

Viel Glück!

    
raggi 09.09.2012 18:44
quelle

Tags und Links