Develop realtime web with Scala and Xitrum

Preview:

Citation preview

Develop realtime and distributed web

with Scala and XitrumNgoc Dao

Saigon Xmas 2014Hanoi New Year 2015

Slides will be shared at:http://www.slideshare.net/ngocdaothanh

This talk is long.Please ask question immediately when you have one.

For questions/discussions after this talk, please post to:https://www.facebook.com/groups/720666194693928

You can also post to scala-user group:https://groups.google.com/d/forum/scala-user

About meWorking at Mobilus in Tokyo: http://mobilus.co.jp/● Server side● Android, iOS

Interests:● Realtime and distributed systems● Web frameworks

(have been written several for Erlang, Scala, Java)● Big data, analytics (learning Apache Spark)

Open source:● https://github.com/ngocdaothanh● https://github.com/xitrum-framework● https://github.com/sinetja● https://github.com/netty

Scala@Japan

● Meetups: ~monthly (in Tokyo)● Conferences: yearly

○ 2013:http://scalamatsuri.org/2013/en/program/index.html

○ 2014:http://scalamatsuri.org/en/program/index.htmlhttp://scalamatsuri.org/en/unconference/index.html

Red Sand DunesPhan Thiet

About you

I guess you already know OOP.

Functional programming:● How many of you have used Ruby?

(somewhat functional, popular)● Have used a more functional language?

(Lisp, Haskell, Erlang, Clojure, F# etc.)

Scala looks like Java and runs on JVM. It’s convenient if you already know Java:● How many of you have used Java?● Have used Scala?

● Why use Scala? Compare with Java, Ruby, Node.js etc.● Books, sites

Getting started:● Install Scala● Ways to run Scala program: Hello World

Scala = OOP + functional:● Learn Scala’s functional feature via collections● Learn Scala’s OOP feature via the Animals exercise

Some tools:● Development:

○ REPL (Read–Eval–Print Loop), SBT (Scala Build Tool)○ IDEs: Eclipse, IntelliJ

● Production: ○ xitrum-package○ Scalive

PART 1/5: Scala overview

● Web app ≈ normal app + routing● Xitrum:

○ Compare with Scalatra, Lift, Play○ Basic usage:

■ Add routes to the previous demos■ respondXxx

○ Swagger UI, Swagger Codegen○ Metrics○ i18n

PART 2/5: Use Scala for web

● Compare with Node.js● Future and future composition● Actor model and Akka actor

↑ NEW programming paradigmA language that doesn't change the way you think about programming is not worth learning.○ Actor vs Thread○ Actor vs Future○ Some pitfalls

● Akka FSM

PART 3/5: Use Scala for concurrency

● Realtime web● WebSocket, Socket.IO, SockJS● Tictactoe web game

PART 4/5: Use Scala for realtime web

PART 5/5: Use Scala for distributed systems

Compare with Redis

Remoting:● Akka remoting

Clustering:● Akka clustering● Glokka● Hazelcast

Scale Tictactoe to multiple servers

● Why use Scala? Compare with Java, Ruby, Node.js etc.● Books, sites

Getting started:● Install Scala● Ways to run Scala program: Hello World

Scala = OOP + functional:● Learn Scala’s functional feature via collections● Learn Scala’s OOP feature via the Animals exercise

Some tools:● Development:

○ REPL (Read–Eval–Print Loop), SBT (Scala Build Tool)○ IDEs: Eclipse, IntelliJ

● Production: ○ xitrum-package○ Scalive

PART 1/5: Scala overview

● Trendy: Used by by Apple, Foursquare, Guardian, LinkedIn, Netflix, Quora, Sony Pictures Entertainment, Twitter, UK Guardian etc.

● Compare with Java, Ruby, Node.js etc.● Language: ≈ Java + Ruby

○ Fast speed of Java + nice syntax of Ruby:Faster than Ruby + syntax nicer than Java

○ Flexible:■ Static + dynamic:

Compiled to Java .class or run as script like Ruby■ OOP of Java + functional of Ruby

http://www.quora.com/Why-is-Swift-so-similar-to-Scala● Not only a good language: Scala has toys

○ Ecosystem: Can reuse all Java libs○ Concurrent/parallel: Future, Akka (≈ Erlang)○ Big data: Apache Spark

Why use Scala?

Books, sites

● http://www.scala-lang.org/documentation/● http://twitter.github.io/effectivescala/● https://github.com/lauris/awesome-scala● https://github.com/akullpp/awesome-java● Search

Learn Scala “enough” to do projects

How much is “enough”?

Level A1:Beginning application programmer

● Java-like statements and expressions: standard operators, method calls, conditionals, loops, try/catch

● class, object, def, val, var, import, package● Infix notation for method calls● Simple closures● Collections with map, filter, etc● for-expressions

http://www.scala-lang.org/old/node/8610

Level A2:Intermediate application programmer

● Pattern matching● Trait composition● Recursion, in particular tail recursion● XML literals

Level A3:Expert application programmer

● Folds, i.e. methods such as foldLeft, foldRight

● Streams and other lazy data structures● Actors● Combinator parsers

Level L1:Junior library designer

● Type parameters● Traits● Lazy vals● Control abstraction, currying● By-name parameters

Level L2:Senior library designer

● Variance annotations● Existential types (e.g., to interface with Java

wildcards)● Self type annotations and the cake pattern

for dependency injection● Structural types (aka static duck typing)● Defining map/flatmap/withFilter for new kinds

of for-expressions● Extractors

Level L3:Expert library designer

● Early initializers● Abstract types● Implicit definitions● Higher-kinded types

A1 → A2/L1 → A3/L2 → L3

Install Scala

1. Download fromhttp://www.scala-lang.org/

2. Config PATH:PATH=path/to/scala-2.11.4/bin:$PATH

REPL (Read–Eval–Print Loop) demo:scala command

Ways to run Scala program

● println("Hello World")● Run as script with scala● Compile with scalac and run with scala● Compile with scalac and run with java

SBT (Scala Build Tool)

http://www.scala-sbt.org/

● Dependency library manager + build tool● Like “gem” + “rake” of Ruby● Like Maven, Gradle● Has plugins to generate project files for IDEs,

like Eclipse and IntelliJ● Has plugins to collect and package .jar files,

ready to deploy to production environment

(Make, Ant are just build tools, not dependency library managers)

Install SBT

1. Download fromhttp://www.scala-sbt.org/download.html

2. Config PATH:PATH=path/to/sbt/bin/dir:$PATH

sbt:java -Xms256M -Xmx512M-jar `dirname $0`/sbt-launch-0.13.7.jar "$@"

Learn SBT:http://www.scala-sbt.org/documentation.html

Simple SBT-based project structure

build.sbtorganization := "com.mycompany"

name := "hello"

version := "1.0"

scalaVersion := "2.11.4"

scalacOptions ++= Seq("-deprecation", "-feature", "-unchecked")

javacOptions ++= Seq("-source", "1.6", "-target", "1.6")

libraryDependencies += "tv.cntt" %% "xitrum" % "3.21"

libraryDependencies += "ch.qos.logback" % "logback-classic" % "1.1.2"

Packaged .jar file:hello_2.11-1.0.jar

$ sbt tasksconsole Starts the Scala interpreter

compile Compiles sourcesclean Deletes files produced by the buildrun Runs a main class

package Produces project jar filepublish Publishes project jar file to a repositorypublish-local Copies project jar file to ~/.ivy2

test Executes all teststest-only Executes the tests provided as argumentstest-quick Executes the tests that either failed before

SBT plugins

http://www.scala-sbt.org/release/docs/Community-Plugins.html

Generate Eclipse project:https://github.com/typesafehub/sbteclipse

Generate IntelliJ project:https://github.com/mpeltonen/sbt-idea

Package project:https://github.com/xitrum-framework/xitrum-package

Hello World demo

● sbt console● sbt run● sbt eclipse● Run in Eclipse● Debug in Eclipse● sbt xitrum-package● Run with java● Add dependency library

http://search.maven.org/● Scalive

Rules of thumb

Use dependency manager:● Do not download dependency libraries

manually● Do not commit dependency libraries

IDEs:● Generate project files for IDEs● Do not commit project files

Scala = OOP + functional

Unifying Object-Oriented and Functional Programminghttp://web.stanford.edu/class/cs94si/OOPFP.pdf

Functional language

● Pass a function as an argument to another function=> Convenient syntaxf(123, g)f(123, { // ...})

● Immutable data structures=> Thread-safe○ Tail recursion

Learn Scala’s functional feature via collections

● From a collection, create another collection of same size=> map

● From a collection, create another collection of larger size=> flatMap

● From a collection, create another collection of smaller size=> filter

● From a collection, create one element=> foldLeft, foldRight, reduce

http://www.scala-lang.org/api/current/index.html#scala.collection.Seq

map

flatMap

filter

foldLeft

Roll

val a = 1

var b = 1b = 2

val → immutable:val c = Seq(1, 2, 3)

var → immutable:var d = Seq(1, 2, 3)d = Seq(4, 5, 6)

val → mutable:val e = Array(1, 2, 3)e(0) = 4

var → mutable:var f = Array(1, 2, 3)f = Array(4, 5, 6)f(0) = 4

val VS varimmutable VS mutable collection

Order of preference (best practice):● val● var● val → immutable: strictly functional● var → immutable● val → mutable● var → mutable: do not use

Some languages only allow val → immutableScala is flexible:var and mutable are OK to use in small, closed scope

For your curiosity: How to write programs with only constants?

Example problem:

Without var, mutable:● Generate a collection of positive numbers

that are <= n, and are multiple of 3 or 5.gen(n: Int): Seq[Int]

● Calculate sum of all numbers in a collection.sum(nums: Seq[Int]): Int

With var and mutable

import scala.collection.mutable.ArrayBufferdef gen(n: Int): Seq[Int] = { val buf = ArrayBuffer[Int]() var i = 1 while (i <= n) { if (i % 3 == 0 || i % 5 == 0) buf.append(i) i += 1 } buf}

def gen(n: Int): Seq[Int] = { val nums = 1 to n nums.filter { i => i % 3 == 0 || i % 5 == 0 }}

def gen(n: Int): Seq[Int] = { for { i <- 1 to n if (i % 3 == 0 || i % 5 == 0) } yield i}

Without var and mutable

● Use recursion to loop● Optimize: Use tail recursion

○ Use accumulator

def gen(n: Int): Seq[Int] = { // Stop condition if (n < 3) return Seq()

// Recursion if (n % 3 == 0 || n % 5 == 0) gen(n - 1) :+ n else gen(n - 1)}

Stackoverflowif n is big enough

def genAcc( n: Int, acc: Seq[Int]): Seq[Int] = { if (n < 3) return acc

// Tail recursion; Scala compiler will // convert to “while” loop if (n % 3 == 0 || n % 5 == 0) genAcc(n - 1, n +: acc) else genAcc(n - 1, acc)}

def gen(n: Int) = genAcc(n, Seq())

def genAcc( n: Int, acc: Seq[Int]): Seq[Int] = { if (n < 3) return acc

if (n % 3 == 0 || n % 5 == 0) genAcc(n - 1, n +: acc) else genAcc(n - 1, acc)}

How to write programs with only constants?

State is storedat function arguments

State is set/changedat function call

How I learn an OOP language:● Learn basic syntax● Learn collections● Animals exercise:

abstraction, encapsulation,inheritance, polymorphism

Learn Scala’s OOP feature via the Animals exercise

Animals exercise

trait (interface) Animal● name: String● talk()

class Cat extends Animalclass Dog extends Animal

class Zoo● addAnimal(a: Animal)● talkAll()

scala-lang.org → /api/ Companion object Class Trait

http://youtu.be/GQxUEAXX_fE

How to read Scaladoc

● Web app ≈ normal app + routing● Xitrum:

○ Compare with Scalatra, Lift, Play○ Basic usage:

■ Add routes to the previous demos■ respondXxx

○ Swagger UI, Swagger Codegen○ i18n

PART 2/5: Use Scala for web

Web ≈ Routing

function

Input Output

function

Input Output

Web ≈ RoutingA web library/framework is not worth using if its routing feature sucks.

function

Request Response

function

ResponseRequest

Request

Request

Router

Xitrum

http://xitrum-framework.github.io/

Compare with Scalatra, Lift, Play

Demos:https://github.com/xitrum-framework/xitrum-demos

Skeleton to create new project:https://github.com/xitrum-framework/xitrum-new

● Basic usage:○ Add routes to the previous demos○ respondXxx

● Swagger UI, Swagger Codegen● Metrics● i18n

Xitrum

● Compare with Node.js● Future and future composition● Actor model and Akka actor

↑ NEW programming paradigmA language that doesn't change the way you think about programming is not worth learning.○ Actor vs Thread○ Actor vs Future○ Some pitfalls

● Akka FSM

PART 3/5: Use Scala for concurrency

Compare with Node.js

Node.js:● Single thread => Single core● Complicate to scale to multiple cores or multiple

servers; except for shared-nothing (non-realtime) systems

● Callback hell

Scala:● Multiple threads; immutable data structures, future, and

actor provide more safety for multithread programming● Easy to scale● No callback hell

Future

http://docs.scala-lang.org/overviews/core/futures.html

Think about Future as a thread pool with some nice methods to:● send tasks to it● get results● handle failures● compose the above together

Future composition

ff

ff

f

f

f

f1

f2

f3

f

Think about Node.js callback hell!

● Future.sequence● for comprehension

val taskParams = Seq(123, 456, 789)val taskFutures: Seq[Future[String]] = tasks.map { ms =>

future { Thread.sleep(ms) s"Result for $ms" }}

val gatheredFuture: Future[Seq[String]] = Future.sequence(taskFutures)

val purchase = for { usd <- future { con.getValue(USD) } chf <- future { con.getValue(CHF) } if isProfitable(usd, chf)} yield connection.buy(amount, chf)

purchase onSuccess { amount =>println("Purchased " + amount + " CHF")

}

↑ NEW programming paradigm

A language that doesn't change the way you think about programming is not worth learning.Alan Perlis(the first recipient of the Turing Award)

Actor model and Akka actor

Benefit of actor in one sentence

C vs Java:You can use memory without having to release memory manually.

Thread vs actor:You can use concurrency without having to create threads manually.

Don't communicate by sharing memory; share memory by communicating.

Actor model● Actor =

states + mailbox + behaviors (msg handlers)

● From outside, can’t manipulate actors directly.● To interact with an actor, must send messages to it.● Each actor has a mailbox, messages are put to mailbox,

and processed one by one. ← An actor is like a single threaded process (each actor is like a Node.js process); it doesn’t do more than one thing at a time.

http://www.cs.tsukuba.ac.jp/~yas/cs/csys-2013/2013-12-03/

Actor vs Thread

Thread:● Heavy weight: Can only create not too many threads;

usually: 2000~5000● Shared state ← Source of bugs● Passive: Have to call object.method() to make the object

alive.Actor:● Light weight: Can create millions of actors;

usually: ~2.5 million actors/GB● Self contained, shared nothing● Active: Actors are alive by themselves. ← Easy to model

programs that have millions of on-going things (very high level of concurrency), like MMOG games.

Actor vs Thread

● Thread: n dimensions, hard to reason about.● Actor: 1D, one thing at a time.

var1

var1

Actor vs Thread

Just like JVM automatically manages memory for you:● Actor is a high level logical way to think, to

model programs.● At lower level, actors run above a thread

pool.

Actor vs Future

Actor:● Messaging● Scheduling● FSM● Monitoring and supervision● Location transparency

(actors on one server can send messages to actors on another server)=> Easier to scale out to multiple servers/clustering

Future:● Syntax is easier to write● Composable● More typesafe

Akka http://akka.io/(an implementation of the actor model)

Summary:https://jraviton.wordpress.com/2015/01/16/lets-brush-up-on-scala-actors/

Demo: Counter

// First, define messagesobject Counter { case class Inc(amount: Int) case class Dec(amount: Int)}

import akka.actor.Actor

// Define actor state and message handlersclass Counter(name: String) extends Actor { // Actor state private var value = 0

...

...

import Counter._

// Message handlers def receive = { case Inc(amount) => value += amount println(s"Value: $value")

case Dec(amount) => value -= amount println(s"Value: $value") }}

import akka.actor.{ActorSystem, Props}

// Think of this as a thread poolval system = ActorSystem("mysystem")

// Create actor reference (actor instance)val c1 = system.actorOf( Props(new Counter("mylock")))

// Send messages to the actorc1 ! Counter.Inc(1)c1 ! Counter.Dec(2)

Some pitfalls

Send mutable msgs between actors.↑ May lead to bug, if actor A sends msg M to actor B, state of B incorporates M, then M is later changed by A.=> Shared memory

Fix: Use immutable messages.

Some pitfallsFrom inside actor:anObject.foo(new Callback { def onCallback() { // Modify actor state directly }})↑ May lead to bug, because the actor’s thread and the callback’s thread may be 2 different threads. Remember: An actor is like a single threaded process, can’t do more than one thing at a time. An actor should be self contained, shared nothing.

Fix: self ! msgFromCallback

Good read

● Concurrent Programming for Scalable Web Architectureshttp://berb.github.io/diploma-thesis/index.html

● Functions + Messages + Concurrency = Erlanghttp://www.infoq.com/presentations/joe-armstrong-erlang-qcon08

● Akka dochttp://doc.akka.io/docs/akka/2.3.8/scala.html

Akka FSM

● FSM: Finite State Machine● Implemented based on actors● Very good for realtime multiplayer games, to

manage states of game sessions and inter-player interactions

Example:Code Lockhttps://github.com/ngocdaothanh/code-lock-fsm-akka

● Realtime web● WebSocket, Socket.IO, SockJS● Tictactoe web game

PART 4/5: Use Scala for realtime web

HTTP problem:Server can send data to clients only one time.

Some years ago:Flash (open TCP socket connection to server)

Now:WebSockethttps://developer.mozilla.org/en-US/docs/WebSockets/Writing_WebSocket_client_applications

Realtime web ≈ server push

var sock = new WebSocket('ws://domain/path');

sock.onopen = function() { console.log('onopen');};

sock.onmessage = function(e) { console.log('onmessage: ' + e.data); sock.send(e.data);};

sock.onclose = function() { console.log('onclose');};

Server can push data to clients multiple times

WebSocket problem

New browsers are required:● Internet Explorer: 10● Firefox: 6● Chrome: 4● Safari: 5● Opera: 12.10

WebSocket emulators

SockJS: WebSocket-like API● JavaScript client:

https://github.com/sockjs/sockjs-client● Protocol:

https://github.com/sockjs/sockjs-protocolhttp://sockjs.github.io/sockjs-protocol/sockjs-protocol-0.3.3.html

● Closer to WebSocket, much simpler than Socket.IO=> Server side support for many languages

Socket.IO: More complicate built-in features, like rooms● http://socket.io/● Node.js

SockJS

● Provides WebSocket-like API● Supports all browsers, e.g. IE 6● Transports: websocket xhr-streaming xdr-

streaming iframe-eventsource iframe-htmlfile xhr-polling xdr-polling iframe-xhr-polling jsonp-polling

● Requires○ Client side: sockjs.js○ Server side: SockJS protocol

implementation

var sock = new WebSocket('ws://domain/path');

sock.onopen = function() {

};

sock.onmessage = function(e) {

sock.send(e.data);

};

sock.onclose = function() {

};

var sock = new SockJS('http://domain/path');

sock.onopen = function() {

};

sock.onmessage = function(e) {

sock.send(e.data);

};

sock.onclose = function() {

};

WebSocket vs SockJS

Tictactoe web game

https://github.com/xitrum-framework/xitrum-tictactoe

Tictactoe web game

Exercises:● Instead of letting player actors send messages directly

to each other, use an intermediate game actor for each game.

● Let users other than the players watch games.● Use Scala.js to convert game logic code written in Scala

to JavaScript, to share game logic code between server side and client side.http://www.scala-js.org/

● Use Akka FSM instead of become.

Compare with Redis

Remoting:● Akka remoting

Clustering:● Akka clustering● Glokka● Hazelcast

Scale Tictactoe to multiple servers

PART 5/5: Use Scala for distributed systems

Compare with Redis

Redis:● Separate process● Single point of failure

Akka, Hazelcast:● In-process

=> Faster, easier to use● Redundancy, failover

Akka remoting

http://doc.akka.io/docs/akka/2.3.8/scala/remoting.html

Akka clustering

http://doc.akka.io/docs/akka/2.3.8/scala/cluster-usage.html

Glokka

https://github.com/xitrum-framework/glokka

A Scala library that allows you to register and lookup actors by names in an Akka cluster.

Hazelcast

Program ≈ Code + Data

Distributed Program ≈ Distributed Code + Distributed Data

Akka ≈ Distributed CodeHazelcast ≈ Distributed Data + Distributed Code

http://hazelcast.org/http://hazelcast.com/

http://docs.hazelcast.org/docs/3.4/manual/html/

● Distributed data structures: Map, Multimap, Queue, Set, List, Topic (pub/sub), Lock, AtomicLong, AtomicReference, Semaphore, CountDownLatch, IdGenerator

● JCache● Distributed ExecutorService● Transaction● MapReduce, Aggregators● Integration: Hibernate, Servlet session replication,

Spring● Client: Java, C++, .NET, REST, memcache

Scale Tictactoe to multiple servers

Only need to change Lobby lookup=> Use Glokka

Config Akka cluster:config/akka.conf

Recommended