Näide sündmustel põhinevast rakendusest, mis kasutab webhook'e Mail.ru Cloud Solutions objektide S3-salves

Näide sündmustel põhinevast rakendusest, mis kasutab webhook'e Mail.ru Cloud Solutions objektide S3-salves
Rube Goldberg kohvimasin

Sündmuspõhine arhitektuur suurendab kasutatavate ressursside hinnatõhusust, kuna neid kaasatakse vaid siis, kui need on vajalikud. On palju võimalusi, kuidas seda teostada ja mitte luua lisapilveseesid worker-rakenduste vormis. Täna räägin ma mitte FaaS-ist, vaid veebihook'idest. Näitan õppepraktikat sündmuste töötlemiseks objekthoidla veebihook'ide abil.

Paari sõna objekthoidla ja veebihook'ide kohta. Objekthoidlad võimaldavad salvestada igasuguseid andmeid pilves objektide kujul, mis on kergesti ligipääsetavad S3 või muu API kaudu (sõltuvalt rakendamisest) HTTP/HTTPS kaudu. Veebihook'id (webhooks) on üldises mõttes kohandatud tagasikutsed HTTP kaudu. Need käivitatakse tavaliselt mingi sündmuse, näiteks koodi saatmisega repositooriumisse või blogisse postitatud kommentaariga. Kui sündmus toimub, saadab algne sait HTTP-päringu veebihook'ile määratud URL-ile. Selle tulemuseks on see, et ühe saidi sündmused võivad esile kutsuda tegevusi teises seotud saidis. Kui algne sait on objekthoidla, esinevad sündmustena muudatused selle sisus.wiki). В случае, когда исходным сайтом выступает объектное хранилище, в роли событий выступают изменения его содержимого.

Lihtsate juhtumite näited, kus automatiseerimist kasutada:

  1. Kõikide objektide kopeerimine teise pilveteenusesse. Koopiad peavad olema loodud "reaalajas" igal failide lisamisel või muutmisel.
  2. Graafikafailide miniatüüride automaatne loomine, vesimärkide lisamine fotodele ja muud pildimuudatused.
  3. Teadete saatmine uute dokumentide saabumise kohta (näiteks jaotatud raamatupidamisteenus üles laadib pilve aruanded ning finantsjärelevalve saab teateid uutest aruannetest, kontrollib ja analüüsib neid).
  4. Veidi keerukamad juhtumid hõlmavad näiteks päringu koostamist Kubernetes'es, mis loob soovitud konteineritega pod'i, edastab sellele ülesande parameetrid ja sulgeb konteiner pärast töötlemist.

Näiteks käsitleme ülesande varianti 1, kus Mail.ru Cloud Solutions (MCS) objektihoidla muudatused sünkroniseeritakse AWS objektihoidlas veebihookide abil. Tegelikult koormatud juhul tuleks ette näha asünkroonne töö, registreerides veebihookid järjekorda, kuid õppeülesande jaoks teeme teostuse ilma selleta.

Töö skeem

Koostööprotokoll on detailselt kirjeldatud MCS S3 veebihookide juhendis. Töö skeemis on järgmised elemendid:

  • Avaldamisteenus, mis asub S3 ladustamise poolel ja saadab HTTP-päringuid, kui webnhook aktiveerub.
  • Veebihookide vastuvõtuserver, mis kuulab avaldamisteenuse HTTP pöördumisi ja täidab vastavaid toiminguid. Serveri võib kirjutada mistahes keeles, meie näites kirjutame serveri Go keeles.

Veebihookide rakendamise eripära S3 API-s on veebihookide vastuvõtuserveri registreerimine avaldamisteenuses. Eelkõige peab veebihookide vastuvõtuserver kinnitama tellimuse avaldamisteenuse sõnumitele (muudes veebihookide rakendustes ei ole tellimuse kinnitamine tavaliselt vajalik).

Seega peab veebihookide vastuvõtuserver toetama kahte põhitoimingut:

  • vastama avaldamisteenuse registreerimise kinnitamise päringule,
  • töötlema saabunud sündmusi.

Veebihookide vastuvõtuserveri seadistamine

Veebihookide vastuvõtuserveri käivitamiseks on vajalik Linuxi server. Käesolevas artiklis kasutame näitena virtuaalset instantsi, mille seadistame MCS-il.

Paigaldame vajalikud tarkvarad ja käivitame veebhookside vastuvõtu serveri.

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) ...

Kloonime veebhookside vastuvõtu serveri kausta:

ubuntu@ubuntu-basic-1-2-10gb:~$ git clone
https://github.com/RomanenkoDenys/s3-webhook.git
Kloonimine 's3-webhook' kausta...
remote: Objekti loendamine: 48, valmis.
remote: Objektide lugemine: 100% (48/48), valmis.
remote: Objektide tihendamine: 100% (27/27), valmis.
remote: Kokku 114 (delta 20), uuesti kasutatud 45 (delta 18), pakke uuesti kasutatud 66
Objektide vastuvõtt: 100% (114/114), 23.77 MiB | 20.25 MiB/s, valmis.
Delta lahendamine: 100% (49/49), valmis.

Käivitame serveri:

ubuntu@ubuntu-basic-1-2-10gb:~$ cd s3-webhook/
ubunt@ubuntu-basic-1-2-10gb:~/s3-webhook$ sudo ./s3-webhook -port 80

Tellimus veebihookide teenusele

Veebihookide vastuvõtva serveri registreerimist saab teostada API või veebiliidese kaudu. Lihtsuse huvides registreerime läbi veebiliidese:

  1. Liigume konteinerite jaotisse haldusliideses.
  2. Siseneme konteinerisse, mille jaoks seadistame veebihookid, ja vajutame hammasratta ikoonile:

Näide sündmustel põhinevast rakendusest, mis kasutab webhook'e Mail.ru Cloud Solutions objektide S3-salves

Käime vahekaart Webhooks ja vajutame Lisa:

Näide sündmustel põhinevast rakendusest, mis kasutab webhook'e Mail.ru Cloud Solutions objektide S3-salves
Täidame väljad:

Näide sündmustel põhinevast rakendusest, mis kasutab webhook'e Mail.ru Cloud Solutions objektide S3-salves

ID — veebihooki nimi.

Sündmus — milliseid sündmusi edastada. Oleme valinud edastada kõik sündmused, mis toimuvad failidega töötamisel (lisamine ja kustutamine).

URL — veebihookide vastuvõtva serveri aadress.

Filtri eesliide/jesliide — filter, mis võimaldab genereerida veebihooke ainult objektidele, mille nimed vastavad kindlatele reeglitele. Näiteks, et veebihook aktiveeruks ainult .png laiendiga failide puhul, tuleb Filtri järelliide sisestada «png».

Praegusel hetkel toetatakse veebihookide vastuvõtva serveriga ühenduse loomisel ainult porte 80 ja 443.

Vajutame Lisa hook ja näeme järgmist:

Näide sündmustel põhinevast rakendusest, mis kasutab webhook'e Mail.ru Cloud Solutions objektide S3-salves
Hook on lisatud.

Veebihookide vastuvõtva serveri logides kuvatakse hooki registreerimise protsessi toimumine:

ubuntu@ubuntu-basic-1-2-10gb:~/s3-webhook$ sudo ./s3-webhook -port 80
2020/06/15 12:01:14 [POST] sissetulek HTTP päring 
95.163.216.92:42530
2020/06/15 12:01:14 Saadi ajatempli: 2020-06-15T15:01:13+03:00 TeemaArn: 
mcs5259999770|myfiles-ash|s3:ObjectCreated:*,s3:ObjectRemoved:* Token: 
E2itMqAMUVVZc51pUhFWSp13DoxezvRxkUh5P7LEuk1dEe9y URL: 
http://89.208.199.220/webhook
2020/06/15 12:01:14 Loo vastuse allkiri: 
3754ce36636f80dfd606c5254d64ecb2fd8d555c27962b70b4f759f32c76b66d

Registreerimine on lõpetatud. Järgmises jaotises vaatame põhjalikumalt veebihookide vastuvõtuserveri töö põhimõtteid.

Veebihookide vastuvõtuserveri kirjeldus

Meie näites on server kirjutatud Go keeles. Vaatleme selle töö põhialuseid.

package main

// Generate hmac_sha256_hex
func HmacSha256hex(message string, secret string) string {
}

// Generate hmac_sha256
func HmacSha256(message string, secret string) string {
}

// Send subscription confirmation
func SubscriptionConfirmation(w http.ResponseWriter, req *http.Request, body []byte) {
}

// Send subscription confirmation
func GotRecords(w http.ResponseWriter, req *http.Request, body []byte) {
}

// Liveness probe
func Ping(w http.ResponseWriter, req *http.Request) {
    // log request
    log.Printf("[%s] incoming HTTP Ping request from %sn", req.Method, req.RemoteAddr)
    fmt.Fprintf(w, "Pongn")
}

//Webhook
func Webhook(w http.ResponseWriter, req *http.Request) {
}

func main() {

    // get command line args
    bindPort := flag.Int("port", 80, "number between 1-65535")
    bindAddr := flag.String("address", "", "ip address in dot format")
    flag.StringVar(&actionScript, "script", "", "external script to execute")
    flag.Parse()

    http.HandleFunc("/ping", Ping)
    http.HandleFunc("/webhook", Webhook)

log.Fatal(http.ListenAndServe(*bindAddr+":"+strconv.Itoa(*bindPort), nil))
}

Vaatame peamiseid funktsioone:

  • Ping() — marsruut, mis vastab URL/ping, lihtsaim liveness probe'i teostus.
  • Webhook() — peamine marsruut, URL/veebikuulutuse töötleja:
    • kinnitab registreerimist e-posti teenusesse (üleminek funktsiooni SubscriptionConfirmation),
    • töötleb saabunud veebikuulutusi (funktsioon GotRecords).
  • Funktsioonid HmacSha256 ja HmacSha256hex on HMAC-SHA256 ja HMAC-SHA256 algoritmide rakendused, mis väljastavad 16-kohaliste arvude stringid allkirja arvutamiseks.
  • peamine — põhifunktsioon, mis töötleb käsurea parameetreid ja registreerib URL-i töötlejad.

Käsurea parameetrid, mille server aktsepteerib:

  • -port — port, millel server kuulab.
  • -address — IP-aadress, millega server kuulab.
  • -script — väline programm, mis käivitatakse iga saabunud hargnemise puhul.

Vaadake mõningaid funktsioone lähemalt:

//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)
    }

}

See funktsioon määrab, mis on saabunud — registreerimise kinnitamise või veebiharu. Nagu selgub dokumentatsioonis, registreerimise kinnitamise korral tuleb järgmine Json-i struktuur Post-päringus:

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":"Olete valinud tellida teema $topic. Tellimuse kinnitamiseks peate vastama arvutatud allkirjaga",
    "TopicArn":"mcs2883541269|bucketA|s3:ObjectCreated:Put",
    "SignatureVersion":1,
    "Token":«RPE5UuG94rGgBH6kHXN9FUPugFxj1hs2aUQc99btJp3E49tA»
}

Sellele päringule tuleb vastata:

content-type: application/json

{"signature":«ea3fce4bb15c6de4fec365d36bcebbc34ccddf54616d5ca12e1972f82b6d37af»}

Kus allkiri arvutatakse järgmiselt:

allkiri = hmac_sha256(url, hmac_sha256(TopicArn, 
hmac_sha256(Timestamp, Token)))

Kui saabub veebiharu, siis Post-päringu struktuur näeb välja selline:

POST  HTTP/1.1
x-amz-sns-messages-type: SubscriptionConfirmation

{ "Records":
    [
        {
            "s3": {
                "object": {
                    "eTag":"aed563ecafb4bcc5654c597a421547b2",
                    "sequencer":1577453615,
                    "key":"some-file-to-bucket",
                    "size":100
                },
            "configurationId":"1",
            "bucket": {
                "name": "bucketA",
                "ownerIdentity": {
                    "principalId":"mcs2883541269"}
                },
                "s3SchemaVersion":"1.0"
            },
            "eventVersion":"1.0",
            "requestParameters":{
                "sourceIPAddress":"185.6.245.156"
            },
            "userIdentity": {
                "principalId":"2407013e-cbc1-415f-9102-16fb9bd6946b"
            },
            "eventName":"s3:ObjectCreated:Put",
            "awsRegion":"ru-msk",
            "eventSource":"aws:s3",
            "responseElements": {
                "x-amz-request-id":"VGJR5rtJ"
            }
        }
    ]
}

Seetõttu, olenevalt päringust tuleb mõista, kuidas andmeid töödelda. Olen valinud indikaatoriks kirje "Type":"SubscriptionConfirmation", kuna see esineb tellimuse kinnitamise päringus ja ei esine veebihookis. Lähtuvalt selle kirje olemasolust / puudumisest POST-päringus, suunatakse täiendav programmitöö kas funktsiooni SubscriptionConfirmation, või funktsiooni GotRecords.

Funktsiooni SubscriptionConfirmation ei hakka me põhjalikult uurima, see on realiseeritud põhimõtete järgi, mis on välja toodud dokumentatsioonis. Selle funktsiooni lähtekoodi saab vaadata projekti git-repositooriumist.

Funktsioon GotRecords töötleb saabuvat päringut ja kutsub iga Record objekti jaoks välja välise skripti (mille nimi edastati parameetris -script) järgmiste parameetritega:

  • ämber nimi
  • objekti võti
  • toiming:
    • copy — kui algses päringus on EventName = ObjectCreated | PutObject | PutObjectCopy
    • delete — kui algses päringus on EventName = ObjectRemoved | DeleteObject

Seega, kui tuleb webhook koos Post-päringuga, nagu kirjeldatud üle, ja parameeter -script=script.sh, kutsub skript välja järgmiselt:

script.sh  bucketA some-file-to-bucket copy

Tuleb mõista, et see webhookide vastuvõtuserver ei ole täielik tootmislahendus, vaid lihtsustatud näide võimalikust rakendusest.

Töö näide

Teeme põhialuste failide sünkroonimise MCS-i varundusämbritesse AWS-is. Põhiline ämber on nimega myfiles-ash, varu- on myfiles-backup (AWS-i ämbrite konfiguratsioon jääb artikli ulatusest välja). vastavalt, kui fail pannakse põhialusesse, peab selle koopia ilmuma varu, kui see kustutatakse põhialusest — kustutatakse varu.

Töötame bucket'itega awscli tööriista abil, mis on ühilduv nii MCS pilvehoidla kui ka AWS pilvehoidlaga.

ubuntu@ubuntu-basic-1-2-10gb:~$ sudo apt-get install awscli
Pakettide loendite lugemine... Valmis
Sõltuvuste puu koostamine
Oleku teabe lugemine... Valmis
Pärast seda toimingut kasutatakse 34.4 MB täiendavat kettaruumi.
awscli paketist lahtipakkimine (1.14.44-1ubuntu1) ...
awscli seadistamine (1.14.44-1ubuntu1) ...

Seame sisselogimise S3 MCS API-ks:

ubuntu@ubuntu-basic-1-2-10gb:~$ aws configure --profile mcs
AWS Access Key ID [None]: hdywEPtuuJTExxxxxxxxxxxxxx
AWS Secret Access Key [None]: hDz3SgxKwXoxxxxxxxxxxxxxxxxxx
Vaikimisi piirkonna nimi [None]:
Vaikimisi väljundi formaat [None]:

Seame sisselogimise S3 AWS API-ks:

ubuntu@ubuntu-basic-1-2-10gb:~$ aws configure --profile aws
AWS Access Key ID [None]: AKIAJXXXXXXXXXXXX
AWS Secret Access Key [None]: dfuerphOLQwu0CreP5Z8l5fuXXXXXXXXXXXXXXXX
Vaikimisi piirkonna nimi [None]:
Vaikimisi väljundi formaat [None]:

Kontrollime ligipääse:

AWS-lt:

ubuntu@ubuntu-basic-1-2-10gb:~$ aws s3 ls --profile aws
2020-07-06 08:44:11 myfiles-backup

MCS puhul tuleb käsu juurde lisada —endpoint-url:

ubuntu@ubuntu-basic-1-2-10gb:~$ aws s3 ls --profile mcs --endpoint-url 
https://hb.bizmrg.com
2020-02-04 06:38:05 databasebackups-0cdaaa6402d4424e9676c75a720afa85
2020-05-27 10:08:33 myfiles-ash

Ligipääs on saadud.

Nüüd kirjutame sissetuleva hook'i töötlemise skripti, nimetame selleks s3_backup_mcs_aws.sh

#!/bin/bash
# Require aws cli
# if file added — copy it to backup bucket
# if file removed — remove it from backup bucket
# Variables
ENDPOINT_MCS="https://hb.bizmrg.com"
AWSCLI_MCS=`which aws`" --endpoint-url ${ENDPOINT_MCS} --profile mcs s3"
AWSCLI_AWS=`which aws`" --profile aws s3"
BACKUP_BUCKET="myfiles-backup"

SOURCE_BUCKET="${1}"
SOURCE_FILE="${2}"
ACTION="${3}"

SOURCE="s3://${SOURCE_BUCKET}/${SOURCE_FILE}"
TARGET="s3://${BACKUP_BUCKET}/${SOURCE_FILE}"
TEMP="/tmp/${SOURCE_BUCKET}/${SOURCE_FILE}"

case ${ACTION} in
    "copy")
    ${AWSCLI_MCS} cp "${SOURCE}" "${TEMP}"
    ${AWSCLI_AWS} cp "${TEMP}" "${TARGET}"
    rm ${TEMP}
    ;;

    "delete")
    ${AWSCLI_AWS} rm ${TARGET}
    ;;

    *)
    echo "Usage: ${0} sourcebucket sourcefile copy/delete"
    exit 1
    ;;
esac

Käivitame serveri:

ubuntu@ubuntu-basic-1-2-10gb:~/s3-webhook$ sudo ./s3-webhook -port 80 -
skript scripts/s3_backup_mcs_aws.sh

Kontrollime, kuidas see töötab. Aja jooksul MCS veebiliidese kaudu. lisame faili test.txt kotti myfiles-ash. Logides on näha, et tehtud oli päring veebihooki serverisse:

2020/07/06 09:43:08 [POST] sisenev HTTP päring aadressilt 
95.163.216.92:56612
downlaad: s3://myfiles-ash/test.txt ../../../tmp/myfiles-ash/test.txt
üleslaadimine: ../../../tmp/myfiles-ash/test.txt s3://myfiles-backup/test.txt

Kontrollime AWS-is myfiles-backup kotti sisu:

ubuntu@ubuntu-basic-1-2-10gb:~/s3-webhook$ aws s3 --profile aws ls 
myfiles-backup
2020-07-06 09:43:10       1104 test.txt

Nüüd kustutame veebiliidese kaudu faili myfiles-ash kotist.

Serveri logid:

2020/07/06 09:44:46 [POST] sisenev HTTP päring aadressilt 
95.163.216.92:58224
delete: s3://myfiles-backup/test.txt

Koti sisu:

ubuntu@ubuntu-basic-1-2-10gb:~/s3-webhook$ aws s3 --profile aws ls 
myfiles-backup
ubuntu@ubuntu-basic-1-2-10gb:~$

Fail on kustutatud, probleem lahendatud.

Kokkuvõte ja ToDo

Kogu artiklis kasutatud kood on saadaval minu repositooriumis. Seal on ka skripti näidendid ja käskluste näidised veebihookide registreerimise jaoks.

See kood on vaid näide sellest, kuidas kasutada S3 veebihäkke oma tegevuses. Nagu ma alguses mainisin, tuleb sellise serveri tootmises kasutamise korral vähemalt server kirja panna asünkroonse töö jaoks: saabuvad veebihäkked registreerida järjekorda (RabbitMQ või NATS) ja sealt neid töötlusrakendustes töödelda. Vastasel juhul võib massiliselt saabuvate veebihäkkide korral tekkida serveri ressursside nappus ülesannete täitmiseks. Järjekordade olemasolu võimaldab jagada serverit ja töötlusrakendusi, samuti lahendada ülesannete kordamise küsimusi tõrgete korral. Samuti on soovitatav muuta logimine detailsemaks ja standardiseeritumaks.

Edu!

Veel lugemist teema kohta:

Allikas: habr.com

Osta usaldusväärne veebihosting DDoS kaitsega, VPS VDS serverid 🔥 Osta usaldusväärne veebihosting DDoS kaitsega, VPS VDS serverid | ProHoster