summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcel Hellkamp <marc@gsites.de>2011-02-25 16:46:09 +0100
committerMarcel Hellkamp <marc@gsites.de>2011-02-25 16:46:09 +0100
commita5d636b5048753491f16e0bc92197dfe4926400a (patch)
tree4fda28cb133d0fa5a1d373e22af10df8dd52185c
parentb80f6d37114211723c020dbcc2eb722519d85685 (diff)
downloadbottle-a5d636b5048753491f16e0bc92197dfe4926400a.tar.gz
doc: Some details on app deployment.
-rwxr-xr-xapidoc/tutorial.rst139
1 files changed, 70 insertions, 69 deletions
diff --git a/apidoc/tutorial.rst b/apidoc/tutorial.rst
index 9df70bc..d6e5a75 100755
--- a/apidoc/tutorial.rst
+++ b/apidoc/tutorial.rst
@@ -632,41 +632,65 @@ finally clauses, etc., are not executed after a ``SIGTERM``.
Deployment
================================================================================
-Bottle uses the built-in ``wsgiref.SimpleServer`` by default. This non-threading
-HTTP server is perfectly fine for development and early production,
-but may become a performance bottleneck when server load increases.
+Bottle runs on the built-in `wsgiref WSGIServer <http://docs.python.org/library/wsgiref.html#module-wsgiref.simple_server>`_ by default. This non-threading HTTP server is perfectly fine for development and early production, but may become a performance bottleneck when server load increases.
There are three ways to eliminate this bottleneck:
-* Use a multi-threaded server adapter
-* Spread the load between multiple bottle instances
-* Do both
+* Use a multi-threaded or asynchronous HTTP server.
+* Spread the load between multiple bottle instances.
+* Do both.
Multi-Threaded Server
--------------------------------------------------------------------------------
-The easiest way to increase performance is to install a multi-threaded and
-WSGI-capable HTTP server like Paste_, flup_, cherrypy_
-or fapws3_ and use the corresponding bottle server-adapter.
-
-::
-
- from bottle import PasteServer, FlupServer, FapwsServer, CherryPyServer
- bottle.run(server=PasteServer) # Example
-
-If bottle is missing an adapter for your favorite server or you want to tweak
-the server settings, you may want to manually set up your HTTP server and use
-``bottle.default_app()`` to access your WSGI application.
-
-::
-
- def run_custom_paste_server(self, host, port):
- myapp = bottle.default_app()
- from paste import httpserver
- httpserver.serve(myapp, host=host, port=port)
-
+.. _flup: http://trac.saddi.com/flup
+.. _gae: http://code.google.com/appengine/docs/python/overview.html
+.. _wsgiref: http://docs.python.org/library/wsgiref.html
+.. _cherrypy: http://www.cherrypy.org/
+.. _paste: http://pythonpaste.org/
+.. _rocket: http://pypi.python.org/pypi/rocket
+.. _gunicorn: http://pypi.python.org/pypi/gunicorn
+.. _fapws3: http://www.fapws.org/
+.. _tornado: http://www.tornadoweb.org/
+.. _twisted: http://twistedmatrix.com/
+.. _diesel: http://dieselweb.org/
+.. _meinheld: http://pypi.python.org/pypi/meinheld
+.. _bjoern: http://pypi.python.org/pypi/bjoern
+
+The easiest way to increase performance is to install a multi-threaded or asynchronous WSGI server like paste_ or cherrypy_ and tell bottle to start it instead of the default single-threaded one::
+
+ bottle.run(server='paste') # Example
+
+Bottle ships with a lot of ready-to-use adapters for the most common WSGI servers and automates the setup process. Here is an incomplete list:
+
+======== ============ ======================================================
+Name Homepage Description
+======== ============ ======================================================
+cgi Run as CGI script
+flup flup_ Run as Fast CGI process
+gae gae_ Helper for Google App Engine deployments
+wsgiref wsgiref_ Single-threaded default server
+cherrypy cherrypy_ Multi-threaded and very stable
+paste paste_ Multi-threaded, stable, tried and tested
+rocket rocket_ Multi-threaded
+gunicorn gunicorn_ Pre-forked, partly written in C
+fapws3 fapws3_ Asynchronous, written in C
+tornado tornado_ Asynchronous, powers some parts of Facebook
+twisted twisted_ Asynchronous, well tested
+diesel diesel_ Asynchronous, based on greenlet
+meinheld meinheld_ Asynchronous, partly written in C
+bjoern bjoern_ Asynchronous, very fast and written in C
+auto Automatically selects an available server adapter
+======== ============ ======================================================
+
+The full list is available through :data:`server_names`.
+
+If there is no adapter for your favorite server or if you need more control over the server setup, you may want to start the server manually. Refer to the server documentation on how to mount WSGI applications. Here is an example for paste_::
+
+ from paste import httpserver
+ httpserver.serve(bottle.default_app(), host='0.0.0.0', port=80)
Multiple Server Processes
@@ -674,7 +698,7 @@ Multiple Server Processes
A single Python process can only utilise one CPU at a time, even if
there are more CPU cores available. The trick is to balance the load
-between multiple independent Python processes to utilise all of your
+between multiple independent Python processes to utilize all of your
CPU cores.
Instead of a single Bottle application server, you start one instance
@@ -685,42 +709,8 @@ a random Bottle processes, spreading the load between all available
back end server instances. This way you can use all of your CPU cores and
even spread out the load between different physical servers.
-But there are a few drawbacks:
-
-* You can't easily share data between multiple Python processes.
-* It takes a lot of memory to run several copies of Python and Bottle at the same time.
-
One of the fastest load balancers available is Pound_ but most common web servers have a proxy-module that can do the work just fine.
-I'll add examples for lighttpd_ and
-Apache_ web servers soon.
-
-Using WSGI and Middleware
---------------------------------------------------------------------------------
-
-A call to `bottle.default_app()` returns your WSGI application. After applying as many WSGI middleware modules as you like, you can tell
-`bottle.run()` to use your wrapped application, instead of the default one.
-
-::
-
- from bottle import default_app, run
- app = default_app()
- newapp = YourMiddleware(app)
- run(app=newapp)
-
-.. rubric: How default_app() works
-
-Bottle creates a single instance of `bottle.Bottle()` and uses it as a default for most of the module-level decorators and the `bottle.run()` routine.
-`bottle.default_app()` returns (or changes) this default. You may, however, create your own instances of `bottle.Bottle()`.
-
-::
-
- from bottle import Bottle, run
- mybottle = Bottle()
- @mybottle.route('/')
- def index():
- return 'default_app'
- run(app=mybottle)
Apache mod_wsgi
--------------------------------------------------------------------------------
@@ -739,7 +729,7 @@ File ``/var/www/yourapp/app.wsgi``::
os.chdir(os.path.dirname(__file__))
import bottle
- # ... add or import your bottle app code here ...
+ # ... build or import your bottle application here ...
# Do NOT use bottle.run() with mod_wsgi
application = bottle.default_app()
@@ -764,16 +754,27 @@ The Apache configuration may look like this::
Google AppEngine
--------------------------------------------------------------------------------
-I didn't test this myself but several Bottle users reported that this
-works just fine::
+.. versionadded:: 0.9
+
+The ``gae`` adapter completely automates the Google App Engine deployment. It even ensures that a ``main()`` function is present in your ``__main__`` module to enable `App Caching <http://code.google.com/appengine/docs/python/runtime.html#App_Caching>`_ (which drastically improves performance)::
import bottle
- from google.appengine.ext.webapp import util
- # ... add or import your bottle app code here ...
- # Do NOT use bottle.run() with AppEngine
- util.run_wsgi_app(bottle.default_app())
+ # ... build or import your bottle application here ...
+ bottle.run(server='gae')
+
+It is always a good idea to let GAE serve static files directly. Here is example ``app.yaml``::
+
+ application: myapp
+ version: 1
+ runtime: python
+ api_version: 1
+ handlers:
+ - url: /static
+ static_dir: static
+ - url: /.*
+ script: myapp.py
Good old CGI
@@ -782,7 +783,7 @@ Good old CGI
CGI is slow as hell, but it works::
import bottle
- # ... add or import your bottle app code here ...
+ # ... build or import your bottle application here ...
bottle.run(server=bottle.CGIServer)