Atendendo Milhares de Requisições com o Play Framework 2 - v2
Entendendo o modelo de atores
1. Entendendo o modelo de
atores
programação concorrente e distribuída de
verdade
Paulo “JCranky” Siqueira
jcranky.com / @jcranky
2. Paulo "JCranky" Siqueira
• desenvolvedor Java e Scala
• consultor independente
• instrutor globalcode
– e criador do curso Core Scala
• um dos fundadores dos Scaladores
7. 1a Opção na JVM: Threads
● Forma “natural” para concorrência
– Um processo, pelo menos uma thread,
possivelmente várias
– Temos que controlar “na mão” essas
threads
8. Em tempo: o processador!
● Para tarefas intensas, não importa
quantas threads...
● Concorrência real, só mais de um núcleo
– (o que não é difícil hoje em dia)
18. Nossa nova filosofia
● Podem esquecer tudo, menos isso!
● mutabilidade isolada
● imutabilidade compartilhada
19. Na mão? Mesmo?
● Java 5 / 6 trouxeram diversas melhorias
– controlar Threads não é mais tão difícil
– mas ainda assim, não é trivial
20. Abstração!
• que tal abstrair programação concorrente?
• porque nos preocupar com Threads?
– e com locks?
– e em fazer isso direito...
21. Enter the “Actor Model”
• entidades independentes
– estado
– comportamento
– mailbox
• como uma classe em OO...
• ... mas mais "pura" (e com a tal da mailbox)
24. Actor Model
• comunicação com troca de mensagens
• "event-driven"
• sempre assíncrono
25. Akka 2.0
• inspirado em Erlang
• abstrai preocupações baixo nível
• pensamos mais nos problemas de negócio
26. Akka 2.0
• API Java e Scala
• Actor Model !
• Open Source
27. Abstração == Overhead?
• overhead do Akka é ínfimo
• extraído da página oficial:
"50 million msg/sec on a single machine."
• obviamente, em um micro-benchmark...
• em uma máquina com 48 núcleos
29. Onde estão as Threads ??
• Akka cria as threads necessárias
• ator != thread
• atores usam threads disponíveis
• akka fornece uma thread para o ator
• sem locks
30. Divisão de trabalho
• threads usando os "cores" disponíveis
• fork-join por padrão
– com algumas melhorias que devem estar
no Java 8...
• ... mas já está embutido no Akka
• tudo configurável
31. config. extraída da documentação:
forkjoinexecutor {
# Min number of threads to cap factorbased parallelism number to
parallelismmin = 8
# Parallelism (threads) ... ceil(available processors * factor)
parallelismfactor = 3.0
# Max number of threads to cap factorbased parallelism number to
parallelismmax = 64
}
38. Lidando com alteração de estado
• Atores não devem compartilhar estado
– somente ele mesmo acessa seus dados
• Acesso a BD poderia ser enfileirado
– ou atores com "fatias" de dados
39. Criando atores
• métodos / classes especiais
• criados abaixo de um nó principal
– ... ou relativos ao contexto atual
• todo ator tem um "pai"
• resultando em uma hierarquia de atores
45. "let it crash"
• tolerância a falhas
• não evitamos que atores quebrem
• decidimos o que fazer quando falhar
– o supervisor decide o que fazer
• todo ator é supervisionado (2.0+)
50. Config. de tolerância a falhas
override val supervisorStrategy =
OneForOneStrategy(
MaxNrOfRetries = 10,
withinTimeRange = 1 minute) {
case _: ArithmeticException ⇒ Resume
case _: NullPointerException ⇒ Restart
case _: IllegalArgumentException ⇒ Stop
case _: Exception ⇒ Escalate
}
51. Dividir para conquistar, outra vez
• quebrar tarefas em pedaços pequenos
• roteadores são uma forma de fazer isso
– definem grupos de atores
– e divide as mensagens
58. Atores remotos
● akka suporta atores remotos
● ajustamos a configuração
● ajustamos o código para usar a config.
59. Atores remotos
● código cliente de atores continua igual
● para o emitente da mensagem, atores
remotos e locais são iguais
● “Atores locais são como otimizações”
60. Ator a partir de configuração
context.actorOf(Props[MeuAtor]
.withRouter(FromConfig()),"nomeator")
61. Tá difícil mesmo assim?
Akka Cluster
●
● atores remotos, com menos configuração
● mais inteligência para suportar nós
entrando e saindo do cluster
● em testes, previsto para Akka 2.1
62. Atores remotos
● cuidados básicos:
● quantidade de mensagens
● tamanho das mensagens
● delay em relação a atores locais
● tudo afeta o design dos atores
● portanto, o código
63. bonus: composição async com Futures
● possibilita código totalmente sem block
● usamos callbacks
● executados quando uma resposta chegar
● ou Futuros, e compomos o resultado final
64. bonus: composição async com Futures
val colorFuture = for {
r < (rPartChooser ? FindColorPart)
.mapTo[ColorPartFound]
g < (gPartChooser ? FindColorPart)
.mapTo[ColorPartFound]
b < (bPartChooser ? FindColorPart)
.mapTo[ColorPartFound]
} yield (r.value, g.value, b.value)
66. Projeto Open Source: Lojinha
• um ator para lances de cada produto
• aguentaria milhões de produtos
• da página oficial do Akka:
"Small memory footprint; ~2.7 million actors per
GB of heap."
67. Atores da Lojinha
Play Akka
System
Image
Master
Thumb
Bid Actor
Router
S3
Sender
Router
Image
Process
Thumb
Bid Actor S3
Actor
Sender
Actor
um para cada produto vários, conforme configurado
vários, conforme configurado
68. Referências
• Programming Concurrency on the JVM,
Venkat Subramariam
• akka.io