適応型webサーバ

レスポンスが遅いか、忙しいモジュールは、インスタンスが増えるかキャッシュされる。
アクセスのツリー単位でキャッシュする。
データは要らないけどFYI、というリクエストの拡張。
<追記:2008/6/27>
acceptする場合、リクエストだけを受け付けてmemcachedとかにpoolしておき、適宜取り出して応答する。
レスポンスはすげー遅いが、hashならば同じアクセスを一度にさばけるかも
以下超てきとうなcode

start_childpool(H|) -> spawn (fun() -> child() end).
start_childpppl(H|T) -> spawn (fun() -> child() end),
             start_childpool(T).

svr() ->
   receive
      {Request} -> if ( H = hit_hash(get_uri(Request))
                     append_request_to_hash(H, Request)
                  else
                     put_hash(Request,)
                  end,
                  svr().
   end

child()
   return_fetch_request

just compilable :-< code below.

 -module(requestquehttpd).
 -compile(export_all).

 -define(IDLEWAIT, 100).
 -define(NUMCHILDREN,10).

start_all() ->
    RequestPool= ets:new(requestpool, [set, public]),
    ContentsCache = ets:new(contentscache, [set, public]),
    start_responderpool(?NUMCHILDREN, RequestPool,ContentsCache),
    {ok, Listen} = gen_tcp:listen(8080, [binary, {packet,0},
					 {reuseaddr, true},
					 {active, true}]),
    accept_loop(Listen, RequestPool).

accept_loop(Listen, RequestPool) ->
    {ok, Socket} = gen_tcp:accept(Listen),
    spawn(fun() -> justsave_request(RequestPool, Socket, ) end),
    accept_loop(Listen, RequestPool).

justsave_request(RequestPool, Socket, T) ->
    receive
	{tcp, Socket, Bin} ->
	    justsave_request(RequestPool, Socket, T ++ Bin);
	{tcp_closed, Socket} ->
            ets:insert(RequestPool, {T, Socket})
    end.

start_responderpool (0, ReqCache, ContentsCache)  -> 
    spawn (fun() -> child(ReqCache, ContentsCache) end);
start_responderpool (N, ReqCache, ContentsCache)  -> 
    spawn (fun() -> child(ReqCache, ContentsCache) end),
    start_responderpool(N - 1, ReqCache, ContentsCache).

child(ReqCache, ContentsCache) -> 
    HIT = ets:lookup(ReqCache, ets:first(ReqCache)),
    case HIT of
     [{Request, Socket, }] -> 
	send_content(Socket, get_content(Request, ContentsCache)); 
     [{_Request, Socket, Content}] -> 
	send_content(Socket, Content);
     _ -> receive
          after ?IDLEWAIT ->
              do_nothing
          end,
          child(ReqCache, ContentsCache)
    end.

get_content(_stub_R, _stub_C) ->
   stub_code.


send_content(_stub_Socket, _stub_Data) ->
   stub_code. 

To make adabptable, I/F to

  • add/remove worker process
  • define variation (Template) of worker process (attach call-back function to each process)

For real use,

  • garbage (zombie connection) collection mechanism
  • timeout of cache

Anyway, it will be fun to testing.
</追記:2008/6/27>