Iulian dogariu the sad story of the server etc

34
The Sad ˝ Story ˝ Of the Server ˝ that Tries to ˝ Please Everyone Iulian Dogariu CodeCamp 25 Oct 2014

description

CodeCampIasi25Oct2014

Transcript of Iulian dogariu the sad story of the server etc

Page 1: Iulian dogariu   the sad story of the server etc

The Sad ˝Story ˝

Of the Server ˝that Tries to ˝

Please Everyone

Iulian Dogariu CodeCamp 25 Oct 2014

Page 2: Iulian dogariu   the sad story of the server etc
Page 3: Iulian dogariu   the sad story of the server etc

Lil' serverobject Tickets extends Controller {

def book(eventId: Int, count: Int) = Action {

val bookings: Seq[Booking] =

TicketsRepository.bookForEvent(eventId, count)

Ok(s"Thank you! These are your bookings " +

bookings.mkString("\n"))

}

}

Page 4: Iulian dogariu   the sad story of the server etc

Lil' serverobject Tickets extends Controller {

def book(eventId: Int, count: Int) = Action {

val bookings: Seq[Booking] =

TicketsRepository.bookForEvent(eventId, count)

Ok(s"Thank you! These are your bookings " +

bookings.mkString("\n"))

}

}

Page 5: Iulian dogariu   the sad story of the server etc

More than a lil'def bookForEvent(eventId: Int, count: Int): Seq[Booking] = {

DB.withTransaction { implicit c =>

val numAvailableTickets: Int = SQL(

"SELECT num_free FROM tickets WHERE event_id={eventId}").

on("eventId" -> eventId).as(SqlParser.int("num_free").single)

(0 to count).map { _ =>

val bookingId: Option[Long] = SQL(

"INSERT INTO bookings(event_id)" +

" VALUES({eventId})").on('eventId -> eventId).executeInsert()

Booking(bookingId, eventId)

}

}

}

Page 6: Iulian dogariu   the sad story of the server etc

More than a lil'

Page 7: Iulian dogariu   the sad story of the server etc

How bad is it?

Normal CPU instruction

Fetch from RAM

Disk seek

Ping from Iași to Bucharest

Ping from Iași to USA

0.5 nsec

120 nsec

10 msec

30 msec

130 msec

Page 8: Iulian dogariu   the sad story of the server etc

No, really

Normal CPU instruction

Fetch from RAM

Disk seek

Ping from Iași to Bucharest

Ping from Iași to USA

1 sec

4 min

7.5 Months

2 Years

6 Years

Page 9: Iulian dogariu   the sad story of the server etc

Back to the lil' server

Page 10: Iulian dogariu   the sad story of the server etc

Back to the lil' server

Page 11: Iulian dogariu   the sad story of the server etc

Back to the lil' server

Page 12: Iulian dogariu   the sad story of the server etc
Page 13: Iulian dogariu   the sad story of the server etc

What does the user see?

Page 14: Iulian dogariu   the sad story of the server etc
Page 15: Iulian dogariu   the sad story of the server etc

If I only knew...

• I'd go somewhere else!

Page 16: Iulian dogariu   the sad story of the server etc

Show me the bottleneck

Page 17: Iulian dogariu   the sad story of the server etc

Queues and messages bookingActor ! NewBookingCommand(1, 2)

def receive = {

case BookingSucceeded(eventId, bookings) =>

println(s"Thank you!" + bookings.mkString("\n"))

}

class BookingActor extends Actor {

def receive = {

case NewBookingCommand(eventId, ct) =>

val bookings = TicketsRepository.bookForEvent(eventId, ct)

sender ! BookingSucceeded(eventId, bookings)

}

}

Page 18: Iulian dogariu   the sad story of the server etc

One small step

Page 19: Iulian dogariu   the sad story of the server etc

Pulling workGIMME WORK!!

Page 20: Iulian dogariu   the sad story of the server etc

WIP

Page 21: Iulian dogariu   the sad story of the server etc

The math of WIP

Page 22: Iulian dogariu   the sad story of the server etc
Page 23: Iulian dogariu   the sad story of the server etc

Push back

Page 24: Iulian dogariu   the sad story of the server etc

Push back

Page 25: Iulian dogariu   the sad story of the server etc

Reactive streams

Page 26: Iulian dogariu   the sad story of the server etc

Reactive streams

Page 27: Iulian dogariu   the sad story of the server etc

val bookingFlow =

Flow[NewBookingCommand].map { command =>

val bookings = TicketsRepository.

bookForEvent(command.eventId, command.count)

BookingSucceeded(

command.eventId, bookings)

}

Page 28: Iulian dogariu   the sad story of the server etc

val in = ThunkTap[NewBookingCommand] {

// Flood with requests

Some(NewBookingCommand(1, 2))

}

val out = ForeachDrain[BookingSucceeded] {

case BookingSucceeded(eventId, bookings) =>

println(s"Thank you!" + bookings.mkString("\n"))

}

Page 29: Iulian dogariu   the sad story of the server etc

FlowGraph { implicit b =>

in ~> bookingFlow ~> out

}.run()

Altogether nowFlowTap

Drain

Page 30: Iulian dogariu   the sad story of the server etc

Recap

• Do you really know what's slow in your code?

• Queues make bottlenecks obvious

• If you can't serve me, tell me so ("Agree to Start")

• Because people pleasers end up disappointing everyone equally :-)

Page 31: Iulian dogariu   the sad story of the server etc

The Soup Nazi problem

Page 32: Iulian dogariu   the sad story of the server etc
Page 33: Iulian dogariu   the sad story of the server etc

Q & A ?

Page 34: Iulian dogariu   the sad story of the server etc

Thank You, Come Again

And please fill in the evaluation form :-)