Jersey @ManagedAsync und Kopieren von Daten zwischen HTTP-Thread und Worker-Thread

8

Ich arbeite an einem Projekt, das in zwei Varianten mit und ohne Mandantenfähigkeit funktioniert.

Das Projekt macht einen REST-Service verfügbar, den ich gerne asynchron nutzen würde. So sieht mein Basisservice aus wie

%Vor%

Das funktioniert ohne Mehrmandanten und ich bekomme die Vorteile des internen Jersey Executor Service kostenlos. Siehe @ManagedAsync

Wenn ich in die Mandantenfähigkeit umschalte, füge ich einen Filter zu der Anfrage hinzu, der die Mandanten-ID auflöst und sie auf den lokalen Thread setzt (in unserem Fall den HTTP-Thread).

Wenn die Verarbeitungskette die "add ()" -Methode übertrifft, ist der aktuelle Thread derjenige, der vom Jersey-Executor-Service bereitgestellt wird. Daher enthält er nicht meine Mandanten-ID. Ich könnte nur über die folgenden Optionen nachdenken, um dieses Problem zu umgehen.

Erweitern Sie den ResouceEndpoint zu MutliTenantResouceEndpoint, und legen Sie den @ManagedAsync ab Mit meinem eigenen Thread-Executor

%Vor%

Aber auf diese Weise muss ich meinen eigenen Thread-Executor verwalten und es fühlt sich an, als würde mir hier etwas fehlen. Irgendwelche Vorschläge zu einem anderen Ansatz?

    
Haim Raman 30.06.2015, 11:33
quelle

1 Antwort

14

Hier sind einige Empfehlungen in der Reihenfolge.

Für den Kontext verwende ich Jersey seit 2 Jahren, und konfrontiert mit genau diesem Problem vor 18 Monaten.

1. Stoppen Sie die Verwendung von @ManagedAsync

Wenn Sie die Kontrolle über den http-Server haben, auf dem Jersey läuft, würde ich Ihnen empfehlen, @ManagedAsync nicht mehr zu benutzen.

Statt Jersey so einzurichten, dass es den HTTP-Thread sofort zurückgibt, und echte Anfragen an einen verwalteten Executor-Service-Thread auszulagern, verwenden Sie so etwas wie Grizzly für Ihren http-Server und konfigurieren Sie ihn für einen größeren Worker-Thread-Pool. Dies führt die gleiche Sache durch, aber schiebt die asynchrone Verantwortung in eine Ebene unterhalb von Jersey.

Wenn Sie @ManagedAsync für ein Medium-zu-Large-Projekt verwenden, werden Sie im Laufe eines Jahres mit vielen Schwachstellen konfrontiert. Hier sind einige von ihnen von meinem Kopf:

  • Wenn ein ContainerRequestFilter auf einen externen Dienst trifft (z. B. ein Auth-Filter trifft Ihr Sicherheitsmodul, das die Datenbank trifft), verlieren Sie die Vorteile, von denen Sie dachten, dass Sie sie erlangten
    • Wenn Ihre Datenbank gedrosselt wird und der Auth-Filter-Aufruf 5 Sekunden dauert, hat Jersey die Arbeit noch nicht in den asynchronen Thread ausgelagert, so dass Ihr Haupt-Thread, der ein neues Conn empfangen muss, blockiert ist
  • Wenn Sie den MDC des Logbacks in einem Filter einrichten und diesen Kontext während Ihrer gesamten Anfrage verwenden möchten, müssen Sie den MDC erneut für den verwalteten asynchronen Thread einrichten
  • Ressourcenmethoden sind kryptisch für Neulinge und hässlich zu lesen, weil:
    • sie brauchen einen zusätzlichen Parameter
    • sie geben void zurück und verstecken ihren echten Antworttyp
    • sie können überall "zurückkehren", ohne irgendwelche tatsächlichen return Statements
  • Swagger oder andere API-Dokumentationswerkzeuge können die asynchronen Ressourcenendpunkte nicht automatisch dokumentieren
  • Guice oder andere DI-Frameworks haben möglicherweise Probleme mit bestimmten Scope-Bindungen und / oder Providern in asynchronen Ressourcenendpunkten

2. Verwenden Sie @Context und ContainerRequest Eigenschaften

Dies würde bedeuten, dass requestContext.setProperty("tenant_id", tenantId) in Ihrem Filter aufgerufen wird und dann der Aufruf von requestContext.getProperty("tenant_id") in Ihrer Ressource mit einer @Context injected request aufgerufen wird.

3. Verwenden Sie HK2 AOP statt Jersey-Filter

Dies würde das Einrichten einer HK2-Bindung von InterceptionService mit einem MethodInterceptor beinhalten, das nach verwalteten asynchronen Ressourcenmethoden sucht und alle RequestScoped bound ContainerRequestFilter s manuell ausführt. Anstatt dass Ihre Filter bei Jersey registriert werden, würden Sie sie bei HK2 registrieren, damit sie vom Methodenabfangprogramm ausgeführt werden.

Ich kann den Optionen 2/3 weitere Details und Codebeispiele hinzufügen, wenn Sie möchten, oder zusätzliche Vorschläge machen, aber es wäre zunächst hilfreich, mehr von Ihrem Filtercode zu sehen, und ich schlage, wenn möglich, erneut Option 1 vor.

    
Alden 09.07.2015, 04:17
quelle