The Sad Story of the Server that Tries to Please Everyone
-
Upload
iulian-dogariu -
Category
Software
-
view
74 -
download
1
Transcript of The Sad Story of the Server that Tries to Please Everyone
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"))
}
}
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"))
}
}
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)
}
}
}
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
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
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)
}
}
val bookingFlow =
Flow[NewBookingCommand].map { command =>
val bookings = TicketsRepository.
bookForEvent(command.eventId, command.count)
BookingSucceeded(
command.eventId, bookings)
}
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"))
}
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 :-)