Erlang OTP: Distributed & Fault-Tolerant Systems Programming · บทเรียน

โครงสร้างต้นไม้การควบคุมที่ซับซ้อน

ออกแบบและใช้งานลำดับชั้นการควบคุมแบบซ้อนที่ซับซ้อน เพื่อจัดการสิ่งที่ต้องพึ่งพาและขอบเขตความล้มเหลวได้อย่างมีประสิทธิภาพ

บทเรียน 1 จาก 411 ขั้นตอน

โครงสร้างต้นไม้การควบคุมที่ซับซ้อน เป็นบทเรียน Erlang OTP: Distributed & Fault-Tolerant Systems Programming ฟรีบน CoddyKit นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Erlang OTP: Distributed & Fault-Tolerant Systems Programming และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Erlang OTP: Distributed & Fault-Tolerant Systems Programming มีบทเรียนทั้งหมด 4 บทเรียน

บางส่วนของบทเรียนนี้ยังไม่ได้รับการแปล และแสดงเป็นภาษาอังกฤษ

Supervision Trees: The Basics

In Erlang, supervisors are special processes that oversee other processes, called children. If a child process crashes, the supervisor can restart it, ensuring fault tolerance.

A supervision tree is formed when a supervisor itself becomes a child of another supervisor. This creates a hierarchy, much like an organizational chart.

Why Complex Trees?

As applications grow, a single supervisor isn't enough. Complex supervision trees allow us to:

  • Manage dependencies: Group related processes so they start and stop together.
  • Isolate failures: A crash in one part of the tree won't necessarily bring down unrelated parts.
  • Improve modularity: Each supervisor can be responsible for a specific subsystem, making the application easier to understand and maintain.

Child Spec: Worker vs. Supervisor

Every process a supervisor manages is defined by a child specification. A child spec tells the supervisor how to start, restart, and shut down the child process.

Crucially, a child can be of two types:

  • worker: A regular process (like a gen_server) that performs application logic.
  • supervisor: Another supervisor process, forming a nested level in the tree.

The Worker: my_worker_module

Let's start with a simple worker process. This gen_server will be the leaf node in our supervision tree. It just prints messages when it starts or receives calls.

-module(my_worker_module).
-behaviour(gen_server).

-export([start_link/1, init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).

start_link(Id) ->
    gen_server:start_link(?MODULE, Id, []).

init(Id) ->
    io:format("Worker ~p starting...~n", [Id]),
    {ok, Id}.

handle_call(Req, _From, State) ->
    io:format("Worker ~p received call: ~p~n", [State, Req]),
    {reply, ok, State}.

handle_cast(Msg, State) ->
    io:format("Worker ~p received cast: ~p~n", [State, Msg]),
    {noreply, State}.

handle_info(Msg, State) ->
    io:format("Worker ~p received info: ~p~n", [State, Msg]),
    {noreply, State}.

terminate(_Reason, State) ->
    io:format("Worker ~p terminating...~n", [State]).

code_change(_OldVsn, State, _Extra) ->
    {ok, State}.

The Nested Supervisor: my_nested_sup

This supervisor will manage our my_worker_module processes. It defines two workers, 'WorkerA' and 'WorkerB', each with slightly different restart strategies.

Notice how its child_specs define type => worker.

-module(my_nested_sup).
-behaviour(supervisor).

-export([start_link/0, init/1]).

start_link() ->
    supervisor:start_link({local, ?MODULE}, ?MODULE, []).

init([]) ->
    SupFlags = #{
        strategy => one_for_one,
        intensity => 10,
        period => 1
    },
    ChildSpecs = [
        #{
            id => worker_A,
            start => {my_worker_module, start_link, ["WorkerA"]},
            type => worker,
            restart => permanent,
            shutdown => 5000,
            modules => [my_worker_module]
        },
        #{
            id => worker_B,
            start => {my_worker_module, start_link, ["WorkerB"]},
            type => worker,
            restart => transient,
            shutdown => 2000,
            modules => [my_worker_module]
        }
    ],
    {ok, {SupFlags, ChildSpecs}}.

The Top-Level Supervisor: my_app_sup

This is the root of our complex tree. It supervises my_nested_sup. Notice that its child_spec for my_nested_sup has type => supervisor. This is how you build nested trees!

-module(my_app_sup).
-behaviour(supervisor).

-export([start_link/0, init/1]).

start_link() ->
    supervisor:start_link({local, ?MODULE}, ?MODULE, []).

init([]) ->
    SupFlags = #{
        strategy => one_for_one,
        intensity => 10,
        period => 1
    },
    ChildSpecs = [
        #{
            id => my_nested_sup_child,
            start => {my_nested_sup, start_link, []},
            type => supervisor,
            restart => permanent,
            shutdown => infinity,
            modules => [my_nested_sup]
        }
    ],
    {ok, {SupFlags, ChildSpecs}}.

Running the Complex Tree

To see our tree in action, compile all three modules (my_worker_module.erl, my_nested_sup.erl, my_app_sup.erl) and then start the top-level supervisor. You'll see the workers start up!

You can use supervisor:which_children(PidOrName) to inspect the tree.

% In the Erlang shell:

c(my_worker_module).
c(my_nested_sup).
c(my_app_sup).

{ok, MySupPid} = my_app_sup:start_link().

% Check the children of the top-level supervisor:
supervisor:which_children(MySupPid).

% Find the nested supervisor's PID:
{_, NestedSupPid, _, _} = lists:keyfind(my_nested_sup_child, 1, supervisor:which_children(MySupPid)).

% Check the children of the nested supervisor:
supervisor:which_children(NestedSupPid).

Visualizing the Hierarchy

Our complex supervision tree looks like this:

  • my_app_sup (top-level supervisor)
    • supervises my_nested_sup (a child supervisor)
      • supervises worker_A (a worker process)
      • supervises worker_B (a worker process)

This structure ensures that if worker_A crashes, only my_nested_sup handles it. If my_nested_sup itself crashes, my_app_sup will restart it, bringing worker_A and worker_B back to life.

Benefits of Complex Trees

Complex supervision trees are a cornerstone of building robust Erlang applications. They provide:

  • Fault Isolation: Failures are contained to specific branches.
  • Logical Grouping: Components with related functions are supervised together.
  • Clear Responsibilities: Each supervisor has a well-defined set of processes it's responsible for.
  • Scalability: Easier to add or remove subsystems without disrupting the entire application.

Quick Check: Supervision Trees

Which of the following are key benefits of using complex (nested) supervision trees in Erlang?

Recap: Complex Supervision

Today, we explored complex supervision trees in Erlang. We learned that supervisors can manage other supervisors, creating nested hierarchies. This powerful pattern enables robust fault tolerance by isolating failures, managing dependencies, and improving the modularity of your applications. By defining child specs with type => supervisor, you can build intricate and resilient Erlang systems.

เริ่มต้นได้ฟรี

เรียนรู้ Erlang ด้วย AI tutor — ฟรี

เขียนและเรียกใช้โค้ดจริงในเบราว์เซอร์ของคุณ รับความช่วยเหลือทันทีจาก AI tutor 24/7 และเรียนรู้ต่อจากที่คุณหยุดบนเว็บหรือในแอป

คอร์ส
12
บทเรียน
48

คำถามที่พบบ่อย

บทเรียน “โครงสร้างต้นไม้การควบคุมที่ซับซ้อน” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “โครงสร้างต้นไม้การควบคุมที่ซับซ้อน” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Erlang OTP: Distributed & Fault-Tolerant Systems Programming ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Erlang OTP: Distributed & Fault-Tolerant Systems Programming มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “โครงสร้างต้นไม้การควบคุมที่ซับซ้อน”

ออกแบบและใช้งานลำดับชั้นการควบคุมแบบซ้อนที่ซับซ้อน เพื่อจัดการสิ่งที่ต้องพึ่งพาและขอบเขตความล้มเหลวได้อย่างมีประสิทธิภาพ คุณปฏิบัติ Erlang OTP: Distributed & Fault-Tolerant Systems Programming ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Erlang OTP: Distributed & Fault-Tolerant Systems Programming หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน Erlang OTP: Distributed & Fault-Tolerant Systems Programming บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน

บทเรียน “โครงสร้างต้นไม้การควบคุมที่ซับซ้อน” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน Erlang OTP: Distributed & Fault-Tolerant Systems Programming นี้ได้ไหม

ได้ บทเรียน Erlang OTP: Distributed & Fault-Tolerant Systems Programming ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. โครงสร้างต้นไม้การควบคุมที่ซับซ้อน
  2. การจัดการโพรเซสแบบไดนามิก
  3. กลยุทธ์การเริ่มต้นใหม่ขั้นสูง
  4. สะพานตัวควบคุมและลำดับชั้นกระบวนการแบบผสม
← กลับไปที่ Erlang OTP: Distributed & Fault-Tolerant Systems Programming