Está en la página 1de 34

Aplicaie nr.

2 Google App Engine (GAE)

1.

Subiect: Capitolul prezint o serie de aspecte practice legate de

folosirea serviciilor i construcia aplicaiilor Cloud, folosind suita de instrumente i mediul Google App Engine (GAE) 2. 3. Titular: Sl.dr.ing. Ciprian DOBRE Obiective: Formarea competentelor specifice lucrului cu servicii

specifice instrumentului Google App Engine (GAE). 5. Breviar teoretic Google App Engine
Google App Engine permite rularea de aplicaii Web direct peste infrastructura Cloud pus la dispoziie de Google. Aplicaiile App Engie sunt uor de construit, meninut i scaleaz odat cu nevoile de trafic i de stocare impuse de utilizatori. Cu App Engine dispare nevoie de meninere a unui server, precum n infrastructurile sau modelele de dezvoltare ale aplicaiilor Web tradiionale: aplicaia se ncarc la distan i e deja pregtit s serveasc utilizatorii. Se pot servi n acest mod aplicaii din domeniul nostrum local (precum http://www.example.com/) folosind Google Apps. Putem partaja aplicaia cu restul lumii, sau limita accesul doar la membri din organizaia noastr local. Google App Engine suport aplicaii scrise n diverse limbaje de programare. Cu mediul Java al App Engine se pot construi aplicaii folosind tehnologii Java standard, incluznd mediul JVM, servlei Java - sau aplicaii scrise n orice limbaj bazat pe un interpretor Java, precum JavaScript sau Ruby. App Engine permite de asemenea dezvoltarea aplicaiilor sub un mediu de dezvoltare Python sau Go. App Engine folosete un model Cloud pay only for what you use. Nu exist costuri de instalare sau costuri ulterioare etapei de deployment. Resursele folosite de aplicaie, precum spaiul de stocare sau banda de reea, se msoar n GigaByte, i sunt taxate

Google App Engine (GAE)

corespunztor (totui, remarcm c aceste costuri sunt inute la un nivel minimal a se vedea i Tabelul 1). Tabel 1. Exemple de costuri impuse de folosirea Google App Engine.

App Engine nu impune costuri de la bun nceput. Aplicaiile pot folosi pn la 1 GB spaiu de stocare i destul CPU i bandwidth pentru a suporta o aplicaie eficient ce poate servi n jur de 5 milioane de pagini vizionate pe lun, absolut gratuit. Cnd se permite i taxarea consumului aplicaiei, limitele gratuite sunt ridicate, i se impun costuri doar pentru consumul peste aceste limite de gratuitate.

5.1. Mediul Aplicaiei Google App Engine permite unei aplicaii s ruleze n mod fiabil, chiar sub o ncrcare mrit i volume mari de date. App Engine include o serie de caracateristici, precum:

Servirea dinamic a paginilor Web, cu suport complet pentru tehnologiile Web mai des folosite

Stocare persistent, suportnd interogri, sortri i tranzacii Scalare i balansare a ncrcrii automate API-uri pentru autentificara utilizatorilor i trimiterea de email-uri folosind conturi Google

Un mediu de dezvoltare local ce simuleaz mediul Cloud Google App Engine pe calculatorul local al dezvoltatorului

Cozi de task-uri pentru efectuarea de activiti n afara scopului unei cereri Web

Task-uri planificate pentru evenimente declanate la anumite ore i intervale Aplicaia dezvoltat poate rula n oricare dintre mediile de dezvoltare suportate

(Java, Python, Go). Fiecare mediu furnizeaz protocoale i tehnologii standard pentru dezvoltarea aplicaiilor Web.

5.2. Mediul Sandbox Aplicaiile ruleaz ntr-un mediu securizat ce furnizeaz acces limitat la resursele sistemului de operare aflat pe nivelul inferior. Aceste limitri permit App Engine s distribuie cereri Web ale aplicaiei pe mai multe servere, i s porneasc i opreasc servere pentru a face fa cererilor de trafic. Modelul sandbox izoleaz aplicaia n propriul mediu sigur, de ncredere, independent de hardware, sistemul de operare i locaia fizic a serverului Web. Exemple de limitri ale mediului sandbox includ:

O aplicaie poate accesa doar alte calculatoare din Internet prin intermediul unor URL-uri i servicii email furnizate. Alte calculatoare se pot conecta la aplicaia doar prin cereri HTTP (sau HTTPS) pe porturi standard.

Aplicaiile nu pot scrie n sistemul de fiiere n oricare din mediile de rulare. O aplicaie poate citi fiiere, dar doar fiiere ncarcate odat cu codul aplicaiei. Aplicaia trebuie s foloseasc datastore-ul App Engine, memcache-ul sau alte servicii pentru toate datele ce trebuie s rmn persistente ntre cereri.

Codul aplicaiei poate rula ca rspuns al unei cereri Web, a unui task planificat sau din coad, i trebuie s ntoarc un rspuns n maxim 60 de secunde. Un handler al cererii nu poate crea noi sub-procese sau executa cod dup ce rspunsul a fost trimis/returnat.

5.3. Mediul Java Runtime Environment Dezvoltatorii pot construi aplicaia pentru Java runtime environment folosind instrumente de dezvoltare Web Java i API-uri standard. Aplicaia astfel dezvoltat poate interaciona cu mediul folosind standardul Java Servlet, i poate folosi tehnologii Web precum JavaServer Pages (JSPs).

Google App Engine (GAE)

Mediul de execuie Java furnizat n Cloud de Google este bazat pe Java 6. SDK-ul App Engine Java suport dezvoltarea de aplicaii folosind Java 5 sau 6. Mediul include platforma Java SE Runtime Environment (JRE) 6 i biblioteci corespunztoare. Restriciile mediului tip sandbox sunt implementate direct n JVM. Aplicaiile pot accesa majoritatea serviciilor AppEngine folosind API-uri standard Java. Pentru App Engine datastore, SDK-ul de Java inculde implementri ale interfeelor Java Data Objects (JDO) i Java Persistence API (JPA). O aplicaie poate folosi i JavaMail API pentru trimiterea de email-uri folosind serviciul App Engine Mail. API-urile java.net HTTP permit accesul la serviciul App Engine URL. App Engine include i API-uri de nivel mai sczut, pentru implementarea unor adaptori.

5.4. Stocarea datelor Mediul App Engine furnizeaz o gam variat de opiuni privind stocarea datelor:

App Engine Datastore furnizeaz un sistem de stocare NoSQL, cu un motor de interogri posibilitatea de a lucra cu tranzacii atomice.

Google Cloud SQL furnizeaz un serviciu de stocare a datelor SQL relaionale pentru aplicaiile App Engine, bazat pe sistemul RDBMS MySQL.

Google Cloud Storage furnizeaz un serviciu de stocare pentru obiecte i fiiere de dimensiuni de ordinul terabyte, accesibile din aplicaiile Python i Java. Ca exemplificare, App Engine furnizeaz un serviciu de stocare a datelor distribuit

NoSQL ce conine un motor de interogare i lucrul cu tranzacii. Pe msur ce serverul Web crete odat cu traficul, sistemul de stocare i el poate crete odat cu datele. Se poate alege ntre dou opiuni de strocare, n funcie de garaniile de disponibilitate i consisten. Datastore-ul App Engine nu seamn cu o baz de date relaional tradiional. Obiectele sau entitile, au un tip i un set de proprieti. Interogrile pot regsi entitile de un anumit tip, filtrate i sortate pe baza valorilor proprietilor acestora.

Entitile din datastore nu au o schem definit. Structura entitilor de date este furnizate de ctre codul aplicaiei. Interfeele Java JDO/JPA i cele din Python similare includ aspecte pentru aplicarea i forarea structurii. Datastore-ul furnizeaz tranzacii ACID folosind un control optimistic al concurenei. Aceasta nseamn c un update al unei entiti are loc ntr-o tranzacie doar atunci cnd i alte procese ncearc actualizarea aceleiai entiti simultan. Aplicaia poate executa mai multe operaii la nivelul datastore ntr-o singur tranzacie, care poate fie s aib succes, fie s eueze asigurnd n final integritatea datelor.

5.5. Alte faciliti App Engine suport integrarea unei aplicaii cu Conturi Google pentru autentificare. Aplicaia poate permite unui utilizator s se autentifice folosind un cont Google, i s acceseze adresa de email i numele afiabil asociat cu respectivul cont. App Engine furnizeaz, de asemenea, servicii ce permit efectuarea de diverse operaii. Exemple de API-uri furnizeaz modaliti de acces la astfel de servicii sunt: URL Fetch Aplicaiile pot accesa resurse peste Internet, precum alte servicii Web sau date, folosind serviciul de regsire a datelor App Engine. Serviciul de regsire URL poate ntoarce resurse Web folosind infrastructura performant a Google pentru regsirea paginilor Web. Mail Aplicaiile pot trimite mesaje email folosind serviciul de mail pus la dispoziie de App Engine. Serviciul mail folosete de asemenea infrastructura Google pentru trimiterea mesajelor. Memcache Serviciul Memcache furnizeaz aplicaiei un cache de nalt performan in-memory de tip cheie-valoare, accesibil instanelor unei aplicaii. Memcache este folositoare pentru datele ce nu necesit persisten sau operaii tranzacionale.

6. Descrierea aplicaiei:

Google App Engine (GAE)

Google App Engine i Java


n cele ce urmeaz prezentm un mic tutorial pentru crearea unei aplicaii n Java ce folosete facilitile Cloud puse la dispoziie de Google App Engine. Mai exact, n acest mic tutorial vom evidenia cum se:

construiete o aplicaie App Engine folosind tehnologii Java Web standard, precum servlets i JSP

creeaz un proiect App Engine n Java folosind Eclipse folosete Google Plugin pentru Eclipse ca mediu de dezvoltare App Engine folosete datastore-ul App Engine integreaz o aplicaie App Engine cu Google Accounts pentru autentificare ncarc aplicaia n App Engine

6.1. Instalare Dezvoltarea aplicaiilor Java pentru Google App Engine se face folosind SDK-ul App Engine Java. SDK-ul include pachete software pentru un server Web ce poate rula pe staia de lucru local n scopul testrii aplicaiilor. Serverul simuleaz toate serviciile App Engine, incluznd o versiune local a datastore, Google Accounts i abilitatea de a regsi URL-uri i trimite email-uri folosind API-uri App Engine. Google App Engine suport Java 5 i 6. Atunci cnd aplicaia Java ruleaz pe App Engine, ruleaz folosind Java 6. Dac se folosete mediul de dezvoltare Eclipse, cel mai simplu mod de a dezvolta, testa i ncrca aplicaiile App Engine const n folosirea Google Plugin for Eclipse. Acest plugin include tot ceea ce e necesar pentru construirea, testarea i deployarea aplicaiei, totul din mediul Eclipse. Plugin-ul este disponibil de altfel pentru diverse versiuni Eclipse.

Pentru instalare se folosete facilitatea Software Update din Eclipse, indicnd un URL corespunztor. De exemplu, pentru Eclipse 3.3 (Europa), URL-ul e: https://dl.google.com/eclipse/plugin/3.3 SDK-ul Java App Engine include o serie de aplicaii demo n directorul demos/. Dac se folosete mediul Eclipse, SDK-ul este localizat n directorul de instalare Eclipse, sub plugins/com.google.appengine.eclipse.sdkbundle_VERSION/, unde VERSION reprezint un identificator de versiune pentru SDK. Dac rulm Windows, putei ncerca versiune demo a aplicaiei de guest book prin execuia urmtoarei comenzi din linia de comand: appengine-java-sdk\bin\dev_appserver.cmd appengine-java-sdk\demos\guestbook\war Corespunztor pentru Mac OS X sau Linux: ./appengine-java-sdk/bin/dev_appserver.sh appengine-java-sdk/demos/guestbook/war Dup pornire, serverul va asculta pe portul 8080 pentru cereri. Verificai c a pornit prin tastarea urmtorului URL n browser: http://localhost:8080/

6.2. Crearea unui proiect Aplicaiile Java App Engine folosesc standardul Java Servlet pentru interaciunea cu mediul serverului Web. Fiierele unei aplicaii, incluznd clasele compilate, pachete JAR, fiiere statice i de configurare, sunt aranjate ntr-o structur de doctor folosind un layout standard WAR corespunztor aplicaiilor Web n Java. n urmtorul exemplu vom presupune un singur director numit Guestbook/ pentru toate fiierele proiectului. Un subdirector src/ conine codul surs Java, iar un subdirector war/ conine aplicaia complet aranjat n format WAR. Proiectul complet arat astfel:
Guestbook/ src/ ...Java source code... META-INF/ ...other configuration... war/

Google App Engine (GAE)

...JSPs, images, data files... WEB-INF/ ...app configuration... lib/ ...JARs for libraries... classes/ ...compiled classes...

Dac se folosete Eclipse, se poate crea un nou proiect prin butonul New Web Application Project din toolbar: Proiectului i se poate da un nume i un nume de mpachetare. Se recomand deselectarea "Use Google Web Toolkit,", ns trebuie s verificm c e selectat opiunea "Use Google App Engine". Ulterior wizard-ul conduce la crearea automat a structurii de directoare de mai sus. Clasa Servlet Aplicaiile Java App Engine folosesc API-ul Java Servlet pentru interaciunea cu serverul Web. Un servlet HTTP reprezint o clas aplicaie ce poate procesa i rspunde unor cereri Web. Aceast clas extinde clasa javax.servlet.GenericServlet sau clasa javax.servlet.http.HttpServlet. Pentru proiectul nostru vom ncepe cu o clas servlet ce va afia pentru nceput un mesaj. n directorul src/guestbook/ vor crea un fiier numit GuestbookServlet.java:
package import import public public class void GuestbookServlet doGet(HttpServletRequest guestbook; java.io.IOException; javax.servlet.http.*; extends HttpServlet { req, HttpServletResponse resp) throws IOException { resp.setContentType("text/plain"); resp.getWriter().println("Hello, world"); }

Fiierul web.xml Atunci cnd serverul Web primete o cerere, el determin care clas servlet trebuie apelat prin inspectarea unui fiier de configurare cunoscut i ca "web application deployment descriptor." Acest fiier are numele web.xml i st n directorul war/WEB-INF/

n WAR. WEB-INF/ i web/xml sunt parte a specificaiei de servlet. n directorul war/WEBINF/, un fiier numit web.xml are urmtorul coninut:
<?xml version="1.0" <!DOCTYPE web-app "-//Oracle Corporation//DTD Web "http://java.sun.com/dtd/web-app_2_3.dtd"> <web-app encoding="utf-8"?> PUBLIC Application 2.3//EN"

xmlns="http://java.sun.com/xml/ns/javaee"

version="2.5"> <servlet> <servlet-name>guestbook</servlet-name> <servlet-class>guestbook.GuestbookServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>guestbook</servlet-name> <url-pattern>/guestbook</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>index.html</welcome-file> </welcome-file-list>

</web-app>

Acest fiier web.xml declar un servlet numit guestbook, pe care l mapeaz la calea URL /guestbook. Specific de asemenea c oricnd un utilizator acceseaaz o cale URL ce nu este deja mapat la un servlet i care reprezint o cale de director din interiorul WAR-ului aplicaiei, serverul ar trebui s verifice existena unui fiier numit index.html pe care s l serveasc ca rspuns la cerere. Fiierul appengine-web.xml App Engine necesit un fiier de configurare suplimentar pentru a regsi modul de deployare i execuie a aplicaiei. Fiierul poart numele de appengine-web.xml i se afl n WEB-INF/, mpreun cu fiierul web.xml. Acesta include ID-ul nregistrat al aplicaiei (Eclipse creeaz implicit proiectul cu un ID necompletat, ns el trebuie adugat ulterior), numrul de versiune al aplicaiei i lista fiierelor ce ar trebui tratate ca fiiere statice (precum imagini sau fiiere CSS) i fiiere resurs (precum fiiere JSP i alte date ale aplicaiei). n directorul war/WEB-INF/, un fiier numit appengine-web.xml are urmtorul coninut:
<?xml <appengine-web-app version="1.0" encoding="utf-8"?> xmlns="http://appengine.google.com/ns/1.0"> <application></application> <version>1</version>

</appengine-web-app>

Rularea proiectului

Google App Engine (GAE)

SDK-ul App Engine include o aplicaie server Web ce poate fi folosit pentru testarea aplicaiei. Acest server simuleaz mediul App Engine i diverse servicii, incluznd restricii tip sandbox, datastore, etc. Din Eclipse se poate porni serverul de dezvoltare folosind Debugger-ul integrat n Eclipse. Se selecteaz proiectul ("Guestbook"), apoi din mediul Run se selecteaz Debug As > Web Application. Dup ce serverul pornete accesarea acestuia se realizeaz prin intermediul unui browser. Dac se folosete Eclipse i pluginul Google Eclipse, serverul va porni implicit pe portul 8888: http://localhost:8888/guestbook Din linia de comand, folosind comanda dev_appserver pentru pornire, serverul va asculta implicit pe portul 8080: http://localhost:8080/guestbook n continuare vom presupune portul 8888.

6.3. Folosirea Serviciului Utilizatori Google App Engine furnizeaz cteva servicii utile bazate pe infrastructura Google, accesibile de ctre aplicaiile ce folosesc biblioteci incluse n SDK. Un astfel de serviciu este serviciul Utilizatori, ce permite aplicaiei integrarea cu conturi utilizator Google. Cu acest serviciu utilizatorii pot folosi conturile Google pentru autentificarea n cadrul aplicaiei. S folosim n cele ce urmeaz serviciul Utilizatori pentru a personaliza aplicaia. Folosirea Utilizatorilor Se editeaz fiierul src/guestbook/GuestbookServlet.java astfel:
package guestbook; import java.io.IOException; import javax.servlet.http.*; import com.google.appengine.api.users.User; import com.google.appengine.api.users.UserService; import com.google.appengine.api.users.UserServiceFactory;

10

public class GuestbookServlet extends HttpServlet { public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { UserService userService = UserServiceFactory.getUserService(); User user = userService.getCurrentUser(); if (user != null) { resp.setContentType("text/plain"); resp.getWriter().println("Hello, " + user.getNickname()); } else { resp.sendRedirect(userService.createLoginURL(req.getRequestURI())); } } }

Dac se folosete Eclipse i serverul de dezvoltare ruleaz n debuggger, la salvarea modificrilor acestui fiier Eclipse va compila noul cod automat i va ncerca inserarea codului n serverul ce deja ruleaz. Modificrile asupra claselor, fiierelor JSP, fiiere statice i appengine-web.xml se reflect imediat asupra serverului ce ruleaz, fr necesitatea repornirii acestuia. Dac se efectueaz modificri asupra fiierului web.xml sau altor fiiere de configurare, atunci serverul trebuie oprit i repornit pentru ca modificrile s devin i vizibile. Dac se folosete Ant, trebuie s oprit serverul i s reconstruim proiectul. Modificrile asupra fiierelor JSP i fiierele statice nici n acest caz nu necesit ns repornirea serverului. Dup ce am fcut modificarea de mai sus, dac revizitm serverul, n locul mesajului anterior vom constata c serverul ne ntmpin cu o cerere de adres de email (precum alfred@example.com), apoi se continu cu "Log In." Aplicaia va afia un mesaj, de data aceasta coninnd adresa de email anterior introdus. Noul cod al clasei GuestbookServlet folosete API-ul Users pentru a verifica c utilizatorul s-a autentificat folosind un cont valid Google. Dac nu, utilizatorul este redirecionat ctre fereastra de autentificare Google Accounts. Secvena userService.createLoginURL(...) ntoarce URL-ul ferestrei de autentificare. Facilitatea de sign-in redirecteaz automat utilizatorul napoi la aplicaia prin intermediul URL-ului transmis n metoda createLoginURL(...), care n acest caz reprezint URL-ul paginii curente.

11

Google App Engine (GAE)

Serverul de dezvoltare tie cum s simuleze facilitatea de sign-in. Atunci cnd se ruleaz pe maina local, redirectarea se face ctre pagina unde se poate introduce orice adres de email, pentru a simula procedura de autentificare. Cnd se ruleaz App Engine, redirectarea se face ctre chiar ecranul Google Accounts. Pentru a permite utilizatorului i opiunea de sign out se furnizeaz un link, generat prin metoda createLogoutURL().

6.4. Folosirea JSP Putem afia codul HTML pentru interfaa utilizator direct din codul servlet Java dar acest lucru ar putea uor crete complexitatea codului. Se recomand folosirea unui sistem de template-uri, cu interfaa utilizator proiectat i implementat n fiiere separate, iar logica de inserare a datelor furnizat de ctre aplicaie. n cele ce urmeaz vom folosi JavaServer Pages (JSP) pentru a implementa interfaa utilizator a aplicaiei noastre. JSP e parte a standardului servlet. App Engine se ocup de compilarea fiierelor JSP n WAR-ul aplicaiei n mod automat, i maparea acestora ctre ci URL. Hello, JSP! Aplicaia noastr guest book scrie iruri de caractere la ieire, dar aceste iruri pot fi scrise i ca JSP. Vom porta n continuare exemplul anterior pe tehnologia JSP. n directorul war/ vom crea un fiier numit guestbook.jsp, avnd urmtorul coninut:
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ page import="java.util.List" %> <%@ page import="com.google.appengine.api.users.User" %> <%@ page import="com.google.appengine.api.users.UserService" %> <%@ page import="com.google.appengine.api.users.UserServiceFactory" %> <%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>

<html> <head> <link type="text/css" rel="stylesheet" href="/stylesheets/main.css" /> </head>

12

<body>

<% UserService userService = UserServiceFactory.getUserService(); User user = userService.getCurrentUser(); if (user != null) { pageContext.setAttribute("user", user); %> <p>Hello, ${fn:escapeXml(user.nickname)}! (You can <a href="<%= userService.createLogoutURL(request.getRequestURI()) %>">sign out</a>.)</p> <% } else { %> <p>Hello! <a href="<%= userService.createLoginURL(request.getRequestURI()) %>">Sign in</a> to include your name with greetings you post.</p> <% } %>

</body> </html>

Implicit orice fiier din war/ sau un subdirector (altul dect WEB-INF/) al crui nume se termin cu extensia .jsp este automat mapat ntr-o cale URL. Calea URL reprezint o cale ctre fiierul .jsp, incluznd numele respectivului fiier. Acest fiier JSP va fi, aadar, mapat automat la URL-ul /guestbook.jsp. Pentru aplicaia guest book dorim ca aceasta s fie chiar pagina principal, prima, a aplicaiei afiat atunci cnd cineva acceseaz URLul /. O modalitate simpl const n declararea n web.xml a paginii guestbook.jsp ca fiind servlet-ul "welcome" pentru aceast cale. Pentru aceasta vom edita fiierul war/WEB-INF/web.xml i vom nlocui elementul <welcome-file> din <welcome-file-list>. De asemenea tergem index.html din list, deoarece fiierele statice au preceden n faa fiierelor JSP i servlets.
<welcome-file-list> <welcome-file>guestbook.jsp</welcome-file> </welcome-file-list>

13

Google App Engine (GAE)

Formularul Guestbook Aplicaia guest book are nevoie i de un formular Web n care utilizatorul s poat posta un nou mesaj de ntmpinare, i o modalitate de a procesa acest formular. Codul HTML al formularului va sta direct n pagina JSP. Destinaia acestui formular e un nou URL, /sign, ce va fi gestionat de ctre o clas servlet, SignGuestbookServlet. SignGuestbookServlet va procesa formularul, apoi va redireciona browser-ul utilizatorului napoi la /guestbook.jsp. Pentru moment noul servlet doar va scrie mesajul postat n log. Se editeaz fiierul guestbook.jsp i se adaug urmtoarele linii deasupra tag-ului de nchidere </body>:
...

<form action="/sign" method="post"> <div><textarea name="content" rows="3" cols="60"></textarea></div> <div><input type="submit" value="Post Greeting" /></div> </form>

</body> </html>

Se creaz o nou clas numit SignGuestbookServlet n pachetul guestbook, cu urmtorul coninut:


package guestbook; import java.io.IOException; import java.util.logging.Logger; import javax.servlet.http.*; import com.google.appengine.api.users.User; import com.google.appengine.api.users.UserService; import com.google.appengine.api.users.UserServiceFactory; public class SignGuestbookServlet extends HttpServlet { private static final Logger log = Logger.getLogger(SignGuestbookServlet.class.getName());

14

public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException { UserService userService = UserServiceFactory.getUserService(); User user = userService.getCurrentUser(); String content = req.getParameter("content"); if (content == null) { content = "(No greeting)"; } if (user != null) { log.info("Greeting posted by user " + user.getNickname() + ": " + content); } else { log.info("Greeting posted anonymously: " + content); } resp.sendRedirect("/guestbook.jsp"); } }

Se editeaz fiierul war/WEB-INF/web.xml, n care se adaug urmtoarele linii pentru declararea servletului SignGuestbookServlet i maparea acestuia la URL-ul /sign:
<web-app xmlns="http://java.sun.com/xml/ns/javaee" version="2.5"> ... <servlet> <servlet-name>sign</servlet-name> <servlet-class>guestbook.SignGuestbookServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>sign</servlet-name> <url-pattern>/sign</url-pattern> </servlet-mapping> ... </web-app>

Acest nou servlet folosete clasa java.util.logging.Logger pentru a scrie mesaje n log. Se poate controla comportamentul acestei clase folosind un fiier logging.properties, i setarea unei proprieti n fiierul aplicaiei appengine-web.xml:
<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">

15

Google App Engine (GAE)

... <system-properties> <property name="java.util.logging.config.file" INF/logging.properties"/> </system-properties> value="WEB-

</appengine-web-app>

Servlet-ul va loga toate mesajele folosind un nivel de logare INFO (folosind log.info()). Nivelul implicit de logare este WARNING, ceea ce dezactiveaz scrierea mesajelor INFO la ieire. Pentru a modifica nivelul de logare pentru toate clasele din pachetul guestbook se poate edita fiierul logging.properties, cruia i se adaug urmtoarea intrare:
.level = WARNING guestbook.level = INFO ...

Dup aceste operaii se repornete serverul i se testeaz din browser (folosind adresa http://localhost:8888/).

6.5. Folosirea Datastore Stocarea datelor ntr-o aplicaie Web care se dorete a fi i scalabil poate fi o provocare. Un utilizator poate interaciona cu multe servere Web la un moment dat. Toate serverele Web au nevoie s interacioneze cu datele, posibil distribuite pe mai multe maini, n diverse locaii. Google App Engine rezolv aceast problem. Infrastructura din spatele App Engine se ocup de distribuirea datelor, replicarea acestora i balansarea ncrcrii. Totul n spatele unui API simplu, ce oferp un motor puternic de interogri. Repository-ul de date din spatele App Engine, numit High Replication Datastore (HRD), folosete algoritmul Paxos pentru replicarea datelor ntre mai multe centre de date.

16

Datele sunt scrise n obiecte din Datastore, cunoscute ca entiti. Fiecare entitate are o cheie ce o definete n mod unic. O entitate poate opional desemna o alt entitate ca i printe al ei; prima entitate devine n acest caz copil al entitii printe. Entitile din Datastore formeaz astfel o ierarhie similar structurii de directoare din sistemul de fiiere. Prinii unei entiti printe sunt numii strmoi; copiii sunt numii descendeni. O entitate fr printe se numete o entitate root sau entitate rdcin. Datastore-ul este reziliant la catastrofe sau defecte, dar garaniile de consisten sunt un pic diferite de modul tradiional. Entitile descendente ale unui strmo comun aparin unui acelaii grup de entiti; cheia comun a strmoului reprezint cheia printelui acelui grup, care servete la identificarea ntregului grup. Interogrile asupra unui grup de entiti, numite interogri de strmoi, se refer sau se fac prin cheia printelui, n locul cheii specifice fiecrei entiti. Grupurile de entiti sunt unitare n ceea ce privesc garaniile de consisten i tranzacionalitatea operaiilor: pe de alt parte, interogrile peste mai multe grupuri de entiti pot ntoarce stri inconsistente, cu rezultate ce satisfac n realitate doar garanii de consisten eventual. Interogrile la nivelul unui grup de entiti ntorc de fiecare dat ns rezultate la zi, ce satisfac aadar o consisten puternic. Exemplele de cod n continuare organizeaz entitile nrudite n grupuri de entiti, i folosesc interogrile de strmoi asupra acestor grupuri de entiti pentru a ntoarce rezultate puternic consistente. Datastore-ul este unul dintre serviciile App Engine ce ofer alegere n privina APIurilor, ce folosesc diverse standarde. API-urile bazate pe standarde decupleaz aplicaia de serviciile de nivel sczut ale App Engine, facilitnd portarea aplicaiei pe alte medii de gzduire i alte tehnologii de baze de date, n funcie de necesiti. API-urile de nivel sczut ale App Engine, pe de alt parte, expun n mod direct capabilitile serviciilor; ele se pot folosi pentru implementarea de noi interfee adaptor de exemplu. App Engine include suport pentru dou API-uri diferite pentru Datastore: Java Data Objects (JDO) i Java Persistence API (JPA). Aceste interfee sunt furnizate de ctre DataNucleus Access Platform, o implementare open-source a mai multor standarde de persisten Java ce ofer un adaptor pentru App Engine Datastore. Actualizarea servletului pentru stocarea de date Prezentm n continuare versiunea actualizat a src/SignGuestbookServlet.java, ce include acum faciliti pentru stocarea mesajelor de ntmpinare n Datastore: 17

Google App Engine (GAE)

package guestbook; import com.google.appengine.api.datastore.DatastoreService; import com.google.appengine.api.datastore.DatastoreServiceFactory; import com.google.appengine.api.datastore.Entity; import com.google.appengine.api.datastore.Key; import com.google.appengine.api.datastore.KeyFactory; import com.google.appengine.api.users.User; import com.google.appengine.api.users.UserService; import com.google.appengine.api.users.UserServiceFactory; import java.io.IOException; import java.util.Date; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class SignGuestbookServlet extends HttpServlet { public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException { UserService userService = UserServiceFactory.getUserService(); User user = userService.getCurrentUser(); // We have one entity group per Guestbook with all Greetings residing // in the same entity group as the Guestbook to which they belong. // This lets us run a transactional ancestor query to retrieve all // Greetings for a given Guestbook. However, the write rate to each

// Guestbook should be limited to ~1/second. String guestbookName = req.getParameter("guestbookName"); Key guestbookKey = KeyFactory.createKey("Guestbook", guestbookName); String content = req.getParameter("content"); Date date = new Date(); Entity greeting = new Entity("Greeting", guestbookKey); greeting.setProperty("user", user); greeting.setProperty("date", date); greeting.setProperty("content", content); DatastoreService datastore =

18

DatastoreServiceFactory.getDatastoreService(); datastore.put(greeting); resp.sendRedirect("/guestbook.jsp?guestbookName=" + guestbookName); } }

Stocarea mesajelor de ntmpinare API-ul Datastore de nivel sczut pentru Java furnizeaz o interfa independent de schem pentru crearea i stocarea entitilor. API-ul nu necesit ca entiti de acelai tip s aib aceleai proprieti, i nici ca o anumit proprietate s aib acelai tip pentru entiti diferite. Urmtoarea secven de cod construiete entitatea Greeting n acelai grup de entiti ca i entitatea guestbook:
Entity greeting = new Entity("Greeting", guestbookKey); greeting.setProperty("user", user); greeting.setProperty("date", date); greeting.setProperty("content", content);

n exemplul nostru fiecare Greeting are coninutul postat, i stocheaz de asemenea informaiile utilizatorului despre cine a postat, precum i data la care a fost submis respectiva postare. La iniializarea entitii se furnizeaz numele entitii, Greeting, precum i un argument guestbookKey ce stabilete printele entitii pe care dorim s o stocm. Obiectele din Datastore ce partajeaz un strmo comun aparin aceluiai grup. Dup construcia entitii instaniem serviciul Datastore, cruia i adugam entitatea:
DatastoreService datastore = DatastoreServiceFactory.getDatastoreService(); datastore.put(greeting);

Deoarece interogarea n High Replication Datastore este puternic consistent doar n cadrul grupurilor de entiti, vom asigna toate entitile Greetings aceluiai grup prin setarea aceluiai printe pentru fiecare entitate Greeting. Aceasta nseamn c un utilizator va vedea un Greeting imediat dup ce acesta a fost scris. Totui, rata cu care se pot face scrierea din acelai grup entitate este limitat la 1 scriere n grup per secund.

19

Google App Engine (GAE)

Cnd proiectm o aplicaie real, acest aspect devine important. Totui, prin folosirea unor servicii suplimentare, precum Memcache, putem totui mitiga ansa ca un utilizator s nu vad rezultate dup o operaie de scriere. Actualizarea JSP n continuare avem nevoie i de modificarea fiierului JSP pe care l-am scris anterior, pentru afiarea mesajelor de ntmpinare din Datastore. n plus, trebuie s includem un formular pentru scrierea/trimiterea de mesaje Greeting. Acesta este codul actualizat pentru fiierul guestbook.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ page import="java.util.List" %> <%@ page import="com.google.appengine.api.users.User" %> <%@ page import="com.google.appengine.api.users.UserService" %> <%@ page import="com.google.appengine.api.users.UserServiceFactory" %> <%@ import="com.google.appengine.api.datastore.DatastoreServiceFactory" %> page

<%@ page import="com.google.appengine.api.datastore.DatastoreService" %> <%@ page import="com.google.appengine.api.datastore.Query" %> <%@ page import="com.google.appengine.api.datastore.Entity" %> <%@ page import="com.google.appengine.api.datastore.FetchOptions" %> <%@ page import="com.google.appengine.api.datastore.Key" %> <%@ page import="com.google.appengine.api.datastore.KeyFactory" %> <%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> <html> <head> <link type="text/css" rel="stylesheet" href="/stylesheets/main.css" /> </head> <body> <% String guestbookName = request.getParameter("guestbookName"); if (guestbookName == null) { guestbookName = "default"; } pageContext.setAttribute("guestbookName", guestbookName); UserService userService = UserServiceFactory.getUserService(); User user = userService.getCurrentUser();

20

if (user != null) { pageContext.setAttribute("user", user); %> <p>Hello, ${fn:escapeXml(user.nickname)}! (You can <a href="<%= userService.createLogoutURL(request.getRequestURI()) %>">sign out</a>.)</p> <% } else { %> <p>Hello! <a href="<%= userService.createLoginURL(request.getRequestURI()) %>">Sign in</a> to include your name with greetings you post.</p> <% } %> <% DatastoreService datastore = DatastoreServiceFactory.getDatastoreService(); Key guestbookKey = KeyFactory.createKey("Guestbook", guestbookName); // Run an ancestor query to ensure we see the most up-to-date // view of the Greetings belonging to the selected Guestbook. Query query = new Query("Greeting", guestbookKey).addSort("date", Query.SortDirection.DESCENDING); List<Entity> greetings = datastore.prepare(query).asList(FetchOptions.Builder.withLimit(5)); if (greetings.isEmpty()) { %> <p>Guestbook '${fn:escapeXml(guestbookName)}' has no messages.</p> <% } else { %> <p>Messages in Guestbook '${fn:escapeXml(guestbookName)}'.</p> <% for (Entity greeting : greetings) { pageContext.setAttribute("greeting_content", greeting.getProperty("content")); if (greeting.getProperty("user") == null) { %> <p>An anonymous person wrote:</p> <% } else { pageContext.setAttribute("greeting_user", greeting.getProperty("user")); %>

21

Google App Engine (GAE)

<p><b>${fn:escapeXml(greeting_user.nickname)}</b> wrote:</p> <% } %> <blockquote>${fn:escapeXml(greeting_content)}</blockquote> <% } } %> <form action="/sign" method="post"> <div><textarea name="content" rows="3" cols="60"></textarea></div> <div><input type="submit" value="Post Greeting" /></div> <input type="hidden" name="guestbookName" value="${fn:escapeXml(guestbookName)}"/> </form> </body> </html>

Atenie: de fiecare dat cnd afim text furnizat de utilizator n HTML, e necesar s folosim secvene escape pentru string folosind funcia fn:escapeXml din JSTL (sau un alt mecanism similar). Dac nu se realizeaz acest lucru utilizatorul maliios poate trimite ca secvene de intrare un text care ar putea s conduc la comportamente incorecte din partea aplicaiei. Regsirea mesajelor de ntmpinare anterior stocate API-ul de nivel sczut din Java furnizeaz o clas Query pentru construirea de interogri i o clas PreparedQuery pentru regsirea entitilor ce se potrivesc unei interogri, preluate din Datastore. Codul urmtor ntoarce aceste date:
Query query = new Query("Greeting", guestbookKey).addSort("date", Query.SortDirection.DESCENDING); List<Entity> greetings = datastore.prepare(query).asList(FetchOptions.Builder.withLimit(5));

Acest cod creeaz o nou interogare asupra entitii Greeting, i seteaz guestbookKey ca i entitate printe necesar pentru toate entitile ce vor fi returnate.

22

Putem, de asemenea, sorta datele ntoarse n funcie de proprietatea date, ntorcnd astfel cel mai nou Greeting primul. Despre indeci n Datastore Fiecare interogare din App Engine Datastore este realizat cu ajutorul a unul sau mai muli indeci. Indecii reprezint tabele ce mapeaz valori de proprieti unor chei de entiti. Acesta este modul n care App Engine poate servi rezultate rapid, indiferent de dimensiunea Datastore-ului aplicaiei. Multe interogri pot fi preluate din indeci preconstruii, dar Datastore-ul necesit specificarea unui index particularizat pentru unele interogri mai complexe. Fr un index particularizat, Datastore-ul nu poate executa eficient interogarea. n exemplul nostru, care filtreaz rezultatele n funcie de strmoi i le ordoneaz n funcie de dat, se folosete o interogare pe strmoi i o operaie de sortare. Aceast interogare necesit un index particularizat a fi specificat n fiierul datastore-indexes.xml al aplicaiei. Cnd rulm aplicaia n SDK, se va aduga automat o intrare n acest fiier. Cnd actualizm aplicaia, definiia indexului particularizat va fi n mod automat actualizat de asemenea. Intrarea pentru aceast interogare va arta astfel:
<?xml version="1.0" encoding="utf-8"?> <datastore-indexes autoGenerate="true"> <datastore-index kind="Greeting" ancestor="true"> <property name="date" direction="desc" /> </datastore-index> </datastore-indexes>

tergerea Datastore-ului Serverul web de dezvoltare folosete o versiune local a Datastore pentru testarea aplicaiei, folosind fiiere locale. Datele persist att timp ct exist fiierele temporare iar serverul Web nu reseteaz aceste fiiere dect atunci cnd acest lucru este explicit cerut. Fiierul se numete local_db.bin, i este creat n directorul WAR al aplicaiei, n directorul WEB-INF/appengine-generated/. Pentru tergerea bazei de date este suficient tergerea acestui fiier.

6.6. Folosirea fiierelor statice Exist multe situaii n care dorim s servim direct fiiere statice din browser. Exemple tipice de fiiere servite direct cuprind imagini, fiiere de stil CSS, cod JavaScript, 23

Google App Engine (GAE)

filme sau animaii Flash. Pentru eficien, App Engine servete static fiiere din servere separate de acelea folosite pentru invocarea servlet-urilor. Implicit, App Engine stabilete toate fiierele din WAR ca fiind fiiere statice, cu excepia fiierelor JSP din WEB-INF/. Orice cerere ctre un URL a crui cale desemneaz un fiier static este servit direct n browser. Exist ns posibilitatea configurrii ca App Engine s trateze doar anumite fiiere ca fiind statice prin editarea fiierului appengineweb.xml. Pentru a nelege mai bine conceptul, n continuare vom aduga un stylesheet CSS aplicaiei noastre n directorul war/ vom crea un director numit stylesheets/. n acest director vom crea un fiier numit main.css, avnd urmtorul coninut:
body { font-family: Verdana, Helvetica, sans-serif; background-color: #FFFFCC; }

Vom edita fiierul war/guestbook.jsp, adugnd urmtoarele linii dup tag-ul <html>:
<html> <head> <link type="text/css" rel="stylesheet" href="/stylesheets/main.css" /> </head>

<body> ... </body> </html>

Dac rencrcm pagina http://localhost:8888/, vom constata c ea folosete acum noul stil definit de noi.

6.7. ncrcarea aplicaiei n Google App Engine

24

Aplicaiile sunt create i gestionate n App Engine din Administration Console. Odat ce nregistrm un ID de aplicaie pentru aplicaia pe care o dezvoltm, ea poate fi ncrcat n Google App Engine folosind fie plugin-ul Eclipse, fie din linia de comand folosind instrumentele puse la dispoziie de SDK. Atenie: Odat ce nregistrm aplicaia, folosind un ID, ea poate fi tears, dar ulterior nu o vom mai putea ncrca n App Engine folosind acelai ID. nregistrarea aplicaiei n App Engine aplicaiile Web sunt create i gestionate, dup cum spuneam, din App Engine Administration Console, accesibil la: https://appengine.google.com/ Odat ce ne autentificm n aplicaie folosind un cont valid Google, putem crea o nou aplicaie folosind butonul "Create an Application". Avem ulterior la dispoziie i o serie de instruciuni privind paii ce trebuie urmai pentru nregistrarea unui ID de aplicaie un nume unic sub care va fi cunoscut aplicaia noastr. Se editeaz n continuare fiierul appengine-web.xml, unde modificm valoarea elementului <application> astfel nct s desemneze ID-ul aplicaiei anterior nregistrat. Pentru exemplul nostru, vom presupune c vrem s folosim numele de domeniu appspot.com aceasta nseamn c ntregul URL al aplicaiei noastre, cel sub care va fi cunoscut pe Web de ctre clienii notri, va fi http://your_app_id.appspot.com/. n continuare, accesnd Authentication Options (Advanced), opiunea implicit "Open to all Google Accounts users" reprezint cea mai simpl alegere. Dac, de exemplu, alegem opiunea "Restricted to the following Google Apps domain", atunci va trebui ca administratorul domeniului s adauge aplicaia nou creat ca un serviciu al respectivului domeniu (ce poate fi accesat la respectiva adres). Dac alegem opiunea Google Apps domain authentication, atunci trebuie s adugm aplicaia n cadrul domeniului Google App, altfel clienii vor obine o eroare HTTP 500, cu un stack trace de eroare de forma "Unexpected exception from servlet: java.lang.IllegalArgumentException: The requested URL was not allowed: /guestbook.jsp". Dac ntlnii aceast eroare nu uitai c trebuie s verificai dac aplicaia este adugat n cadrul domeniului vedei i Configuring Google Apps to Authenticate on Appspot pentru mai multe detalii. Dac deinem un cont App Engine Premier, putem specifica c noua aplicaie ar trebui s fie gzduit ntr-un domeniu EU (European Union), i nu ntr-unul gzduit n

25

Google App Engine (GAE)

United States. Acest aspect este folositor n particular pentru utilizatorii aplicaiei ce sunt mai aproape de serverele Google din Europa latena comunicaiei va fi mult redus pentru ei n acest caz. n acest caz ns trebuie explicit specificat locaia n care nregistrm aplicaia (atenie: ea nu mai poate fi ulterior schimbat). Pentru aceast opiune se acceseaz Edit n seciunea Location Options i se selecteaz o opiune privind locaia. ncrcarea aplicaiei pe Google App Engine Putem ncrca aplicaia fie din Eclipse, fie folosind linia de comand. Aplicaiile ncrcate trebuie s aib o dimensiune maxim de 32 MB. ncrcarea din Eclipse Codul aplicaiei i fiierele necesare acesteia se pot ncrca n Google App Engine folosind Google Plugin, din Eclipse. Pentru ncrcarea aplicaiei se apas pe butonul Google , i se selecteaz opiunea "Deploy to App Engine".

Dac e necesar se urmeaz instruciunile pentru furnizarea unui ID de aplicaie din App Engine console, pe care dorim s l folosim pentru aplicaia noastr, precum i credenialele contului valid de Google. Apoi se apas pe butonul Deploy. Eclipse automatizeaz operaiile i transfer tot coninutul directorului war/ pe web. ncrcarea din linia de comand Codul aplicaiei i fiierele necesare se pot ncrca i din linia de comand,

folosind utilitarele puse la dispoziie n SDK. Mai exact, instrumentul appcfg.cmd (pe Windows) sau appcfg.sh (pe Mac OS X sau Linux). AppCfg este un utilitar ce faciliteaz comunicaia cu aplicaia noastr n cadrul App Engine. Utilitarul primete ca argumente numele unei aciuni ce se dorete a fi executat, calea ctre directorul war/ al aplicaiei, respectiv posibil alte opiuni funcie de aciune. Pentru ncrcarea aplicaiei n App Engine vom folosi aciunea update. Pentru ncrcarea aplicaiei pe Windows vom executa:
..\appengine-java-sdk\bin\appcfg.cmd update war

Pentru a ncrca aplicaia pe Mac OS X sau Linux:

26

../appengine-java-sdk/bin/appcfg.sh update war

Accesarea aplicaiei Putem vizualiza aplicaia ce ruleaz n Google App Engine, presupunnd c am folosit numele de domeniu appspot.com, accesnd din browser urmtoarea adres (unde prima parte se nlocuiete cu ID-ul aplicaiei): http://your_app_id.appspot.com/

7. Informaii suplimentare Consola de Administrare


Google App Engine Administration Console permite accesul complet la versiunea public a aplicaiei. Putem s ne autentificm n cadrul domeniului nregistrat n App ENgine folosind un URL similar cu: https://appengine.google.com/a/your-domain.com Consola de administrare se poate folosi pentru

Efectuarea unor operaii de baz asupra aplicaiei, precum modificarea numelui aplicaiei, specificarea unor opiuni privind cookies, de autentificare, etc.

Setarea unor opiuni de performan pentru aplicaie Vizualizarea serviciilor configurate Setarea unui nou nume de domeniu Dezactivarea scrierilor n datastore, precum i administrarea acestuia, efectuarea de operaii de backup/restore, copierea sau tergerea datelor

Dezactivarea sau tergerea aplicaiei Migrarea de la modelul Master/Slave la High Replication Datastore Balansarea traficului ntre diverse versiuni ale aplicaiei Vizualizarea informaiilor privind instanele aplicaiei Modificarea rolurilor utilizatorilor, invitarea unor persoane ca dezvoltatori ai aplicaiei, etc.

Vizualizarea informaiilor de log (cereri, erori), sau analiza traficului

27

Google App Engine (GAE)

Administrarea cozilor de activiti Gestiunea unor activiti individuale din coad Testarea unei versiuni a aplicaiei

7.1. Instane n Consola de Administrare Instanele reprezint uniti computaionale pe care App Engine le folosete pentru scalarea automat a aplicaiei. Ele sunt similare unor maini virtuale deoarece i instanele dispun de o cantitate alocat de memorie de exemplu. Totui, instanele GAE nu au overhead impus de sistemul de operare sau de alte aplicaii ce ruleaz. Instanele sunt elementele de baz ale App Engine. Ele furnizeaz resursele necesare pentru gzduirea cu succes a aplicaiei. O instan include un runtime dependent de limbaj, API-uri ale App Engine, precum i codul i memoria aplicaiei. Fiecare instan include un nivel de securitate pentru a ne asigura c instanele nu se afecteaz unele pe altele. La orice moment aplicaia poate rula fie pe o singur instan, fie mai multe caz n care cererile sunt distribuite ntre acestea. Acestea sunt instane dinamice denumite astfel pentru c ele pornesc i sunt oprite automat, n funcie de necesiti. App Engine ofer de asemenea instane rezidente, ce rmn active tot timpul. Instanele rezidente permit mbuntirea performanei aplicaiei iar dac aplicaia folosete un backend, ele permit efectuarea de activiti de mai lung durat. Instanele rezidente pot fi activate prin setarea numrului minim de instane idle. App Engine taxeaz funcie de folosirea instanei, per or de activitate. Dac utilizatorul se ateapt s foloseasc un anumit numr de ore pe sptmn, se pot salva bani prin cumprarea n avans a necesarului de ore din Billing Settings, n consola de administrare. App Engine ofer dou tipuri de instane:

Instane Frontend: O instan ce ruleaz codul i scaleaz dinamic n funcie de cereri, dar limitate la ct poate rula o cerere. Instanele frontend pot gestiona toate cererile, inclusiv cozile de activiti i cron-ul.

28

Instane Backend: O instan a crei durat este determinat din configurare, ce are ns limitri n privina scalabilitii setate.

7.2. Scalarea aplicaiei Aplicaiile App Engine au la baz o serie de instane dinamice, pornite n funcie de volumul cererilor primite de aplicaie. Pe msur ce apar mai multe cereri ctre aplicaiei, numrul de instane dinamice crete (respectiv, vice versa, numrul de instane dinamice scade dac volumul de cereri se reduce). Fiecare instan are propria coad pentru gestionarea cererilor de intrare. App Engine monitorizeaz numrul de cereri ce pot atepta n coada fiecrei instane. Dac App Engine detecteaz c o coad a unei aplicaii devine prea mare, posibil datorit unei creteri a ncrcrii, va crea automat o nou instan a aplicaiei pentru gestionarea ncrcrii suplimentare. Atunci cnd o aplicaie nu este folosit, App Engine oprete instanele dinamice asociate acesteia (i le repornete la fel de uor atunci cnd acest lucru este necesar). Se poate specifica un numr minim de instane idle. Setarea numrului funcie de volumul cererilor permite aplicaiei, de exemplu, s serveasc cererile cu mai puin laten. Gestionarea cererilor pe instane Latena aplicaiei are cel mai mare impact asupra numrului de instane necesare servirii unei aplicaii. Dac serviciile sunt servite prea repede, o singur instan ar putea gestiona, cel puin teoretic, toate cererile. Instanele dispunnd de un singur Thread (Python sau Java) pot gestiona o singur cerere concurent. Aadar, exist o relaie direct ntre laten i numrul de cereri ce pot fi gestionate de instan pe secund. De exemplu, 10 ms de laten egaleaz 100 cereri/secund/instan, 100 ms laten egaleaz 10 cereri/secund/instan, etc. Instanele multi-thread pot gestiona mai multe cereri concurent. Aadar, exist o relaie direct ntre cantitatea de procesor consumat i numrul de cereri/secund. Aplicaiile Java i Python suport de asemenea cereri concurente. Aadar, o singur instan poate gestiona noi cereri, n timp ce alte cereri nc ruleaz. Concurena reduce semnificativ numrul de instane necesare aplicaiei dar aplicaia trebuie proiectat n acest caz avnd suport pentru multithread. De exemplu, dac o instan

29

Google App Engine (GAE)

backend B4 (aproximativ 2.4 GHz) consum 10 Mcycles/cerere, se pot procesa 240 cereri/secund/instan. Dac consum 100 Mcycles/cerere, se pot procesa 24 cereri/secund/instan, amd. Aceste numere reprezint valori ideale. ncrcarea cererilor Cnd App Engine creeaz o nou instan pentru aplicaie, instana trebuie nti s ncarce bibliotecile i resursele necesare gestionrii cererii. Aceasta se ntmpl n timpul primei cereri ctre instan. Urmtoarele sfaturi pot conduce la minimizarea operaiilor de ncrcare:

ncrcarea doar a codului necesar pentru startup Accesarea discului ct mai puin posibil n unele cazuri, ncrcarea codului din fiiere .zip sau .jar e mai rapid dect ncrcarea din fiiere separate Instance Dashboard Instance Dashboard este parte din App Engine Admin Console:

Utilitarul arat instanele asignate aplicaiei, mpreun cu o serie de informaii de control

Average Queries Per Second (QPS) pentru ultimul minut

30

Average Latency pentru ultimul minut Numrul de cereri primite n ultimul minut Durata de timp de cnd a fost pornit instana Folosirea memoriei Disponibilitatea memoriei, fie rezident fie dinamic Un buton de Shutdown pentru oprirea instanei Modelul de costuri asociat instanei Folosirea unei instane se taxeaz per or, pe baza timpului de uptime ct instana

ruleaz. Instana se taxeaz din momentul cnd ea pornete, pn 15 minute dup ce instana se oprete (pentru un timp idle de oprire).

7.3. Roluri App Engine furnizeaz trei roluri ce furnizeaz diverse nivele de acces la facilitile Consolei de Administrare. Fiecare rol crete progresiv odat cu permisiunile rolului anterior: Rol Viewer Permisiuni Vizualizarea Consolei de Administrare a unei aplicaii.

Developer Vizualizarea i editarea unei aplicaii prin intermediul Consolei de Administrare. Owner Vizualizarea, editarea i tergerea unei aplicaii prin intermediul Consolei de Administrare, invitarea de utilizatori i modificarea rolurilor utilizatorilor. Administratorii pot vizualiza, asigna i modifica roluri folosind intrarea

Permissionions din Consola de Administrare.

7.4. Migrarea pe High Replication Datastore Aplicaia se poate migra de pe Datastore-ul Master/Slave pe noua soluie High Replication Datastore (HRD), folosind instrumentele din Application Settings n Consola de Administrare. S-ar putea ns s fie necesar modificarea aplicaiei pentru a asigura o

31

Google App Engine (GAE)

migrare optim a acesteia: datele trebuie structurate pentru asigurarea unei consistene puternice (Java), respectiv tranzaciile trebuie izolate (Transaction Isolation). Pentru finalizarea procesului de migrare trebuie s: 1. Crem un duplicat al aplicaiei folosind HRD 2. Instalm noua aplicaie HRD 3. Migrm datele folosind Migration Tool Duplicarea aplicaiei Atenie: urmtoarele indicaii se bazeaz pe folosirea Duplicate Application Settings, din Consola de Administrare. Toate etapele se pot realiza i manual, dar metoda pe care o descriem n continuare este mai rapid i asigur un control asupra procesului de duplicare. Pentru a crea o copie a aplicaiei existente, 1. Se deschide Consola de Administrare, se selecteaz aplicaia pe care dorim s o copiem, i selectm Application Settings. 2. n csua New Application Identifier ID-ul curent al aplicaiei este marcat cu un sufix hrd. Se poate folosi acest ID sau furniza unul complet nou. 3. Se selecteaz Check Availability pentru verificarea c ID-ul ales al aplicaiei este i disponibil. Se modific ID-ul dac acest lucru este necesar. 4. Se execut click pe Duplicate Application. 5. Doar titlul aplicaiei i setrile de control al accesului sunt copiate n timpul acestui proces de copiere. Alte caracteristici necesare pentru noua aplicaiei trebuie specificate manual. Instalarea noii aplicaii HRD Aplicaia HRD trebuie instalat nainte copierii datelor ei. Dup duplicarea aplicaiei i finalizarea modificrilor noii aplicaii, se instaleaz noua aplicaie astfel.

32

Pentru Java, dac se folosete Google Plugin (din Eclipse), aplicaia se instaleaz prin selectarea butonului deploy din toolbar. Alternativ, se poate instala aplicaia din linia de comand, folosind utilitarul appcfg din directorul appengine-java-sdk/bin/, astfel: Pentru Windows:
appengine-java-sdk\bin\appcfg.cmd update myapp/war

Pentru Mac OS sau Linux:


./appengine-java-sdk/bin/appcfg.sh update myapp/war

Folosirea Migration Tool Instrumentul pentru migrare poate fi folosit pentru mutarea aplicaiei, chiar n timpul ct aceasta continu s serveasc cereri i/sau s scrie date n Master/Slave Datastore. Cererile de intrare sunt servite n continuare de aplicaia curent folosind Master/Slave, pn cnd procesul de copiere se finalizeaz i trecerea la aplicaia HRD este pregtit. Pentru rularea procesului de migrare: 1. Se realizeaz duplicarea aplicaiei n prealabil, dup cum s-a descris anterior. n continuare vom migra datele aplicaiei existente n aceast nou aplicaie. 2. Se verific c i codul aplicaiei i configurarea indexului n cazul aplicaiei HRD au fost instalate (a se vedea Deploying Your New HRD Application). 3. Se deschide Consola de Administrare, selecteaz aplicaia pe care dorim s o migrm i se selecteaz Application Settings > View Migration Tool. 4. n meniul Destination Application se selecteaz aplicaia HRD creia dorim s i migrm datele. 5. Dac aplicaia are date n format blob n Blobstore, trebuie mutate i aceste date. Se bifeaz checkbox-ul numit Migrate Blobstore Data. Datele blob vor fi copiate i considernd noile chei de blob ale noii aplicaii, Datastore-ul vor fi actualizate cu noile chei de blob. 6. Dac se dorete primirea de email-uri odat cu definitivarea fiecrei faze, se bifeaz Email.

33

Google App Engine (GAE)

7. Se selecteaz Start Migration i se ateapt finalizarea primei faze a migrrii. Lista de activiti completate este afiat n fereastra HRD Migration, mpreun cu un status privind activitile aflate n progres. 8. Finalizarea operaiei de migrare este semnalizat prin trimiterea unui email. 9. Cnd se primete un mesaj status "Waiting to activate read-only. See below...," se selecteaz Launch Incremental Copy. Aceast operaie va copia toate datele existente pe noul Datastore HRD. 10. Cnd copierea se finalizeaz, se selecteaz Activate Read-only. 11. n final instrumentul de migrare va interoga utilizatorul pentru specificarea unui alias pentru aplicaie. La final se selecteaz Finish Migration pentru finalizarea procesului. n acest moment noua aplicaie HRD este pregtit deja s serveasc cererile de intrare.

Bibliografie
[GAE12] Google App Engine, Google Developers, accesibil online la

https://developers.google.com/appengine/. [APP12] App Engine, accesibil online la https://appengine.google.com/.

34

También podría gustarte