Download - Scala na soundcloud [QCon]

Transcript
Page 1: Scala na soundcloud [QCon]
Page 2: Scala na soundcloud [QCon]

@flaviowbrasil

Aficionado por open source

Expert em escalabilidade

Mestre Jedi Scala

Prefere uma sessão de profiling a uma tarde na praia

Page 3: Scala na soundcloud [QCon]

@herval

Fundador de Startups

Dois Easter Eggs publicados

Padawan Scala

Tem um cachorro

Page 4: Scala na soundcloud [QCon]

A Nuvem de Som

12 horas de novo conteúdo/ minuto350 milhões de usuários/mês12 milhões de horas ouvidas/mês1 usuário no espaço

Page 5: Scala na soundcloud [QCon]

Era uma vez uma startup...

Page 6: Scala na soundcloud [QCon]

Era uma vez uma startup...

Uma base de código

Page 7: Scala na soundcloud [QCon]

Era uma vez uma startup...

Uma base de códigoUm punhado de construtores

Page 8: Scala na soundcloud [QCon]

Move fast and break things

Page 9: Scala na soundcloud [QCon]

Um milhão de featuresBase de código gigante

Page 10: Scala na soundcloud [QCon]

Quebrando os muros

Page 11: Scala na soundcloud [QCon]

Muitos vilarejos, muitos idiomas

Page 12: Scala na soundcloud [QCon]

Muitos vilarejos, muitos idiomas

Microserviços → "tudo é http"Culturas de códigoInfraestruturaMonitoramento"production ready"

Page 13: Scala na soundcloud [QCon]

Ninguém entende ninguém

Page 14: Scala na soundcloud [QCon]

Move fast without breaking everything, bitte.

Page 15: Scala na soundcloud [QCon]

Java

Page 16: Scala na soundcloud [QCon]

JavaServiços de baseBibliotecas compartilhadasMonitoriaAutenticação/segurança (cross-cutting concerns)

Page 17: Scala na soundcloud [QCon]

JavaServiços de baseBibliotecas compartilhadasMonitoriaAutenticação/segurança (cross-cutting concerns)

INFRAESTRUTURA BÁSICA

Page 18: Scala na soundcloud [QCon]
Page 19: Scala na soundcloud [QCon]

JVM-Kit + Finagle

Page 20: Scala na soundcloud [QCon]

Estudo de caso

O novo Stream

Page 21: Scala na soundcloud [QCon]
Page 22: Scala na soundcloud [QCon]

Reescrever pra quê?

Page 23: Scala na soundcloud [QCon]

APIMySQL

Cassandra

Reescrever pra quê?

Page 24: Scala na soundcloud [QCon]

APIMySQL

Cassandra

Reescrever pra quê?

Page 25: Scala na soundcloud [QCon]

APIMySQL

Cassandra

Reescrever pra quê?80% request queueing

Page 26: Scala na soundcloud [QCon]

Reescrever pra quê?

Novas featuresLatênciaVazãoMicroserviços

Page 27: Scala na soundcloud [QCon]

Timeline

API

Page 28: Scala na soundcloud [QCon]

Timeline

API

Roshi

Page 29: Scala na soundcloud [QCon]

Timeline

API

Roshi

Autentic.

Autoriz.

Geo loc.

Page 30: Scala na soundcloud [QCon]

Timeline

API

Roshi

Autentic.

Autoriz.

Geo loc.

Page 31: Scala na soundcloud [QCon]

Timeline

API

Roshi

Autentic.

Autoriz.

Geo loc.

Playlists

Tracks

Usuários

Page 32: Scala na soundcloud [QCon]

Timeline

API

Roshi

Autentic.

Autoriz.

Geo loc.

Playlists

Tracks

Usuários

Likes

Coment.

Promoted

Stats

Page 33: Scala na soundcloud [QCon]

Timeline

API

Roshi

Autentic.

Autoriz.

Geo loc.

Playlists

Tracks

Usuários

Likes

Coment.

Promoted

Stats

...

Page 34: Scala na soundcloud [QCon]

Timeline

API

Roshi

Autentic.

Autoriz.

Geo loc.

Playlists

Tracks

Usuários

Likes

Coment.

Promoted

Stats

...

BuscarAgregar

Page 35: Scala na soundcloud [QCon]

BuscarLatência

Page 36: Scala na soundcloud [QCon]

Timeline

API

Roshi

Autentic.

Autoriz.

Geo loc.

Playlists

Tracks

Usuários

Likes

Coment.

Promoted

Stats

...

Page 37: Scala na soundcloud [QCon]

AgregarComplexidade

Page 38: Scala na soundcloud [QCon]

Timeline

API

Roshi

Autentic.

Autoriz.

Geo loc.

Playlists

Tracks

Usuários

Likes

Coment.

Promoted

Stats

...

Page 39: Scala na soundcloud [QCon]

Scala yay!

Page 40: Scala na soundcloud [QCon]

Buscar

Paralelizar

Page 41: Scala na soundcloud [QCon]
Page 42: Scala na soundcloud [QCon]

Futuros

Page 43: Scala na soundcloud [QCon]

Futuros

Referência para um valor que será disponibilizado no futuro.

Page 44: Scala na soundcloud [QCon]

Futuros val response: Future[Int] = …

// Não compila

response + 1

Page 45: Scala na soundcloud [QCon]

val response: Future[Int] = …

// Adiciona um callback

response.onSuccess { int =>

println(int)

}

Futuros

Page 46: Scala na soundcloud [QCon]

val response: Future[Int] = …

// Compõe um novo futuro

val count: Future[Int] =

response.map { int =>

int + 1

}

Futuros

Page 47: Scala na soundcloud [QCon]

for {

user <- authenticate(request)

} yield {

}

Futuros

Page 48: Scala na soundcloud [QCon]

for {

user <- authenticate(request)

geo <- geoLocationFor(request, user)

} yield {

}

Futuros

Page 49: Scala na soundcloud [QCon]

for {

user <- authenticate(request)

geo <- geoLocationFor(request, user)

timeline <- timelineFor(user, geo)

} yield {

}

Futuros

Page 50: Scala na soundcloud [QCon]

for {

user <- authenticate(request)

geo <- geoLocationFor(request, user)

timeline <- timelineFor(user, geo)

resources <-

fetchTracks(timeline)

.join(fetchPlaylists(timeline))

.join(fetchComments(timeline))

} yield {

}

Futuros

Page 51: Scala na soundcloud [QCon]

for {

user <- authenticate(request)

geo <- geoLocationFor(request, user)

timeline <- timelineFor(user, geo)

resources <-

fetchTracks(timeline)

.join(fetchPlaylists(timeline))

.join(fetchComments(timeline))

} yield {

new EnrichedTimeline(timeline, resources)

}

Futuros

Page 52: Scala na soundcloud [QCon]

def handle(request: Request): Future[EnrichedTimeline] =

for {

user <- authenticate(request)

geo <- geoLocationFor(request, user)

timeline <- timelineFor(user, geo)

resources <-

fetchTracks(timeline)

.join(fetchPlaylists(timeline))

.join(fetchComments(timeline))

} yield {

new EnrichedTimeline(timeline, resources)

}

Futuros

Page 53: Scala na soundcloud [QCon]

Futuros

+ NIO

Escalabilidade

Page 54: Scala na soundcloud [QCon]

Máquinas

Page 55: Scala na soundcloud [QCon]

MáquinasProcessos

Page 56: Scala na soundcloud [QCon]

MáquinasProcessosThreads

Page 57: Scala na soundcloud [QCon]

MáquinasProcessosThreadsFuturos

Page 58: Scala na soundcloud [QCon]

def handle(request: Request): Future[EnrichedTimeline] =

for {

user <- authenticate(request)

geo <- geoLocationFor(request, user)

timeline <- timelineFor(user, geo)

resources <-

fetchTracks(timeline)

.join(fetchPlaylists(timeline))

.join(fetchComments(timeline))

} yield {

new EnrichedTimeline(timeline, resources)

}

Futuros

Page 59: Scala na soundcloud [QCon]

Agregar

Funcional

Page 60: Scala na soundcloud [QCon]

Collections

Page 61: Scala na soundcloud [QCon]

val timeline: Timeline = …

Page 62: Scala na soundcloud [QCon]

val timeline: Timeline = …

val actorsToFetch: List[User] =

timeline.items.map(_.actor)

Page 63: Scala na soundcloud [QCon]

val timeline: Timeline = …

val actorsToFetch: List[User] =

timeline.items.map(_.actor)

val itemsByActor: Map[User, List[Item]] =

timeline.items.groupBy(_.actor)

Page 64: Scala na soundcloud [QCon]

val timeline: Timeline = …

val actorsToFetch: List[User] =

timeline.items.map(_.actor)

val itemsByActor: Map[User, List[Item]] =

timeline.items.groupBy(_.actor)

val numberOfItemsByActor: Map[User, Int] =

itemsByActor.mapValues(_.size)

Page 65: Scala na soundcloud [QCon]

def createEnrichedTimeline(

timeline: Timeline,

users: Map[User, EnrichedUser]) = {

timeline.items.map { item =>

new EnrichedItem(

item, users.get(item.actor))

}

}

Page 66: Scala na soundcloud [QCon]

Options

Page 67: Scala na soundcloud [QCon]

Some(value)None

Option[T]

Page 68: Scala na soundcloud [QCon]

def findUser(id: Int): Option[User]

// Não compila

render.json(findUser(666).name)

Options

Page 69: Scala na soundcloud [QCon]

def findUser(id: Int): Option[User]

// Compila

findUser(666).map {

case Some(user) => render.json(user.name)

case None => render.notFound

}

Options

Page 70: Scala na soundcloud [QCon]

PatternMatching

Page 71: Scala na soundcloud [QCon]

case class User(name: String, gender: Gender, email: Email)

Page 72: Scala na soundcloud [QCon]

case class User(name: String, gender: Gender, email: Email)

timelineActors.foreach {

}

Page 73: Scala na soundcloud [QCon]

case class User(name: String, gender: Gender, email: Email)

timelineActors.foreach {

case User(name, Female, Email(_, “soundcloud.com”) =>

println(“mulher trabalhando na soundcloud”)

}

Page 74: Scala na soundcloud [QCon]

case class User(name: String, gender: Gender, email: Email)

timelineActors.foreach {

case User(name, Female, Email(_, “soundcloud.com”) =>

println(“mulher trabalhando na soundcloud”)

case User(name, Male, Email(_, “soundcloud.com”) =>

println(“homem trabalhando na soundcloud”)

}

Page 75: Scala na soundcloud [QCon]

case class User(name: String, gender: Gender, email: Email)

timelineActors.foreach {

case User(name, Female, Email(_, “soundcloud.com”) =>

println(“mulher trabalhando na soundcloud”)

case User(name, Male, Email(_, “soundcloud.com”) =>

println(“homem trabalhando na soundcloud”)

case User(name, gender, Email(_, “qconrio.com.br”) =>

println(“organizador da qconrio”)

}

Page 76: Scala na soundcloud [QCon]

case class User(name: String, gender: Gender, email: Email)

timelineActors.foreach {

case User(name, Female, Email(_, “soundcloud.com”) =>

println(“mulher trabalhando na soundcloud”)

case User(name, Male, Email(_, “soundcloud.com”) =>

println(“homem trabalhando na soundcloud”)

case User(name, gender, Email(_, “qconrio.com.br”) =>

println(“organizador da qconrio”)

case _ =>

println(“pessoa desconhecida”)

}

Page 77: Scala na soundcloud [QCon]

Nem tudo são flores...

Page 78: Scala na soundcloud [QCon]
Page 79: Scala na soundcloud [QCon]

Código denso

def flatMap[B, That] (f: (A) ⇒ Traversable[B]) (implicit bf: CanBuildFrom[

List[A], B, That]): That

Page 80: Scala na soundcloud [QCon]

Código denso

def flatMap[B, That] (f: (A) ⇒ Traversable[B]) (implicit bf: CanBuildFrom[

List[A], B, That]): That

listOfThings.flatMap(_.toUpperCase)

Page 81: Scala na soundcloud [QCon]

XML também é código?

<fruits> <fruit type="banana" origin="brazil"/> <fruit type="apple"/> <fruit type="orange" origin="usa"/> <fruit type="orange" origin="brazil"/></fruits> \\ "fruit"

filter { _ \\ "@origin" exists (_.text == "brazil") }

Page 82: Scala na soundcloud [QCon]
Page 83: Scala na soundcloud [QCon]

Mas e o Stream...?

Page 84: Scala na soundcloud [QCon]

Mas e o Stream...?

APIMySQL

Cassandra

Page 85: Scala na soundcloud [QCon]

Mas e o Stream...?

API

MySQL

RedisTimeline Service

Tracks ServicePlaylists ServiceMultiple Services

Page 86: Scala na soundcloud [QCon]

Mas e o Stream...?

API

MySQL

RedisTimeline Service

Tracks ServicePlaylists ServiceMultiple Services

~150 ms~0% request queueing

Page 87: Scala na soundcloud [QCon]

Mas só o Stream...?

Data teamOutros serviços em ScalaFerramental jvmkit

Page 88: Scala na soundcloud [QCon]

Stranglers

Page 89: Scala na soundcloud [QCon]

Stranglers

Page 90: Scala na soundcloud [QCon]

StranglersNovo

streamCache

Page 91: Scala na soundcloud [QCon]

O presente

Page 92: Scala na soundcloud [QCon]

Em resumo...

Produtivo como Ruby, typesafe como Java*

Move faster break fewer things

Page 93: Scala na soundcloud [QCon]

O futuro

Page 94: Scala na soundcloud [QCon]

Padrões de códigoBibliotecas mais estáveisFacilidade de inovação"One Scala"

O futuro

Page 95: Scala na soundcloud [QCon]

Perguntas?