Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/335.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
Java Akka Http请求和响应模式_Java_Scala_Akka_Akka Stream_Akka Http - Fatal编程技术网

Java Akka Http请求和响应模式

Java Akka Http请求和响应模式,java,scala,akka,akka-stream,akka-http,Java,Scala,Akka,Akka Stream,Akka Http,我有一个要求,客户机调用通过akka http创建的post REST端点。一旦请求在post方法中,我就需要将post对象传递给流(由源、多个流和接收器等组成),并从接收器获取响应,以便将响应返回给客户端 我已经阅读了一些文章,看到了下面的代码,但我担心我不想为每个请求实现流。我只想具体化一个流,并继续将元素传递给该流 以下是我所看到的高层次内容: val route: Route = path("dummy path") { p => get { (extrac

我有一个要求,客户机调用通过akka http创建的post REST端点。一旦请求在post方法中,我就需要将post对象传递给流(由源、多个流和接收器等组成),并从接收器获取响应,以便将响应返回给客户端

我已经阅读了一些文章,看到了下面的代码,但我担心我不想为每个请求实现流。我只想具体化一个流,并继续将元素传递给该流

以下是我所看到的高层次内容:

val route: Route =
  path("dummy path") { p =>
    get {
      (extract(_.request) & extractMaterializer) { (req, mat) ⇒
        **Source.single(req).runWith(sink)(mat)**

        complete {
          s"<h1>Say hello to akka-http. p=$p</h1>"
        }
      }
    }
  }

或者,我还可以在我的用例中加入其他内容。

我想你想要的是让请求的处理通过流[只具体化一次],并从流中将响应发送回用户。可能是队列源,中间的参与者可以执行此任务

import java.util.concurrent.TimeUnit

import akka.actor.{Actor, ActorRef, ActorSystem, Props}
import akka.http.scaladsl.Http
import akka.http.scaladsl.server.Directives.{
  get,
  onSuccess,
  pathEnd,
  pathPrefix
}
import akka.pattern.ask
import akka.stream.scaladsl.{Keep, Sink, Source, SourceQueueWithComplete}
import akka.stream.{ActorMaterializer, OverflowStrategy, QueueOfferResult}
import akka.util.Timeout
import akka.http.scaladsl.server.directives.RouteDirectives.complete
import com.typesafe.config.ConfigFactory

import scala.concurrent.ExecutionContext

object TestApp2 extends App {

  implicit val actorSystem = ActorSystem("test-system")
  implicit val mat = ActorMaterializer()
  implicit val ec = mat.executionContext

  val streamSource = Source
    .queue[(Message, ActorRef)](100, OverflowStrategy.dropNew)
    .map { p =>
      //do anything here
      println("I am processing request")
      ("It works", p._2)
    }
    .toMat(Sink.foreach { resp =>
      resp._2 ! resp._1
    })(Keep.left)
    .run()
  implicit val timeout = Timeout(
    10000,
    TimeUnit.MILLISECONDS
  )

  val internalActor =
    actorSystem.actorOf(Props(new InternalActor(streamSource)))
  Http(actorSystem)
    .bindAndHandle(
      getRoutes(internalActor),
      "0.0.0.0",
      8080
    )

  def getRoutes(
      internalActor: ActorRef
  )(implicit mat: ActorMaterializer, ec: ExecutionContext, timeout: Timeout) = {
    pathPrefix("healthcheck") {
      get {
        pathEnd {
          val responseReturned = internalActor ? Message()
          onSuccess(responseReturned) {
            case response: String =>
              complete(response)
            case _ => complete("error")
          }
        }
      }
    }
  }
}

case class Message()

class InternalActor(streamSource: SourceQueueWithComplete[(Message, ActorRef)])(
    implicit ec: ExecutionContext
) extends Actor {

  override def receive: Receive = {
    case m: Message =>
      val senderRef = sender()
      streamSource.offer((m, senderRef)).map {
        case QueueOfferResult.Enqueued => // do nothing for success
        case QueueOfferResult.Dropped => senderRef ! "error" // return error in case of backpressure 
        case QueueOfferResult.Failure(ex) => senderRef ! "error" // return error
        case QueueOfferResult.QueueClosed => senderRef ! "error" // return error
      }
  }
}

卷曲“


它可以工作

处理的输出是什么?是否要在数据仍然传入时开始流式输出结果?Hi jrudolph,Request是post http请求,响应将是一个对象(普通pojo),封送到json响应,并通过相同的http调用返回给用户。我现在在我的场景中使用akka http低级DSL(我只想具体化我的流一次),它按照预期工作。不过,有时当客户端应用程序发出多个http调用时,有时我的流被挂起并超时,并且没有返回响应。这是因为在超时期间,HttpEntity.Default与Strict相比返回。我尝试使用.toStict(),但问题仍然存在?我做错了吗?嗨,jrudolph,关于你的问题:你想在数据仍然传入时开始流式输出结果吗->我相信没有。原因是一旦我收到http请求,我只想在流中进一步处理这个问题。处理完成后,将响应流式输出回来。
import java.util.concurrent.TimeUnit

import akka.actor.{Actor, ActorRef, ActorSystem, Props}
import akka.http.scaladsl.Http
import akka.http.scaladsl.server.Directives.{
  get,
  onSuccess,
  pathEnd,
  pathPrefix
}
import akka.pattern.ask
import akka.stream.scaladsl.{Keep, Sink, Source, SourceQueueWithComplete}
import akka.stream.{ActorMaterializer, OverflowStrategy, QueueOfferResult}
import akka.util.Timeout
import akka.http.scaladsl.server.directives.RouteDirectives.complete
import com.typesafe.config.ConfigFactory

import scala.concurrent.ExecutionContext

object TestApp2 extends App {

  implicit val actorSystem = ActorSystem("test-system")
  implicit val mat = ActorMaterializer()
  implicit val ec = mat.executionContext

  val streamSource = Source
    .queue[(Message, ActorRef)](100, OverflowStrategy.dropNew)
    .map { p =>
      //do anything here
      println("I am processing request")
      ("It works", p._2)
    }
    .toMat(Sink.foreach { resp =>
      resp._2 ! resp._1
    })(Keep.left)
    .run()
  implicit val timeout = Timeout(
    10000,
    TimeUnit.MILLISECONDS
  )

  val internalActor =
    actorSystem.actorOf(Props(new InternalActor(streamSource)))
  Http(actorSystem)
    .bindAndHandle(
      getRoutes(internalActor),
      "0.0.0.0",
      8080
    )

  def getRoutes(
      internalActor: ActorRef
  )(implicit mat: ActorMaterializer, ec: ExecutionContext, timeout: Timeout) = {
    pathPrefix("healthcheck") {
      get {
        pathEnd {
          val responseReturned = internalActor ? Message()
          onSuccess(responseReturned) {
            case response: String =>
              complete(response)
            case _ => complete("error")
          }
        }
      }
    }
  }
}

case class Message()

class InternalActor(streamSource: SourceQueueWithComplete[(Message, ActorRef)])(
    implicit ec: ExecutionContext
) extends Actor {

  override def receive: Receive = {
    case m: Message =>
      val senderRef = sender()
      streamSource.offer((m, senderRef)).map {
        case QueueOfferResult.Enqueued => // do nothing for success
        case QueueOfferResult.Dropped => senderRef ! "error" // return error in case of backpressure 
        case QueueOfferResult.Failure(ex) => senderRef ! "error" // return error
        case QueueOfferResult.QueueClosed => senderRef ! "error" // return error
      }
  }
}