HTML

asdf

Google App Engine tapasztalatok

2011.08.15. 12:20 tvk

Egy éve fejlesztek egy alkalmazást Google App Engine platformon, úgyhogy itt az ideje felvésni egy-két tapasztalatot róla. Röviden: az appengine egy webalkalmazások futtatására alkalmas, némileg ingyenes, felhő alapú platform. Egy Google Account-tal és egy telefonszámmal bárki szerezhet appengine account-ot, amivel lehetősége van max 10 webalkalmazás egyidejű üzemeltetésére. Bizonyos kvótákat kell betartani, vagy gondoskodni a kvótatúllépések viszonylag barátságos díjának befizetéséről. Java-ban, Python-ban vagy Go-ban lehet fejleszteni a platformra, miközben komolyan kell venni néhány olyan szabályt, amit bármelyik más platformra való fejlesztésnél komolyan kellene venni, elvileg.

Step In

Ami engem illet Java-val foglalkozom, úgyhogy ezt a témát fogom körbejárni. Először is nem árt ha tisztában van az ember a szabványos Java webalkalmazások szerkezetével, mert az appengine alkalmazások is erre épülnek, néhány plusz konfig fájllal kiegészülve. Az első lépések nagyon egyszerűek. A letölthető SDK-ban jónéhány példaalkalmazás található amit akár lokálisan is ki lehet próbálgatni a szintén mellékelt tesztkörnyezettel, de ugyanezeket az alkalmazásokat fel lehet tölteni az éles szerverre is. A dokumentációt külön lehet letölteni, ami nagyon jó minőségű, HTML formátumú. De egyébként online is megvan.

Buildelés, deployolás

Az SDK-ban Ant-tal megy a buildelés és a szerverre való deployolás néhány speciális Ant task-kal, viszont van két bökkenő. Ha az éles szerverhez akarok csatlakozni, akkor előbb egy command line-os script segítségével authentikálnom kell magamat. Eközben be kell gépelni az account jelszót, ami megjelenik a képernyőn. Ez baj. A másik bökkenő, hogy ha lokálisan indítok teszteléshez egy appengine-t (ez is egy Ant target) azt csak erőszakos módszerrel tudom leállítani. Windows-on pl. úgy hogy kinyomom a task managerben a java processzt. Létezik egy független GAE Maven plugin, ami elég jól megoldja ezeket a problémákat, viszont sokkal kellemetlenebb problémákat hoz be, úgyhogy ezt a Maven plugin-t egy-két napos szívás után egyelőre hanyagolom. Egyébként az én build-em úgy néz ki, hogy Maven-nel csinálok egy sima Java webalkalmazást és a Google-s Ant build.xml-t használom az alkalmazás éles szerverre való feltöltésére. A jelszó és lokális appengine leállítási problémával pedig együtt élek. Emellett pedig létezik a szoftvernek egy olyan üzemmódja, hogy elfut egy sima Jetty-ben. Fejlesztés közben általában így futtatom. De amúgy JRebel-t állítólag be lehet izzítani a lokális appengine alá is, ami hasznos lehet.

Perzisztencia

A perzisztens adattárolás az appengine egyik legfontosabb szolgáltatása. Ez a szolgáltatás NoSQL séma nélküli elosztott adatbázisra épül. Lehet használni a saját entitásokra és lekérdezésekre épülő API-t, ami elég egyszerű csak egyáltalán nem hordozható, valamint lehet használni JDO vagy JPA ORM-et. A JDO valamivel jobban van dokumentálva, de mégiscsak a JPA a szabvány úgyhogy emellett döntöttem. Eddig leginkább a NoSQL adatbázis hátrányaival sikerült találkoznom, mert például csak viszonylag egyszerű query-ket lehet beküldeni. Nem lehet hozzácsatlakozni "adatbázis nézegetővel", csak az admin konzolon keresztül, ami viszont elég fapados. Többször is kénytelen voltam beleírni az alkalmazásba fáradságos munkával kódrészeket olyan feladatokra, amiket relációs adatbázisban egy update paranccsal másodpercek alatt megoldanék. Viszont véletlenül elég nehéz törölni adatokat és ha frissítem az alkalmazást az adatok természetesen megmaradnak. Séma frissítésről nincs értelme beszélni, mert nincs séma: Az újonnan megjelent mezők null-ok lesznek, a régi, nem használt mezők ott maradnak a perzisztens tárban.

Még pár dolog az ORM eszközökkel kapcsolatban:

A JDO vagy JPA alkalmazásakor a buildelés közben a modell osztályaira rá kell engedni a DataNucleus bájtkód buherátort, hogy az osztályokba beleheggessze a perzisztencia kezelést. Ez szerencsére benne van a gyári Ant script-ekben, viszont a Maven pluginnél külön sportolni kell hozzá. Itt hasaltam el egyébként.

Az alkalmazás működése során legalább egyszer szükség van rá, hogy az ORM rendszer összeszedje magát, felépítse a mappeléseket. Ez nálam pár táblánál pár másodperc, és közben szépen bele is szemetel a logba. De a nagyobb bökkenő az, hogy terhelés hiányában az éles szerver leállíthatja az alkalmazásunkat (vagy nagy terhelés esetén új alkalmazáspéldányt indíthat) és ez a pár másodperc hozzáadódhat az éppen bejövő kérés kiszolgálásához. Sok tábla esetén ez több perc is lehet, ami már komoly baj. Viszont megvannak rá a módszerek, hogy az alkalmazás ne induljon újra gyakran.

Update 2012.01.23: Léteznek kimondottan a GAE vékony és kényelmetlen perzisztencia API-jára felhúzott Java framework-ök: JiqlObjectify, Twig, SimpleDS, Siena, Slim3 és Cloud2b. Itt pedig egy ínterjú az Objectify, a Twig és a SimpleDS készítőivel. Az interjúban részletesen kitérnek rá, hogy miért szívás a JDO, vagy különösen a JPA az appengine esetében, de egyéb általánosabb GAE-vel kapcsolatos témákat is kifejtenek. Ugyanettől a szerzőtől van még egy Objectify véleménnyilvánítás további hasznos linkekkel. A tartalma röviden az, hogy átütő performancianövekedést nem, viszont lényegesen kényelmesebb programozhatóságot el lehet érni az Objectify-jal. Hosszabb távon én is tervezem, hogy lecserélem a JPA DAO implementációmat valamire, ami közelebb áll a NoSQL világhoz. Btw, itt egy hasznos SQL/NoSQL írás.

Kvóták

Az admin konzol kiválóan jelzi, hogy mely napi kvótákat mennyire használjuk ki. A napi kvóták magyar idő szerint reggel 9-kor nullázódnak. (Kaliforniában ekkor van éjfél.) Van itt CPU kihasználtság, perzisztens tárterület, kiküldött emailek száma, kimenő-bejövő forgalom. A tapasztalatom az, hogy 2-3 olyan kvóta van, ami szűk keresztmetszetet jelenthet, amire oda kell figyelni az alkalmazás típusától függően. Egyébként az ingyenes tartományban simán ki lehet szolgálni napi több tízezer kérést, ha nem túl extrém bonyolult a belső logika. Nekem egyébként a CPU kihasználtság a legmagasabb. Csúcsidőben 25%-ig ment fel, de még nem vittem túlzásba az optimalizálást, a cache használatát.

A másik fajta korlátozás a HTTP kérések kiszolgálásához szükséges idő maximálása. Ha gyanúsan sok idő kell egy HTTP kérés kiszolgálásához akkor az admin konzol kijelzi és elvileg le is lőheti a processzt. A logban rögtön utána is tudunk nézni egy kattintással a problémás URI-knak. Az időigényesebb admin kéréseket én inkább feldaraboltam több kis részre. Pl. nagyobb adathalmazokat több HTTP post-tal töltök fel a szerverre. A másik megoldás a task queue használata lenne, de erre még nem volt szükségem.

Update 2012.01.23: Így néz ki a logban, amikor a HTTP kérés túl sokáig tartana. A kérés kiszolgálása ilyenkor természetesen megszakad:

ERROR: com.google.apphosting.runtime.HardDeadlineExceededError: This request (4766834106261465) started at 2012/01/17 12:49:07.933 UTC and was still executing at 2012/01/17 12:50:08.115 UTC.

WARNING: A serious problem was encountered with the process that handled this request, causing it to exit. This is likely to cause a new process to be used for the next request to your application. If you see this message frequently, you may be throwing exceptions during the initialization of your application. (Error code 104) Időzítés

Időzített feladatokat lehet beütemezni, ami annyiból áll, hogy a megadott időközönként vagy időben egy kilövődik egy HTTP GET az alkalmazásunkra. Én 1 percenként végrehajtódó task-ot szerettem volna csinálni, de úgy tapasztaltam, hogy ez olyan mint a kutya vacsorája: vagy van vagy nincs. Néha kimarad a hívás, sajnos nem elhanyagolhatóan kevésszer.

Loggolás

Az alkalmazás "valahova a felhőbe" loggol Java Util Logging segítségével. A logokat lehet nézegetni az admin konzol segítségével, vagy le lehet tölteni fájlba parancssori script vagy Ant target segítségével. Az admin konzol egészen hasznos, mert lehet szűrni pár dologra és vannak mindenféle IP cím, böngésző, időkvóta infók, de a log letöltésnél problémákba ütköztem. Info szinttel visszamenőleg több napra le lehet tölteni a logokat, de debug szinttel csak kb. az utolsó napra. Java Util Logging-tól eltérő loggolás használatánál úgy kell beállítani a loggereket, hogy a standard out-ra írjanak és ez megjelenik infó szinttel az appengine logban. Nem túl elegáns.

Üzemeltetés

Egy GAE alkalmazás alaphelyzetben a neten http://APPNAME.appspot.com URL-en elérhető, ahol APPNAME az alkalmazás neve, de ezt át lehet kötni saját URL-re. Hazai szolgáltatónál vett domainnévnél kicsit macerás ez az átkötés, mert nekem mindenfélét leveleznem kellett velük hogy mit kell átírni a DNS rekordban, de a Google-nél vett domainnévnél pár kattintással magam is meg tudtam csinálni, pedig nem értek a domainnév adminisztrációhoz.

Konklúzió

Sok mindenről nem írtam, pl. cache-elésről, biztonságról, authentikációról, email küldésről, websocket jellegű adatfolyamokról, képfeldolgozásról, fájlfeltöltésről, XMPP-ről, mert ezekkel még nem kellett foglalkoznom, de azt a tendenciát látom, hogy előbb-utóbb minden funkcióval kénytelen leszek megbarátkozni. Valószínűleg jön még írás ezekkel kapcsolatban kb. 1 év múlva. Ha addig élni fog a blog.

Néha megfordul a fejemben, hogy mi lenne (mi lett volna) ha kihagyom az appengine-t és egy saját szerveren vagy egy bérelt virtuális gépen futtatom az alkalmazásomat. Egy csomó appengine specifikus dologgal elvileg nem kellene foglalkoznom. Viszont számomra nagyon kényelmes, hogy nem kell egy operációs rendszert és egy adatbázist (meg még ki tudja mit) adminisztrálnom, és főleg -legalábbis egyelőre- nem kell fizetnem érte. Persze vérbeli rendszergazdák szerint talán ezek a világ legegyszerűbb dolgai. Egyébként rászántam pár napot arra is, hogy magamévá tegyek némi Linux rendszeradminisztrátori ismereteket, de ezt az irányt végül berekesztettem, mert az appengine-re való áttérés gyorsabb látható eredménnyel kecsegtetett és most sem hátráltat igazán. Szóval nem bántam meg hogy ezt az irányt választottam, de azért nem égettem fel minden hidat. Az alkalmazás bármikor telepíthetó sima webszerverre is.

Végszóként az Appengine-t azoknak a fejlesztőknek és startuppereknek ajánlanám, akik nem feltétlenül érzik a vénájukban szerteáradó rendszeradminisztrátori vért, és/vagy nyitottak a dinamikusabb technológiákra.

3 komment

Címkék: java appengine

A bejegyzés trackback címe:

https://kodzaj.blog.hu/api/trackback/id/tr353154762

Kommentek:

A hozzászólások a vonatkozó jogszabályok  értelmében felhasználói tartalomnak minősülnek, értük a szolgáltatás technikai  üzemeltetője semmilyen felelősséget nem vállal, azokat nem ellenőrzi. Kifogás esetén forduljon a blog szerkesztőjéhez. Részletek a  Felhasználási feltételekben és az adatvédelmi tájékoztatóban.

vicziani · http://jtechlog.hu 2011.08.15. 14:35:16

Jó cikk!

A kérdésem az lenne, hogy alapban ha regisztrálsz, akkor nem lehet túlmenni a limiten, ugye? Szóval letilt, de nem az lesz, hogy hó végén jön a csekk? :)

Én a Python-t próbáltam (jtechlog.blogspot.com/2011/06/masodik-nyelv-python.html), és azzal koránt sem volt ennyi szívás, sőt, egyszerűbbnek tűnt egy sima (nem Google App Engine-es) Java fejlesztésnél is.

Maven esetén meg nem lenne megfelelő a plugin helyett az Ant task-okat hívogatni?

tvk · http://kodzaj.blog.hu 2011.08.15. 15:08:53

@Viczi: Helló, köszi!
-Nem lehet túlmenni a limiten. Simán letilt és valami HTTP hibakóddal fognak visszajönni a kérések. Élőben még nem találkoztam vele.

-Gondoltam már rá, hogy a Maven-ből hívogassam az Ant task-okat, de egyelőre nem zavar annyira az Ant-Maven együttes használata, hogy lépéseket is tegyek az ügyben.

tvk · http://kodzaj.blog.hu 2012.01.17. 14:45:03

Ez történik, amikor egy kérés kiszolgálása túl sokáig tart:

ERROR: com.google.apphosting.runtime.HardDeadlineExceededError: This request (4766834106261465) started at 2012/01/17 12:49:07.933 UTC and was still executing at 2012/01/17 12:50:08.115 UTC.

WARNING: A serious problem was encountered with the process that handled this request, causing it to exit. This is likely to cause a new process to be used for the next request to your application. If you see this message frequently, you may be throwing exceptions during the initialization of your application. (Error code 104)