2014. október 25., szombat

CMS rendszer statikus oldalakkal

CMS rendszer statikus oldalakkal

Már többször, több formában szembejött a probléma, hogy ha valaki akar egy site-ot, feldob egy PHP/MySQL CMS-t, ami nagyon kényelmes első körben, de aztán amikor elkezd nőni a forgalom, kezdenek egyre jobban kijönni a rendszer korlátai. A MySQL nem bírja a terhelést, a PHP nagyon izzasztja a gépet. Persze, lehet alá erősebb gépet tenni, szét lehet szórni több gépre, így végül is a végtelenségig lehet skálázni egy ilyen rendszert, csakhogy egy sima hírportálra teljesen feleslegesnek tűnik többgépes szerverpark, hisz tulajdonképpen statikus tartalom kiszolgálásáról van szó.

A probléma oka szerintem mélyen a rendszerek architektúrájában keresendő. A WordPress, a Drupal, a Joomla, és a többi CMS rendszer is úgy működik, hogy minden egyes kérésénél összeszedi az adatokat a MySQL-ből, és újra meg újra legenerálja az oldalt. Ez tök kényelmes, mert a generálási folyamatba ide-oda be lehet illeszteni dolgokat (ezt csinálják a pluginek), így igény szerint bővíthető és alakítható a rendszer. Ugyanakkor ez a folyamatos újragenerálás az oka annak, hogy a végén aztán a világ összes számítási kapacitása sem elég az oldalnak, pedig valójában az idő 99%-ban feleslegesen dolgozik a gép a PHP futtatással, és a MySQL kérések kiszolgálásával.

Azon gondolkodtam, hogy kellene készíteni egy olyan CMS rendszert, aminek kezdetektől fogva az a filozófiája, hogy statikus oldalakat generál, amiket minimális erőforrás felhasználásával kiszolgálhat a szerver, illetve akár kliens oldalon cache-elhető is, és akkor csak NotModified header-ek mászkálnak az esetek nagy részében. A dinamikus adatok meg simán js-el lennének megoldva. Tehát pl. egy notification box a bejelentkezett usernek. De ezeknek az ajax komponenseknek az adatforrása is sok esetben lehetne statikus json. Tehát pl. ennél a notification jelzőnél minden usernek fixen le lehetne generálni egy json-t, amit csak akkor kell újragenerálni, ha új üzenet jön.

Robert Cartman -el beszéltünk nemrég ilyesmiről, ebből jött az ötlet.

#blog

28 megjegyzés:

  1. Ötlet jó, és úgy tudom van is ilyen. Csak elég bonyolult. Meg persze a CMS-ek kesselnek is, sőt azt hiszem van erre külön megoldás.

    Egy statikus oldalakat generáló egyszerű kis programot én is írtam régebben (pklapgen).

    VálaszTörlés
  2. Tudomásom szerint a Drupal már operál ilyesmivel a cachelésen túl is, és egyéb optimalizálásokat is tartalmaz (pl. CSS fájlok összevonása).

    VálaszTörlés
  3. Persze, cache van, csak pl. egy ilyen notification counter agyon is vágja rögtön. Meg össze is lehetne rakni ilyesmit, itt csak annyi a lényeg, hogy eleve ez lenne az alapfilozófia.

    VálaszTörlés
  4. Mondjuk szinte minden CMS-ben van cache, amivel gyorsítja az adatbázis-lekérdezéseket. A Drupalhoz akár statikus fájl alapú cache is illeszthető. Mondjuk a kérdésfeltevő kicsit jobban is téjékozódhatna, mert a CMS nem „eszi meg a gépet”, vagy ha igen, akkor ott már tervezési hiba van. Ha teljesítménykritikus a dolog, akkor gyorstárazni úgysem ezen a szinten érdemes, hanem pl. Memcached, Redis, esetleg a kritikus adatok MongoDB-re rakása. Bár a PHP-t és a MySQL-t is lehet optimalizálni kifejezetten nagy teljesítményhez (lásd Facebook), de ha az alapbeállításokat nem piszkálják, már az is elég a legtöbb esetben. Szóval nem, nem fogja megenni a gépet a CMS alapú oldal.
    Amúgy meg nem biztos, hogy mindenhova CMS kell, szerencsére már rengeteg site generator elérhető.

    VálaszTörlés
  5. Kurucz István Arra céloztam, hogy sok esetben az emberek egy ilyen rendszerrel összerakják az oldalt, ami aztán nagy terhelés esetén sokkal több erőforrást fogyaszt, mint kellene. Tudom, hogy vannak cache megoldások, és ki lehet alakítani így egy WordPress, Drupal, stb. rendszert, de nem erre vannak kihegyezve. Ezért írtam, hogy jó ötlet lenne egy olyan rendszer, aminek kezdetektől fogva ez az alapfilozófiája, hogy statikus tartalmakat generál. Itt nem a PHP/MySQL optimalizálásáról van szó, nem is a cache-ről, vagy hogy mennyire lehet kioptimalizálni egy Drupal-t, hanem a rendszer alapfilozófiájáról.

    VálaszTörlés
  6. Laszlo Fazekas Ne haragudj, de nagyon általánosságokban beszélsz.

    „összerakják az oldalt, ami aztán nagy terhelés esetén sokkal több erőforrást fogyaszt, mint kellene”

    Nagy terhelés esetén sok rendszer sokkal több erőforrást fogyaszt, mint kellene. Ez nem feltétlenül a rendszer hibája, de a MySQL és a PHP is végtelenül finomhangolható. De ha arról van szó, akár dobható a MySQL is, mert pl. egy MongoDB sokkal gyorsabb lesz, viszont (meglepetéééééééés!) sokkal több erőforrást fogyaszt. Valamit valamiért, ugyebár.

    „Tudom, hogy vannak cache megoldások, és ki lehet alakítani így egy WordPress, Drupal, stb. rendszert, de nem erre vannak kihegyezve.”

    Mire vannak kihegyezve akkor? Számtalan nagy terhelés alatt üzemelő Drupal és Wordpress oldalt ismerek. Ez így csak egy sima általánosítás.

    „jó ötlet lenne egy olyan rendszer, aminek kezdetektől fogva ez az alapfilozófiája, hogy statikus tartalmakat generál”

    Erre írtam a site generatorokat, amelyek sok esetben megfelelőek. Kb. addig, amíg a rendszer nem fogad bemenetet, minden látógatónak ugyanazokat mutatja (pl. nincs jogosultságkezelés) és a szükséges szolgáltatásokat (pl. keresés, hozzászólások) ki lehet szervezni más szolgáltatóhoz.

    VálaszTörlés
  7. Ez így nekem azt mutatja, hogy baromira nem tudod mi van egy PHP alapú keretrendszer mögöt. A legtöbb keretrendszer legenerálja egyszer a nézetet, megjelöli azt ami változhat és csak azokat geberálja újra, ha valaki odafigyel a beállításokra, akkor azt is csak akkor ha kell. Wordpress-hez is van plugin hozzá, ahogyan Drupal is a nyolcassal megkapta a Twig-et, ami pedig ezt csinája (erősen felhasználták a symfony-t több ízben is).

    Ha felraksz egy Wordpress-t akkor lassú lesz. Gyorsan rákeresel, hogy miel lehet gyorsíteni és igen hamar rátalálsz (egyszerű felhasználóként is) olyan pluginekre, amiket 1 kattintással felraksz és utána úgy működik, hogy minden posztra csinál egy cachefájlt, amit újra se generál, csak akkor ha a PostEdit hook hívódik meg adott ID-vel. A Page-eknél ugyen ezt csinálja. Persze van még jópár eset amikor törni az adott (már kész legenerált fájlt).

    VálaszTörlés
  8. Kurucz István Azzal nem vitatkozom, hogy vannak nagy terhelés alatt jól üzemelő WP, Drupal, stb. oldalak. Azzal sem, hogy össze lehet ezeket úgy lőni, hogy ne zabáljanak sok erőforrást.

    Egyszerűen arról van szó, hogy egy WP, Drupal, stb. oldal ALAPBÓL azt csinálja, hogy minden egyes kérésnél MySQL-ből összeszedi az adatokat, PHP-val legenerálja a lapot, és visszadobja a usernek. Olyan esetben is, amikor erre semmi szükség, mert az adott oldal tartalma amúgy hosszú idő óta nem változott. Erre írtam, hogy jó lenne valami, ami ALAPBÓL arra van kitalálva, hogy ilyen statikus oldalakat generáljon. Azok a dolgok, amik pedig dinamikusak (pl. keresés, notification doboz, stb.) ajax-on jönnének le, nem kellene külön szolgáltatókhoz kiszervezni. Amikor a LAIKUS felhasználó feldob egy ilyet, akkor MINDEN KÜLÖNÖSEBB TRÜKK NÉLKÜL, minimális erőforrást felhasználva elfutna egy ilyen, nagy terhelés esetén is. Tehát egy WordPress szintű rendszer, egyszerű adminnal, ahol a pluginek, és az alap működés arra a filozófiára épül, hogy statikusan generáljuk ki, amit lehet. Ennyire gondoltam.

    VálaszTörlés
  9. Balazs Nadasdi Ok, lehet, hogy ez csak nekem újdonság. Csak akkor miért kell ehhez plugin? Egy defult WordPress miért nem ezt csinálja?

    VálaszTörlés
  10. Balazs Nadasdi Illetve tudsz valami jól bevált WP plugint erre? Ami statikusan legenerálja az oldalakat. Tom, keressek rá, csak ha van valami jól bevált.

    VálaszTörlés
  11. Laszlo Fazekas Akkor neked nem CMS-re van szükséged. Amúgy meg finomhangolás nélkül nem üzemeltetünk oldalt, pláne nagyobb terhelésre szántat.
    A fájlrendszer elérése gyakran lassabb, mint egy jól belőtt adatbázisé, szóval nem biztos, hogy olyan sokat nyersz a fájl alapú gyorstárazással.

    VálaszTörlés
  12. Kurucz István A fragmenteket lehetne db-ben is tárolni, vagy memcached-ben, stb. Ami a lényeg ebből, hogy ezek a rendszerek sok olyan dolgot csinálnak emiatt, ami felesleges. Az adatbázis kérések egy része felesleges, a futó PHP kód (plugin rendszer inicializálása minen request-re, db kapcsolat újra felépítése, stb.) felesleges. Eleve a PHP futtatásnál az értelmező elindítása, inicializálgatások minden request esetén felesleges, stb. Szóval sok olyan dolog van szerintem, amivel feleslegesen dolgozik a gép. Sok mindent ki lehet optimalizálni, de én valami olyasmin gondolkodtam, ami eleve optimális ebből a szempontból, mert más a filozófiája. Vannak ilyen statikus site generátorok, de amiket ismerek, azok elég fapadosak egy laikusnak, és nem foglalkoznak azzal, hogy bizonyos dolgokat ajax-on szedjen össze az oldal a felhasználótól függően. Tehát azok meg nem igazi CMS-ek. Az én fejemben egy ilyen sitegenerátor szerű dolog jelent meg, aminek van egy egyszerű admin felülete, illetve szolgáltat egy ajax felületet, amivel a pluginek a dinamikus adatokat szolgáltathatják. Az is lehet, hogy van ilyen. Én nem ismerek, de attól még lehet.

    VálaszTörlés
  13. Laszlo Fazekas Ne haragudj, de szerintem is érdemes lenne néhány CMS lelkivilágát alaposan, előítélettől mentesen megismerned. Amúgy meg ha már adatbázis van, akkor nem sokkal vagy előrébb. A Drupal pl. tud fragmenteket Redisben tárolni.
    Plusz nem árt teljesen végiggondolni, hogy mit is szeretnél tulajdonképpen.

    VálaszTörlés
  14. Kurucz István De ezek mind plusz feature-ök, "tud redisben fragmenteket tárolni", lehet hozzá szerezni ilyen plugint, stb. Nem ez az alap. Nem CMS rendszereket akarok fikázni, és nem azt mondom, hogy nem lehet kihozni ilyen működést bármelyikből, csak hogy nem ezt csinálják alapból, és jó ötlet lenne egy olyan, ami eleve erre a filozófiára épül.

    VálaszTörlés
  15. A más filozófia szerint alapból statikushoz meg a dinamikusságot megoldandó lennének pluginok meg egyebek.

    VálaszTörlés
  16. én messzebbre mennék. A szerver oldali html generálást el kell felejteni. Ha én most kezdenék új cms fejlesztésébe, akkor előrelátóbb lennék attól, hogy szerver oldalon végezzem a kulimunkát. Az más kérdés, hogy  a call-okat így is kell cachelni, de az már egy másik tészta.

    VálaszTörlés
  17. Persze, lehet azt, hogy egy js az egész oldal, és ajax-on szed le mindent. AngularJS-el ilyet jól össze lehet rakni, meg így csináltuk meg mi is elmu.hu-t. De itt akkor mondjuk a REST hívások cache-elésére tolódik tovább a dolog (amit te is írtál). De ilyen CMS-t sem nagyon ismerek.

    Azt érti itt félre amúgy szerintem mindenki, hogy nem az a gond a meglévő megoldásokkal, hogy nem lehet bennük cache-elni, hanem hogy nem eleve arra vannak kitalálva, hanem ehhez pluginek kellenek, meg külön konfigurálgatás. Egy ilyen angular-os oldalt is meg lehetne hajtani WordPress-el, meg Drupal-al, meg akármivel, de ilyen alap Angular-os, cache-re kihegyezett CMS-t nem ismerek.

    VálaszTörlés
  18. Lehet csak látszólagos az előnye, aztán kisakkozva kijön, hogy nem érdemes vele szöszölni, mert a meglévő megközelítések pluginszükséglettel együtt kellően optimálisak, skálázhatók és bővíthetőek a felmerülő igényekre.

    VálaszTörlés
  19. Lehet. :) Igazából azon nem gondolkodtam, hogy meg is csinálom, csak ötletfelvetés volt ...

    VálaszTörlés
  20. Előre szólok, hogy én nem értek hozzá, csak ha már meg lettem említve fentebb, akkor belekotyogok :)
    Igazából minden megvan a Wordpress-hez, csak meg kell találni, meg meg kell tanulni használni. Pl: nálunk az az egyik probléma, hogy nem tudunk full-page cache-t használni a belépett felhasználóknak, mert van egy csomó dinamikus, izgő-mozgó kontent (új üzenet értesítő, új kommentek, fórumbejegyzések, lájkok, stb) és a legtöbb cache plugin ezekre nincs felkészítve. 
    Persze meg lehet oldani ezeket, ajax-al, meg Transients API-el, de ez messze nem az, amit bárki meg tud csinálni. Pl.: én ehhez kicsi vagyok és buta.
    Szerintem arra gondolt Laszlo Fazekas , hogy egy olyan CMS-t kellene csinálni, ami leegyszerűsítené az ilyen feladatokat is.

    VálaszTörlés
  21. Yepp. Robert Cartman Jól összefoglalta, mi a bejegyzés lényege. Amit írtam, abból lehet nem jött le rendesen, de ez volna a lényeg.

    VálaszTörlés
  22. Van ahol nem éri meg, van ahol nincs rá szükség. Egyszerűbb valamit belerakni, mint letiltogatni és megírni a kivéteket, amikor le akarjuk tiltani. Full page cache pedig nagyon, de nagyon ritka esetben használható. Mikor sajat template rendszert írtam, ott az volt a lényeg eleve a renszerben, hogy amit lehet ne generáljon. Végül kismillió függvény kezelte le, hogy a dokumentumot szétszabdalja és csak részegységeit futtassa le és ezt a fejlesztőre bíztam (volt pár eset amikor ő maga állította elő ezt). A Twig cache rendszere nagyon jól meg van csinálva, de még az is messze áll attól a mély generált kiszolgálástól, amit én próbáltam annó megcsinálni. nagyjából azt is lehet mondani, hogy én megpróbálkoztam pár éve (2011) azzal, amit Laszlo Fazekas leírt, de nem működik, adott rendszerhez jó volt, aztán adott rendszeren módosítani kellett és volt ahol elhasalt. Végül nagyon kusza kód lett mögötte és még így is nagyon sok dolog valós időben lett generálva, mert egyszerűen nem lehetett máshogyan. Le lehet egyszerűsíteni, hogy általános esetben működjön, de sajnos az meg lofaszt nem érne úgy általában sem.

    Persze lehet generált oldalt készíteni Jekyll, Octopress és ezek utódai. Lehet ezt a logikát követni, de akkor sok olyan ponttól elesel, ami amúgy meg kellhet, ilyen például a bejelentkezett felhasználó, amennyiben a kommenteléshez login kell. Neki mit generálsz be a "profilboxába"? Minden felasználónak külön generált html fájlt adsz? Ez úgy azért ütős :D Ha admin látogatja a weboldalt, akkor eleve már nem is használod ezt a funkciót. XHR kérésekkel kellene megoldani? No hát azzal se sokra mész, főleg, ha olyan tartalom is van, ami a kereső számára is fontos információ, mert azt ő nem látja (legfrissebb bejegyzés, random bejegyzés, utoljára megtekintett bejegyzés, utolsó komment, napszak specifikus banner). Amennyiben az oldal kis látogatottságú, akkor baromira mindegy, hogy generálod-e vagy sem, ha meg sokan nézik, akkor gyakran változnak a zárójelben említett dolgok, lévén sokan mozognak az oldalon.

    Megoldható, de nem éri meg... Vagy általánosan nem megoldható, hogy ne legyen több szopás, akkor ha mégse kell vagy nem úgy kell. Egyszerűbb bekapcsolni / pluginként bepakolni, mint utólag kiszedni belőle.

    VálaszTörlés
  23. Lehet, még nem próbáltam ilyet csinálni, csak a gondolat merült fel. Ami google-nek kell, bejegyzés lista, ilyesmi, azt bele lehetne generálni, ha valami változik, újra kell generálni az oldalt, de akkor sem minden requestre. A felhasználó függő adatok, meg az olyan nagyon dinamikus dolgok, mint a banner, meg xhr-en lenne megoldva. Most hirtelen nem jut eszembe olyan dolog, ami értelmetlenné tenné ezt. Tehát ha mondjuk olyat akarsz, hogy utolsó 10 comment legyen kint az oldalon, és jön másodpercenként 1 comment, viszont van másodpercenként 10 látogatód, akkor is 9x a statikus tartalom megy le, és nem kell piszkálni a MySQL-t, meg a PHP is kevesebbet fut. Szóval így sem tűnik hülyeségnek a dolog. Lehet, konkrét esetben kiderülne, hogy nem működik, de így végiggondolva, még az általad írtak után sem tűnik értelmetlennek.

    VálaszTörlés
  24. Laszlo Fazekas Ezekre való a Memcache, a redis (én utóbbit pártolom). Nem várhatja el sem a Wordpress, sem semmi más általános CMS, hogy az adatbázis mellett neked még legyen cache service-d is. Sőt, erősen megcsappanna a felhasználói kör a "jó, de hogyan állítsam be?" kérdések miatt. Így is sokaknak gondot okoz az adatbázis.

    A Wordpress.com meg a háttérben igen sokan cache-el neked.

    Egyszerűen nem éri meg. XHR esetén meg a témagyártókkal basznál ki és az lenne kevesebb. Mi van ha nincs JS támogatás, összeomlik valamiért a JS? Mi van akkor ha mondjuk az egyik dependency JS nem töltődik be a kliens szar netje miatt? Mi van ha simán csak egy plugin lehagyott egy pontosveszőt és a concat után nem tudja feldolgozni a JS file-t? Akkor az XHR specifikus részek be se tudnak töltődni.

    Még mindig azt mondom, hogy megoldható, de sokkal egyszerűbb valamit pluginként betölteni, ha kell, mint kivenni belőle.

    VálaszTörlés
  25. Még kicsit gondolkodtam rajta. :) A template-eket most is úgy kell csinálni, hogy legyenek benne "lukak", ahová a hook-okon keresztül be lehet kötni a tartalmat. Ez itt is ugyanúgy nézne ki. Magát a tartalom ajaxos behúzását pedig nem a plugin fejlesztőjének kellene lefejelsztenie, hanem lenne rá egy általános rendszer. Annyi lenne a változás, hogy a hook-nál be kellene állítani, hogy a statikus lapgenerálásnál fusson le, vagy az ajaxosnál. A statikus lapgenerálásosnál még fel kellene iratkozni eseményekre, amik invalidálják azokat az oldalakat, aminek a generálásánál használatban van a hook. Így az ajax-os hook-ok minden request-re lefutnának, a statikus laposak pedig csak akkor, ha újra kell generálni a lapot. Ennyi lenne a bonyolítás. Így akkor nem kellene a plugin fejlesztőjének js-el bajlódnia, és nincs az a veszély, hogy egy rossz plugin tönkre vágja a rendszert. Az, hogy nincs js, már most is sok oldalt agyonvágna. De lehet, hogy konkrét esetben szívás lenne, nem tudom ... :)

    VálaszTörlés
  26. De ezt már megoldottad/megoldottuk, Laca :-)

    VálaszTörlés
  27. Most ilyen PHP/MySQL WP oldalról próbáltam megközelíteni a dolgot. Valamit, amit csak úgy feldobsz valahová. De amúgy ja. Tulképpen a MadeMove/nBoss páros ilyen, ha beleszámolom a memcached/etag támogatást. ;)

    VálaszTörlés