aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLoïc Hoguin <[email protected]>2011-05-09 22:01:31 +0200
committerLoïc Hoguin <[email protected]>2011-05-09 22:01:31 +0200
commit5d698250b228229001ca9966a390bf1545fcd0b0 (patch)
tree9491764e4c0310f4c0d16cb120b6d64edae9c868 /src
parentb3d3045cae8d90257851e87e0073c227656d3ad0 (diff)
downloadcowboy-5d698250b228229001ca9966a390bf1545fcd0b0.tar.gz
cowboy-5d698250b228229001ca9966a390bf1545fcd0b0.tar.bz2
cowboy-5d698250b228229001ca9966a390bf1545fcd0b0.zip
Add a max_connections transport option.
Limits the number of parallel requests processed at once. Waiting requests are kept in the accept queue. The limit is not explicitly observed, but it should be around the given value at any time. Defaults to 1024. Thanks to ostinelli's benchmark to point out the issue hopefully solved by this and the previous commit.
Diffstat (limited to 'src')
-rw-r--r--src/cowboy_acceptor.erl30
-rw-r--r--src/cowboy_acceptors_sup.erl3
2 files changed, 23 insertions, 10 deletions
diff --git a/src/cowboy_acceptor.erl b/src/cowboy_acceptor.erl
index f27f446..9bcc733 100644
--- a/src/cowboy_acceptor.erl
+++ b/src/cowboy_acceptor.erl
@@ -13,28 +13,31 @@
%% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-module(cowboy_acceptor).
--export([start_link/5]). %% API.
--export([acceptor/5]). %% Internal.
+-export([start_link/6]). %% API.
+-export([acceptor/6]). %% Internal.
%% API.
-spec start_link(LSocket::inet:socket(), Transport::module(),
- Protocol::module(), Opts::term(), ReqsSup::pid()) -> {ok, Pid::pid()}.
-start_link(LSocket, Transport, Protocol, Opts, ReqsSup) ->
+ Protocol::module(), Opts::term(),
+ MaxConns::non_neg_integer(), ReqsSup::pid()) -> {ok, Pid::pid()}.
+start_link(LSocket, Transport, Protocol, Opts, MaxConns, ReqsSup) ->
Pid = spawn_link(?MODULE, acceptor,
- [LSocket, Transport, Protocol, Opts, ReqsSup]),
+ [LSocket, Transport, Protocol, Opts, MaxConns, ReqsSup]),
{ok, Pid}.
%% Internal.
-spec acceptor(LSocket::inet:socket(), Transport::module(),
- Protocol::module(), Opts::term(), ReqsSup::pid()) -> no_return().
-acceptor(LSocket, Transport, Protocol, Opts, ReqsSup) ->
+ Protocol::module(), Opts::term(),
+ MaxConns::non_neg_integer(), ReqsSup::pid()) -> no_return().
+acceptor(LSocket, Transport, Protocol, Opts, MaxConns, ReqsSup) ->
case Transport:accept(LSocket, 2000) of
{ok, CSocket} ->
{ok, Pid} = supervisor:start_child(ReqsSup,
[CSocket, Transport, Protocol, Opts]),
- Transport:controlling_process(CSocket, Pid);
+ Transport:controlling_process(CSocket, Pid),
+ limit_reqs(MaxConns, ReqsSup);
{error, timeout} ->
ignore;
{error, _Reason} ->
@@ -42,4 +45,13 @@ acceptor(LSocket, Transport, Protocol, Opts, ReqsSup) ->
%% we may want to try and listen again on the port?
ignore
end,
- ?MODULE:acceptor(LSocket, Transport, Protocol, Opts, ReqsSup).
+ ?MODULE:acceptor(LSocket, Transport, Protocol, Opts, MaxConns, ReqsSup).
+
+-spec limit_reqs(MaxConns::non_neg_integer(), ReqsSup::pid()) -> ok.
+limit_reqs(MaxConns, ReqsSup) ->
+ Counts = supervisor:count_children(ReqsSup),
+ Active = lists:keyfind(active, 1, Counts),
+ case Active < MaxConns of
+ true -> ok;
+ false -> timer:sleep(1)
+ end.
diff --git a/src/cowboy_acceptors_sup.erl b/src/cowboy_acceptors_sup.erl
index 3fbffb1..f5b2de3 100644
--- a/src/cowboy_acceptors_sup.erl
+++ b/src/cowboy_acceptors_sup.erl
@@ -32,8 +32,9 @@ start_link(NbAcceptors, Transport, TransOpts, Protocol, ProtoOpts, ReqsPid) ->
-spec init(list(term())) -> term(). %% @todo These specs should be improved.
init([NbAcceptors, Transport, TransOpts, Protocol, ProtoOpts, ReqsPid]) ->
{ok, LSocket} = Transport:listen(TransOpts),
+ MaxConns = proplists:get_value(max_connections, TransOpts, 1024),
Procs = [{{acceptor, self(), N}, {cowboy_acceptor, start_link, [
- LSocket, Transport, Protocol, ProtoOpts, ReqsPid
+ LSocket, Transport, Protocol, ProtoOpts, MaxConns, ReqsPid
]}, permanent, brutal_kill, worker, dynamic}
|| N <- lists:seq(1, NbAcceptors)],
{ok, {{one_for_one, 10, 10}, Procs}}.