building a reactive restful api with akka http & slick

59
Codemotion 2015, Berlin, Germany Building a Reactive RESTful API with Akka Http & Slick

Upload: zalando-technology

Post on 18-Jan-2017

9.536 views

Category:

Technology


2 download

TRANSCRIPT

Page 1: Building a Reactive RESTful API with Akka Http & Slick

Codemotion 2015,Berlin, Germany

Building a

Reactive RESTful APIwith Akka Http & Slick

Dan Persa - @danpersa

Page 2: Building a Reactive RESTful API with Akka Http & Slick

Dan Persa● Senior Software Engineer

● Twitter: @danpersa

[email protected]

Page 3: Building a Reactive RESTful API with Akka Http & Slick

EUROPE’S LEADING ONLINE FASHION PLATFORM

15 countries3 fulfillment centers16+ million active customers2.2+ billion € revenue 2014130+ million visits per month9.000+ employees

Visit us: tech.zalando.com

Page 4: Building a Reactive RESTful API with Akka Http & Slick
Page 5: Building a Reactive RESTful API with Akka Http & Slick
Page 6: Building a Reactive RESTful API with Akka Http & Slick

ZALANDOTECHNOLOGY

Page 7: Building a Reactive RESTful API with Akka Http & Slick
Page 8: Building a Reactive RESTful API with Akka Http & Slick
Page 9: Building a Reactive RESTful API with Akka Http & Slick

500+Apps

800+ Tech employees

August

Page 10: Building a Reactive RESTful API with Akka Http & Slick
Page 11: Building a Reactive RESTful API with Akka Http & Slick

Conway’s Law

“organizations which design systems ...are constrained to produce designs which are copies of the communication structures of these organizations”

Page 12: Building a Reactive RESTful API with Akka Http & Slick

ARCHITECTURE

AN ARCHITECTURE FOR INNOVATION

Page 13: Building a Reactive RESTful API with Akka Http & Slick

API FIRSTRESTSAAS

MICRO SERVICESCLOUD

OPEN SOURCE

Page 14: Building a Reactive RESTful API with Akka Http & Slick
Page 15: Building a Reactive RESTful API with Akka Http & Slick

THE SHOP MONOLITH

Page 16: Building a Reactive RESTful API with Akka Http & Slick

http://blog.codinghorror.com/new-programming-jargon/

We call it “Jimmy”

Page 17: Building a Reactive RESTful API with Akka Http & Slick

Thousands of Java classes, undocumented featuresBusiness logic on all layers (including the database)

Page 18: Building a Reactive RESTful API with Akka Http & Slick

MICROSERVICES

Page 19: Building a Reactive RESTful API with Akka Http & Slick

Internet

LB

SKIPPERSKIPPER

SKIPPERSKIPPER

JIMMYMOSAIC

INNKEEPERINNKEEPER

INNKEEPERLB

REST APIs

Page 20: Building a Reactive RESTful API with Akka Http & Slick

HIGHLY AVAILABLE0 DOWNTIMERELIABLEFAST

Page 21: Building a Reactive RESTful API with Akka Http & Slick

INNKEEPER github.com/zalando/innkeeper

Page 22: Building a Reactive RESTful API with Akka Http & Slick

API FIRSTREST

Page 23: Building a Reactive RESTful API with Akka Http & Slick

FORMAL SPECIFICATION FOR RESTful APIs

The World's Most Popular Framework for APIs.

Page 24: Building a Reactive RESTful API with Akka Http & Slick
Page 25: Building a Reactive RESTful API with Akka Http & Slick

REST RESOURCES

GET /routesGET /routes/{id}POST /routesDELETE /routes/{id}

GET /updated-routes/{id}

Page 26: Building a Reactive RESTful API with Akka Http & Slick

GOING REACTIVE

Page 27: Building a Reactive RESTful API with Akka Http & Slick
Page 28: Building a Reactive RESTful API with Akka Http & Slick

MODEL DBCONTROLLER

BUFFERBUFFERDB RecordsDTOsJSON

CLIENT

TRADITIONAL APPLICATION

HTTP Request Method Call SQL

Blocking IO

Page 29: Building a Reactive RESTful API with Akka Http & Slick

MODEL DBCONTROLLER

DB StreamDTOsJSON

CLIENT

REACTIVE APPLICATION

HTTP Request Method Call SQL

Non-Blocking IO

StreamStreamStream

Page 30: Building a Reactive RESTful API with Akka Http & Slick

ScalaTypesafeComposable

Meet

Page 31: Building a Reactive RESTful API with Akka Http & Slick

Separation of I/0ResilienceReactive Streams

Meet

Page 32: Building a Reactive RESTful API with Akka Http & Slick

def routesModifiedSince(localDateTime: LocalDateTime): DatabasePublisher[RouteRow] = {

}

val routesTable = TableQuery[RoutesTable]

val q = for { routeRow <- routesTable if (routeRow.createdAt > localDateTime | routeRow.deletedAt > localDateTime)} yield routeRow

db.stream { q.result }

Page 33: Building a Reactive RESTful API with Akka Http & Slick

ComposableMaterializableReactive Streams

Meet

Streams

Page 34: Building a Reactive RESTful API with Akka Http & Slick

import akka.stream.scaladsl.Source

def findRoutesModifiedSince(localDateTime: LocalDateTime): Source[Route, Unit] = {

}

Source(

).mapConcat(_.toList)

routesRepo.selectModifiedSince(localDateTime).mapResult { row =>

}

row.id.map { id => Route( id = id, route = row.routeJson.parseJson.convertTo[NewRoute], row.createdAt, row.deletedAt )}

Page 35: Building a Reactive RESTful API with Akka Http & Slick

val route = path("hello") { get { complete { <h1>Hello World</h1> } } }

Meet

Http

Page 36: Building a Reactive RESTful API with Akka Http & Slick

object Main extends App {

}

implicit val system = ActorSystem("my-system")implicit val materializer = ActorMaterializer()val route = ...val bindingFuture = Http().bindAndHandle(route, "localhost", 8080)...

Page 37: Building a Reactive RESTful API with Akka Http & Slick

Innkeeper’s AKKA HTTP Routesval route = path("updated-routes" / Rest) { lastModifiedString => get { complete(…) } } ~ path("routes") { get { complete(…) } ~ post { complete(…) } } ~ path("routes" / LongNumber) { id => get { … } ~ delete { … } }

Page 38: Building a Reactive RESTful API with Akka Http & Slick

path("routes") { get {

complete { HttpResponse(

) } }}

entity = HttpEntity.Chunked( MediaTypes.`application/json`, chunkedStreamSource )

val chunkedStreamSource = jsonService.sourceToJsonSource(routesService.allRoutes)

Page 39: Building a Reactive RESTful API with Akka Http & Slick

def sourceToJsonSource[T](source: Source[T, Unit]) (implicit writer: JsonWriter[T]):

Source[ChunkStreamPart, ((Unit, Unit), Unit)] = {

val commaSeparatedRoutes: Source[ChunkStreamPart, Unit] = source .map(t => Some(t.toJson.compactPrint)) .scan[Option[ChunkStreamPart]](None)({ case (None, Some(sourceElement)) => Some(ChunkStreamPart(sourceElement)) case (_, Some(sourceElement)) => Some(ChunkStreamPart(s", $sourceElement")) }) .mapConcat(_.toList)

Source.single(ChunkStreamPart("[")) ++ commaSeparatedRoutes ++ Source.single(ChunkStreamPart("]")) }

Page 40: Building a Reactive RESTful API with Akka Http & Slick

SAAS

Page 41: Building a Reactive RESTful API with Akka Http & Slick

OAUTH

Page 42: Building a Reactive RESTful API with Akka Http & Slick

val route: RequestContext => Future[RouteResult] = authenticationToken { token => authenticate(token, authService) { authenticatedUser => path("updated-routes" / Rest) { lastModifiedString => get { hasOneOfTheScopes(authenticatedUser)(scopes.READ) { ...

Page 43: Building a Reactive RESTful API with Akka Http & Slick

import akka.http.scaladsl._import akka.http.scaladsl.server.directives.HeaderDirectives._

trait OAuthDirectives { def authenticationToken: Directive1[String] = headerValue(optionalValue("authorization")) | reject {

AuthenticationFailedRejection( CredentialsMissing, HttpChallenge("", "")

) }...

Page 44: Building a Reactive RESTful API with Akka Http & Slick

CLOUD

Page 45: Building a Reactive RESTful API with Akka Http & Slick

STUPS.IO

Page 46: Building a Reactive RESTful API with Akka Http & Slick

FROM zalando/openjdk:8u45-b14-5MAINTAINER Team Spearheads <[email protected]>

EXPOSE 8080

RUN mkdir -p /opt/innkeeper

ADD target/scala-2.11/innkeeper-assembly-0.0.1.jar /opt/innkeeper/

WORKDIR /opt/innkeeper

ENTRYPOINT java $(java-dynamic-memory-opts) -Dinnkeeper.env=prod -server -jar innkeeper-assembly-0.0.1.jar

Page 47: Building a Reactive RESTful API with Akka Http & Slick

docker:sbt assemblydocker build -t innkeper:latest-SNAPSHOT .

docker-push:docker push innkeper:latest-SNAPSHOT

docker-run:docker run -p 8080:8080 -t innkeper:latest-SNAPSHOT

test-db:docker run -e POSTGRES_PASSWORD=innkeeper-test -e

POSTGRES_USER=innkeeper-test -p 5433:5432 postgres:9.4

tick:senza create senza.yaml tick latest-SNAPSHOT

tock:senza create senza.yaml tock latest-SNAPSHOT

Page 48: Building a Reactive RESTful API with Akka Http & Slick

OPENSOURCE

Page 49: Building a Reactive RESTful API with Akka Http & Slick

github.com/zalando/innkeeper

Page 50: Building a Reactive RESTful API with Akka Http & Slick

DOOSF

Page 51: Building a Reactive RESTful API with Akka Http & Slick

RADICAL AGILITY

TRUSTINSTEAD OF CONTROL

Page 52: Building a Reactive RESTful API with Akka Http & Slick
Page 53: Building a Reactive RESTful API with Akka Http & Slick
Page 54: Building a Reactive RESTful API with Akka Http & Slick

# use Docker-based container (instead of OpenVZ)sudo: false

cache: directories: - $HOME/.sbt - $HOME/.ivy2

language: scala

script: - sbt ++$TRAVIS_SCALA_VERSION test - sbt ++$TRAVIS_SCALA_VERSION it:test

# Trick to avoid unnecessary cache updates - find $HOME/.sbt -name "*.lock" | xargs rm

scala: - 2.11.7jdk: - oraclejdk8

addons: postgresql: "9.4"

before_script: - psql -c 'CREATE ROLE innkeepertest superuser login createdb;' -U postgres - psql -c 'CREATE DATABASE innkeepertest;' -U postgres

Page 55: Building a Reactive RESTful API with Akka Http & Slick

NEXTSTEPS

Page 56: Building a Reactive RESTful API with Akka Http & Slick

APPLICATION LOGS: SCALYR

Page 57: Building a Reactive RESTful API with Akka Http & Slick

TODO: Screenshot

ZMON

Page 58: Building a Reactive RESTful API with Akka Http & Slick

Where to Find Us:Tech Blog: tech.zalando.com

GitHub: github.com/zalando

Innkeeper: github.com/zalando/innkeeper

Twitter: @ZalandoTech

Instagram: zalandotech

Jobs: http://tech.zalando.com/jobs

Page 59: Building a Reactive RESTful API with Akka Http & Slick

THANK YOU!QUESTIONS?