Netramesh - solusi layanan ringan

Dalam proses transisi dari aplikasi monolitik ke arsitektur layanan mikro, kita dihadapkan dengan masalah baru.


Dalam aplikasi monolitik, biasanya cukup sederhana untuk menentukan bagian mana dari sistem yang terjadi kesalahan. Kemungkinan besar, masalahnya ada pada kode monolith itu sendiri, atau dalam database. Tetapi ketika kita mulai mencari masalah dalam arsitektur microservice, semuanya tidak begitu jelas. Anda perlu menemukan seluruh jalur yang diminta dari awal hingga akhir, untuk memilihnya dari ratusan layanan mikro. Selain itu, banyak dari mereka juga memiliki repositori sendiri, yang juga dapat menyebabkan kesalahan logis, serta masalah dengan kinerja dan toleransi kesalahan.



Untuk waktu yang lama saya mencari alat yang akan membantu mengatasi masalah seperti itu (saya menulis tentang hal itu di Habré: 1 , 2 ), tetapi pada akhirnya saya membuat solusi open source saya sendiri. Dalam artikel itu, saya berbicara tentang manfaat dari pendekatan service mesh dan berbagi alat baru untuk implementasinya.


Pelacakan terdistribusi adalah solusi umum untuk masalah menemukan kesalahan dalam sistem terdistribusi. Tetapi bagaimana jika sistem belum menerapkan pendekatan seperti itu untuk mengumpulkan informasi tentang interaksi jaringan, atau, lebih buruk, di bagian sistem itu sudah berfungsi dengan baik, dan sebagian tidak, karena tidak ditambahkan ke layanan yang lama? Untuk menentukan akar penyebab masalah, Anda harus memiliki gambaran lengkap tentang apa yang terjadi di sistem. Sangat penting untuk memahami layanan microser mana yang terlibat dalam jalur kritis bisnis utama.


Di sini, pendekatan mesh layanan dapat membantu kami, yang akan menangani semua mesin untuk mengumpulkan informasi jaringan pada tingkat yang lebih rendah dari apa yang dilakukan oleh layanan itu sendiri. Pendekatan ini memungkinkan kita untuk mencegat semua lalu lintas dan menganalisisnya dengan cepat. Apalagi aplikasi tentang hal itu seharusnya tidak tahu apa-apa.


Pendekatan layanan mesh


Gagasan utama dari pendekatan layanan mesh adalah untuk menambahkan lapisan infrastruktur lain melalui jaringan, yang akan memungkinkan kita untuk melakukan hal-hal dengan interaksi antar-layanan. Sebagian besar implementasi bekerja sebagai berikut: wadah sespan tambahan dengan proxy transparan ditambahkan ke masing-masing layanan mikro, di mana semua lalu lintas layanan masuk dan keluar dilewatkan. Dan ini adalah tempat di mana kita dapat melakukan penyeimbangan klien, menerapkan kebijakan keamanan, memperkenalkan batasan pada jumlah permintaan dan mengumpulkan informasi penting tentang interaksi layanan dalam produksi.



Solusi


Sudah ada beberapa implementasi dari pendekatan ini: Istio dan linkerd2 . Mereka menyediakan banyak fitur di luar kotak. Tetapi pada saat yang sama overhead besar datang ke sumber daya. Selain itu, semakin besar cluster di mana sistem tersebut bekerja, semakin banyak sumber daya yang dibutuhkan untuk memelihara infrastruktur baru. Di Avito, kami mengoperasikan kelompok kubernet dengan ribuan contoh layanan (dan jumlahnya terus bertambah dengan cepat). Dalam implementasi saat ini, Istio mengkonsumsi ~ 300Mb RAM per instance layanan. Karena banyaknya fitur, penyeimbangan transparan juga memengaruhi total waktu respons layanan (hingga 10 ms).


Sebagai hasilnya, kami melihat fitur apa yang kami butuhkan saat ini, dan memutuskan bahwa alasan utama kami mulai menerapkan solusi tersebut adalah kemampuan untuk mengumpulkan informasi penelusuran dari seluruh sistem secara transparan. Kami juga ingin memiliki kontrol atas interaksi layanan dan melakukan berbagai manipulasi dengan header yang ditransfer antar layanan.


Pada akhirnya, kami sampai pada keputusan kami: Netramesh .


Netramesh


Netramesh adalah solusi mesh layanan ringan dengan skalabilitas tak terbatas terlepas dari jumlah layanan dalam sistem.


Tujuan utama dari solusi baru adalah overhead kecil dalam sumber daya dan kinerja tinggi. Dari fitur utama, kami segera ingin dapat mengirim tracing span secara transparan ke sistem Jaeger kami.


Saat ini, sebagian besar solusi cloud diimplementasikan pada Golang. Dan, tentu saja, ada alasan untuk ini. Menulis aplikasi jaringan Golang yang bekerja secara asinkron dengan I / O dan skala ke kernel sesuai kebutuhan mudah dan cukup sederhana. Dan, yang juga sangat penting, kinerjanya cukup untuk menyelesaikan masalah ini. Karena itu, kami juga memilih Golang.


Performa


Kami telah memfokuskan upaya kami untuk mencapai kinerja maksimal. Untuk solusi yang digunakan di sebelah setiap instance layanan, diperlukan sedikit konsumsi RAM dan waktu prosesor. Dan, tentu saja, keterlambatan dalam menjawab juga harus kecil.


Mari kita lihat apa hasilnya.


RAM


Netramesh mengkonsumsi ~ 10Mb tanpa lalu lintas dan maksimum 50Mb dengan beban hingga 10.000 RPS per instance.


Utusan utusan Istio selalu mengkonsumsi ~ 300Mb dalam kelompok kami dengan ribuan instance. Ini tidak memungkinkan Anda untuk skala ke seluruh cluster.




Dengan Netramesh, kami mendapat ~ 10 kali lebih sedikit konsumsi memori.


CPU


Penggunaan CPU relatif sama dengan beban. Itu tergantung pada jumlah permintaan per unit waktu untuk sespan. Nilai pada 3000 permintaan per detik pada puncaknya:




Ada poin penting lainnya: Netramesh - solusi tanpa bidang kontrol dan tanpa beban tidak menghabiskan waktu CPU. Dengan Istio, sespan selalu memperbarui titik akhir layanan. Hasilnya, kita dapat melihat gambar seperti itu tanpa memuat:



Kami menggunakan HTTP / 1 untuk berkomunikasi antar layanan. Peningkatan waktu respons untuk Istio ketika probing melalui utusan hingga 5-10ms, yang cukup banyak untuk layanan yang siap merespons dalam milidetik. Dengan Netramesh, kali ini turun menjadi 0,5-2ms.


Skalabilitas


Sejumlah kecil sumber daya yang dihabiskan oleh setiap proxy memungkinkan untuk menempatkannya di sebelah setiap layanan. Netramesh sengaja dibuat tanpa komponen bidang kontrol untuk sekadar mempertahankan kecerahan setiap sespan. Seringkali dalam solusi mesh layanan, bidang kontrol mendistribusikan informasi penemuan layanan ke setiap sespan. Bersamaan dengan itu muncul informasi tentang batas waktu, pengaturan keseimbangan. Semua ini memungkinkan Anda untuk melakukan banyak hal berguna, tetapi, sayangnya, mengembang ukuran sidecar'y.


Penemuan layanan



Netramesh tidak menambahkan mekanisme tambahan untuk penemuan layanan. Semua lalu lintas diproksikan secara transparan melalui sespan netra.


Netramesh mendukung protokol aplikasi HTTP / 1. Daftar port yang dapat dikonfigurasi digunakan untuk menentukannya. Biasanya, ada beberapa port pada sistem yang berkomunikasi melalui HTTP. Misalnya, kami menggunakan 80, 8890, 8080 untuk berinteraksi dengan layanan dan permintaan eksternal. Dalam hal ini, mereka dapat diatur menggunakan NETRA_HTTP_PORTS lingkungan NETRA_HTTP_PORTS .


Jika Anda menggunakan Kubernet sebagai orkestra dan mekanisme entitas Layanannya untuk interaksi intracluster antar layanan, maka mekanismenya tetap sama persis. Pertama, microservice mendapatkan alamat IP layanan menggunakan kube-dns dan membuka koneksi baru untuk itu. Koneksi ini dibuat terlebih dahulu dengan netra-sidecar lokal, dan semua paket TCP awalnya tiba di netra. Selanjutnya, netra-sidecar membuat koneksi ke tujuan awal. NAT pada pod IP pada node tetap sama persis seperti tanpa netra.


Pelacakan terdistribusi dan pengguliran konteks


Netramesh menyediakan fungsionalitas yang diperlukan untuk mengirim tracing span tentang interaksi HTTP. Netra-sidecar mem-parsing protokol HTTP, mengukur keterlambatan permintaan, mengambil informasi yang diperlukan dari header HTTP. Pada akhirnya, kita mendapatkan semua jejak dalam satu sistem Jaeger. Untuk fine- tuning, Anda juga dapat menggunakan variabel lingkungan yang disediakan oleh pustaka jaeger go resmi.




Tapi ada masalah. Hingga layanan menghasilkan dan meneruskan header uber khusus, kami tidak akan melihat bentang penelusuran yang tersambung di sistem. Dan inilah yang kita butuhkan untuk menemukan penyebab masalah dengan cepat. Di sini Netramesh punya solusi lagi. Proxy membaca tajuk HTTP dan, jika mereka tidak memiliki jejak uber, hasilkan. Netramesh juga menyimpan informasi tentang permintaan masuk dan keluar di sespan dan membandingkannya dengan memperkaya header yang diperlukan dari permintaan keluar. Yang perlu dilakukan dalam layanan adalah membuang hanya satu header X-Request-Id , yang dapat dikonfigurasi menggunakan NETRA_HTTP_REQUEST_ID_HEADER_NAME lingkungan NETRA_HTTP_REQUEST_ID_HEADER_NAME . Untuk mengontrol ukuran konteks di Netramesh, Anda dapat mengatur variabel lingkungan berikut: NETRA_TRACING_CONTEXT_EXPIRATION_MILLISECONDS (waktu di mana konteks akan disimpan) dan NETRA_TRACING_CONTEXT_CLEANUP_INTERVAL (periodisitas pembersihan konteks).


Dimungkinkan juga untuk menggabungkan beberapa jalur di sistem Anda dengan menandainya dengan penanda sesi khusus. Netra memungkinkan Anda untuk mengatur HTTP_HEADER_TAG_MAP untuk mengubah header HTTP menjadi tag span tracing yang sesuai. Ini bisa sangat berguna untuk pengujian. Setelah melewati tes fungsional, Anda dapat melihat bagian mana dari sistem yang terpengaruh oleh pemfilteran dengan kunci sesi yang sesuai.


Menentukan sumber permintaan


Untuk menentukan dari mana permintaan berasal, Anda dapat menggunakan fungsi untuk secara otomatis menambahkan header dengan sumber. Menggunakan NETRA_HTTP_X_SOURCE_HEADER_NAME lingkungan NETRA_HTTP_X_SOURCE_HEADER_NAME Anda dapat menentukan nama header yang akan ditetapkan secara otomatis. Menggunakan NETRA_HTTP_X_SOURCE_VALUE Anda dapat mengatur nilai di mana header X-Source akan ditetapkan untuk semua permintaan keluar.


Ini memungkinkan Anda secara seragam di seluruh jaringan untuk melakukan distribusi tajuk yang bermanfaat ini. Maka Anda sudah bisa menggunakannya dalam layanan dan menambahkannya ke log dan metrik.


Netramesh traffic dan routing internal


Netramesh terdiri dari dua komponen utama. Yang pertama, netra-init, mengatur aturan jaringan untuk memotong lalu lintas. Ia menggunakan aturan pengalihan iptables untuk mencegat semua atau sebagian dari lalu lintas di sespan, yang merupakan komponen utama kedua dari Netramesh. Anda dapat mengonfigurasikan port mana yang ingin Anda INBOUND_INTERCEPT_PORTS, OUTBOUND_INTERCEPT_PORTS sesi TCP yang masuk dan keluar: INBOUND_INTERCEPT_PORTS, OUTBOUND_INTERCEPT_PORTS .


Alat ini juga memiliki fitur menarik - perutean probabilistik. Jika Anda menggunakan Netramesh secara eksklusif untuk mengumpulkan rentang penelusuran, maka dalam lingkungan produksi Anda dapat menghemat sumber daya dan mengaktifkan perutean probabilistik menggunakan variabel NETRA_INBOUND_PROBABILITY dan NETRA_OUTBOUND_PROBABILITY (dari 0 hingga 1). Nilai default adalah 1 (semua lalu lintas dicegat).


Setelah intersepsi berhasil, netra sidecar menerima koneksi baru dan menggunakan opsi soket SO_ORIGINAL_DST untuk mendapatkan tujuan awal. Netra kemudian membuka koneksi baru ke alamat IP asli dan membangun komunikasi TCP dua arah antara para pihak, mendengarkan semua lalu lintas yang lewat. Jika port didefinisikan sebagai HTTP, Netra akan mencoba mengurai dan merutekannya. Jika penguraian HTTP tidak berhasil, Netra akan mundur pada TCP dan byte proksi secara transparan.


Membangun grafik ketergantungan


Setelah menerima banyak informasi penelusuran di Jaeger, saya ingin mendapatkan grafik lengkap interaksi dalam sistem. Tetapi jika sistem Anda dimuat dengan cukup dan miliaran pelacakan rentang menumpuk per hari, membuat agregasi mereka menjadi tugas yang tidak begitu mudah. Ada cara resmi untuk melakukan ini: percikan-dependensi . Namun, akan dibutuhkan berjam-jam untuk membuat grafik lengkap dan memaksa seluruh dataset untuk diunduh dari Jaeger selama 24 jam terakhir.


Jika Anda menggunakan Elasticsearch untuk menyimpan rentang penelusuran, Anda dapat menggunakan utilitas sederhana di Golang yang akan membuat grafik yang sama dalam hitungan menit menggunakan fitur dan kemampuan Elasticsearch.



Cara menggunakan Netramesh


Netra dapat dengan mudah ditambahkan ke layanan yang menjalankan orkestra mana saja. Anda dapat melihat contohnya di sini .


Saat ini, Netra tidak memiliki kemampuan untuk secara otomatis menggunakan sespan untuk layanan, tetapi ada rencana untuk implementasi.


Netramesh di masa depan


Tujuan utama Netramesh adalah untuk mencapai biaya sumber daya minimum dan kinerja tinggi, memberikan peluang utama untuk pengamatan dan kontrol interaksi antar-layanan.


Di masa depan, Netramesh akan menerima dukungan untuk protokol tingkat aplikasi selain HTTP. Dalam waktu dekat akan ada kemungkinan routing L7.


Gunakan Netramesh jika Anda menemukan masalah yang sama dan tulis kami pertanyaan dan saran.

Source: https://habr.com/ru/post/id449974/


All Articles