Integração de Aplicações em Python - ark 4 n

Propaganda
Integração de aplicações em
Luiz Eduardo Borges
http://ark4n.wordpress.com/
Sumário
●
Integração de aplicações
●
Aplicações distribuídas
●
Camada de comunicação
●
Formatos de dados
●
Aplicações externas
Integração de aplicações (tradicional)
Aplicação
A
Aplicação
B
Bibliotecas
Dados e regras de
negócio precisam
estar em um SGBD
para garantir a
integridade e sigilo.
Dados
Funções
disponíveis para
as aplicações.
Ambiente que requer
muita administração
para se manter
organizado.
Integração através de middleware
Aplicação
A
Regras de negócio
podem ficar em
componentes.
Aplicação
B
Middleware
Dados
Funções
disponíveis para
todas as
aplicações.
O ambiente requer
muita padronização
para se manter
organizado.
Middleware
●
●
●
É uma camada de software que conecta componentes
ou aplicações, tendo como o objetivo a
interoperabilidade.
Várias opções:
–
ZOPE (Z Object Publishing Environment)
–
WSGI (Web Server Gateway Interface)
–
Twisted
–
Muitos outros
O próprio Python pode ser encarado como um
middleware.
Aplicações distribuídas
Arquiteturas:
●
Computacional
●
De recursos
●
De aplicação ou híbrida
Modelo computacional
O servidor distribui as
requisições e centraliza os
resultados.
A
B
C
D
Os outros nós (workers)
recebem as tarefas e
calculam os resultados.
Modelo de recursos
A
B
C
D
Os servidores recebem as
requisições e devolvem os
resultados.
Os clientes enviam as
requisições e recebem
os resultados.
E
F
G
H
Modelo híbrido ou de aplicação
A aplicação se confunde com
a infraestrutura, provendo os
recursos.
A
B
C
D
Cada nó pode atuar como
servidor e cliente, inclusive
ao mesmo tempo.
Modelos (comparação)
Computacional
Recursos
Híbrido
Escalabilidade
Média
Alta
Alta
Complexidade
Baixa
Média
Alta
Tolerância a
falhas
Média
Alta
Alta
Principal
Aplicação
Processamento
memória
Infra
Arquivos
Exemplo
SETI@home
Servidores
Web
P2P
Aplicações distribuídas (requisito I)
Primeiro requisito: definir
a forma de comunicação
entre os nós.
A
B
C
D
Aplicações distribuídas (requisito II)
Segundo requisito: manter
os metadados sobre os
nós, usuários, arquivos e
outros recursos.
A
B
C
D
Aplicações distribuídas (requisito III)
Terceiro requisito: fazer o
monitoramento e
controle dos componentes
do sistema.
A
B
C
D
Aplicações distribuídas (requisito IV)
A
B
C
D
Quarto requisito: manter a
segurança (sigilo, integridade
e disponibilidade) dos dados e
sistemas envolvidos.
Camada de comunicação
A camada torna
transparente os
protocolos de
rede.
Rede
Máquina
Máquina
Framework
Framework
Aplicação
Aplicação
Camadas de comunicação em Python
●
PYRO
●
XML-RPC
●
Socket
PYRO (Python Remote Objects)
Implementa:
●
●
●
●
Um protocolo que permite a execução remota via
TCP/IP de métodos de um objeto.
Envio de estruturas de dados “serializáveis” como
parâmetros.
Servidor de nomes que facilita a localização
automática dos métodos.
Validadores para verificar as credenciais do cliente.
PYRO (servidor)
import numpy
import Pyro.core
class Dist(Pyro.core.ObjBase):
def fft(self, l):
return numpy.fft.fft(l)
# Inicia a thread do servidor
Pyro.core.initServer()
# Cria o servidor
daemon = Pyro.core.Daemon()
# Publica o objeto
uri = daemon.connect(Dist(),'dist')
# Coloca o servidor em estado operacional
daemon.requestLoop()
Classe do objeto que será
publicado na rede pelo PYRO.
Método que calcula a
transformada de Fourier.
PYRO (cliente)
# -*- coding: utf-8 -*import numpy
import Pyro.core
# Dados de teste
dados = numpy.random.rand(100)
# Cria um objeto local para acessar o objeto remoto
proxy = Pyro.core.getProxyForURI('PYROLOC://127.0.0.1/dist')
# Evoca um método do objeto distribuído
print proxy.fft(dados)
XML-RPC
Implementa:
●
●
●
Protocolo de execução remota de procedimentos.
Transferências de dados em XML usando HTTP ou
HTTPS (criptografado) como protocolo de transporte.
Suporte a tipos básicos: inteiro, ponto flutuante,
texto, ...
XML-RPC (servidor)
import numpy
from SimpleXMLRPCServer import SimpleXMLRPCServer
# Cria um servidor
server = SimpleXMLRPCServer(('localhost', 8888))
server.register_introspection_functions()
def fft(l):
return [ float(x) for x in numpy.fft.fft(l) ]
server.register_function(fft)
# Inicia o loop do servidor
server.serve_forever()
Conversão para tipos que o
XML-RPC aceita.
XML-RPC (cliente)
import numpy
import xmlrpclib
Conversão para tipos que o
XML-RPC aceita.
# Dados de teste
dados = [ float(x) for x in numpy.random.rand(100) ]
server = xmlrpclib.Server("http://localhost:8888")
# Evoca o procedimento remoto
print server.fft(dados)
Socket
Implementa:
●
●
Acesso de baixo nível a biblioteca de sockets que
disponível em praticamente qualquer sistema
operacional atual.
Conexões ponto a ponto vai TCP/IP.
Socket (servidor I)
import
import
import
import
cPickle
socket
threading
numpy
Classe que implementa as
threads para o servidor.
class Server(threading.Thread):
def __init__(self, skt):
self.skt = skt
threading.Thread.__init__ (self)
def run(self):
# Recebe os dados
rec = self.skt.recv(5000)
# Calcula o resultado
ff = numpy.fft.fft(cPickle.loads(rec))
# Retorna a resposta
self.skt.send(cPickle.dumps(ff))
Método que é executado na
thread.
Dados foram serializados no
cliente.
Continua...
Socket (servidor II)
# cria um socket INET STREAM
server = socket.socket(
socket.AF_INET, socket.SOCK_STREAM)
# Associa o socket a uma porta na interface de rede
server.bind((socket.gethostname(), 8000))
# Passa a "ouvir" a porta
server.listen(5)
while True:
# aceita acesso externo
(skt, addr) = server.accept()
svr =Server(skt)
svr.start()
Socket (cliente)
import cPickle
import socket
import numpy
# Dados
dados = numpy.random.rand(100)
# cria um socket INET STREAM
svr = socket.socket(
socket.AF_INET, socket.SOCK_STREAM)
# Conecta na interface de rede
svr.connect((socket.gethostname(), 8000))
svr.send(cPickle.dumps(dados))
# Recebe a resposta
rec = svr.recv(5000)
print cPickle.loads(rec)
Os resultados foram
serializados no servidor.
Comunicação (comparação)
PYRO
XML-RPC
Socket
Performance
Alta
Baixa
Alta
Portabilidade
Baixa
Alta
Alta
Escalabilidade
Alta
Baixa
Depende da
aplicação
Complexidade
Baixa
Média
Alta
Dependências
Média
Baixa
Baixa
YAML (YAML Ain't a Markup Language)
Implementa:
●
●
●
●
Formato de serialização de dados para texto, amigável
para humanos.
Representação de dados através de combinações de
listas, dicionários e escalares.
Convenções de sintaxe similares as linguagens
dinâmicas, com forte influência do Python.
Um superset do JSON (JavaScript Object Notation).
YAML (exemplo)
- Artista: King Crimson
Faixas:
- Starless
- Frature
- Red
- Lizard
- Artista: Genesis
Faixas:
- Supper's Ready
- In The Cage
- The Lamia
Documento
YAML
[{'Artista': 'King Crimson',
'Faixas': ['Starless',
'Frature',
'Red', 'Lizard']},
{'Artista': 'Genesis',
'Faixas': ["Supper's Ready",
'In The Cage',
'The Lamia']}]
Estrutura
Python
Formatos (comparação)
YAML / JSON
XML
(c)Pickle
Performance
Média
Baixa
Alta
Portabilidade
Alta
Alta
Baixa
Escalabilidade
Média
Alta
Alta
Complexidade
Baixa
Média
Baixa
Dependências
Média
Baixa
Baixa
Aplicações externas
Aplicações “pythônicas”:
●
BrOffice.org
●
Blender
●
GIMP
●
Inkscape
●
PostgreSQL
BrOffice.org
Implementa:
●
●
Suporte ao Python como linguagem de macro,
permitindo a automatização de tarefas e a construção
de extensões (add ons).
Serviço para atender conexões, através de uma API
chamada UNO (Universal Network Objects).
BrOffice.org (serviço)
Interpretador
PyUNO
Python UNO
Bridge
Aplicação
BrOffice.org
Aceita conexões
remotas via
named pipes ou
sockets.
BrOffice.org (exemplo I)
# -*- coding: latin1 -*# Para iniciar o BrOffice.org como servidor:
# swriter.exe -headless
# "-accept=pipe,name=py;urp;StarOffice.ServiceManager"
import os
import uno
from com.sun.star.beans import PropertyValue
# Dados...
mus = [('Artista', 'Faixa'),
('King Crimson', 'Starless'), ('Yes', 'Siberian Khatru'),
('Led Zeppellin', 'No Quarter'), ('Genesis', 'Supper\'s Ready')]
rows = len(mus)
cols = len(mus[0])
Continua...
BrOffice.org (exemplo II)
# Inicio do "Boiler Plate"...
# Contexto de componente local
loc = uno.getComponentContext()
# Para resolver URLs
res = loc.ServiceManager.createInstanceWithContext(
'com.sun.star.bridge.UnoUrlResolver', loc)
# Contexto para a URL
con = res.resolve('uno:pipe,name=py;urp;StarOffice.ComponentContext')
# Documento corrente
desktop = con.ServiceManager.createInstanceWithContext(
'com.sun.star.frame.Desktop', con)
# Fim do "Boiler Plate"...
Continua...
BrOffice.org (exemplo III)
# Cria um documento novo no Writer
doc = desktop.loadComponentFromURL('private:factory/swriter',
'_blank', 0, ())
# Cursor de texto
cursor = doc.Text.createTextCursor()
# Muda propriedades
cursor.setPropertyValue('CharFontName', 'Verdana')
cursor.setPropertyValue('CharHeight', 20)
cursor.setPropertyValue('CharWeight', 180)
doc.Text.insertString(cursor, 'Músicas favoritas\n', 0)
Texto
inserido
# Cria tabela
tab = doc.createInstance('com.sun.star.text.TextTable')
tab.initialize(rows, cols)
doc.Text.insertTextContent(cursor, tab, 0)
Continua...
BrOffice.org (exemplo IV)
# Preenche a tabela
for row in xrange(rows):
for col in xrange(cols):
cel = chr(ord('A') + col) + str(row + 1)
tab.getCellByName(cel).setString(mus[row][col])
Tabela
# Propriedades para exportar o documento
props = []
p = PropertyValue()
p.Name = 'Overwrite'
p.Value = True # Sobrescreve o documento anterior
props.append(p)
p = PropertyValue()
p.Name = 'FilterName'
p.Value = 'writer_pdf_Export' # Writer para PDF
props.append(p)
Continua...
BrOffice.org (exemplo V)
# URL de destino
url = uno.systemPathToFileUrl(os.path.abspath('musicas.pdf'))
# Salva o documento como PDF
doc.storeToURL(url, tuple(props))
# Fecha o documento
doc.close(True)
Arquivo de
saída
Referências
PYRO:
●
http://pyro.sourceforge.net/
Socket Programming HOWTO:
●
http://www.amk.ca/python/howto/sockets/
YAML Cookbook:
●
http://yaml4r.sourceforge.net/cookbook/
Python – OpenOffice.org Wiki:
●
http://wiki.services.openoffice.org/wiki/Python
Integração de aplicações em
Luiz Eduardo Borges
http://ark4n.wordpress.com/
Fim
Download