Erlang OTP: Programmering af distribuerede og fejltolerante systemer · Lektion

Avancerede genstartstrategier

Fordyb Dem i genstartstrategierne one_for_one, one_for_all og rest_for_one, og forstå deres betydning for fejltolerance.

Lektion 3 af 411 trin

Avancerede genstartstrategier er en gratis Erlang OTP: Programmering af distribuerede og fejltolerante systemer-lektion på CoddyKit. Dette er lektion 3 af 4. Du kan læse alle 3 lektioner i dette læringsspor gratis i deres fulde længde — derefter låser CoddyKit PRO alle lektioner op samt praktiske øvelser med en indbygget kodeeditor og en AI-underviser døgnet rundt. Den er en del af læringsforløbet i Erlang OTP: Programmering af distribuerede og fejltolerante systemer, og dine fremskridt synkroniseres på tværs af nettet og CoddyKit-appen. Erlang OTP: Programmering af distribuerede og fejltolerante systemer-kurset indeholder 4 lektioner i alt.

Introduktion til genstartsstrategier

Velkommen til et vigtigt emne i Erlang: genstartsstrategier! De definerer, hvordan en supervisor reagerer, når en af dens underordnede processer går ned.

Det er afgørende at forstå disse strategier for at opbygge fejltolerante og selvreparerende systemer, som er kendetegnende for Erlang/OTP.

Supervisorer: Fejlhåndteringsansvarlige

Før vi går i dybden, får du en kort opsummering: En supervisor er en særlig proces, der overvåger andre processer (sine børn).

  • Hvis en underordnet proces dør, registrerer supervisoren det.
  • På baggrund af den konfigurerede genstartsstrategi beslutter supervisoren, hvordan systemet bringes tilbage i en sund tilstand.
  • Det sikrer, at din applikation automatisk kan komme sig efter fejl i enkelte processer.

`one_for_one`: Isolerede genstarter

Strategien one_for_one er den enkleste og mest almindelige. Når en underordnet proces afsluttes:

  • Genstartes kun den fejlramte underordnede proces.
  • Alle andre søskendeprocesser forbliver upåvirkede og fortsætter med at køre.

Denne strategi er ideel til systemer, hvor de underordnede processer i høj grad er uafhængige af hinanden, f.eks. individuelle klientforbindelser.

`one_for_one` i praksis

Lad os se one_for_one i praksis. Vi har en supervisor, der administrerer en enkelt arbejder. Når arbejderen går ned, genstartes kun den.

Sådan køres det:
1. Kompilér: c(worker_gen). c(supervisor_one_for_one).
2. Start supervisoren: supervisor_one_for_one:start_link().
3. Få arbejderen til at gå ned: worker_gen:crash(worker_1).
Se outputtet i din Erlang-shell.

-module(worker_gen).
-behaviour(gen_server).
-export([start_link/1, init/1, handle_call/3, terminate/2, crash/1]).

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

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

handle_call(crash, _From, State) ->
    exit(i_crashed),
    {reply, ok, State};
handle_call(_Req, _From, State) ->
    {reply, ok, State}.

terminate(_Reason, Id) ->
    io:format("Worker ~p (~p) terminated.~n", [Id, self()]).

crash(Id) ->
    gen_server:call(Id, crash).

-module(supervisor_one_for_one).
-behaviour(supervisor).
-export([start_link/0, init/1]).

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

init([]) ->
    ChildSpec = #{
        id => worker_1,
        start => {worker_gen, start_link, [worker_1]},
        restart => permanent,
        shutdown => 5000,
        type => worker,
        modules => [worker_gen]
    },
    {ok, #{
        strategy => {one_for_one, 3, 5},
        children => [ChildSpec]
    }}.

`one_for_all`: Alle for én fejl

Strategien one_for_all anvender en mere drastisk tilgang:

  • Hvis en hvilken som helst underordnet proces afsluttes, afsluttes alle andre underordnede processer først.
  • Derefter genstartes alle underordnede processer, inklusive den proces, der gik ned.

Dette er nyttigt, når dine underordnede processer er tæt koblet og kræver en ensartet, synkroniseret tilstand. En fejl i én proces betyder, at hele gruppen skal nulstilles.

`one_for_all` i praksis

Her administrerer en supervisor to arbejdere. Få den ene til at gå ned, så genstartes de begge.

Sådan køres det:
1. Kompilér: c(worker_gen). c(supervisor_one_for_all).
2. Start supervisoren: supervisor_one_for_all:start_link().
3. Få arbejderen til at gå ned: worker_gen:crash(worker_A).
Bemærk, hvordan både worker_A og worker_B genstarter.

-module(worker_gen).
-behaviour(gen_server).
-export([start_link/1, init/1, handle_call/3, terminate/2, crash/1]).

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

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

handle_call(crash, _From, State) ->
    exit(i_crashed),
    {reply, ok, State};
handle_call(_Req, _From, State) ->
    {reply, ok, State}.

terminate(_Reason, Id) ->
    io:format("Worker ~p (~p) terminated.~n", [Id, self()]).

crash(Id) ->
    gen_server:call(Id, crash).

-module(supervisor_one_for_all).
-behaviour(supervisor).
-export([start_link/0, init/1]).

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

init([]) ->
    Child1 = #{
        id => worker_A,
        start => {worker_gen, start_link, [worker_A]},
        restart => permanent, shutdown => 5000, type => worker, modules => [worker_gen]
    },
    Child2 = #{
        id => worker_B,
        start => {worker_gen, start_link, [worker_B]},
        restart => permanent, shutdown => 5000, type => worker, modules => [worker_gen]
    },
    {ok, #{
        strategy => {one_for_all, 3, 5},
        children => [Child1, Child2]
    }}.

`rest_for_one`: Kaskadegenstarter

Strategien rest_for_one er et kompromis:

  • Hvis en underordnet proces afsluttes, afsluttes den selv og alle efterfølgende børn (dem, der er defineret efter den på supervisorens børneliste).
  • Derefter genstartes den fejlramte proces og alle efterfølgende børn.
  • Børn, der er defineret før den fejlramte proces, berøres ikke.

Dette er nyttigt, når processer har sekventielle afhængigheder, hvor en fejl på et tidligere trin kan gøre tilstanden på senere trin ugyldig.

`rest_for_one` i praksis

Vi har tre arbejdere: X, Y og Z. Hvis Y går ned, genstarter Y og Z, mens X forbliver aktiv.

Sådan køres det:
1. Kompilér: c(worker_gen). c(supervisor_rest_for_one).
2. Start supervisoren: supervisor_rest_for_one:start_link().
3. Få arbejderen til at gå ned: worker_gen:crash(worker_Y).
Se, hvordan worker_X fortsætter med at køre, mens worker_Y og worker_Z genstarter.

-module(worker_gen).
-behaviour(gen_server).
-export([start_link/1, init/1, handle_call/3, terminate/2, crash/1]).

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

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

handle_call(crash, _From, State) ->
    exit(i_crashed),
    {reply, ok, State};
handle_call(_Req, _From, State) ->
    {reply, ok, State}.

terminate(_Reason, Id) ->
    io:format("Worker ~p (~p) terminated.~n", [Id, self()]).

crash(Id) ->
    gen_server:call(Id, crash).

-module(supervisor_rest_for_one).
-behaviour(supervisor).
-export([start_link/0, init/1]).

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

init([]) ->
    ChildA = #{
        id => worker_X,
        start => {worker_gen, start_link, [worker_X]},
        restart => permanent, shutdown => 5000, type => worker, modules => [worker_gen]
    },
    ChildB = #{
        id => worker_Y,
        start => {worker_gen, start_link, [worker_Y]},
        restart => permanent, shutdown => 5000, type => worker, modules => [worker_gen]
    },
    ChildC = #{
        id => worker_Z,
        start => {worker_gen, start_link, [worker_Z]},
        restart => permanent, shutdown => 5000, type => worker, modules => [worker_gen]
    },
    {ok, #{
        strategy => {rest_for_one, 3, 5},
        children => [ChildA, ChildB, ChildC]
    }}.

Vælg den bedste strategi

Valget af den rigtige strategi afhænger af din applikations arkitektur og processernes afhængigheder:

  • one_for_one: Brug den til uafhængige processer som individuelle klientforbindelser eller anmodningshåndterere.
  • one_for_all: Bedst til tæt koblede processer, der altid skal være i en ensartet tilstand sammen (f.eks. en gruppe processer, der administrerer én ressource).
  • rest_for_one: Velegnet til sekventielle pipelines eller lagdelte systemer, hvor en fejl på et tidligere trin påvirker de efterfølgende trin.

Test din viden

Du er ved at opbygge et system, hvor en primær arbejder henter data, og to sekundære arbejdere behandler forskellige aspekter af disse data. Hvis den primære arbejder fejler, kan de sekundære arbejdere ikke fortsætte med forældede data og skal også genstartes. Hvis en sekundær arbejder fejler, påvirkes de andre ikke. Hvilken strategi er mest passende for den primære arbejder og dens afhængige sekundære arbejdere?

Opsummering: Få styr på genstarter

Du har gennemgået Erlangs effektive genstartsstrategier:

  • one_for_one: Genstarter kun det fejlramte barn, mens de andre fortsætter med at køre.
  • one_for_all: Genstarter alle børn, hvis et af dem fejler, så der sikres fuld ensartethed.
  • rest_for_one: Genstarter det fejlramte barn og alle efterfølgende børn på listen.

Disse strategier er grundlæggende for at opbygge robuste, selvreparerende applikationer i Erlang, så systemet kan komme sig kontrolleret efter fejl.

Gratis at komme i gang

Lær Erlang med en AI-underviser — gratis

Skriv og kør rigtig kode i din browser, få øjeblikkelig hjælp fra en AI-underviser døgnet rundt, og fortsæt, hvor du slap, på web eller i appen.

Kurser
12
Lektioner
48

Ofte stillede spørgsmål

Er lektionen “Avancerede genstartstrategier” gratis?

Ja — alle 3 lektioner i læringssporet Erlang OTP: Programmering af distribuerede og fejltolerante systemer, inklusive “Avancerede genstartstrategier”, kan læses gratis i deres fulde længde her på webstedet. Derefter låser CoddyKit PRO alle lektioner op samt interaktive øvelser med en indbygget kodeeditor og en AI-underviser døgnet rundt. Erlang OTP: Programmering af distribuerede og fejltolerante systemer-kurset indeholder 4 lektioner i alt.

Hvad lærer jeg i “Avancerede genstartstrategier”?

Fordyb Dem i genstartstrategierne one_for_one, one_for_all og rest_for_one, og forstå deres betydning for fejltolerance. Du øver dig i Erlang OTP: Programmering af distribuerede og fejltolerante systemer med praktisk kode, som du kører direkte i browseren, og en AI-vejleder døgnet rundt besvarer dine spørgsmål, mens du arbejder dig gennem lektionen.

Skal jeg have erfaring for at begynde på Erlang OTP: Programmering af distribuerede og fejltolerante systemer?

Der kræves ingen tidligere erfaring. Erlang OTP: Programmering af distribuerede og fejltolerante systemer på CoddyKit er tilrettelagt for både begyndere og øvede, så du kan starte her eller fra begyndelsen og lære i dit eget tempo. Dette er lektion 3 af 4.

Hvor lang tid tager lektionen “Avancerede genstartstrategier”?

De fleste CoddyKit-lektioner tager cirka 5–10 minutter. Hver lektion er kort og interaktiv, så du gør løbende fremskridt og kan fortsætte, hvor du slap – på både web og app.

Kan jeg skrive og køre kode i denne Erlang OTP: Programmering af distribuerede og fejltolerante systemer-lektion?

Ja. Alle Erlang OTP: Programmering af distribuerede og fejltolerante systemer-lektioner har en indbygget kodeeditor, så du kan skrive og køre rigtig kode direkte i din browser og få øjeblikkelig feedback fra AI – uden lokal opsætning.

Alle lektioner i dette kursus

  1. Komplekse supervisionstræer
  2. Dynamisk proceshåndtering
  3. Avancerede genstartstrategier
  4. Supervisor bridges og blandede proceshierarkier
← Tilbage til Erlang OTP: Programmering af distribuerede og fejltolerante systemer