Nginx简单入门
软件位置,不同安装方式可能不同,一般如下:
- docker容器:/usr/sbin/nginx
- centos:/usr/local/nginx/sbin
配置环境变量即可在任意地方使用nginx命令
常用命令
默认已经配置环境变量
启动与关闭
1
2
3
4nginx # 启动
nginx -s reload # 重新载入配置文件,热部署、热加载
nginx -s reopen # 重启 Nginx
nginx -s stop # 停止 Nginx检查配置文件nginx.conf的正确性命令
1
nginx -t
查看版本号
1
nginx -v
第三方模块安装主要命令解释
查看已经有的模块1
nginx -V # 大写V
nginx第三方模块安装方法
1
./configure --prefix=/你的安装目录 --add-module=/第三方模块目录
Nginx配置文件
nginx配置文件可以引入其它配置文件,即include操作
配置文件位置
- docker容器:/etc/nginx/nginx.conf
- centos:/usr/local/nginx/conf/nginx.conf
配置文件构成
官方初始的配置文件
1 | user nginx; |
构成如下:
全局块
文件开始到events块之前的内容,配置影响nginx整体运行的指令;
如worker_processes是nginx服务器处理并发服务的关键配置,值越大能力越强(还得看硬件配置);1
2
3
4
5
6
7worker_processes 1; # 可设置值和CPU核心数一致
# worker_processes auto; # 可设置为auto
error_log /var/log/nginx/error.log warn; # 日志存放位置
pid /var/run/nginx.pid;# 进程id,不用管events块
events 块涉及的指令主要影响Nginx 服务器与用户的网络连接1
worker_connections 1024; # worker进程支持的最大连接数
http块。
- http全局块(server块之前)
http 全局块配置的指令包括文件引入、MIME-TYPE定义、日志自定义、连接超时时间、单链接请求数上限等1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19http {
include /etc/nginx/mime.types;#include代表引入一个外部的文件 ->/minle.types中放着大量的媒体类型
default_type application/octet-stream; # 默认类型
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
keepalive_timeout 65;
server {} # server块
# include /etc/nginx/conf. d/*.conf; -〉引入了conf.d目录下的以.conf为结尾的配置文件
include /etc/nginx/conf.d/*.conf;
} - server块(主要关注此处)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25http {
# server块
server {
listen 80; #监听端口
server_name localhost;# 域名
#charset koi8-r;
#access_log /var/log/nginx/host.access.log main;
location / {# 匹配的url的规则
#root:将接收到的请求根据/usr/share/nginx/html去查找静态资源
root /usr/share/nginx/html;
#index:默认去上述的路径中找到index.html或者index. htm
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
}
- http全局块(server块之前)
反向代理
主要修改Http Server块的配置
1 | server { # server块 |
负载均衡
配置
1 | http { |
负载均衡策略:
轮询(默认);按照时间顺序分配请求,其中一台服务器挂掉时自动剔除
权重 weight;默认权重为 1,权重越高得到的请求越多
1
2
3
4
5
6
7
8upstream myServer { # 加入 upstream ,服务名 myServer
server 192.168.0.100:9001 weight = 5;# 权重为 5
server 192.168.0.100:9002 weight = 10;# 权重为 10
}
IP hash;每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器,可以解决session的问题。
1
2
3
4
5
6
7
8upstream myServer { # 加入 upstream ,服务名 myServer
ip_hash
server 192.168.0.100:9001;
server 192.168.0.100:9002 ;
}fair;按后端服务器的响应时间来分配请求,响应时间短的优先分配。
1
2
3
4
5
6
7
8upstream myServer { # 加入 upstream ,服务名 myServer
server 192.168.0.100:9001;
server 192.168.0.100:9002;
fair
}
动静分离
Nginx动静分离简单来说就是把动态请求跟静态请求分开,不能理解成只是单纯的把动态页面和静态页面物理分离。严格意义上说应该是动态请求跟静态请求分开,可以理解成使用Nginx处理静态页面,Tomcat处理动态页面。动静分离从目前实现角度来讲大致分为两种:一种是纯粹把静态文件独立成单独的域名,放在独立的服务器上,也是目前主流推崇的方案;另外一种方法就是动态跟静态文件混合在一起发布,通过Nginx来分开。
通过location 指定不同的后缀名实现不同的请求转发。通过 expires(过期)参数设置,可以使浏览器缓存过期时间,减少与服务器之前的请求和流量。具体Expires定义:是给一个资源设定一个过期时间,也就是说无需去服务端验证,直接通过浏览器自身确认是否过期即可,所以不会产生额外的流量。此种方法非常适合不经常变动的资源。(如果经常更新的文件,不建议使用expires来缓存),设置3d,表示在这3天之内访问这个URL,发送一个请求,比对服务器该文件最后更新时间没有变化,则不会从服务器抓取,返回状态码304,如果有修改,则直接从服务器重新下载,返回状态码200。
配置
假设有文件 /mypath/image/a.png
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15server { # server块
listen 80; #监听端口
server_name 192.168.100.100;# 域名
# 匹配到 /image
location /image/ {
root /mypath/; # 去此目录下找对应文件
autoindex on; # 列出当前目录下的文件及文件夹
}
}访问 192.168.100.100/image 则得到一个类似ftp的页面,列出/mypath/static/image文件夹下的文件(因为配置了 autoindex on;);
访问 192.168.100.100/image/a.png 则得到一张图片,即 /mypath + /image/a.png ;
其它动态请求进行代理配置即可。
Server块location入门
匹配类型
= 精准匹配
1
2
3location = /xxx {
#精准匹配
}例
1
2
3
4
5
6
7
8
9
10location = /app {
proxy_pass http://127.0.0.1:8082/demo;
# /app -> http://127.0.0.1:8082/demo
# /app?name=abc -> http://127.0.0.1:8082/demo?name=abc
# /app/userService -> http://127.0.0.1:8082/demo/userService
# /app/ -> 匹配不到
# /app+++ -> 匹配不到
# 精准匹配,可携带query参数
}通用匹配
1
2
3location /xxx{
#匹配所有以/xxx开头的路径
}例
1
2
3
4
5
6
7location /app {
proxy_pass http://127.0.0.1:8082/demo;
# /app?name=ls -> http://127.0.0.1:8082/demo?name=ls
# /app/ -> http://127.0.0.1:8082/demo/
# /app+++ -> http://127.0.0.1:8082/demo+++
# 即拼接操作
}正则匹配
1
2
3
4location ~ xxx {
# xxx是一个正则表达式
# ~ 符告诉nginx:xxx是一个正则表达式不是一个普通的字符串
}例
1
2
3
4
5
6
7
8
9
10
11server {
listen 80;
server_name 127.0.0.1;
location ~ (/ggg){
# 匹配包含 /ggg 字符串的url, 匹配到的值为 /ggg
# 第一个匹配到的值为$1,值即为 /ggg
# 代理到 http://127.0.0.1:8082/demo/ggg
proxy_pass http://127.0.0.1:8082/demo$1;
}
# 即 $ 后的数字表示正则匹配到的内容的索引,从1开始,且代理地址proxy_pass必须使用其中之一
}匹配开头路径
1
2
3location ^~ /images/ {
# 匹配所有以/images/开头的路径
}例
1
2
3
4
5location ^~ /static/ {
proxy_pass http://127.0.0.1:8082/demo;
# /static/aaa -> http://127.0.0.1:8082/demo/aaa
# 即拼接操作
}匹配后缀
1
2
3location ~* . (gifl jpglpng)$ {
# 匹配以gif或者jpg或者png为结尾的路径
}
正则匹配注意点:
- ~ 代表进行正则时区分大小写
- ~* 代表进行正则时不区分大小写
优先级:
(location = ) > (location /xxx/yyy/zzz) > (location ^~) > (location ~,~*) > (location /起始路径) > (location /)
Nginx更进一步
Nginx变量
Nginx的配置文件使用的就是一门微型的编程语言,变量说白了就是存放“值”的容器。而所谓“值”,在许多编程语言里,既可以是3.14这样的数值,也可以是 hello world 这样的字符串,甚至可以是像数组、哈希表这样的复杂数据结构。然而在 Nginx 配置中,变量只能存放一种类型的值,因为也只存在一种类型的值,那就是字符串。
1 | set $a "hello world"; |
所有的 Nginx 变量在 Nginx 配置文件中引用时都须带上 $ 前缀,直接把变量嵌入到字符串常量中以构造出新的字符串:
变量插值
关键在于引号
1 | # 1 |
使用花括号
1 | server { |
变量生命周期
Nginx 变量的创建和赋值操作发生在全然不同的时间阶段。Nginx 变量的创建只能发生在 Nginx 配置加载的时候,或者说 Nginx 启动的时候;而赋值操作则只会发生在请求实际处理的时候。这意味着不创建而直接使用变量会导致启动失败,同时也意味着我们无法在请求处理时动态地创建新的 Nginx 变量。我们无法在请求处理时动态地创建新的 Nginx 变量。
Nginx 变量名的可见范围虽然是整个配置,但每个请求都有所有变量的独立副本,或者说都有各变量用来存放值的容器的独立副本,彼此互不干扰。比如前面我们请求了/bar接口后,$foo变量被赋予了值32,但它丝毫不会影响后续对/foo接口的请求所对应的foo值(它仍然是空的!),因为各个请求都有自己独立的foo变量的副本。
Nginx 变量理解成某种在请求之间全局共享的东西,或者说“全局变量”。而事实上,Nginx 变量的生命期是不可能跨越请求边界的
1 | server { |
简而言之,nginx的全局变量生命周期是和请求的生命周期一致,每个子请求有自己的全局变量。
Nginx内置变量
在配置基于nginx服务器的网站时,必然会用到 nginx内置变量。内置变量存放在 ngx_http_core_module 模块中,变量的命名方式和apache 服务器变量是一致的。总而言之,这些变量代表着客户端请求头的内容,例如$http_user_agent, $http_cookie, 等等。下面是nginx支持的所有内置变量:
1 | $arg_name # 请求中的的参数名,即“?”后面的arg_name=arg_value形式的arg_name |
常见模块
geo模块
根据客户端地址创建新变量,常见写法
1 | geo $remote_addr $geo {# 跟姐客户端IP定义 $geo 变量的值 |
location中使用
1 | # 如果不在白名单,返回403 |
注意点
- 如果geo指令后不输入address,那么默认就使用变量remite_addr作为ip地址
- {} 内的指令匹配:优先最长匹配
map模块
- ngx_http_map_module ;默认编译进Nginx ;通过–without-http_map_module禁用;
- 基于已有变量,使用类似switch{case: … default: …}的语法创建新变量,为其他基于变量值实现功能的模块提供更多的可能性。
简单地说,map 的主要作用是创建自定义变量,通过使用 nginx 的内置变量,去匹配某些特定规则,如果匹配成功则设置某个值给自定义变量。 而这个自定义变量又可以作于他用。
作用域: http 块
三个参数(指令):
- default : 指定源变量匹配不到任何表达式时将使用的默认值。当没有设置 default,将会用一个空的字符串作为默认的结果。
- hostnames : 允许用前缀或者后缀掩码指定域名作为源变量值。这个参数必须写在值映射列表的最前面。
- include : 包含一个或多个含有映射值的文件。
case规则:
- 字符串严格匹配
- 使用hostnames指令,可以对域名使用前缀泛域名匹配
- 使用hostnames指令,可以对域名使用后缀泛域名匹配
- ~和~*正则表达式匹配,后者忽略大小写
default规则:
- 没有匹配到任何规则时,使用default,缺失default时,返回空字符串给新变量
map_hash_bucket_size size;指令:
指定一个映射表中的变量在哈希表中的最大值,这个值取决于处理器的缓存。
1
map_hash_bucket_size 128; # 变量过长时配置文件加载报错,此处设置为128
根据主机名称(请求的域名)给 $name赋值
1 | map http_host name { |
实用操作之一,重定向处理
1 | map $sent_http_location $location{ # 根据重定向location响应头$sent_http_location给变量$location赋值 |
headers_more模块
headers_more模块用于 添加、修改或清除 请求/响应头,该模块不是nginx自带的,需要另外安装。openresty默认包含了该模块,可以直接使用。
headers_more模块主要有4个指令,指令可使用-s选项指定HTTP状态码:
more_set_headers 用于修改响应头,具有相同名称的响应头总是覆盖 ,因为set的特性,故也可达到添加、清除响应头的作用;
配置段
1
http, server, location, location if
语法
more_set_headers [-t <content-type list>]... [-s <status-code list>]... <new-header>
1
2
3
4
5
6
7
8location /app {
more_set_headers "Foo: foo"; # 任何请求响应后都设置响应头"Foo: foo"
more_set_headers -s 302 "Foo: foo"; # 响应状态码为302,则设置响应头"Foo: foo"
# 单一指令中,选项可以多次出现
more_set_headers -s 302 -s 301 "Foo: foo"; # 响应状态码为302或301,则设置响应头"Foo: foo"
more_set_headers -s '302 301' "Foo: foo";# 响应状态码为302或301,则设置响应头"Foo: foo"
# 允许使用Nginx变量# 提前定义 set $my_var “ dog” ;more_set_headers "服务器:$my_var";
}新的响应体格式可如下:
name: vlaue
name:
name
注意:more_set_headers允许在location的if块中,但不允许在server的if块中。下面的配置就报语法错误1
2
3
4
5
6# error
server {
if ($args ~ 'download' {
more_set_headers 'Foo: Bar';
}
}
more_clear_headers 用于清除响应头:
配置段
1
http, server, location, location if
语法
more_clear_headers [-t <content-type list>]... [-s <status-code list>]... <new-header>
1
2
3
4
5
6
7location /app {
more_clear_headers -s 404 -t 'text/plain' Foo Baz;# 响应状态码为404,响应类型为text/plain时 移除响应头 "Foo: Baz"
more_set_headers -s 404 -t 'text/plain' "Foo:""Baz: "; # 同上
more_set_headers -s 404 -t 'text/plain' Foo Baz # 同上
# 也可以使用通配符*,如:
more_clear_headers 'x-Hidden-*';
}more_set_input_headers 用于修改请求头,因为set的特性,故也可达到添加、清除请求头的作用;
配置段
1
http, server, location, location if
语法
more_set_input_headers [-r][-t ]... <new-header>
类似于more_set_headers,不同之处在于它对输入标头(或请求标头)进行操作,并且仅支持该-t选项。
请注意,-t 选项根据请求内容的类型( Content-Type )过滤。more_clear_input_headers 用于清除请求头
配置段
1
http, server, location, location if
语法
more_clear_input_headers [-t <content-type list>]... <new-header>
1
2
3
4
5
6
7location /app {
more_clear_input_headers -t 'text/plain' Foo Baz;
more_set_input_headers -t 'text/plain' Foo Baz
more_clear_input_headers "Foo" "Baz";
# 也可以使用通配符*,如:
more_clear_input_headers 'X-Hidden-*';
}
sub模块
ngx_http_sub_filter_module模块,默认未编译进Nginx ,通过–with-http_sub_module启用;
sub模块用于响应内容的替换,即替换响应中的字符串;指令如下:
sub_filter
匹配文本后替换sub_filter_last_modified
是否阻止response header中写入Last-Modified,防止缓存,默认是off,即防止缓存sub_filter_once
sub_filter指令是执行一次,还是重复执行,默认是只执行一次 ;即替换一次(on),全部替换(off)sub_filter_types
指定类型的MINE TYPE才有效1
2
3
4
5
6
7
8
9
10location / {
sub_filter 'aaa' 'bbb';# 忽略大小写,将响应内容内的aaa字符串替换成bbb
sub_filter 'name' '$host';# 可使用变量
#sub_filter_once on;
sub_filter_once off;# 执行一次与否
#sub_filter_last_modified on;
sub_filter_last_modified off;# 防止缓存
sub_filter_types application/json; # 仅响应类型为 application/json 时进行替换
#sub_filter_types *; # 可使用通配符
}
指令
set指令
set 指令是用于定义一个变量,并且赋值
1 | server,location,if # 应用环境 |
例:
1 | set $a hello; |
return 指令
return 指令用于返回状态码给客户端
1 | server,location,if # 应用环境 |
例:
1 | location ~* \.sh$ { |
if指令
if指令用来判断条件表达式的结果,为true时执行的指令,条件为false时不执行相应的指令
1 | server,location# 应用环境 |
语法格式与编程语言类似if (condition) { ... }
condition可以是如下类型:
- 变量名,如果变量的值是空字符串或者0表示false
- 变量使用“=”和“!=”来跟字符串比较
- 可以是正则表达式
- 检查文件是否存在使用“-f” 和 “!-f”
- 检查目录是否存在使用 “-d” 和 “!-d”
- 检查文件、目录、符号链接是否存在使用 “-e” 和 “!-e”
- 检查是否是可执行文件使用“-x” 和 “!-x”
if指令不支持多条件、不支持嵌套、不支持else,与常见的条件表达式不同的特点是,if指令使用单个等号=而不是双等号==表达等值比较。
1 | if ($http_user_agent ~* mac) { |