Lambda belső rész - 2. rész: Mélyebb

Az AWS Lambda futásidejű könyvtárak feltárása

Fotó: Jim Beaudoin

Szerver nélküli fejlesztés egyszerűen a legjobb. Kattintson duplán, töltse fel a kódját, és kész! A legtöbb ember örömmel hagyja el ezt. Ha Ön nem a legtöbb ember, és néhány Lambda-felfedezésre vár, ez a cikk csak neked szól.

Az előző cikkben kapunk egy héjat a Lambda tárolóhoz, letöltöttük a Lambda futási környezetet és felfedeztük annak összetevőit:

  • bootstrap.py - a python-kód, amely a kezünkbe csomagolja.
  • awslambda / runtime.so - egy python-kompatibilis megosztott objektum, a bootstrap.py nagyon jól mindent felhasznál.
  • liblambda * .so - A runtime.so viszont más megosztott objektumokat is használ. A liblambdaruntime.so-ra összpontosítunk, amely a nehéz emelésért felelős a Lambda logika irányításában.

Szórakozottan szórakoztunk a bootstrap.py webhelyen. Ezúttal felcsavarjuk a hüvelyünket és belemerülünk a Lambda futásidejű környezetének bináris könyvtáraiban. Megvizsgáljuk a Lambda számlázási rendszerét, és (spoileri figyelmeztetés) szórakozhatunk a Lambda időkorlátozásaival.

„Ó, azok a helyek, ahol mész! Jó szórakozást lehet tenni! Vannak pontok, amelyeket pontozni kell. Vannak játékok, amelyeket meg kell nyerni. ”- Dr. Seuss. Fotó: Joshua Earle

A könyvtárak feltárása

A könyvtárak (liblambda * .so) szimbólumokkal vannak összeállítva, így sokat tanulhat a könyvtárakról a szimbólumok nevének átlépésével. A runtime.so emellett sok ilyen funkciót lefedi, importálva és csomagolva őket, így a Python szkript (a mi esetünkben a bootstrap.py) felhasználhatja ezek közül néhányat. Milyen kényelmes!

Részleges funkciók listája a liblambdaruntime.so szétszerelésből. Köszönöm Istennek a szimbólumokat.

Az egyik dolog, amelyet eredetileg igazán szerettem volna megnézni, a Lambda számlázási rendszerének mögötti színfalak mögött állt, és csak a függvénynevekre nézve volt néhány kísérlet, amelyet meg akartam kipróbálni. De először - beszéljünk egy kicsit a Lambda számlázásáról.

Lambda számlázás

A Lambda-nak van egy időalapú árazási modellje, és anélkül, hogy minden részletbe belemenne, lényege minél hosszabb időt vesz igénybe a Lambda futtatása, annál többet fizet. Lambda meghívásakor könnyedén megfigyelheti annak kezdetét és végét a CloudWatch naplókban, valamint annak időtartamát és a számlázási időtartamot.

A CloudWatch naplózza a Lambdat. Megnézheti mind a Lambda időtartamát, mind a számlázott időtartamot

Van azonban egy bonyolultabb forgatókönyv. Vegyük figyelembe a következő lambdat:

Egy tipikus futtatásnál ennek a Lambda-nak az időtartamának rövidnek kell lennie (a számlázási időtartam szinte mindig 100 ms). De mi történik az első meghívással? Vagy hidegindításkor (amikor a modult újra importálják)?

A Lambda naplózza, amikor hidegindulás történt. Az időtartam sokkal magasabb, mint egy rendszeres meghívásnál

Az empirikus tesztek azt mutatják, hogy az első Lambda hívás (vagy hidegindítás) időtartama tartalmazza az inicializálás időtartamát. De szerettem volna megnézni, hogy a Lambda hogyan valósítja meg ezt.

A könyvtárak importálása

A bootstrap.py fájlban a következő függvények hívása történik, amelyeket bináris könyvtárakból importáltak:

  • lambda_runtime.recept_start () vagy lambda_runtime.recept_invoke () - új indító érkezésekor.
  • lambda_runtime.report_done () - Lambda készítésekor

Lehet, hogy itt az ideje, hogy részletesebben ismertessük a szeletelőt, amelyre az előző cikkben hivatkoztam. A szeletelő az a komponens a Lambda-ban, amely felelős a futási idő kiosztásáról a tárolóban futó különböző felhasználói Lambdas-ok számára. Ezek a funkciók értesítést küldenek a szeletelőnek (és más Lambda felügyeleti összetevőknek), amikor a Lambda végrehajtása megtörtént, vagy információkat kapnak az újonnan kezdeményezett végrehajtásokról.

Tehát miután azonosítottuk a lambda_runtime hívásait, és tudtuk, mi a szeletelő, volt valami, amit csak meg kellett kipróbálnom: magam importáltam a futásidejű könyvtárat és szórakoztam vele! (ezekkel a kísérletekkel tudtam megtudni a szeletelő darabokat, leginkább a szétszerelés és néhány kísérlet és hiba elolvasásával). A teszt, amelyet meg akarok osztani veled, szintén az első, amit megpróbáltam: a lambda_runtime.report_done () hívása a Lambda-ból. Ezt a kódot használtam:

Meglepő módon azt tapasztaltam, hogy a példa futtatásakor a kódom leállt, miután csak a „Beginning” -t nyomtattam. Aztán, amikor újra beindítottam a Lambda-t, akkor pontosan ott folytatta végrehajtását, ahonnan abbahagytuk - és kinyomtatta az „Először kész” -t! (Hozzáadtam az alvást, mert néha Lambda-nak sikerült húznia egy „nyomtatást”, mielőtt a szeletelő szüneteltette). Ez újra és újra megtörtént, amíg a Lambda kivégzése véget nem ér.

Cloudwatch naplók a Lambda végrehajtásához. Figyelem: több kérési azonosítónk van ugyanahhoz a Lambda-hoz!

Ez tehát számomra egyértelművé tette - a szeletelő mindaddig számláz nekünk, amíg a Lambda-nak CPU-ideje van. Ez azt jelenti, hogy a számlázási időtartamunk két részből áll:

  1. A modul inicializálási ideje (csak első hívás / hidegindítás esetén)
  2. A tényleges funkció időtartama

A lambda időtúllépések elkerülése

Amellett, hogy ez a felfedezés nagyon jó, ennek a felfedezésnek van egy gyakorlati (jól… praktikus is a néző szemében, de határozottan érdekes) felhasználása: a Lambda időtúllépéseinek kezelése! Vegyük figyelembe a következő lambdat:

Egyszer elindítottam a Lambdat, és megállt a 13. vonalon. Aztán vártam egy kis időt, és újraindítottam. Ennek eredményeként a kontextusobjektum metódusának visszatérési ideje 0 volt, de a Lambda nem járt le! A Lambda időtúllépését visszaállítottuk, mivel ez egy másik meghívás, és most megdupláztuk a Lambda időkorlátját (és természetesen az AWS számlánkat)! Hasznos eset lehet például egy hurok, amely sok rekordot feldolgoz, és időnként lejár. Most ellenőrizhetjük, hogy közeledik-e az időtúllépés, és ha igen, akkor hívjuk a lambda_runtime.report_done () -ot, és várhatjuk meg, amíg a következő eseményindító felveszi a végrehajtást pont ott, ahol szüneteltettem!

A Cloudwatch napló a Lambda hívásból. Hátralévő idő: 0

Egy másik dolog, ami számomra felmerült a kérdés kidolgozása során, az, hogy az AWS valódi szolgáltatást nyújthat ennek a viselkedésnek a alapján, ahol a felhasználó felfüggesztheti Lambda-ját, és folytathatja ugyanazon a helyről a következő meghívásakor. Ez hasznos lehet nem csak jelentős mennyiségű adat feldolgozása és a közepén lévő időtúllépések kezelése érdekében. Egy másik felhasználási eset lehet például a Lambda felfüggesztése, amíg drága IO / más feladat eredményére vár, ahelyett, hogy a Lambda készenléti idejét fizeti! Meg fogják csinálni? Nem tudom. Ez rendkívül jó? Defo.

Ennek mindazonáltal hátránya van. Mivel ez egy szélsőséges módszer, a Lambda következő két meghívása Amazon belső hibával kudarcot vall. Biztos vagyok benne, hogy ezt a kérdést is kis erőfeszítésekkel meg tudjuk oldani, de ez egyelőre elég jó volt számomra.

Következtetés

Sokat tanultunk az AWS Lambda belső oldaláról. Megvizsgáltuk a futásidejű környezetben lévő bináris könyvtárakat és a Lambda számlázási rendszert. Azt is behoztuk a Lambda futásidejű könyvtárat, és felhasználtuk az időtúllépések kezelésére! Ennek ellenére még mindig sok felfedezésre vár az AWS és más gyártók esetében is. Várakozással tekintve a következő kihívásokra, ha bármilyen kérése van - tudassa velem!

Frissítettem a nyílt forráskódú könyvtárat is, amely tartalmazza az általam elvégzett különféle kísérleteket, remélem hasznosnak találja!

Itt, Epsagonban, kiszolgáló nélküli alkalmazásokhoz testreszabott megfigyelő eszközt fejlesztünk ki. Szerver nélküli és szeretne többet hallani? Látogasd meg weboldalunkat!