Έτσι συλλέγετε μετρήσεις. Οπως είμαστε. Συλλέγουμε επίσης μετρήσεις. Φυσικά, απαραίτητο για τις επιχειρήσεις. Σήμερα θα μιλήσουμε για τον πρώτο σύνδεσμο του συστήματος παρακολούθησης - έναν διακομιστή συγκέντρωσης συμβατό με statsd
Από προηγούμενα άρθρα μας (
Αξίωση 1. Ο Github, ο προγραμματιστής του έργου, σταμάτησε να το υποστηρίζει: δημοσιεύει ενημερώσεις κώδικα και διορθώσεις, αποδέχεται τα δικά μας και (όχι μόνο τα δικά μας) PR. Τους τελευταίους μήνες (κάπου από τον Φεβρουάριο-Μάρτιο του 2018), η δραστηριότητα επανήλθε, αλλά πριν από αυτό υπήρχαν σχεδόν 2 χρόνια απόλυτης ηρεμίας. Επιπλέον, το έργο βρίσκεται σε εξέλιξη
Αξίωση 2. Ακρίβεια υπολογισμών. Το Brubeck συλλέγει συνολικά 65536 τιμές για συνάθροιση. Στην περίπτωσή μας, για ορισμένες μετρήσεις, κατά τη διάρκεια της περιόδου συγκέντρωσης (30 δευτερόλεπτα), μπορεί να φτάσουν πολύ περισσότερες τιμές (1 στην κορυφή). Ως αποτέλεσμα αυτής της δειγματοληψίας, οι μέγιστες και ελάχιστες τιμές φαίνονται άχρηστες. Για παράδειγμα, όπως αυτό:
Οπως ήταν
Πώς έπρεπε να ήταν
Για τον ίδιο λόγο, τα ποσά γενικά υπολογίζονται λανθασμένα. Προσθέστε εδώ ένα σφάλμα με υπερχείλιση float 32-bit, το οποίο γενικά στέλνει τον διακομιστή σε segfault όταν λαμβάνει μια φαινομενικά αθώα μέτρηση και όλα γίνονται υπέροχα. Το σφάλμα, παρεμπιπτόντως, δεν έχει διορθωθεί.
Και, τελικά, Αξίωση X. Τη στιγμή που γράφονται αυτές οι γραμμές, είμαστε έτοιμοι να το παρουσιάσουμε και στις 14 περισσότερο ή λιγότερο λειτουργικές υλοποιήσεις statsd που μπορέσαμε να βρούμε. Ας φανταστούμε ότι κάποια μεμονωμένη υποδομή έχει μεγαλώσει τόσο πολύ που η αποδοχή 4 εκατομμυρίων MPS δεν αρκεί πλέον. Ή ακόμα κι αν δεν έχει αυξηθεί ακόμα, αλλά οι μετρήσεις είναι ήδη τόσο σημαντικές για εσάς που ακόμη και σύντομες, 2-3 λεπτά πτώσεις στα γραφήματα μπορεί να γίνουν ήδη κρίσιμες και να προκαλέσουν κρίσεις ανυπέρβλητης κατάθλιψης μεταξύ των διευθυντών. Δεδομένου ότι η θεραπεία της κατάθλιψης είναι μια άχαρη εργασία, απαιτούνται τεχνικές λύσεις.
Πρώτον, ανοχή σφαλμάτων, ώστε ένα ξαφνικό πρόβλημα στον διακομιστή να μην προκαλέσει ψυχιατρική αποκάλυψη ζόμπι στο γραφείο. Δεύτερον, κλιμάκωση για να μπορέσετε να δεχτείτε περισσότερα από 4 εκατομμύρια MPS, χωρίς να σκάβετε βαθιά στη στοίβα του δικτύου Linux και να μεγαλώνετε ήρεμα «σε πλάτος» στο απαιτούμενο μέγεθος.
Επειδή είχαμε χώρο για κλιμάκωση, αποφασίσαμε να ξεκινήσουμε με την ανοχή σφαλμάτων. "ΣΧΕΤΙΚΑ ΜΕ! Ανοχή σε σφάλματα! Είναι απλό, μπορούμε να το κάνουμε», σκεφτήκαμε και ξεκινήσαμε 2 διακομιστές, σηκώνοντας ένα αντίγραφο του brubeck στον καθένα. Για να γίνει αυτό, έπρεπε να αντιγράψουμε την κυκλοφορία με μετρήσεις και στους δύο διακομιστές και ακόμη και να γράψουμε για αυτό
Εάν σκεφτείτε λίγο το πρόβλημα και ταυτόχρονα σκάβετε χιόνι με ένα φτυάρι, τότε μπορεί να σας έρθει στο μυαλό η εξής προφανής ιδέα: χρειάζεστε ένα statsd που μπορεί να λειτουργήσει σε κατανεμημένη λειτουργία. Δηλαδή, ένα που υλοποιεί συγχρονισμό μεταξύ κόμβων σε χρόνο και μετρήσεις. «Φυσικά, μια τέτοια λύση μάλλον υπάρχει ήδη», είπαμε και πήγαμε στο Google…. Και δεν βρήκαν τίποτα. Αφού διαβάσετε την τεκμηρίωση για διαφορετικά statsd (
Και μετά θυμηθήκαμε το «παιχνίδι» statsd - bioyino, το οποίο γράφτηκε στο Just for Fun hackathon (το όνομα του έργου δημιουργήθηκε από το σενάριο πριν από την έναρξη του hackathon) και συνειδητοποιήσαμε ότι χρειαζόμασταν επειγόντως το δικό μας statsd. Για τι?
- επειδή υπάρχουν πολύ λίγοι κλώνοι statsd στον κόσμο,
- επειδή είναι δυνατή η παροχή της επιθυμητής ή κοντά στην επιθυμητή ανοχή και επεκτασιμότητα σφαλμάτων (συμπεριλαμβανομένου του συγχρονισμού συγκεντρωτικών μετρήσεων μεταξύ των διακομιστών και της επίλυσης του προβλήματος της αποστολής διενέξεων),
- επειδή είναι δυνατός ο υπολογισμός των μετρήσεων με μεγαλύτερη ακρίβεια από ό,τι το Brubeck,
- γιατί μπορείτε να συλλέξετε μόνοι σας πιο λεπτομερή στατιστικά στοιχεία, τα οποία πρακτικά δεν μας παρείχε το μπρούμπεκ,
- επειδή είχα την ευκαιρία να προγραμματίσω τη δική μου εφαρμογή εργαστηρίου κατανεμημένης κλίμακας υπεραπόδοσης, η οποία δεν θα επαναλάβει πλήρως την αρχιτεκτονική ενός άλλου παρόμοιου hyperfor... καλά, αυτό είναι.
Σε τι να γράψω; Φυσικά, στο Rust. Γιατί;
- επειδή υπήρχε ήδη μια πρωτότυπη λύση,
- επειδή ο συγγραφέας του άρθρου γνώριζε ήδη τον Rust εκείνη την εποχή και ήθελε να γράψει κάτι σε αυτό για παραγωγή με την ευκαιρία να το βάλει σε ανοιχτό κώδικα,
- επειδή οι γλώσσες με GC δεν είναι κατάλληλες για εμάς λόγω της φύσης της λαμβανόμενης κίνησης (σχεδόν σε πραγματικό χρόνο) και οι παύσεις GC είναι πρακτικά απαράδεκτες,
- γιατί χρειάζεστε μέγιστη απόδοση συγκρίσιμη με το C
- γιατί το Rust μάς παρέχει άφοβο συγχρονισμό και αν ξεκινούσαμε να το γράφουμε σε C/C++, θα είχαμε ακόμα περισσότερα τρωτά σημεία, υπερχείλιση buffer, συνθήκες αγώνα και άλλες τρομακτικές λέξεις από το brubeck.
Υπήρχε επίσης ένα επιχείρημα κατά του Rust. Η εταιρεία δεν είχε εμπειρία στη δημιουργία έργων στο Rust και τώρα δεν σκοπεύουμε να το χρησιμοποιήσουμε στο κύριο έργο. Ως εκ τούτου, υπήρχαν σοβαροί φόβοι ότι τίποτα δεν θα λειτουργούσε, αλλά αποφασίσαμε να πάρουμε μια ευκαιρία και προσπαθήσαμε.
Η ώρα πέρασε...
Τελικά, μετά από αρκετές αποτυχημένες προσπάθειες, η πρώτη λειτουργική έκδοση ήταν έτοιμη. Τι συνέβη? Αυτό έγινε.
Κάθε κόμβος λαμβάνει το δικό του σύνολο μετρήσεων και τις συσσωρεύει και δεν συγκεντρώνει μετρήσεις για εκείνους τους τύπους όπου απαιτείται το πλήρες σύνολο τους για την τελική συγκέντρωση. Οι κόμβοι συνδέονται μεταξύ τους με κάποιο είδος κατανεμημένου πρωτοκόλλου κλειδώματος, το οποίο σας επιτρέπει να επιλέξετε μεταξύ τους το μόνο (εδώ κλάψαμε) που αξίζει να στείλετε μετρήσεις στο Great One. Αυτό το πρόβλημα επιλύεται αυτήν τη στιγμή από
Τα πακέτα UDP με μετρήσεις δεν είναι ισορροπημένα μεταξύ των κόμβων στον εξοπλισμό δικτύου μέσω ενός απλού Round Robin. Φυσικά, το υλικό του δικτύου δεν αναλύει τα περιεχόμενα των πακέτων και επομένως μπορεί να τραβήξει πολύ περισσότερα από 4 εκατομμύρια πακέτα ανά δευτερόλεπτο, για να μην αναφέρουμε μετρήσεις για τις οποίες δεν γνωρίζει απολύτως τίποτα. Αν λάβουμε υπόψη ότι οι μετρήσεις δεν έρχονται μία κάθε φορά σε κάθε πακέτο, τότε δεν προβλέπουμε προβλήματα απόδοσης σε αυτό το μέρος. Εάν ένας διακομιστής διακοπεί, η συσκευή δικτύου γρήγορα (εντός 1-2 δευτερολέπτων) εντοπίζει αυτό το γεγονός και αφαιρεί από την περιστροφή τον διακομιστή που έχει καταρρεύσει. Ως αποτέλεσμα αυτού, οι παθητικοί κόμβοι (δηλαδή, οι μη αρχηγοί) μπορούν να ενεργοποιηθούν και να απενεργοποιηθούν πρακτικά χωρίς να παρατηρήσετε μειώσεις στα γραφήματα. Το μέγιστο που χάνουμε είναι μέρος των μετρήσεων που μπήκαν το τελευταίο δευτερόλεπτο. Μια ξαφνική απώλεια/τερματισμός/αλλαγή ενός ηγέτη θα εξακολουθεί να δημιουργεί μια μικρή ανωμαλία (το διάστημα των 30 δευτερολέπτων εξακολουθεί να είναι εκτός συγχρονισμού), αλλά εάν υπάρχει επικοινωνία μεταξύ των κόμβων, αυτά τα προβλήματα μπορούν να ελαχιστοποιηθούν, για παράδειγμα, στέλνοντας πακέτα συγχρονισμού .
Λίγα λόγια για την εσωτερική δομή. Η εφαρμογή είναι, φυσικά, πολυνηματική, αλλά η αρχιτεκτονική νήματος είναι διαφορετική από αυτή που χρησιμοποιείται στο brubeck. Τα νήματα στο μπρουμπέκ είναι τα ίδια - καθένα από αυτά είναι υπεύθυνο τόσο για τη συλλογή πληροφοριών όσο και για τη συγκέντρωση. Στο bioyino, οι εργαζόμενοι χωρίζονται σε δύο ομάδες: σε αυτούς που είναι υπεύθυνοι για το δίκτυο και σε αυτούς που είναι υπεύθυνοι για τη συγκέντρωση. Αυτή η διαίρεση σάς επιτρέπει να διαχειρίζεστε πιο ευέλικτα την εφαρμογή ανάλογα με τον τύπο των μετρήσεων: όπου απαιτείται εντατική συγκέντρωση, μπορείτε να προσθέσετε aggregators, όπου υπάρχει μεγάλη κίνηση δικτύου, μπορείτε να προσθέσετε τον αριθμό των ροών δικτύου. Αυτή τη στιγμή, στους διακομιστές μας εργαζόμαστε σε 8 ροές δικτύου και 4 αθροίσεις.
Το κομμάτι της καταμέτρησης (υπεύθυνο για τη συγκέντρωση) είναι αρκετά βαρετό. Τα buffer που πληρούνται από ροές δικτύου κατανέμονται μεταξύ των ροών καταμέτρησης, όπου στη συνέχεια αναλύονται και συγκεντρώνονται. Κατόπιν αιτήματος, δίνονται μετρήσεις για αποστολή σε άλλους κόμβους. Όλα αυτά, συμπεριλαμβανομένης της αποστολής δεδομένων μεταξύ κόμβων και της εργασίας με το Consul, εκτελούνται ασύγχρονα, εκτελώντας το πλαίσιο
Πολύ περισσότερα προβλήματα κατά την ανάπτυξη προκλήθηκαν από το τμήμα δικτύου που είναι υπεύθυνο για τη λήψη μετρήσεων. Ο κύριος στόχος του διαχωρισμού των ροών δικτύου σε ξεχωριστές οντότητες ήταν η επιθυμία να μειωθεί ο χρόνος που ξοδεύει μια ροή όχι για να διαβάσετε δεδομένα από την πρίζα. Οι επιλογές που χρησιμοποιούν ασύγχρονο UDP και κανονικό recvmsg εξαφανίστηκαν γρήγορα: η πρώτη καταναλώνει πάρα πολύ χώρο CPU για την επεξεργασία συμβάντων, η δεύτερη απαιτεί πάρα πολλούς διακόπτες περιβάλλοντος. Επομένως χρησιμοποιείται τώρα
Σημείωση
Στις προεπιλεγμένες ρυθμίσεις, το μέγεθος του buffer έχει οριστεί να είναι αρκετά μεγάλο. Εάν αποφασίσετε ξαφνικά να δοκιμάσετε μόνοι σας τον διακομιστή, μπορεί να αντιμετωπίσετε το γεγονός ότι μετά την αποστολή ενός μικρού αριθμού μετρήσεων, δεν θα φτάσουν στο Graphite, παραμένοντας στο buffer ροής δικτύου. Για να εργαστείτε με μικρό αριθμό μετρήσεων, πρέπει να ορίσετε το bufsize και το task-queue-size σε μικρότερες τιμές στη διαμόρφωση.
Τέλος, μερικά charts για τους λάτρεις των chart.
Στατιστικά στοιχεία για τον αριθμό των εισερχόμενων μετρήσεων για κάθε διακομιστή: περισσότερα από 2 εκατομμύρια MPS.
Απενεργοποίηση ενός από τους κόμβους και αναδιανομή εισερχόμενων μετρήσεων.
Στατιστικά στοιχεία για τις εξερχόμενες μετρήσεις: μόνο ένας κόμβος στέλνει πάντα - το αφεντικό της επιδρομής.
Στατιστικά της λειτουργίας κάθε κόμβου, λαμβάνοντας υπόψη σφάλματα σε διάφορες μονάδες συστήματος.
Λεπτομέρειες των εισερχόμενων μετρήσεων (τα ονόματα των μετρήσεων είναι κρυφά).
Τι σκοπεύουμε να κάνουμε με όλα αυτά στη συνέχεια; Φυσικά, γράψε κώδικα, φτου...! Το έργο είχε αρχικά προγραμματιστεί να είναι ανοιχτού κώδικα και θα παραμείνει έτσι καθ' όλη τη διάρκεια της ζωής του. Τα άμεσα σχέδιά μας περιλαμβάνουν τη μετάβαση στη δική μας έκδοση του Raft, την αλλαγή του ομότιμου πρωτοκόλλου σε μια πιο φορητή, την εισαγωγή πρόσθετων εσωτερικών στατιστικών, νέων τύπων μετρήσεων, διορθώσεις σφαλμάτων και άλλες βελτιώσεις.
Φυσικά, όλοι είναι ευπρόσδεκτοι να βοηθήσουν στην ανάπτυξη του έργου: δημιουργήστε PR, Θέματα, εάν είναι δυνατόν θα απαντήσουμε, θα βελτιώσουμε κ.λπ.
Με αυτό που λέγεται, αυτά είναι όλα παιδιά, αγοράστε τους ελέφαντες μας!
Πηγή: www.habr.com