NGINX 微服务 Unit + PHP 初探
简介
NGINX Unit 是一个动态的网络应用服务器,它的设计初衷是为了运行多种编程语言。如有需要,通过 API 可以动态配置已有应用的参数。
核心功能
- 可使用 RESTful JSON API 动态配置服务器
- 可同时运行多语言及多版本的应用
- 动态语言的进程管理功能(开发中)
- TLS 支持(开发中)
- TCP, HTTP, HTTPS, HTTP/2 路由和代理(开发中)
支持的语言
- Python
- PHP
- Go
- JavaScript / Node.js(开发中)
- Java(开发中)
- Ruby(开发中)
使用包管理器安装
目前只支持 CentOS 7.0 和 Ubuntu 16.04。
CentOS
安装
yum install unit
创建 /etc/yum.repos.d/unit.repo,内容如下:
[unit]
name=unit repo
baseurl=http://nginx.org/packages/mainline/centos/7/$basearch/
gpgcheck=0
enabled=1
Ubuntu
安装
apt-get update
apt-get install unit
在 /etc/apt/sources.list 增加如下内容:
deb http://nginx.org/packages/mainline/ubuntu/ xenial nginx
deb-src http://nginx.org/packages/mainline/ubuntu/ xenial nginx
下载 秘钥,该秘钥用于验证 NGINX 源的签名,执行
sudo apt-key add nginx_signing.key
从源码编译安装
安装依赖
CentOS
yum install gcc make php-devel php-embedded
Ubuntu
apt-get install build-essential php-dev libphp-embed
配置 PHP 模块,最终会生成名为 php.unit.so 的文件
git clone https://github.com/nginx/unit
cd unit
./configure
./configure php
如果是自定义安装的 PHP,需要用如下命令:
./configure php --module=<prefix> --config=<script-name> --lib-path=<pathname>
其中的参数含义如下:
- --module
设置 php 模块的文件名前缀,最终生成的文件名为<prefix>.unit.so - --config
php-config 脚本所在的路径 - --lib-path
PHP library 所在的路径
以 PHP7.0 为例,命令如下:
./configure php --module=php70 \
--config=/usr/lib64/php7.0/php-config \
--lib-path=/usr/lib64/php7.0/lib64
得到如下输出:
configuring PHP module
checking for PHP ... found
+ PHP version: 7.0.22-0ubuntu0.16.04.1
+ PHP SAPI: [apache2handler embed cgi cli fpm]
checking for PHP embed SAPI ... found
+ PHP module: php70.unit.so
编译安装
make all
make install
从 Docker 安装
docker pull airycanon/nginx-unit-php
配置和运行
配置文件
一个基础的配置文件必须包含以下两部分:
监听器监听器指定了 IP 和 端口以及绑定的应用,下面的示例中,端口 8300 的请求全部会被发送至 blogs 这个应用:
{
"listeners": {
"*:8300": {
"application": "blog"
}
},
...
}
应用下面的示例描述了一个名为 blog 的 PHP 应用
{
"applications": {
"blog": {
"type": "php",
"workers": 20,
"root": "/www/blogs/scripts",
"index": "index.php"
}
}
}
| 配置项 | 描述 |
|---|---|
| type | 应用的编程语言 |
| workers | workers 的数量 |
| root | 应用的根目录 |
| index | 应用入口文件 |
| working_directory (可选) | 应用的工作目录 |
| script(可选) | 脚本路径,基于应用根目录的相对路径,访问应用内的任意 URL 均会运行该脚本 |
| user (可选) | 运行进程的用户,默认为 nobody |
| group (可选) | 用户所在的用户组,默认为 user 的用户组 |
创建应用
这里为了简化步骤,采用了 Docker 的方式运行。
默认情况下,Unit 通过 Unix domain socket 文件 unit.control.sock 提供 API,通过如下命令创建应用:
curl -X PUT -d @./json/config.json --unix-socket ./run/control.unit.sock http://localhost/
访问 http://localhost:8300 可以看到 phpinfo 的页面
创建一个 applications/blog/index.php,内容如下
<?php phpinfo(); ?>
创建一个配置文件 json/config.json,内容如下:
{
"listeners": {
"*:8300": {
"application": "blog"
}
},
"applications": {
"blog": {
"type": "php",
"workers": 20,
"root": "/applications/blog",
"index": "index.php"
}
}
}
首先创建两个目录 applications run 作为容器的 Volume 挂载
mkdir applications run
docker run -v `pwd`/applications:/applications -v `pwd`/run:/var/run:rw
-p 8300:8300 -d airycanon/nginx-unit-php
查看应用配置
查看某个应用的配置:
curl --unix-socket ./run/control.unit.sock http://localhost/applications/blog
{
"type": "php",
"user": "nobody",
"group": "nobody",
"workers": 20,
"root": "/applications/blog",
"index": "index.php"
}
查看所有应用的配置:
curl --unix-socket ./run/control.unit.sock http://localhost/
{
"applications": {
"blogs": {
"type": "php",
"user": "nobody",
"group": "nobody",
"workers": 20,
"root": "/applications/blog",
"index": "index.php"
}
},
"listeners": {
"*:8300": {
"application": "blog"
},
}
}
修改应用
修改应用的根目录:
curl -X PUT -d '"/applications/blog-dev"' --unix-socket
./run/control.unit.sock http://localhost/applications/blog/root
{
"success": "Reconfiguration done."
}
修改 *:8300 监听绑定的应用:
curl -X PUT -d '"blog-dev"' --unix-socket
./run/control.unit.sock http://localhost/listeners/*:8300/application
{
"success": "Reconfiguration done."
}
删除应用
删除应用:
curl -X DELETE --unix-socket ./run/control.unit.sock http://localhost/applications/blog
{
"success": "Reconfiguration done."
}
删除对 *:8300 端口的监听:
curl -X DELETE --unix-socket ./run/control.unit.sock
http://localhost/listeners/*:8300
{
"success": "Reconfiguration done."
}
与 NGINX 一起使用
使用 NGINX 作为代理
upstream unit_backend {
server 127.0.0.1:8300;
}
示例 1
server {
location / {
root /var/www/static-data;
}
location ~ \.php$ {
proxy_pass http://unit_backend;
proxy_set_header Host $host;
}
}
示例 2
server {
location /static {
root /var/www/files;
}
location / {
proxy_pass http://unit_backend;
proxy_set_header Host $host;
}
}
设置 Unix domain socket 的 API 可以被远程访问
由于 API 可以动态修改应用配置,请注意增加安全认证 https://1winkenya.top
server {
# Configure SSL encryption
server 443 ssl;
ssl_certificate /path/to/ssl/cert.pem;
ssl_certificate_key /path/to/ssl/cert.key;
# Configure SSL client certificate validation
ssl_client_certificate /path/to/ca.pem;
ssl_verify_client on;
# Configure network ACLs
#allow 1.2.3.4; # Uncomment and change to the IP addresses and networks
# of the administrative systems.
deny all;
# Configure HTTP Basic authentication
auth_basic on;
auth_basic_user_file /path/to/htpasswd.txt;
location / {
proxy_pass http://unix:/var/run/control.unit.sock
}
}