Dear Graham & al.,
Congratulations for your software and documentation. I have however some
difficulties as outlined in the subject caption.
I'm building a case study for an application on an intranet within a
company where the users would interact with their browser communicating
with the Apache2/mod_wsgi server (daemon mode + multi-threads).
However I'm afraid I'm misunderstanding some important underlying concepts
of the architecture. Please allow me to give an example and to give you my
thoughts - which could go wrong somewhere.
*Part 1:*
I wrote a simple HTML page with a one field input form.
In my `environment` dictionary, I have, among other key/value pairs, the
following:
REQUEST_METHOD: POST
REQUEST_URI: /core/my-wsgi-app
mod_wsgi.callable_object: application
The first two values come obviously from my html <form
action="core/my-wsgi-app" method="post">...</form>, and the third value is
the default value in the configuration directive (WSGICallableObject
application).
In my my-wsgi-app script, I have of course:
def application (environment, start_response):
[my code here]
return [response_body]
So all is fine and works well but there is something I don't get (I mean I
haven't fully assimilated), certainly in a multi-users, multi-threads, ...
environment. The main question is about the WSGICallableObject.
The documentation
(https://code.google.com/p/modwsgi/wiki/ConfigurationDirectives#WSGICallableObject)
says "*The WSGICallableObject directive can be used to override the name of
the Python callable object in the script file which is used as the entry
point into the WSGI application.*" [underlining is mine]. For me the WSGI
application is the whole application: when finished the target application
I'm case studying could serve one hundred users, delivering thousands of
pages built dynamically over hundreds of SQL tables, ... Am I right in
thinking than one entry point would be fit for such purpose. The size of
the application is such that I already opted for a daemon configuration
with multi-threads (I do not wish to have users waiting in a single queue
because one of them is building a page that takes seconds to assemble).
Having one single callable object seems to give me these only 4 options:
1) Have only one single REQUEST_URI, say /core/my-wsgi-app, where only one
callable object (function, class, ...) is used under the one and same name
(application). In such case that callable object is the one and only full
single entry point to the overall application (thousands of pages built
dynamically) and I must care for checking, authorisation, parsing,
dispatching, ... and finally assembling the response and returning it. I'm
wondering if this single script/callable-object could become a bottleneck.
It is the concern I've just expressed. Of course, Python can handle
hundreds of function calls and instance calls. This option makes me doubt I
fully understand the mechanism. I call this option N to 1.
2) Have various REQUEST_URI (even one per page if need be) and in each
called script, there would be one callable object with the same name
("application" as defined in the WSGICallableObject directive). In that
case, I could create a callable instance of a base class but that instance
should bear the application name and use the two positional arguments
passed by mod_wsgi. This option, if used exclusively, seems to me like a
normal "CGI static serving", i.e. one request activates one script (the
whole logic and dynamism is in the script). This point too makes me doubt I
understand the real nature of WSGI. I call this option N to N.
3) One could combine option 1 and 2 to create more dynamism without risking
the potential (?) bottleneck of option 1 when used alone. I call this
option N to M (<<N)
4) There seems to be a possibility to define the WSGICallableObject per
directory. My understanding is that the REQUEST_URI belonging to a
directory (and its sub-directories) would use that callable object name.
This means for instance that any URI of the form /core/section-1/abc would
have a callable object Application_1, while any URI under
/core/section-N/... would have a callable object Application_N. I haven't
tried this directive yet so I may misunderstand its role.
This is my overall understanding but I'm afraid I'm missing something
fundamental [please note that I'm not an English speaker and I might have
missed subtleties in the documentation which is quite dense]. I tried to
picture this in a diagram but I'm not sure I got it right:
M (html requests) -> 1 (http server) -> N x P (mod_wsgi daemons x threads)
-> X? (Python instance(s) / one per daemon ? I don't know) -> M (calls to
one object in one URI or to many objects - named the same - in many URI ? )
and back to the user via the same route.
I assume that one user html request generates ultimately one call to a
callable object (give or take) : that's why I use M in toth cases. Is this
assumption correct ? My dilemma is that I can't understand the spread of
the load between the 2 extremes: one URI containing the `application`
callable object (that is eventually called hundreds of times per second) or
many hundreds URI each containing a callable object named `application`
that all get called much less frequently.
*Part 2:*
As a consequence of this hazy understanding of mine, I wonder why can't the
name of the callable object be chosen on demand ?
If I refer to PEP3333 (http://legacy.python.org/dev/peps/pep-3333/) I
understand that:
"
*A server or gateway must invoke the application object using positional
(not keyword) arguments. (E.g. by calling result = application(environ,
start_response)*"
So my guess is that, still referring to the example at the top, one thread
in mod_wsgi loads (I wouldn't call this an import) the /core/my-wsgi-app
script and calls application(environment, start_response) that has been
defined in it. Is this the correct mechanism ?
Could we imagine that mod_wsgi would sometime call my_App (arg1, arg2),
some other time call your_App (req, resp) or call Small_app (in, out) where
my_App, your_App, Small_app would be defined because mod_wsgi would be able
to set dynamically the WSGICallableObject . Imagine that in the
WSGIImportScript script file, we would have:
def my_App (param1, param2):
[code here]
return [my_Response]
def your_App (param1, param2):
[code here]
return [your_Response]
def Small_app (param1, param2):
[code here]
return [Small_response]
all the functions would be ready to be called.
I suppose that in any case we are limited:
A) by the HTTP protocol (URI given via the action attribute, the POST,
GET, OPTIONS, ... from the method attribute and the key/value pairs from
the various input fields); and
B) by directives we could give to configure mod_wsgi. I guess it is not
the role neither the intend to build some "user logic" within mod_wsgi.
*Conclusions:*
1) Am I correct in my understanding of mod_wsgi as expressed here above
(Part 1) ? Beware that I could be out of my depth, i.e. talking about
something I don't properly understand. In that case please correct me or
complement my view.
2) Do we need to dynamically choose the callable object name for the sake
of dynamism and multiplicity ?
-> If not, the current set-up is enough. In which case is the preceding
point ( 1) ) complete and correct ?
-> If yes, how to do it simply and elegantly ?
=> Idea 1: create an extra key/value pair (e.g.
wsgi_callable_object=my_application). It seems cumbersome to me.
=> Idea 2: if the URI were to have the form
/core/my-wsgi-app/_my_application then mod_wsgi could provide:
REQUEST_URI: /core/my-wsgi-app
mod_wsgi.callable_object: my_application
in the 'environment` dictionary because it would strip the
trailing part beginning with an underscore provided it is told to do so by
a directive;
otherwise it would behave as now and deliver:
REQUEST_URI: /core/my-wsgi-app/_my_application
mod_wsgi.callable_object: application
*Thanks:*
I do realize this is an unusual post (maybe it should find its way in the
group working on the documentation) but I would be very happy if some of
you could answer / feedback to me. In any case I do thank you all in
advance.
René
--
You received this message because you are subscribed to the Google Groups
"modwsgi" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/modwsgi.
For more options, visit https://groups.google.com/d/optout.