diff options
Diffstat (limited to 'code/spyglass/docs/lookout.html')
| -rw-r--r-- | code/spyglass/docs/lookout.html | 325 |
1 files changed, 325 insertions, 0 deletions
diff --git a/code/spyglass/docs/lookout.html b/code/spyglass/docs/lookout.html new file mode 100644 index 0000000..a017f33 --- /dev/null +++ b/code/spyglass/docs/lookout.html @@ -0,0 +1,325 @@ +<!DOCTYPE html> + +<html> +<head> + <title>lookout.rb</title> + <meta http-equiv="content-type" content="text/html; charset=UTF-8"> + <meta name="viewport" content="width=device-width, target-densitydpi=160dpi, initial-scale=1.0; maximum-scale=1.0; user-scalable=0;"> + <link rel="stylesheet" media="all" href="docco.css" /> +</head> +<body> + <div id="container"> + <div id="background"></div> + + <ul id="jump_to"> + <li> + <a class="large" href="javascript:void(0);">Jump To …</a> + <a class="small" href="javascript:void(0);">+</a> + <div id="jump_wrapper"> + <div id="jump_page"> + + + <a class="source" href="configurator.html"> + configurator.rb + </a> + + + <a class="source" href="logging.html"> + logging.rb + </a> + + + <a class="source" href="lookout.html"> + lookout.rb + </a> + + + <a class="source" href="master.html"> + master.rb + </a> + + + <a class="source" href="server.html"> + server.rb + </a> + + + <a class="source" href="worker.html"> + worker.rb + </a> + + </div> + </li> + </ul> + + <ul class="sections"> + + <li id="title"> + <div class="annotation"> + <h1>lookout.rb</h1> + </div> + </li> + + + + <li id="section-1"> + <div class="annotation"> + + <div class="pilwrap "> + <a class="pilcrow" href="#section-1">¶</a> + </div> + + </div> + + <div class="content"><div class='highlight'><pre><span class="class"><span class="keyword">module</span> <span class="title">Spyglass</span></span> + <span class="class"><span class="keyword">class</span> <span class="title">Lookout</span></span> + <span class="keyword">include</span> <span class="constant">Singleton</span>, <span class="constant">Logging</span></pre></div></div> + + </li> + + + <li id="section-2"> + <div class="annotation"> + + <div class="pilwrap "> + <a class="pilcrow" href="#section-2">¶</a> + </div> + <p>This method is the main entry point for the Lookout class. It takes +a socket object.</p> + + </div> + + <div class="content"><div class='highlight'><pre> <span class="function"><span class="keyword">def</span> <span class="title">start</span><span class="params">(socket)</span></span> + trap_signals</pre></div></div> + + </li> + + + <li id="section-3"> + <div class="annotation"> + + <div class="pilwrap "> + <a class="pilcrow" href="#section-3">¶</a> + </div> + <p>The Lookout doesn't know anything about the app itself, so there's +no app related setup to do here.</p> + + </div> + + <div class="content"><div class='highlight'><pre> loop <span class="keyword">do</span></pre></div></div> + + </li> + + + <li id="section-4"> + <div class="annotation"> + + <div class="pilwrap "> + <a class="pilcrow" href="#section-4">¶</a> + </div> + <p>Accepts a new connection on our socket. This class won't actually +do anything interesting with this connection, it will pass it down +to the <code>Master</code> class created below to do the actual request handling.</p> + + </div> + + <div class="content"><div class='highlight'><pre> conn = socket.accept + out <span class="string">"Received incoming connection"</span></pre></div></div> + + </li> + + + <li id="section-5"> + <div class="annotation"> + + <div class="pilwrap "> + <a class="pilcrow" href="#section-5">¶</a> + </div> + <p>In this block the Lookout forks a new process and invokes a Master, +passing along the socket it received and the connection it accepted +above.</p> + + </div> + + <div class="content"><div class='highlight'><pre> <span class="variable">@master_pid</span> = fork <span class="keyword">do</span> + master = <span class="constant">Master</span>.new(conn, socket) + master.start + <span class="keyword">end</span></pre></div></div> + + </li> + + + <li id="section-6"> + <div class="annotation"> + + <div class="pilwrap "> + <a class="pilcrow" href="#section-6">¶</a> + </div> + <p>The Lookout can now close its handle on the client socket. This doesn't +translate to the socket being closed on the clients end because the +forked Master process also has a handle on the same socket. Since this +handle is now cleaned up it's up to the Master process to ensure that +its handle gets cleaned up.</p> + + </div> + + <div class="content"><div class='highlight'><pre> conn.close</pre></div></div> + + </li> + + + <li id="section-7"> + <div class="annotation"> + + <div class="pilwrap "> + <a class="pilcrow" href="#section-7">¶</a> + </div> + <p>Now this process blocks until the Master process exits. The Master process +will only exit once traffic is slow enough that it has reached its timeout +without receiving any new connections.</p> + + </div> + + <div class="content"><div class='highlight'><pre> <span class="constant">Process</span>.waitpid(<span class="variable">@master_pid</span>)</pre></div></div> + + </li> + + + <li id="section-8"> + <div class="annotation"> + + <div class="pilwrap "> + <a class="pilcrow" href="#section-8">¶</a> + </div> + <p>The interaction of fork(2)/waitpid(2) above deserve some explanation.</p> + + </div> + + </li> + + + <li id="section-9"> + <div class="annotation"> + + <div class="pilwrap for-h3"> + <a class="pilcrow" href="#section-9">¶</a> + </div> + <h3>Why fork(2)? Why not just spin up the Master?</h3> +<p>The whole point of the Lookout process is to be very lean. The only resource +that it initializes is the listening socket for the server. It doesn't load +any of your application into memory, so its resource footprint is very small.</p> + + </div> + + </li> + + + <li id="section-10"> + <div class="annotation"> + + <div class="pilwrap "> + <a class="pilcrow" href="#section-10">¶</a> + </div> + <p>The reason that it does a fork(2) before invoking the Master is because once +the Master times out we want the Lookout process to remain lean when accepting +the next connection. </p> + + </div> + + </li> + + + <li id="section-11"> + <div class="annotation"> + + <div class="pilwrap "> + <a class="pilcrow" href="#section-11">¶</a> + </div> + <p>If it were to load the application code without forking +then there would be no (simple) way for it to later unload the application code.</p> + + </div> + + </li> + + + <li id="section-12"> + <div class="annotation"> + + <div class="pilwrap "> + <a class="pilcrow" href="#section-12">¶</a> + </div> + <p>By doing a fork(2), then waiting for the Master process to exit, that guarantees +that all resources (notably memory usage) that were in use by the Master process +will be reclaimed by the kernel. </p> + + </div> + + </li> + + + <li id="section-13"> + <div class="annotation"> + + <div class="pilwrap for-h3"> + <a class="pilcrow" href="#section-13">¶</a> + </div> + <h3>Who knows what your app will demand!</h3> +<p>While handling requests your app may require lots of memory. Containing this in a +child process, and exiting that process, is the easiest way to ensure that memory +bloat isn't shared with our simple parent process.</p> + + </div> + + </li> + + + <li id="section-14"> + <div class="annotation"> + + <div class="pilwrap "> + <a class="pilcrow" href="#section-14">¶</a> + </div> + <p>This allows our Lookout process will to go back around +the loop with nothing more than it started with, just a listening socket.</p> + + </div> + + </li> + + + <li id="section-15"> + <div class="annotation"> + + <div class="pilwrap "> + <a class="pilcrow" href="#section-15">¶</a> + </div> + <p>The fork(2)/waitpid(2) approach requires little code to implement, and pushes +responsibility down to the kernel to track resource usage and nicely clean up +the Master process when it's finished.</p> + + </div> + + <div class="content"><div class='highlight'><pre> <span class="keyword">end</span> + <span class="keyword">end</span> + + <span class="function"><span class="keyword">def</span> <span class="title">trap_signals</span></span> + [<span class="symbol">:INT</span>, <span class="symbol">:QUIT</span>].each <span class="keyword">do</span> |sig| + trap(sig) { + <span class="keyword">begin</span> + <span class="constant">Process</span>.kill(sig, <span class="variable">@master_pid</span>) <span class="keyword">if</span> <span class="variable">@master_pid</span> + <span class="keyword">rescue</span> <span class="constant">Errno::ESRCH</span> + <span class="keyword">end</span> + exit + } + <span class="keyword">end</span> + <span class="keyword">end</span> + <span class="keyword">end</span> +<span class="keyword">end</span></pre></div></div> + + </li> + + </ul> + </div> +</body> +</html> |
