# 运行 Sanic(Running Sanic)

Sanic 自带了一个 Web 服务器。在大多数情况下,推荐使用该服务器来部署您的 Sanic 应用。除此之外,您还可以使用支持 ASGI 应用的服务器来部署 Sanic,或者使用 Gunicorn。

# Sanic 服务器(Sanic Server)

当定义了 sanic.Sanic 实例后,我们可以调用其 run 方法,该方法支持以下几个关键字参数:

参数名称 默认值 参数说明
host "127.0.0.1" 服务器监听的地址。
port 8000 服务器监听的端口。
unix None Unix 套接字文件(不是 TCP)。
debug False 开启 DEBUG 输出 (降低服务器性能)。
ssl None SSLContext,子进程用于 SSL 加密。
sock None 服务器接受连接的套接字。
workers 1 要生成的子进程数量。
loop None 一个兼容 asyncio 的事件循环。如果没有指定,Sanic 会创建自己的事件循环。
protocol HttpProtocol asyncio.protocol 子类。
access_log True 启用请求访问日志(显著降低服务器速度)。

在该样例中,我们关闭输出访问日志来提升性能。

# server.py
app = Sanic("My App")
app.run(host='0.0.0.0', port=1337, access_log=False)

现在,执行包含 app.run(...) 代码的 Python 脚本。

python server.py

# 子进程(Workers)

在默认情况下,Sanic 在主进程中只占用一个 CPU 核心进行服务的监听。要想增加并发,只需在运行参数中指定 workers 的数量即可。

app.run(host='0.0.0.0', port=1337, workers=4)

Sanic 会自动管理多个进程,并在它们之间进行负载均衡。我们建议将子进程数量设置的和您机器的 CPU 核心数量一样。

获得最大 CPU 性能的最简单方法是使用 fast 参数。这将自动以系统最大的核心数量来创建工作线程。

app.run(host='0.0.0.0', port=1337, fast=True)
$ sanic server:app --host=0.0.0.0 --port=1337 --fast

在没有 fast 选项的旧版 Sanic 中, 在基于 Linux 的操作系统上,有一个通用的方式来检查 CPU 核心数量:

$ nproc

或者,我们可以使用 Python 来获取该值:

import multiprocessing
workers = multiprocessing.cpu_count()
app.run(..., workers=workers)

# 通过命令行运行(Running via command)

# Sanic 命令行界面(Sanic CLI)

Sanic 也提供一个简单的命令行界面,来帮助您通过命令行启动。

比如,如果您在 server.py 文件中初始化了一个 Sanic 应用,您可以使用右侧命令运行程序:

sanic server.app --host=0.0.0.0 --port=1337 --workers=4

您还可以使用 sanic --help 来查看所有选项。

$ sanic --help
usage: sanic [-h] [--version] [--factory] [-s] [-H HOST] [-p PORT] [-u UNIX] [--cert CERT] [--key KEY] [--tls DIR] [--tls-strict-host]
             [-w WORKERS | --fast] [--access-logs | --no-access-logs] [--debug] [-d] [-r] [-R PATH] [--motd | --no-motd] [-v]
             [--noisy-exceptions | --no-noisy-exceptions]
             module
   ▄███ █████ ██      ▄█▄      ██       █   █   ▄██████████
  ██                 █   █     █ ██     █   █  ██
   ▀███████ ███▄    ▀     █    █   ██   ▄   █  ██
               ██  █████████   █     ██ █   █  ▄▄
  ████ ████████▀  █         █  █       ██   █   ▀██ ███████
 To start running a Sanic application, provide a path to the module, where
 app is a Sanic() instance:
     $ sanic path.to.server:app
 Or, a path to a callable that returns a Sanic() instance:
     $ sanic path.to.factory:create_app --factory
 Or, a path to a directory to run as a simple HTTP server:
     $ sanic ./path/to/static --simple
Required
========
  Positional:
    module                         Path to your Sanic app. Example: path.to.server:app
                                   If running a Simple Server, path to directory to serve. Example: ./
Optional
========
  General:
    -h, --help                     show this help message and exit
    --version                      show program's version number and exit
  Application:
    --factory                      Treat app as an application factory, i.e. a () -> <Sanic app> callable
    -s, --simple                   Run Sanic as a Simple Server, and serve the contents of a directory
                                   (module arg should be a path)
  Socket binding:
    -H HOST, --host HOST           Host address [default 127.0.0.1]
    -p PORT, --port PORT           Port to serve on [default 8000]
    -u UNIX, --unix UNIX           location of unix socket
  TLS certificate:
    --cert CERT                    Location of fullchain.pem, bundle.crt or equivalent
    --key KEY                      Location of privkey.pem or equivalent .key file
    --tls DIR                      TLS certificate folder with fullchain.pem and privkey.pem
                                   May be specified multiple times to choose multiple certificates
    --tls-strict-host              Only allow clients that send an SNI matching server certs
  Worker:
    -w WORKERS, --workers WORKERS  Number of worker processes [default 1]
    --fast                         Set the number of workers to max allowed
    --access-logs                  Display access logs
    --no-access-logs               No display access logs
  Development:
    --debug                        Run the server in debug mode
    -d, --dev                      Currently is an alias for --debug. But starting in v22.3,
                                   --debug will no longer automatically trigger auto_restart.
                                   However, --dev will continue, effectively making it the
                                   same as debug + auto_reload.
    -r, --reload, --auto-reload    Watch source directory for file changes and reload on changes
    -R PATH, --reload-dir PATH     Extra directories to watch and reload on changes
  Output:
    --motd                         Show the startup display
    --no-motd                      No show the startup display
    -v, --verbosity                Control logging noise, eg. -vv or --verbosity=2 [default 0]
    --noisy-exceptions             Output stack traces for all exceptions
    --no-noisy-exceptions          No output stack traces for all exceptions

# 作为模块运行 (As a module)

Sanic 也可以被当做模板直接调用。

python -m sanic server.app --host=0.0.0.0 --port=1337 --workers=4

小提示

无论使用哪种方法(CLI 或模块),都再不应该在 Python 文件中调用 app.run()。如果您想调用该方法,请确认将其包装起来,使它只有在使用解释器运行文件时才会被执行。

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=1337, workers=4)

# Sanic 简易服务器

有时,您为了快速搭建一个本地环境,只需要代理一些静态文件。现在,只要指定一个特定的目录,Sanic 就能为您搭建一个简易的静态文件服务器。

sanic ./path/to/dir --simple

这也可以和自动重启功能一起使用。

sanic ./path/to/dir --simple --reload --reload-dir=./path/to/dir

# ASGI

Sanic 同样兼容 ASGI。这意味着您可以使用您喜爱的 ASGI 服务器来运行 Sanic。现在有三大主流的 ASGI 服务器, Daphne (opens new window)Uvicorn (opens new window),和 Hypercorn (opens new window)

警告

Daphne 不支持 ASGI 中的 lifespan 协议,因此并不能用于 Sanic。更多详细信息请参考 Issue #264 (opens new window)

您需要参考他们的文档来找到运行 ASGI 应用的正确方式,这些启动命令大概看起来像这样:

uvicorn myapp:app
hypercorn myapp:app

当使用 ASGI 时,您需要关注以下几件事情:

  1. 当使用 Sanic 服务器,websocket 功能将使用 websockets 包来实现。在 ASGI 模式中,将不会使用该第三方包,因为 ASGI 服务器将会管理 websocket 链接。

  2. ASGI 生命周期协议 (opens new window) 中规定 ASGI 只支持两种服务器事件:启动和关闭。而 Sanic 则有四个事件:启动前、启动后、关闭前和关闭后。因此,在 ASGI 模式下,启动和关闭事件将连续运行,并不是根据服务器进程的实际状态来运行(因为此时是由 ASGI 服务器控制状态)。因此,最好使用 after_server_startbefore_server_stop

# Trio

Sanic 对使用 Trio 运行有着实验性的支持:

hypercorn -k trio myapp:app

# Gunicorn

Gunicorn (opens new window) ("Green Unicorn") 是一个基于 UNIX 操作系统的 WSGI HTTP 服务器。它是从 Ruby 的 Unicorn 项目中移植而来,采用的是 pre-fork worker 模型。

为了使用 Gunicorn 来运行 Sanic 应用程序,您需要使用 Sanic 提供的 sanic.worker.GunicornWorker 类作为 Gunicorn worker-class 参数。

gunicorn myapp:app --bind 0.0.0.0:1337 --worker-class sanic.worker.GunicornWorker

如果您的应用有内存泄漏的困扰,您可以通过配置 Gunicorn 使子进程在处理了一定数量的请求后平滑重启。这种方法可以很方便得减少内存泄漏带来的影响。

查看 Gunicorn 文档 (opens new window) 来获取更多信息。

注意

当通过 gunicorn 运行 Sanic 时,您将失去 async/await 带来的诸多性能优势。对于该种部署方式,请三思而后行。的确,Gunicorn 提供了很多配置选项,但它不是让 Sanic 全速运行的最佳坏境。

# 性能方面的考虑 (Performance considerations)

当部署在生产环境时,请确保 debug 模式处于关闭状态。

app.run(..., debug=False)

如果您选择关闭了 access_log ,Sanic 将会全速运行。

如果您的确需要请求访问日志,又想获得更好的性能,可以考虑使用 Nginx 作为代理,让 Nginx 来处理您的访问日志。这种方式要比用 Python 处理快得多得多。

app.run(..., access_log=False)
MIT Licensed
Copyright © 2018-present Sanic Community Organization

~ Made with ❤️ and ☕️ ~