Arhitektura vođena događajima povećava isplativost korišćenih resursa jer se koriste samo u trenutku kada su potrebni. Postoji mnogo opcija kako to implementirati i ne kreirati dodatne entitete u oblaku kao radne aplikacije. I danas ću govoriti ne o FaaS-u, već o webhookovima. Pokazat ću tutorial primjer rukovanja događajima koristeći web-hookove za pohranu objekata.
Nekoliko riječi o pohranjivanju objekata i webhookovima. Skladištenje objekata vam omogućava pohranjivanje svih podataka u oblaku u obliku objekata, dostupnih preko S3 ili drugog API-ja (ovisno o implementaciji) putem HTTP/HTTPS-a. Webhookovi su općenito prilagođeni HTTP povratni pozivi. Obično ih pokreće događaj, kao što je kod koji se gura u spremište ili komentar koji se postavlja na blog. Kada se dogodi neki događaj, izvorna stranica šalje HTTP zahtjev na URL naveden za webhook. Kao rezultat toga, možete učiniti da događaji na jednoj lokaciji pokreću radnje na drugoj (Wiki). U slučaju kada je izvorna stranica skladište objekata, događaji se ponašaju kao promjene njegovog sadržaja.
Primjeri jednostavnih slučajeva kada se takva automatizacija može koristiti:
Kreiranje kopija svih objekata u drugom skladištu u oblaku. Kopije se moraju kreirati u hodu kad god se fajlovi dodaju ili mijenjaju.
Automatsko kreiranje serije sličica grafičkih datoteka, dodavanje vodenih žigova fotografijama i druge modifikacije slika.
Obavijest o pristizanju novih dokumenata (na primjer, distribuirani računovodstveni servis prenosi izvještaje u oblak, a finansijski monitoring prima obavijesti o novim izvještajima, provjerava ih i analizira).
Nešto složeniji slučajevi uključuju, na primjer, generiranje zahtjeva za Kubernetes, koji kreira pod s potrebnim kontejnerima, prosljeđuje mu parametre zadatka i nakon obrade sažima kontejner.
Kao primjer, napravit ćemo varijantu zadatka 1, kada se promjene u Mail.ru Cloud Solutions (MCS) spremniku za pohranu objekata sinkroniziraju u AWS pohranu objekata pomoću webhookova. U stvarno učitanom slučaju, asinhroni rad bi trebao biti osiguran registracijom web-hukova u red čekanja, ali za zadatak obuke mi ćemo implementaciju odraditi bez toga.
Izdavačka usluga, koji se nalazi na strani S3 memorije i objavljuje HTTP zahtjeve kada se pokrene webnhook.
Webhook server za prijem, koji sluša zahtjeve HTTP servisa za objavljivanje i izvodi odgovarajuće radnje. Server može biti napisan na bilo kom jeziku; u našem primjeru, server ćemo pisati u Go.
Posebna karakteristika implementacije webhookova u S3 API je registracija servera za primanje webhooka na servisu za objavljivanje. Konkretno, server koji prima webhook mora potvrditi pretplatu na poruke iz usluge objavljivanja (u drugim implementacijama webhook-a, potvrda pretplate obično nije potrebna).
U skladu s tim, server koji prima webhook mora podržavati dvije glavne operacije:
odgovori na zahtjev izdavačke službe za potvrdu registracije,
obraditi dolazeće događaje.
Instaliranje servera za primanje webhook-a
Da biste pokrenuli server za primanje webhook-a, potreban vam je Linux server. U ovom članku, kao primjer, koristimo virtuelnu instancu koju postavljamo na MCS.
Hajde da instaliramo neophodan softver i pokrenemo server za primanje webhooka.
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) ...
Klonirajte folder sa serverom za primanje webhook-a:
Idite na kantu za koju ćemo konfigurirati webhookove i kliknite na zupčanik:
Idite na karticu Webhooks i kliknite na Dodaj:
Popunite polja:
ID — naziv webhok-a.
Događaj - koje događaje prenijeti. Postavili smo prijenos svih događaja koji se javljaju pri radu sa fajlovima (dodavanje i brisanje).
URL — webhook adresa servera za prijem.
Prefiks/sufiks filtera je filter koji vam omogućava da generišete webhookove samo za objekte čija imena odgovaraju određenim pravilima. Na primjer, da bi webhook pokrenuo samo datoteke sa ekstenzijom .png, in Sufiks filtera potrebno je da napišete "png".
Trenutno su samo portovi 80 i 443 podržani za pristup serveru za primanje webhook-a.
Hajde da kliknemo Dodajte kuku i videcemo sledece:
Hook je dodao.
Server za primanje webhook-a pokazuje u svojim zapisnicima napredak procesa registracije kuke:
Ping() - ruta koja odgovara putem URL-a/pinga, najjednostavnije implementacije sonde za živost.
Webhook() - glavna ruta, URL/webhook rukovalac:
potvrđuje registraciju na izdavačkoj usluzi (idite na funkciju SubscriptionConfirmation),
obrađuje dolazne webhookove (funkcija Gorecords).
Funkcije HmacSha256 i HmacSha256hex su implementacije algoritama za šifriranje HMAC-SHA256 i HMAC-SHA256 sa izlazom kao nizom heksadecimalnih brojeva za izračunavanje potpisa.
main je glavna funkcija, obrađuje parametre komandne linije i registruje URL rukovaoce.
Parametri komandne linije koje server prihvata:
-port je port na kojem će server slušati.
-address - IP adresa koju će server slušati.
-script je eksterni program koji se poziva za svaku dolaznu zakačicu.
Pogledajmo pobliže neke od funkcija:
//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)
}
}
Ova funkcija određuje da li je stigao zahtjev za potvrdu registracije ili webhook. Kako slijedi iz dokumentaciju, ako je registracija potvrđena, sljedeća Json struktura se prima u zahtjevu za poštu:
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»
}
Shodno tome, ovisno o zahtjevu, morate razumjeti kako obrađivati podatke. Odabrao sam unos kao indikator "Type":"SubscriptionConfirmation", budući da je prisutan u zahtjevu za potvrdu pretplate i nije prisutan u webhooku. Na osnovu prisustva/odsustva ovog unosa u POST zahtevu, dalje izvršavanje programa ide ili na funkciju SubscriptionConfirmation, ili u funkciju GotRecords.
Funkciju SubscriptionConfirmation nećemo razmatrati detaljno; ona se implementira prema principima navedenim u dokumentaciju. Izvorni kod za ovu funkciju možete pogledati na projektna git spremišta.
Funkcija GotRecords analizira dolazni zahtjev i za svaki objekt Record poziva eksternu skriptu (čije je ime proslijeđeno u parametru -script) s parametrima:
naziv kante
objektni ključ
akcija:
kopija - ako je u originalnom zahtjevu EventName = ObjectCreated | PutObject | PutObjectCopy
delete - ako je u originalnom zahtjevu EventName = ObjectRemoved | DeleteObject
Dakle, ako kuka stigne sa Post zahtjevom, kao što je opisano viši, i parametar -script=script.sh tada će skripta biti pozvana na sljedeći način:
script.sh bucketA some-file-to-bucket copy
Treba shvatiti da ovaj webhook server za primanje nije kompletno proizvodno rješenje, već pojednostavljeni primjer moguće implementacije.
Primjer rada
Hajde da sinhronizujemo fajlove iz glavnog segmenta u MCS-u u rezervni segment u AWS-u. Glavni bucket se zove myfiles-ash, rezervni se zove myfiles-backup (konfiguracija bucketa u AWS-u je izvan okvira ovog članka). Shodno tome, kada se datoteka stavi u glavnu kantu, njena kopija treba da se pojavi u rezervnoj, a kada se izbriše iz glavne, treba je izbrisati u rezervnoj.
Radit ćemo s buckets koristeći awscli uslužni program, koji je kompatibilan i sa MCS cloud storage i AWS cloud storage.
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) ...
Konfigurirajmo pristup S3 MCS API-ju:
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]:
Konfigurirajmo pristup AWS S3 API-ju:
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]:
Provjerimo pristupe:
Za AWS:
ubuntu@ubuntu-basic-1-2-10gb:~$ aws s3 ls --profile aws
2020-07-06 08:44:11 myfiles-backup
Za MCS, kada izvodite naredbu morate dodati —endpoint-url:
Hajde da vidimo kako to radi. Kroz MCS web interfejs dodajte datoteku test.txt u korpu myfiles-ash. Dnevnici konzole pokazuju da je učinjen zahtjev webhook serveru:
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
Provjerimo sadržaj myfiles-backup bucketa u AWS-u:
Sada ćemo preko web interfejsa izbrisati datoteku iz myfiles-ash bucketa.
Dnevnici servera:
2020/07/06 09:44:46 [POST] incoming HTTP request from
95.163.216.92:58224
delete: s3://myfiles-backup/test.txt
Sadržaj korpe:
ubuntu@ubuntu-basic-1-2-10gb:~/s3-webhook$ aws s3 --profile aws ls
myfiles-backup
ubuntu@ubuntu-basic-1-2-10gb:~$
Fajl je obrisan, problem je riješen.
Zaključak i ToDo
Sav kod korišten u ovom članku je u mom spremištu. Tu su i primjeri skripti i primjeri brojanja potpisa za registraciju webhok-ova.
Ovaj kod nije ništa drugo do primjer kako možete koristiti S3 webhookove u svojim aktivnostima. Kao što sam rekao na početku, ako planirate da koristite takav server u produkciji, morate barem prepisati server za asinhroni rad: registrirati dolazne web hookove u red čekanja (RabbitMQ ili NATS), a odatle ih analizirati i obraditi sa radničkim aplikacijama. U suprotnom, kada webhookovi stignu masovno, možete naići na nedostatak serverskih resursa za dovršavanje zadataka. Prisustvo redova vam omogućava distribuciju servera i radnika, kao i rješavanje problema s ponavljanjem zadataka u slučaju kvarova. Također je preporučljivo promijeniti evidenciju na detaljnije i standardiziranije.