Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala 持续轮询HTTP服务器并分派给参与者的惯用方法_Scala_Akka_Spray - Fatal编程技术网

Scala 持续轮询HTTP服务器并分派给参与者的惯用方法

Scala 持续轮询HTTP服务器并分派给参与者的惯用方法,scala,akka,spray,Scala,Akka,Spray,我需要编写一个客户端,不断轮询web服务器的命令。来自服务器的响应表示命令可用(在这种情况下,响应包含该命令)或指示没有可用的命令,您应该发出新的传入命令请求 我正试图找出如何使用spray client和Akka来实现这一点,我可以想出一些方法来实现这一点,但没有一种方法看起来像是实现这一点的惯用方法。因此,问题是: 让两个线程在同一个web服务器上轮询传入的命令并将命令交给参与者,最明智的方法是什么 你可以用。它在许多Scala框架中实现。例如,在代码中如下所示: class SSE ext

我需要编写一个客户端,不断轮询web服务器的命令。来自服务器的响应表示命令可用(在这种情况下,响应包含该命令)或指示没有可用的命令,您应该发出新的传入命令请求

我正试图找出如何使用spray client和Akka来实现这一点,我可以想出一些方法来实现这一点,但没有一种方法看起来像是实现这一点的惯用方法。因此,问题是:

让两个线程在同一个web服务器上轮询传入的命令并将命令交给参与者,最明智的方法是什么

你可以用。它在许多Scala框架中实现。例如,在代码中如下所示:

class SSE extends Controller {
  def sse = GET("/sse") {
    addConnectionClosedListener {
      // The connection has been closed
      // Unsubscribe from events, release resources etc.
    }

    future {
        respondEventSource("command1")
        //...
        respondEventSource("command2")
        //...
    }
 }
SSE非常简单,可以在任何软件中使用,而不仅仅是在浏览器中。 Akka集成在xitrum中,我们在类似系统中使用它。但它将netty用于异步服务器,它还适合在10-15个线程中处理数千个请求

这样,您的客户端将保持与服务器的连接,并在连接中断时重新连接。

您可以使用。它在许多Scala框架中实现。例如,在代码中如下所示:

class SSE extends Controller {
  def sse = GET("/sse") {
    addConnectionClosedListener {
      // The connection has been closed
      // Unsubscribe from events, release resources etc.
    }

    future {
        respondEventSource("command1")
        //...
        respondEventSource("command2")
        //...
    }
 }
SSE非常简单,可以在任何软件中使用,而不仅仅是在浏览器中。 Akka集成在xitrum中,我们在类似系统中使用它。但它将netty用于异步服务器,它还适合在10-15个线程中处理数千个请求

因此,通过这种方式,您的客户端将保持与服务器的连接,并在连接中断时重新连接。

本例使用,和

实现根据所需的行为而有所不同(同时并行执行多个请求、以不同的间隔执行、向一个参与者发送响应以一次处理一个响应、向多个参与者发送响应以并行处理……等等)

此特定示例显示如何同时并行执行多个请求,然后在每个结果完成时对其执行某些操作,而无需等待同时触发的任何其他请求完成

// Executes `oneThing`, executes `andThenAnother` when `oneThing` is complete,
// then executes `finally` when `andThenAnother` completes.
for {
  oneThing <- future1
  andThenAnother <- future2
  finally <- future3
} yield (...)
下面的代码将每5秒并行执行两个HTTP请求,分别为0.0.0.0:9000/helloWorld和0.0.0.0:9000/goodbyeWorld

在Scala 2.10、Spray 1.1-M7和Akka 2.1.2中测试:

处理定期作业执行的实际调度代码:

// Schedule a periodic task to occur every 5 seconds, starting as soon 
// as this schedule is registered
system.scheduler.schedule(initialDelay = 0 seconds, interval = 5 seconds) {

  val paths = Seq("helloWorld", "goodbyeWorld")

  // perform an HTTP request to 0.0.0.0:9000/helloWorld and 
  // 0.0.0.0:9000/goodbyeWorld
  // in parallel (possibly, depending on available cpu and cores)
  val retrievedData = Future.traverse(paths) { path =>
    val response = fetch(path)
    printResponse(response)
    response
  }
}
助手方法/样板设置:

// Helper method to fetch the body of an HTTP endpoint as a string
def fetch(path: String): Future[String] = {
  pipeline(HttpRequest(method = GET, uri = s"/$path"))

}

// Helper method for printing a future'd string asynchronously
def printResponse(response: Future[String]) {
  // Alternatively, do response.onComplete {...}
  for (res <- response) {
    println(res)
  }
}


// Spray client boilerplate
val ioBridge = IOExtension(system).ioBridge()
val httpClient = system.actorOf(Props(new HttpClient(ioBridge)))

// Register a "gateway" to a particular host for HTTP requests 
// (0.0.0.0:9000 in this case)
val conduit = system.actorOf(
  props = Props(new HttpConduit(httpClient, "0.0.0.0", 9000)),
  name = "http-conduit"
)

// Create a simple pipeline to deserialize the request body into a string
val pipeline: HttpRequest => Future[String] = {
  sendReceive(conduit) ~> unmarshal[String]
}
  • 系统
    需要替换为实际的Akka actor系统

  • system.scheduler.schedule
    在本例中,每5秒执行一个任意代码块——还有一个重载版本,用于调度要发送到actorRef的消息

    system.scheduler.schedule(
      initialDelay = 0 seconds,
      frequency    = 30 minutes,
      receiver     = rssPoller, // an actorRef
      message      = "doit" // the message to send to the actorRef
    )
    
  • 对于您的特定情况,printResponse可以替换为actor send:
    anActorRef!响应

  • 代码示例不考虑失败——处理失败的好地方是printResponse(或等效)方法,方法是使用未来的onComplete回调:
    response.onComplete{…}
  • 也许很明显,但是spray客户端可以被另一个http客户端替换,只需替换
    fetch
    方法和附带的spray代码即可
  • 更新:完整运行代码示例如下:

    git克隆repo,签出指定的提交sha,
    $sbt run
    ,导航到
    0.0.0.0:9000
    ,并在执行
    sbt run
    的控制台中查看代码——它应该打印
    Hello World\再见,世界或<代码>再见世界\我的世界(由于并行Future.traverse执行,顺序可能是随机的)。

    此示例使用,和

    实现根据所需的行为而有所不同(同时并行执行多个请求、以不同的间隔执行、向一个参与者发送响应以一次处理一个响应、向多个参与者发送响应以并行处理……等等)

    此特定示例显示如何同时并行执行多个请求,然后在每个结果完成时对其执行某些操作,而无需等待同时触发的任何其他请求完成

    // Executes `oneThing`, executes `andThenAnother` when `oneThing` is complete,
    // then executes `finally` when `andThenAnother` completes.
    for {
      oneThing <- future1
      andThenAnother <- future2
      finally <- future3
    } yield (...)
    
    下面的代码将每5秒并行执行两个HTTP请求,分别为0.0.0.0:9000/helloWorld和0.0.0.0:9000/goodbyeWorld

    在Scala 2.10、Spray 1.1-M7和Akka 2.1.2中测试:

    处理定期作业执行的实际调度代码:

    // Schedule a periodic task to occur every 5 seconds, starting as soon 
    // as this schedule is registered
    system.scheduler.schedule(initialDelay = 0 seconds, interval = 5 seconds) {
    
      val paths = Seq("helloWorld", "goodbyeWorld")
    
      // perform an HTTP request to 0.0.0.0:9000/helloWorld and 
      // 0.0.0.0:9000/goodbyeWorld
      // in parallel (possibly, depending on available cpu and cores)
      val retrievedData = Future.traverse(paths) { path =>
        val response = fetch(path)
        printResponse(response)
        response
      }
    }
    
    助手方法/样板设置:

    // Helper method to fetch the body of an HTTP endpoint as a string
    def fetch(path: String): Future[String] = {
      pipeline(HttpRequest(method = GET, uri = s"/$path"))
    
    }
    
    // Helper method for printing a future'd string asynchronously
    def printResponse(response: Future[String]) {
      // Alternatively, do response.onComplete {...}
      for (res <- response) {
        println(res)
      }
    }
    
    
    // Spray client boilerplate
    val ioBridge = IOExtension(system).ioBridge()
    val httpClient = system.actorOf(Props(new HttpClient(ioBridge)))
    
    // Register a "gateway" to a particular host for HTTP requests 
    // (0.0.0.0:9000 in this case)
    val conduit = system.actorOf(
      props = Props(new HttpConduit(httpClient, "0.0.0.0", 9000)),
      name = "http-conduit"
    )
    
    // Create a simple pipeline to deserialize the request body into a string
    val pipeline: HttpRequest => Future[String] = {
      sendReceive(conduit) ~> unmarshal[String]
    }
    
  • 系统
    需要替换为实际的Akka actor系统

  • system.scheduler.schedule
    在本例中,每5秒执行一个任意代码块——还有一个重载版本,用于调度要发送到actorRef的消息

    system.scheduler.schedule(
      initialDelay = 0 seconds,
      frequency    = 30 minutes,
      receiver     = rssPoller, // an actorRef
      message      = "doit" // the message to send to the actorRef
    )
    
  • 对于您的特定情况,printResponse可以替换为actor send:
    anActorRef!响应

  • 代码示例不考虑失败——处理失败的好地方是printResponse(或等效)方法,方法是使用未来的onComplete回调:
    response.onComplete{…}
  • 也许很明显,但是spray客户端可以被另一个http客户端替换,只需替换
    fetch
    方法和附带的spray代码即可
  • 更新:完整运行代码示例如下:


    git克隆repo,签出指定的提交sha,
    $sbt run
    ,导航到
    0.0.0.0:9000
    ,并在执行
    sbt run
    的控制台中查看代码——它应该打印
    Hello World\再见,世界或<代码>再见世界\我的世界(由于并行Future.traverse执行,顺序可能是随机的)。

    您不能控制服务器吗?如果是,请使用websocket和