2012-04-08 3 views
32

Ich komme aus einem Java SE-Hintergrund, und ich habe einige Servlets Tutorials und lesen Kopf zuerst JSP & Servlet. Ich lese jetzt den Artikel JavaWorld.com über Async-Unterstützung, aber ich verstehe es nicht ganz.Ich verstehe nicht Async-Unterstützung in Servlets 3.0 API

Worum geht es bei Async? Was ist der Unterschied zwischen Ajax und Servlet Async?

P.S ich einen PHP-Hintergrund mit Ajax habe und ich weiß, das Konzept, aber ich habe es nicht versucht mit Java

Antwort

81

Im traditionellen Servlet-Modell, es ist normalerweise der Fall, dass ein Antrag auf 1 Faden entspricht.

Diese Threads stammen normalerweise aus einem Pool, der vom Servlet-Container verwaltet wird. Der Servlet-Container kann nur neue Anforderungen verarbeiten, solange er über freie Threads in diesem Pool verfügt. Solange Ihr eigener Code die Anfrage bearbeitet, ist der Thread nicht frei.

In einigen Situationen könnte es sich lohnen, dieses Modell zu brechen. Was passiert, ist, dass eine Anfrage über einen solchen servlet-containerverwalteten Thread am Servlet eintrifft und Ihr Code dann nach einer asynchronen Ausführung fragt. Sie können dann von der Servlet-Anfrage zurückkehren und der Container-Thread wird freigegeben.

Im Gegensatz zur synchronen Anforderungsverarbeitung wird dadurch keine Reaktion ausgelöst und die Verbindung wird nicht geschlossen. Stattdessen können Sie den asynchronen Kontext an einen anderen Thread-Pool übergeben, der ihn aufheben kann, und wenn ein Thread frei ist, ihn zu verarbeiten, können Sie ihn bearbeiten und in die Antwort schreiben.

Ein Beispiel:

@WebServlet(urlPatterns = "/somepath", asyncSupported = true) 
public class AsyncServlet extends HttpServlet { 

    @EJB 
    private AsyncBean asyncBean; 

    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 
     AsyncContext asyncContext = request.startAsync(); 

     // The following line will not block and return immediately 
     asyncBean.doAsyncStuff(asyncContext); 

    } // Shortly after this method has ended, thread will be returned to pool 
} 

Mit dem AsyncBean wird als umgesetzt:

@Stateless 
public class AsyncBean { 

    @Asynchronous 
    public void doAsyncStuff(AsyncContext asyncContext) throws IOException { 
     asyncContext.getResponse().getWriter().write("test"); 
    } 
} 

Im Code oben, irgendwo kurz nachdem Sie von der AsyncServlet#doGet() Methode zurückkehren, wird der Servlet Thread zu zurückgegeben werden der Pool. Eine 'Anfrage' (Task) zum Ausführen von AsyncBean#doAsyncStuff() wird in die Warteschlange für den EJB-Thread-Pool aufgenommen.

Die Antwort auf WARUM und WANN, wenn Sie dies verwenden würden, ist nicht so einfach. Wenn Sie nur Threads beibehalten möchten, würden Sie im obigen Fall einen Thread aus einem Threadpool für den anderen austauschen (in diesem Fall den Servlet-Pool im Vergleich zum EJB-Async-Pool), und der Nettonutzen wäre nicht so groß. Sie hätten Ihrem Servlet-Thread-Pool auch einen zusätzlichen Thread geben können.

In fortgeschritteneren Szenarien könnten Sie jedoch eine feinere Verwaltung von Anforderungen durchführen. Teilen Sie sie in mehrere Aufgaben auf und lassen Sie diese Aufgaben von einem Thread-Pool erledigen. Z.B. Stellen Sie sich 100 Download-Anfragen für eine 10MB-Datei vor, die von 10 Threads behandelt wird, die Round-Robin geben 100KB eine Zeit für jede Anfrage sendet.

Noch eine andere Anwendung ist eine Anfrage, die auf Daten von einem externen System warten muss, und wo dieses externe System in der Lage ist, eine Nachricht zu senden, die an den Anforderer zurückgeschickt werden kann. I.e. Ein Datenbankaufruf wäre hier nicht sinnvoll, da Sie ohnehin einen anderen Thread benötigen würden, der auf die Antwort wartet. Dann würden Sie wieder einen Thread für einen anderen wechseln. Wenn Sie jedoch auf eine eingehende E-Mail warten müssen, kann ein Thread auf eine E-Mail warten und diese an eine ausgesetzte E-Mail weiterleiten.

+2

Vielen Dank Arjan, der erste Absatz ist wirklich klar und verständlich. –

+4

Ich verstehe nicht vollständig, wie das Verschieben eines Threads von einem Pool in einen anderen aus Sicht der Skalierbarkeit einen Unterschied machen kann. Ich sehe den Punkt in der Rückgabe des Server-Listener-Thread an den Pool, aber ich weiß nicht wirklich, ob das die Skalierbarkeit Ihrer Anwendung sehr verbessern kann. –

+3

Der Austausch von Threads hilft nicht bei der Skalierbarkeit, aber siehe Download-Beispiel. Einige Threads können möglicherweise viele asynchrone Verbindungen versorgen. Wenn die Anforderung in mehrere Aufgaben aufgeteilt werden kann, die in die Warteschlange gestellt werden können, lohnt es sich möglicherweise, diesen Modus zu berücksichtigen. Sonst gibt es nicht viel zu erwartende Vorteile. –