本文所述nginx配置及测试在window环境下进行;
下载
移步官网
常用的几个命令行参数
- 启动nginx可以直接使用
nginx
或者nginx -c file.conf
-c file.conf
: 使用单独指定的配置文件file.conf
而不是默认的配置文件nginx/conf/nginx.conf
;-v
: 查看nginx的版本信息;-V
: 查看nginx的版本信息、编译版本及配置参数
-t
: 测试当前默认配置文件是否正确;仅用于测试,不会启动nginx服务;-s arg
: 用于向控制进程发送信号对nginx服务进行控制,支持的参数有stop
、quit
、reload
、reopen
;
stop
表示立即关闭nginx服务;
quit
表示处理完当前连接请求后再关闭服务;
reload
表示重载配置文件,关闭之前的工作进程并使用新载入的配置文件重启一个新的工作进程;
reopen
表示重新打开日志文件,常用于日常的日志分割;
nginx内置变量
nginx包含了许多内置变量,可以让我们更方便更精细的进行路径匹配,处理请求等操作;
变量 | 含义 |
---|---|
$arg_name | query string中的某个参数名 |
$is_args | 请求地址是否包含查询参数 |
$remote_addr | 客户端地址 |
$request | 完整的原始请求行 |
$request_uri | 包括查询参数的完整请求URI |
$request_method | 请求方法 |
$scheme | 请求使用的协议:http或https |
示例:
$arg_name
:访问http://localhost/variable?num=123&name=fn
,返回601;访问http://localhost/variable?num=123&name=who
返回602;访问http://localhost/variable
返回603;location /variable { if ($arg_name = fn) { return 601; } if ($is_args) { return 602; } return 603; }
$request
、$request_uri
、$request_method
:请求的完整url是http://localhost/test?name=fn&id=123
,此时$request
为GET /test?name=fn&id=123 HTTP/1.1
;$request_method
为GET
;$request_uri
为/test?name=fn&id=123
;
简单自定义日志格式
由于nginx可能同时配置多个服务,不同的服务需要不同的日志文件以及对应的不同精细程度的日志内容格式;nginx提供了用户自定义日志文件及具体日志内容格式的功能;
-
定义方法:
指令 含义 access_log path [format [buffer=size] [gzip[=level]] [flush=time] [if=condition]]; 指定日志路径文件名及日志所用格式名;用于具体日志文件对应于不同服务,因此定义在server字段层级 log_format name [escape=default|json|none] string … 日志格式命名及具体定义,格式定义由于在各服务之间可以通用,因此定义在http字段层,server外层 -
配置文件示例
worker_processes 1; events { worker_connections 1024; } http { # 自定义日志格式 log_format example '$remote_addr' - '$status' - '$request_uri' - '$bytes_sent'; server { listen 80; server_name localhost; # 日志文件路径及日志格式定义 access_log logs/example.log example; } }
location匹配规则
- 语法:
location [ = | ~ | ~* | ^~ ] uri { ... }
或者location @name { ... }
(非正则,通常用于重定向),其中路径中的转义字符会被解码后再匹配; - 符号解释:
\
:通配符=
:严格相等^~
:非正则匹配,不进行正则匹配,常用于目录匹配~
:大小写敏感正则匹配~*
:大小写不敏感正则匹配
- 匹配顺序:
- 优先级最高的是
=
严格相等匹配符;如果严格匹配,则跳过剩余步骤(严格匹配处理请求的速度更快); - 进行字符串前缀匹配并找到可以匹配的最长子串,并记录为re;
- 如果前缀匹配项包含
^~
,那么匹配项为^~
前缀匹配对应项,并跳过剩余步骤; - 否则进行正则匹配,正则匹配优先级按照出现在配置文件中的位置先后顺序,匹配则终止;
- 通配符;
- 优先级最高的是
- demo:
进行域名绑定:nginx.test.com为127.0.0.1;测试结果:location = / { [ configuration A ] } location / { [ configuration B ] } location /documents/ { [ configuration C ] } location ^~ /images/ { [ configuration D ] } location ~* \.(gif|jpg|jpeg)$ { [ configuration E ] }
正向代理与反向代理
所谓的正向代理,是指代理客户端去访问某个需要访问的网站以获取特定的资源,比如通常说的翻墙等;反向代理通常是设置在服务端,主要是进行安全隔离、负载均衡等;使用代理可以隐藏客户端(正向代理)或者真实身份(反向代理),并且可以通过缓存策略提高访问效率;
- 正向代理
- 反向代理
在服务器端localhost:5555
域名下有一个test.html文件,访问结果如下:
现在使用nginx配置代理,添加配置// 启动一个服务器,端口号5555 const http = require('http'); const server = http.createServer(); const url = require('url'); const qs = require('querystring'); const WebSocket = require('ws'); server.on('request', (req, res) => { res.write('another server, port: 5555'); res.end(); }) server.listen(5555); console.log('server is running at port 5555...')
proxy_pass http://localhost:5555
,并使用location匹配规则匹配test.html文件
现在访问# 80端口服务器 server { listen 80; server_name localhost; location / { root html; index index.html index.htm; #proxy_pass http://site; } location ~ /test.html$ { proxy_pass http://127.0.0.1:5555; } }
http://localhost/test.html
,结果如下:
这样看来,我们已经实现了反向代理;
负载均衡
通过nginx的upstream
字段可以实现服务器负载均衡;关键配置如下:
upstream name {
server address [params];
server address [params];
...
}
其中可选的参数列表包括
weigth=number
,表示各服务器的访问权重,默认为1;fail_timeout=seconds
,表示最大尝试建立连接时长,默认为10s;
首先在本地启动两个服务localhost:5555
和localhost:6688
;max_fails=number
:允许的最大失败请求次数,与fail_timeout
相关,默认值为1;backup
:标明该服务器为后备服务器,当主服务器挂起时,该服务会启用;
// localhost:5555
const http = require('http');
const server = http.createServer();
const url = require('url');
const qs = require('querystring');
const WebSocket = require('ws');
server.on('request', (req, res) => {
res.write('another server, port: 5555');
res.end();
})
server.listen(5555);
console.log('server is running at port 5555...')
// localhost:6688
const http = require('http');
const server = http.createServer();
const qs = require('querystring');
const url = require('url');
let count= 0;
server.on('request', (req, res) => {
// var params = url.parse(req.url, true);
var params = qs.parse(req.url.split('?')[1]);
res.write(JSON.stringify(params));
res.end(`port: 6688`);
})
server.listen(6688);
console.log('server is running at port 6688...')
然后在nginx中设置负载均衡,主要字段是`upstream sitename { hostlist },具体如下:
worker_processes 1; # 工作进程数(CPU数*核数)
events {
worker_connections 1024; # 进程最大连接数
}
#设定负载服务器侯台服务器列表
upstream site {
#ip_hash;
server localhost:6688;
server localhost:5555;
}
http {
server {
listen 80;
server_name localhost;
location / {
root html;
index index.html index.htm;
}
# 负载均衡和反向代理
location /test {
proxy_pass http://site;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
然后访问http://localhost/test?name=fn&id=123
,并刷新页面,可以看到页面返回是上述服务器的随机之一;
截图如下:
类似,可以在负载均衡服务器列表设置多个服务器,从而实现负载均衡;另外,为了更好的性能,通常希望访问某个负载均衡服务器后,以后的一段时间都访问该服务器,可以将上述nginx配置中的ip_hash on
去掉注释,这样客户端在一段时间内都会访问同一台负载服务器,(可以有效缓存),从而提高性能;
url重写
对访问的url进行重写,其实是做一次地址映射;
- 语法:
rewrite regex replacement [flag];
- 示例:
此时,访问location / { root html; # 根目录为nginx/html; index index.html index.htm index.php; } location /rewrite { rewrite (.*) /page/test.html; }
localhost/rewrite
时就会访问到localhost/html/page/test.html
;
try_files
使用try_files
可以更加简单的实现url重写功能;
- 语法
try_files file ... uri; try_files file ... =code;
- 示例
nginx目录结果如下图:location / { root html; index index.html index.htm index.php; } # try_files location /mine { try_files $uri /page/$uri; # try_files $uri /static.log.png # 访问的指定资源不存在返回default图片; # try_files $uri 404; # 访问指定资源不存在则返回404; }
此时访问http://localhost/mine/index.html
时可以自动访问到/page/mine/index.html/
文件,结果如下图:
参考文献
- http://nginx.org/en/docs/switches.html
- http://nginx.org/en/docs/http/ngx_http_core_module.html#location
- http://nginx.org/en/docs/http/ngx_http_core_module.html#variables
- https://gist.github.com/magnetikonline/10791403
- http://nginx.org/en/docs/http/ngx_http_log_module.html#access_log
- http://nginx.org/en/docs/http/ngx_http_core_module.html