Akka 2.0
Chega de multi-threading na unha

            @jcranky
Paulo "JCranky" Siqueira



● desenvolvedor java e scala
● consultor independente
● instrutor globalcode
● um dos fundadores dos Scaladores
Concorrência de forma correta?
Tolerância a falhas?
Abstração!

● em OO aprendemos a abstrair conceitos
● programação concorrente não pode ser
  abstraída?
● porque nos preocupar com Threads?
● e com locks?
● e em fazer isso direito...
Akka 2.0


● inspirado em Erlang
● abstrai preocupações baixo nível
● pensamos mais nos problemas de negócio
● API Java e Scala
● Actor Model !
Actor Model
● entidades independentes
● estado
● comportamento
● mailbox
● como uma classe em OO...
● ... mas mais "pura"
Actor Model

mensagens      mailbox



              Comportamento



              Estado
Actor Model



● comunicação com troca de mensagens
● "event-driven"
● sempre assíncrono
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...
Escalabilidade...



● horizontal e vertical
● nosso foco é a vertical
● a horizontal seria fácil com atores remotos
Threads... cadê?


● Akka cria as threads necessárias
● ator != thread
● atores usando threads disponíveis
● akka fornece uma thread para o ator
● sem locks
Divisão de trabalho

● threads usando os "cores" disponíveis
● fork-join por padrão
● fork-join estará no Java 8...
● ... mas já está embutido no Akka
● tudo configurável
config. extraída da documentação:
fork-join-executor {
    # Min number of threads to cap factor-based parallelism number to
    parallelism-min = 8

    # Parallelism (threads) ... ceil(available processors * factor)
    parallelism-factor = 3.0

    # Max number of threads to cap factor-based parallelism number to
    parallelism-max = 64
}
Imutabilidade


● origem de muitos problemas
● para não precisar de locks
● nunca teremos deadlocks
● desnecessário sincronizar acesso ao estado
Uma mensagem - Scala



case class SendToS3(fileName: String)
Uma mensagem - Java
public class SendToS3 {
  private final String fileName;

    public SendToS3(String fileName) {
      this.fileName = fileName;
    }

    public String getFileName() {
      return fileName;
    }
}
Um ator - Scala


class S3SenderActor extends Actor {
  def receive = {
    case SendToS3(fileName) =>
     // lógica de negócios aqui
  }
}
Um ator - Java

public class S3SenderActor extends UntypedActor {
  public void onReceive(Object message)
         throws Exception {
     if (message instanceof String)
         // lógica de negócios aqui
     else
         unhandled(message);
    }
}
Lidando com alteração de estado

● atores não devem compartilhar estado
● um único ator será responsável pelos dados
● acesso a BD pode ser enfileirado
● ou atores responsáveis por "fatias" de dados
● veremos exemplo disso mais adiante
Criando atores

● métodos / classes especiais
● atores criados abaixo da raiz do nó principal
● ... ou relativos ao contexto atual
● todo ator tem um "pai"
● veremos mais sobre isso adiante
Criando um ator - Scala
val system = ActorSystem("MyActorSystem")

// ator com construtor default
val ator =
  system.actorOf(Props[S3SenderAtor])

// ator com outro construtor
val ator2 =
  system.actorOf(Props(new Ator(<params>)))
Criando um ator - Java
ActorSystem system =
  ActorSystem.create("MyActorSystem");

// ator com construtor default
ActorRef ator = system.actorOf(
    new Props(S3SenderActor.class));
Criando um ator - Java
// ator com outro construtor
ActorRef ator2 = system.actorOf(
    new Props(new UntypedActorFactory() {
      public UntypedActor create() {
         return new Ator(<params>);
      }
   })
);
Protegendo o estado


val minhaInstancia = new Ator(<params>)

// erro em runtime
val ator2 =
  system.actorOf(Props(minhaInstancia))
Atores relativos ao contexto


● todo ator tem um campo "context"
● esse campo pode criar novos atores
● esses atores serão "filhos" do ator atual


context.actorOf(Props[S3SenderActor])
"let it crash"

● tolerância a falhas
● não evitamos que atores quebre
● e decidimos o que fazer quando acontecer
● todo ator é supervisionado (2.0+)
● o supervisor decide o que fazer
Hierarquia de atores

                  A




          B            C




     D        E            F
Hierarquia de atores

                  A




          B            C




     D        E            F
Hierarquia de atores

                 A



                       C




                           F
Hierarquia de atores

                  A




          B            C




     D        E            F
Config. de tolerância a falhas - Scala
override val supervisorStrategy =
 OneForOneStrategy(
  maxNrOfRetries = 10, withinTimeRange = 1 minute) {

    case _: ArithmeticException ⇒ Resume
    case _: NullPointerException ⇒ Restart
    case _: IllegalArgumentException ⇒ Stop
    case _: Exception ⇒ Escalate

}
Config. de tolerância a falhas - Java
private static SupervisorStrategy strategy =
 new OneForOneStrategy(10, Duration.parse("1 minute"),
 new Function<Throwable, Directive>() {
   @Override
   public Directive apply(Throwable t) {
     if (t instanceof ArithmeticException) {
       return resume();
     } else if (t instanceof NullPointerException) {
       return restart();
     } else if (t instanceof IllegalArgumentException) {
       return stop();
     } else {
       return escalate();
     }
   }
 });
Config. de tolerância a falhas - Java

@Override
public SupervisorStrategy supervisorStrategy() {
  return strategy;
}




obs: exemplos de configs extraídos da doc.
Ponto para divisão de tarefas


● recomenda-se quebrar as tarefas
● roteadores são uma forma de fazer isso
● definem grupos de atores
● e o roteador divide as mensagens
Exemplo roteador - Scala


val s3SenderRouter = system.actorOf(
  Props[S3SenderActor].withRouter(
   SmallestMailboxRouter(2))
)
Exemplo roteador - Java


ActorRef s3SenderRouter = system.actorOf(
  new Props(S3SenderActor.class).withRouter(
   new SmallestMailboxRouter(2))
);
Projeto Open Source: Lojinha



● Scala
● Akka 2.0
● Play Framework 2.0
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."
Atores da Lojinha

                                 Play Akka
                                  System



                                                                  Image
      Master Bid
                                                                  Thumb
        Actor
                                                                  Router
                                S3 Sender
                                 Router




                                                                  Image
       Process
                                                                  Thumb
       Bid Actor
                                S3 Sender                          Actor
                                  Actor
um para cada produto                                  vários, conforme configurado
                       vários, conforme configurado
código!


● lojinha no NetBeans...
● ... se der tempo
● senão, está tudo no github =)
Referências


● site oficial: akka.io
● meu blog: jcranky.com
● meu twitter: twitter.com/jcranky
● lojinha, no github: https://github.
  com/jcranky/lojinha
coming soon...

● curso de Scala na Globalcode
● mais informações nas próximas semanas
● tópicos principais:
   ○ Scala
   ○ Akka
   ○ Play Framework
Questions?




             ?
thanks!


 @jcranky

Akka no Just Java 2012

  • 1.
    Akka 2.0 Chega demulti-threading na unha @jcranky
  • 2.
    Paulo "JCranky" Siqueira ●desenvolvedor java e scala ● consultor independente ● instrutor globalcode ● um dos fundadores dos Scaladores
  • 3.
  • 4.
  • 5.
    Abstração! ● em OOaprendemos a abstrair conceitos ● programação concorrente não pode ser abstraída? ● porque nos preocupar com Threads? ● e com locks? ● e em fazer isso direito...
  • 6.
    Akka 2.0 ● inspiradoem Erlang ● abstrai preocupações baixo nível ● pensamos mais nos problemas de negócio ● API Java e Scala ● Actor Model !
  • 7.
    Actor Model ● entidadesindependentes ● estado ● comportamento ● mailbox ● como uma classe em OO... ● ... mas mais "pura"
  • 8.
    Actor Model mensagens mailbox Comportamento Estado
  • 9.
    Actor Model ● comunicaçãocom troca de mensagens ● "event-driven" ● sempre assíncrono
  • 10.
    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...
  • 11.
    Escalabilidade... ● horizontal evertical ● nosso foco é a vertical ● a horizontal seria fácil com atores remotos
  • 12.
    Threads... cadê? ● Akkacria as threads necessárias ● ator != thread ● atores usando threads disponíveis ● akka fornece uma thread para o ator ● sem locks
  • 13.
    Divisão de trabalho ●threads usando os "cores" disponíveis ● fork-join por padrão ● fork-join estará no Java 8... ● ... mas já está embutido no Akka ● tudo configurável
  • 14.
    config. extraída dadocumentação: fork-join-executor { # Min number of threads to cap factor-based parallelism number to parallelism-min = 8 # Parallelism (threads) ... ceil(available processors * factor) parallelism-factor = 3.0 # Max number of threads to cap factor-based parallelism number to parallelism-max = 64 }
  • 15.
    Imutabilidade ● origem demuitos problemas ● para não precisar de locks ● nunca teremos deadlocks ● desnecessário sincronizar acesso ao estado
  • 16.
    Uma mensagem -Scala case class SendToS3(fileName: String)
  • 17.
    Uma mensagem -Java public class SendToS3 { private final String fileName; public SendToS3(String fileName) { this.fileName = fileName; } public String getFileName() { return fileName; } }
  • 18.
    Um ator -Scala class S3SenderActor extends Actor { def receive = { case SendToS3(fileName) => // lógica de negócios aqui } }
  • 19.
    Um ator -Java public class S3SenderActor extends UntypedActor { public void onReceive(Object message) throws Exception { if (message instanceof String) // lógica de negócios aqui else unhandled(message); } }
  • 20.
    Lidando com alteraçãode estado ● atores não devem compartilhar estado ● um único ator será responsável pelos dados ● acesso a BD pode ser enfileirado ● ou atores responsáveis por "fatias" de dados ● veremos exemplo disso mais adiante
  • 21.
    Criando atores ● métodos/ classes especiais ● atores criados abaixo da raiz do nó principal ● ... ou relativos ao contexto atual ● todo ator tem um "pai" ● veremos mais sobre isso adiante
  • 22.
    Criando um ator- Scala val system = ActorSystem("MyActorSystem") // ator com construtor default val ator = system.actorOf(Props[S3SenderAtor]) // ator com outro construtor val ator2 = system.actorOf(Props(new Ator(<params>)))
  • 23.
    Criando um ator- Java ActorSystem system = ActorSystem.create("MyActorSystem"); // ator com construtor default ActorRef ator = system.actorOf( new Props(S3SenderActor.class));
  • 24.
    Criando um ator- Java // ator com outro construtor ActorRef ator2 = system.actorOf( new Props(new UntypedActorFactory() { public UntypedActor create() { return new Ator(<params>); } }) );
  • 25.
    Protegendo o estado valminhaInstancia = new Ator(<params>) // erro em runtime val ator2 = system.actorOf(Props(minhaInstancia))
  • 26.
    Atores relativos aocontexto ● todo ator tem um campo "context" ● esse campo pode criar novos atores ● esses atores serão "filhos" do ator atual context.actorOf(Props[S3SenderActor])
  • 27.
    "let it crash" ●tolerância a falhas ● não evitamos que atores quebre ● e decidimos o que fazer quando acontecer ● todo ator é supervisionado (2.0+) ● o supervisor decide o que fazer
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
    Config. de tolerânciaa falhas - Scala override val supervisorStrategy = OneForOneStrategy( maxNrOfRetries = 10, withinTimeRange = 1 minute) { case _: ArithmeticException ⇒ Resume case _: NullPointerException ⇒ Restart case _: IllegalArgumentException ⇒ Stop case _: Exception ⇒ Escalate }
  • 33.
    Config. de tolerânciaa falhas - Java private static SupervisorStrategy strategy = new OneForOneStrategy(10, Duration.parse("1 minute"), new Function<Throwable, Directive>() { @Override public Directive apply(Throwable t) { if (t instanceof ArithmeticException) { return resume(); } else if (t instanceof NullPointerException) { return restart(); } else if (t instanceof IllegalArgumentException) { return stop(); } else { return escalate(); } } });
  • 34.
    Config. de tolerânciaa falhas - Java @Override public SupervisorStrategy supervisorStrategy() { return strategy; } obs: exemplos de configs extraídos da doc.
  • 35.
    Ponto para divisãode tarefas ● recomenda-se quebrar as tarefas ● roteadores são uma forma de fazer isso ● definem grupos de atores ● e o roteador divide as mensagens
  • 36.
    Exemplo roteador -Scala val s3SenderRouter = system.actorOf( Props[S3SenderActor].withRouter( SmallestMailboxRouter(2)) )
  • 37.
    Exemplo roteador -Java ActorRef s3SenderRouter = system.actorOf( new Props(S3SenderActor.class).withRouter( new SmallestMailboxRouter(2)) );
  • 38.
    Projeto Open Source:Lojinha ● Scala ● Akka 2.0 ● Play Framework 2.0
  • 39.
    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."
  • 40.
    Atores da Lojinha Play Akka System Image Master Bid Thumb Actor Router S3 Sender Router Image Process Thumb Bid Actor S3 Sender Actor Actor um para cada produto vários, conforme configurado vários, conforme configurado
  • 41.
    código! ● lojinha noNetBeans... ● ... se der tempo ● senão, está tudo no github =)
  • 42.
    Referências ● site oficial:akka.io ● meu blog: jcranky.com ● meu twitter: twitter.com/jcranky ● lojinha, no github: https://github. com/jcranky/lojinha
  • 43.
    coming soon... ● cursode Scala na Globalcode ● mais informações nas próximas semanas ● tópicos principais: ○ Scala ○ Akka ○ Play Framework
  • 44.
  • 45.