Advertisement
  1. Code
  2. Elixir

Supervisor di Elixir

by
Read Time:9 minsLanguages:

Indonesian (Bahasa Indonesia) translation by Imam Firmansyah (you can also view the original English article)

Dalam artikel saya sebelumnya, kami berbicara tentang Open Telecom Platform (OTP) dan, lebih spesifik lagi, abstraksi GenServer yang membuatnya menjadi lebih mudah untuk bekerja dengan proses server. GenServer, seperti yang mungkin Anda ingat, adalah perilaku — untuk menggunakannya, Anda perlu menentukan modul callback khusus yang memenuhi kontrak sebagaimana ditentukan oleh perilaku ini.

Apa yang belum kita bahas, bagaimanapun, adalah penanganan error. Maksud saya, setiap sistem mungkin akhirnya mengalami kesalahan, dan penting untuk mengatasinya dengan benar. Anda dapat merujuk pada artikel Cara menangani exception pada Elixir untuk mempelajari try/rescue block, raise, dan beberapa solusi generic lainnya. Solusi ini sangat mirip dengan yang ditemukan dalam bahasa pemrograman populer lainnya, seperti JavaScript atau Ruby.

Namun, ada lebih banyak topik tentang ini. Pada akhirnya, Elixir dirancang untuk membangun sistem konkuren dan toleran terhadap fault(kesalahan), sehingga memiliki hal lain untuk ditawarkan. Dalam artikel ini kita akan berbicara tentang supervisors, yang memungkinkan kita untuk mengawasi proses-proses dan me-restart mereka setelah mereka berhenti. Supervisors tidak serumit itu, namun sangat powerful. Mereka dapat dengan mudah diambil, diatur dengan strategi variatif terkait cara melakukan restart,dan digunakan pada supervision trees.

Jadi hari ini kita akan melihat supervisor beraksi!

Persiapan

Untuk tujuan demonstrasi, kami akan menggunakan beberapa kode contoh dari artikel saya sebelumnya tentang GenServer. Modul ini disebut CalcServer, dan memungkinkan kita untuk melakukan beragam kalkulasi dan mempertahankan hasilnya.

Baiklah, jadi pertama-tama, buatlah sebuah proyek baru menggunakan perintah mix new calc_server. Selanjutnya, definisikan modulnya, termasuk GenServer, dan berikan shortcut start/1:

Selanjutnya, beri callback init/1 yang akan dijalankan sesaat setelah server dijalankan. Dibutuhkan nilai awal dan menggunakan clause penjaga untuk memeriksa apakah itu angka. Jika bukan, server akan berhenti:

Saat ini fungsi code antarmuka untuk melakukan penambahan, pembagian, perkalian, perhitungan akar kuadrat, dan menghitung hasilnya (tentu saja, Anda dapat menambahkan lebih banyak operasi matematika sesuai kebutuhan):

Sebagian besar fungsi ini ditangani secara asinkron, yang berarti kita tidak menunggu mereka sampai selesai. Fungsi yang terakhir sinkron karena kita sebenarnya ingin menunggu hasilnya tiba. Oleh karena itu, tambahkan handle_call dan callback handle_cast:

Juga, tentukan apa yang harus dilakukan jika server dihentikan (kita memerankan Captain Obvious disini):

Sekarang program dapat di-compile menggunakan iex -S mix dan digunakan dengan cara berikut:

Masalahnya adalah server mengalami crash ketika error dinaikkan. Misalnya, coba bagi dengan nol:

Jadi proses dihentikan dan tidak bisa digunakan lagi. Ini memang buruk, namun kita akan memperbaikinya sesegera mungkin!

Biarkan itu Crash

Setiap bahasa pemrograman memiliki idiom, dan begitu juga Elixir. Ketika berhadapan dengan supervisor, satu pendekatan umum adalah membiarkan suatu proses crash dan kemudian melakukan sesuatu tentang hal itu — mungkin, mulai ulang dan terus berjalan.

Beberapa bahasa pemrograman hanya menggunakan try dan catch (atau construct yang serupa), yang merupakan gaya pemrograman yang lebih defensif. Kami pada dasarnya berusaha mengantisipasi semua kemungkinan masalah dan menyediakan cara untuk mengatasinya.

Hal-hal sangat berbeda dengan supervisor: jika suatu proses macet, ia mengalami crash. Tetapi supervisor, layaknya seorang medis pemberani dalam peperangan, hadir untuk membantu memulihkan proses yang gugur. Ini mungkin terdengar agak aneh, tetapi dalam kenyataannya hal tersebut sangat masuk akal. Terlebih lagi, Anda bahkan dapat membuat pohon supervisi dan cara ini mengisolasi kesalahan, mencegah seluruh aplikasi terhempas jika salah satu bagiannya mengalami masalah.

Bayangkan mengendarai sebuah mobil: ini terdiri dari berbagai subsistem, dan Anda tidak dapat memeriksanya setiap waktu. Yang dapat anda lakukan adalah memperbaiki subsistem jika rusak (atau, bisa minta montir mobil untuk melakukannya) dan melanjutkan perjalanan Anda. Supervisor pada Elixir pun sama halnya, mereka hanya melakukan itu: mereka mengawasi proses anda (disebut sebagai child processes) dan me-restart proses sesuai kebutuhan.

Membuat sebuah Supervisor

Anda dapat menerapkan sebuah supervisor menggunakan modul behaviour(perilaku) terkait. Ini memberikan fungsi umum untuk penelusuran dan pelaporan error.

Pertama-tama, Anda harus membuat sebuah link ke supervisor anda. Linking merupakan teknik yang cukup penting juga: saat 2 proses saling terkait dan salah satu dari mereka dihentikan / terhenti, yang satunya menerima notifikasi(pemberitahuan) yang satu menerima pemberitahuan dengan alasan keluar. Jika proses yang terkait dihentikan secara tidak normal (artinya, crashed), rekannya pun akan ikut keluar.

Ini dapat ditunjukkan menggunakan spawn/1 dan fungsi spawn_link/1:

Dlam contoh ini, kita menumbuhkan dua proses, fungsi dalam ditumbuhkan dan dikaitkan ke proses yang sedang berlangsung. Sekarang, jika anda memunculkan sebuah error pada salah satunya, yang lain akan berhenti juga:

Jadi, untuk membuat sebuah link saat menggunakan GenServer, ganti saja fungsi start anda dengan start_link:

Ini semua tentang behaviour (Perilaku)!

Sekarang, tentu, sebuah supervisor harus dibuat. Tambahkan sebuah file lib/calc_supervisor.ex baru dengan isi sebagai berikut:

Ada banyak hal yang terjadi di sini, jadi mari kita telaah dengan perlahan.

start_link/2 adalah fungsi untuk memulai supervisor yang sebenarnya. Perhatikan bahwa child process (proses anakan) yang bersangkutan akan dimulai juga, jadi Anda tidak perlu mengetik CalcServer.start_link(5) lagi.

init/2 adalah callback yang harus dihadirkan untuk memakai behaviour. supervise Fungsinya, pada dasarnya, menggambarkan supervisor ini. di dalam anda tentukan proses anakan mana yang ingin diawasi. Kita, tentu saja, menentukan proses pekerja CalcServer[0]disini berarti keadaan awal dari proses itu sama dengan mengatakan CalcServer.start_link(0).

:one_for_one adalah nama dari strategi proses restart (menyerupai sebuah moto musketeer ternama). Strategi ini menentukan bahwa ketika proses anak berhenti, yang baru harus dimulai. Terdapat sejumlah beberapa strategi yang tesedia lainnya:

  • :one_for_all (bahkan lebih bergaya musketeer!)—merestart semua proses jika satu proses dihentikan.
  • :rest_for_one — proses anakan akan dimulai setelah proses yang terhenti direstart. proses yang terhenti juga direstar.
  • :simple_one_for_one — serupa dengan :one_for_one hanya memerlukan proses anakan untuk diadakan dalam penentuan (spesifikasi). Digunakan saat proses yang diawasi harus dimulai dan dihentikan secara dinamis.

Jadi ide keseluruhannya cukup sederhana:

  • Pertama, proses pengawas dimulai. init callback harus mengembalikan spesifikasi yang menjelaskan proses apa yang harus dipantau dan bagaimana menangani crash.
  • Proses anakan yang diawasi dimulai sesuai spesifikasi.
  • Setelah proses anakan macet, informasi tersebut dikirim ke supervisor berkat link yang ditetapkan. Supervisor kemudian mengikuti strategi restart dan melakukan tindakan yang diperlukan.

Sekarang Anda dapat menjalankan kembali program Anda dan mencoba membaginya dengan nol:

Jadi keadaan tersebut hilang, tetapi prosesnya berjalan meskipun kesalahan telah terjadi, yang berarti bahwa pengawas kita bekerja dengan baik!

Proses anakan ini cukup anti peluru (handal), dan Anda benar-benar akan memiliki waktu yang sulit untuk memusnahkannya:

Perhatikan, bagaimanapun, bahwa secara teknis prosesnya tidak dimulai kembali — melainkan, yang baru sedang dimulai, jadi id proses tidak akan sama. Ini pada dasarnya berarti Anda harus memberikan nama proses Anda ketika memulainya.

Aplikasi

Anda mungkin merasa agak membosankan untuk memulai supervisor secara manual setiap waktu. Untungnya, cukup mudah untuk memperbaikinya dengan menggunakanmodul aplikasi. contoh kasus yang paling mudah, anda hanya perlu membuat dua perubahan.

pertama-tama, ambil file mix.exs yang terletak di root proyek anda

Selanjutnya, masukkan modul Aplikasi dan berikan start/2callback yang akan berjalan secara otomotasi saat aplikasi anda dimulai:

Skarang setelah mengeksekusi perintah iex -S mix, supervisor Anda akan segera bangun dan berjalan!

Restart tak terbatas?

Anda mungkin bertanya-tanya apa yang akan terjadi jika prosesnya terus-menerus macet dan supervisor yang bersangkutan merestartnya lagi. Apakah siklus ini akan berjalan tanpa batas? Yah, sebenarnya, tidak. Secara default, hanya3 restart within 5 5 detik diperbolehkan — tidak lebih dari itu. Jika lebih banyak restart terjadi, supervisor menyerah dan membunuh dirinya sendiri dan semua proses anakan. Kedengarannya mengerikan, ya?

Anda dapat dengan mudah memeriksanya cepat jalankan baris kode berikut dan lakukan lagi dan lagi (atau melakukannya dalam siklus):

Terdapat 2 pilihan yang dapat kamu ambil untuk merubah perilaku ini:

  • :max_restarts—berapa banyak restart yang diizinkan dalam jangka waktu tersebut
  • :max_seconds—jangka waktu yang sesungguhnya

Kedua opsi ini harus diteruskan ke fungsi supervise di dalam init callback:

Kesimpulan

Dalam artikel ini, kita sudah membicarakan prihal Elixir Supervisors, yang memungkinkan kita untuk mengawasi dan merestart proses anakan sesuai kebutuhan. Kita sudah melihat bagaimana cara mereka bisa mengawasi proses anda dan merestartnya sesuai kebutuhan, dan bagaimana cara mengambil pengaturan variatif, termasuk strategi restart dan frequensi restart.

Semoga Anda menemukan artikel ini bermanfaat dan menarik. Saya berterima kasih untuk tetap bersama saya dan sampai waktu berikutnya!

Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.