NGINX Unit是一款完全动态的应用服务器,可支持多种语言以及每种语言的多个版本。其动态性体现在:可以使用RESTful JSON API修改内存中的配置,无需中断服务或重新加载配置。
在10月举行的NGINX Conf 2018上,我演示了如何在现有生产环境中配置新应用。具体来说,我在运行基于PHP的WordPress的环境中部署了一个使用Django框架的Python应用。我还演示了如何从文件加载配置,以及如何通过API调用参数指定并加载配置。
本博客包含我在演示中使用的所有命令和配置代码,便于您根据自己的部署进行调整。
先决条件
为了在NGINX Conf上进行演示,我安装了以下软件:
- Ubuntu 16.04
- NGINX Plus,但除非另有说明,也可以使用 NGINX Open Source
- NGINX Unit,已安装所有语言模块
- Python 3
- Django(尚未配置,本演示和这篇博客将介绍如何配置)
root权限,或通过sudo获得的同等访问权限(我们会在必要时使用)
我还安装了PHP和WordPress作为现有应用。
创建Django项目
- 切换到要创建Django项目的目录:
$ cd /var/www/- 使用
django-adminstartproject命令初始化新项目。我们将其命名为djapp。
$ sudo django-admin startproject djapp- 切换到项目目录:
$ cd djapp- 使用
manage.py脚本迁移项目数据库,这是新建项目的必要步骤。Django默认使用SQLite,本演示也采用此默认设置,但您可以使用任何满足项目需求的数据库。manage.py脚本由我们在第2步运行的django-admin命令安装;它执行与django-admin相同的命令并接受相同的参数,但会自动获取并使用一些项目特定的设置,更加方便。有关详细信息,请参阅Django文档。
$ sudo python3 manage.py migrate- 对于此类示例项目,虽然并非必须,但建议创建一个Django 超级用户身份:
$ sudo python3 manage.py createsuperuser- 切换到包含settings.py文件的子目录。该文件由第 2 步中的
django-adminstartproject命令创建。
$ cd /var/www/djapp/djapp- 使用常用的文本编辑器打开settings.py。此处使用
nano:
$ sudo nano settings.py- 找到
ALLOWED_HOSTS行,并添加应用程序的域名、主机名或IP地址:
ALLOWED_HOSTS = ['domain-name']- 此外,在文件末尾添加以下行,用于指定存储应用程序所提供的所有静态内容的目录(请参阅步骤 9)。
STATIC_ROOT = '/var/www/djapp/djapp/static'- 切换回主项目目录(即manage.py所在的目录)。
$ cd ..- 运行
manage.pycollectstatic命令,收集Django项目中的所有静态文件,并将其放入步骤7中定义的STATIC_ROOT位置。
$ sudo python3 manage.py collectstatic配置NGINX
默认情况下,Django本身负责提供项目的静态内容,但NGINX Open Source和NGINX Plus可提供更出色的性能。此处配置的是NGINX Plus,但除下文所述的一项功能外,也可以使用NGINX Open Source。
- 切换到目录/etc/nginx/conf.d,这是存放特定功能(在本例中为特定应用)HTTP配置文件的常用位置:
$ cd /etc/nginx/conf.d- 创建一个名为“django.conf”的文件(这里仍使用
nano):
$ sudo nano django.conf- 插入以下配置以启用缓存。该配置还包含两项NGINX Plus专属功能。如果您使用NGINX Plus并希望利用这些功能,请取消相关指令的注释。需要注意的是,在NGINX Conf的演示中,我将本地计算机的IP地址指定为
proxy_set_header指令的第二个参数。在生产环境中,更适合使用如下所示的$host变量。
# Upstream group for the backend (NGINX Unit running the Python application)
upstream django_unit {
zone django_unit 64k;
server 127.0.0.1:8000;
}
server {
listen 8080;
# Uncomment to collect metrics if using NGINX Plus and the NGINX Plus API
#status_zone django;
# enable caching
proxy_cache django_cache;
proxy_cache_valid 200 60m;
# root directory for static files
root /var/www/djapp/djapp;
# proxy to the NGINX Unit backend
location / {
proxy_pass http://django_unit;
# Second argument must match your production hostname and the value of
# ALLOWED_HOSTS in settings.py
proxy_set_header Host $host;
# Uncomment to enable active health checks if using NGINX Plus
#health_check;
}
# Location for the static files collected from Django and served by
# NGINX Plus; can be empty (as here), because it inherits the value of the
# 'root' directive from its parent block
location /static {
}
}- 扩展指标收集功能,通过
status_zone指令为此虚拟服务器启用。这里假定已在配置的其他位置启用 NGINX Plus API。 - 主动运行状况检查,通过
health_check指令启用。
- 检查配置的语法是否有效:
$ sudo nginx –t- 修复所有错误后,重新加载配置:
$ sudo nginx -s reload配置 NGINX Unit
最后,我们需要配置NGINX Unit,将请求转发给应用程序。
- 运行以下
curl命令,显示当前的NGINX Unit配置,该配置用于在PHP上运行的WordPress。此处不显示输出,但在下面的步骤6中会同时显示WordPress配置和即将添加的Python应用配置。请注意,我在sudo命令中使用了curl,但大多数curl命令可能不需要这样做。此处必须使用该命令,因为访问UNIX套接字需要root对其拥有的读写权限。
$ sudo curl --unix-socket /run/control.unit.sock http://localhost/config/- 切换到NGINX Unit配置文件所在的目录。请注意,这些文件并非必需,只是为了方便加载一组配置,无需在调用NGINX Unit API时将所有数据作为参数输入。由于文件内容与所有配置数据一样通过API上传,因此NGINX Unit并不知道文件的位置,也无法在启动时自动读取文件(这与NGINX Open Source和NGINX Plus不同)。NGINX Unit会将其运行时状态保存在单独的目录中。
$ cd /etc/unit- 创建一个名为“django.config”的文件(这里仍使用
nano):
$ sudo nano django.config- 添加以下JSON,该JSON表示我们的Python应用程序。
{
"type": "python",
"processes": 5,
"module": "djapp.wsgi",
"path": "/var/www/djapp"
}- 运行以下
curl命令,将django.config中包含的JSON加载为由NGINX Unit管理的新应用程序对象,并将其命名为djapp:
$ sudo curl -X PUT --data-binary @/etc/unit/django.config --unix-socket /run/control.unit.sock http://localhost/config/applications/djapp- 在此命令中:
- HTTP
PUT方法会在最后一个参数(URL)指定的位置创建新的 NGINX Unit 配置对象。请参阅下方最后一个项目符号。 - The
--data-binary参数指示curl按原样加载django.config的内容,保留换行符和回车符,不进行任何处理。 - The
--unix-socket参数用于定义NGINX Unit API的侦听位置。(由于套接字使用默认所有者sudo,因此我们使用root命令。) - 最后一个参数用于定位并命名新的应用程序对象,以便使用以下文件中采用JSON格式的配置数据填充该对象:django.config。其中,
config是NGINX Unit的顶层配置对象,applications是应用程序对象的父对象,djapp是新应用程序对象的名称。
- HTTP
- 为应用定义监听器对象。与步骤4中加载配置数据文件不同,我们直接在
curl命令行中定义数据,并指定djapp应用监听8000端口。
$ sudo curl -X PUT --data-binary '{"application":"djapp"}' --unix-socket /run/control.unit.sock 'http://localhost/config/listeners/*:8000'- 重复执行步骤 1 中的“
curl”命令,以显示 NGINX Unit 配置。该配置现在包含我们的 Python 应用程序“djapp”,并以橙色突出显示:
$ sudo curl --unix-socket /run/control.unit.sock http://localhost/config/{
"listeners": {
"127.0.0.1:8090": {
"application": "script_index_php"
},
"127.0.0.1:8091": {
"application": "direct_php"
},
"*:8000": { "application": "djapp" }
},
"applications": {
"script_index_php": {
"type": "php",
"processes": {
"max": 20,
"spare": 5
},
"user": "www-data",
"group": "www-data",
"root": "/var/www/wordpress",
"script": "index.php"
},
"direct_php": {
"type": "php",
"processes": {
"max": 5,
"spare": 0
},
"user": "www-data",
"group": "www-data",
"root": "/var/www/wordpress",
"index": "index.php"
},
"djapp": { "type": "python", "processes": 5, "module": "djapp.wsgi", "path": "/var/www/djapp" }
}
}总结
本文首先介绍了如何使用NGINX Unit在生产环境中运行WordPress的PHP应用,然后添加了一个Python应用。在演示中,我使用NGINX Plus仪表盘说明添加新应用不会中断现有应用,但也可以使用任何系统监控工具(例如ps命令)来验证这一点。NGINX Unit配置的动态特性可以为正在运行的应用节省资源,并确保新部署实现零停机,以及应用版本之间平稳过渡。
要了解更多信息,请访问unit.nginx.org。
相关博客文章
NGINX Plus R26 正式发布
NGINX Plus R26通过缓存JSON Web密钥集加快JWT验证,并强化TLS握手,从而提升安全性。NGINX JavaScript的新功能包括增强对异步函数的支持,以及实现WebCrypto API。
使用NGINX App Protect DoS保护gRPC应用,抵御严重的DoS攻击
gRPC具备开发人员设计和部署现代应用所需的速度与灵活性,但其开放性也使其极易受到第7层DoS攻击。NGINX App Protect DoS可保护gRPC应用免受此类破坏性攻击。
Ingress Controller 选型指南(第 2 部分):风险与面向未来的规划
了解选择错误的Ingress控制器可能带来的风险,以及如何从关键方面着手,让您的选择更好地适应未来需求。
NGINX Plus R19 正式发布
NGINX Plus R19扩展了监控功能,不仅提供更多指标,还新增了指标分析方式;增加试运行模式,用于测试限速效果;增强键值存储,以支持IP地址范围;并使限速更加动态。
NGINX现已正式加入F5
NGINX现已正式成为F5的一部分。Gus Robertson现任F5 NGINX业务部门负责人。他阐述了两家公司在人才、文化和愿景方面融合的价值,以及双方将如何携手增强NGINX的开源产品和商业产品。
