Ennek ellenere PHP-ban ezek biztos hogy csak egymas utan fognak lefutni. a multiprocessing ott azt jelenti, hogy 250 ilyen keres mehet parhuzamosan, de ez mindegyiknel sorrendben lesz, nem is szamit.
NodeJS-ben egesz maskepp kell gondolkodnod. Meg maguk a db libek is async hivast csinalnak, ergo:
save1();
save2();
save3();
Ha fugg egymastol az amugy async save1() save2() es save3(), akkor vagy callback-be kell tenni (sikerult vagy nem sikerult fuggveny), vagy fire-olni kell egy eventet es annak a listenerebe kell tenni, vagy promise-ba kell tenni es annak a .then() fuggvenyebe
var saveret1 = save1();
saveret1.onDone(function{
var saveret2= save2();
...
});
Nem feltetlen kell ezeket undoritoan egymasba agyazni. Lehet globalis event listener ami done-kor fire-olodik mint event, vannak async dependency kezelo libek, amik segitenek egymastol fuggetlenul lefuttatni ezeket a megfelelo fuggosegi sorrendekben, de sajnos meg db muveletekhez is egyszeruen EL KELL FELEJTENED a proceduralis egymas utan irast nemtrivialis muveletekre (pl db lekerdezes). Cserebe jobban multiprocess ready lesz a kodod akaratlanul is.
Tehat roviden osszefoglalva: itt nem egymas utan lefuto dolgokat definialsz. Itt sorrendeket es process-ek kozti fuggosegi tablakat definialsz.
Magyarazo pszedudokod (nem valid nodejs kod) a fenti PHP kod NodeJS-es valtozatara:
var can10run = 0; // trivialis muvelet, szinkron lefut, kovetkezo sor elott
var can10runlistener = new eventListener(); // trivialis muvelet, szinkron lefut, kovetkezo sor elott
Utasitas1().done(Utasitas2().done(Utasitas3().done( function { // mind aszinkron, done-ra hivjak meg egymast
Utasitas4().done(function {
can10run++;
can10runlistener.triggerEvent();
});
Utasitas5(); // Ennek a done-ja nem is erdekel minket, mindegy lefutott-e, csak elindul ugy async
})));
// az Utasitas1()-ben bealllitott valtozot itt jo esellyel nem latod
Utasitas6().done(Utasistas7.done(Utasitas8.done(Utasitas9.done( function () { // az Utasitas 1-gyel egyidoben elkezdodik
can10run++;
can10runlistener.triggerEvent();
}))));
onEvent(can10runlistener) {
if (can10run == 2) { // akkor fut le, ha Utasitas4() es Utasitas9() is vegzett, mert azok az elofelteteleik, mindegy milyen sorrendben tortent ez.
Utasitas10(); // mint minden mas, ez is fut a hatterben
}
}
Olvashatatlanabb igen. De cserebe Utasitas1() es Utasitas6() egyszerre lefut mindjart az elejen pl., igy kihasznalva, hogy a gepedben bizony nem csak egymagos processzor van (fixed in comments). Vannak szebb, de kevesbe kezdobarat megvalositasok ezekre, de jobb ha megszokja a szemed ezt a stilust, mert ennel sokkal olvashatobb sose lesz, tanuld meg az event listenereket es az eventek sorrendjet ertelmezni.
Es a legfontosabb: kerlek a nagy tomeggel ellentetben legyszives csinalj olyan kodot, ahol nagyjabol azert egy helyen vannak azok az eventek, amik egymastol fuggnek. Ugyanis ebben a kornyezetben nagyon konnyu write-only kodot irni, ahol osszevissza fut 30 forrasfajl random fuggvenye es event listenere.
Sok helyen lattam mar NodeJS tutorialokat, de ezt a leges legelso lepest atteres elott hianyoltam. Remelem ezzel masoknak segithettem, mert nekem rengeteg idobe tellett felfognom.
- carlcolt blogja
- A hozzászóláshoz be kell jelentkezni
- 2212 megtekintés
Hozzászólások
"De cserebe Utasitas1() es Utasitas6() egyszerre lefut mindjart az elejen pl., igy kihasznalva, hogy a gepedben bizony nem csak egymagos processzor van."
Ez sajnos nem igaz, a javascript futtato kornyezet szigoruan 1 magon (es egy szalban) fut, az IO muveletek (net/disk/db) tudnak csak ebbol profitalni.
- A hozzászóláshoz be kell jelentkezni
Így van, ezt lenne a legfontosabb megérteni. Egyszálúság van. Ez a kódban bár hátránynak tűnik (sok php-n/java-n szocializálódott fejlesztő nem képes ezt a gátat leküzdeni), ugyanakkor pont ennek is köszönheti a jó skálázódási tulajdonságait. Mind development, mind futtatás szempontjából.
- A hozzászóláshoz be kell jelentkezni
Koszi mindkettotoknek, fixed
- A hozzászóláshoz be kell jelentkezni
> Így van, ezt lenne a legfontosabb megérteni. Egyszálúság van. Ez a kódban bár hátránynak tűnik (sok php-n/java-n szocializálódott fejlesztő nem képes ezt a gátat leküzdeni), ugyanakkor pont ennek is köszönheti a jó skálázódási tulajdonságait. Mind development, mind futtatás szempontjából.
Ezt elmagyaráznád nekem, miért?
--
blogom
- A hozzászóláshoz be kell jelentkezni
A developernek jó, mert nem küzd lockokkal, happens-before-ral és a többi nagyon bonyolult™ koncepttel.
A processzormagnak jó, mert nagyságrendekkel kevesebb context switch van.
A Moore úr "törvényéből" levezetett vertikális performancianövekedés megállt, hát jönnek az olyan eszközök, amik a horizontális felé terelik a népet. Ilyen a node.js-ökoszisztéma. Ez sem a szent grál, csak itt más konceptekkel kell bajlódni (clustering, async - amiről a kezdő poszt is szól, stb.)
- A hozzászóláshoz be kell jelentkezni
Hogyan tud jól skálázódni az, ami egyszálú?
----------------
Lvl86 Troll, "hobbifejlesztő" - Think Wishfully™
- A hozzászóláshoz be kell jelentkezni
A javascript, event based modelljében léptékekkel olcsóbb egy "szál" létrehozása, mint ha külön thread-et vagy process-t használna minden lekérdezés kiszolgálására. Persze ennek is meg van a határa, ezért szoktak rendes webszervert node elé rakni, ami több process-ben futtatja a node-os lekérdezésket.
- A hozzászóláshoz be kell jelentkezni
Na de létezik olyan is, hogy thread pool.
----------------
Lvl86 Troll, "hobbifejlesztő" - Think Wishfully™
- A hozzászóláshoz be kell jelentkezni
thread poolban is 1 kliens = 1 thread csak maximalizálva van ez egyszerre futtatható példányok száma, itt viszont akkor is 1 thread van, ha mondjuk 1000 kliens oldalletöltés közben épp várakozik az sql-re
- A hozzászóláshoz be kell jelentkezni
Szerintem elbeszélünk egymás mellett. Én arról beszélek, hogy ha van két párhuzamosan végezhető feladat, akkor miért jó az, hogy gyakorlatilag sorosítjuk? Mert egy szálon gyakorlatilag sorosítva tud csak futni két dolog.
----------------
Lvl86 Troll, "hobbifejlesztő" - Think Wishfully™
- A hozzászóláshoz be kell jelentkezni
Utananezve azzal ervelnek nodejs-ek, hogy ne kelljen egy valtozot tobb thread/process kozt megosztani, mert az tul bonyolult konkurens eseteket eredmenyezne, amit jobb ha a fejlesztonek nem kell ismernie. Helyette lehet csinalni worker process-eket (ugy vettem ki hogy azt sem annyira regota), de azok nem ismerhetik egymas valtozoit. Nincs olyan szofisztikalt megoldas, mint pl a volatile kulcsszo C++-ban es Javaban.
- A hozzászóláshoz be kell jelentkezni
A Node.JS-t tipikusan arra használják, hogy HTTP requestként bejön egy kérés, azzal valamit kezdeni kell, pl. adatbázisból előkotorni valamit, és visszaadni szépen formázott HTML-ként vagy JSON-ként.
A Node.JS azt mondja, hogy nem kell kliensenként egy szálat indítani, csak azért, hogy az várakozzon. Helyette callback-es aszinkron megoldást implementáltak, ami jól illeszkedik a JavaScript logikájához.
Egyébként eredetileg nem is JS-t választott a szerző, hanem Luát. Kár, hogy ez elmúlt...
Fuszenecker Róbert
- A hozzászóláshoz be kell jelentkezni
"A Node.JS azt mondja, hogy nem kell kliensenként egy szálat indítani"
Miért kellene? Attól, hogy vársz IO-ra, hálózatra, db-re, akármire, attól még ugyanazon a szálon tudsz csinálni addig mást.
----------------
Lvl86 Troll, "hobbifejlesztő" - Think Wishfully™
- A hozzászóláshoz be kell jelentkezni
igen, tudsz ezt használja a nodejs is (polling)
- apache/ngnix + php esetében 1 thread egyszerre 1 lekérdezéssel foglalkozik
- apache/ngnix + nodejs esetében 1 thread egyszerre több lekérdezéssel foglalkozik
- A hozzászóláshoz be kell jelentkezni
Értem. Ez mondjuk számomra ebben a formában nem felskálázódás, csupán egy értelmesebb implementáció a Single thread feldolgozásra.
Jó oké persze, egy CPU magra nézve igen, de ma már lassan a mobilokban is 8 core van...
----------------
Lvl86 Troll, "hobbifejlesztő" - Think Wishfully™
- A hozzászóláshoz be kell jelentkezni
Az (adat)párhuzamos meg a konkurens programozás nem ugyanaz teljesen.
- A hozzászóláshoz be kell jelentkezni
Ezt én értem, de attól még lehetnek párhuzamosan végezhető feladatok. (Mi egyébként leginkább ezzel küzdünk a webeinken.)
----------------
Lvl86 Troll, "hobbifejlesztő" - Think Wishfully™
- A hozzászóláshoz be kell jelentkezni
Persze, hogy lehetnek. De pont ez a lényeg: párhuzamosan végezhető, egymástól elszeparált feladatok igazából olyanok, hogy n db egyszálú alkalmazásod fut egymás mellett. Semmi konkurencia nincs benne.
NodeJS alatt is futhat több processzed (több JS threaded fut, egymástól teljesen függetlenül).
Hogy értsd:
Klasszikus konkurens modelben, ahol hiába van több szál, a fő feldolgozandó, szálak között megosztott adatstruktúrát (legyen ez a HTTP request/response pár) úgyis sorosítva éred el, ha nem akarsz konzisztenciahibát.
Namármost, a JS programozási modelljében nem lockokat használsz, hogy a request/response-on végzett műveleteket sorosítsad (és a műveletek hívási sorrendje teteszúleges, legfeljebb várnak a threadek a lockokra - azaz implicit a hívási lánc), hanem explicit hívási lánc van.
- A hozzászóláshoz be kell jelentkezni
és akkor a fenti példa* miért jobb a JS-es, callbackes formában, mint így, egymás után írva?
Hiszen pont az veszik el belőle, hogy a
feladat3()
majd párhuzamosan (másik feldolgozón?) fut amíg a itt folytatódik a végrehajtás, nem? Mert az egész __egy__ szálon hajtódik végre, csak nem az általam megadott sorrendben, hanem ahogy az interpreter jónak látja (ez előny, hogy az interpreter dönt, elismerem. de továbbra is egy szál)
ehhez képest Java-ban (s valszeg .NET-ben is), az egész feladat1-3-5-t kirakom egy AsyncTask-ra, s az onnantól külön szál. Ugyanez a paralellStreamekkel.
Még mindig nem értem, miért jobb az előbbi, pedig tényleg érdekel.
*:
feladat1();
feladat2();
feladat3(); // függ az 1-től
feladat4();
feladat5(); // függ a 3-tól
feladat6(); // függ a 4-től
--
blogom
- A hozzászóláshoz be kell jelentkezni
Szerintem azt a részét nem érted a dolgoknak, hogy itt a taszkokat mindenképp sorosítani kell, mert ugyanahhoz az adatstruktúrához férnek hozzá (ugyanaz a global scope).
Hogy értsd: feladat3() függ 1-től (nem futhat 1 előtt), de nem futhat feladat2()-vel párhuzamosan sem.
Ez az egész egy happens-before gráfot ír le. Nem párhuzamosításról, hanem sorosításról van szó.
Javaban ugyanezt lockokkal oldod meg, lockokkal írod le a happens-before relációkat.
Illetve azt fejezed még ki így, hogy feladat2() elindulhat anélkül, hogy feladat1() ténylegesen véget érne (mondjuk inputra vár, vagy DB írást csinál).
Ugyebár az, ha több szálad van, de valójában a lockolások miatt mindig csak 1 fut, akkor a kódod semmit nem nyert a (formai) többszálúságon :)
Szerintem te ezt kevered a ServiceWorkerrel, az a konkurens programozás (azaz amikor nincs adatfüggés két végrehajtható kód között) JS-es megoldása.
Hogy a JS-hez hasonlítsam: ez a feladat1()-feladatn() kód az AsyncTaskok vezérlő kódja: minden egyes feladatN() az egy AsyncTask-Future indítás lehet.
Meg azért ugye azt vegyük észre, hogy ha 1 CPU-n futsz, akkor teljesen mindegy, hány szálad vna, egyszerre csak egy műveletet végez ez a gép :)
- A hozzászóláshoz be kell jelentkezni
teljesen hülye vagyok a JS-hez, szóval bármivel keverhetem :-)
köszönöm!
--
blogom
- A hozzászóláshoz be kell jelentkezni
A feladat1().then(feladat3).then(feladat4) ugyebár annak felel meg, amikor azt mondod, hogy (pszeudokód)
future1 = feladat1.execute();
future1.get(); // ez megvárja feladat1-et
future3 = feladat3.execute();
etc.
Az, hogy te eközben még leírod a feladat1().execute() után, hogy feladat2().execute, azzal ugyanott vagy, mint a JS-es kódban:
a feladat2-t végrehajtod, MAJD a feladat3 csak akkor indul, ha feladat1 és feladat2 is végzett.
Azaz feladat3 nem fut most sem semmivel párhuzamosan, hiába formailag külön szál.
Azt értem, hogy JS-ben feladat1() és feladat2() egy szálon fut, mert így indítjuk el, és lehetne párhuzamosítani, de erre más technika való.
A JS-es szintakszist képzeld úgy, hogy 1 szálban futtatsz sok függvényt, és mindegyik Future-rel tér vissza, nem kell külön lockolnod a dolgokat, hanem a hívások struktúrája (meg a Future-ok bevárása) leírja azt, hogy pontosan mi mi után fog történni.
Javaban meg ugye figyelned kell arra, hogy ha több szálon indítod el a dolgokat, akkor kikényszerítsd a happens-before relációt.
Igazából az egész csak syntax.
Azt kell megérteniük az embereknek, hogy az I/O nem azonnali művelet, és amíg az I/O processzor vár (lehet ez egy USB-s billentyűzet, meg egy Ethernet chip is), addig is végezhet a CPU hasznos munkát. Ez az a gondolkodásmód, amit meg kell érteni. Az, hogy ezt hogyan fejezed ki szintakszisban, megint más kérdés.
- A hozzászóláshoz be kell jelentkezni
Ooo, nem. Ez netto baromsag. Persze, lehet igy is csinalni, de lehet maskepp is. Pl a pool tagjai select()elnek es valtogatnak a kliensek kozott. Kompromisszum a ket veglet kozott. Gyonyoruen tud mukodni.
--
|8]
- A hozzászóláshoz be kell jelentkezni
mondjuk 5 kulonbozo VM-ben fut?
Ha minden non-blocking (callback, promise, event), akkor teljesen vallalhato.
Egyebkent a node.js-esek most akarnak worker thread-et letrehozni.
---
Saying a programming language is good because it works on all platforms is like saying anal sex is good because it works on all genders....
- A hozzászóláshoz be kell jelentkezni
Több példányban futtatod, külön magon, és nincs a szálak közötti szinkronizációnak overheadje.
- A hozzászóláshoz be kell jelentkezni
Cserebe a peldanyok (vagy peldanyok & db, stb) kozti kommunikacionak van.
--
|8]
- A hozzászóláshoz be kell jelentkezni
Csak akkor, ha nem elég az eventual consistency. Ott nyilván sorosítani fogod az adathozzáférést azon a helyen, ahol erre szükség van.
- A hozzászóláshoz be kell jelentkezni
Ilyen esetben viszont thread poollal is ugyanolyan konnyu megoldani, es a thread kevesebb eroforrast eszik, mint egy kulon processz. ;)
--
|8]
- A hozzászóláshoz be kell jelentkezni
Cserébe nem is lehet egy beragadt szálat csak úgy lelőni :)
- A hozzászóláshoz be kell jelentkezni
Valoban, de szerencsere ilyen esetben el lehet inditani a cuccost megegyszer, es a beragadtat leloni ;)
Pont, mint az egyszalunal.
--
|8]
- A hozzászóláshoz be kell jelentkezni
Az, hogy egy szal van, egyatalan nem teszi konnyebbe a skalazhatosagot. Konnyebb igy fejleszteni, es egymas melle tenni szimplabb szeleteket. De a skalazodas nem olyan egyszeru, hogy elinditasz N darabot belole, max ha teljesen stateless, vagy semmilyen modon nem kell kommunikalniuk. Ha kell, akkor kb ugyanott tartasz, csak egyszerubb komponenseid vannak, cserebe nehezebb - es koltsegesebb - lesz a kommunikacio.
--
|8]
- A hozzászóláshoz be kell jelentkezni
Sok PHP-n/Java-n szocializálódott fejlesztő a konkurens programozás gátját sem tudja leküzdeni :)
- A hozzászóláshoz be kell jelentkezni
azert skalazodik jol, mert egyszalu! ekkora duplagondolt mar regen olvastam
https://en.wikipedia.org/wiki/Cognitive_dissonance
--
NetBSD - Simplicity is prerequisite for reliability
- A hozzászóláshoz be kell jelentkezni
Promise-ek, generátorok, stb. - olvass utána.
És igen, kulturált fejlesztő "az eventeket", vagyis az IO-t különválasztja a nem
IO-tól, tesztelés, concurrency, stb. miatt. Ez nem Node, nem JS specifikus, de
illene így lennie bármilyen nyelvről is beszélünk.
- A hozzászóláshoz be kell jelentkezni
"olvass utána"
Azoknak keszult ez, akik meg csak fogjak ezeket olvasni, vagy mar akar felfogas nelkul olvastak is, de tippjuk sincs miert van rajuk egyaltalan szukseg. Pont az "olvass utana"-kat elkerulendo, ertsek mit olvasnak es mit hol keressenek es miert. Vagy valahol netan teves informaciot kozoltem volna a promise-okrol? Mert azt akkor javitom (meg en se vagyok ezzel nagyon kepben). A celja ennek az volt, hogy tudd, hova nezelodj tovabb, megse legyen semmi tul hosszan magyarazva.
- A hozzászóláshoz be kell jelentkezni
"Lazan" kapcsolodik:
http://andyshora.com/promises-angularjs-explained-as-cartoon.html :)
- A hozzászóláshoz be kell jelentkezni
"Olvashatatlanabb igen. De cserebe Utasitas1() es Utasitas6() egyszerre lefut mindjart az elejen pl., igy kihasznalva, hogy a gepedben bizony nem csak egymagos processzor van (fixed in comments). Vannak szebb, de kevesbe kezdobarat megvalositasok ezekre, de jobb ha megszokja a szemed ezt a stilust, mert ennel sokkal olvashatobb sose lesz, tanuld meg az event listenereket es az eventek sorrendjet ertelmezni."
Ez nem igaz, igenis lehet olvasható async kódot írni, csak meg kell ismerni az eszközöket.
- A hozzászóláshoz be kell jelentkezni
Vagy átmenni reaktívba...
- A hozzászóláshoz be kell jelentkezni
Én, mint már immár lassan 3 hónapja tisztán frontend fejlesztő lévén tanúsíthatom mekkora szopacs és kíllódás átállni erre a gondolkozásra.
De nem lehetetlen. :)
---------------------------------------
Devmeme - fejlesztői pillanatok
- A hozzászóláshoz be kell jelentkezni
Ez ugyanaz a csodaság, ami legutóbb a leftpad-vs-kik üggyel hívta fel magára a figyelmet? Mert az szemre teljesen normális szekvenciális kódnak látszott. (Mind a 11 sor.)
- A hozzászóláshoz be kell jelentkezni
Az proceduralis fuggveny volt, nem volt benne async hivas. Amit most leirtam (elsore rosszul, de javitva) az az async mukodese, kommentekben kozben kiegeszult hogy egy CPU varakozasi sorrendjet lovod be ilyenkor. De ez a leftpadot nem erintette, abban semmi async nem volt, az egy kivetelesen szinkron JS kod volt. Azok megvarjak az elozo (trivialis) utasitast.
- A hozzászóláshoz be kell jelentkezni