ProHoster > Blog > διαχείριση > Ένα παράδειγμα μιας εφαρμογής που βασίζεται σε συμβάντα που βασίζεται σε webhook στην αποθήκευση αντικειμένων S3 Mail.ru Cloud Solutions
Ένα παράδειγμα μιας εφαρμογής που βασίζεται σε συμβάντα που βασίζεται σε webhook στην αποθήκευση αντικειμένων S3 Mail.ru Cloud Solutions
Η αρχιτεκτονική με γνώμονα τα συμβάντα αυξάνει την αποδοτικότητα κόστους των πόρων που χρησιμοποιούνται επειδή χρησιμοποιούνται μόνο τη στιγμή που χρειάζονται. Υπάρχουν πολλές επιλογές για το πώς να το εφαρμόσετε και να μην δημιουργήσετε πρόσθετες οντότητες cloud ως εφαρμογές εργασίας. Και σήμερα δεν θα μιλήσω για FaaS, αλλά για webhooks. Θα δείξω ένα παράδειγμα εκμάθησης χειρισμού συμβάντων με χρήση webhook αποθήκευσης αντικειμένων.
Λίγα λόγια για την αποθήκευση αντικειμένων και τα webhook. Η αποθήκευση αντικειμένων σάς επιτρέπει να αποθηκεύετε οποιαδήποτε δεδομένα στο cloud με τη μορφή αντικειμένων, προσβάσιμα μέσω S3 ή άλλου API (ανάλογα με την υλοποίηση) μέσω HTTP/HTTPS. Τα webhook είναι γενικά προσαρμοσμένες επανακλήσεις HTTP. Συνήθως ενεργοποιούνται από ένα συμβάν, όπως η ώθηση κώδικα σε ένα αποθετήριο ή ένα σχόλιο που δημοσιεύεται σε ένα ιστολόγιο. Όταν συμβαίνει ένα συμβάν, ο ιστότοπος προέλευσης στέλνει ένα αίτημα HTTP στη διεύθυνση URL που έχει καθοριστεί για το webhook. Ως αποτέλεσμα, μπορείτε να κάνετε τα συμβάντα σε έναν ιστότοπο να ενεργοποιούν ενέργειες σε έναν άλλο (wiki). Στην περίπτωση που ο ιστότοπος προέλευσης είναι χώρος αποθήκευσης αντικειμένων, τα συμβάντα λειτουργούν ως αλλαγές στο περιεχόμενό του.
Παραδείγματα απλών περιπτώσεων κατά τις οποίες μπορεί να χρησιμοποιηθεί τέτοιος αυτοματισμός:
Δημιουργία αντιγράφων όλων των αντικειμένων σε άλλο χώρο αποθήκευσης cloud. Αντίγραφα πρέπει να δημιουργούνται εν κινήσει κάθε φορά που προστίθενται ή αλλάζουν αρχεία.
Αυτόματη δημιουργία μιας σειράς μικρογραφιών αρχείων γραφικών, προσθήκη υδατογραφημάτων σε φωτογραφίες και άλλες τροποποιήσεις εικόνας.
Ειδοποίηση σχετικά με την άφιξη νέων εγγράφων (για παράδειγμα, μια κατανεμημένη λογιστική υπηρεσία μεταφορτώνει αναφορές στο cloud και η οικονομική παρακολούθηση λαμβάνει ειδοποιήσεις για νέες αναφορές, τις ελέγχει και τις αναλύει).
Ελαφρώς πιο περίπλοκες περιπτώσεις περιλαμβάνουν, για παράδειγμα, τη δημιουργία ενός αιτήματος στο Kubernetes, το οποίο δημιουργεί ένα pod με τα απαραίτητα κοντέινερ, του μεταβιβάζει παραμέτρους εργασίας και μετά την επεξεργασία συμπτύσσει το κοντέινερ.
Για παράδειγμα, θα κάνουμε μια παραλλαγή της εργασίας 1, όταν οι αλλαγές στον κάδο αποθήκευσης αντικειμένων Mail.ru Cloud Solutions (MCS) συγχρονίζονται στην αποθήκευση αντικειμένων AWS χρησιμοποιώντας webhook. Σε μια πραγματική φορτωμένη περίπτωση, η ασύγχρονη εργασία θα πρέπει να παρέχεται με την εγγραφή webhooks σε μια ουρά, αλλά για την εκπαιδευτική εργασία θα κάνουμε την υλοποίηση χωρίς αυτό.
Σχέδιο εργασίας
Το πρωτόκολλο αλληλεπίδρασης περιγράφεται λεπτομερώς στο Οδηγός για τα webhook S3 στο MCS. Το σχήμα εργασίας περιλαμβάνει τα ακόλουθα στοιχεία:
Εκδοτική υπηρεσία, το οποίο βρίσκεται στην πλευρά αποθήκευσης S3 και δημοσιεύει αιτήματα HTTP όταν ενεργοποιείται το webnhook.
Διακομιστής λήψης Webhook, το οποίο ακούει αιτήματα από την υπηρεσία δημοσίευσης HTTP και εκτελεί τις κατάλληλες ενέργειες. Ο διακομιστής μπορεί να γραφτεί σε οποιαδήποτε γλώσσα· στο παράδειγμά μας, θα γράψουμε τον διακομιστή στο Go.
Ένα ιδιαίτερο χαρακτηριστικό της υλοποίησης webhook στο S3 API είναι η εγγραφή του διακομιστή λήψης webhook στην υπηρεσία δημοσίευσης. Ειδικότερα, ο διακομιστής λήψης webhook πρέπει να επιβεβαιώσει τη συνδρομή σε μηνύματα από την υπηρεσία δημοσίευσης (σε άλλες εφαρμογές webhook, συνήθως δεν απαιτείται επιβεβαίωση συνδρομής).
Συνεπώς, ο διακομιστής λήψης webhook πρέπει να υποστηρίζει δύο κύριες λειτουργίες:
απαντήστε στο αίτημα της υπηρεσίας έκδοσης για επιβεβαίωση εγγραφής,
επεξεργασία εισερχόμενων συμβάντων.
Εγκατάσταση διακομιστή λήψης webhook
Για να εκτελέσετε τον διακομιστή λήψης webhook, χρειάζεστε έναν διακομιστή Linux. Σε αυτό το άρθρο, για παράδειγμα, χρησιμοποιούμε μια εικονική παρουσία που αναπτύσσουμε στο MCS.
Ας εγκαταστήσουμε το απαραίτητο λογισμικό και ας ξεκινήσουμε τον διακομιστή λήψης webhook.
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) ...
Κλωνοποιήστε το φάκελο με τον διακομιστή λήψης webhook:
Μεταβείτε στον κάδο για τον οποίο θα διαμορφώσουμε τα webhook και κάντε κλικ στο γρανάζι:
Μεταβείτε στην καρτέλα Webhooks και κάντε κλικ στην Προσθήκη:
Συμπληρώστε τα πεδία:
ID — το όνομα του webhook.
Συμβάν - ποια γεγονότα να μεταδοθούν. Έχουμε ορίσει τη μετάδοση όλων των συμβάντων που συμβαίνουν κατά την εργασία με αρχεία (προσθήκη και διαγραφή).
URL — διεύθυνση διακομιστή λήψης webhook.
Το πρόθεμα/το επίθημα φίλτρου είναι ένα φίλτρο που σας επιτρέπει να δημιουργείτε webhook μόνο για αντικείμενα των οποίων τα ονόματα ταιριάζουν με ορισμένους κανόνες. Για παράδειγμα, για να ενεργοποιεί το webhook μόνο αρχεία με επέκταση .png, in Επίθημα φίλτρου πρέπει να γράψετε "png".
Προς το παρόν, υποστηρίζονται μόνο οι θύρες 80 και 443 για πρόσβαση στον διακομιστή λήψης webhook.
Ας κάνουμε κλικ Προσθέστε γάντζο και θα δούμε τα εξής:
Ο Χουκ προστέθηκε.
Ο διακομιστής λήψης webhook εμφανίζει στα αρχεία καταγραφής του την πρόοδο της διαδικασίας εγγραφής του άγκιστρου:
επιβεβαιώνει την εγγραφή στην υπηρεσία δημοσίευσης (μεταβείτε στη συνάρτηση Επιβεβαίωση Συνδρομής),
επεξεργάζεται τα εισερχόμενα webhook (συνάρτηση Gorecords).
Οι συναρτήσεις HmacSha256 και HmacSha256hex είναι υλοποιήσεις των αλγορίθμων κρυπτογράφησης HMAC-SHA256 και HMAC-SHA256 με έξοδο ως συμβολοσειρά δεκαεξαδικών αριθμών για τον υπολογισμό της υπογραφής.
main είναι η κύρια συνάρτηση, επεξεργάζεται τις παραμέτρους της γραμμής εντολών και καταχωρεί τους χειριστές URL.
Παράμετροι γραμμής εντολών αποδεκτές από τον διακομιστή:
-port είναι η θύρα στην οποία θα ακούσει ο διακομιστής.
-διεύθυνση - διεύθυνση IP που θα ακούσει ο διακομιστής.
-Το script είναι ένα εξωτερικό πρόγραμμα που καλείται για κάθε εισερχόμενο άγκιστρο.
Ας ρίξουμε μια πιο προσεκτική ματιά σε μερικές από τις λειτουργίες:
//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)
}
}
Αυτή η λειτουργία καθορίζει εάν έχει φτάσει ένα αίτημα για επιβεβαίωση εγγραφής ή ένα webhook. Όπως προκύπτει από τεκμηρίωση, εάν επιβεβαιωθεί η εγγραφή, λαμβάνεται η ακόλουθη δομή Json στο αίτημα Post:
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»
}
Αντίστοιχα, ανάλογα με το αίτημα, πρέπει να κατανοήσετε τον τρόπο επεξεργασίας των δεδομένων. Επέλεξα την καταχώρηση ως δείκτη "Type":"SubscriptionConfirmation", αφού υπάρχει στο αίτημα επιβεβαίωσης συνδρομής και δεν υπάρχει στο webhook. Με βάση την παρουσία/απουσία αυτής της καταχώρησης στο αίτημα POST, η περαιτέρω εκτέλεση του προγράμματος πηγαίνει είτε στη συνάρτηση SubscriptionConfirmation, ή στη συνάρτηση GotRecords.
Δεν θα εξετάσουμε λεπτομερώς τη λειτουργία SubscriptionConfirmation· εφαρμόζεται σύμφωνα με τις αρχές που ορίζονται στο τεκμηρίωση. Μπορείτε να δείτε τον πηγαίο κώδικα για αυτήν τη λειτουργία στη διεύθυνση αποθετήρια project git.
Η συνάρτηση GotRecords αναλύει ένα εισερχόμενο αίτημα και για κάθε αντικείμενο Εγγραφής καλεί ένα εξωτερικό σενάριο (το όνομα του οποίου μεταβιβάστηκε στην παράμετρο -script) με τις παραμέτρους:
όνομα κάδου
κλειδί αντικειμένου
δράση:
αντίγραφο - εάν στο αρχικό αίτημα Όνομα συμβάντος = ObjectCreated | PutObject | PutObjectCopy
Έτσι, εάν φτάσει ένα άγκιστρο με αίτημα Post, όπως περιγράφεται πάνω από, και την παράμετρο -script=script.sh τότε το σενάριο θα καλείται ως εξής:
script.sh bucketA some-file-to-bucket copy
Πρέπει να γίνει κατανοητό ότι αυτός ο διακομιστής λήψης webhook δεν είναι μια ολοκληρωμένη λύση παραγωγής, αλλά ένα απλοποιημένο παράδειγμα μιας πιθανής υλοποίησης.
Παράδειγμα εργασίας
Ας συγχρονίσουμε τα αρχεία από τον κύριο κάδο στο MCS στον κάδο αντιγράφων ασφαλείας στο AWS. Ο κύριος κάδος ονομάζεται myfiles-ash, ο αντίγραφος ασφαλείας ονομάζεται myfiles-backup (η διαμόρφωση του κάδου στο AWS είναι πέρα από το πεδίο εφαρμογής αυτού του άρθρου). Αντίστοιχα, όταν ένα αρχείο τοποθετείται στον κύριο κάδο, το αντίγραφό του θα πρέπει να εμφανίζεται στον εφεδρικό και όταν διαγράφεται από τον κύριο κάδο, θα πρέπει να διαγράφεται στον εφεδρικό.
Θα εργαστούμε με κουβάδες χρησιμοποιώντας το βοηθητικό πρόγραμμα awscli, το οποίο είναι συμβατό τόσο με την αποθήκευση cloud MCS όσο και με την αποθήκευση cloud 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) ...
Ας διαμορφώσουμε την πρόσβαση στο 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]:
Ας διαμορφώσουμε την πρόσβαση στο API AWS S3:
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]:
Ας ελέγξουμε τις προσβάσεις:
Προς AWS:
ubuntu@ubuntu-basic-1-2-10gb:~$ aws s3 ls --profile aws
2020-07-06 08:44:11 myfiles-backup
Για το MCS, κατά την εκτέλεση της εντολής πρέπει να προσθέσετε —endpoint-url:
Ας δούμε πώς λειτουργεί. Διά μέσου Διεπαφή ιστού MCS προσθέστε το αρχείο test.txt στον κάδο myfiles-ash. Τα αρχεία καταγραφής της κονσόλας δείχνουν ότι υποβλήθηκε ένα αίτημα στον διακομιστή webhook:
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
Ας ελέγξουμε τα περιεχόμενα του κάδου δημιουργίας αντιγράφων ασφαλείας myfiles στο AWS:
Τώρα, μέσω της διεπαφής web, θα διαγράψουμε το αρχείο από τον κάδο myfiles-ash.
Αρχεία καταγραφής διακομιστή:
2020/07/06 09:44:46 [POST] incoming HTTP request from
95.163.216.92:58224
delete: s3://myfiles-backup/test.txt
Περιεχόμενα κάδου:
ubuntu@ubuntu-basic-1-2-10gb:~/s3-webhook$ aws s3 --profile aws ls
myfiles-backup
ubuntu@ubuntu-basic-1-2-10gb:~$
Το αρχείο διαγράφεται, το πρόβλημα έχει λυθεί.
Συμπέρασμα και εργασίες
Όλος ο κώδικας που χρησιμοποιείται σε αυτό το άρθρο είναι στο αποθετήριο μου. Υπάρχουν επίσης παραδείγματα σεναρίων και παραδείγματα καταμέτρησης υπογραφών για την καταχώρηση webhook.
Αυτός ο κώδικας δεν είναι τίποτα άλλο από ένα παράδειγμα του πώς μπορείτε να χρησιμοποιήσετε τα webhook S3 στις δραστηριότητές σας. Όπως είπα στην αρχή, εάν σκοπεύετε να χρησιμοποιήσετε έναν τέτοιο διακομιστή στην παραγωγή, πρέπει τουλάχιστον να ξαναγράψετε τον διακομιστή για ασύγχρονη εργασία: να καταχωρήσετε τα εισερχόμενα webhook σε μια ουρά (RabbitMQ ή NATS) και από εκεί να τα αναλύσετε και να τα επεξεργαστείτε με αιτήσεις εργαζομένων. Διαφορετικά, όταν τα webhook φτάνουν μαζικά, μπορεί να αντιμετωπίσετε έλλειψη πόρων διακομιστή για την ολοκλήρωση εργασιών. Η παρουσία ουρών σάς επιτρέπει να διανέμετε τον διακομιστή και τους εργαζόμενους, καθώς και να επιλύετε προβλήματα με την επανάληψη εργασιών σε περίπτωση αποτυχίας. Συνιστάται επίσης να αλλάξετε την καταγραφή σε πιο λεπτομερή και πιο τυποποιημένη.