2012-09-25 4 views
1

Je suis en train de construire un petit outil pour mon employeur, et je tente de l'implémenter avec Akka 2 + Scala.Traitement des messages SOAP avec Akka

L'un des systèmes que je suis en interface avec a aa api SOAP, qui a une mise en œuvre intéressante:

---- ------- Demande

client ---- Demande ----> serveur

client < --- ----- Req Ack serveur

---- ------ Réponse

client < --- Réponse ---- Serveur

client ---- ---- Resp Ack> Serveur

Garder la trace des demandes se fait via un identifiant de tâche envoyé par le req-ack.

Ma question est la communauté SO et toute personne qui possède de l'expérience avec Akka sont les suivantes:

  • Quelle serait un moyen idéal pour gérer les messages HTTP à l'aide akka pour ce scénario particulier? J'ai vu des exemples avec Akka-Mist, qui semble avoir été abandonné en faveur de play-mini, puis il y a akka-camel, pour lequel je ne peux pas trouver la bibliothèque dans le cadre de l'akka 2.0.3 distribution, donc je suis un peu confus quant à l'approche que je devrais prendre. Existe-t-il un moyen recommandé d'encapsuler un comportement de servlet dans un acteur akka?

Merci d'avance.

+0

Vous ne spécifiez pas si l'application est le client ou le serveur. –

+0

L'application est un client, mais doit également avoir un point de terminaison uri pour recevoir des réponses. – cudiaco

Répondre

2

Votre question est très ouverte, donc je vais faire quelques hypothèses sur vos besoins.

Hypothèse de la requête: De nombreuses requêtes sont générées lors d'un événement.

Créez un routeur ayant des acteurs qui encapsulent le client async-http (https://github.com/sonatype/async-http-client). Une fois que le client async-http a terminé une requête, il enverra un message ayant l'ID contenu dans le Req Ack à un acteur de coordination. L'acteur de coordination regrouperait les identifiants. Ce qui suit est en grande partie un pseudo-code, mais il est assez proche de l'API réelle que vous devriez être en mesure de comprendre les pièces manquantes.

case class Request(url:String) 
case class IDReceived(id:String) 

case class RequestingActor extends Actor { 

    override def receive = { 
     case Request(url) => { 
      //set up the async client and run the request 
      //since it's async the client will not block and this actor can continue making generating more requests 
     } 
    } 
} 


class AsyncHttpClientResponseHandler(aggregationActor:ActorRef) extends SomeAsyncClientHandler { 

    //Override the necessary Handler methods. 

    override def onComplete = { 
     aggregationActor ! IDReceived(//get the id from the response) 
    } 
} 

class SomeEventHandlerClass { 

    val requestRouter = actorSystem.actorOf(Props[RequestingActor].withRouter(FromConfig(//maybe you've configured a round-robin router)), requestRouterName) 

    def onEvent(url:String) { 
     requestRouter ! Request(url) 
    } 

} 

case class AggregationActor extends Actor { 

    val idStorage = //some form of storage, maybe a Map if other information about the task ID needs to be stored as well. Map(id -> other information) 

    override def receive = { 
     case IDReceived(id) => //add the ID to idStorage 
    } 
} 

Hypothèse de réponse: Vous devez faire quelque chose avec les données contenues dans la réponse, puis marquer l'ID comme complet. Le frontend HTTP a seulement besoin de gérer ce jeu de messages. Au lieu d'essayer de trouver un framework avec l'intégration d'Akka, il suffit d'utiliser une simple interface HTTP qui enverra des messages dans le réseau Akka que vous avez créé. Je ne peux imaginer aucun avantage obtenu en utilisant play-mini et je pense que cela masquerait certaines des lignes qui délimitent la séparation et le contrôle du travail. Ce n'est pas toujours le cas, mais étant donné le manque d'exigences dans votre question, je n'ai rien d'autre sur quoi baser mon opinion.

case class ResponseHandlingActor extends Actor { 

    val aggregationActor = actorSystem.actorFor(//the name of the aggregation router within the Actor System) 

    override def receive = { 
     case Response(data) => { 
      //do something with the data. If the data manipulation is blocking or long running it may warrant its own network of actors. 
      aggregationActor ! ResponseReceived(//get the id from the response) 
     } 
    } 
} 

class ScalatraFrontEnd() extends ScalatraServlet { 

    val responseRouter = actorSystem.actorOf(Props[RequestingActor].withRouter(FromConfig(//maybe you've configured a round-robin router)), requestRouterName) 

    post("/response") { 
     responseRouter ! Response(//data from the response) 
    } 

} 

Création d'un système similaire à ce qui vous donne bonne séparation des préoccupations, rend vraiment facile à raisonner sur où le traitement a lieu et beaucoup de place pour étendre le système ou l'étendre.

+0

C'est en fait exactement ce que je cherchais. Merci! – cudiaco

Questions connexes