Pohon supervisi

Struktur pohon supervisi: rest-for-one, one-for-all, dan susunan application.

Daftar isi

Topik ini memperluas supervisor dari satu lapis menjadi pohon: supervisor yang mengawasi supervisor, urutan child sebagai bagian desain, dan konsekuensi pemilihan strategi terhadap kebenaran data. Setelah membaca, struktur pohon sebuah aplikasi dapat dirancang dengan alasan yang bisa dipertanggungjawabkan.

Supervisor mengawasi supervisor#

Child sebuah supervisor boleh berupa supervisor lain, dan bentuk inilah yang disebut pohon supervisi. Supervisor berumur paling panjang diletakkan di akar dan mengawasi child yang kecil kemungkinannya untuk gagal, sedangkan supervisor yang mengawasi pekerja berumur pendek berada di cabang. Bila supervisor pekerja menyerah karena melampaui intensitas restartnya, supervisor induknya yang memulai ulang cabang itu, sehingga kegagalan yang tidak dapat ditangani di satu level naik ke level yang lebih mampu. Pohon ini juga menjadi unit mati bersama: link antar supervisor menyambung seluruh cabang, sehingga kegagalan akar meruntuhkan pohon secara tertib dan memulihkannya dari atas.

Urutan child dan rest-for-one#

Daftar spesifikasi child bukan sekadar koleksi. Urutannya adalah semantik. Strategi rest_for_one membaca urutan itu secara harfiah: bila child ke-N mati, child ke-N beserta semua yang dimulai setelahnya dimulai ulang, sedangkan yang di depan dibiarkan. Aturan ini cocok dengan kebutuhan nyata, misalnya child pertama mengelola koneksi yang dibutuhkan child berikutnya: koneksi yang dimulai ulang membuat dependennya ikut dimulai ulang, sehingga tidak ada pasangan yang tidak sinkron. Diagram berikut membandingkan ketiga strategi ketika child B mati:

supervisorABCone_for_onehanya B dipulihkansupervisorABCone_for_allsemua dipulihkansupervisorABCrest_for_oneB dan C dipulihkan
Perbandingan strategi restart saat child B mati
Strategi one_for_one menyisakan A dan C berjalan karena keduanya tidak bergantung pada B, one_for_all memulihkan ketiganya karena state bersama diragukan, dan rest_for_one memulihkan B beserta C yang dimulai setelah B. Pertanyaan yang menentukan pilihan selalu sama, yaitu apakah data yang dipegang child lain masih bisa dipercaya setelah B jatuh.

Inspeksi pohon#

Pohon yang berjalan dapat diperiksa dari shell tanpa alat tambahan. Fungsi supervisor:which_children/1 membaca child sebuah supervisor, dan keluarannya memuat id, PID, tipe, dan modulnya:

erlang Membaca child supervisor yang berjalan
Erlang/OTP 29 [erts-17.1.1] [source] [64-bit] [smp:2:2] [ds:2:2:10] [async-threads:1] [jit:ns]

Eshell V17.1.1 (press Ctrl+G to abort, type help(). for help)
1> c(tiket).
{ok,tiket}
2> c(sup_tiket).
{ok,sup_tiket}
3> sup_tiket:start_link().
{ok,<0.97.0>}
4> supervisor:which_children(sup_tiket).
[{tiket,<0.98.0>,worker,[tiket]}]

Untuk pohon berlapis, fungsi ini dipanggil pada tiap supervisor dari akar ke bawah, dan hasilnya berupa inventaris langsung dari struktur yang berjalan, bukan spesifikasinya. Bentuk inspeksi yang lebih lengkap, termasuk status state internal, disediakan modul sys dan dibahas pada modul Production.

Merancang tingkat pohon#

Pohon yang sehat memiliki tingkat sesuai kebutuhan pemulihan, bukan sebanyak mungkin. Dua pola yang lazim adalah pohon datar dengan satu supervisor akar untuk aplikasi kecil, dan pohon dua tingkat dengan supervisor per kelompok pekerja pada aplikasi yang lebih besar. Kelompok yang sebaiknya dicabangkan antara lain:

  • pekerja dengan pola kegagalan berbeda, karena intensitas restartnya berbeda
  • pekerja yang saling bergantung secara urutan, karena membutuhkan rest_for_one di cabangnya sendiri
  • sumber daya yang mahal untuk dimulai ulang, karena kegagalan satu pekerja tidak boleh memulihkan sumber daya yang tidak terlibat

Sebaliknya, cabang berisi satu child adalah sinyal kelebihan tingkat, dan dua cabang dengan strategi serta konfigurasi yang identik adalah sinyal untuk digabung.

Tingkat pohon juga menjadi tempat menetapkan intensitas restart secara berbeda. Intensitas pada supervisor induk hanya menghitung kegagalan pada levelnya, yaitu berakhirnya supervisor anak yang ia awasi, sementara supervisor anak menghitung kegagalan pekerjanya sendiri dengan nilai intensitas sendiri. Susunan ini memungkinkan kebijakan berbeda pada tiap tingkat: cabang pekerja yang mudah gagal diberi intensitas longgar, sedangkan supervisor yang menyalakan sumber daya mahal diberi intensitas ketat agar kegagalan struktural cepat naik ke akar dan diperbaiki di sana.

Pohon aplikasi tiketapp#

Pohon pada modul OTP behaviour ini kecil tetapi lengkap susunannya: aplikasi tiketapp memulai supervisor sup_tiket dari callback start/2, dan supervisor itu mengawasi satu worker bernama tiket. Pemanggilan supervisor:which_children(sup_tiket) pada topik ini menunjukkan baris [{tiket,<0.98.0>,worker,[tiket]}], yaitu inventaris lengkap lapisan bawah pohon itu. Pada aplikasi nyata, lapisan atas dibaca dengan memanggil which_children pada supervisor akar aplikasinya, dan pengulangan pemeriksaan itu dari akar ke daun memberikan peta struktur yang sama dengan yang dirancang pada init/1 tiap supervisor. Ketika pohon tumbuh, membandingkan hasil inspeksi dengan rancangan awal adalah cara termurah untuk menemukan cabang yang menyimpang dari desain.

Ringkasan#

  • Supervisor boleh mengawasi supervisor lain, dan bentuk pohon itulah struktur aplikasi OTP.
  • Urutan daftar child adalah semantik untuk strategi rest_for_one, yang memulai ulang child yang mati beserta semua yang mengikutinya.
  • which_children/1 menginspeksi child supervisor yang berjalan beserta id, PID, dan tipenya.
  • Tingkat pohon dirancang dari pola kegagalan dan ketergantungan data, bukan dari kebiasaan mencabangkan.

Referensi#