2010-08-21 6 views
12

Ich habe eine Scala-Anwendung, die Akka verwendet, die REST-Anforderungen empfängt, einige Operationen gegen eine Datenbank ausführt und mit einigen Informationen an den Client antwortet. Da meine db-Vorgänge sehr lange dauern, kann mein REST-fähiger Akteur in der Zwischenzeit nicht auf neue Anforderungen reagieren, obwohl ich viele Operationen gleichzeitig mit der Datenbank ausführen könnte. Ich verwende die javax.ws.rs-Annotationen, um Methoden in meinem Akteur REST-fähig zu machen.Wie skaliere ich meine Scala REST-Anwendung, die Akka verwendet?

Die Frage; Was ist der beste Weg, um es meiner Anwendung zu ermöglichen, eine große Anzahl gleichzeitiger Anfragen zu bearbeiten?

BEARBEITEN: Ich füge einen Beispielcode hinzu.

import se.scalablesolutions.akka.actor._ 
    import javax.ws.rs._ 

    @Path("/test") 
    class TestService { 

    @GET 
    def status() = 
     actorPool !! Status(session). 
     getOrElse(<error>Unable to connect to service</error>) 
    } 

    class TestActor { 

    def receive = { 
     case Status() => { 
     reply(SomeObject.slowDBMethod) 
     } 
    } 
    } 

    case class Status() 

EDIT2: Das ist, was ich im Protokoll zu bekommen. Ich sende die drei Anfragen von meinem Browser so schnell, wie ich Tabs wechseln kann und F5 drücke, aber die RS-Bean wartet immer noch auf die erste Anfrage, bevor sie mit der nächsten fertig wird.

[INFO] [2010-08-29 16:27:03,232] [akka:event-driven:dispatcher:global-15] c.n.StatusActor: got Slow request 
[INFO] [2010-08-29 16:27:06,916] [akka:event-driven:dispatcher:global-10] c.n.StatusActor: got Slow request 
[INFO] [2010-08-29 16:27:10,589] [akka:event-driven:dispatcher:global-3] c.n.StatusActor: got Slow request 
+0

Vielleicht möchten Sie in Apache Bench statt F5 drücken, so viel Tolles Tool für Parallelitätstests. http://httpd.apache.org/docs/2.2/programs/ab.html – cbmeeks

Antwort

6

Während ich feststelle, dass dieser Thread 4+ Monate alt ist, ist es bemerkenswert, dass Akka eine neue HTTP-Modul-Implementierung hat, die die Anfrage effizient in einen Aktor überträgt. Dieser Ansatz nutzt die asynchrone Servlet-API (die auch mit Jetty-Fortsetzungen funktioniert), um zu ermöglichen, dass die ausgesetzte Anforderung als Nachricht an das System weitergeleitet und zu jedem Zeitpunkt fortgesetzt wird. Beseitigung, zum Beispiel, die Notwendigkeit zu verwenden !! um die Arbeit des Schauspielers auszulösen und in dem kommentierten POJO zu antworten. Da die Anforderung im Container aufgehoben wird und der Kontext so schnell wie möglich in einen Akteur umgewandelt wird, werden keine Threads blockiert, um die Antwort oder die Zukunft zu verarbeiten.

Eine naive Art und Weise das obige Beispiel könnte heute neu geschrieben werden:

class TestEndpoint extends Actor with Endpoint { 
    def hook(uri:String) = uri == "/test" 
    def provide(uri:String) = actorOf[TestService].start 

    override def preStart = { 
    ActorRegister.actorsFor[classOf[RootEndpoint]).head ! Endpoint.Attach(hook, provide) 
    } 

    def receive = handleHttpRequest 
} 

class TestService extends Actor { 
    def receive = { 

    case get:Get => 
     get.timeout(SomeObject.TimeoutInSeconds) // for example 
     get.OK(SomeObject.slowDBMethod) 

    case other:RequestMethod => 
     other.NotAllowed("Invalid method for this endpoint") 
    } 
} 

Mehr Dokumentation auf der akka Website zu finden ist: http://doc.akkasource.org/http

3

Sobald Sie eine Anfrage erhalten, sollten Sie einen neuen Akteur erstellen, um diese Anfrage zu bearbeiten. Geben Sie den ursprünglichen Absender weiter, damit der neu erstellte Akteur weiß, wem er antworten soll.

+0

In einer "normalen" Akteur Situation würde ich erwarten, dass zu arbeiten. Aber in meinem Fall kann ich den "Sender" in der status() -Methode des hinzugefügten Codebeispiels nicht wirklich weitergeben? Ich gehe davon aus, dass der Aktor, egal was ich in der Empfangsmethode mache, nicht für weitere REST-Anforderungen bereit sein wird, solange die status() -Methode nicht abgeschlossen ist. – Magnus

+0

Wie wäre es, Schauspieler pro Benutzersitzung zu halten? – andreypopp

7

Sie scheinen eine ältere Version von Akka zu verwenden.

Ich empfehle auf 0,10 Upgrade (die Schauspieler und die RS-Beans trennt), dann können Sie LoadBalancer verwenden 1 (und 2), um die Arbeitsbelastung zu drosseln, oder nutzen Sie die WorkStealingDispatcher 3 (und 4)

Hilft das?

+0

Das sieht vielversprechend aus. Ich werde 0.10 ausprobieren. – Magnus

+0

Ich konnte keine 0.10-Version von akka-rest finden, zumindest nicht im maven2-Repository. Soll ich die Version 0.8 verwenden? – Magnus

+0

@Magnus Siehe http://doc.akkasource.org/getting-started#The%20Next%20Steps-Using%20Akka%20with%20Maven –

1

Obwohl dieses Thema alt ist, ich mag Spiffy hinzufügen (Stecker!) auf die Mischung:

https://github.com/mardambey/spiffy

Was Spiffy ist?

Spiffy ...

  • wird in Scala geschrieben
  • die fantastische Akka Bibliothek und Schauspieler verwendet 3 maßstabs
  • verwendet Servlet-API.0 für die asynchrone Anforderung bearbeitet
  • modular ist (Austausch von Komponenten geradlinig)
  • DSLs verwendet auf Code zu reduzieren, wo man es nicht
  • wollen unterstützt Anfrage Haken um Controller

Spiffy ist ein Web-Framework mit Scala, Akka (eine Scala-Actor-Implementierung) und Java Servelet 3.0 API. Es nutzt die asynchrone Schnittstelle und zielt darauf ab, eine massiv parallele und skalierbare Umgebung für Webanwendungen bereitzustellen. Die verschiedenen Komponenten von Spiffy basieren alle auf der Idee, dass sie unabhängige, minimalistische Module sein müssen, die sehr schnell kleine Aufgaben erledigen und die Anfrage an die nächste Komponente in der Pipeline weiterleiten. Nachdem die letzte Komponente die Anfrage bearbeitet hat, signalisiert sie dem Servlet-Container, indem er die Anfrage "abschließt" und sie an den Client zurücksendet.