Implementera GenServer-behavior
Lär er implementera en GenServer, hantera tillstånd och behandla synkrona och asynkrona anrop – grunden för de flesta Erlang-komponenter.
Implementera GenServer-behavior är en gratis lektion i Erlang OTP: Programmering av distribuerade och feltoleranta system på CoddyKit. Detta är lektion 2 av 4. Du kan läsa vilka 3 lektioner som helst i den här lärvägen kostnadsfritt i sin helhet – därefter låser CoddyKit PRO upp alla lektioner, plus praktisk övning med en inbyggd kodredigerare och en AI-lärare dygnet runt. Den ingår i lärvägen för Erlang OTP: Programmering av distribuerade och feltoleranta system, och Era framsteg synkroniseras mellan webben och CoddyKit-appen. Kursen i Erlang OTP: Programmering av distribuerade och feltoleranta system innehåller totalt 4 lektioner.
Vad är en GenServer?
Välkommen tillbaka! I den förra lektionen lärde vi oss om Erlangs OTP-behaviors. Ett av de viktigaste är GenServer.
- En GenServer är en generisk server som hanterar begäranden.
- Den hanterar internt tillstånd och bearbetar meddelanden sekventiellt.
- Se den som ett standardiserat sätt att bygga tillförlitliga och feltoleranta serverprocesser i Erlang.
Den utgör grunden för många Erlang-applikationer.
GenServers kärna: callbacks
För att implementera en GenServer definierar du en modul som exporterar specifika callback-funktioner. Dessa funktioner anropas av behavioren gen_server i olika steg.
init/1: Initierar serverns tillstånd.handle_call/3: Hanterar synkrona klientbegäranden (förväntar sig ett svar).handle_cast/2: Hanterar asynkrona klientbegäranden (skicka och glöm).terminate/2: Stänger ner resurser när servern stoppas.code_change/3: Hanterar koduppgraderingar under drift.
I den här lektionen fokuserar vi på init, handle_call och handle_cast.
Initiera tillstånd med `init/1`
Varje GenServer börjar med att initiera sitt tillstånd. Detta görs i callback-funktionen init/1.
Den tar ett argument (vanligtvis en lista med argument som skickas vid uppstart) och ska returnera {ok, State}, där State är de initiala data som din GenServer ska hantera.
Här är en grundläggande init-funktion:
-module(my_counter).
-behaviour(gen_server).
-export([init/1]).
init([]) ->
io:format("Counter initialized with state 0.~n"),
{ok, 0}.Starta en GenServer-process
För att få vår GenServer att köra måste vi starta den. Det vanligaste sättet är att använda gen_server:start_link/3 eller gen_server:start_link/4. Vi lägger till en start_link/0-funktion i vår modul.
Funktionen start_link skapar en ny Erlang-process och länkar den till den anropande processen, vilket gör den till en del av ett övervakningsträd (mer om detta senare!).
-module(my_counter).
-behaviour(gen_server).
-export([start_link/0, init/1]).
start_link() ->
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
init([]) ->
io:format("Counter process started!~n"),
{ok, 0}.Synkrona anrop: `handle_call`
När en klient behöver ett svar från servern gör den ett synkront anrop med gen_server:call/2 eller gen_server:call/3.
GenServer hanterar dessa begäranden i sin callback handle_call/3. Funktionen tar tre argument:
Request: Meddelandet från klienten.From: Den sändande processens ID (Pid) och en tagg.State: GenServers aktuella interna tillstånd.
Den returnerar vanligtvis {reply, Reply, NewState}.
Implementera `handle_call` (räknare)
Vi lägger till en increment-funktion i vår räknare. Detta blir ett synkront anrop, vilket innebär att klienten väntar på det nya värdet.
Prova att köra den här koden. Kompilera den först (c(my_counter).) och starta den sedan (my_counter:start_link().). Därefter kan du anropa my_counter:increment(). för att se räknaren öka.
-module(my_counter).
-behaviour(gen_server).
-export([start_link/0, increment/0, get_count/0]).
-export([init/1, handle_call/3, handle_cast/2, terminate/2, code_change/3]).
start_link() ->
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
increment() ->
gen_server:call(?MODULE, increment).
get_count() ->
gen_server:call(?MODULE, get_count).
init([]) ->
{ok, 0}.
handle_call(increment, _From, State) ->
NewState = State + 1,
{reply, NewState, NewState};
handle_call(get_count, _From, State) ->
{reply, State, State};
handle_call(_Request, _From, State) ->
{reply, {error, bad_request}, State}.
handle_cast(_Msg, State) -> % Placeholder
{noreply, State}.
terminate(_Reason, _State) -> ok.
code_change(_OldVsn, State, _Extra) -> {ok, State}.Asynkrona anrop: `handle_cast`
Ibland behöver en klient inget svar utan vill bara skicka ett meddelande utan att vänta. Detta är ett asynkront anrop med gen_server:cast/2.
GenServer hanterar dessa meddelanden i sin callback handle_cast/2. Den tar två argument:
Message: Meddelandet från klienten.State: GenServers aktuella interna tillstånd.
Den returnerar alltid {noreply, NewState}, eftersom inget svar skickas tillbaka till klienten.
Implementera `handle_cast` (återställning)
Vi lägger till en reset-funktion i vår räknare. Detta blir ett asynkront anrop, eftersom klienten inte behöver känna till det nya värdet direkt.
Kompilera och starta modulen som tidigare. Anropa `my_counter:increment().` några gånger och sedan `my_counter:reset().`. Du kommer att märka att `reset` returnerar direkt utan något värde.
-module(my_counter).
-behaviour(gen_server).
-export([start_link/0, increment/0, get_count/0, reset/0]).
-export([init/1, handle_call/3, handle_cast/2, terminate/2, code_change/3]).
start_link() ->
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
increment() ->
gen_server:call(?MODULE, increment).
get_count() ->
gen_server:call(?MODULE, get_count).
reset() ->
gen_server:cast(?MODULE, reset).
init([]) ->
{ok, 0}.
handle_call(increment, _From, State) ->
NewState = State + 1,
{reply, NewState, NewState};
handle_call(get_count, _From, State) ->
{reply, State, State};
handle_call(_Request, _From, State) ->
{reply, {error, bad_request}, State}.
handle_cast(reset, _State) ->
{noreply, 0};
handle_cast(_Msg, State) ->
{noreply, State}.
terminate(_Reason, _State) -> ok.
code_change(_OldVsn, State, _Extra) -> {ok, State}.Hantera GenServers tillstånd
GenServers styrka ligger i hur de hanterar tillstånd. Argumentet State skickas till varje callback, och callback-funktionen returnerar ett NewState.
- Detta säkerställer att endast en process (själva GenServer-processen) någonsin ändrar dess tillstånd, vilket förhindrar kapplöpningstillstånd.
- Det gör serverns interna logik enklare att förstå och resonera kring.
- Tillståndet kan vara vilken Erlang-term som helst: ett heltal, en lista, en map, en post eller en komplex datastruktur.
Denna sekventiella meddelandehantering och explicita överföring av tillstånd är central i Erlangs samtidighetsmodell.
Typer av GenServer-anrop
Vilka av följande påståenden om GenServer-anrop är SANNA?
Sammanfattning: implementera GenServer
Du har nu byggt din första GenServer! Här är det vi gick igenom:
- GenServers är standardbeteenden i OTP för att bygga servrar med tillstånd.
- Callback-funktionen
init/1initierar serverns tillstånd. gen_server:start_linkskapar GenServer-processen.handle_call/3hanterar synkrona begäranden (klienten väntar på svar).handle_cast/2hanterar asynkrona meddelanden (klienten väntar inte).- GenServers hanterar sitt tillstånd genom att skicka det mellan callback-funktioner, vilket säkerställer sekventiella uppdateringar.
Härnäst ska vi se hur supervisors automatiskt kan starta om GenServers som har kraschat!
Lär dig Erlang med en AI-lärare – gratis
Skriv och kör riktig kod i webbläsaren, få omedelbar hjälp av en AI-lärare dygnet runt och fortsätt där du slutade – på webben eller i appen.
- Kurser
- 12
- Lektioner
- 48
Vanliga frågor
Är lektionen ”Implementera GenServer-behavior” gratis?
Ja – du kan läsa vilka 3 lektioner som helst i lärvägen Erlang OTP: Programmering av distribuerade och feltoleranta system, inklusive ”Implementera GenServer-behavior”, kostnadsfritt i sin helhet här på webben. Därefter låser CoddyKit PRO upp alla lektioner, plus interaktiv övning med en inbyggd kodredigerare och en AI-lärare dygnet runt. Kursen i Erlang OTP: Programmering av distribuerade och feltoleranta system innehåller totalt 4 lektioner.
Vad lär jag mig i ”Implementera GenServer-behavior”?
Lär er implementera en GenServer, hantera tillstånd och behandla synkrona och asynkrona anrop – grunden för de flesta Erlang-komponenter. Ni övar på Erlang OTP: Programmering av distribuerade och feltoleranta system med praktisk kod som körs direkt i webbläsaren, medan en AI-handledare som är tillgänglig dygnet runt svarar på Era frågor under lektionen.
Behöver jag någon erfarenhet för att börja lära mig Erlang OTP: Programmering av distribuerade och feltoleranta system?
Du behöver inga förkunskaper. Utbildningen i Erlang OTP: Programmering av distribuerade och feltoleranta system på CoddyKit är upplagd för allt från nybörjare till avancerade elever, så att du kan börja här eller från början och gå fram i din egen takt. Detta är lektion 2 av 4.
Hur lång tid tar lektionen ”Implementera GenServer-behavior”?
De flesta CoddyKit-lektioner tar cirka 5–10 minuter. Varje lektion är kort och interaktiv, så att du gör stadiga framsteg och kan fortsätta precis där du slutade – på webben eller i appen.
Kan jag skriva och köra kod i den här Erlang OTP: Programmering av distribuerade och feltoleranta system-lektionen?
Ja. Varje Erlang OTP: Programmering av distribuerade och feltoleranta system-lektion innehåller en inbyggd kodredigerare, så att du kan skriva och köra riktig kod direkt i webbläsaren och få omedelbar AI-feedback – utan lokal installation.
Alla lektioner i den här kursen
- Förstå OTP och behaviors
- Implementera GenServer-behavior
- Introduktion till supervisors
- Bygga OTP-applikationer och releaser