Architektura řízená událostmi zvyšuje nákladovou efektivitu používaných zdrojů, protože jsou využívány pouze v okamžiku, kdy jsou potřeba. Existuje mnoho možností, jak to implementovat a nevytvářet další cloudové entity jako pracovní aplikace. A dnes nebudu mluvit o FaaS, ale o webhoocích. Ukážu výukový příklad zpracování událostí pomocí webhooků pro ukládání objektů.
Pár slov o ukládání objektů a webhoocích. Objektové úložiště umožňuje ukládat jakákoli data v cloudu ve formě objektů, přístupných přes S3 nebo jiné API (v závislosti na implementaci) přes HTTP/HTTPS. Webhooky jsou obecně vlastní zpětná volání HTTP. Obvykle jsou spouštěny událostí, jako je odeslání kódu do úložiště nebo zveřejnění komentáře na blogu. Když dojde k události, původní web odešle požadavek HTTP na adresu URL zadanou pro webhook. V důsledku toho můžete události na jednom webu spouštět akce na jiném (wiki). V případě, že je zdrojovým webem úložiště objektů, události fungují jako změny jeho obsahu.
Příklady jednoduchých případů, kdy lze takovou automatizaci použít:
Vytváření kopií všech objektů v jiném cloudovém úložišti. Kopie musí být vytvářeny za chodu při každém přidání nebo změně souborů.
Automatické vytváření série náhledů grafických souborů, přidávání vodoznaků k fotografiím a další úpravy obrázků.
Upozornění na příchod nových dokumentů (například distribuovaná účetní služba nahraje sestavy do cloudu a finanční monitoring přijímá upozornění na nové sestavy, kontroluje je a analyzuje).
O něco složitější případy zahrnují například vygenerování požadavku na Kubernetes, který vytvoří pod s potřebnými kontejnery, předá mu parametry úkolu a po zpracování kontejner sbalí.
Jako příklad uděláme variantu úlohy 1, kdy se změny v bucketu úložiště objektů Mail.ru Cloud Solutions (MCS) synchronizují v úložišti objektů AWS pomocí webhooků. Ve skutečně nabitém případě by asynchronní práce měla být zajištěna registrací webhooků ve frontě, ale pro tréninkový úkol provedeme implementaci bez tohoto.
Pracovní schéma
Interakční protokol je podrobně popsán v Průvodce webhooky S3 na MCS. Pracovní schéma obsahuje následující prvky:
Vydavatelská služba, který je na straně úložiště S3 a publikuje požadavky HTTP, když je spuštěn webnhook.
Webhookový přijímací server, která naslouchá požadavkům od služby publikování HTTP a provádí příslušné akce. Server může být napsán v libovolném jazyce, v našem příkladu napíšeme server v Go.
Zvláštností implementace webhooků v S3 API je registrace přijímajícího serveru webhooku na publikační službě. Přijímající server webhooku musí zejména potvrdit přihlášení k odběru zpráv ze služby publikování (v jiných implementacích webhooku se potvrzení předplatného obvykle nevyžaduje).
V souladu s tím musí přijímací server webhooku podporovat dvě hlavní operace:
reagovat na žádost vydavatelské služby o potvrzení registrace,
zpracovávat příchozí události.
Instalace přijímacího serveru webhooku
Ke spuštění přijímacího serveru webhooku potřebujete server Linux. V tomto článku jako příklad používáme virtuální instanci, kterou nasazujeme na MCS.
Nainstalujme potřebný software a spusťte přijí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 složku s přijímajícím serverem webhooku:
Přejděte do kbelíku, pro který budeme konfigurovat webhooky, a klikněte na ozubené kolo:
Přejděte na kartu Webhooky a klikněte na Přidat:
Vyplňte pole:
ID — název webhooku.
Událost – které události přenést. Nastavili jsme přenos všech událostí, ke kterým dochází při práci se soubory (přidávání a mazání).
URL — adresa přijímajícího serveru webhooku.
Prefix/suffix filtru je filtr, který umožňuje generovat webhooky pouze pro objekty, jejichž názvy odpovídají určitým pravidlům. Například, aby webhook spouštěl pouze soubory s příponou .png, in Přípona filtru musíte napsat „png“.
V současné době jsou pro přístup k přijímacímu serveru webhooku podporovány pouze porty 80 a 443.
Pojďme kliknout Přidejte háček a uvidíme následující:
dodal Hook.
Přijímající server webhooku zobrazuje ve svých protokolech průběh procesu registrace háku:
Ping() – cesta, která odpovídá přes URL/ping, nejjednodušší implementace sondy živosti.
Webhook() – hlavní trasa, obslužný program URL/webhooku:
potvrdí registraci na vydavatelské službě (přejděte na funkci SubscriptionConfirmation),
zpracovává příchozí webhooky (funkce Gorecords).
Funkce HmacSha256 a HmacSha256hex jsou implementacemi šifrovacích algoritmů HMAC-SHA256 a HMAC-SHA256 s výstupem jako řetězec hexadecimálních čísel pro výpočet podpisu.
main je hlavní funkce, zpracovává parametry příkazového řádku a registruje obsluhu URL.
Parametry příkazového řádku akceptované serverem:
-port je port, na kterém bude server naslouchat.
-address - IP adresa, kterou bude server poslouchat.
-script je externí program, který je volán pro každý příchozí háček.
Podívejme se blíže na některé funkce:
//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)
}
}
Tato funkce určuje, zda přišel požadavek na potvrzení registrace nebo webhook. Jak vyplývá z dokumentace, pokud je registrace potvrzena, v žádosti o příspěvek je přijata následující struktura 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»
}
Podle toho musíte v závislosti na požadavku pochopit, jak data zpracovávat. Jako indikátor jsem zvolil vstup "Type":"SubscriptionConfirmation", protože je přítomen v žádosti o potvrzení předplatného a není přítomen ve webhooku. Na základě přítomnosti/nepřítomnosti tohoto záznamu v požadavku POST přejde další provádění programu buď do funkce SubscriptionConfirmation, nebo do funkce GotRecords.
Funkci SubscriptionConfirmation nebudeme podrobně zvažovat, je implementována podle zásad uvedených v dokumentace. Zdrojový kód této funkce si můžete prohlédnout na projektové git repozitáře.
Funkce GotRecords analyzuje příchozí požadavek a pro každý objekt Record zavolá externí skript (jehož jméno bylo předáno v parametru -script) s parametry:
název kbelíku
objektový klíč
akce:
kopie - pokud je v původním požadavku EventName = ObjectCreated | PutObject | PutObjectCopy
delete - pokud v původním požadavku EventName = ObjectRemoved | SmazatObjekt
Pokud tedy přijde hák s požadavkem Post, jak je popsáno nada parametr -script=script.sh, pak bude skript volán následovně:
script.sh bucketA some-file-to-bucket copy
Mělo by být zřejmé, že tento webhookový přijímací server není kompletním produkčním řešením, ale zjednodušeným příkladem možné implementace.
Pracovní příklad
Pojďme synchronizovat soubory z hlavního bucketu v MCS do záložního bucketu v AWS. Hlavní bucket se nazývá myfiles-ash, záložní se nazývá myfiles-backup (konfigurace bucketu v AWS je nad rámec tohoto článku). V souladu s tím, když je soubor umístěn do hlavního segmentu, jeho kopie by se měla objevit v záložním, a když je odstraněn z hlavního, měl by být odstraněn v záložním.
S buckety budeme pracovat pomocí utility awscli, která je kompatibilní jak s cloudovým úložištěm MCS, tak s cloudovým úložištěm 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) ...
Pojďme nakonfigurovat pří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]:
Pojďme nakonfigurovat pří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]:
Zkontrolujeme přístupy:
Do AWS:
ubuntu@ubuntu-basic-1-2-10gb:~$ aws s3 ls --profile aws
2020-07-06 08:44:11 myfiles-backup
Pro MCS musíte při spuštění příkazu přidat —endpoint-url:
Pojďme se podívat, jak to funguje. Přes webové rozhraní MCS přidejte soubor test.txt do kbelíku myfiles-ash. Protokoly konzoly ukazují, že byl odeslán požadavek na server webhooku:
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
Pojďme zkontrolovat obsah kbelíku zálohování myfiles v AWS:
Nyní prostřednictvím webového rozhraní smažeme soubor z kbelíku myfiles-ash.
Protokoly serveru:
2020/07/06 09:44:46 [POST] incoming HTTP request from
95.163.216.92:58224
delete: s3://myfiles-backup/test.txt
Obsah kbelíku:
ubuntu@ubuntu-basic-1-2-10gb:~/s3-webhook$ aws s3 --profile aws ls
myfiles-backup
ubuntu@ubuntu-basic-1-2-10gb:~$
Soubor je smazán, problém je vyřešen.
Závěr a úkol
Veškerý kód použitý v tomto článku je v mém úložišti. Nechybí ani ukázky skriptů a příklady počítání podpisů pro registraci webhooků.
Tento kód není nic jiného než příklad toho, jak můžete webhooky S3 využít ve svých aktivitách. Jak jsem řekl na začátku, pokud plánujete používat takový server v produkci, musíte server alespoň přepsat pro asynchronní práci: zaregistrovat příchozí webhooky do fronty (RabbitMQ nebo NATS) a odtud je analyzovat a zpracovat s pracovními aplikacemi. V opačném případě, když webhooky dorazí masivně, můžete narazit na nedostatek serverových zdrojů k dokončení úkolů. Přítomnost front vám umožňuje distribuovat server a pracovníky a také řešit problémy s opakujícími se úkoly v případě selhání. Je také vhodné změnit protokolování na podrobnější a standardizovanější.