From: satoshi k. <ki...@ge...> - 2009-08-17 02:31:14
|
At Mon, 17 Aug 2009 09:46:54 +0900, Ngoc Dao wrote: > > [1 <multipart/alternative (7bit)>] > [1.1 <text/plain; UTF-8 (7bit)>] > > [1.2 <text/html; UTF-8 (quoted-printable)>] > How about listen_backlog (http://yaws.hyber.org/yman.yaws?page=yaws.conf)? > > Ngoc > > On Sun, Aug 16, 2009 at 6:34 PM, Jan Jacobs <hp...@mw...> wrote: > > Hi, > > Is it possible to limit the number of connections that YAWs will handle? Hi, Attached below is a patch to add a feature to limit the number of simultanious connections to accept. It's adding one new proprerty to gconf to specifiy the max number and a new status value to remember the number of connetions currently opened. yaws_server compares those two values and decide to or not to accept more connections. More precisely, it accepts TCP connections any way and will close it if it's more than the max. We're going to use this feature for our products and hope we can share this with people who are intertested. Thanks, Kinoshita / Gemini Mobile Technologies --- yaws-1.84/include/yaws.hrl.orig 2009-05-29 06:05:44.000000000 +0900 +++ yaws-1.84/include/yaws.hrl 2009-07-13 16:32:31.000000000 +0900 @@ -82,6 +82,7 @@ max_num_cached_files = 400, max_num_cached_bytes = 1000000, %% 1 MEG max_size_cached_file = 8000, + max_connections = nolimit, %% max number of TCP connections to accept large_file_chunk_size = 10240, mnesia_dir = [], log_wrap_size = 10000000, % wrap logs after 10M --- ./yaws-1.84/src/yaws_server.erl.orig 2009-07-06 03:20:13.000000000 +0900 +++ ./yaws-1.84/src/yaws_server.erl 2009-08-03 12:38:14.000000000 +0900 @@ -56,6 +56,7 @@ certinfo, %% undefined | #certinfo{} l, %% listen socket mnum = 0, + connections = 0, %% number of TCP connections opened now sessions = 0, %% number of active HTTP sessions reqs = 0}). %% total number of processed HTTP requests @@ -577,18 +578,25 @@ {From , status} -> From ! {self(), GS}, gserv_loop(GS, Ready, Rnum, Last); - {_From, next} when Ready == [] -> - New = acceptor(GS), - gserv_loop(GS#gs{sessions = GS#gs.sessions + 1}, Ready, Rnum, New); - {_From, next} -> + {_From, next, Accepted} when Ready == [] -> + close_accepted_if_max(GS,Accepted), + New = acceptor(GS), + GS2 = inc_con(GS), + gserv_loop(GS2#gs{sessions = GS2#gs.sessions + 1}, Ready, Rnum, New); + {_From, next, Accepted} -> + close_accepted_if_max(GS,Accepted), [{_Then, R}|RS] = Ready, R ! {self(), accept}, - gserv_loop(GS, RS, Rnum-1, R); + GS2 = inc_con(GS), + gserv_loop(GS2, RS, Rnum-1, R); + {_From, decrement} -> + GS2 = dec_con(GS), + gserv_loop(GS2, Ready, Rnum, Last); {From, done_client, Int} -> GS2 = if - Int == 0 -> GS#gs{sessions = GS#gs.sessions - 1}; - Int > 0 -> GS#gs{sessions = GS#gs.sessions - 1, - reqs = GS#gs.reqs + Int} + Int == 0 -> dec_con(GS#gs{sessions = GS#gs.sessions - 1}); + Int > 0 -> dec_con(GS#gs{sessions = GS#gs.sessions - 1, + reqs = GS#gs.reqs + Int}) end, if Rnum == 8 -> @@ -877,7 +885,7 @@ ?TC([{record, GS, gs}]), put(gc, GS#gs.gconf), X = do_accept(GS), - Top ! {self(), next}, + Top ! {self(), next, X}, case X of {ok, Client} -> if @@ -888,6 +896,7 @@ {error, Reason} -> error_logger:format("SSL accept failed: ~p~n", [Reason]), + Top ! {self(), decrement}, exit(normal) end; true -> @@ -918,20 +927,26 @@ {ok, Int} when is_integer(Int) -> Top ! {self(), done_client, Int}; {'EXIT', normal} -> + Top ! {self(), decrement}, exit(normal); {'EXIT', shutdown} -> exit(shutdown); {'EXIT', {error, einval}} -> %% Typically clients that close their end of the socket %% don't log. Happens all the time. + Top ! {self(), decrement}, exit(normal); {'EXIT', {{error, einval}, _}} -> + Top ! {self(), decrement}, exit(normal); {'EXIT', {error, closed}} -> + Top ! {self(), decrement}, exit(normal); {'EXIT', {{error, closed}, _}} -> + Top ! {self(), decrement}, exit(normal); {'EXIT', {{error, econnreset},_}} -> + Top ! {self(), decrement}, exit(normal); {'EXIT', Reason2} -> error_logger:error_msg("Yaws process died: ~p~n", @@ -964,6 +979,7 @@ end; {error, closed} -> %% This is what happens when we call yaws --stop + Top ! {self(), decrement}, exit(normal); ERR -> %% When we fail to accept, the correct thing to do @@ -4282,3 +4298,19 @@ %% specified in conf file for the 'vdir' directive. Result. +close_accepted_if_max(GS,{ok, Socket}) -> + MaxCon = (GS#gs.gconf)#gconf.max_connections, + NumCon = GS#gs.connections, + if MaxCon == nolimit orelse NumCon < MaxCon -> + ok; + true -> + gen_tcp:close(Socket) + end; +close_accepted_if_max(_,_) -> + ok. + +inc_con(GS) -> + GS#gs{connections=GS#gs.connections + 1}. + +dec_con(GS) -> + GS#gs{connections=GS#gs.connections - 1}. |