Sembilan garu Elasticsearch yang saya injak

Ilustrasi oleh Anton Gudim


“Seseorang yang terlatih juga menginjak garu.
Tetapi di sisi lain, di mana pulpen itu berada. "

Elasticsearch adalah alat yang hebat, tetapi setiap alat tidak hanya membutuhkan penyetelan dan perawatan , tetapi juga perhatian terhadap detail. Beberapa tidak signifikan dan terletak di permukaan, sementara yang lain tersembunyi begitu dalam sehingga dibutuhkan lebih dari satu hari untuk mencari, tidak selusin cangkir kopi dan tidak satu kilometer saraf. Dalam artikel ini saya akan memberi tahu Anda tentang sembilan garu yang indah dalam pengaturan elastis yang saya injak.

Saya akan mengatur penggaruk dalam urutan bukti. Dari yang dapat diramalkan dan dielakkan pada tahap pengaturan dan memasuki sebuah cluster di negara produksi, hingga yang sangat aneh yang membawa pengalaman paling banyak (dan bintang di mata).

Node data harus sama


"Cluster berjalan pada kecepatan simpul data paling lambat" - aksioma yang menyakitkan. Tetapi ada titik jelas lain yang tidak terkait dengan kinerja: elastis tidak berpikir dalam ruang disk, tetapi dalam pecahan, dan mencoba untuk mendistribusikannya secara merata di antara data node. Jika beberapa node data memiliki lebih banyak ruang daripada yang lain, maka akan sia-sia untuk diam.

Deprecation.log


Mungkin terjadi bahwa seseorang tidak menggunakan cara paling modern untuk mengirim data ke elastis, yang tidak tahu cara mengatur Tipe-Konten saat menjalankan kueri. Dalam daftar ini, misalnya, heka, atau ketika log meninggalkan perangkat dengan cara bawaannya). Dalam hal ini, penghinaan. log mulai tumbuh pada tingkat yang mengkhawatirkan, dan untuk setiap permintaan, baris berikut muncul di dalamnya:

[2018-07-07T14:10:26,659][WARN ][oedrRestController] Content type detection for rest requests is deprecated. Specify the content type using the [Content-Type] header. [2018-07-07T14:10:26,670][WARN ][oedrRestController] Content type detection for rest requests is deprecated. Specify the content type using the [Content-Type] header. [2018-07-07T14:10:26,671][WARN ][oedrRestController] Content type detection for rest requests is deprecated. Specify the content type using the [Content-Type] header. [2018-07-07T14:10:26,673][WARN ][oedrRestController] Content type detection for rest requests is deprecated. Specify the content type using the [Content-Type] header. [2018-07-07T14:10:26,677][WARN ][oedrRestController ] Content type detection for rest requests is deprecated. Specify the content type using the [Content-Type] header. 

Permintaan datang, rata-rata, setiap 5-10 ms - dan setiap kali baris baru ditambahkan ke log. Ini secara negatif mempengaruhi kinerja subsistem disk dan meningkatkan iowait. Deprecation.log dapat dimatikan, tetapi itu tidak terlalu masuk akal. Untuk mengumpulkan log elastis ke dalamnya, tetapi tidak membuang sampah sembarangan, saya hanya menonaktifkan log dari kelas oedrRestController.

Untuk melakukan ini, tambahkan konstruksi berikut ke logs4j2.properties:

 logger.restcontroller.name = org.elasticsearch.deprecation.rest.RestController logger.restcontroller.level = error 

Ini akan menaikkan log kelas ini ke tingkat kesalahan, dan mereka tidak akan lagi jatuh ke dalam deprecation.log.

.kibana


Seperti apa proses instalasi kluster? Kami menempatkan node, menggabungkan mereka ke dalam sebuah cluster, menempatkan x-pack (yang membutuhkannya), dan tentu saja, Kibana. Kami mulai, memverifikasi bahwa semuanya berfungsi dan Kibana melihat cluster, dan terus mengonfigurasi. Masalahnya adalah bahwa pada cluster yang baru diinstal, template default terlihat seperti ini:

 { "default": { "order": 0, "template": "*", "settings": { "number_of_shards": "1", "number_of_replicas": "0" } }, "mappings": {}, "aliases": {} } 

Dan indeks .kibana, tempat semua pengaturan disimpan, dibuat dalam satu salinan.

Pernah ada kasus ketika, karena kegagalan perangkat keras, salah satu node data di cluster terbunuh. Dengan cepat mencapai kondisi yang konsisten, meningkatkan replika pecahan dari node data tetangga, tetapi, untungnya, pada node data inilah satu-satunya pecahan dengan indeks .ibibana ditemukan. Situasinya macet - cluster hidup, dalam kondisi kerja, dan Kibana dalam status merah, dan ponsel saya dihancurkan oleh panggilan karyawan yang sangat membutuhkan log mereka.

Semua ini diselesaikan dengan sederhana. Sejauh ini, tidak ada yang jatuh:

 XPUT .kibana/_settings { "index": { "number_of_replicas": "<__>" } } 

XMX / XMS


Dokumentasi mengatakan "Tidak lebih dari 32 GB," dan memang demikian. Tetapi juga benar bahwa Anda tidak perlu menginstal di pengaturan layanan
 -Xms32g -Xmx32g 

Karena sudah lebih dari 32 gigabytes, dan di sini kita melihat nuansa Java yang menarik dengan memori. Di atas batas tertentu, Java berhenti menggunakan pointer terkompresi dan mulai mengkonsumsi banyak memori. Memeriksa apakah pointer terkompresi menggunakan mesin Java yang menjalankan Elasticsearch sangat sederhana. Kami melihat di log layanan:

 [2018-07-29T15:04:22,041][INFO][oeeNodeEnvironment][log-elastic-hot3] heap size [31.6gb], compressed ordinary object pointers [true] 

Jumlah memori yang tidak boleh terlampaui tergantung, antara lain, pada versi Java yang digunakan. Untuk menghitung volume tepat dalam kasus Anda, lihat dokumentasi .

Sekarang saya telah menginstal pada semua data node elastis:

 -Xms32766m -Xmx32766m 

Tampaknya menjadi fakta biasa, dan dokumentasinya dijelaskan dengan baik, tetapi saya secara teratur menemukan instalasi Elasticsearch di mana saya melewatkan poin ini, dan Xms / Xmx diatur ke 32g.

/ var / lib / elasticsearch


Ini adalah jalur default untuk menyimpan data dalam elasticsearch. yml:

 path.data: /var/lib/elasticsearch 

Di sana saya biasanya memasang satu array RAID besar, dan inilah sebabnya: kami menetapkan ES beberapa cara untuk menyimpan data, misalnya, seperti ini:

 path.data: /var/lib/elasticsearch/data1, /var/lib/elasticsearch/data2 

Disk atau raid array yang berbeda dipasang di data1 dan data2. Tetapi elastis tidak seimbang dan tidak mendistribusikan beban antara jalur ini. Pertama, dia mengisi satu bagian, lalu mulai menulis di bagian lain, sehingga beban pada penyimpanan tidak merata. Mengetahui hal ini, saya membuat keputusan yang tidak ambigu - saya menggabungkan semua disk di RAID0 / 1 dan memasangnya di path yang ditentukan di path.data.

tersedia_prosesor


Dan tidak, saya tidak bermaksud prosesor pada node menelan sekarang. Jika Anda melihat properti dari simpul yang berjalan (melalui API _nodes), Anda dapat melihat sesuatu seperti ini:

 "os". { "refresh_interval_in_millis": 1000, "name": "Linux", "arch": "amd64", "version": "4.4.0-87-generic", "available_processors": 28, "allocated_processors": 28 } 

Dapat dilihat bahwa node berjalan pada host dengan 28 core, dan elastis menentukan dengan benar jumlah mereka dan mulai semuanya. Tetapi jika ada lebih dari 32 core, kadang-kadang terjadi seperti ini:

 "os": { "refresh_interval_in_millis": 1000, "name": "Linux", "arch": "amd64", "version": "4.4.0-116-generic", "available_processors": 72, "allocated_processors": 32 } 

Anda harus memaksa jumlah prosesor yang tersedia untuk layanan - ini memiliki efek yang baik pada kinerja node.

 processors: 72 

thread_pool.bulk.queue_size


Di bagian thread_pool.bulk.rejected dari artikel terakhir , ada semacam metrik - hitungan jumlah kegagalan permintaan untuk menambahkan data.

Saya menulis bahwa pertumbuhan indikator ini adalah pertanda yang sangat buruk, dan pengembang merekomendasikan untuk tidak menyiapkan thread thread, tetapi menambahkan node baru ke cluster - yang seharusnya, ini memecahkan masalah kinerja. Tetapi aturan dibutuhkan untuk kadang-kadang melanggarnya. Dan tidak selalu mungkin untuk "melempar masalah dengan besi", jadi salah satu langkah untuk memerangi kegagalan dalam permintaan massal adalah meningkatkan ukuran antrian ini.

Secara default, pengaturan antrian terlihat seperti ini:

 "thread_pool": { "bulk": { "type": "fixed", "min": 28, "max": 28, "queue_size": 200 } } 

Algoritma adalah sebagai berikut:

  1. Kami mengumpulkan statistik tentang ukuran rata-rata antrian sepanjang hari (nilai instan disimpan di thread_pool.bulk.queue);
  2. Hati-hati tingkatkan queue_size ke ukuran yang sedikit lebih besar daripada ukuran rata-rata antrian aktif - karena kegagalan terjadi ketika melebihi;
  3. Kami menambah ukuran kolam - ini tidak perlu, tapi bisa diterima.

Untuk melakukan ini, tambahkan sesuatu seperti ini ke pengaturan host (Anda tentu saja akan memiliki nilai sendiri):

 thread_pool.bulk.size: 32 thread_pool.bulk.queue_size: 500 

Dan setelah me-restart node, kita pasti akan memonitor beban, I / O, konsumsi memori. dan semua yang mungkin untuk mengembalikan pengaturan jika perlu.

Penting: pengaturan ini hanya masuk akal pada node yang bekerja untuk menerima data baru.

Pembuatan Indeks Awal


Seperti yang saya katakan di artikel pertama seri ini, kami menggunakan Elasticsearch untuk menyimpan log dari semua layanan Microsoft. Intinya sederhana - satu indeks menyimpan log dari satu komponen dalam satu hari.

Dari sini dapat disimpulkan bahwa setiap hari indeks-indeks baru dibuat oleh jumlah layanan-mikro - oleh karena itu, lebih awal setiap malam, elastis jatuh ke dalam lubang selama sekitar 8 menit, sementara seratus indeks baru dibuat, beberapa ratus pecahan baru, jadwal pemuatan disk pergi “ke rak”, antrian bertambah untuk mengirim log ke elastis pada host, dan Zabbix berkembang dengan peringatan seperti pohon Natal.

Untuk menghindari ini, adalah akal sehat untuk menulis skrip Python untuk membuat indeks sebelumnya. Script bekerja seperti ini: ia menemukan indeks untuk hari ini, mengekstrak pemetaan mereka dan membuat indeks baru dengan pemetaan yang sama, tetapi untuk hari berikutnya. Ini berjalan pada cron, berjalan selama jam-jam ketika Elastis adalah yang paling sedikit dimuat. Script menggunakan perpustakaan elasticsearch dan tersedia di GitHub .

Halaman induk transparan yang besar


Setelah kami menemukan bahwa node elastis yang mengoperasikan penerimaan data mulai menggantung di bawah beban selama jam sibuk. Dan dengan gejala yang sangat aneh: penggunaan semua inti prosesor turun ke nol, namun demikian, layanan ini hang dalam memori, mendengarkan dengan benar ke port, tidak melakukan apa-apa, tidak menanggapi permintaan, dan setelah beberapa waktu jatuh dari cluster. Layanan tidak menanggapi restart systemctl. Hanya pembunuhan lama yang bagus yang membantu.

Ini tidak ditangkap oleh alat pemantauan standar, pada grafik sampai saat jatuhnya gambar biasa, dalam log layanan - kosong. Memori dump mesin java pada saat ini juga tidak mungkin.

Tetapi, seperti yang mereka katakan, "kami adalah profesional, jadi setelah beberapa waktu kami mencari solusinya." Masalah serupa juga dibahas dalam utas pada mendiskusikan.elastic.co dan ternyata merupakan bug kernel yang terkait dengan halaman besar tranparent. Semuanya diselesaikan dengan mematikan thp di kernel menggunakan paket sysfsutils.

Memeriksa apakah Anda mengaktifkan halaman besar transparan itu sederhana:

 cat /sys/kernel/mm/transparent_hugepage/enabled always madvise [never] 

Jika [selalu] ada, Anda berpotensi berisiko.

Kesimpulan


Ini adalah penggaruk utama (sebenarnya ada, tentu saja, lebih banyak), yang kebetulan saya tapak selama satu setengah tahun sebagai administrator dari cluster Elasticsearch. Saya harap informasi ini berguna dalam perjalanan yang sulit dan misterius ke cluster Elasticsearch yang ideal.

Terima kasih untuk ilustrasinya, Anton Gudim - masih ada banyak kebaikan di instagramnya .

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


All Articles