Dæmi um atburðadrifið forrit sem byggir á vefhókum í S3 hlutageymslu Mail.ru Cloud Solutions

Dæmi um atburðadrifið forrit sem byggir á vefhókum í S3 hlutageymslu Mail.ru Cloud Solutions
Rube Goldberg kaffivél

Atburðadrifinn arkitektúr eykur kostnaðarhagkvæmni auðlindanna sem notuð eru vegna þess að þau eru aðeins notuð á því augnabliki sem þeirra er þörf. Það eru margir möguleikar til að útfæra þetta og búa ekki til viðbótarskýjaeiningar sem starfsmannaforrit. Og í dag mun ég ekki tala um FaaS, heldur um webhooks. Ég mun sýna kennsludæmi um meðhöndlun atburða með því að nota vefkróka til að geyma hluti.

Nokkur orð um hlutgeymslu og vefkróka. Hlutageymsla gerir þér kleift að geyma hvaða gögn sem er í skýinu í formi hluta, aðgengileg í gegnum S3 eða annað API (fer eftir útfærslu) í gegnum HTTP/HTTPS. Webhooks eru almennt sérsniðnar HTTP svarhringingar. Þau eru venjulega kveikt af atburði, eins og kóða sem er ýtt í geymslu eða athugasemd sem er sett á blogg. Þegar atburður á sér stað sendir upprunasíðan HTTP beiðni á vefslóðina sem tilgreind er fyrir vefhookinn. Þar af leiðandi geturðu látið atburði á einni síðu kalla fram aðgerðir á annarri (Wiki). Í því tilviki þar sem upprunasíðan er hlutgeymsla virka atburðir sem breytingar á innihaldi hennar.

Dæmi um einföld tilvik þegar hægt er að nota slíka sjálfvirkni:

  1. Að búa til afrit af öllum hlutum í annarri skýgeymslu. Búa verður til afrit á flugi þegar skrám er bætt við eða þeim breytt.
  2. Sjálfvirk gerð röð af smámyndum af grafískum skrám, bætt vatnsmerkjum við ljósmyndir og aðrar breytingar á myndum.
  3. Tilkynning um komu nýrra skjala (til dæmis hleður dreifð bókhaldsþjónusta upp skýrslum í skýið og fjármálaeftirlit fær tilkynningar um nýjar skýrslur, athugar og greinir þær).
  4. Örlítið flóknari tilvik fela til dæmis í sér að búa til beiðni til Kubernetes, sem býr til belg með nauðsynlegum ílátum, sendir verkfæribreytur til hans og eftir vinnslu fellur ílátið saman.

Sem dæmi munum við búa til afbrigði af verkefni 1, þegar breytingar á Mail.ru Cloud Solutions (MCS) hlutageymslufötu eru samstilltar í AWS hlutageymslu með vefhókum. Í raunverulegu hlaðnu tilviki ætti að veita ósamstillta vinnu með því að skrá vefkróka í biðröð, en fyrir þjálfunarverkefnið munum við framkvæma innleiðinguna án þess.

Vinnuskipulag

Samskiptareglunum er lýst í smáatriðum í Leiðbeiningar um S3 webhooks á MCS. Vinnuáætlunin inniheldur eftirfarandi þætti:

  • Útgáfuþjónusta, sem er á S3 geymsluhliðinni og birtir HTTP beiðnir þegar webnhook er ræst.
  • Webhook móttökuþjónn, sem hlustar á beiðnir frá HTTP útgáfuþjónustunni og framkvæmir viðeigandi aðgerðir. Hægt er að skrifa þjóninn á hvaða tungumáli sem er; í okkar dæmi munum við skrifa þjóninn í Go.

Sérstakur eiginleiki við innleiðingu vefhóka í S3 API er skráning vefhókamóttökuþjónsins á útgáfuþjónustuna. Sérstaklega verður vefhook móttökuþjónninn að staðfesta áskrift að skilaboðum frá útgáfuþjónustunni (í öðrum vefhook útfærslum er venjulega ekki krafist staðfestingar á áskrift).

Í samræmi við það verður vefhook móttökuþjónninn að styðja tvær meginaðgerðir:

  • svara beiðni útgáfuþjónustunnar um að staðfesta skráningu,
  • vinna úr komandi atburðum.

Uppsetning á vefhook móttökuþjóni

Til að keyra webhook móttökuþjóninn þarftu Linux netþjón. Í þessari grein, sem dæmi, notum við sýndartilvik sem við sendum á MCS.

Setjum upp nauðsynlegan hugbúnað og ræsum vefhook móttökuþjóninn.

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

Klóna möppuna með vefhook móttökuþjóninum:

ubuntu@ubuntu-basic-1-2-10gb:~$ git clone
https://github.com/RomanenkoDenys/s3-webhook.git
Cloning into 's3-webhook'...
remote: Enumerating objects: 48, done.
remote: Counting objects: 100% (48/48), done.
remote: Compressing objects: 100% (27/27), done.
remote: Total 114 (delta 20), reused 45 (delta 18), pack-reused 66
Receiving objects: 100% (114/114), 23.77 MiB | 20.25 MiB/s, done.
Resolving deltas: 100% (49/49), done.

Byrjum þjóninn:

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

Gerast áskrifandi að útgáfuþjónustu

Þú getur skráð vefhook móttökuþjón þinn í gegnum API eða vefviðmót. Til einföldunar munum við skrá okkur í gegnum vefviðmótið:

  1. Við skulum fara í fötuhlutann í stjórnklefanum.
  2. Farðu í fötuna sem við munum stilla webhooks fyrir og smelltu á gírinn:

Dæmi um atburðadrifið forrit sem byggir á vefhókum í S3 hlutageymslu Mail.ru Cloud Solutions

Farðu í Webhooks flipann og smelltu á Bæta við:

Dæmi um atburðadrifið forrit sem byggir á vefhókum í S3 hlutageymslu Mail.ru Cloud Solutions
Fylltu út reitina:

Dæmi um atburðadrifið forrit sem byggir á vefhókum í S3 hlutageymslu Mail.ru Cloud Solutions

Auðkenni — nafn vefhóksins.

Atburður - hvaða atburði á að senda. Við höfum stillt sendingu allra atburða sem eiga sér stað þegar unnið er með skrár (bætt við og eytt).

Vefslóð — netfang sem tekur á móti netþjóni.

Síuforskeyti/viðskeyti er sía sem gerir þér kleift að búa til vefkróka eingöngu fyrir hluti sem nöfnin passa við ákveðnar reglur. Til dæmis, til þess að webhook geti aðeins kveikt á skrám með .png endingunni, í Síuviðskeyti þú þarft að skrifa "png".

Eins og er eru aðeins port 80 og 443 studd til að fá aðgang að vefhook móttökuþjóninum.

Við skulum smella Bæta við krók og við munum sjá eftirfarandi:

Dæmi um atburðadrifið forrit sem byggir á vefhókum í S3 hlutageymslu Mail.ru Cloud Solutions
Hook bætt við.

Móttökuþjónn fyrir vefkrók sýnir í annálum sínum framvindu krókaskráningarferlisins:

ubuntu@ubuntu-basic-1-2-10gb:~/s3-webhook$ sudo ./s3-webhook -port 80
2020/06/15 12:01:14 [POST] incoming HTTP request from 
95.163.216.92:42530
2020/06/15 12:01:14 Got timestamp: 2020-06-15T15:01:13+03:00 TopicArn: 
mcs5259999770|myfiles-ash|s3:ObjectCreated:*,s3:ObjectRemoved:* Token: 
E2itMqAMUVVZc51pUhFWSp13DoxezvRxkUh5P7LEuk1dEe9y URL: 
http://89.208.199.220/webhook
2020/06/15 12:01:14 Generate responce signature: 
3754ce36636f80dfd606c5254d64ecb2fd8d555c27962b70b4f759f32c76b66d

Skráningu er lokið. Í næsta hluta munum við skoða nánar reiknirit fyrir rekstur vefhook móttökuþjónsins.

Lýsing á vefhook móttökuþjóninum

Í dæminu okkar er þjónninn skrifaður í Go. Við skulum líta á grundvallarreglur um starfsemi þess.

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

Íhugaðu helstu aðgerðir:

  • Ping() - leið sem svarar með vefslóð/ping, einfaldasta útfærslan á lifandi könnun.
  • Webhook() - aðalleið, vefslóð/vefhook stjórnandi:
    • staðfestir skráningu á útgáfuþjónustuna (farðu í áskriftarstaðfestingaraðgerðina),
    • vinnur úr komandi vefkrókum (Gorecords aðgerð).
  • Aðgerðir HmacSha256 og HmacSha256hex eru útfærslur á HMAC-SHA256 og HMAC-SHA256 dulkóðunaralgrímunum með úttak sem strengur sextánsímtalna til að reikna út undirskriftina.
  • main er aðalaðgerðin, vinnur úr skipanalínubreytum og skráir vefslóðameðferðaraðila.

Skipanalínubreytur samþykktar af þjóninum:

  • -port er portið sem þjónninn mun hlusta á.
  • -address - IP tölu sem þjónninn mun hlusta á.
  • -script er utanaðkomandi forrit sem er kallað fyrir hvern krók sem kemur inn.

Við skulum skoða nánar nokkrar af aðgerðunum:

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

}

Þessi aðgerð ákvarðar hvort beiðni um staðfestingu skráningar eða vefhook hafi borist. Eins og segir af skjöl, ef skráning er staðfest berst eftirfarandi Json uppbygging í Post beiðni:

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»
}

Þessari fyrirspurn þarf að svara:

content-type: application/json

{"signature":«ea3fce4bb15c6de4fec365d36bcebbc34ccddf54616d5ca12e1972f82b6d37af»}

Þar sem undirskriftin er reiknuð út sem:

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

Ef vefkrókur kemur lítur uppbygging póstbeiðnarinnar svona út:

POST <url> 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"
            }
        }
    ]
}

Í samræmi við það, eftir beiðni, þarftu að skilja hvernig á að vinna úr gögnunum. Ég valdi færsluna sem vísir "Type":"SubscriptionConfirmation", þar sem það er til staðar í beiðni um staðfestingu áskriftar og er ekki til staðar í vefhóknum. Byggt á tilvist/fjarveru þessarar færslu í POST beiðninni fer frekari keyrsla forritsins annað hvort í aðgerðina SubscriptionConfirmation, eða í fall GotRecords.

Við munum ekki íhuga áskriftarstaðfestingaraðgerðina í smáatriðum; hún er útfærð í samræmi við meginreglurnar sem settar eru fram í skjöl. Þú getur skoðað frumkóðann fyrir þessa aðgerð á project git geymslur.

GotRecords aðgerðin greinir innkomna beiðni og fyrir hvern Record hlut kallar á ytri skriftu (sem nafnið var sent í -script færibreytunni) með færibreytunum:

  • heiti fötu
  • hlutlykil
  • aðgerð:
    • afrita - ef í upprunalegu beiðninni EventName = ObjectCreated | PutObject | PutObjectCopy
    • eyða - ef í upprunalegu beiðninni EventName = ObjectRemoved | EyðaObject

Svona, ef krókur kemur með Post beiðni, eins og lýst er ofan, og færibreytan -script=script.sh þá verður forskriftin kölluð sem hér segir:

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

Það ætti að skilja að þessi webhook móttökuþjónn er ekki fullkomin framleiðslulausn, heldur einfaldað dæmi um mögulega útfærslu.

Dæmi um vinnu

Við skulum samstilla skrárnar frá aðalfötunni í MCS við öryggisafritið í AWS. Aðalfötan er kölluð myfiles-ash, varaafritið heitir myfiles-backup (uppsetning fötu í AWS er ​​utan gildissviðs þessarar greinar). Í samræmi við það, þegar skrá er sett í aðalfötuna, ætti afrit hennar að birtast í öryggisafritinu og þegar henni er eytt úr aðalfötunni ætti að eyða henni í öryggisafritinu.

Við munum vinna með fötu með því að nota awscli tólið, sem er samhæft við bæði MCS skýgeymslu og AWS skýgeymslu.

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

Við skulum stilla aðgang að 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]:

Við skulum stilla aðgang að 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]:

Við skulum athuga aðganginn:

Til AWS:

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

Fyrir MCS, þegar þú keyrir skipunina þarftu að bæta við —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

Skoðað.

Nú skulum við skrifa handrit til að vinna úr króknum sem kemur inn, við skulum kalla það 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=""
SOURCE_FILE=""
ACTION=""

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: 
#!/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
sourcebucket sourcefile copy/delete" exit 1 ;; esac

Byrjum þjóninn:

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

Við skulum sjá hvernig það virkar. Í gegnum MCS vefviðmót bættu test.txt skránni við myfiles-ash fötuna. Stjórnborðsskrárnar sýna að beiðni var gerð til vefhookþjónsins:

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

Við skulum athuga innihald myfiles-backup fötunnar í AWS:

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ú, í gegnum vefviðmótið, munum við eyða skránni úr myfiles-ash fötunni.

Server logs:

2020/07/06 09:44:46 [POST] incoming HTTP request from 
95.163.216.92:58224
delete: s3://myfiles-backup/test.txt

Innihald fötu:

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

Skránni er eytt, vandamálið er leyst.

Niðurstaða og ToDo

Allur kóði sem notaður er í þessari grein er í geymslunni minni. Einnig eru dæmi um forskriftir og dæmi um talningu undirskrifta til að skrá vefhooks.

Þessi kóði er ekkert annað en dæmi um hvernig þú getur notað S3 webhooks í athöfnum þínum. Eins og ég sagði í upphafi, ef þú ætlar að nota slíkan netþjón í framleiðslu, þá þarftu að minnsta kosti að endurskrifa netþjóninn fyrir ósamstillta vinnu: skrá innkomna netkróka í biðröð (RabbitMQ eða NATS) og þaðan þátta þá og vinna úr þeim með umsóknum starfsmanna. Annars, þegar vefhooks berast gríðarlega, gætirðu lent í skorti á netþjónaauðlindum til að klára verkefni. Tilvist biðraða gerir þér kleift að dreifa þjóninum og starfsmönnum, sem og leysa vandamál með endurtekin verkefni ef bilanir koma upp. Einnig er ráðlegt að breyta skráningu í ítarlegri og staðlaðari.

Good Luck!

Meira lesefni um efnið:

Heimild: www.habr.com

Bæta við athugasemd