Mam problem: chcę utworzyć serwer Erlang, który może utrzymywać jednoczesne otwarte połączenie TCP 1M. Dostroiłem system operacyjny (Oracle Linux 7), aby podnieść deskryptory plików. Na serwerze zrobić gen_tcp: ListenErlang jednocześnie łączą klientów 1M
// point_1
Socket = gen_tcp: przyjąć
ikry (rękojeść (Socket)) // inny wątek
pleców do point_1
Jeśli łączę sekwencyjnie nie ma problemu, w 100 s łączyłem klientów 100K; ale nie miałem więcej cierpliwości.
Jeśli chcę połączyć te w sposób conncurent, tylko około 80 połączeń jest na przykład ze 100.
ten sposób uruchomić wszystko:
erlc *.erl
erl +Q 134217727 +P 1000000 -env ERL_MAX_PORTS 40960000 -env ERTS_MAX_PORTS 40960000
// uruchomić jeden serwer, który będzie nasłuchiwał na porcie 9999
ex:start(1, 9999)
// 100 klientów starają się łączyć na porcie 9999
ex:connect_clients(100, 9999)
Pozwól mi pokazać jakiś kod:
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.
Rzeczywiście, miałeś rację w tych dwóch sprawach. Naprawiłem te. Teraz, gdy wywołuję connect_clients (1000, 9999), łączy on około 100 na sekundę i przechodzi do 800; to się zatrzymuje. Serwer nie ulega awarii, więc mogę zadzwonić ponownie, łącząc jednego klienta lub numer, który chcę. Ale nie mogę połączyć więcej niż około 800 na połączenie. Chciałbym móc wywołać connect_clients (1000000, 9999), ale wtedy moja VM zawiesza się. jakieś pomysły? Dzięki za to, co mi pomogłeś. –
Pamiętaj też, że możesz mieć kilka procesów akceptujących wywoływanie 'gen_tcp: accept/1' na tym samym gnieździe nasłuchu, aby uzyskać lepszą przepustowość podczas akceptowania. –
@ ŞtefanStan ciężko powiedzieć, jakie nowe problemy napotykasz. Czy używasz opcji 'sasl'? Możesz go uruchomić, aby upewnić się, że nie trafisz na żadne problemy, które mogą pozostać niezauważone. Czy jesteś pewien, że twój system operacyjny jest odpowiednio skonfigurowany, aby umożliwić liczbę połączeń, których potrzebujesz? Co oznacza "ulimit -n" w twojej powłoce? Jakiej wersji Erlanga/OTP używasz? –