部署

bottle 的 run() 函数在不带任何参数调用时,会在端口 8080 上启动一个本地开发服务器。如果您在同一台主机上,可以通过 http://localhost:8080/ 访问和测试您的应用程序。

要使您的应用程序可供外部访问,请指定服务器应监听的 IP(例如 run(host='192.168.0.1')),或让服务器同时监听所有接口(例如 run(host='0.0.0.0'))。监听端口也可以通过类似的方式更改,但选择 1024 以下的端口需要 root 或管理员权限。端口 80 是 HTTP 服务器的标准端口。

# Listen to HTTP on all interfaces
if __name__ == '__main__':
    run(host='0.0.0.0', port=80)

生产环境下的扩容

内置的开发服务器基于 wsgiref WSGIServer,这是一个非常简单的非线程 HTTP 服务器实现。这对于开发来说是完全没问题的,但当服务器负载增加时,可能会成为性能瓶颈。

提高性能的最简单方法是安装一个多线程服务器库,如 cherootgunicorn,并告诉 Bottle 使用它而不是单线程的 wsgiref 服务器

run(server='cheroot', ...)   # Pure Python, runs everywhere
run(server='gunicorn', ...)  # High performance

或使用 bottle 命令行界面

python3 -m bottle --server gunicorn [...] mymodule:app

对于生产部署,gunicorn 是一个非常好的选择。它自带了一个命令行工具,支持比 bottle 更多的选项。由于 Bottle 实例是 WSGI 应用程序,您可以告诉 gunicorn(或任何其他 WSGI 服务器)加载您的应用程序,而不是自己调用 run()

gunicorn -w 4 mymodule:app

这将使用 4 个 gunicorn 工作进程和合理的默认设置来启动您的应用程序。有关更多详细信息和更完整的示例,请查阅 Gunicorn Documentation

服务器适配器

Bottle 附带了一系列针对最常见 WSGI 服务器的即用型适配器,因此您可以轻松尝试不同的服务器后端。您可以通过 run(server=’NAME’)python3 -m bottle –server NAME 选择一个服务器后端。以下是一个不完整的列表:

名称

主页

描述

cgi

作为 CGI 脚本运行

flup

flup

作为 FastCGI 进程运行

gae

gae

Google App Engine 部署助手

wsgiref

wsgiref

单线程默认服务器

cherrypy

cherrypy

多线程(已弃用)

cheroot

cheroot

cherrypy 的后继者

paste

paste

多线程,稳定,经过测试

waitress

waitress

多线程,为 Pyramid 提供支持

gunicorn

gunicorn

预分叉,部分用 C 语言编写

eventlet

eventlet

支持 WSGI 的异步框架。

gevent

gevent

异步(greenlets)

diesel

diesel

异步(greenlets)

tornado

tornado

异步,为 Facebook 的某些部分提供支持

twisted

twisted

异步,经过良好测试但……有点 twisted (绕)

meinheld

meinheld

异步,部分用 C 语言编写

bjoern

bjoern

异步,速度非常快,用 C 语言编写

auto

自动选择第一个可用的服务器适配器

不过,这些适配器非常基础,仅为方便起见。如果您需要对部署进行更多控制,请参阅服务器后端文档,并将您的 Bottle 应用程序像其他任何 WSGI 应用程序一样进行挂载。

WSGI 部署

如果没有您喜欢的服务器的适配器,或者您需要对服务器设置有更多控制,您可能希望手动启动服务器。请参考服务器文档了解如何运行 WSGI 应用程序。cheroot 的示例如下:

import cheroot.wsgi
import mymodule.app

wsgi_server = cheroot.wsgi.Server(
    bind_addr=('0.0.0.0', 80),
    wsgi_app=mymodule.app
)

try:
    wsgi_server.start()
finally:
    wsgi_server.stop()