- 浏览: 2566888 次
- 性别:
- 来自: 成都
-
文章分类
最新评论
-
nation:
你好,在部署Mesos+Spark的运行环境时,出现一个现象, ...
Spark(4)Deal with Mesos -
sillycat:
AMAZON Relatedhttps://www.godad ...
AMAZON API Gateway(2)Client Side SSL with NGINX -
sillycat:
sudo usermod -aG docker ec2-use ...
Docker and VirtualBox(1)Set up Shared Disk for Virtual Box -
sillycat:
Every Half an Hour30 * * * * /u ...
Build Home NAS(3)Data Redundancy -
sillycat:
3 List the Cron Job I Have>c ...
Build Home NAS(3)Data Redundancy
Spray(2)spray-can
Prepare the Sample codes
>git clone https://github.com/spray/spray.git
>cd spray
And we can run both the 2 examples like this:
>sbt "project simple-http-client" run
>sbt "project simple-http-server" run
Everything runs fine, I will import the project into eclipse
>sbt update
>sbt eclipse
And I import these projects to my eclipse
simple-http-server
spray-can
spray-http
spray-io
spray-util
Go through the Online Documents to understand spray-can
Dependencies
spray-can depends on spray-io, spray-http, spray-util, akka-actor.
Create a learning project under easy sub system
>mkdir easyspray
>cd easyspray
>vi build.sbt
name := "easyspray"
organization := "com.sillycat"
version := "1.0"
scalaVersion := "2.10.0-RC1"
scalacOptions := Seq("-unchecked", "-deprecation", "-encoding", "utf8")
>sbt update
>sbt eclipse
Import my sample project into eclipse.
Installation
I already have a sbt project named easyspray, and I will install spray-can in that project.
make the resolvers in sbt as follow:
resolvers ++= Seq(
"sonatype releases" at "https://oss.sonatype.org/content/repositories/releases/",
"sonatype snapshots" at "https://oss.sonatype.org/content/repositories/snapshots/",
"typesafe repo" at "http://repo.typesafe.com/typesafe/releases/",
"spray repo" at "http://repo.spray.io/"
)
Add the sbt maven dependencies like this>
libraryDependencies ++= Seq(
"io.spray" % "spray-io" % "1.1-M4",
"io.spray" % "spray-http" % "1.1-M4",
"io.spray" % "spray-can" % "1.1-M4",
"io.spray" % "spray-util" % "1.1-M4",
"com.typesafe.akka" %% "akka-actor" % "2.1.0-RC1" cross CrossVersion.full,
"com.typesafe" % "config" % "1.0.0"
)
The most important configuration file is
reference.conf configure the server side configuration and database connection configuration.
HttpServer
Connection management
Message parsing and header separation
Timeout management
Response ordering
Basic Architecture
The spray-can HttpServer is implemented as an Akka actor, which talks to an underlying IOBridge and spawns new child actors for every new connection.
Just receive the request, and design in which case it will go, sender it to the handler when response the html.
def receive = {
case HttpRequest(GET, "/", _, _, _) =>
sender ! index
}
lazy val index = HttpResponse(
entity = HttpBody(`text/html`,
<html>
<body>
<h1>Say hello to <i>spray-can</i>!</h1>
<p>Defined resources:</p>
<ul>
<li><a href="/ping">/ping</a></li>
<li><a href="/stream">/stream</a></li>
<li><a href="/server-stats">/server-stats</a></li>
<li><a href="/io-stats">/io-stats</a></li>
<li><a href="/crash">/crash</a></li>
<li><a href="/timeout">/timeout</a></li>
<li><a href="/timeout/timeout">/timeout/timeout</a></li>
<li><a href="/stop">/stop</a></li>
</ul>
</body>
</html>.toString
)
)
Starting and Stopping
The HttpServer is a regular actor, it starts like this
// the handler actor replies to incoming HttpRequests
val handler = system.actorOf(Props[DemoService])
// create a new HttpServer using our handler and tell it where to bind to
newHttpServer(handler) ! Bind(interface = "localhost", port = 8080)
It stops like this:
context.system.scheduler.scheduleOnce(1 second span, new Runnable { def run() { context.system.shutdown() } })
I think probably this command statement will shutdown the actor context.system.shutdown(), other codes are just try to schedule that.
Message Protocol
A running HttpServer actor understands the following command messages.
Bind
Start listening for incoming connections on a particular port.
Unbind
Revert a previous Bind.
GetStats
ClearStats
…snip…
SprayCanHttpServerApp trait
I found that I am using the latest sample codes, so I need to change my version from 1.1-M4 to 1.1-M7. So the latest version make SprayCanHttpServerApp trait work.
package com.sillycat.easyspray.external
import spray.can.server.SprayCanHttpServerApp
import akka.actor.Props
object Server extends App with SprayCanHttpServerApp {
val handler = system.actorOf(Props[EasyRouter])
newHttpServer(handler) ! Bind(interface = "localhost", port = 8080)
}
package com.sillycat.easyspray.external
import akka.actor.Actor
import spray.http.HttpMethods
import spray.http.HttpRequest
import spray.http.HttpResponse
import spray.util.SprayActorLogging
import spray.http.HttpBody
import spray.http.MediaTypes._
class EasyRouter extends Actor with SprayActorLogging {
def receive = {
case HttpRequest(HttpMethods.GET, "/", _, _, _) =>
sender ! index
}
lazy val index = HttpResponse(
entity = HttpBody(`text/html`,
<html]]>
<body]]>
<h1]]>Welcome Page</h1]]>
</body]]>
</html]]>.toString))
}
HttpClient
…snip…
HttpDialog
…snip…
Examples
Example for stop the server and get status from the server:
package com.sillycat.easyspray.external
import scala.concurrent.duration._
import akka.pattern.ask
import akka.util.Timeout
import akka.actor._
import spray.io.{IOBridge, IOExtension}
import spray.can.server.HttpServer
import spray.util._
import spray.http._
import HttpMethods._
import MediaTypes._
class EasyRouter extends Actor with SprayActorLogging {
implicit val timeout: Timeout = Duration(1, "sec")
def receive = {
case HttpRequest(HttpMethods.GET, "/", _, _, _) =>
sender ! index
case HttpRequest(HttpMethods.GET, "/stop", _, _, _) =>
sender ! HttpResponse(entity = "Shutting down in 1 second ...")
context.system.scheduler.scheduleOnce(1 second span, new Runnable { def run() { context.system.shutdown() } })
case HttpRequest(GET, "/server-stats", _, _, _) =>
val client = sender
(context.actorFor("../http-server") ? HttpServer.GetStats).onSuccess {
case x: HttpServer.Stats => client ! statsPresentation(x)
}
case HttpRequest(GET, "/io-stats", _, _, _) =>
val client = sender
(IOExtension(context.system).ioBridge() ? IOBridge.GetStats).onSuccess {
case IOBridge.StatsMap(map) => client ! statsPresentation(map)
}
}
lazy val index = HttpResponse(
entity = HttpBody(`text/html`,
<html>
<body>
<h1>Welcome Page</h1>
<ul>
<li><a href="/stop">Stop The Server</a></li>
<li><a href="/server-stats">Server Status</a></li>
<li><a href="/io-stats">IO Status</a></li>
</ul>
</body>
</html>.toString))
def statsPresentation(s: HttpServer.Stats) = HttpResponse(
entity = HttpBody(`text/html`,
<html>
<body>
<h1>HttpServer Stats</h1>
<table>
<tr><td>uptime:</td><td]]>{s.uptime.formatHMS}</td></tr>
<tr><td>totalRequests:</td><td>{s.totalRequests}</td></tr>
<tr><td>openRequests:</td><td>{s.openRequests}</td></tr>
<tr><td>maxOpenRequests:</td><td>{s.maxOpenRequests}</td></tr>
<tr><td>totalConnections:</td><td>{s.totalConnections}</td></tr>
<tr><td>openConnections:</td><td>{s.openConnections}</td></tr>
<tr><td>maxOpenConnections:</td><td>{s.maxOpenConnections}</td></tr>
<tr><td>requestTimeouts:</td><td>{s.requestTimeouts}</td></tr>
<tr><td>idleTimeouts:</td><td>{s.idleTimeouts}</td></tr>
</table>
</body>
</html>.toString
)
)
def statsPresentation(map: Map[ActorRef, IOBridge.Stats]) = HttpResponse(
entity = HttpBody(`text/html`,
<html>
<body]]>
<h1]]>IOBridge Stats</h1]]>
<table]]>
{
def extractData(t: (ActorRef, IOBridge.Stats)) = t._1.path.elements.last :: t._2.productIterator.toList
val data = map.toSeq.map(extractData).sortBy(_.head.toString).transpose
valheaders = Seq("IOBridge", "uptime", "bytesRead", "bytesWritten", "connectionsOpened", "commandsExecuted")
headers.zip(data).map { case (header, items) =>
<tr><td]]>{header}:</td]]>{items.map(x => <td]]>{x}</td]]>)}</tr]]>
}
}
</table]]>
</body]]>
</html]]>.toString
)
)
}
References:
http://spray.io/documentation/spray-routing/
http://spray.io/documentation/spray-can/#spray-can
http://sillycat.iteye.com/blog/1744082
http://sillycat.iteye.com/blog/1750374
http://www.scala-sbt.org/release/docs/Getting-Started/index.html
http://spray.io/project-info/maven-repository/
Prepare the Sample codes
>git clone https://github.com/spray/spray.git
>cd spray
And we can run both the 2 examples like this:
>sbt "project simple-http-client" run
>sbt "project simple-http-server" run
Everything runs fine, I will import the project into eclipse
>sbt update
>sbt eclipse
And I import these projects to my eclipse
simple-http-server
spray-can
spray-http
spray-io
spray-util
Go through the Online Documents to understand spray-can
Dependencies
spray-can depends on spray-io, spray-http, spray-util, akka-actor.
Create a learning project under easy sub system
>mkdir easyspray
>cd easyspray
>vi build.sbt
name := "easyspray"
organization := "com.sillycat"
version := "1.0"
scalaVersion := "2.10.0-RC1"
scalacOptions := Seq("-unchecked", "-deprecation", "-encoding", "utf8")
>sbt update
>sbt eclipse
Import my sample project into eclipse.
Installation
I already have a sbt project named easyspray, and I will install spray-can in that project.
make the resolvers in sbt as follow:
resolvers ++= Seq(
"sonatype releases" at "https://oss.sonatype.org/content/repositories/releases/",
"sonatype snapshots" at "https://oss.sonatype.org/content/repositories/snapshots/",
"typesafe repo" at "http://repo.typesafe.com/typesafe/releases/",
"spray repo" at "http://repo.spray.io/"
)
Add the sbt maven dependencies like this>
libraryDependencies ++= Seq(
"io.spray" % "spray-io" % "1.1-M4",
"io.spray" % "spray-http" % "1.1-M4",
"io.spray" % "spray-can" % "1.1-M4",
"io.spray" % "spray-util" % "1.1-M4",
"com.typesafe.akka" %% "akka-actor" % "2.1.0-RC1" cross CrossVersion.full,
"com.typesafe" % "config" % "1.0.0"
)
The most important configuration file is
reference.conf configure the server side configuration and database connection configuration.
HttpServer
Connection management
Message parsing and header separation
Timeout management
Response ordering
Basic Architecture
The spray-can HttpServer is implemented as an Akka actor, which talks to an underlying IOBridge and spawns new child actors for every new connection.
Just receive the request, and design in which case it will go, sender it to the handler when response the html.
def receive = {
case HttpRequest(GET, "/", _, _, _) =>
sender ! index
}
lazy val index = HttpResponse(
entity = HttpBody(`text/html`,
<html>
<body>
<h1>Say hello to <i>spray-can</i>!</h1>
<p>Defined resources:</p>
<ul>
<li><a href="/ping">/ping</a></li>
<li><a href="/stream">/stream</a></li>
<li><a href="/server-stats">/server-stats</a></li>
<li><a href="/io-stats">/io-stats</a></li>
<li><a href="/crash">/crash</a></li>
<li><a href="/timeout">/timeout</a></li>
<li><a href="/timeout/timeout">/timeout/timeout</a></li>
<li><a href="/stop">/stop</a></li>
</ul>
</body>
</html>.toString
)
)
Starting and Stopping
The HttpServer is a regular actor, it starts like this
// the handler actor replies to incoming HttpRequests
val handler = system.actorOf(Props[DemoService])
// create a new HttpServer using our handler and tell it where to bind to
newHttpServer(handler) ! Bind(interface = "localhost", port = 8080)
It stops like this:
context.system.scheduler.scheduleOnce(1 second span, new Runnable { def run() { context.system.shutdown() } })
I think probably this command statement will shutdown the actor context.system.shutdown(), other codes are just try to schedule that.
Message Protocol
A running HttpServer actor understands the following command messages.
Bind
Start listening for incoming connections on a particular port.
Unbind
Revert a previous Bind.
GetStats
ClearStats
…snip…
SprayCanHttpServerApp trait
I found that I am using the latest sample codes, so I need to change my version from 1.1-M4 to 1.1-M7. So the latest version make SprayCanHttpServerApp trait work.
package com.sillycat.easyspray.external
import spray.can.server.SprayCanHttpServerApp
import akka.actor.Props
object Server extends App with SprayCanHttpServerApp {
val handler = system.actorOf(Props[EasyRouter])
newHttpServer(handler) ! Bind(interface = "localhost", port = 8080)
}
package com.sillycat.easyspray.external
import akka.actor.Actor
import spray.http.HttpMethods
import spray.http.HttpRequest
import spray.http.HttpResponse
import spray.util.SprayActorLogging
import spray.http.HttpBody
import spray.http.MediaTypes._
class EasyRouter extends Actor with SprayActorLogging {
def receive = {
case HttpRequest(HttpMethods.GET, "/", _, _, _) =>
sender ! index
}
lazy val index = HttpResponse(
entity = HttpBody(`text/html`,
<html]]>
<body]]>
<h1]]>Welcome Page</h1]]>
</body]]>
</html]]>.toString))
}
HttpClient
…snip…
HttpDialog
…snip…
Examples
Example for stop the server and get status from the server:
package com.sillycat.easyspray.external
import scala.concurrent.duration._
import akka.pattern.ask
import akka.util.Timeout
import akka.actor._
import spray.io.{IOBridge, IOExtension}
import spray.can.server.HttpServer
import spray.util._
import spray.http._
import HttpMethods._
import MediaTypes._
class EasyRouter extends Actor with SprayActorLogging {
implicit val timeout: Timeout = Duration(1, "sec")
def receive = {
case HttpRequest(HttpMethods.GET, "/", _, _, _) =>
sender ! index
case HttpRequest(HttpMethods.GET, "/stop", _, _, _) =>
sender ! HttpResponse(entity = "Shutting down in 1 second ...")
context.system.scheduler.scheduleOnce(1 second span, new Runnable { def run() { context.system.shutdown() } })
case HttpRequest(GET, "/server-stats", _, _, _) =>
val client = sender
(context.actorFor("../http-server") ? HttpServer.GetStats).onSuccess {
case x: HttpServer.Stats => client ! statsPresentation(x)
}
case HttpRequest(GET, "/io-stats", _, _, _) =>
val client = sender
(IOExtension(context.system).ioBridge() ? IOBridge.GetStats).onSuccess {
case IOBridge.StatsMap(map) => client ! statsPresentation(map)
}
}
lazy val index = HttpResponse(
entity = HttpBody(`text/html`,
<html>
<body>
<h1>Welcome Page</h1>
<ul>
<li><a href="/stop">Stop The Server</a></li>
<li><a href="/server-stats">Server Status</a></li>
<li><a href="/io-stats">IO Status</a></li>
</ul>
</body>
</html>.toString))
def statsPresentation(s: HttpServer.Stats) = HttpResponse(
entity = HttpBody(`text/html`,
<html>
<body>
<h1>HttpServer Stats</h1>
<table>
<tr><td>uptime:</td><td]]>{s.uptime.formatHMS}</td></tr>
<tr><td>totalRequests:</td><td>{s.totalRequests}</td></tr>
<tr><td>openRequests:</td><td>{s.openRequests}</td></tr>
<tr><td>maxOpenRequests:</td><td>{s.maxOpenRequests}</td></tr>
<tr><td>totalConnections:</td><td>{s.totalConnections}</td></tr>
<tr><td>openConnections:</td><td>{s.openConnections}</td></tr>
<tr><td>maxOpenConnections:</td><td>{s.maxOpenConnections}</td></tr>
<tr><td>requestTimeouts:</td><td>{s.requestTimeouts}</td></tr>
<tr><td>idleTimeouts:</td><td>{s.idleTimeouts}</td></tr>
</table>
</body>
</html>.toString
)
)
def statsPresentation(map: Map[ActorRef, IOBridge.Stats]) = HttpResponse(
entity = HttpBody(`text/html`,
<html>
<body]]>
<h1]]>IOBridge Stats</h1]]>
<table]]>
{
def extractData(t: (ActorRef, IOBridge.Stats)) = t._1.path.elements.last :: t._2.productIterator.toList
val data = map.toSeq.map(extractData).sortBy(_.head.toString).transpose
valheaders = Seq("IOBridge", "uptime", "bytesRead", "bytesWritten", "connectionsOpened", "commandsExecuted")
headers.zip(data).map { case (header, items) =>
<tr><td]]>{header}:</td]]>{items.map(x => <td]]>{x}</td]]>)}</tr]]>
}
}
</table]]>
</body]]>
</html]]>.toString
)
)
}
References:
http://spray.io/documentation/spray-routing/
http://spray.io/documentation/spray-can/#spray-can
http://sillycat.iteye.com/blog/1744082
http://sillycat.iteye.com/blog/1750374
http://www.scala-sbt.org/release/docs/Getting-Started/index.html
http://spray.io/project-info/maven-repository/
发表评论
-
Update Site will come soon
2021-06-02 04:10 1694I am still keep notes my tech n ... -
Hadoop Docker 2019 Version 3.2.1
2019-12-10 07:39 310Hadoop Docker 2019 Version 3.2. ... -
Nginx and Proxy 2019(1)Nginx Enable Lua and Parse JSON
2019-12-03 04:17 472Nginx and Proxy 2019(1)Nginx En ... -
Data Solution 2019(13)Docker Zeppelin Notebook and Memory Configuration
2019-11-09 07:15 316Data Solution 2019(13)Docker Ze ... -
Data Solution 2019(10)Spark Cluster Solution with Zeppelin
2019-10-29 08:37 265Data Solution 2019(10)Spark Clu ... -
AMAZON Kinesis Firehose 2019(1)Firehose Buffer to S3
2019-10-01 10:15 341AMAZON Kinesis Firehose 2019(1) ... -
Rancher and k8s 2019(3)Clean Installation on CentOS7
2019-09-19 23:25 336Rancher and k8s 2019(3)Clean In ... -
Pacemaker 2019(1)Introduction and Installation on CentOS7
2019-09-11 05:48 360Pacemaker 2019(1)Introduction a ... -
Crontab-UI installation and Introduction
2019-08-30 05:54 472Crontab-UI installation and Int ... -
Spiderkeeper 2019(1)Installation and Introduction
2019-08-29 06:49 534Spiderkeeper 2019(1)Installatio ... -
Supervisor 2019(2)Ubuntu and Multiple Services
2019-08-19 10:53 387Supervisor 2019(2)Ubuntu and Mu ... -
Supervisor 2019(1)CentOS 7
2019-08-19 09:33 343Supervisor 2019(1)CentOS 7 Ins ... -
Redis Cluster 2019(3)Redis Cluster on CentOS
2019-08-17 04:07 384Redis Cluster 2019(3)Redis Clus ... -
Amazon Lambda and Version Limit
2019-08-02 01:42 450Amazon Lambda and Version Limit ... -
MySQL HA Solution 2019(1)Master Slave on MySQL 5.7
2019-07-27 22:26 551MySQL HA Solution 2019(1)Master ... -
RabbitMQ Cluster 2019(2)Cluster HA and Proxy
2019-07-11 12:41 475RabbitMQ Cluster 2019(2)Cluster ... -
Running Zeppelin with Nginx Authentication
2019-05-25 21:35 334Running Zeppelin with Nginx Aut ... -
Running Zeppelin with Nginx Authentication
2019-05-25 21:34 335Running Zeppelin with Nginx Aut ... -
ElasticSearch(3)Version Upgrade and Cluster
2019-05-20 05:00 340ElasticSearch(3)Version Upgrade ... -
Jetty Server and Cookie Domain Name
2019-04-28 23:59 420Jetty Server and Cookie Domain ...
相关推荐
在实际使用中,`spray-template-on_spray-can_1.3`可能是一个包含spray-template特定版本的库,用于与spray-can 1.3版兼容。这个压缩包文件可能包含了以下内容: - `spray-template`的Scala源码或编译后的JAR文件,...
Docker-Spray-HttpServer概括Docker Hub 中的仓库名称: 该存储库包含 Dockerized ,通过自动构建机制发布到公共 。 该应用程序主要用作评估 + 框架性能的基准目标。配置此 docker 映像包含以下软件堆栈: 操作系统...
喷雾罐,Scala 2.9 + Akka 2.0 +喷雾1.0( on_spray-can_1.0分支) 喷雾罐,Scala 2.10 + Akka 2.1 +喷雾1.1( on_spray-can_1.1分支) 喷雾罐,Scala 2.10 + Akka 2.2 +喷雾1.2( on_spray-can_1.2分支) 喷雾罐...
它包括两个主要部分:一是spray-can,提供了一个异步非阻塞的HTTP服务器容器;二是spray-routing,提供了声明式路由构造器,使构建RESTful服务变得简单直观。在Scala-Spray-Demo中,Spray框架被用来构建RESTful API...
粒子系统在计算机图形学领域扮演着至关重要的角色,它们能够实时地创造出生动逼真的自然现象,例如海洋的浪花、火光、烟雾、星系等。这背后的关键技术,便是通过模拟无数个微小粒子的行为来构建复杂的视觉效果。...
在使用这个项目时,开发者需要对Java、Netty、Socket.IO以及Scala(因为spray-can是用Scala编写的)有一定的了解。首先,要确保环境中已经安装了JDK和Scala,然后通过Git克隆项目到本地,使用Maven或Gradle等构建...
3. **spray框架**:包括spray-can(HTTP服务器组件)、spray-routing(构建路由的DSL)、spray-client(HTTP客户端)等,它们共同为创建高效的HTTP服务提供了一整套解决方案。 4. **swagger规范**:Swagger定义了一...
Spray doesn't have friendly API for Java, the spray.japi package provides a few of Helpers and Factories to help Java developers to construct spray entities easily. Validation provides ...
尽管他并非硬件或汽车专家,但他的背景包括JIT-SPRAY、shellcodes、ROP、BoF和Web安全技术,这些知识现在被应用于汽车行业。他参与创建的#CarPWN社区聚集了一群来自俄罗斯的汽车黑客和爱好者,他们热衷于研究汽车...
2. **AKKA框架**:AKKA是基于Actor模型的并发处理库,由Lightbend公司(前身为Typesafe)开发。在CJSpider中,AKKA用于处理分布式系统中的通信问题。Actor模型允许并发执行,每个Actor都有自己的状态和邮箱,通过...
5. **spray-can和akka-http的集成**:kebs库可以与spray-can和akka-http这两个流行的Scala HTTP服务器库无缝集成,简化了HTTP请求处理的实现。 6. **类型安全的属性验证**:kebs还提供了属性验证的功能,允许开发者...
However, creating an app in Scala can get a little tricky because of the complexity. This book will help you dive straight into app development by creating a real, reactive, and functional ...
5. **喷枪(Spray Can)**: - 喷枪工具通常模仿绘画中的喷漆效果,需要创建一个自定义的绘图算法。可以使用`Graphics`的`DrawLines()`方法或`DrawCurve()`方法,结合一定的随机性和密度来实现。 6. **曲线绘制**...
- **spray-can**: 是spray工具集的一部分,用于构建高性能的HTTP服务器和客户端,基于Akka。 - **Sttp**: 一个现代、可扩展的HTTP客户端库,支持多种后端,如Java的HttpURLConnection或Akka HTTP。 - **Finch**: ...
Based on the recent oceanographic research, can simulate hundreds of thousands of waves with excellent foam and particle spray simulation adding a lot of realism to storm and windy weather. UWS is ...
Based on the synchrotron radiation X-ray tomography technique, the 3D digital models of nozzle tips can be constructed. A new automatic method is presented to reveal the inlet structures accor