Objetos Distribuídos Nazareno Andrade O Problema Orientação a objetos é um paradigma poderoso Porque distribuir os objetos: Modularidade, extensibilidade, manutenibilidade Localidade dos objetos Tolerância a falhas Performance Como estender o modelo OO para sistemas distribuídos? Referências, invocações de métodos, erros, ... O Modelo local remote invocation B A C local E invocation invocation local invocation D remote invocation Um Objeto Remoto é aquele que pode receber uma invocação remota (RMI) Referências remotas Interfaces remotas F Referências e Interfaces Remotas Referências remotas Identificador único para um objeto no sistema distribuído Transparência de localidade para o cliente Interfaces remotas Definem os métodos de um objeto que podem receber invocações remotas Linguagem de definição de interface (IDL) C Interface m1 remota m2 A m1 m2 m3 L Semântica de Invocações remotas Invocações locais são executadas exatamente uma vez Isso não é possível em Objetos Distribuídos Falhas Outras semânticas: talvez, pelo menos uma vez, no máximo uma vez Mais sobre semânticas Mecanismo de tolerância a falhas Retransmissão de request Filtro de duplicatas Re-execução do método ou retransmissão do reply Não --- --- Sim Não Re-execução do método Sim Sim Retransmissão do reply Semântica Mais sobre semânticas Mecanismo de tolerância a falhas Semântica Retransmissão de request Filtro de duplicatas Re-execução do método ou retransmissão do reply Não --- --- Talvez Sim Não Re-execução do método No mínimo uma vez Sim Sim Retransmissão do reply No máximo uma vez RMI e transparência 100% de transparência é impossível Falhas de comunicação RMIs possuem exceções intrínsecas Transparência pode não ser desejada Explorar diferentes semânticas Cancelamento de requisições Um exemplo: Quadro negro distribuído Clientes compartilham um quadro negro Todos podem adicionar e modificar figuras Todos se mantém atualizados via polling createShape, getAllShapes DrBd Cliente getState, setState shape shape DrawingBoard, Shape e GraphicalObject Tecnologias Java RMI .Net remoting Java apenas Integração com a linguagem Solução proprietária da Microsoft Integrada com a linguagem CORBA Independente de linguagem Diferentes implementações Exemplo: Java RMI import java.rmi.*; public interface DrawingBoard extends Remote { Shape createShape(GraphicalObject g) throws RemoteException; List getAllShapes() throws RemoteException; } public interface Shape extends Remote { GraphicalObject getState() throws RemoteException; void setState(GraphicalObject g) throws RemoteException } public class DrawingBoardServer extends UnicastRemoteObject implements DrawingBoard {...} Exemplo: CORBA interface DrawingBoard { Shape createShape(in GraphicalObject g); All getAllShapes(); } Typedef sequence<Shape, 100> All; interface Shape { GraphicalObject getState(); void setState(in GraphicalObject g) } struct GraphicalObject { ... } Serialização x Referência Remota Objetos não-remotos são passados por cópia Objetos remotos têm uma referência remota passada getAllShapes Ref remota para shape GraphicalObject Cliente setState referência remota DrBd shape cópia serializada Até agora... Porque Objetos Distribuídos Conceitos Básicos Tecnologia Exemplo Arquitetura de um sistema de Objetos Distribuídos Limitações e alternativas Conclusões Arquitetura de um Sistema de Objetos Distribuídos cliente C servidor Proxy p/ B Request B Módulo de Ref. remota Skeleton e Dispatcher da classe de B Reply Módulo de comunicação • Implementa interface remota • Torna o RMI transparente • Serializa requests e desserializa replys • Cria referências remotas e locais envolvidas no RMI Módulo de comunicação • Implementa o protocolo de reply response Dispatcher: • Recebe msgs do módulo de comunicação e invoca o skeleton apropriado S Módulo de Ref. remota Skeleton: • Implementa métodos da interface remota • Desserializa requests e serializa replys Binder Binder Objetos precisam descobrir referências remotas Nome Nome DrawingBd Object2 Ref Ref refToDrBd refToObj2 Object2 redToObj2 lookup O binder mapeia nomes para referências remotas bind(), rebind(), unbind() O binder precisa rodar em um nome bem conhecido CORBA Naming Service e RMIregistry bind C Proxy DrBd Um exemplo funcional, cliente public class Client { public void main(String args[]){ DrawingBoard db = null; try{ // o servidor se registrou com WELLKNOWN_NAME db = (DrawingBoard) Naming.lookup(WELLKNOWN_NAME); }catch(Exception e){ // Esta exceção pode ser Remote, Malformed ou // NotBoundException System.err.println(“Could not lookup server. Reason: ” + e.getMessage()); System.exit(1); } … //continua Exemplo funcional, cliente … // ainda dentro do main() try{ List allShapes = db.getAllShapes(); Iterator it = allShapes.iterator(); while(it.hasNext()){ Shape s = (Shape) it.next(); display(s.getState()); } }catch(RemoteException e){ System.err.println(“comm. error:” + e.getMessage()); } } // main } // class public class DrawingBoardServer { public static void main(String args[]){ System.setSecurityManager(new RMISecurityManager()); try{ DrawingBoard db = new DrawingBoard(); Naming.rebind(“Drawing Board XPTO", db); System.out.println(“DB server ready"); }catch(Exception e) { ... } } } public class DrawingBoardImpl extends UnicastRemoteObject implements DrawingBoard{ private List<Shape> theList; public Shape newShape(GraphicalObject g) throws RemoteException{ version++; Shape s = new ShapeImpl(g); theList.addElement(s); return s; } public Vector getAllShapes()throws RemoteException{ return theList; } } public class GraphicalObject implements Serializable{ … } Mais questões práticas E se queremos adicionar novas classes que implementam Shape no sistema? Como os objetos não-remotos são passados? E se queremos adicionar novas classes que extendem GraphicalObject? De onde os clientes obterão o código? E se o código não for em apenas uma linguagem? Outras questões Garbage collection distribuído Threads no servidor Coordenação entre cliente e servidor, detecção de falhas Uma alternativa são leases Multithreading precisa ser tratado pelo programador Activation service Redução do custo de manter serviços rodando Limitações de Objetos Distribuídos Invocações de métodos são síncronas Componentes são fortemente acoplados Escalabilidade Conexão intermitente Extensibilidade Alternativas: RMI assíncrono (conexão intermitente) Sistemas baseados em eventos (escalabilidade, extensibilidade) Arquiteturas orientadas a serviços (todos os pontos) RMI assíncrono A partir de CORBA 2.3 Implementado no lado cliente Callback Cliente informa objeto que receberá resposta Polling Cliente recebe um handle para requisitar resposta mais tarde RMI vs. Mensagens RMI é uma boa idéia para um cliente-servidor simples? E em um sistema de transferência de arquivos? E em um sistema onde posso ter milhões de clientes? E quando quero desempenho? E quando quero desenvolver rápido? Sumário Objetos distribuídos oferecem abstrações poderosas para o programador Transparência total é impossível O programador pode ou deve lidar com outros serviços Falhas Ex.: descoberta e ativação Limitações do paradigma e alternativas Para mais Sobre objetos distribuídos Distributed Systems Concepts and Design, Coulouris, Dollimore e Kindberg Objetos Distribuídos x Serviços Estudos de caso com Java RMI e Corba Mais sobre Sistemas baseados em eventos Web Services are not Distributed Objects, Vogel, IEEE Computing ou no blog dele .Net Remoting .Net Remoting, Strawmyer (http://www.developer.com/net/cplus/article.php/1 479761) Exemplo .Net Remoting: 1 using using using using System; System.Runtime.Remoting; System.Runtime.Remoting.Channels; System.Runtime.Remoting.Channels.Tcp; namespace CodeGuru.Remoting { public class SampleObject : MarshalByRefObject{ public SampleObject() { } public string HelloWorld() { return "Hello World!"; } } } Exemplo .Net Remoting: 2 public class SampleServer { public static int Main(string [] args) { TcpChannel channel = new TcpChannel(8080); ChannelServices.RegisterChannel(channel); RemotingConfiguration.RegisterWellKnownSer viceType( typeof(SampleObject), "HelloWorld", WellKnownObjectMode.SingleCall ); System.Console.WriteLine("Press the enter key to exit..."); System.Console.ReadLine(); return 0; } }