Puštanje Pajton veb projekata u rad
Propratni problemi i neka rešenja
Autor: Nikola Hardi
PHP je dominantan, ali postoje i druge mogućnosti
PHP je još uvek dominantan jezik u sferi web programiranja, ali oduvek je prisutna i alternativa. Nekada su „ozbiljne“ web aplikacije pisane u Javi, hakerima je bio zanimljiv Perl, a ljubitelje MS tehnologije su privlačili ASP, ADO i drugi. U poslednje vreme su JavaScript, Ruby i Python vrlo popularni, a i u našem časopisu smo u više navrata pisali o web programiranju u Python-u, pa i sada želimo da podelimo neka naša iskustva.
Šta je problem i šta je cilj
Mnoge kolege i prijatelje, koji već dugo koriste PHP, pokušavamo polako da nagovorimo da pređu na Python i uporno im pokazujemo nove vratolomije koje izvodimo, ali oni još uvek imaju jedan snažan argument, a on je: „Gde ću ja to da hostujem?“.
Hajde da se ukratko prisetimo šta je potrebno za pokretanje jedne PHP i jedne Python web aplikacije i kakva sve rešenja imamo u ponudi.
Klasičan „shared“ web hosting plan obuhvata prostor za skladištenje datoteka na serveru sa FTP pristupom (File Trynsfer Protocol), određeni broj baza podataka i neku vrstu kontrolne table, kao što je to recimo Cpanel. Naravno, uz sve to nas čeka i web server podešen za naš sajt i čiju konfiguraciju uglavnom u ovakvoj situaciji ne možemo da prilagođavamo. Kada se odlučimo za ovakvo rešenje, sve nas lepo čeka podešeno i mi samo treba da postavimo svoj kôd, podesimo bazu podataka ukoliko je to neophodno – i možemo da koristimo naš novi sajt.
Sa druge strane, postoje i „vritual private server“ (VPS) rešenja koja podrazumevaju da na raspolaganju imamo ceo računar. Hosting provajder nam obezbedi virtuelnu mašinu sa željenom distribucijom, odnosno operativnim sistemom i dostavi nam parametre za pristupanje toj mašni putem SSH protokola (Secure Socket Shell). Kao root možemo da radimo šta hoćemo, a za jednu python aplikaciju to znači sledeće: instalirati potrebne pakete, obezbediti servis koji će pokretati aplikaciju (recimo uwsgi ili gunicorn), proxy server za prihvatanje spoljašnjih zahteva i prosleđivanje tih zahteva prethodno pomenutom servisu (praktično je to u pitanju proxy i Nginx je sjajan izbor) i bazu podataka koja nam odgovara.
Moramo još jednom da naglasimo da je na klijentu obaveza da obezbedi ove resurse i podesi ih za rad jer je dobio računar na kojem je instaliran samo operativni sistem. Za PHP nas je sve čekalo podešeno i bilo je potrebno samo da postavimo kôd našeg sajta.
Postoji i treća strana koju još uvek nismo sretali u ponudama hosting kompanija iz regiona. U pitanju su takozvana PaaS rešenja (Platform as a Service), a reč je o tome da kompanija klijentima nudi razne platforme već podešene za različita okruženja koja su vrlo sveža, zanimljiva i možda egzotična. Osim izbora platforme, imamo mogućnost i za skaliranje, da izaberemo koliko nam je servera potrebno, koji će šta da radi, da napravimo cluster prema našim potrebama. Ovom prilikom spomenućemo Heroku servis i kompaniju koja ima sjajne uslove za besplatne aplikacije i koja je izbor mnogih web programera koji se bave ovim novim, šarenim tehnologijama. Servis kao što je Heroku možemo i sami da održavamo jer su prisutni projekti kao što je OpenShift. Heroku i OpenShift su jedna sasvim posebna priča.
Pomoćni alati
Mnoge kompanije u svojem IT arsenalu često imaju i servere o kojima se brinu, imaju zaposlene koji su odgovorni kada nešto zakaže (tzv. sysadmini) i donekle razrađenu infrastrukturu. Naravno, najviše šta možete da očekujete da ćete zateći u takvom okruženju su redovan web server i eventualno neko Java rešenje (Tomcat ili .NET, ASP, ADO i družina). Naravno, to nam ne odgovara za Python i možemo, ili da se dogovorimo sa zaposlenim da na neku od postojećih mašina instaliraju i podese ono šta nam je potrebno za rad, ili da nam obezbede jednu posebnu mašinu koju ćemo spremiti sebi onako kako nama odgovara. Sledi objašnjenje zašto je dobro imati posebnu mašinu i nekoliko korisnih alata koji će nam olakšati da to sve sredimo.
Svi mi na našim računarima imamo gomilu softvera za koje ni ne znamo da su prisutni. Podešavali smo sisteme na svakakve načine i mala je verovatnoća da ćemo naići na istu konfiguraciju, a u produkciji i to može da dovede do vrlo ozbiljnih problema kada naše novo isprogramirano čedo preselimo na drugi računar i mnoge stvari više ne rade. Čak i ako uspemo brzo da pohvatamo šta je nedostajalo i pravilo probleme, sledeći put kada nešto izmenimo, ne možemo biti sigurni da li je ta promena uspešno obavljena samo na našem sistemu ili će proći bezbolno i u produkciji. Rešenje je da svaki programer koji radi na određenom projektu ima na raspolaganju i okruženje kakvo ga očekuje u produkciji i pre puštanja novog kôda ili servisa da može da ga testira u uslovima koji verno preslikavaju stvarno stanje.
Vagrant i Puppet
Sysadmini već imaju neku svoju rutinu u podešavanju raznoraznih servisa i to se svodi na „instaliraš ovo, i onda izmeniš onu datoteku, restartuješ onaj daemon, a sve ti to piše na našem wiki-ju“. To tamo piše, ali je uputstvo zastarelo, komplikovano je ili programer ne želi da se bavi time. Srećom na raspolaganju su nam virtuelizacija i softver koji taj posao još više pojednostavljuje. Alatima kao što su Vagrant i Puppet možemo da kreiramo novu virtuelnu mašinu na našem računaru sa željenim instaliranim operativnim sistemom, a Puppet može da nam obezbedi instaliranje i podešavanje ostalih servisa. Okruženje iz produkcije možemo da dobijemo u tri komande: vagrant init, vagrant up i vagrant ssh. Vrlo korisna stvarčica, jer ako krenemo unazad, i prvo tako pripremimo naše razvojno okruženje, onda nemamo problema sa kreiranjem okruženja za produkciju, jer će Puppet isto tako jednostavno instalirati i podesiti sve servise koji smo izabrali. Priču o Vagrantu i Puppetu ćemo ostati dužni za neki drugi broj, a do tada proverite sami o čemu se radi.
Drugi vrlo bitan problem koji Puppet donekle rešava su različite verzije softvera za koji razvijamo naš kôd i koji će nas dočekati u produkciji. Python to rešava na vrlo elegantan način pomoću virtuelnih okruženja (virtualenv – virtual environment) i alata za upravljanje Python modulima. Prednost virtualenv+pip kombinacije u odnosu na instaliranje Python paketa iz zvaničnih riznica naše distribucije je u tome što za svaki projekat možemo da napravimo posebno radno okruženje sa svojim setom paketa i sa određenim verzijama tih paketa. Tako da, ako odlučimo da razvijamo projekat u odnosu na Django 1.4.x seriju, a naša distribucija nudi 1.3.x ili 1.5.x, virtualenv može da reši ovaj problem. Štaviše, ako imamo dva projekta na istoj mašini koji zahtevaju različite verzije paketa, to je sasvim normalna situacija koja se rešava sa dva radna okruženja. Uz python i pip je obavezno spomenuti i virtualenvwrapper, pomoćnu skriptu za bash koja olakšava upravljanje i aktiviranje virtualnih okruženja, i naravno njihovo kreiranje.
Biblioteka Fabric
Sada već imamo zavidan set alata u našoj radionici: Vagrant i Puppet za instaliranje i podešavanje mašine i potrebnih servisa na njoj, pip i virtuelne da obezbede željene verzije i da okruženje nezavisno od ostatka operativnog sistema koji smo namenili za produkciju. Uz ova dva para vrlo korisnih alata, veoma je koristan i fabric. Fabric je python biblioteka za automatizaciju zadataka raznih vrsta. Prednosti koje pruža fabric su skriptovanje u pythonu, jednostavna integracija sa virtualenv i mnogim drugim alatima i podrška za upravljanje udaljenim mašinama putem SSH protokola pomoću paramiko biblioteke. Cilj je da u jednoj datoteci (najčešće fabfile.py) definišemo funkcije i zadamo uputstva za automatizaciu određenih zadataka. Evo nekoliko ideja:
- fab deploy: pokreni testove, ako se testovi uspešno izvrše dodaj nov kôd u repozitorijum, poveži se na server i osveži kôd na njemu, restartuj servise na serveru i proveri da li je sve završeno kako treba;
- fab test: pokreni testove i proveri da li su nove izmene u kôdu možda poremetile nešto;
- fab init: poveži se na udaljeni server, preuzmi konfiguracionu datoteku za puppet (manifest), postavi potrebne servise, podesi radno okruženje, instaliraj zavisnosti, preuzmi moju aplikaciju i inicijalizuj bazu podataka, restartuj servise i proveri da li je sve u redu.
Tri složena primera, koji su naizgled komplikovani da se iskodiraju, ali vrlo brzo ćete se uhodati i nakon toga ćete bez razmišljanja biti spremni da klijentu u roku od 15 minuta rešite problem i nadogradite mu sistem sa potpunom sigurnošću da će sve proći bez problema jer ako radi kod vas, mora da radi i kod njega.
Testiranje kao sastavni deo programiranja
U prethodnom odeljku smo više puta spomenuli testiranje. Jedan važan deo razvoja softvera zauzimaju i razne vrste testiranja. Moramo biti uvereni pre svega da je kôd sintaksno ispravan, da može da bude pokrenut. Nakon toga, treba testirati i semantiku celog sistema i videti da li se kôd ponaša očekivano. Testiraju se pouzdanost, robusnost, performanse i još mnogo stvari. Početkom 2000-ih godina se pojavio termin „agile software develpment“ koji obuhvata razne tehnike za razvoj softvera na takav način da se nove mogućnosti brzo dodaju, greške što primećuju i ispravljaju i da se skrati vreme potrebno za putovanje kôda od razvojnog okruženja do puštanja u rad.
Sastavni deo ovakvog načina razvoja softvera je pisanje testova i pojavili su se termini kao što su Test Driven Development (TDD, razvoj vođen testiranjem) i Behaviour Driven Development (BDD, razvoj vođen ponašanjem softvera). Dva vrlo slična pristupa, TDD je nešto stariji nego BDD, ali oba pristupa dele vrlo bitne principe. Jedan je da prvo napišemo test za mogućnost koju treba da implementiramo, a potom dodajemo ili menjamo kôd sve dok ta mogućnost ne proradi. Drugi princip se direktno nadovezuje na prethodni i podrazumeva da izmene u kôdu ne smeju da pokvare ni jedan drugi test, odnosno nismo završili posao sve dok imamo neuspešnih testova.
U čemu je prednost i zašto bi neko pisao nekoliko puta više linija kôda za testove nego za sam kôd koji predstavlja funkcionalnost? Pokazalo se da tokom životnog veka projekta, 90% kôda bude vrlo brzo napisano, a potom sledi pakao ispravljanja grešaka. Upravo ovi testovi nam daju slobodu da se slobodno krećemo po kôdu i bezbrižno ga menjamo, jer ćemo u svakom trenutku znati šta smo kada pokvarili i moći ćemo da pogledamo čak i deo kôda koji je u tom trenutku izmenjen i ko ga je izmenio. Kod TDD-a, testovi su u nadležnosti programera, jer je on dužan da osmisli i implementira test primere. BDD je otišao korak dalje i omogućio poslodavcima da napišu test primere jezikom koji razumeju, a potom programeri na vrlo jednostavan način kreiraju parsiranje i izvršavanje tih primera. Dobit za programere je neprocenjiva. Pre svega, poslodavci su naterani da dobro razmisle o svojim idejama i željama koje su nekada toliko fantastične, da ni oni sami ne mogu da ih zapišu rečima, a očekuju od programera da ih pretoče u kôd. Drugo, ako testovi koji predstavljaju sve njihove test primere uspešno prolaze, a oni se žale da nešto još ne radi, uvek možete od njih da zatražite da vam pokažu u kojem se to primeru nalazi, a uglavnom će oni biti krivi, jer tu mogućnost nisu zadali u specifikaciji. Projekti vredni pažnje su Cucumber, Nose Test, Lettuce, Robot Framework, Selenium i mnoštvo drugih.
Zaključak
Predstavili smo nekoliko praktičnih problema u razvoju softvera uopšte i nekoliko rešenja koja su uglavnom vezana za Python svet, ali naravno da ekvivalenti postoje i za druge „programerske kulture“. Pisali smo o problemu postavljanja infrastrukture koji rešavaju vagrant i puppet, o tome da je važno da okruženje za razvoj i za produkciju bude što sličniji, u čemu nam pomažu pip i virtualenv. Spomenuli smo i primer kako na jednostavan način možemo naše ispravke brzo da plasiramo klijentu i o sve popularnijem načinu razvoja projekata vođenim pisanjem testova. Ovo je samo vrh ledenog brega, samo pojmovi, alati i veštine sakupljene na jednom mestu. Bilo bi vrlo dobro kada bismo mogli da porazgovaramo, razmenimo iskustva i možda malo skrenemo pažnju hosting kompanijama na PaaS usluge kao što pruža Heroku, jer je to u interesu svima nama.