部署

不添加任何参数,直接运行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核心,但服务器实例之间的交流代价比较高昂。你需要一个数据库或消息队列来在进程之间共享状态,或将你的应用设计成根本不需要共享状态。多进程服务器的安装也比较负责,但已经有很多好的教程了。

更改服务器后端

提高性能的最简单方法是安装类似 pastecherrypy 告诉 Bottle 使用它而不是单线程默认服务器:

run(server='paste')

Bottle为很多常见的WSGI服务器都编写了适配器,能自动化安装过程。下面是一个不完整的清单:

名称 主页 描述
CGI   以CGI脚本运行
弗洛普 flup 作为fastcgi进程运行
盖伊 gae 用于Google App Engine
维吉里夫 wsgiref 默认的单线程服务器
樱桃色 cherrypy 多线程,稳定
粘贴 paste 多线程,稳定,久经考验,充分测试
火箭 rocket 多线程
女服务员 waitress 多线程,源于Pyramid
gunicorn gunicorn 预分叉,部分用C书写
事件片 eventlet 支持WSGI的异步框架
格兰特 gevent 异步 (greenlets)
柴油机 diesel 异步 (greenlets)
FAPWS3 fapws3 异步 (network side only), written in C
龙卷风 tornado 异步,支撑Facebook的部分应用
扭曲的 twisted 异步, well tested but... twisted
缅因州 meinheld 异步,部分用C语言编写
比约恩 bjoern 异步,用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')