【问题标题】:Processing SOAP messages with Akka使用 Akka 处理 SOAP 消息
【发布时间】:2012-09-25 13:13:14
【问题描述】:

我正在为我的雇主构建一个小工具,并尝试使用 Akka 2 + Scala 来实现它。

我正在与之交互的其中一个系统有一个 SOAP api,它有一个有趣的实现:

----请求-------

客户端----请求---->服务器

客户端

----响应-----

客户端

客户端----响应确认---->服务器

通过 req-ack 发送的任务 ID 来跟踪请求。

我的问题是向 SO 社区提出的问题,任何对 akka 有经验的人如下:

  • 在这种特殊情况下,使用 akka 处理 http 消息的理想方法是什么?我已经看到了 Akka-Mist 的示例,看起来它已经停止支持 play-mini,然后是 akka-camel,我似乎无法找到作为 akka 2.0.3 一部分的库分布,所以我有点困惑我应该采取什么方法。是否有推荐的方法将 servlet 的行为封装在 akka actor 中?

提前谢谢大家。

【问题讨论】:

  • 您没有指定应用程序是客户端还是服务器。
  • 应用程序是一个客户端,但是还必须有一个 uri 端点来接收响应。

标签: http scala servlets akka


【解决方案1】:

您的问题非常开放,因此我将对您的要求做出一些假设。

请求假设:由于某个事件而产生了很多请求。

创建一个包含封装 async-http-client (https://github.com/sonatype/async-http-client) 的 Actor 的路由器。一旦 async-http-client 完成一个请求,它就会向协调参与者发送一条消息,该消息的 ID 包含在 Req Ack 中。协调参与者将聚合 ID。

以下大部分是伪代码,但它与真正的 API 足够接近,您应该能够找出缺失的部分。

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
    }
}

响应假设:您需要对响应中包含的数据做一些事情,然后将 ID 标记为完整。 HTTP 前端只需要处理这一组消息。

不要试图找到一个与 Akka 集成的框架,只需使用一个简单的 HTTP 前端,它将消息发送到您创建的 Akka 网络。我无法想象使用 play-mini 获得的任何优势,而且我认为它会掩盖一些描绘工作分离和控制的界限。情况并非总是如此,但鉴于您的问题缺乏要求,我没有其他可依据的意见。

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)
    }

}

创建一个与此类似的系统可以很好地分离关注点,让您很容易推断处理发生在哪里,并有足够的空间来扩展或扩展系统。

【讨论】:

  • 这实际上正是我想要的。谢谢!
猜你喜欢
  • 2016-09-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多