File: request.html

package info (click to toggle)
libapache2-mod-rivet 3.2.2-1
  • links: PTS
  • area: main
  • in suites: bookworm
  • size: 6,296 kB
  • sloc: xml: 8,554; tcl: 7,568; ansic: 7,094; sh: 5,017; makefile: 195; sql: 91; lisp: 78
file content (191 lines) | stat: -rw-r--r-- 19,928 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Apache Child Processes Lifecycle and Request Processing</title><link rel="stylesheet" type="text/css" href="rivet.css"><meta name="generator" content="DocBook XSL Stylesheets Vsnapshot"><link rel="home" href="index.html" title="Apache Rivet 3.2"><link rel="up" href="index.html" title="Apache Rivet 3.2"><link rel="prev" href="processing.html" title="Apache Rivet HTTP Request Processing"><link rel="next" href="commands.html" title="Rivet Tcl Commands and Variables"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Apache Child Processes Lifecycle and Request Processing</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="processing.html"><img src="images/prev.png" alt="Prev"></a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="commands.html"><img src="images/next.png" alt="Next"></a></td></tr></table></div><div class="section"><div class="titlepage"><div><div><hr><h2 class="title" style="clear: both"><a name="request"></a>Apache Child Processes Lifecycle and Request Processing</h2></div></div></div><div class="simplesect"><div class="titlepage"><div><div><h3 class="title"><a name="idm639"></a>Apache Child Process Lifecycle</h3></div></div></div><p style="width:90%">
            Apache Rivet devolves to the <a class="ulink" href="" target="_top">Multi-Processing Module (MPM)</a>
            the task of managing the agents responding to network requests. 
            An MPM is responsible for creating such agents during the start-up, 
            and is in charge for terminating existing ones and recreating new 
            agents when the workload is requiring it. 
       </p><p style="width:90%">
            Apache Rivet 2.x supported only the
            <a class="ulink" href="https://httpd.apache.org/docs/2.4/mod/prefork.html" target="_top">prefork</a>
            MPM which creates child processes as independent agents responding to network requests. 
            Starting with 3.0 also the <a class="ulink" href="https://httpd.apache.org/docs/2.4/mod/worker.html" target="_top">worker</a> and
            <a class="ulink" href="https://httpd.apache.org/docs/2.4/mod/event.html" target="_top">event</a> MPM are supported. The worker MPM is
            an hybrid model where forked child processes in turn create threads as real
            network agents. Also Apache on Windows© is now supported and tested
            with the <a class="ulink" href="https://httpd.apache.org/docs/2.4/mod/mpm_winnt.html" target="_top">winnt</a> MPM, 
            where a single process creates and manages a large number of thread agents.
       </p><p style="width:90%">
	    		Configuration parameters about this critical point can be read in the
	    		<a class="ulink" href="https://httpd.apache.org/docs/2.4/misc/perf-tuning.html" target="_top">Apache
	    		documentation</a>. 
	    </p><p style="width:90%">
	    		There are 4 stages in the lifetime of an Apache webserver that are relevant
	    		to Rivet: 
	    </p><div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem"><h4><a name="idm653"></a>Server Initialization</h4><div style="margin-bottom:1.5ex ; padding .5ex">
               Apaches starts up as a single process. During this stage Apache performs 
               various preliminary tasks including reading and parsing the configuration. 
					After the configuration has been read Rivet sets up some internal resources
					and if a Tcl script is set as argument of a <span style="font-family:monospace"><span class="command"><strong>ServerInitScript</strong></span></span>
					directive the script is executed. 
					Variables, arrays or dictionaries created during 
					the execution of this script will be preserved and later replicated in the 
					child process intepreters if the prefork MPM is loaded (which restricts
					this feature to the Unix systems). 
					The prefork MPM creates new child processes with a fork() 
					system call, which involves only in memory copy of sections of a
					process address space. Tcl is careful about reproducing an environment
					across a fork call in order to have a functional interpreter.
				</div><div style="margin-bottom:1.5ex ; padding .5ex">
					Still, regardless the OS and loaded MPM <span style="font-family:monospace"><span class="command"><strong>ServerInitScript</strong></span></span>
		    		is a good place to do global initialization that doesn't involve
		    		creation of private data. Example of tasks that can be done
		    		in this context are IPC methods that must be initialized at this stage.
		    		With the prefork MPM also importing from namespaces and loading packages
		    		can be done here removing the burden from the child initialization stage. 	
	    		</div></li><li class="listitem"><h4><a name="idm659"></a>Child Process Initialization</h4><div style="margin-bottom:1.5ex ; padding .5ex">
					A child process calls the MPM bridge interface function to set up
					the Tcl run time environment,either creating multiple threads each running its
					Tcl interpreters or, in the case of the prefork MPM bridge, setting up
					the environment within a the child process itself as a single Tcl thread.
	    		</div><div style="margin-bottom:1.5ex ; padding .5ex">
               This is the stage where most likely you want to open I/O channels,
               database connections or any other resource that has to be private to an 
               interpreter and has to persist over a whole thread lifespan.
               When the option <span style="font-family:monospace"><span class="command"><strong>SeparateVirtualInterps</strong></span></span> is 
               turned off child processes will have a single interpreter regardless
		    		the number of virtual hosts configured. The
               <span style="font-family:monospace"><span class="command"><strong>GlobalInitScript</strong></span></span> is the configuration script 
               the child process will run once before getting ready to 
               serve requests
	    		</div><div style="margin-bottom:1.5ex ; padding .5ex">
	    			When <span style="font-family:monospace"><span class="command"><strong>SeparateVirtualInterps</strong></span></span> is turned on 
	    			each configured virtual host will have its own slave interpreter which
	    			can will run the <span style="font-family:monospace"><span class="command"><strong>ChildInitScript</strong></span></span> directive as
	    			initialization script. The	    			
	    			<span style="font-family:monospace"><span class="command"><strong>ChildInitScript</strong></span></span> has to be
	    			placed within a &lt;VirtualHost...&gt;...&lt;/VirtualHost ...&gt;
	    			stanza to associate a script to a specific virtual host initialization.
	    			This scenario of interpreter separation is extremely useful to
	    			prevent resource conflicts when different virtual hosts are 
	    			serving different web applications. 
	    		</div><div style="margin-bottom:1.5ex ; padding .5ex">
	    			<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><span style="font-family:monospace"><span class="command"><strong>GlobalInitScript</strong></span></span> has no effect to working interpreters
	    				when <span style="font-family:monospace"><span class="command"><strong>SeparateVirtualInterps</strong></span></span> is set.
	    			</td></tr></table></div>
	    			<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top">
	    				The lazy MPM bridge implements a model where
	    				every worker thread has exactly one interpreter and belongs to 
	    				a single virtual host, therefore <span style="font-family:monospace"><span class="command"><strong>SeparateVirtualInterps</strong></span></span>
	    				is ignored and you can't share the same interpreter among virtual host
	    			</td></tr></table></div>
	    		</div></li><li class="listitem"><h4><a name="idm675"></a>Request Processing and Content Generation</h4><div style="margin-bottom:1.5ex ; padding .5ex">
			    		<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top">
			    			This section explain the default request handling procedure which
			    			was written to let Rivet 3.0 work as a drop in replacement 
			    			of any 2.x module. For a in-depth understanding of
			    			the new request processing mechanics please read the
			    			<a class="link" href="processing.html" title="Apache Rivet HTTP Request Processing">request processing</a> section of the manual
			    		</td></tr></table></div>
			   </div><div style="margin-bottom:1.5ex ; padding .5ex">
                 After a child has been initialized it's ready to serve requests. 
                 A child process' lifetime is almost entirely spent in this phase, waiting
                 for connections and responding to requests. At every request the URL 
                 goes through filter processing and, in case, rewritten
                 (mod_rewrite, Alias directives, etc). 
                 Parameter values encoded in the request are made available to the 
                 environment and finally the script encoded in the URL is run. 
                 The developer can tell Rivet if optionally the execution has to
                 be  preceded by a <span style="font-family:monospace"><span class="command"><strong>BeforeScript</strong></span></span> and followed by an
                 <span style="font-family:monospace"><span class="command"><strong>AfterScript</strong></span></span>. The real script mod_rivet will
                 execute is the result of the concatenation of the 
                 <span style="font-family:monospace"><span class="command"><strong>BeforeScript</strong></span></span>,
                 the script encoded in the URL and the <span style="font-family:monospace"><span class="command"><strong>AfterScript</strong></span></span>.
                 Thus the whole ensemble of code that makes up a web application might
                 be running within the same "before" and "after" scripts to which 
                 the programmer can devolve tasks common to every 
                 page of an application.
            </div></li><li class="listitem"><h4><a name="idm685"></a>Child Process Exit</h4><div style="margin-bottom:1.5ex ; padding .5ex">
                 If no error condition forces the child process to a premature exit, his
                 life is determined by the Apache configuration parameters. To reduce
                 the effects of memory leaks in buggy applications the Apache webserver 
                 forces a child process to exit after a
                 certain number of requests served. A child process gets replaced 
                 with a brand new one if the workload of webserver requires so. 
                 Before the process quits an exit handler can be run
                 to do some housekeeping, just in case something the could have been 
                 left behind has to be cleaned up. Like the initialization scripts
                 <span style="font-family:monospace"><span class="command"><strong>ChildExitScript</strong></span></span> too is a "one shot" script.
             </div><div style="margin-bottom:1.5ex ; padding .5ex">
                 The Tcl <span style="font-family:monospace"><span class="command"><strong>exit</strong></span></span> command forces an interpreter to
                 quit, thus removing the ability of the process embedding it 
                 to run more Tcl scripts. The child process then is forced
                 to exit and be replaced by a new one when the workload demands it.
                 This operation implies the <span style="font-family:monospace"><span class="command"><strong>ChildExitScript</strong></span></span> be
                 run before the interpreter is actually deleted.
             </div></li></ol></div></div><div class="simplesect"><div class="titlepage"><div><div><h3 class="title"><a name="idm691"></a>Apache Rivet Error and Exception Scripts Directives</h3></div></div></div><p style="width:90%">
         Rivet is highly configurable and each of the webserver lifecycle stages 
         can be exploited to control a web application. 
         Not only the orderly sequence of stages
         in a child lifecycle can be controlled with Tcl scripts, but also
         Tcl error or abnormal conditions taking place during
         the execution can be caught and handled with specific scripts.
       </p><p style="width:90%">
	    	Tcl errors (conditions generated when a command exits with code TCL_ERROR) 
	    	usually result in the printing of a backtrace of the code fragment
	    	relevant to the error.
	    	Rivet can set up scripts to trap these errors and run instead
	    	an <span style="font-family:monospace"><span class="command"><strong>ErrorScript</strong></span></span> to handle it and conceal details
	    	that usually have no interest for the end user and it
	    	may show lines of code that ought to remain private. The ErrorScript
	    	handler might create a polite error page where things
	    	can be explained in human readable form, thus enabling the end user
	    	to provide meaningful feedback information. 
	    </p><p style="width:90%">
	    	In other cases an unmanageable conditions might take place in the data and
	    	this could demand an immediate interruption of the content generation. These abort 
	    	conditions can be fired by the <a class="xref" href="abort_page.html" title="abort_page">abort_page</a> command, which
	    	in turn fires the execution of an <span style="font-family:monospace"><span class="command"><strong>AbortScript</strong></span></span> to handle
	    	the abnormal condition. Starting with Rivet 2.1.0 <a class="xref" href="abort_page.html" title="abort_page">abort_page</a>
	    	accepts a free form parameter that can be retrieved later with the command 
	    	<a class="xref" href="abort_code.html" title="abort_code">abort_code</a>
	    </p></div><div class="simplesect"><div class="titlepage"><div><div><h3 class="title"><a name="idm701"></a>Tcl Namespaces in Rivet and the <span style="font-family:monospace"><span class="command"><strong>::request</strong></span></span> Namespace</h3></div></div></div><p style="width:90%">
    		</p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top">
    			This section explain the default request handling procedure which
    			was written to let Rivet 3.0 work as a drop in replacement 
    			of any 2.x module. For a in-depth understanding of
    			the new request processing mechanics please read the
    			<a class="link" href="processing.html" title="Apache Rivet HTTP Request Processing">request processing</a> section of the manual
    		</td></tr></table></div><p style="width:90%">
	   </p><p style="width:90%">
			With the sole exception of .rvt templates, mod_rivet runs pure Tcl scripts 
			at the global namespace. That means that every variable or procedure 
			created in Tcl scripts resides by default in the 
			"::" namespace (just like in traditional Tcl scripting) and they
			are persistent across different requests until explicitly unset or
			until the interpreter is deleted.
			You can create your own application namespaces to store data but
			it is important to remember that subsequent requests will in general be served 
			by different child processes. Your application can rely on the fact that 
			certain application data will be in the interpreter, but you shouldn't 
			assume the state of a transaction spanning several pages 
			can be stored in this way and be safely kept available to a 
			specific client. Sessions exist for this purpose and Rivet ships its own 
			session package with support for most of popular DBMS. Nonetheless 
			storing data in the global namespace can be useful, even though scoping 
			data in a namespace is recommended. I/O channels and
			database connections are examples of information usually specific 
			to a process for which you don't want to pay the overhead of creating them
			at every request, probably causing a dramatic loss in the application
			performance.
		</p><p style="width:90%">
			A special role in the interpreter is played by the <span style="font-family:monospace"><span class="command"><strong>::request</strong></span></span> 
			namespace.	The <span style="font-family:monospace"><span class="command"><strong>::request</strong></span></span> namespace is deleted and recreated
			at every request and Rivet templates (.rvt files) are executed within it.
		</p><p style="width:90%"> 
			Unless you're fully qualifying variable names outside the <span style="font-family:monospace"><span class="command"><strong>::request</strong></span></span> 
			namespace, every variable and procedure created in .rvt files is by default placed in
			it and deleted before any other requests gets processed. It is therefore safe to
			create variables or object instances in template files and foresake about them: Rivet
			will take care of cleaning the namespace up and everything created inside the namespace
			will be destroyed.
		</p><div class="table"><table align="center" title="Apache Rivet Scripts" class="namespaces"><thead><td>Stage</td><td>Script</td><td>Namespace</td></thead><tbody><tr class="init"><td>Apache Initialization</td><td>ServerInitScript</td><td>::</td></tr><tr class="childinit"><td rowspan="2">Child Initialization</td><td>GlobalInitScript</td><td>::</td></tr><tr class="childinit"><td>ChildInitScript</td><td>::</td></tr><tr class="processing"><td rowspan="6">Request Processing</td><td>BeforeScript</td><td>::</td></tr><tr class="processing"><td>.rvt</td><td>::request</td></tr><tr class="processing"><td>.tcl</td><td>::</td></tr><tr class="processing"><td>AfterScript</td><td>::</td></tr><tr class="processing"><td>AbortScript</td><td>::</td></tr><tr class="processing"><td>AfterEveryScript</td><td>::</td></tr><tr class="childexit"><td>Child Termination</td><td>ChildExitScript</td><td>::</td></tr><tr class="processing"><td>Error Handling</td><td>ErrorScript</td><td>::</td></tr></tbody></table></div></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="processing.html"><img src="images/prev.png" alt="Prev"></a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="commands.html"><img src="images/next.png" alt="Next"></a></td></tr><tr><td width="40%" align="left" valign="top">Apache Rivet HTTP Request Processing </td><td width="20%" align="center"><a accesskey="h" href="index.html"><img src="images/home.png" alt="Home"></a></td><td width="40%" align="right" valign="top"> Rivet Tcl Commands and Variables</td></tr></table></div></body></html>