Laravel kao 12-faktorska aplikacija

Ljudi koji su radili na platformi Heroku definirali su 12 točaka o kojima bi programer trebao voditi računa ako planira posluživati aplikaciju u nekom PaaS okruženju, ili generalno za bilo koju aplikaciju koja će raditi kao servis. Opis tog koncepta dostupan je na poveznici https://www.12factor.net/

Platform as a Service (PaaS) je računalna platforma koja omogućuje korisnicima korištenje okruženja u kojem mogu upravljati svojim aplikacijama i posluživati ih a da ne moraju sami izgraditi infrastrukturu na kojoj će posluživati svoje aplikacije. Tipično sadrži operacijski sustav, okruženje za specifični programski jezik, baze podataka, web-poslužitelje i slično. Sve te dostupne servise korisnici mogu definirati i koristiti prema potrebi i prema svojim postavkama. Neki od primjera PaaS platformi su: AWS Elastic Beanstalk, Windows Azure, Heroku, Force.com, Google App Engine, Apache Stratos i Cloud Foundry. (Izvor: https://apprenda.com/library/paas/paas-examples-platformasaservice-options-to-consider)

Prođimo kroz spomenutih 12 točaka i pogledajmo kako možemo imati aplikaciju Laravel koja je pogodna za postavljanje u bilo koje PaaS okruženje.

I. Codebase (One codebase tracked in revision control, many deploys)

Ova točka odnosi se na način na koji radimo s izvornim kodom aplikacije. Uvijek bismo se trebali koristiti nekim sustavom za verzioniranje programskog koda, kao što je npr. Git ili slično. Aplikacija mora imati jedan izvor koda, a on se može postavljati u različita okruženja (npr. produkcijsko, testno, okruženje za razvijanje i slično). Pravilo ćemo zadovoljiti ako se npr. koristimo Git sustavom za pohranu programskog koda i njegovo verzioniranje.

II. Dependencies (Explicitly declare and isolate dependencies)

Aplikacija Laravel koristi se alatom Composer koji služi za upravljanje ovisnim PHP paketima. Time su ovisni paketi definirani i izolirani od same aplikacije. Definicija ovisnih paketa nalazi se u datoteci 'composer.json', a ovisni paketi će biti instalirani u direktoriju 'vendor'.

III. Config (Store config in the environment)

Aplikacija Laravel ima mogućnost definiranja i korištenja različite konfiguracije u različitim okruženjima. Npr. za produkcijsko okruženje možemo se koristiti jednom konfiguracijom, za testno okruženje drugom konfiguracijom i slično. Prema početnim postavkama konfiguraciju možemo definirati u datoteci '.env' koja se nalazi u korijenskom direktoriju aplikacije.

IV. Backing services (Treat backing services as attached resources)

Ova točka opisuje kako bi sve servise kojim se aplikacija koristi trebali tretirati kao attached resources. Neovisno o okruženju, aplikacija bi se trebala moći povezati na neki resurs bilo preko URL‑a, socketa itd. Na primjer, ako se aplikacija koristi bazom podataka MySQL, onda bi se aplikacija trebala moći povezati na tu bazu tako da samo definiramo korisničke podatke za pristup. Ako aplikaciju premjestimo u drugo okruženje (npr. iz testnog u produkcijsko), sve što je potrebno jest promijeniti korisničke podatke za pristup. Laravel radi na taj način.

V. Build, release, run (Strictly separate build and run stages)

Programski kod pušta se u produkciju kroz tri faze. Prva faza je faza izgradnje (engl. build stage) u kojoj se programski kod pretvara u izvršni kod. PHP je skriptni programski jezik koji se interpretira prilikom svakog izvršavanja (nema kompiliranja). Druga faza je faza izdavanja (engl. release stage). U toj fazi koristi se izvršni kod i kombinira se s konfiguracijskim parametrima. Takav izvršni kod je spreman za izvršavanje. Treća faza je faza izvršavanja (engl. run stage). U toj fazi pokreću se sistemski procesi potrebni za pokretanje i rad izvršnog koda.

VI. Processes (Execute the app as one or more stateless processes)

Aplikacija ne smije ovisiti o nekim lokalnim podacima koje generira tijekom svog rada. Npr. aplikacija ne bi trebala spremati neke podatke na lokalni disk, koji joj onda trebaju za rad, jer do tih podataka tipično može doći samo ta jedna instanca aplikacije. Budući da u okruženjima PaaS možemo pokrenuti više instanci jedne aplikacije, podatke koje aplikacija treba za rad ne smije spremati lokalno, nego ih treba spremati s pomoću dodatnog servisa (npr. u bazu podataka ili slično), kako bi do tih podataka mogla doći svaka instanca aplikacije. Također, u okruženjima PaaS prilikom svakog puštanja aplikacije u pogon svi podaci iz radne memorije i podaci s lokalnog diska brišu se. Dakle, ako je aplikacija imala neko lokalno 'stanje', npr. prije resetiranja aplikacije, nakon resetiranja aplikacije u PaaS okruženju ti će podaci tipično biti izgubljeni. Dakle, takve podatke moramo spremati preko dodatnih servisa do kojih će aplikacija moći doći u bilo kojem trenutku. U aplikaciji Laravel to pravilo možemo jednostavno zadovoljiti korištenjem vanjskih servisa za spremanje potrebnih podataka. Npr. za spremanje informacija o sesijama korisnika možemo se koristiti servisom Redis.

VII. Port binding (Export services via port binding)

Pravilo kaže da bi aplikacija trebala biti dostupna kao servis preko određenog porta. Čitava stvar se definira tako da je aplikacija izolirana od okruženja, a preko postavki definiramo kojim aplikacijama će se koristiti za posluživanje aplikacije. Npr. imamo izvorni programski kod aplikacije Laravel koju držimo kao Git repozitorij. Preko postavki za okruženje PaaS definiramo koju verziju PHP-a želimo, kojim se web-poslužiteljem želimo koristiti i slično (sada je nebitno kako definiramo te stvari, bitno je navesti da se one dodatno/nezavisno definiraju).

VIII. Concurrency (Scale out via the process model)

Pravilo kaže da bi aplikacija trebala biti predstavljena procesom. Dakle, u našem slučaju to može značiti da će web-poslužitelj Apache pokrenuti proces kada stigne HTTP zahtjev na našu aplikaciju. Trebalo bi se moći pokrenuti više procesa, ovisno o broju zahtjeva, i to ne samo na jednom stroju, nego na više različitih strojeva. Također, zahtjevi za koje je potrebno kratko vrijeme mogu se odraditi preko jednog tipa procesa, a zadaci koji zahtijevaju više vremena mogu se pokrenuti preko drugog tipa procesa (npr. proces worker za obavljanje nekih pozadinskih zadataka ili slično). Ako aplikaciju razvijamo na način da ne ovisi o lokalnim podacima tijekom rada, jednostavno ćemo moći pokrenuti više instanci jedne aplikacije (možemo je skalirati), a o ostatku će se brinuti okruženje PaaS.

IX. Disposability (Maximize robustness with fast startup and graceful shutdown)

Ako aplikaciju shvatimo kao proces, onda bismo je trebali moći ugasiti i/ili upaliti u bilo kojem trenutku. Gašenje aplikacije nikad ne bi trebalo napraviti neki problem u okruženju, a svi podaci bi trebali ostati konzistentni.

X. Dev/prod parity (Keep development, staging, and production as similar as possible)

Radi se o tome da sva okruženja u kojima će naša aplikacija raditi moraju biti što sličnija, bilo to produkcijsko, testno ili razvojno okruženje.

XI. Logs (Treat logs as event streams)

Aplikacija se ne bi trebala brinuti o tome gdje će se spremati logovi za aplikaciju, nego bi jednostavno sve događaje trebala bacati u STDOUT. U aplikaciji Laravel možemo jednostavno konfigurirati na koji način će se spremati logovi.

XII. Admin processes (Run admin/management tasks as one-off processes)

Programeri često imaju potrebu pokrenuti neku naredbu u proizvoljnom trenutku. Primjer može biti migriranje baze podataka ili pokretanje bilo kakve naredbe u komandnoj liniji. Ovo pravilo jednostavno kaže da bi se svi ti dodatni zadaci (naredbe) trebale pokretati u istom okruženju u kojem radi aplikacija, dakle uključujući istu konfiguraciju kojom se koristi aplikacija. U nastavku ćemo vidjeti primjer pokretanja migracija za bazu u aplikaciji Laravel u PaaS okruženju i na koji načine možemo to napraviti.