我并不是说播放禁用PlayNettyServer并启用AkkaHttpServer的方式,使用以下文档中描述的AkkaHttpServer:
lazy val root = (project in file("."))
.enablePlugins(PlayScala, PlayAkkaHttpServer)
.disablePlugins(PlayNettyServer)
Run Code Online (Sandbox Code Playgroud)
我的意思是利用play框架的依赖注入和play-slick等其他工具,并直接在代码中使用akka-http:
class AppInitiation @Inject()(implicit val system: ActorSystem, configuration: Configuration) {
implicit val materializer = ActorMaterializer()
implicit val timeout: Timeout = 5 seconds
val logger = Logger("Server")
val milkywayPath = path(Segment ~ RestPath)
val methods = get | put | post | delete
val gatewayExceptionHandler = ExceptionHandler {
case e: AskTimeoutException =>
complete(HttpResponse(InternalServerError, Nil, "Ask timeout!"))
case e: Exception =>
logger.error("unknown error", e)
complete(HttpResponse(InternalServerError, Nil, "Unknown error! Please contact administratro!")) …Run Code Online (Sandbox Code Playgroud) 我正在使用遗留的HTTP API(我无法更改),它在正文中以JSON响应,但是给出了一个Content-Type: text/plain; charset=utf-8标题.
我试图将HTTP主体解组为JSON,但我得到以下异常: akka.http.scaladsl.unmarshalling.Unmarshaller$UnsupportedContentTypeException: Unsupported Content-Type, supported: application/json
我的代码看起来像这样:
import spray.json.DefaultJsonProtocol
import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._
import akka.http.scaladsl.unmarshalling._
case class ResponseBody(status: String, error_msg: String)
object ResponseBodyJsonProtocol extends DefaultJsonProtocol {
implicit val responseBodyFormat = jsonFormat2(ResponseBody)
}
def parse(entity: HttpEntity): Future[ResponseBody] = {
implicit val materializer: Materializer = ActorMaterializer()
import ResponseBodyJsonProtocol._
Unmarshal[HttpEntity](entity).to[ResponseBody]
}
Run Code Online (Sandbox Code Playgroud)
HTTP响应示例如下所示:
HTTP/1.1 200 OK
Cache-Control: private
Content-Encoding: gzip
Content-Length: 161
Content-Type: text/plain; charset=utf-8
Date: Wed, 16 Dec 2015 18:15:14 GMT
Server: Microsoft-IIS/7.5
Vary: Accept-Encoding
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET …Run Code Online (Sandbox Code Playgroud) 我使用akka指令来匹配特定的路径模式:
/item/quantity
Run Code Online (Sandbox Code Playgroud)
例子就是
/apples/100
/bananas/200
Run Code Online (Sandbox Code Playgroud)
可能的项目(例如"苹果","香蕉",......)事先不知道,因此path不能选择使用项目进行硬编码.
但是,我找不到提取路径头部的PathMatcher.我正在寻找形式的东西
val route =
get {
path(PathHeadAsString) { item : String =>
path(IntNumber) { qty : Int =>
complete(s"item: $item quantity: $qty")
} ~ complete("no quantity specified")
} ~ complete("no item specified")
}
Run Code Online (Sandbox Code Playgroud)
哪里
Get("/apples/100") ~> route ~> check {
responseAs[String] shouldEqual "item: apples quantity: 100"
}
Run Code Online (Sandbox Code Playgroud)
有没有办法提取路径的第一段?
path(segment)如果数量在路径中,匹配器将不匹配.
我显然可以使用path(segments)获取List[String]路径元素,但我必须手动提取列表头和列表尾部,这似乎是不优雅的.
提前感谢您的考虑和回应.
如何在存储变量中保持客户端(Web)连接,然后在需要时将传出消息发送到客户端(Web)?
我已经有了一些简单的代码,一旦服务器从客户端接收到消息,就可以将消息推回客户端。如何为外发邮件部分修改以下代码?
implicit val actorSystem = ActorSystem("akka-system")
implicit val flowMaterializer = ActorMaterializer()
implicit val executionContext = actorSystem.dispatcher
val ip = "127.0.0.1"
val port = 32000
val route = get {
pathEndOrSingleSlash {
complete("Welcome to websocket server")
}
} ~
path("hello") {
get {
handleWebSocketMessages(echoService)
}
}
def sendMessageToClient(msg : String) {
// *** How to implement this?
// *** How to save the client connection when it is first connected?
// Then how to send message to this connection?
} …Run Code Online (Sandbox Code Playgroud) 使用HTTP阿卡绑定到一个端口,然后将传入的连接是很容易的给出的文档.
未解决的一个问题是如何为不同的路由绑定多个端口.如果我有多个规格:
val route1 : Flow[HttpRequest, HttpResponse,_] = ???
val interface1 : String = ???
val port1 : Int = ???
val route2 : Flow[HttpRequest, HttpResponse,_] = ???
val interface2 : String = ???
val port2 : Int = ???
Run Code Online (Sandbox Code Playgroud)
这些应该绑一个HttpExt吗?
implicit val actorSystem : akka.actor.ActorSystem = ???
val httpExt = akka.http.scaladsl.Http()
httpExt.bindAndHandle(route1, interface1, port1)
httpExt.bindAndHandle(route2, interface2, port2)
Run Code Online (Sandbox Code Playgroud)
或者,HttpExt每个绑定是否应该使用不同的?
Http().bindAndHandle(route1, interface1, port1)
Http().bindAndHandle(route2, interface2, port2)
Run Code Online (Sandbox Code Playgroud)
如果其中一个有效,那么使用一种方法对另一种方法有什么影响吗?
提前感谢您的审核和回复.
我正在尝试编写一个Akka HTTP微服务(akka版本2.4.11,Scala版本2.11.8,这两个版本在编写时都是最新版本),它们知道客户端服务的IP(即远程地址),我无法得到这个上班.
我可以创建并运行一个名为"你好!"的服务.使用这样的路线:
val routeHello: Route = path("SayHello") {
get {
entity(as[String]) {
body => complete {
HttpResponse(entity = HttpEntity("Hello!"))
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
我已经构建了一个与上面相似的路由,它被扩展,以便它知道客户端的IP地址.
我注意到我需要编辑application.conf文件并设置'remote-address-header = on'以启用添加包含Remote-Address客户端(远程)IP地址的标头.如果需要,我已经这样做了.
这是路线:
val routeHelloIp: Route = path("SayHelloIp") {
get {
// extractClientIp appears to be working as a filter
// instead of an extractor - why?
extractClientIp {
clientIp => {
entity(as[String]) {
body => complete {
HttpResponse(entity = HttpEntity("Hello!"))
}
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
但是,当我运行此路由时,我收到一条消息"无法找到所请求的资源.".
看起来我在上面的例子中得到了Akka-http DSL语法糖错误.如果你能把我放在正确的道路上,我将不胜感激!
编辑:
我已经尝试了以下程序来回应Ramon的有用答案.不幸的是它没有编译,我无法看到我需要做什么才能使它编译. …
基本上我想允许用户从服务器下载csv文件.假设服务器上已存在CSV文件.通过GET/export公开API端点.如何将文件从Akka HTTP服务器流式传输到客户端?这就是我到目前为止......
服务:
def export(): Future[IOResult] = {
FileIO.fromPath(Paths.get("file.csv"))
.to(Sink.ignore)
.run()
}
Run Code Online (Sandbox Code Playgroud)
路线:
pathPrefix("export") {
pathEndOrSingleSlash {
get {
complete(HttpEntity(ContentTypes.`text/csv`, export())
}
}
}
Run Code Online (Sandbox Code Playgroud) 我有一个从客户端到api服务的websocket连接,然后从API服务连接到其他服务.现在默认情况下连接超时(即在Web套接字连接上没有消息/通信时)是1分钟,我发现设置增加它,即使用akka.http.client.idle-timeout = 300s和akka.http.server .idle-timeout = 300s.
但在我的情况下,这些设置在本地工作,超时增加(即在我的电脑上本地运行服务时),但不是当我在EC2上部署服务制作docker图像时.
所以请任何人都能告诉我为什么它的表现如此?
问题是为什么Playframework团队决定从Netty迁移到Akka?它在性能意义上更有效吗?
我有一个Web服务器,它接受传入的Websocket连接,并在Scala中用akka http实现。但是,我一直在观察应用程序的内存使用量的单调增加。经过长时间的挖掘,我发现每个内部连接都会创建一些内部Akka对象,但是在客户端断开连接后它们不会被清除。特别是此类:akka.stream.impl.fusing.ActorGraphInterpreter。每个连接都会创建一个新的此类对象。我曾经jmap计算对象的数量,下面提供了命令。我不确定在这里是否做错了什么。任何建议将不胜感激。
我有一个超级简单的echo websocket服务器来复制此观察结果:
package samples
import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.model.ws.{Message, TextMessage}
import akka.http.scaladsl.server.Directives._
import akka.stream.ActorMaterializer
import akka.stream.scaladsl.{Flow, Source}
import scala.concurrent.ExecutionContext.Implicits.global
import scala.io.StdIn
object AkkaWsExample {
implicit val system = ActorSystem()
implicit val materializer = ActorMaterializer()
private val greeterWebSocketService = {
Flow[Message]
.collect {
case tm: TextMessage =>
println(s"Received $tm")
TextMessage(Source.single("Hello ") ++ tm.textStream)
}
}
def main(args: Array[String]): Unit = {
//#websocket-routing
val route =
path("greeter") {
get {
handleWebSocketMessages(greeterWebSocketService)
}
}
val bindingFuture …Run Code Online (Sandbox Code Playgroud)