Ho un problema: voglio creare un server Erlang in grado di contenere una connessione TCP simultanea aperta 1M. Ho ottimizzato il mio sistema operativo (Oracle Linux 7) per aumentare i descrittori di file. Sul server faccio gen_tcp: ascoltareErlang collega contemporaneamente client 1M
// point_1
Attacco = gen_tcp: accettare
spawn (maniglia (zoccolo)) // un altro thread
torna a point_1
se collego sequenzialmente non è un problema, in 100 secondi ho collegato client 100K; ma non ho avuto legami per di più.
Se voglio connettere quelli in un modo conncurent, solo circa 80 connessioni sono fatte da 100, per esempio.
Ecco come ho eseguito il tutto:
erlc *.erl
erl +Q 134217727 +P 1000000 -env ERL_MAX_PORTS 40960000 -env ERTS_MAX_PORTS 40960000
// avviare un server che sarà in ascolto sulla porta 9999
ex:start(1, 9999)
// 100 clienti cercano di connettersi sulla porta 9999
ex:connect_clients(100, 9999)
Lasciami mostrare un po 'di codice:
start(Num,LPort) ->
case gen_tcp:listen(LPort,[{active, false},{packet,2}]) of
{ok, ListenSock} ->
start_servers(Num,ListenSock),
{ok, Port} = inet:port(ListenSock),
Port;
{error,Reason} ->
{error,Reason}
end.
start_servers(0,_) ->
ok;
start_servers(Num,LS) ->
spawn(?MODULE,server,[LS,0]),
start_servers(Num-1,LS).
server(LS, Nr) ->
io:format("before accept ~w~n",[Nr]),
case gen_tcp:accept(LS) of
{ok,S} ->
io:format("after accept ~w~n",[Nr]),
spawn(ex,loop,[S]),
server(LS, Nr+1);
Other ->
io:format("accept returned ~w - goodbye!~n",[Other]),
ok
end.
loop(S) ->
inet:setopts(S,[{active,once}]),
receive
{tcp,S, _Data} ->
Answer = 1,
gen_tcp:send(S,Answer),
loop(S);
{tcp_closed,S} ->
io:format("Socket ~w closed [~w]~n",[S,self()]),
ok
end.
client(PortNo) ->
{ok,Sock} = gen_tcp:connect("localhost", PortNo,
[]).
connect_clients(Number, Port) ->
spawn(ex, client, [Port]),
case Number of
0 -> ok;
_ -> connect_clients(Number-1, Port)
end.
In effetti, avevi ragione su questi due problemi. Ho risolto quelli. Ora quando chiamo connect_clients (1000, 9999) si connette circa 100 al secondo e va a 800; poi si ferma. Il server non si arresta in modo anomalo, quindi posso richiamarlo di nuovo, collegando un client o il numero desiderato. Ma non riesco a collegarmi più di circa 800 per chiamata. Vorrei poter chiamare connect_clients (1000000, 9999), ma poi la mia VM si blocca. qualche idea? Grazie per quello che mi hai già aiutato. –
Inoltre, ricorda, puoi avere diversi processi acceptor che chiamano 'gen_tcp: accept/1' sullo stesso socket di ascolto per una migliore velocità effettiva al momento dell'accettazione. –
@ ŞtefanStan difficile dire quali nuovi problemi stai colpendo. Sei in esecuzione con 'sasl' abilitato? Potresti avviarlo per assicurarti di non avere problemi che potrebbero passare inosservati. Sei sicuro che il tuo sistema operativo sia impostato correttamente per consentire il numero di connessioni necessarie? Cosa indica 'ulimit -n' nella shell? Inoltre, quale versione di Erlang/OTP stai usando? –