部署¶
不添加任何参数,直接运行Bottle的 run()
函数,会启动一个本地的开发服务器,监听8080端口。你可在同一部主机上访问http://localhost:8080/来测试你的应用。
要使您的应用程序可供外部使用,请指定服务器应侦听的IP(例如 run(host='192.168.0.1')
)或者让服务器一次监听所有接口(例如 run(host='0.0.0.0')
)可以用类似的方式更改侦听端口,但您需要根或管理员权限才能选择低于1024的端口。端口80是HTTP服务器的标准:
# Listen to HTTP requests on all interfaces
run(host='0.0.0.0', port=80)
可选服务器¶
内置默认服务器基于 wsgiref WSGIServer . 这种非线程HTTP服务器对于开发来说非常好,但是当服务器负载增加时,它可能会成为性能瓶颈。有三种方法可以消除这一瓶颈:
使用多线程或支持异步IO的其他服务器。
运行多个服务器,使用负载均衡
同时使用上面两种方法
Multi-threaded 服务器是实现这一目标的“经典”方式。它们非常健壮,速度相当快,易于管理。作为一个缺点,由于python运行时的“全局解释器锁”(gil),它们只能同时处理有限数量的连接,并且只能使用一个CPU核心。这不会伤害大多数应用程序,它们大多数时间都在等待网络IO,但可能会降低CPU密集型任务(例如图像处理)的速度。
异步io 服务器速度非常快,可以处理几乎无限数量的并发连接,并且易于管理。为了充分利用它们的潜力,您需要相应地设计应用程序并理解特定服务器的概念。
多进程 (forking) 服务器就没有受到GIL的限制,能利用多个CPU核心,但服务器实例之间的交流代价比较高昂。你需要一个数据库或消息队列来在进程之间共享状态,或将你的应用设计成根本不需要共享状态。多进程服务器的安装也比较负责,但已经有很多好的教程了。
更改服务器后端¶
提高性能的最简单方法是安装类似 paste 或 cherrypy 告诉 Bottle 使用它而不是单线程默认服务器:
run(server='paste')
Bottle为很多常见的WSGI服务器都编写了适配器,能自动化安装过程。下面是一个不完整的清单:
名称 |
主页 |
描述 |
---|---|---|
CGI |
以CGI脚本运行 |
|
弗洛普 |
作为fastcgi进程运行 |
|
盖伊 |
用于Google App Engine |
|
维吉里夫 |
默认的单线程服务器 |
|
樱桃色 |
多线程,稳定 |
|
粘贴 |
多线程,稳定,久经考验,充分测试 |
|
女服务员 |
多线程,源于Pyramid |
|
gunicorn |
预复刻,部分用C书写 |
|
事件片 |
支持WSGI的异步框架 |
|
格兰特 |
异步 (greenlets) |
|
柴油机 |
异步 (greenlets) |
|
龙卷风 |
异步,支撑Facebook的部分应用 |
|
扭曲的 |
异步, well tested but... twisted |
|
缅因州 |
异步,部分用C语言编写 |
|
比约恩 |
异步,用C语言编写,非常快 |
|
汽车 |
自动选择一个可用的服务器 |
完整的列表在 server_names
。
如果没有适合你的服务器的适配器,或者你需要更多地控制服务器的安装,你也许需要手动启动服务器。可参考你的服务器的文档,看看是如何运行一个WSGI应用。下面是一个使用 paste 的例子。
application = bottle.default_app()
from paste import httpserver
httpserver.serve(application, host='0.0.0.0', port=80)
阿帕奇莫迪WSGI¶
除了直接在Bottle里面运行HTTP服务器,你也可以将你的应用部署到一个Apache服务器上,使用 mod_wsgi 来运行。
你需要的只是提供一个 application
对象的 app.wsgi
文件。mod_wsgi会使用这个对象来启动你的应用,这个对象必须是兼容WSGI的 callable对象。
File /var/www/yourapp/app.wsgi
:
import os
# Change working directory so relative paths (and template lookup) work again
os.chdir(os.path.dirname(__file__))
import bottle
# ... build or import your bottle application here ...
# Do NOT use bottle.run() with mod_wsgi
application = bottle.default_app()
Apache的配置
<VirtualHost *>
ServerName example.com
WSGIDaemonProcess yourapp user=www-data group=www-data processes=1 threads=5
WSGIScriptAlias / /var/www/yourapp/app.wsgi
<Directory /var/www/yourapp>
WSGIProcessGroup yourapp
WSGIApplicationGroup %{GLOBAL}
Require all granted
</Directory>
</VirtualHost>
UWSGI¶
uWSGI 是FastCGI的现代替代方案,也是服务器上建议的部署选项,如 nginx, lighttpd, 和 cherokee. Uwsgi项目提供了一个运行应用程序的应用程序服务器,并定义了前端Web服务器可以与之对话的协议。看看那些优秀的 Quickstart for Python/WSGI applications .
谷歌Appengine¶
0.9 新版功能.
使用python 2.7运行时环境的新应用程序引擎应用程序支持任何wsgi应用程序,应该配置为直接使用bottle应用程序对象。例如,假设应用程序的主模块是 myapp.py
::
import bottle
@bottle.route('/')
def home():
return '<html><head></head><body>Hello world!</body></html>'
app = bottle.default_app()
然后您可以配置应用程序引擎 app.yaml
使用 app
这样的对象:
application: myapp
version: 1
runtime: python27
api_version: 1
handlers:
- url: /.*
script: myapp.app
让GAE直接服务静态文件总是一个好主意。下面是一个工作的例子 app.yaml
(使用传统的python 2.5运行时环境)::
application: myapp
version: 1
runtime: python27
api_version: 1
handlers:
- url: /static
static_dir: static
- url: /.*
script: myapp.py
负载均衡 (手动安装)¶
单一的Python进程一次只能使用一个CPU内核,即使CPU是多核的。我们的方法就是在多核CPU的机器上,使用多线程来实现负载均衡。
不只是启动一个应用服务器,你需要同时启动多个应用服务器,监听不同的端口(localhost:8080, 8081, 8082, ...)。你可选择任何服务器,甚至那些异步服务器。然后一个高性能的负载均衡器,像一个反向代理那样工作,将新的请求发送到一个随机端口,在多个服务器之间分散压力。这样你就可以利用所有的CPU核心,甚至在多个机器上实现负载均衡。
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.
Pound的例子:
ListenHTTP
Address 0.0.0.0
Port 80
Service
BackEnd
Address 127.0.0.1
Port 8080
End
BackEnd
Address 127.0.0.1
Port 8081
End
End
End
Apache的例子:
<Proxy balancer://mycluster>
BalancerMember http://127.0.0.1:8080
BalancerMember http://127.0.0.1:8081
</Proxy>
ProxyPass / balancer://mycluster
Lighttpd的例子:
server.modules += ( "mod_proxy" )
proxy.server = (
"" => (
"wsgi1" => ( "host" => "127.0.0.1", "port" => 8080 ),
"wsgi2" => ( "host" => "127.0.0.1", "port" => 8081 )
)
)
CGI这个老好人¶
CGI服务器会为每个请求启动一个进程。虽然这样代价高昂,但有时这是唯一的选择。 cgi 这个适配器实际上并没有启动一个CGI服务器,只是将你的Bottle应用转换成了一个有效的CGI应用。
bottle.run(server='cgi')