node.js

13
2. Node.js Korišćena literatura pri izradi ovog poglavlja: Amos Q. Haviv, (2014), MEAN Web Development, str. 30-41 Adam Bretz i Colin J. Ihrig, (2014), Full Stack JavaScript Development With MEAN, str. 48-119 Simon Holmes, (2015), Getting MEAN with Mongo,Express, Angular and Node, str. 70-73 M. Cantelon, M. Harter, T.J. Holowaychuk i N. Rajlich, (2014), Node in Action, str. Oficijalni Node.js veb-sajt, https://nodejs.org/ , [16.05.2015] Oficijalni veb-sajt definiše Node.js (u nastavku samo Node) kao „Platforma izgrađena nad Google-ovim V8 JavaScript engine-u za izradu brzih, skalabilnih mrežnih aplikacija. Node koristi event- driven, non-blocking U/I model koji ga čini lakim i efikasnim, pogodnim za izradu data-intensive real-time aplikacija koje se mogu izvršavati na različitim uređajima“. 2.1. Istorijat i razvoj Node-a Na konferenciji „JSConf EU“ održanoj 2009. godine developer Ryan Dahl je prvi put prezentovao svoj projekat pod nazivom „Node.js“. Početkom 2008 Dahl je primetio čudan način funkcionisanja tadašnjih veb aplikacija. Uvođenjem AJAX tehnologije nekoliko godina ranije statičke veb stranice transformisane su u dinamičke veb aplikacije, ali osnovni gradivni blokovi kod izrade aplikacija su ostali isti. Problem se ogledao u tome da nije postojala dvosmerna komunikacuja između brauzera i servera. Pa npr. prilikom upload-ovanja fajla, brauzer nije mogao da zna koliko da pomera prograss bar, jer server nije mogao da ga obavesti koliko podataka je upload-ovano. Dahl-ova ideja bila je

Upload: nenad-bugaric

Post on 17-Sep-2015

20 views

Category:

Documents


0 download

DESCRIPTION

About NodeJS

TRANSCRIPT

2. Node.js

Koriena literatura pri izradi ovog poglavlja:Amos Q. Haviv, (2014), MEAN Web Development, str. 30-41Adam Bretz i Colin J. Ihrig, (2014), Full Stack JavaScript Development With MEAN, str. 48-119Simon Holmes, (2015), Getting MEAN with Mongo,Express, Angular and Node, str. 70-73M. Cantelon, M. Harter, T.J. Holowaychuk i N. Rajlich, (2014), Node in Action, str. Oficijalni Node.js veb-sajt, https://nodejs.org/, [16.05.2015]

Oficijalni veb-sajt definie Node.js (u nastavku samo Node) kao Platforma izgraena nad Google-ovim V8 JavaScript engine-u za izradu brzih, skalabilnih mrenih aplikacija. Node koristi event-driven, non-blocking U/I model koji ga ini lakim i efikasnim, pogodnim za izradu data-intensive real-time aplikacija koje se mogu izvravati na razliitim ureajima.

2.1. Istorijat i razvoj Node-a

Na konferenciji JSConf EU odranoj 2009. godine developer Ryan Dahl je prvi put prezentovao svoj projekat pod nazivom Node.js. Poetkom 2008 Dahl je primetio udan nain funkcionisanja tadanjih veb aplikacija. Uvoenjem AJAX tehnologije nekoliko godina ranije statike veb stranice transformisane su u dinamike veb aplikacije, ali osnovni gradivni blokovi kod izrade aplikacija su ostali isti. Problem se ogledao u tome da nije postojala dvosmerna komunikacuja izmeu brauzera i servera. Pa npr. prilikom upload-ovanja fajla, brauzer nije mogao da zna koliko da pomera prograss bar, jer server nije mogao da ga obavesti koliko podataka je upload-ovano. Dahl-ova ideja bila je da napravi veb platformu koja e obazbediti ovakav vid komunikacije.

Kod uobiajenih veb aplikacija, platforma koja se koristi mora da podrava stotine (nekada i hiljade) istovremenih konekcija izmeu servera i brauzera. Veina veb platformi koristi niti za hendlovanje pristiglih zahteva, to zahteva dosta hardverskih resursa. Tako da se Dahl odluio za drugaini pristup. On se odluio za korienje neblokirajuih soketa to zahteva mnogo manje hardverskih resursa, a onda je dokazao da je to mogue izvesti korienjem C jezika. Tu tehniku je mogue realizovati u skoro svakom programskom jeziku a poto je Dahl-ov stav bio da bi bilo naporno raditi sa neblokirajuim C kodom, on se odluio da iskoristi jezik koji bi bio pogodniji za takav nain programiranja.

Google je najavio svoj novi V8 JavaScript engine pri kraju 2008. godine, koji je obezbeivao da se JavaScript izvrava mnogo bre nego to je to bio sluaj do tada. Glavna prednost V8 nad drugim engine-ima je bila kompajliranje JavaScript koda u mainski kod pre njegovog izvravanja. Ove i ostale optimizacije uticale su na to da Dahl odabere JavaScript. On je iskoristio V8 engine, koji je obmotao svojim postojeim C kodom i time je kreirao prvu verziju Node-a.

Nakon dobrog pijema na koji je naiao u zajednici odluio se da priiri funkcionalnost jezgra Node-a. Poto je V8 pravljen za rad u brauzeru a ne na serveru, njegova funkcionalnost morala je biti proirena kako bi odgovarala zadacima na serverskoj strani kao to je npr. pristup fajl sistemu itd. Kao rezultat dobijena je platforma sposobna za izvravanje kompleksnih JavaScript aplikacija lakih za programiranje, vrlo efikasnih u pogledu hardverskih resursa, i lakih za skaliranje.Comment by Nenad Bugaric: Ascetic - 30

2.2. Node event-driven programiranje

Poto brauzer koristi jednu nit pri radu, ukoliko bi se koristilo sinhrono programiranje esto bi nastajale situacije gde je sve zamrznuto dok se neki deo koda ne izvri do kraja. I za to vreme bi korisnici morali da ekaju kako bi mogli da obave neku akciju, to bi bilo dosta loe iskustvo. Zato JavaScript koristi event-e da izvri set komandi, a to postie zahvaljujui unitranjoj petlji, koja se esto naziva i event petlja. Event petlja je petlja koja radi na jednoj niti, i izvrava se sve vreme. Svaki put kada se event desi, brauzer ga dodaje u red event-a. Event petlja uzima prvi event koji je dostupan u redu event-a, i izvrava event hendler-e koji su registrovani za taj event. Nakon to zavrsi sa obradom hendlera, event petlja ponovo proverava red event-a i postupak se ponavlja.

Slika 2.1 - Princip rada event petlje

Razlika se ogleda u tome to se brauzer obino bavi event-ima generisanim od strane korisnika kao to je npr. klik na neko dugme, dok se Node bavi event-ima razliitog tipa koji su generisani od strane razliitih izvora.

Kod uobiajene veb server logike, esti su sluajevi traenja sistemskih resursa usled blokirajueg koda. Dobar primer za ovo je interakcija sa bazom podataka, gde server izda upit bazi koja e zatim izvriiti select naredbu i rezultat vratiti nazad nakon ega e server biti obaveten o pribavljenim podacima, i moi e da nastavi dalje sa izvrenjem. Glavni problem kod ove procedure, je taj to se blokiraju sve operacije dok se razultat ne pribavi iz baze. to u sutini znai da e nit ostati u stanju mirovanja ne radei nita, a za to vreme e koristiti sistemske resurse. Pa pristup koji koriste mnoge veb platforme, gde se obino izdaje jedna nit po zahtevu, tj. po konekciji nije najbolje reenje. Ovo reenje poveava kompleksnost platforme, sistemski resursi se troe na niti koje ne rade nita, i na kraju skaliranje se ne moe lako obaviti.

Ovo nije veliki problem kada se razvija aplikacija koja se ne obraa esto serveru, i gde se komunikacija sa serverom zavrava nakon to se primi odgovor. Ali kada se radi o real-time aplikaciji gde je ivotni vek konekcije dug stvari se drastino menjaju to pokazuje i graf ispod. Na slici je dato poreenje u obradi konkurentnih zahteva kod Apache koji je blokirajui veb server i NGINX-a koji kao i Node koristi neblokirajuu event petlju.

Slika 2.2 - Poreenje broja prihvacenih zahteva u zavisnosti od broja konkurentnih korisnika kod nginx i apache servera

Pored razlike u konkutentnoj mogunosti obradi, jo vidljivija je razlika na sledeoj slici koja pokazuje razliku u korienju memorije kod ova dva servera.Comment by Nenad Bugaric: http://blog.webfaction.com/2008/12/a-little-holiday-present-10000-reqssec-with-nginx-2/

Slika 2.3 - Alokacija memorije u zavisnosti od broja konkurentnih korisnika kod Apache i Nginx-a

Kao to se moe videti iz testova event-driven arhitektura moe drastino pomoi da se smanji optereenje servera to Node koristei JavaScript i obezbeuje.

2.3. Node moduli

Prilikom pisanja koda aplikacija, zbog preglednosti koda, lakseg odravanja i ponovne upotrebe delova koda ne prepuruuje se smetanje celokupne logike u samo jednom fajlu, ve se vri grupisanje povezane logike i vri se razmetanje tih logikih celina po posebnim fajlovima.

Jedna od glavnih mana JavaScript programskog jezika je deljenje jednog globalnog namespace-a. to za posledicu ima da kada se uita skripta u veb-stranu, engine ubacuje njen kod u adresni prostor deljiv izmeu svih uitanih skripti. Pa ukoliko se kreira promenjiva u jednoj skripti, moe se desiti da se promenjiva u drugoj skripti nenamerno overwrite-uje jer im se imena poklapaju. Na ovakve greke je lako naii u veim veb aplikacijama, a vrlo ih je teko detektovati. Comment by Nenad Bugaric: Ascetic - 36

Node reava ovaj potencijalni problem korienjem mehanizma za pisanje i ukljuivanje izolovanih modula, i na taj nain izbegava greke koje se mogu javiti u globalnom namespace-u. Node moduli dozvoljavaju selekciju funkcija i promenjivih u modulu koje aplikacija moe koristiti, sto se postie korienjem exports objekta. Primer kako izgleda kod jednog prostog modula dat je ispod.Comment by Nenad Bugaric: Node in Action - 39

var message = Hello;exports.sayHello = funtion(){console.log(message);}exports.sayHelloWorld = funtion(){console.log(message + World);}

Ukoliko se kod modula nalazi u fajlu ije je ime npr. hello.js, postupak ukljuenja modula u kod nekog drugog fajla je sledei:

var hello = require('./hello');hello.sayHello();

U navedenom primeru hello modul aplikaciji na korienje izlae sayHello() metod definiui ga kao property export objekta. Onda se u drugom delu aplikacije vri uitavanje modula korienjem require() metode, to omoguava pozivanje sayHello() sayHelloWorld() metoda modula.

Drugi pristup kreiranju modula koristi se ukoliko se aplikaciji na korienje eli izloiti samo jedna funkcija, i on se svodi na korienje module.exports pokazivaa. Ukoliko modul treba da izvri samo kod funkcije sayHello() iz predhodnog primera, on e izgledati ovako:

module.exports = function() {var message = 'Hello';console.log(message);}

Dok e kod ukljuenja modula u biti:

var hello = require('./hello');hello();Comment by Nenad Bugaric: Ascetic - 37

U ovom primeru aplikacija koristi modul direktno kao funkciju umesto da koristi sayHello() metod kao u predhodnom primeru.

Slika 2.4 - Ukljuenje modula u aplikacijuComment by Nenad Bugaric: Node in action - 40

Node dolazi sa velikim brojem ve ugraenih modula, koji omoguavaju veinu osnovnih funkcionalnosti ukljuujui pristup fajl sistemu, HTTP server i jos mnogo toga. Svi moduli sa kojima Node dolazi dobro su dokumentovani na oficijalnom sajtu. Ukljuivanje modula u aplikacuju obavlja se na isti nain kao u predhodnom primeru, jedino je potrebno znati ime modula koji je potrebno ukljuiti. Pa bi za ukljuivanje modula za pristup fajl sistemu kod bio:

fs = require('fs');

2.4. NPM

Osim modula koji dolaze uz Node, mogue je koristiti i third-party module. Npm je package manager za Node i ini srce njegovog modularnog ekosistema. On je i sam u sustini modul koji se instalira globalno u sistemu prilikom instalacije Node-a. Zadatak NPM-a je da prui mogunost pretraivanja i instalacije dostupnih modula koji se po difoltnim podeavanjima npm-a nalaze na udaljenom registry-ju (npmjs.com). Moduli koji se pribavljaju putem NPM-a mogu biti instalirani globalno ili lokalno, i moe se zahtevati konkretna verzija modula. Prilikom instalacije odreenog modula npm takoe preko mree pribavlja i instalira sve module koji su potrebni za rad tog konkretnog modula. U fajlu package.json koji se nalazi u root folderu projekta definisani su svi moduli koji se koriste u projektu, kao i osnovne informacije o samom projektu.

{name:testApp,version:1.0.0,scripts:{start:node app.js},dependencies:{express:4.2.0,jade:*Comment by Nenad Bugaric: Getting MEAN - 72}}

name - je ime modula ili aplikacije, i potrebno je da bude jedinstveno ukoliko se planira objavljivanje modula na npm. version - predstavlja semantiku verziju paketa i preporuuje se da se pone sa verzijom 1.0.0. script - sadri dodatne komande koje e se izvravati u toku ivotnog ciklusa aplikacije. Gde key vrednost prestavlja event u toku ivotnog ciklusa, a value predstavlja komandu koja se tada izvrava. U primeru iznad npm e pokrenuti izvrenje app.js skripte. dependencies - je najbitniji deo fajla i koristi se za navoenje modula koji su potrebni aplikaciji kako bi funkcionisala korektno. On predstavlja objekat koji sadri key-value parove, gde se za key postavlja ime a za value verzija modula koji se koristi. Komandom npm install vri se instalacija svih navedenih modula.

Kreiranje ovog fajla se obino ne radi runo, vec se koristi generator koji se pokree npm init komandom u terminalu. Takoe ni module nije potrebno runo unositi, ve je samo potrebno navesti opciju -save prilikom instalacije i on e automacki biti dodat u dependencies. Na primer ukoliko se instalira express modul komanda e biti:Comment by Nenad Bugaric: Full Stack - 65

npm install express -save

Kao to je ve pomenuto moduli koji se instaliraju mogu biti lokalni i globalni. Lokalni moduli se instaliraju lokalno u projekat iz kog je instalacija pozvana, i ne mogu se koristiti spolja. Dok se globalno instalirani moduli mogu pozivati bilo gde u sistemu uz pomo terminala. NPM je jedan takav modul. Da bi se modul instalirao globalno, sve to je potrebno uraditi je dodati opciju -global prilikom instalacije. Na primer:npm install express-generator -global

2.5. Connect Middleware

Connect je HTTP modul koji je pravljen da podri presretanje zahteva na modularan nain. I za to koristi modularne komponente nazvane middleware. Prosto reeno middleware su funkcije koje hendluju zahteve. Server kreiran sa connect.createServer (gde connect predstavlja connect modul), ima dodeljen stack middleware-a. Kada zahtev pristigne, on se prosleuje prvoj middleware funkciji zajedno sa ServerResponse objektom i next callback-om. Svaki middleware moe da odlui da odgovori pozivanjem metode nad response objektom, i/ili da prosledi zahtev sledeem middleware-u u stack-u pozivanjem next(). Jednostavni middleware koji nema nikakvu aplikacionu logiku ve samo vri prosleivanje sledeem middeware-u dat je ispod.Comment by Nenad Bugaric: http://stephensugden.com/middleware_guide/

function uselessMiddleware(req, res, next) { next() }

U datom primeru req je objekat koji sadri HTTP request, res je objekat koji sadri HTTP response informacije i omoguava postavljanje response propertie-a, dok je next sledea middleware funkcija kojoj se request prosleuje. Za dodavanje middleware-a u stack middleware-a servera koristi se use.

connect = require('connect');useless = connect.createServer();useless.use(uselessMiddleware);

Prilikom dodavanja middleware-a mogue je dodati i prefiks, i tada e middleware biti pozvan da hendluje zahtev samo ukoliko taj prefiks odgovara zahtevu.

connect = require('connect');useless = connect.createServer();useless.use(/user, uselessMiddleware);

Connect je modul koji podrava razne karakteristike uobiajenih veb aplikacija, i omoguava neogranieno nadograivanje aplikacione logike. Iako je Connect veliko unapreenje u odnosu na runo pisanje infrastrukture veb aplikacije, on ipak ne prua neke osnovne osobine koje se koriste kod veb aplikacija. Razlog za to lezi u osnovnim principima Node zajednice, koja predlae da se prave mravi moduli a onda da se oni koriste za izgradnju drugih veih modula. Pa je tako na primer developer TJ Holowaychuk iskoristio Connect modul i napravio veb framework koji je nazvao Express, o kom e vie biti reeno u sledeem poglavlju.Comment by Nenad Bugaric: Ascetic - 48

2.6. Node TCP i veb server

Node je platforma koja podrava razliite tipove aplikacija, ali najpopularnija vrsta je izrada veb aplikacija. Pa su u duhu toga dati i objanjeni prosti primeri veb servera i tcp servera koji su dati na oficijalnom sajtu (https://nodejs.org/).Comment by Nenad Bugaric: https://nodejs.org/

2.6.1. Veb server

var http = require('http');http.createServer(function (req, res) { res.writeHead(200, {'Content-Type': 'text/plain'}); res.end('Hello World\n');}).listen(3000, '127.0.0.1');

Da bi se pokrenuo server potrebno je kod sauvati u nekom fajlu, npr. app.js a onda ga je potrebno pokrenuti iz terminala komandom node app.js. Ovaj jednostavni server uvek e oslukuje na portu 3000 i uvek odgovarati sa Hello World, a zahtev mu se upuuje unoenjem adrese http://127.0.0.1:3000 u brauzer.

Prvo je potrebno pribaviti http modul i onda iskoristiti njegov createServer() metod koji vraa novi server objekat. Zatim se kotisti listen() metod nad tim objektom koji slua na portu 3000. Callback funkcija koja je prosleena createServer metodu poziva se svaki put kada pristigne novi HTTP zahteva. Njoj se prosleuju req i res argumenti koji sadre informacije i finkcionalnosti potrebne za slanje HTTP odgovora. U callback funkciji e se prvo pozvati writeHead() metod response objekta koji postavlja tip response-a i Content-Type. Onda se poziva end() metoda response objekta koja se koristi za finaliziranje objekta. Ovom metodu prosleuje se jedan string argument koji se koristi za telo HTTP response-a.

2.6.2. TCP server

var net = require('net');var server = net.createServer(function (socket) {socket.end("Hello World\n");}).listen(7000, "127.0.0.1");

Kao i kod veb servera prvo je potrebno ukljuiti modul, ovog puta se radi o net modulu. Kada je modul pribavljen koristi se njegova metoda createServer() koja kreira novi TCP server objekat, koji poziva callback funkciju na svaki connection event. Dok listen metod server objekta slua na portu 7000 za novim zahtevima za konekciju. End() metod unutar callback funkcije odgovara na svaku novu konekciju sa Hello World a zatim zatvara tu konekciju.