{ "metadata": { "name": "" }, "nbformat": 3, "nbformat_minor": 0, "worksheets": [ { "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "[Python para Desenvolvedores](http://ricardoduarte.github.io/python-para-desenvolvedores/#conteudo)\n", "===================================\n", "2ª edi\u00e7\u00e3o, revisada e ampliada\n", "-----------------------------------\n", "\n", "Cap\u00edtulo 38: Processamento distribu\u00eddo\n", "=============================\n", "_____________________________\n", "Geralmente a solu\u00e7\u00e3o para problemas que requerem muita pot\u00eancia computacional \u00e9 a utiliza\u00e7\u00e3o de m\u00e1quinas mais poderosas, por\u00e9m esta solu\u00e7\u00e3o \u00e9 limitada em termos de escalabilidade. Uma alternativa \u00e9 dividir os processos da aplica\u00e7\u00e3o entre v\u00e1rias m\u00e1quinas que se comunicam atrav\u00e9s de uma rede, formando um *cluster* ou um *grid*.\n", "\n", "A diferen\u00e7a b\u00e1sica entre *cluster* e *grid* \u00e9 que o primeiro tem como premissa de projeto ser um ambiente controlado, homog\u00eaneo e previs\u00edvel, enquanto o segundo \u00e9 geralmente heterog\u00eaneo, n\u00e3o controlado e imprevis\u00edvel. Um *cluster* \u00e9 um ambiente planejado especificamente para processamento distribu\u00eddo, com m\u00e1quinas dedicadas em um lugar adequado. Um *grid* se caracteriza pelo uso de esta\u00e7\u00f5es de trabalho que podem estar em qualquer lugar.\n", "\n", "![Processamento distribuido](files/bpypd_diags30.png)\n", "\n", "Os modelos mais comuns de *cluster*:\n", "\n", "+ computacional.\n", "+ de recursos.\n", "+ de aplica\u00e7\u00e3o ou h\u00edbrido.\n", "\n", "O modelo computacional tem como objetivo usar processadores e mem\u00f3ria dos equipamentos envolvidos para obter mais pot\u00eancia computacional. A implementa\u00e7\u00e3o geralmente utiliza um sistema escalonador de filas (*metascheduler*), que realiza o agendamento das tarefas a serem processadas pelos n\u00f3s (m\u00e1quinas que comp\u00f5em o modelo), com isso a opera\u00e7\u00e3o tende a ser cont\u00ednua, com intera\u00e7\u00e3o reduzida com os usu\u00e1rios. Um exemplo conhecido \u00e9 o [SETI@home](http://setiathome.berkeley.edu/).\n", "\n", "![Processamento distribuido](files/bpypd_diags31.png)\n", "\n", "O *cluster* de recursos \u00e9 usado para armazenar informa\u00e7\u00f5es em um grupo de computadores, tanto para obter mais performance de recupera\u00e7\u00e3o de dados quanto para expandir a capacidade de armazenamento. Este modelo pode ser usado para prover infra-estrutura para aplica\u00e7\u00f5es ou para atender requisi\u00e7\u00f5es feitas de forma interativa por usu\u00e1rios. Entre os servi\u00e7os que podem operar desta forma est\u00e3o os Sistemas Gerenciadores de Banco de Dados (SGBD), como o [MySQL Cluster](http://www.mysql.com/products/database/cluster/).\n", "\n", "O modelo h\u00edbrido \u00e9 uma aplica\u00e7\u00e3o projetada especificamente para funcionar em v\u00e1rias m\u00e1quinas ao mesmo tempo. Ao inv\u00e9s de prover recursos diretamente, a aplica\u00e7\u00e3o utiliza os equipamentos para suportar suas pr\u00f3prias funcionalidades. Com isso, a infra-estrutura \u00e9 utilizada de forma quase transparente pelos usu\u00e1rios que usam a aplica\u00e7\u00e3o interativamente. Todos os n\u00f3s rodam o aplicativo e podem operar como servidores e clientes. O exemplo mais comum de arquitetura h\u00edbrida s\u00e3o os sistemas de compartilhamento de arquivos (*file sharing*) que usam comunica\u00e7\u00e3o *Peer To Peer* (P2P).\n", "\n", "Independente do modelo utilizado. sistemas distribu\u00eddos devem atender a quatro requisitos b\u00e1sicos:\n", "Comunica\u00e7\u00e3o: as m\u00e1quinas envolvidas devem se comunicar de forma a permitir a troca de informa\u00e7\u00f5es entre elas.\n", "Metadados: os dados sobre o processamento precisam ser mantidos de forma adequada.\n", "Controle: os processos devem ser gerenciados e monitorados.\n", "Seguran\u00e7a: o sigilo, integridade e disponibilidade devem estar protegidos.\n", "\n", "Existem diversas tecnologias voltadas para o desenvolvimento de aplica\u00e7\u00f5es distribu\u00eddas, tais como: [XML-RPC](http://www.xmlrpc.com/), Web Services, objetos distribu\u00eddos, MPI e outras.\n", "\n", "Objetos distribu\u00eddos\n", "--------------------\n", "A premissa b\u00e1sica da tecnologia de objetos distribu\u00eddos \u00e9 tornar objetos dispon\u00edveis para que seus m\u00e9todos possam ser evocados remotamente a partir de outras m\u00e1quinas ou mesmo por outros processos na mesma m\u00e1quina, usando a pilha de protocolos de rede TCP/IP para isso.\n", "\n", "![Processamento distribuido](files/bpypd_diags32.png)\n", "\n", "Existem diversas solu\u00e7\u00f5es para estes casos, por\u00e9m utilizar objetos distribu\u00eddos oferece v\u00e1rias vantagens em rela\u00e7\u00e3o a outras solu\u00e7\u00f5es que implementam funcionalidades semelhantes, tal como o protocolo XML-RPC:\n", "\n", "+ Simplicidade para implementa\u00e7\u00e3o.\n", "+ Oculta as camadas de comunica\u00e7\u00e3o.\n", "+ Suporte a estruturas de dados nativas (contanto que sejam serializ\u00e1veis).\n", "+ Boa performance.\n", "+ Maturidade da solu\u00e7\u00e3o.\n", "\n", "PYthon Remote Objects ([PYRO](http://pyro.sourceforge.net/)) \u00e9 um *framework* para aplica\u00e7\u00f5es distribu\u00eddas que permite publicar objetos via TCP/IP. Na m\u00e1quina servidora, o PYRO publica o objeto, cuidando de detalhes como: protocolo, controle de sess\u00e3o, autentica\u00e7\u00e3o, controle de concorr\u00eancia e outros.\n", "\n", "Exemplo de servidor:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "import Pyro.core\n", "\n", "# A classe Pyro.core.ObjBase define\n", "# o comportamento dos objetos distribu\u00eddos\n", "class Dist(Pyro.core.ObjBase):\n", "\n", " def calc(self, n):\n", "\n", " return n**n\n", "\n", "if __name__ == '__main__':\n", "\n", " # Inicia a thread do servidor\n", " Pyro.core.initServer()\n", "\n", " # Cria o servidor\n", " daemon = Pyro.core.Daemon()\n", "\n", " # Publica o objeto\n", " uri = daemon.connect(Dist(),'dist')\n", "\n", " # Coloca o servidor em estado operacional\n", " daemon.requestLoop()" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Na m\u00e1quina cliente, o programa usa o PYRO para evocar rotinas do servidor e recebe os resultados, da mesma forma que um m\u00e9todo de um objeto local.\n", "\n", "Exemplo de cliente:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "import Pyro.core\n", "\n", "# Cria um objeto local para acessar o objeto remoto\n", "proxy = Pyro.core.getProxyForURI('PYROLOC://127.0.0.1/dist')\n", "\n", "# Evoca um m\u00e9todo do objeto remoto\n", "print proxy.calc(1000)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Os m\u00e9todos publicados atrav\u00e9s do PYRO n\u00e3o podem ser identificados por introspec\u00e7\u00e3o pelo cliente.\n", "\n", "Embora o PYRO resolva problemas de concorr\u00eancia de comunica\u00e7\u00e3o com os clientes que est\u00e3o acessando o mesmo servidor (cada conex\u00e3o roda em uma *thread* separada), fica por conta do desenvolvedor (ou de outros *frameworks* que a aplica\u00e7\u00e3o utilize) resolver quest\u00f5es de concorr\u00eancia por outros recursos, como arquivos ou conex\u00f5es de banco de dados, por exemplo. \u00c9 poss\u00edvel autenticar as conex\u00f5es atrav\u00e9s da cria\u00e7\u00e3o de objetos da classe Validator, que podem verificar credenciais, endere\u00e7os IP e outros itens." ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [ { "html": [ "\n", "" ], "output_type": "pyout", "prompt_number": 1, "text": [ "" ] } ], "prompt_number": 1 } ], "metadata": {} } ] }