Share
Embed
Akka - Uma plataforma para o desenvolvimento de sistemas concorrentes e distribuídos para a JVM
Uma descrição da plataforma Akka, descrição do que são atores, e outras funcionalidades providas, com exemplos para Java.
Daniel Capo Sobral
June 04, 2012
Transcript
51 slides
-
Akka Uma plataforma para o desenvolvimento de sistemas concorrentes e
distribuídos para a JVM • Daniel Capó Sobral • Consultor pela Tecnisys • Programador e Sysadmin • Ex-committer FreeBSD • Aficionado por Scala -
Akka Uma plataforma para o desenvolvimento de sistemas concorrentes e
distribuídos para a JVM Conheça Akka, uma plataforma para o JVM para desenvolvimento de sistemas concorrentes e/ou distribuídos através do paradigma de Atores. Descreveremos o paradigma de atores, suas vantagens e desvantagens, e mostraremos exemplos da API em Java e em Scala, com execução local e distribuída, memória transacional e tolerância a falhas. -
Conteúdo • O que é Akka? • Para que serve?
• O que são atores? Objetivos Principais • Ensinar Akka • Ensinar programação com atores • Mostrar todos os módulos de Akka Não é tema -
Uma cadeia de montanhas? • “Akka” é uma cadeia de
montanhas na Suécia -
Um componente do Typesafe Stack? • A Typesafe foi fundada
em 2011 pelos criadores da linguagem de programação Scala e do middleware Akka. • O Typesafe Stack contém Scala, Akka e ferramentas de desenvolvimento, tudo open source. • A Typesafe Subscription provê suporte comercial. -
Uma solução de: • Atores • STM • Agentes •
Dataflow Concorrência Escalabilidade Tolerância à Falhas -
Uma solução de: Concorrência • Vertical • Atores • Horizontal
• Atores Remotos • Gestão de Cluster Escalabilidade Tolerância à Falhas -
Uma solução de: Concorrência Escalabilidade • Supervisão de Atores •
Todos Por Um • Cada Um Por Si • “Deixe falhar” Tolerância à Falhas -
Atores • Popularizou o conceito • 9 9s de disponibilidade
Erlang • Atores como prova de conceito Scala • Novo design • Solução completa Akka -
Objetos vs Atores • Públicos • Privados Métodos • Rascunho
• Estático • Dinâmico Estado -
Objetos vs Atores • Públicos • Privados Métodos • Rascunho
• Estático • Dinâmico Estado • Orientado a eventos Thread -
Fatos sobre Atores • Assíncronos • Threads próprios Orientados à
eventos • Caixa de mensagens • Não compartilham estado! Comunicação via mensagens • Atores não são threads • Aproximadamente 600 bytes Baratos -
Definindo um Ator - Java public class SampleUntypedActor extends UntypedActor
{ public void onReceive(Object message) throws Exception { if (message instanceof String) EventHandler.info(this, String.format("Received String message: %s", message)); else throw new IllegalArgumentException("Unknown message: " + message); } } -
Criando um Ator - Java import static akka.actor.Actors.*; ActorRef myActor
= actorOf(SampleUntypedActor.class); myActor.start(); // Construtor com parâmetros ActorRef actor = actorOf(new UntypedActorFactory() { public UntypedActor create() { return new MyUntypedActor("service:name", 5); } }).start(); -
ActorRef vs Actor • Serializável • Remote-aware Portabilidade • Actor
é membro privado de ActorRef Opacidade • Actor this • ActorRef self this vs self -
Ciclo de Vida New • Não processa mensagens Started •
Iniciado com “start” • Processa mensagens Shutdown • Iniciado com “exit” ou “stop” • Não pode fazer nada -
Enviando uma mensagem • actor.sendOneWay("Hello"); Envie e esqueça • actor.sendOneWay("Hello",
getContext()); Envie, com remetente • Object result = actorRef.sendRequestReply("Hello", getContext(), 1000); Envie, talvez receba resposta (ou exceção) • Future future = actorRef.sendRequestReplyFuture("Hello", getContext(), 1000); Envie, receba futuro -
Futuros interface Future<T> { void await(); boolean isCompleted(); boolean isExpired();
long timeoutInNanos(); Option<T> result(); Option<Throwable> exception(); Future<T> onComplete(Procedure<Future<T>> procedure); } -
Usando Futuros - Java Future future = actorRef.sendRequestReplyFuture("Hello", getContext(), 1000);
future.await(); if (future.isCompleted()) { Option resultOption = future.result(); if (resultOption.isDefined()) { Object result = resultOption.get(); ... } ... // whatever } -
Respondendo ao Remetente - Java public void onReceive(Object message) throws
Exception { if (message instanceof String) { String msg = (String)message; if (msg.equals("Hello") && getContext().getSenderFuture().isDefined()) { // Reply to original sender of message using the channel getContext().channel().sendOneWay(msg + " from " + getContext().getUuid()); } } } -
Respondendo Mensagem - Java public void onReceive(Object message) throws Exception
{ if (message instanceof String) { String msg = (String)message; if (msg.equals("Hello")) { if (getContext().replySafe(msg + " from " + getContext().getUuid())) ... // success else ... // handle failure } } } -
Akka em Scala • router.tell(new Work(arg, nrOfElements), getContext()); • router
! Work(arg, nrOfElements) Concisão • val a = actorOf(new MyActor(..)).start() Parâmetros “by-name” • Ver exemplo de concisão acima! Parâmetros implícitos -
Akka em Scala • case class Work(arg: Int, nrOfElements: Int)
• Coleções imutáveis por default • Estruturas de dados persistentes Melhor suporte a imutabilidade • case Work(arg, n) => // do stuff Pattern matching -
Typed Actors • Requer Interface + Implementation POJO -> TypedActors
• AspectWerkz Proxy AOP • Métodos viram mensagens assíncronas! Objetos -> Atores -
Agentes Inspirado nos Agentes de Clojure • Uma modificação de
cada vez • Modificações de cada origem processadas em ordem Modificações Assíncronas • Toma parte em transações Integrado ao STM • Valor “atual” após todas modificações enfileiradas Futuros -
Agentes - Scala • val agent = Agent(5) • agent.close()
Criando e Parando • agent send 7 • agent send (_ + 1) Alterando • val result = agent() • val result = agent.future.await.result.get Lendo -
STM • Estado compartilhado • Transações multi-atores (transactors) Mutabilidade Controlada
Modelo Clojure de Referências Multiverse STM -
STM - Java final Ref<Integer> ref = new Ref<Integer>(0); public
int counter() { return new Atomic<Integer>() { public Integer atomically() { int inc = ref.get() + 1; ref.set(inc); return inc; } }.execute(); } -
Dataflow • Mesmo resultado todas as vezes • Baseado em
futuros • Scala Delimited Continuations Concorrência Determinística Derivado da linguagem Oz • Exceções, data/hora, números aleatórios, etc Nada de efeitos colaterais! -
Dataflow - Scala • val x = Promise[Int]() Declarar variável
dataflow • flow { ... x() ... } Usar valor • flow { ... x << 5 ... } Assinalar valor • flow { ... x << y ... } Assinalar a uma outra variável -
Escalabilidade • Atores • Dataflow Vertical • Atores Remotos •
Gestão de Cluster Horizontal -
Atores Remotos - Java // server code class HelloWorldActor extends
UntypedActor { public void onReceive(Object msg) { getContext().replySafe(msg + " World"); } } remote().start("localhost", 9999).register( "hello-service", actorOf(HelloWorldActor.class)); // client code ActorRef actor = remote().actorFor( "hello-service", "localhost", 9999); Object res = actor.sendRequestReply("Hello"); -
Tolerância à Falhas • Não se proteja de exceções •
Deixe outro lidar com o problema Deixe falhar... • Erlang OTP • Proteção em Profundidade Supervisores • OneForOne • AllForOne Estratégias de Supervisão -
Tolerância à Falhas • Recuperável • Não-recuperável Estado • Antes
da reinicialização • Depois da reinicialização Ganchos de reinicialização • Permanente • Temporário Ciclo de vida -
Só isso? • getContext().forward(message, getContext()); Encaminhando mensagens para outro Ator
• become(scatter); • actor ! HotSwap( self => { case message => self.reply("hotswapped body") }) Alterando o comportamento de um ator -
Só isso? • Por eventos • Por thread • Eventos
priorizados • Eventos com work-stealing Dispatcher • Dispatcher (roteador, não módulo) • Load balance • Actor pool Routing • Usados por atores, agentes, dataflow e outros componentes Futuros