BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
Akka HTTP Intro
1. Introduction to Akka HTTP
Building scalable rest service in Scala
https://github.com/shashankgowdal/introduction-to-akkahttp
2. ● Shashank L
● Senior Software engineer at Tellius
● Part time big data consultant and trainer
at datamantra.io
● www.shashankgowda.com
3. Agenda
● Motivation
● Akka, Reactive streams
● Akka Http
● Akka Http High level API
● Testing
● Additional functionality
● Working with files
● Websockets
● Akka Http with Spark
4. Scala frameworks to build REST API
● Play/Lift
○ Full stack web framework
● Scalatra
○ Lightweight but requires a application container for
deployment
● Spray
○ Lightweight and robust as it's asynchronous and built on top
of Actors
● Akka HTTP
○ Next version of Spray framework
5. Why Akka HTTP
● Its 2.0 version of Spray.io
● Internals of Spray have been rewritten to use
Reactive streams
● Reactive streams idea gel well with earlier ideas of
Spray
● Multiple level API
6. Akka
● Toolkit and runtime for building highly concurrent,
distributed, and fault tolerant applications on the JVM
● Uses message passing based concurrency model
● Written in Scala
● Scale up or out
● Program at higher level
● Distributable by design
● Message passing is built on top of AkkaActor model
7. Akka actor
● Receives message and takes action to handle them
● Consists of
○ Behaviour
○ State
○ Mailbox
8. Reactive streams
● Asynchronous
● Stream processing
● Back-pressured
● Interoperability
● Few Implementations
○ Akka Streams
○ RxJava
○ Play
○ Kafka
● Spark streaming with Kafka receiver
9. Akka streams
● Akka’s implementation of Reactive streams
● DSL for building a complete stream
● Higher level abstraction over the actor model
● Stream inputs and outputs are typesafe
● Internally uses Actor to implement Reactive stream
properties
11. Source, Flow and Sink
com.shashank.akkahttp.IntroductionToStream
implicit val sys = ActorSystem("IntroductionToStream")
implicit val mat:Materializer = ActorMaterializer()
val source = Source(List(1, 2, 3))
val flow = Flow[Int].map(_.toString)
val sink = Sink.foreach(println)
val runnableGraph = source via flow to sink
runnableGraph.run()
12. HTTP server with Akka streams
HTTPServer as a:
Flow[HttpRequest, HttpResponse]
Socket
input
Bytes ⇒
HttpRequest
HttpRequest ⇒
HttpResponse
HttpResponse
⇒ Bytes
Socket
Sink
13. Akka Http server using Flow
implicit val sys = ActorSystem("IntroductionToAkkaHttp")
implicit val mat:Materializer = ActorMaterializer()
val requestResponseFlow = Flow.fromFunction[HttpRequest, HttpResponse]( request => {
println(request.toString)
HttpResponse(StatusCodes.OK, entity = "Hello!")
})
Http().bindAndHandle(requestResponseFlow, "localhost", 8080)
com.shashank.akkahttp.basic.serving.StreamsServing
14. Akka HTTP
● Part of Akka project
● HTTP toolkit (Client and Server)
● On top of akka-actor and akka-streams
● Multiple levels of abstraction - Open API
● Scalable, Max throughput, acceptable latency
● APIs in both Scala and Java
15. Akka HTTP - Implementation
● Fully asynchronous and nonblocking
● Focused on higher level API
● Lightweight
● Modular
● Testable
● Based on spray.io
● Better streaming REST functionality support
18. Akka HTTP - Parts
● akka-http-core
○ low-level server & client side HTTP implementation
● akka-http
○ high-level API : DSL, (un)marshalling, (de)compression
● akka-http-testkit
○ Utilities for testing server-side implementation
● akka-http-spray-json
○ (de)serialization from/to JSON with spray-json
● akka-http-xml
○ (de)serialization from/to XML with scala-xml
19. HTTP model
● Fully immutable, case-class based
● Abstraction for most HTTP things (Types!)
● Little logic inside
● Lots of predefined types - media type, status code,
encodings etc
● Efficient parsing and rendering
● Clients/Connected services should obey the standard
20. HTTP model - Examples
case class HttpRequest(method: HttpMethod = HttpMethods.GET,
uri: Uri = Uri./,
headers: immutable.Seq[HttpHeader] = Nil,
entity: RequestEntity = HttpEntity.Empty,
protocol: HttpProtocol = HttpProtocols.`HTTP/1.1`)
case class HttpResponse(status: StatusCode = StatusCodes.OK,
headers: immutable.Seq[HttpHeader] = Nil,
entity: ResponseEntity = HttpEntity.Empty,
protocol: HttpProtocol = HttpProtocols.`HTTP/1.1`)
case class Uri(scheme: String,
authority: Authority,
path: Path,
rawQueryString: Option[String],
fragment: Option[String])
21. HTTP model - Examples
object ContentTypes {
val `application/json` = ContentType(MediaTypes.`application/json`)
val `application/octet-stream` = ContentType(MediaTypes.`application/octet-stream`)
val `text/plain(UTF-8)` = MediaTypes.`text/plain` withCharset HttpCharsets.`UTF-8`
val `text/html(UTF-8)` = MediaTypes.`text/html` withCharset HttpCharsets.`UTF-8`
val `text/xml(UTF-8)` = MediaTypes.`text/xml` withCharset HttpCharsets.`UTF-8`
val `text/csv(UTF-8)` = MediaTypes.`text/csv` withCharset HttpCharsets.`UTF-8`
val NoContentType = ContentType(MediaTypes.NoMediaType)
}
val `US-ASCII` = register("US-ASCII")("iso-ir-6", "ANSI_X3.4-1968", "ANSI_X3.4-1986", "ISO_646.irv:1991", "ASCII", "ISO646-US",
"us", "IBM367", "cp367", "csASCII")
val `ISO-8859-1` = register("ISO-8859-1")("iso-ir-100", "ISO_8859-1", "latin1", "l1", "IBM819", "CP819", "csISOLatin1")
val `UTF-8` = register("UTF-8")("UTF8")
val `UTF-16` = register("UTF-16")("UTF16")
val `UTF-16BE` = register("UTF-16BE")()
val `UTF-16LE` = register("UTF-16LE")()
22. HTTP server functional way
● Low level HTTP API
● Provided by akka-http-core-module
implicit val sys = ActorSystem("IntroductionToAkkaHttp")
implicit val mat:Materializer = ActorMaterializer()
val handler :(HttpRequest => HttpResponse) = {
case HttpRequest(HttpMethods.GET, Uri.Path("/ping"), _, _, _) =>
HttpResponse(StatusCodes.OK, entity = "pong!")
case r =>
HttpResponse(status = StatusCodes.BadRequest)
}
Http().bindAndHandleSync(handler, "localhost", 8080)
com.shashank.akkahttp.basic.serving.FunctionalServing
24. HTTP Server Nice way!
● Low level API becomes uneasy to handle when we
need large number of routes
● For this we should use higher level API by akka-http
● Route using Routing DSL
implicit val sys = ActorSystem("IntroductionToAkkaHttp")
implicit val mat:Materializer = ActorMaterializer()
val routes: Route = ???
Http(sys).bindAndHandle(route, "localhost", 8090)
25. Routing DSL
● Internal domain specific language for routing
● How most services are actually written
● Layer to the application
● Type safe but flexible
● Not just routing - behaviour definition
● Very composable
● Fun, powerful and looks clean
26. Routing DSL - Example
val route =
path("welcome"){
get{
complete {
"welcome to rest service"
}
}
} ~
path("demo"){
get{
complete {
"welcome to demonstration"
}
}
}
Http().bindAndHandle(route, "localhost", 8090)
com.shashank.akkahttp.basic.routing.RoutingDSL
27. Directives
● A Directive is a small building block used for creating
routes.
● There are some predefined directives( get, post,
complete etc.)
● We can also define our custom directives.
● Roles: extracting, transforming request or response,
filtering, side-effecting
● ~136 predefined directives
28. Rejections
● Produced by directives
● Travel down the routing structure
● EmptyRejection is thrown when no route completes
● Can be extended
● Can be cancelled
● Handling rejection = transforming it to response
● Ex. MethodRejection, AuthorizationFailedRejection,
MissingCookieRejection, MissingQueryParamRejection
29. Rejections
● ~ operator connects two routes in a way that allows a
second route to get a go at a request if the first route
"rejected" it.
path("order") {
get {
complete("Received GET")
} ~
post {
complete("Received POST")
}
}
com.shashank.akkahttp.basic.routing.Rejection
30. Failures
● Are triggered by exceptions
● Travel up the routing structure
● Can be handled by handleExceptions directive or
top-level ExceptionHandler
● Can be used to simplify the flow for validation
purpose
com.shashank.akkahttp.basic.routing.Failure
32. ● Simple and straightforward
● Allows to assert responses returned for given
requests
● Integrates well with Scalatest
Get("/ping") ~> route ~> check{
status === OK
entity.as[String] === "It Works!"
}
com.shashank.akkahttp.basic.routing.TestKit
Testkit
34. Query parameters
def parameters(param: <ParamDef[T]>): Directive1[T]
● Mandatory parameters
● Optional parameters
● Parameters with required value
● Deserialized parameter
● Repeated parameter
● Deserialized parameter into Case class
35. (Un)Marshalling
● Marshalling - high level → low (wire) level
● Unmarshalling - low (wire) level → high level
● Many predefined (un) marshallers are available
● Extensible
● JSON and XML supported
● Type-class approach - Implicit resolution
36. Custom Http entity data
● Akka Http JSON support
● Support conversion to and from JVM objects to wire
representation like JSON, XML etc
● SprayJsonSupport provides a
FromEntityUnmarshaller[T] and ToEntityMarshaller[T]
for every type T with Spray Json Reader/Writer
com.shashank.akkahttp.basic.routing.CustomEntityWithJson
39. File upload
def uploadedFile(fieldName: String): Directive1[(FileInfo, File)]
● Streams the contents of a file uploaded as a multipart
form into a temporary file on disk
● Cannot start processing the file unless it written
completely to temporary file
com.shashank.akkahttp.basic.routing.FileUpload
40. File upload stream
def fileUpload(fieldName: String): Directive1[(FileInfo,
Source[ByteString, Any])]
● Simple access to the stream of bytes for a file
uploaded as a multipart form together with metadata
about the upload as extracted value.
com.shashank.akkahttp.basic.routing.FileUploadStream
42. Websocket
● WebSocket is a protocol that provides a bi-directional channel
between browser and webserver
● Data is exchanged in messages whereby a message can either
be binary data or unicode text
43. Server side websocket in AkkaHttp
● Akka HTTP provides a stream-based implementation of the
WebSocket protocol
● basic unit of data exchange in the WebSocket is a message i.e
TextMessage or BinaryMessage
● Websocket handshake is managed and hidden from application
layer
● A message handler is expected to be implemented as a
Flow[Message, Message, Any]
● Testing Websocket using WSProbe
com.shashank.akkahttp.basic.routing.Websocket
44. Akka HTTP with Spark
Spark Cluster
Akka Http
Rest
server
Client
HDFS
45. Pros and Cons
● Pros
○ Backed by Lightbend(Typesafe)
○ Integration layers
○ Microservices
○ Pure REST APIs
● Cons
○ Full fledged web applications (server side template generation)
○ Not mature enough
○ Easy to start, hard to master
46. References
● Akka HTTP - A reactive web toolkit
● Akka HTTP - What, Why and How
● Introduction to Akka HTTP
● Akka HTTP documentation
http://doc.akka.io/docs/akka/2.4.2/scala/http/
● http://blog.madhukaraphatak.com/categories/akka-http/