Elixir & Phoenix: Pembangunan Bahagian Belakang Boleh Skala · Pelajaran

Strategi Penyeliaan Lanjutan

Terokai pelbagai strategi penyeliaan melangkaui `:one_for_one` dan reka bentuk sistem toleran terhadap kegagalan yang kukuh.

Pelajaran 2 daripada 411 langkah

Strategi Penyeliaan Lanjutan ialah pelajaran Elixir & Phoenix: Pembangunan Bahagian Belakang Boleh Skala percuma di CoddyKit. Ini ialah pelajaran 2 daripada 4. Anda boleh membaca keseluruhan pelajaran di bawah secara percuma — kemudian berlatih secara praktikal dalam pelayar menggunakan penyunting kod terbina dalam dan tutor kecerdasan buatan 24/7. Pelajaran ini merupakan sebahagian daripada laluan pembelajaran Elixir & Phoenix: Pembangunan Bahagian Belakang Boleh Skala, dan kemajuan anda disegerakkan merentas web serta aplikasi CoddyKit. Kursus Elixir & Phoenix: Pembangunan Bahagian Belakang Boleh Skala merangkumi sejumlah 4 pelajaran.

Melangkaui Penyeliaan Asas

Dalam Elixir, penyelia ialah kunci untuk membina aplikasi yang tahan terhadap kegagalan. Anda mungkin pernah menemui strategi lalai :one_for_one.

Strategi ini hanya memulakan semula proses anak yang mengalami kegagalan. Tetapi bagaimana jika proses-proses tersebut sangat berkait rapat atau mempunyai kebergantungan?

Elixir menawarkan strategi penyeliaan yang lebih lanjut untuk mengendalikan senario kegagalan yang kompleks, sekali gus memastikan aplikasi anda kekal kukuh.

Strategi: Satu untuk Semua

Strategi :one_for_all berkuasa untuk proses yang sangat berkait rapat.

  • Fungsinya: Jika mana-mana proses anak terhenti, semua proses anak yang lain ditamatkan, kemudian semua anak dimulakan semula.
  • Bilakah perlu digunakan: Sesuai apabila proses anak saling bergantung dan tidak dapat berfungsi dengan betul jika salah satu daripadanya gagal. Bayangkan sekumpulan proses yang mesti sentiasa berada dalam keadaan yang konsisten bersama-sama.

Strategi ini memastikan seluruh kumpulan sentiasa berada dalam keadaan baharu dan konsisten selepas kegagalan.

Satu untuk Semua dalam Tindakan

Mari kita lihat :one_for_all dengan dua pekerja. Jika Worker 1 mengalami kegagalan, kedua-dua Worker 1 dan Worker 2 akan dimulakan semula.

Perhatikan output yang menunjukkan kedua-dua pekerja ditamatkan dan kemudian dimulakan semula.

defmodule Main do
  defmodule MyWorker do
    use GenServer

    def start_link(name) do
      GenServer.start_link(__MODULE__, nil, name: name)
    end

    def init(_) do
      IO.puts("Worker #{inspect(self())} started!")
      {:ok, %{}}
    end

    def handle_call(:crash, _from, state) do
      IO.puts("Worker #{inspect(self())} crashing!")
      exit(:boom)
      {:reply, :crashed, state}
    end

    def handle_call(:status, _from, state) do
      {:reply, :ok, state}
    end

    def terminate(reason, _state) do
      IO.puts("Worker #{inspect(self())} terminating due to #{inspect(reason)}!")
    end
  end

  def main() do
    children = [
      {MyWorker, :worker1},
      {MyWorker, :worker2}
    ]

    opts = [strategy: :one_for_all, name: MyOFA_Supervisor]
    {:ok, _pid} = Supervisor.start_link(children, opts)

    Process.sleep(100)

    IO.puts("\n--- Initial state ---")
    GenServer.call(:worker1, :status, 100)
    GenServer.call(:worker2, :status, 100)

    IO.puts("\n--- Crashing Worker 1 ---")
    try do
      GenServer.call(:worker1, :crash, 100)
    rescue
      _ -> IO.puts("Worker 1 process exited.")
    end

    Process.sleep(500)

    IO.puts("\n--- After crash and restart ---")
    GenServer.call(:worker1, :status, 100)
    GenServer.call(:worker2, :status, 100)

    :ok
  end
end

Main.main()

Strategi: Selebihnya untuk Satu

Strategi :rest_for_one berguna untuk proses yang mempunyai rantaian kebergantungan linear.

  • Fungsinya: Jika proses anak terhenti, proses itu dan semua proses anak berikutnya (yang dimulakan kemudian) ditamatkan dan kemudian dimulakan semula. Proses yang dimulakan sebelum proses anak yang mengalami kegagalan dibiarkan tanpa perubahan.
  • Bilakah perlu digunakan: Gunakan strategi ini apabila proses mempunyai kebergantungan berantai. Contohnya, jika Proses C bergantung pada Proses B, dan Proses B bergantung pada Proses A. Jika B mengalami kegagalan, C juga mesti dimulakan semula, tetapi A tidak terjejas.

Ini ialah permulaan semula yang lebih terarah berbanding :one_for_all.

Selebihnya untuk Satu dalam Tindakan

Di sini, kita mempunyai tiga pekerja. Jika Worker 2 mengalami kegagalan, Worker 2 dan Worker 3 akan dimulakan semula, tetapi Worker 1 tidak akan terjejas.

Perhatikan bahawa hanya proses yang terjejas dan proses yang bergantung padanya dimulakan semula.

defmodule Main do
  defmodule MyWorker do
    use GenServer

    def start_link(name) do
      GenServer.start_link(__MODULE__, nil, name: name)
    end

    def init(_) do
      IO.puts("Worker #{inspect(self())} started!")
      {:ok, %{}}
    end

    def handle_call(:crash, _from, state) do
      IO.puts("Worker #{inspect(self())} crashing!")
      exit(:boom)
      {:reply, :crashed, state}
    end

    def handle_call(:status, _from, state) do
      {:reply, :ok, state}
    end

    def terminate(reason, _state) do
      IO.puts("Worker #{inspect(self())} terminating due to #{inspect(reason)}!")
    end
  end

  def main() do
    children = [
      {MyWorker, :worker1},
      {MyWorker, :worker2},
      {MyWorker, :worker3}
    ]

    opts = [strategy: :rest_for_one, name: MyRFO_Supervisor]
    {:ok, _pid} = Supervisor.start_link(children, opts)

    Process.sleep(100)

    IO.puts("\n--- Initial state ---")
    GenServer.call(:worker1, :status, 100)
    GenServer.call(:worker2, :status, 100)
    GenServer.call(:worker3, :status, 100)

    IO.puts("\n--- Crashing Worker 2 ---")
    try do
      GenServer.call(:worker2, :crash, 100)
    rescue
      _ -> IO.puts("Worker 2 process exited.")
    end

    Process.sleep(500)

    IO.puts("\n--- After crash and restart ---")
    GenServer.call(:worker1, :status, 100)
    GenServer.call(:worker2, :status, 100)
    GenServer.call(:worker3, :status, 100)

    :ok
  end
end

Main.main()

Keamatan Permulaan Semula Penyelia

Penyelia juga mempunyai pilihan untuk menghalang gelung permulaan semula tanpa penghujung, yang boleh menggunakan sumber sistem.

  • :max_restarts: Bilangan maksimum proses anak (atau kumpulan proses, bergantung pada strategi) boleh dimulakan semula dalam tempoh tertentu.
  • :max_seconds: Tempoh masa (dalam saat) yang digunakan untuk mengira :max_restarts.

Jika kiraan permulaan semula melebihi :max_restarts dalam tempoh :max_seconds, penyelia itu sendiri akan ditamatkan dan berkemungkinan menyebabkan penyelianya turut mengalami kegagalan.

Contoh Keamatan Permulaan Semula

Di sini, kita menetapkan max_restarts: 2 dan max_seconds: 5. Jika Worker 1 mengalami kegagalan lebih daripada dua kali dalam tempoh 5 saat, penyelia akan berputus asa dan mengalami kegagalan sendiri.

Jalankan kod ini beberapa kali dan perhatikan penyelia ditamatkan.

defmodule Main do
  defmodule MyWorker do
    use GenServer

    def start_link(name) do
      GenServer.start_link(__MODULE__, nil, name: name)
    end

    def init(_) do
      IO.puts("Worker #{inspect(self())} started!")
      {:ok, %{}}
    end

    def handle_call(:crash, _from, state) do
      IO.puts("Worker #{inspect(self())} crashing!")
      exit(:boom)
      {:reply, :crashed, state}
    end

    def handle_call(:status, _from, state) do
      {:reply, :ok, state}
    end

    def terminate(reason, _state) do
      IO.puts("Worker #{inspect(self())} terminating due to #{inspect(reason)}!")
    end
  end

  def main() do
    children = [
      {MyWorker, :worker1}
    ]

    opts = [strategy: :one_for_one, name: MyIntensitySupervisor,
            max_restarts: 2, max_seconds: 5]
    {:ok, sup_pid} = Supervisor.start_link(children, opts)

    Process.sleep(100)

    IO.puts("\n--- Crashing Worker 1 repeatedly ---")
    Enum.each(1..3, fn i ->
      IO.puts("Attempt #{i}:")
      try do
        GenServer.call(:worker1, :crash, 100)
      rescue
        _ -> IO.puts("Worker 1 process exited.")
      end
      Process.sleep(100) # Short delay between crashes
    end)

    Process.sleep(1000) # Give supervisor time to react

    IO.puts("\n--- Supervisor status ---")
    if Process.is_alive(sup_pid) do
      IO.puts("Supervisor is still alive.")
    else
      IO.puts("Supervisor has terminated due to excessive restarts.")
    end

    :ok
  end
end

Main.main()

Strategi Penyeliaan Tersuai

Walaupun :one_for_one, :one_for_all dan :rest_for_one merangkumi kebanyakan keadaan, Elixir membenarkan strategi penyeliaan tersuai.

  • Anda boleh melaksanakan tingkah laku Supervisor sendiri.
  • Ini melibatkan penentuan init/1 dan pengendalian logik permulaan semula berdasarkan argumen :which_child dalam handle_call/3.

Ini ialah topik lanjutan yang biasanya diperlukan untuk dasar permulaan semula yang sangat khusus dan kompleks, yang tidak diliputi oleh strategi terbina dalam.

Bilakah Perlu Menggunakan Setiap Strategi?

Memilih strategi yang betul amat penting untuk ketahanan aplikasi anda.

  • :one_for_one: Proses bebas, dan merupakan lalai. Paling biasa digunakan.
  • :one_for_all: Proses yang sangat berkait rapat dan memerlukan konsistensi sebagai keutamaan.
  • :rest_for_one: Proses dengan kebergantungan linear dan berantai.
  • Tersuai: Jarang digunakan, untuk keperluan permulaan semula yang unik.

Sentiasa pertimbangkan hubungan dan kebergantungan antara proses anda apabila mereka bentuk pepohon penyeliaan.

Kuiz Penyelia Lanjutan

Proses kritikal P1 menyediakan perkhidmatan yang sangat bergantung pada P2 dan P3. Jika P1 mengalami kegagalan, P2 dan P3 tidak dapat berfungsi dengan betul dan juga perlu dimulakan semula untuk memastikan konsistensi data.

Strategi penyeliaan manakah yang paling sesuai untuk penyelia yang mengurus P1, P2 dan P3 dalam senario ini?

Ulang Kaji: Penyeliaan Kukuh

Kini anda telah meneroka strategi penyeliaan Elixir lanjutan yang melangkaui :one_for_one lalai.

  • :one_for_all memulakan semula semua anak jika mana-mana anak gagal.
  • :rest_for_one memulakan semula anak yang gagal dan semua anak berikutnya.
  • Anda juga telah mempelajari max_restarts dan max_seconds untuk mengawal keamatan permulaan semula.

Alat-alat ini membolehkan anda mereka bentuk aplikasi yang sangat berdaya tahan dan tahan terhadap kegagalan dengan mengawal tindak balas sistem anda terhadap kegagalan proses secara tepat.

Percuma untuk bermula

Pelajari Elixir dengan tutor kecerdasan buatan — percuma

Tulis dan jalankan kod sebenar dalam pelayar anda, dapatkan bantuan segera daripada tutor kecerdasan buatan yang tersedia 24/7, dan sambung semula dari tempat anda berhenti di web atau dalam aplikasi.

Kursus
12
Pelajaran
48

Soalan Lazim

Adakah pelajaran “Strategi Penyeliaan Lanjutan” percuma?

Ya — teks penuh “Strategi Penyeliaan Lanjutan” boleh dibaca secara percuma di web ini. Untuk berlatih secara interaktif menggunakan penyunting kod terbina dalam dan tutor kecerdasan buatan 24/7, serta membuka kunci baki kursus Elixir & Phoenix: Pembangunan Bahagian Belakang Boleh Skala, tingkat taraf kepada CoddyKit PRO. Kursus Elixir & Phoenix: Pembangunan Bahagian Belakang Boleh Skala merangkumi sejumlah 4 pelajaran.

Apakah yang akan saya pelajari dalam “Strategi Penyeliaan Lanjutan”?

Terokai pelbagai strategi penyeliaan melangkaui `:one_for_one` dan reka bentuk sistem toleran terhadap kegagalan yang kukuh. Anda berlatih Elixir & Phoenix: Pembangunan Bahagian Belakang Boleh Skala menggunakan kod praktikal yang dijalankan terus dalam pelayar, manakala tutor kecerdasan buatan 24/7 menjawab soalan anda semasa anda mengikuti pelajaran.

Adakah saya memerlukan pengalaman untuk memulakan Elixir & Phoenix: Pembangunan Bahagian Belakang Boleh Skala?

Tiada pengalaman terdahulu diperlukan. Pembelajaran Elixir & Phoenix: Pembangunan Bahagian Belakang Boleh Skala di CoddyKit disusun untuk pelajar daripada peringkat pemula hingga lanjutan, jadi anda boleh bermula di sini atau dari awal dan belajar mengikut kadar anda sendiri. Ini ialah pelajaran 2 daripada 4.

Berapa lamakah pelajaran “Strategi Penyeliaan Lanjutan” diambil?

Kebanyakan pelajaran CoddyKit mengambil masa kira-kira 5–10 minit. Setiap pelajaran ringkas dan interaktif, jadi anda boleh membuat kemajuan secara berterusan dan menyambung tepat dari tempat anda berhenti di web atau aplikasi.

Bolehkah saya menulis dan menjalankan kod dalam pelajaran Elixir & Phoenix: Pembangunan Bahagian Belakang Boleh Skala ini?

Ya. Setiap pelajaran Elixir & Phoenix: Pembangunan Bahagian Belakang Boleh Skala menyertakan penyunting kod terbina dalam, jadi anda boleh menulis dan menjalankan kod sebenar terus dalam pelayar serta menerima maklum balas kecerdasan buatan serta-merta — tanpa memerlukan persediaan setempat.

Semua pelajaran dalam kursus ini

  1. Elixir Teragih dan Pengelompokan
  2. Strategi Penyeliaan Lanjutan
  3. Penyelia Dinamik dan Registry
  4. Saluran Paip GenStage dan Tekanan Balik
← Kembali ke Elixir & Phoenix: Pembangunan Bahagian Belakang Boleh Skala