Erlang simultaneously connects 1M clients

I have a problem: I want to create an Erlang server that can support a 1M open tcp connection 1M. I configured my OS (Oracle Linux 7) to raise file descriptors. On the server, I am doing gen_tcp: listen

// point_1
Socket = gen_tcp: accept
spawn (handle (Socket)) // another thread
back to point_1

If I connect in series, this is not a problem, after 100 seconds I connected 100K clients; but I had no complaints for more.

If I want to connect them using conncurent , only about 80 connections are made, for example, out of 100.

This is how I run everything:

erlc *.erl erl +Q 134217727 +P 1000000 -env ERL_MAX_PORTS 40960000 -env ERTS_MAX_PORTS 40960000 

// start one server that will listen on port 9999

 ex:start(1, 9999) 

// 100 clients try to connect to port 9999

 ex:connect_clients(100, 9999) 

Let me show you the code:

 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. 
+7
erlang sockets connect gen-tcp
source share
1 answer

I see at least two questions here:

  • You need to raise your auditory diary; by default it is 5. You can raise it by setting {backlog, N} in your listening options, for example, {backlog, 1024} .

  • The server/2 function is erroneous because it accepts the connection and then starts a new process to start loop/1 , but does not make this new process control the process for the received socket. The loop/1 function tries to set the {active,once} mode to the socket, trying to receive incoming messages, but since it does not work in the control process, it will not work. (You should check the return value of inet_setopts/2 by specifying ok = inet:setopts(S,[{active,once}]), instead.)

Instead of spawning a loop, you should instead create a new acceptor, for example:

 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,server,[LS,Nr+1]), loop(S); Other -> io:format("accept returned ~w - goodbye!~n",[Other]), ok end. 

With this approach, the process receiving the socket starts loop/1 , and therefore there is no need to change the socket management process.

+8
source share

All Articles