Architektúra riadená udalosťami zvyšuje nákladovú efektívnosť použitých zdrojov, pretože sa využívajú len v momente, keď sú potrebné. Existuje veľa možností, ako to implementovať a nevytvárať ďalšie cloudové entity ako pracovné aplikácie. A dnes nebudem hovoriť o FaaS, ale o webhookoch. Ukážem výukový príklad spracovania udalostí pomocou webhookov na ukladanie objektov.
Pár slov o ukladaní objektov a webhookoch. Objektové úložisko umožňuje ukladať akékoľvek dáta v cloude vo forme objektov, prístupných cez S3 alebo iné API (v závislosti od implementácie) cez HTTP/HTTPS. Webhooky sú vo všeobecnosti vlastné spätné volania HTTP. Zvyčajne sú spúšťané udalosťou, ako je vloženie kódu do úložiska alebo uverejnenie komentára na blogu. Keď nastane udalosť, pôvodná lokalita odošle požiadavku HTTP na adresu URL zadanú pre webhook. Výsledkom je, že udalosti na jednej stránke spúšťajú akcie na inej (wiki). V prípade, že zdrojovou stránkou je úložisko objektov, udalosti pôsobia ako zmeny v jej obsahu.
Príklady jednoduchých prípadov, kedy je možné použiť takúto automatizáciu:
Vytváranie kópií všetkých objektov v inom cloudovom úložisku. Kópie sa musia vytvárať za chodu pri každom pridávaní alebo zmene súborov.
Automatické vytváranie série miniatúr grafických súborov, pridávanie vodoznakov do fotografií a ďalšie úpravy obrázkov.
Notifikácia o príchode nových dokumentov (napríklad distribuovaná účtovná služba nahráva zostavy do cloudu a finančný monitoring dostáva notifikácie o nových zostavách, kontroluje ich a analyzuje).
O niečo zložitejšie prípady zahŕňajú napríklad vygenerovanie požiadavky pre Kubernetes, ktorý vytvorí pod s potrebnými kontajnermi, odovzdá mu parametre úlohy a po spracovaní kontajner zbalí.
Ako príklad urobíme variant úlohy 1, keď sa zmeny v sektore úložiska objektov Mail.ru Cloud Solutions (MCS) synchronizujú v objektovom úložisku AWS pomocou webhookov. V skutočne zaťaženom prípade by mala byť asynchrónna práca zabezpečená registráciou webhookov vo fronte, ale pre tréningovú úlohu vykonáme implementáciu bez toho.
Vydavateľská služba, ktorý je na strane úložiska S3 a publikuje požiadavky HTTP pri spustení webnhooku.
Prijímací server webhooku, ktorá počúva požiadavky od publikačnej služby HTTP a vykonáva príslušné akcie. Server môže byť napísaný v akomkoľvek jazyku, v našom príklade napíšeme server v Go.
Zvláštnosťou implementácie webhookov v S3 API je registrácia prijímacieho servera webhookov na publikačnej službe. Prijímací server webhooku musí predovšetkým potvrdiť odber správ zo služby publikovania (v iných implementáciách webhooku sa potvrdenie odberu zvyčajne nevyžaduje).
V súlade s tým musí prijímací server webhooku podporovať dve hlavné operácie:
odpovedať na žiadosť vydavateľskej služby o potvrdenie registrácie,
spracovávať prichádzajúce udalosti.
Inštalácia prijímacieho servera webhooku
Na spustenie prijímacieho servera webhooku potrebujete server Linux. V tomto článku ako príklad používame virtuálnu inštanciu, ktorú nasadíme na MCS.
Nainštalujeme potrebný softvér a spustíme prijímací server webhooku.
ubuntu@ubuntu-basic-1-2-10gb:~$ sudo apt-get install git
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following packages were automatically installed and are no longer required:
bc dns-root-data dnsmasq-base ebtables landscape-common liblxc-common
liblxc1 libuv1 lxcfs lxd lxd-client python3-attr python3-automat
python3-click python3-constantly python3-hyperlink
python3-incremental python3-pam python3-pyasn1-modules
python3-service-identity python3-twisted python3-twisted-bin
python3-zope.interface uidmap xdelta3
Use 'sudo apt autoremove' to remove them.
Suggested packages:
git-daemon-run | git-daemon-sysvinit git-doc git-el git-email git-gui
gitk gitweb git-cvs git-mediawiki git-svn
The following NEW packages will be installed:
git
0 upgraded, 1 newly installed, 0 to remove and 46 not upgraded.
Need to get 3915 kB of archives.
After this operation, 32.3 MB of additional disk space will be used.
Get:1 http://MS1.clouds.archive.ubuntu.com/ubuntu bionic-updates/main
amd64 git amd64 1:2.17.1-1ubuntu0.7 [3915 kB]
Fetched 3915 kB in 1s (5639 kB/s)
Selecting previously unselected package git.
(Reading database ... 53932 files and directories currently installed.)
Preparing to unpack .../git_1%3a2.17.1-1ubuntu0.7_amd64.deb ...
Unpacking git (1:2.17.1-1ubuntu0.7) ...
Setting up git (1:2.17.1-1ubuntu0.7) ...
Naklonujte priečinok s prijímacím serverom webhooku:
Prejdite do segmentu, pre ktorý budeme konfigurovať webhooky, a kliknite na ozubené koliesko:
Prejdite na kartu Webhooky a kliknite na Pridať:
Vyplňte polia:
ID — názov webhooku.
Udalosť – ktoré udalosti sa majú prenášať. Nastavili sme prenos všetkých udalostí, ktoré sa vyskytujú pri práci so súbormi (pridávanie a mazanie).
URL — adresa prijímacieho servera webhooku.
Predpona/prípona filtra je filter, ktorý vám umožňuje generovať webhooky iba pre objekty, ktorých názvy zodpovedajú určitým pravidlám. Napríklad, aby webhook spúšťal iba súbory s príponou .png, in Prípona filtra musíte napísať „png“.
V súčasnosti sú na prístup k prijímaciemu serveru webhooku podporované iba porty 80 a 443.
Poďme kliknúť Pridajte háčik a uvidíme nasledovné:
dodal Hook.
Prijímací server webhooku zobrazuje vo svojich denníkoch priebeh procesu registrácie háku:
Funkcie HmacSha256 a HmacSha256hex sú implementáciami šifrovacích algoritmov HMAC-SHA256 a HMAC-SHA256 s výstupom ako reťazec hexadecimálnych čísel na výpočet podpisu.
main je hlavná funkcia, spracováva parametre príkazového riadku a registruje obsluhu URL.
-script je externý program, ktorý sa volá pre každý prichádzajúci hák.
Pozrime sa bližšie na niektoré funkcie:
//Webhook
func Webhook(w http.ResponseWriter, req *http.Request) {
// Read body
body, err := ioutil.ReadAll(req.Body)
defer req.Body.Close()
if err != nil {
http.Error(w, err.Error(), 500)
return
}
// log request
log.Printf("[%s] incoming HTTP request from %sn", req.Method, req.RemoteAddr)
// check if we got subscription confirmation request
if strings.Contains(string(body),
""Type":"SubscriptionConfirmation"") {
SubscriptionConfirmation(w, req, body)
} else {
GotRecords(w, req, body)
}
}
Táto funkcia určuje, či prišla požiadavka na potvrdenie registrácie alebo webhooku. Ako vyplýva z dokumentáciu, ak je registrácia potvrdená, v žiadosti o príspevok sa dostane nasledujúca štruktúra Json:
POST http://test.com HTTP/1.1
x-amz-sns-messages-type: SubscriptionConfirmation
content-type: application/json
{
"Timestamp":"2019-12-26T19:29:12+03:00",
"Type":"SubscriptionConfirmation",
"Message":"You have chosen to subscribe to the topic $topic. To confirm the subscription you need to response with calculated signature",
"TopicArn":"mcs2883541269|bucketA|s3:ObjectCreated:Put",
"SignatureVersion":1,
"Token":«RPE5UuG94rGgBH6kHXN9FUPugFxj1hs2aUQc99btJp3E49tA»
}
Preto v závislosti od požiadavky musíte pochopiť, ako spracovať údaje. Ako indikátor som zvolil vstup "Type":"SubscriptionConfirmation", pretože sa nachádza v žiadosti o potvrdenie predplatného a nenachádza sa vo webhooku. Na základe prítomnosti/neprítomnosti tohto záznamu v požiadavke POST prejde ďalšie vykonávanie programu buď do funkcie SubscriptionConfirmationalebo do funkcie GotRecords.
Funkciou SubscriptionConfirmation sa nebudeme podrobne zaoberať, je implementovaná podľa zásad uvedených v dokumentáciu. Zdrojový kód tejto funkcie si môžete pozrieť na projektové git repozitáre.
Funkcia GotRecords analyzuje prichádzajúcu požiadavku a pre každý objekt Record volá externý skript (ktorého názov bol odovzdaný v parametri -script) s parametrami:
názov vedra
objektový kľúč
akcia:
copy - ak je v pôvodnej požiadavke EventName = ObjectCreated | PutObject | PutObjectCopy
delete - ak je v pôvodnej požiadavke EventName = ObjectRemoved | OdstrániťObjekt
Ak teda príde hák s požiadavkou Post, ako je opísané nada parametrom -script=script.sh sa skript bude volať takto:
script.sh bucketA some-file-to-bucket copy
Malo by byť zrejmé, že tento prijímací server webhooku nie je kompletným produkčným riešením, ale zjednodušeným príkladom možnej implementácie.
Príklad práce
Poďme synchronizovať súbory z hlavného vedra v MCS do záložného vedra v AWS. Hlavný bucket sa nazýva myfiles-ash, záložný sa nazýva myfiles-backup (konfigurácia bucketu v AWS je nad rámec tohto článku). Podľa toho, keď je súbor umiestnený v hlavnom segmente, jeho kópia by sa mala objaviť v záložnom, a keď je vymazaný z hlavného, mal by byť vymazaný v záložnom.
S vedrami budeme pracovať pomocou pomôcky awscli, ktorá je kompatibilná s cloudovým úložiskom MCS aj cloudovým úložiskom AWS.
ubuntu@ubuntu-basic-1-2-10gb:~$ sudo apt-get install awscli
Reading package lists... Done
Building dependency tree
Reading state information... Done
After this operation, 34.4 MB of additional disk space will be used.
Unpacking awscli (1.14.44-1ubuntu1) ...
Setting up awscli (1.14.44-1ubuntu1) ...
Poďme nakonfigurovať prístup k S3 MCS API:
ubuntu@ubuntu-basic-1-2-10gb:~$ aws configure --profile mcs
AWS Access Key ID [None]: hdywEPtuuJTExxxxxxxxxxxxxx
AWS Secret Access Key [None]: hDz3SgxKwXoxxxxxxxxxxxxxxxxxx
Default region name [None]:
Default output format [None]:
Poďme nakonfigurovať prístup k AWS S3 API:
ubuntu@ubuntu-basic-1-2-10gb:~$ aws configure --profile aws
AWS Access Key ID [None]: AKIAJXXXXXXXXXXXX
AWS Secret Access Key [None]: dfuerphOLQwu0CreP5Z8l5fuXXXXXXXXXXXXXXXX
Default region name [None]:
Default output format [None]:
Pozrime sa na prístupy:
Do AWS:
ubuntu@ubuntu-basic-1-2-10gb:~$ aws s3 ls --profile aws
2020-07-06 08:44:11 myfiles-backup
V prípade MCS musíte pri spustení príkazu pridať —endpoint-url:
Pozrime sa, ako to funguje. Cez webové rozhranie MCS pridajte súbor test.txt do vedra myfiles-ash. Protokoly konzoly ukazujú, že na server webhook bola odoslaná požiadavka:
2020/07/06 09:43:08 [POST] incoming HTTP request from
95.163.216.92:56612
download: s3://myfiles-ash/test.txt to ../../../tmp/myfiles-ash/test.txt
upload: ../../../tmp/myfiles-ash/test.txt to
s3://myfiles-backup/test.txt
Pozrime sa na obsah zásobníka myfiles-backup v AWS:
Teraz cez webové rozhranie vymažeme súbor z vedra myfiles-ash.
Denníky servera:
2020/07/06 09:44:46 [POST] incoming HTTP request from
95.163.216.92:58224
delete: s3://myfiles-backup/test.txt
Obsah vedra:
ubuntu@ubuntu-basic-1-2-10gb:~/s3-webhook$ aws s3 --profile aws ls
myfiles-backup
ubuntu@ubuntu-basic-1-2-10gb:~$
Súbor je odstránený, problém je vyriešený.
Záver a ToDo
Všetok kód použitý v tomto článku je v mojom úložisku. Nechýbajú ani príklady skriptov a príklady počítania podpisov na registráciu webhookov.
Tento kód nie je nič iné ako príklad toho, ako môžete použiť webhooky S3 vo svojich aktivitách. Ako som povedal na začiatku, ak plánujete používať takýto server vo výrobe, musíte server aspoň prepísať na asynchrónnu prácu: zaregistrovať prichádzajúce webhooky do fronty (RabbitMQ alebo NATS) a odtiaľ ich analyzovať a spracovať s pracovnými aplikáciami. V opačnom prípade, keď webhooky prichádzajú masívne, môžete sa stretnúť s nedostatkom serverových zdrojov na dokončenie úloh. Prítomnosť frontov vám umožňuje distribuovať server a pracovníkov, ako aj riešiť problémy s opakujúcimi sa úlohami v prípade zlyhania. Taktiež je vhodné zmeniť protokolovanie na podrobnejšie a štandardizovanejšie.