Jadi, Anda mengumpulkan metrik. Seperti kita. Kami juga mengumpulkan metrik. Tentu saja diperlukan untuk bisnis. Hari ini kita akan berbicara tentang tautan pertama dari sistem pemantauan kami - server agregasi yang kompatibel dengan statsd
Dari artikel kami sebelumnya (
Klaim 1. Github, pengembang proyek, berhenti mendukungnya: menerbitkan tambalan dan perbaikan, menerima PR kami dan (bukan hanya milik kami). Dalam beberapa bulan terakhir (sekitar Februari-Maret 2018), aktivitas telah kembali normal, namun sebelumnya hampir 2 tahun dalam keadaan tenang. Selain itu, proyek ini sedang dikembangkan
Klaim 2. Akurasi perhitungan. Brubeck mengumpulkan total 65536 nilai untuk agregasi. Dalam kasus kami, untuk beberapa metrik, selama periode agregasi (30 detik), lebih banyak nilai yang mungkin muncul (1 pada puncaknya). Akibat pengambilan sampel ini, nilai maksimum dan minimum tampak tidak berguna. Misalnya seperti ini:
Seperti itu
Bagaimana seharusnya
Untuk alasan yang sama, jumlah pada umumnya dihitung secara tidak benar. Tambahkan di sini bug dengan float overflow 32-bit, yang biasanya mengirim server ke segfault ketika menerima metrik yang tampaknya tidak berbahaya, dan semuanya menjadi baik-baik saja. Omong-omong, bug tersebut belum diperbaiki.
Dan, akhirnya, Klaim X. Pada saat penulisan, kami siap menyajikannya ke 14 implementasi statsd yang kurang lebih berfungsi yang dapat kami temukan. Bayangkan saja suatu infrastruktur telah berkembang pesat sehingga menerima 4 juta MPS saja tidak lagi cukup. Atau bahkan jika grafiknya belum berkembang, namun metriknya sudah sangat penting bagi Anda sehingga bahkan penurunan singkat selama 2-3 menit saja sudah bisa menjadi hal yang kritis dan menyebabkan depresi yang tidak dapat diatasi di kalangan manajer. Karena mengobati depresi adalah tugas tanpa pamrih, solusi teknis diperlukan.
Pertama, toleransi kesalahan, sehingga masalah mendadak di server tidak menyebabkan kiamat zombie psikiatris di kantor. Kedua, melakukan penskalaan agar dapat menerima lebih dari 4 juta MPS, tanpa menggali lebih dalam tumpukan jaringan Linux dan dengan tenang berkembang βsecara luasβ ke ukuran yang dibutuhkan.
Karena kami memiliki ruang untuk penskalaan, kami memutuskan untuk memulai dengan toleransi kesalahan. "TENTANG! Toleransi kesalahan! Sederhana saja, kita bisa melakukannya,β pikir kami dan meluncurkan 2 server, memunculkan salinan brubeck di masing-masing server. Untuk melakukan ini, kami harus menyalin lalu lintas dengan metrik ke kedua server dan bahkan menulis untuk ini
Jika Anda memikirkan sedikit tentang masalahnya dan pada saat yang sama menggali salju dengan sekop, gagasan yang jelas berikut ini mungkin muncul di benak Anda: Anda memerlukan statsd yang dapat bekerja dalam mode terdistribusi. Artinya, yang mengimplementasikan sinkronisasi antar node dalam waktu dan metrik. βTentu saja, solusi seperti itu mungkin sudah ada,β kata kami dan membuka Googleβ¦. Dan mereka tidak menemukan apa pun. Setelah melalui dokumentasi untuk statsd yang berbeda (
Dan kemudian kami teringat tentang statsd "mainan" - bioyino, yang ditulis di hackathon Just for Fun (nama proyek dihasilkan oleh skrip sebelum dimulainya hackathon) dan menyadari bahwa kami sangat membutuhkan statsd kami sendiri. Untuk apa?
- karena terlalu sedikit klon statsd di dunia,
- karena dimungkinkan untuk memberikan toleransi kesalahan dan skalabilitas yang diinginkan atau mendekati yang diinginkan (termasuk menyinkronkan metrik agregat antar server dan menyelesaikan masalah konflik pengiriman),
- karena metrik dapat dihitung dengan lebih akurat dibandingkan brubeck,
- karena Anda dapat mengumpulkan sendiri statistik yang lebih rinci, yang secara praktis tidak diberikan oleh brubeck kepada kami,
- karena saya berkesempatan memprogram aplikasi lab skala terdistribusi hyperperformance saya sendiri, yang tidak akan sepenuhnya mengulangi arsitektur hyperfor serupa lainnya... yah, itu saja.
Apa yang harus ditulis? Tentu saja, di Rust. Mengapa?
- karena sudah ada solusi prototipe,
- karena penulis artikel tersebut sudah mengenal Rust pada saat itu dan sangat ingin menulis sesuatu di dalamnya untuk produksi dengan kesempatan untuk memasukkannya ke dalam open-source,
- karena bahasa dengan GC tidak cocok untuk kami karena sifat lalu lintas yang diterima (hampir real-time) dan jeda GC secara praktis tidak dapat diterima,
- karena Anda membutuhkan performa maksimal yang sebanding dengan C
- karena Rust memberi kita konkurensi yang tak kenal takut, dan jika kita mulai menulisnya dalam C/C++, kita akan mendapatkan lebih banyak kerentanan, buffer overflow, kondisi balapan, dan kata-kata menakutkan lainnya selain brubeck.
Ada juga argumen yang menentang Rust. Perusahaan tidak memiliki pengalaman membuat proyek di Rust, dan sekarang kami juga tidak berencana menggunakannya di proyek utama. Oleh karena itu, ada ketakutan yang serius bahwa tidak ada yang akan berhasil, tetapi kami memutuskan untuk mengambil risiko dan mencoba.
Waktu berlalu...
Akhirnya, setelah beberapa kali gagal, versi pertama yang berfungsi telah siap. Apa yang telah terjadi? Inilah yang terjadi.
Setiap node menerima kumpulan metriknya sendiri dan mengakumulasikannya, dan tidak mengagregasi metrik untuk jenis-jenis yang memerlukan kumpulan metrik lengkap untuk agregasi akhir. Node-node tersebut terhubung satu sama lain melalui semacam protokol kunci terdistribusi, yang memungkinkan Anda memilih di antara mereka satu-satunya (di sini kami menangis) yang layak untuk mengirimkan metrik ke Yang Hebat. Masalah ini saat ini sedang diselesaikan oleh
Paket UDP dengan metrik tidak seimbang antar node pada peralatan jaringan melalui Round Robin sederhana. Tentu saja, perangkat keras jaringan tidak menguraikan isi paket dan oleh karena itu dapat menarik lebih dari 4 juta paket per detik, belum lagi metrik yang tidak diketahui sama sekali. Jika kami memperhitungkan bahwa metrik tidak muncul satu per satu di setiap paket, maka kami tidak melihat adanya masalah kinerja di tempat ini. Jika server mogok, perangkat jaringan dengan cepat (dalam 1-2 detik) mendeteksi fakta ini dan menghapus server yang mogok dari rotasi. Hasilnya, node pasif (yaitu, non-pemimpin) dapat diaktifkan dan dinonaktifkan secara praktis tanpa memperhatikan penurunan pada grafik. Kerugian maksimum yang kami alami adalah bagian dari metrik yang masuk pada detik terakhir. Hilangnya/shutdown/pergantian pemimpin secara tiba-tiba masih akan menimbulkan anomali kecil (interval 30 detik masih tidak sinkron), namun jika ada komunikasi antar node, masalah tersebut dapat diminimalkan, misalnya dengan mengirimkan paket sinkronisasi. .
Sedikit tentang struktur internal. Aplikasinya tentu saja multithread, tetapi arsitektur threadingnya berbeda dengan yang digunakan di brubeck. Utas di brubeck sama - masing-masing bertanggung jawab atas pengumpulan dan agregasi informasi. Di bioyino, pekerja dibagi menjadi dua kelompok: mereka yang bertanggung jawab atas jaringan dan mereka yang bertanggung jawab atas agregasi. Pembagian ini memungkinkan Anda mengelola aplikasi dengan lebih fleksibel tergantung pada jenis metrik: jika diperlukan agregasi intensif, Anda dapat menambahkan agregator, jika terdapat banyak lalu lintas jaringan, Anda dapat menambahkan jumlah aliran jaringan. Saat ini, di server kami, kami bekerja di 8 jaringan dan 4 aliran agregasi.
Bagian penghitungan (bertanggung jawab atas agregasi) cukup membosankan. Buffer yang diisi oleh aliran jaringan didistribusikan di antara aliran penghitungan, yang kemudian diurai dan dikumpulkan. Berdasarkan permintaan, metrik diberikan untuk dikirim ke node lain. Semua ini, termasuk pengiriman data antar node dan bekerja dengan Konsul, dilakukan secara asinkron, berjalan pada kerangka kerja
Lebih banyak masalah selama pengembangan disebabkan oleh bagian jaringan yang bertanggung jawab menerima metrik. Tujuan utama memisahkan aliran jaringan menjadi entitas terpisah adalah keinginan untuk mengurangi waktu yang dihabiskan suatu aliran tidak untuk membaca data dari soket. Opsi yang menggunakan UDP asinkron dan recvmsg reguler dengan cepat menghilang: opsi pertama menghabiskan terlalu banyak ruang pengguna CPU untuk pemrosesan acara, opsi kedua memerlukan terlalu banyak pengalih konteks. Oleh karena itu sekarang digunakan
Catatan
Pada pengaturan default, ukuran buffer diatur cukup besar. Jika Anda tiba-tiba memutuskan untuk mencoba server sendiri, Anda mungkin menghadapi kenyataan bahwa setelah mengirim sejumlah kecil metrik, metrik tersebut tidak akan tiba di Grafit, tetap berada di buffer aliran jaringan. Untuk bekerja dengan sejumlah kecil metrik, Anda perlu mengatur bufsize dan task-queue-size ke nilai yang lebih kecil di konfigurasi.
Terakhir, beberapa grafik untuk pecinta grafik.
Statistik jumlah metrik yang masuk untuk setiap server: lebih dari 2 juta MPS.
Menonaktifkan salah satu node dan mendistribusikan ulang metrik yang masuk.
Statistik metrik keluar: hanya satu node yang selalu mengirimkan - bos serangan.
Statistik operasi setiap node, dengan mempertimbangkan kesalahan di berbagai modul sistem.
Merinci metrik yang masuk (nama metrik disembunyikan).
Apa yang akan kita lakukan selanjutnya dengan semua ini? Tentu saja, tulis kodenya, sial...! Proyek ini awalnya direncanakan menjadi open-source dan akan tetap demikian sepanjang masa pakainya. Rencana jangka pendek kami termasuk beralih ke versi Raft kami sendiri, mengubah protokol rekan ke yang lebih portabel, memperkenalkan statistik internal tambahan, jenis metrik baru, perbaikan bug, dan peningkatan lainnya.
Tentu saja, semua orang boleh membantu dalam pengembangan proyek: membuat PR, Isu, jika memungkinkan kami akan merespons, meningkatkan, dll.
Oleh karena itu, semuanya, belilah gajah kami!
Sumber: www.habr.com