Skip to content

Nginx

像 Gunicorn 这类 WSGI 服务器内置了 Web 服务器,所以我们不需要 Web 服务器也可以与客户端交换数据,处理请求和响应。但内置的 Web 服务器不够强健,虽然程序已经可以运行,但是更流行的部署方式是使用一个常规的 Web 服务器运行在前端,为 WSGI 服务器提供反向代理。

流行的开源 Web 服务器有 Nginx(http://nginx.org/ )、Apache(https://www.apache.org/ )等,因为我们上面使用了 Gunicorn ,所以这里选择使用和 Gunicorn 集成良好的 Nginx 。首先使用下面的命令安装 Nginx :

shell
sudo apt install nginx

设置反向代理

在这种模式下,Nginx 作为代理服务器,监听来自外部的 80 端口的请求;而 Gunicorn 负责监听本地机 8000 端口的请求。Nginx 会把来自外部的请求转发给 Gunicorn 处理,接收到响应后再返回给客户端。这样做有下面这些好处:

  • 提高处理静态文件的效率。Nginx 处理静态文件的速度非常快,而且可以对静态文件设置缓存。
  • 提高安全系数。使用它可以避免直接暴露 WSGI 服务器,而且可以作为防火墙来防御网络攻击。
  • 提高程序处理能力。设置反向代理可以缓冲请求,对请求进行预处理,交给 WSGI 服务器一个完整的 HTTP 请求。还可以设置负载均衡,优化请求处理效率。

当使用反向代理服务器后,Gunicorn 不需要再监听外部请求,而是直接监听本地机的某个端口。我们可以使用默认值,即本地机的 8000 端口。不过现在还不用着急运行,我们需要先来配置Nginx。

当我们安装了 Nginx 后,它会自动运行,现在本地访问远程主机的 IP 地址,会看到 Nginx 提供的测试页面。

image-20201128142459222

Nginx测试页面

我们可以在 Nginx 的默认配置文件(/etc/nginx/nginx.conf )中写入程序配置,但通常情况下,为了便于组织,我们可以在 /etc/nginx/sites-enabled/ 或是 /etc/nginx/conf.d/ 目录下为我们的 Flask 程序创建单独的 Nginx 配置文件。这个目录下的 default 文件存储了上面提到的测试页面的配置,也是作为一个配置文件示例,你可以修改它来作为程序配置,但为了更直观这里我们将直接删除它,然后使用 nano 为我们的程序创建一个新的配置文件(编写 etc/ 下的配置文件需要超级用户权限,因此要添加 sudo):

$ sudo rm /etc/nginx/sites-enabled/default
$ sudo vi /etc/nginx/sites-enabled/qdbbs

Nginx 使用指令来组织配置。直接写在配置文件中的是全局指令,定义了 Nginx 的一些通用设置。其他的指令通常写在使用块指令定义的块中,块使用花括号包围。

Nginx配置的常用指令

提示

其他的语法规则包括:块通过花括号“{}”指定;每一行指令以“;”结尾;以“#”开头的是注释。

/etc/nginx/sites-enabled 目录下的配置文件可以直接定义 server 块,而不必添加 http 父块,因为这个文件的内容会被自动插入到全局配置文件(/etc/nginx/nginx.conf)的 http 块中。

/etc/nginx/sites-enabled/qdbbs:Nginx配置

nginx
server {
    listen 80 default_server;
    access_log  /var/log/nginx/access.log;
    error_log  /var/log/nginx/error.log;

   location / {
            proxy_pass http://127.0.0.1:5000;  # 转发的地址,即Gunicorn运行的地址
            proxy_redirect     off;

            proxy_set_header   Host                 $host;
            proxy_set_header   X-Real-IP            $remote_addr;
            proxy_set_header   X-Forwarded-For      $proxy_add_x_forwarded_for;
            proxy_set_header   X-Forwarded-Proto    $scheme;
    }
}

在这个 server 块中,listen 指令设置监听 80 端口,然后使用 server_name 设置被转发请求的 IP 或域名,这里使用_作为通配符(catch-all)。如果你注册了域名并设置了域名解析,可以这样写前两行:

nginx
server {
    listen 80;
    server_name example.com;
    ...
}

在 server 块中我们创建两个 location 块。

第一个 location 块为 HTTP 规则 “/” 设置转发,proxy_pass 指定设置转发的目标位置,即本地机的 8000 端口,我们待会将要让 Gunicorn 服务器监听这个地址;proxy_set_header 指令用来重写一些请求首部,以便让程序正常工作;

第二个 location 块用来将发往 /static 路径下的请求发给 Nginx 处理,并使用 alias 指令设置这个 URL 对应文件系统中的具体路径。expires 30d 设置缓存时间为 30 天。当客户端发来静态文件的请求时会由 Nginx 直接从静态文件目录获取,这要比使用 Flask 获取快得多。

注意

这时需要考虑到扩展提供的静态文件问题,因为扩展内置的静态文件目录在虚拟环境的扩展包目录下,我们需要匹配到正确的路径,这也是为什么我不推荐使用扩展内置资源的原因之一。

Nginx 还有很多可用的配置选项。比如,你还可以使用它来设置Gzip压缩,这里的配置只是一个简单的示例,更多设置请访问文档(http://nginx.org/en/docs/ )了解。

更新配置文件后,我们可以通过下面的命令来测试语法正确性:

$ sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

如果一切正常,那么现在可以重启Nginx让配置生效:

sudo service nginx restart

当使用反向代理服务器后,Gunicorn 不需要再监听外部请求,而是直接监听本地机的某个端口。我们可以使用默认值,即本地机的 8000 端口。不过现在还不用着急运行,我们需要先来配置Nginx。

最后,我们使用下面的命令运行 Gunicorn ,这会默认监听本地机的 8000 端口,即我们在 Nginx 设置的转发目标地址:

gunicorn -w 4 wsgi:app

现在打开浏览器直接访问服务器域名就可以看到你的程序主页。如果你没有设置域名,那么可以通过服务器公网 IP 访问,比如 http://106.52.167.142/