desenvolvimento de aplicações para o google app engine (cpbr5)
DESCRIPTION
[Video: http://www.youtube.com/watch?feature=player_detailpage&v=nzo9dcCMi-4#t=1169s ] Palestra que introduz o desenvolvimento de aplicativos na plataforma do Google de forma pragmática, apresentada na 5a. edição (2012) do Campus Party (#cpbr5)TRANSCRIPT
Google App Engine
http://slideshare.net/chesterbr
desenvolvimento de aplicações para o
Proposta
Apresentar de forma simples, prática e ao alcance de todos uma
alternativa para a criação de aplicativos na web escaláveis.
http://slideshare.net/chesterbr
não-especialista
(ou seja: se esse mané pode, eu também posso!)
Como surgem os bonsaplicativos web?
existem existem muitasmuitas lendas... lendas...
A mais popular
Dilema da Hospedagem
Enquanto o site não fizer sucesso,vou ter que custear a hospedagem
Quando ele crescer e meu provedor não aguentar, vou ter que mudar de provedor
(e talvez de tecnologia)
Quanto isso vai custar?
Dilema da Arquitetura
Projetar uma arquitetura para escalar exige tempo e skills, que poderiam ser
aplicados na aplicação em si (em particular no início), mas deixar isso pra depois pode gerar um problema difícil
Google App Engine
Equilíbrio
Crie seu aplicativo web rapidamente e a custo zero. Com alguns cuidados, ele
vai se adaptar a volumes de tráfego maiores e o custo de hospedagem será
proporcional a este aumento.
Obstáculos
O App Engine não é completamente diferente de outras arquiteturas, mas é
preciso aprender coisas novas
Nossa proposta hoje é ver essascoisas novas na prática
Escolhendo a Linguagem
?
Java
É uma opção para quem já conhece ela (ou C#), mas muita coisa vai ter que
ser feita do “jeito App Engine”
(e não é lá muito popular hoje em dia...)
Java
X
Go
Criada pelo próprio Google, é boa em tarefas que exigem muita CPU (é
compilada e com tipos estáticos), mas o suporte ainda é experimental* e você
vai ter pouca companhia
* eles mesmos alertam: http://code.google.com/appengine/docs/
Go
Python
Fácil de aprender, poderosa(dinâmica, funcional, interativa),
estimula a escrita de código legível e tem uma comunidade muito ativa*
*
Python
Hello, App Engine
Ingredientes
● Google App Engine SDK para Python● Seu editor de textos favorito● Internet (para colocar no ar)
(opcional: Eclipse + plugin do App Engine)
http://code.google.com/appengine/downloads.html
SDK (Launcher) no Windows
http://code.google.com/appengine/downloads.html
SDK (Launcher) no Mac
http://code.google.com/appengine/downloads.html
Um app é uma pasta
Um app é uma pasta
app.yaml
Descreve o seu aplicativo para os servidores do Google (nome, versão, linguagem), associando os endereços (ex.: “/”, “/noticias”) com o código
app.yaml
application: meusiteversion: 1runtime: pythonapi_version: 1
handlers:- url: /.* script: meusite.py
meusite.py
print "Oi, Campus Party!"
Tá pronto, vamos rodar!
acrescentando no Launcher
diga onde ele está...
...e solta o play!
era só isso?
Era!
☺
Falando sério agora...
Criando via Launcher
Criando via Launcher
app.yamlapplication: siteserioversion: 1runtime: pythonapi_version: 1
Handlers:- url: /favicon\.ico static_files: favicon.ico upload: favicon\.ico
- url: .* script: main.py
main.py “sério”from google.appengine.ext import webappfrom google.appengine.ext.webapp import util
class MainHandler(webapp.RequestHandler): def get(self): self.response.out.write('Hello world!')
def main(): application = webapp.WSGIApplication(
[('/', MainHandler)], debug=True) util.run_wsgi_app(application)
if __name__ == '__main__': main()
webapp
É a biblioteca (framework) que mapeia (através de um objeto WSGIApplication) cada caminho (ou grupo deles) para a
classe RequestHandler apropriada
Exemplo: site de notícias
...
def main(): application = webapp.WSGIApplication([
('/', HomeHandler),('/noticias', ListaNoticiasHandler),('/noticia/(\w+)', NoticiaHandler),...
], debug=True) util.run_wsgi_app(application)
...
Recuperando a notícia...
class NoticiaHandler(webapp.RequestHandler): def get(self, id_not): # id_not contém o item entre # parênteses em '/noticia/(\w+)' # ex.: /noticia/123 => id_not=123 noticia = dao.busca_noticia(id_not)
# montando o html com os dados: html = template.render('/noticia.html', noticia) self.response.out.write(noticia)
...
Template (noticia.html)<html> <body> <h1>{{titulo}}</h1> <h2>{{autor.nickname}}</h2> {{texto}} </body></html>
Parâmetros e REST...
class AlgumHandler(webapp.RequestHandler): def get(self): # parâmetros de formulário (GET, POST): p = self.request.get('nome_parametro')
# Outros verbos HTTP (i.e., REST): def post(self): ... def delete(self): ...
...
Alternativas
O webapp é minimalista, mas se isso não agradar, o App Engine suporta
outros frameworks populares
http://www.franciscosouza.com.br/tag/frameworks/
Armazenando Dados
Jeito clássico (relacional)
Bancos Relacionais
Têm implementações maduras, facilitam operações robustas (ACID), mapeiam (mais-ou-menos) com classes/objetos, performam bem em servidor único e (quase) todo mundo sabe usar SQL
mas...
Bancos Relacionais
...é difícil paralelizar sem afetar o aplicativo e/ou abrir mão de algumas dessas vantagens, o que tem levado à
busca de novas alternativas
App Engine Datastore
Baseada no Bigtable, que é
“Um mapa ordenado esparso, distribuído, persistente e multidimensional. O mapa é
indexado por chave de linha, chave de coluna e data/hora; cada valor no mapa é
um array não-interpretado de bytes”
http://research.google.com/archive/bigtable-osdi06.pdf
Na prática
Vamos usar uma estrutura mais simples, na qual o aplicativo vai cuidar de mais coisas (ex.: consistência de dados), mas
o sistema poderá escalar facilmente usando a estrutura do Google
Boa notícia
O App Engine reduz esse trabalho com classes que encapsulam o Datastore na forma de “entidades” e permitem até
consultar em estilo SQL (GQL)
(só tome cuidado com as diferenças)
Exemplo...
class Noticia(db.Model): id = db.IntegerProperty(required=True) titulo = db.StringProperty(required=True) texto = db.StringProperty(required=True) editoria = db.StringProperty(required=True, choices=set(['politica', 'esportes', 'informatica'])) data_criacao = db.DateTimeProperty( auto_now=True) data_publicacao = db.DateTimeProperty() autor = db.UserProperty() avaliacao = db.IntegerProperty() acessos = db.IntegerProperty()...
Cadastrando (put)
...
noticia = Noticia( id = 123, titulo = 'SOPA foi pro vinagre!', texto = 'bla bla bla bla', editoria = 'politica') noticia.put() ...
Consulta (query)
...
# Montando a query q = Noticia.all() q.filter("editoria =", "esportes") q.order("-data_publicacao")
# Executando a query noticias = q.fetch(10) for noticia in noticias: print noticia.titulo...
Consulta (query) com GQL
...
# Montando a query q = db.GqlQuery("SELECT * FROM Noticia " + "WHERE editoria = :1" + "ORDER BY data_publicacao DESC", "esportes")
# Executando a query (não mudou nada!) noticias = q.fetch(10) for noticia in noticias: print noticia.titulo...
Índices
Todas as consultas são baseadas em índices definidos no index.yaml (mas
criados automaticamente à medida que você testa o site no servidor local)
(sim, vale dar uma espiada no arquivo)
Restrições
Como as buscas usam índices, existem algumas restrições. Por exemplo,
desigualdades (<, <=, >=, >, !=) só podem afetar um campo por consulta.
http://bit.ly/y3xtkk (Documentação: Restrições)
Restrições
...
# Query válida q = Noticia.all() q.filter("avaliacao >=", 3) q.filter("avaliacao <=", 8)...
# Query INVÁLIDA q = Noticia.all() q.filter("avaliacao >=", 5) q.filter("acessos >=", 12)...
http://bit.ly/y3xtkk (Documentação: Restrições)
Memcache
Alguns dados são muito mais acessados que outros (working set), e o AppEngine disponbiliza o Memcache para manter
esses dados em RAM
Memcache...
def busca_noticia(self, id): cache = memcache.Client() noticia = cache.get(id) if noticia is None: result = Noticia.all().filter("id =", int(id)).fetch(1) if result: noticia = result[0] cache.add(id, noticia) return noticia...
(não esqueça do cache.delete() se os dados mudarem)
Colocando no ar
appengine.google.com
Cadastrando o aplicativo
oh, oh...
cadastre com outro nome...
...e altere no app.yamlapplication: appdojoselitoversion: 1runtime: pythonapi_version: 1
Handlers:- url: /favicon\.ico static_files: favicon.ico upload: favicon\.ico
- url: .* script: main.py
Launcher
login do Google
ele trabalha, e...
Conclusão
O poder é de vocês!
http://code.google.com/intl/pt-BR/appengine/docs/
É preciso estudar e experimentar, mas o App Engine está ao alcance de todos.
Basta começar!
Dúvidas?Obrigado!
@chesterbr
http://slideshare.net/chesterbrhttp://chester.me
Créditos e LicenciamentoEsta apresentação está disponível para uso e reuso
sob os termos da licença Creative Commons “by-nc” 3.0,observadas as exceções abaixo
Fotos e ilustrações são em sua maioria logomarcas dos produtos e projetos referenciados (inclusos sob premissa de “fair use”) e ilustrações
de uso supostamente livre cuja autoria foi mencionada sempre que possível (correções são bem-vindas). Tais elementos são de propriedade de seus autores, e não estão cobertos pela licença acima, não havendo
qualquer relação deles com o autor