S3 objektuen biltegiratze Mail.ru Cloud Solutions-en webhooketan oinarritutako gertaeretan oinarritutako aplikazio baten adibidea

S3 objektuen biltegiratze Mail.ru Cloud Solutions-en webhooketan oinarritutako gertaeretan oinarritutako aplikazio baten adibidea
Rube Goldberg kafe-makina

Gertaeren araberako arkitekturak erabiltzen diren baliabideen kostu-eraginkortasuna areagotzen du, behar diren unean soilik erabiltzen direlako. Aukera asko daude hau ezartzeko eta ez sortzeko hodeiko entitaterik langile-aplikazio gisa. Eta gaur ez dut FaaS-i buruz hitz egingo, webhook-ei buruz baizik. Objektuen biltegiratze webhook-ak erabiliz gertaerak kudeatzeko tutorial adibide bat erakutsiko dut.

Objektuen biltegiratzeari eta webhookei buruzko hitz batzuk. Objektuen biltegiratzeak hodeian edozein datu gordetzeko aukera ematen du objektu moduan, S3 edo beste API baten bidez eskuragarri (inplementazioaren arabera) HTTP/HTTPS bidez. Webhook-ak, oro har, HTTP dei-itzulera pertsonalizatuak dira. Gertaera batek abiarazten ditu normalean, esate baterako, kodea biltegi batera bidaltzen den edo blog batean argitaratzen den iruzkin bat. Gertaera bat gertatzen denean, jatorri guneak HTTP eskaera bidaltzen du webhook-erako zehaztutako URLra. Ondorioz, gertaerak gune batean ekintzak abiarazi ditzakezu beste batean (wiki). Iturburu-gunea objektuen biltegiratze bat den kasuan, gertaerek bere edukien aldaketa gisa jokatzen dute.

Automatizazio hori erabil daitekeen kasu errazen adibideak:

  1. Hodeiko beste biltegiratze batean objektu guztien kopiak sortzea. Fitxategiak gehitzen edo aldatzen diren bakoitzean kopiak berehala sortu behar dira.
  2. Fitxategi grafikoen miniatura sorta automatikoki sortzea, argazkiei ur-markak gehitzea eta beste irudi aldaketa batzuk.
  3. Dokumentu berriak iristeari buruzko jakinarazpena (adibidez, banatutako kontabilitate-zerbitzu batek txostenak kargatzen ditu hodeira, eta finantza-jarraipena txosten berriei buruzko jakinarazpenak jasotzen ditu, horiek egiaztatu eta aztertzen ditu).
  4. Kasu apur bat konplexuagoak dira, adibidez, Kubernetes-i eskaera bat sortzea, eta horrek beharrezko edukiontziak dituen pod bat sortzen du, ataza-parametroak pasatzen dizkio eta prozesatu ondoren edukiontzia kolapsatzen du.

Adibide gisa, 1. atazaren aldaera bat egingo dugu, Mail.ru Cloud Solutions (MCS) objektuen biltegiratze-ontziaren aldaketak AWS objektuen biltegian webhook-en bidez sinkronizatzen direnean. Benetako kargatutako kasu batean, lan asinkronoa eman beharko litzateke webhook-ak ilara batean erregistratuz, baina prestakuntza-zereginerako hori gabe inplementazioa egingo dugu.

Laneko eskema

Interakzio-protokoloa xehetasunez deskribatzen da S3 webhook-en gida MCS-n. Lan eskemak elementu hauek ditu:

  • Argitalpen zerbitzua, S3 biltegiratze aldean dagoena eta HTTP eskaerak argitaratzen ditu webnhook abiarazten denean.
  • Webhook jasotzeko zerbitzaria, HTTP argitalpen zerbitzuaren eskaerak entzuten dituena eta ekintza egokiak egiten dituena. Zerbitzaria edozein hizkuntzatan idatz daiteke; gure adibidean, zerbitzaria Go-n idatziko dugu.

Webhook-ak S3 APIan ezartzearen ezaugarri berezi bat webhook jasotzeko zerbitzaria argitalpen-zerbitzuan erregistratzea da. Bereziki, webhook jasotzeko zerbitzariak argitalpen zerbitzuko mezuetarako harpidetza berretsi behar du (beste webhook inplementazio batzuetan, normalean ez da harpidetzaren berrespena behar).

Horren arabera, webhook jasotzeko zerbitzariak bi eragiketa nagusi onartu behar ditu:

  • argitalpen-zerbitzuak erregistroa berresteko eskaerari erantzun,
  • sarrerako gertaerak prozesatu.

Webhook jasotzeko zerbitzari bat instalatzea

Webhook jasotzeko zerbitzaria exekutatzeko, Linux zerbitzari bat behar duzu. Artikulu honetan, adibide gisa, MCSn zabaltzen dugun instantzia birtual bat erabiltzen dugu.

Instalatu dezagun beharrezko softwarea eta abi dezagun webhook jasotzeko zerbitzaria.

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

Klonatu karpeta webhook jasotzeko zerbitzariarekin:

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.

Abiarazi dezagun zerbitzaria:

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

Harpidetu argitalpen zerbitzura

Zure webhook jasotzeko zerbitzaria erregistratu dezakezu API edo web interfazearen bidez. Erraztasunerako, web interfazearen bidez erregistratuko gara:

  1. Goazen kuboen atalera kontrol gelan.
  2. Joan webhook-ak konfiguratuko ditugun ontzira eta egin klik engranajean:

S3 objektuen biltegiratze Mail.ru Cloud Solutions-en webhooketan oinarritutako gertaeretan oinarritutako aplikazio baten adibidea

Joan Webhooks fitxara eta egin klik Gehitu:

S3 objektuen biltegiratze Mail.ru Cloud Solutions-en webhooketan oinarritutako gertaeretan oinarritutako aplikazio baten adibidea
Bete eremuak:

S3 objektuen biltegiratze Mail.ru Cloud Solutions-en webhooketan oinarritutako gertaeretan oinarritutako aplikazio baten adibidea

ID β€” webhook-aren izena.

Gertaera - zein gertakari transmititu. Fitxategiekin lan egitean gertatzen diren gertaera guztien transmisioa ezarri dugu (gehitzea eta ezabatzea).

URL β€” zerbitzariaren helbidea jasotzen duen webhook.

Iragazki-aurrizkia/atzizkia webhook-ak sortzeko aukera ematen duen iragazkia da, izenak arau batzuekin bat datozen objektuetarako soilik. Adibidez, webhook-ak .png luzapena duten fitxategiak soilik abiarazteko, in Iragazki atzizkia "png" idatzi behar duzu.

Gaur egun, 80 eta 443 atakak soilik onartzen dira webhook jasotzeko zerbitzarian sartzeko.

Egin dezagun klik Gehitu amua eta honako hauek ikusiko ditugu:

S3 objektuen biltegiratze Mail.ru Cloud Solutions-en webhooketan oinarritutako gertaeretan oinarritutako aplikazio baten adibidea
Hook gehitu zuen.

Webhook jasotzeko zerbitzariak bere erregistroetan erakusten du hook erregistratzeko prozesuaren aurrerapena:

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

Izen-ematea amaitu da. Hurrengo atalean, webhook jasotzeko zerbitzariaren funtzionamendu-algoritmoa zehatzago aztertuko dugu.

Webhook jasotzeko zerbitzariaren deskribapena

Gure adibidean, zerbitzaria Go-n idatzita dago. Ikus ditzagun bere funtzionamenduaren oinarrizko printzipioak.

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

Kontuan izan funtzio nagusiak:

  • Ping() - URL/ping bidez erantzuten duen ibilbidea, bizitasun-zunda baten ezarpen errazena.
  • Webhook() - bide nagusia, URL/webhook kudeatzailea:
    • argitalpen-zerbitzuan erregistratzea berresten du (joan Harpidetza Berrespen funtziora),
    • sarrerako webhook-ak prozesatzen ditu (Gorecords funtzioa).
  • HmacSha256 eta HmacSha256hex funtzioak HMAC-SHA256 eta HMAC-SHA256 enkriptazio-algoritmoen inplementazioak dira, sinadura kalkulatzeko zenbaki hamaseitarren kate gisa irteerarekin.
  • main funtzio nagusia da, komando-lerroko parametroak prozesatzen ditu eta URL kudeatzaileak erregistratzen ditu.

Zerbitzariak onartutako komando-lerroko parametroak:

  • -port zerbitzariak entzungo duen ataka da.
  • -address - zerbitzariak entzungo duen IP helbidea.
  • -script kanpoko programa bat da, sarrerako kako bakoitzerako deitzen dena.

Ikus ditzagun funtzio batzuk gertutik:

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

}

Funtzio honek erregistroa berresteko eskaera edo webhook bat iritsi den zehazten du. Honen arabera dokumentazioa, erregistroa baieztatzen bada, Json egitura hau jasotzen da Post eskaeran:

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

Galdera honi erantzuna eman behar zaio:

content-type: application/json

{"signature":Β«ea3fce4bb15c6de4fec365d36bcebbc34ccddf54616d5ca12e1972f82b6d37afΒ»}

Sinadura honela kalkulatzen den:

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

Webhook bat iristen bada, Post eskaeraren egitura honelakoa izango da:

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

Horren arabera, eskaeraren arabera, datuak nola prozesatu ulertu behar duzu. Adierazle gisa sarrera aukeratu dut "Type":"SubscriptionConfirmation", harpidetza berresteko eskaeran dagoenez eta webhook-ean ez dagoelako. POST eskaeran sarrera honen presentzia/absentziaren arabera, programaren exekuzio gehiago funtziora doa. SubscriptionConfirmation, edo funtzioan sartu GotRecords.

Ez dugu Harpidetza Baieztapen funtzioa zehatz-mehatz kontuan hartuko; atalean ezarritako printzipioen arabera ezartzen da dokumentazioa. Funtzio honen iturburu-kodea hemen ikus dezakezu proiektuko git biltegiak.

GotRecords funtzioak sarrerako eskaera bat analizatzen du eta Record objektu bakoitzeko kanpoko script bat deitzen du (haren izena -script parametroan pasatu zen) parametro hauekin:

  • kuboaren izena
  • objektuaren gakoa
  • ekintza:
    • kopiatu - jatorrizko eskaeran EventName = ObjectCreated | JarriObject | JarriObjectCopy
    • ezabatu - jatorrizko eskaeran EventName = ObjectRemoved | EzabatuObject

Horrela, amu bat Post eskaera batekin iristen bada, azaldu bezala arriba,ru, eta -script=script.sh parametroa, script-a honela deituko da:

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

Ulertu behar da webhook jasotzeko zerbitzari hau ez dela produkzio soluzio osoa, inplementazio posible baten adibide sinplifikatua baizik.

Lanaren adibidea

Sinkroniza ditzagun fitxategiak MCS-ko ontzi nagusitik AWS-ko babeskopia-ontzira. Kubo nagusia myfiles-ash deitzen da, babeskopia myfiles-backup (AWS-en kuboaren konfigurazioa artikulu honen esparrutik kanpo dago). Horren arabera, fitxategi bat kubo nagusian jartzen denean, haren kopia babeskopian agertu behar da, eta nagusitik ezabatzen denean, babeskopian ezabatu behar da.

Kuboekin lan egingo dugu awscli utilitatea erabiliz, MCS hodeiko biltegiratzearekin eta AWS hodeiko biltegiarekin bateragarria dena.

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

Konfigura dezagun S3 MCS APIrako sarbidea:

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]:

Konfigura dezagun AWS S3 APIrako sarbidea:

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]:

Ikus ditzagun sarbideak:

AWSra:

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

MCSrako, komandoa exekutatzean β€”endpoint-url gehitu behar duzu:

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

Sartu.

Orain idatz dezagun sarrerako amua prozesatzeko script bat, deitu dezagun 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

Abiarazi dezagun zerbitzaria:

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

Ea nola funtzionatzen duen. bidez MCS web interfazea gehitu test.txt fitxategia myfiles-ash ontzira. Kontsolaren erregistroek webhook zerbitzariari eskaera egin diotela erakusten dute:

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

Egiaztatu dezagun myfiles-backup ontziaren edukia AWS-n:

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

Orain, web interfazearen bidez, myfiles-ash ontzitik fitxategia ezabatuko dugu.

Zerbitzariaren erregistroak:

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

Kuboaren edukia:

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

Fitxategia ezabatu da, arazoa konpondu da.

Ondorioa eta ToDo

Artikulu honetan erabilitako kode guztia da nire biltegian. Webhook-ak erregistratzeko scripten adibideak eta sinadurak zenbatzeko adibideak ere badaude.

Kode hau zure jardueretan S3 webhook-ak nola erabil ditzakezun erakusteko adibide bat baino ez da. Hasieran esan dudan bezala, produkzioan zerbitzari bat erabiltzeko asmoa baduzu, gutxienez zerbitzaria berridatzi behar duzu lan asinkronorako: erregistratu sarrerako webhook-ak ilara batean (RabbitMQ edo NATS), eta hortik analizatu eta prozesatu. langileen aplikazioekin. Bestela, webhook-ak masiboki iristen direnean, baliteke zereginak burutzeko zerbitzariaren baliabide falta aurkitzea. Ilarak egoteak zerbitzaria eta langileak banatzeko aukera ematen du, baita hutsegiteen kasuan zereginak errepikatzeko arazoak konpontzeko ere. Era berean, komenigarria da erregistroa zehatzago eta estandarizatuago batera aldatzea.

Good Luck!

Gaiari buruzko irakurketa gehiago:

Iturria: www.habr.com

Gehitu iruzkin berria