nginx简介
Nginx是一款是由俄罗斯的程序设计师Igor Sysoev所开发高性能的 Web和 反向代理 服务器,也是一个 IMAP/POP3/SMTP 代理服务器。在高连接并发的情况下,Nginx是Apache服务器不错的替代品。
-
nginx的优势
- 高并发高性能
- 可扩展性好,跨平台 - 模块拓展
- 高可靠性 - 宕机概率很小
- 热部署
- 开源许可
- 等等
nginx 的最重要的几个使用场景:
- 静态资源服务,通过本地文件系统提供服务;
- 反向代理服务,延伸出包括缓存、负载均衡等;
-
api
接口服务
nginx
和node.js
的很多理念类似,HTTP
服务器、事件驱动、异步非阻塞等。nginx 擅长于底层服务器端资源的处理(静态资源处理转发、反向代理,负载均衡等),总之目前形式,在服务器上应用非常广泛
nginx架构之工作模式
-
-
nginx
启动后,有一个master
进程和多个相互独立的worker
进程
-
-
- 每个
worker
进程都有可能处理request
连接
- 每个
-
-
master
进程可以监控worker
进程的运行状态,当worker
进程异常退出,会自动启动新的worker
进程
-
-
worker
进程数,一般会设置成机器cpu核数。因为更多的worker
数,只会导致进程相互竞争CPU
,从而带来不必要的上下文切换 - 使用多进程模式,不仅能提高并发率,而且进程之间相互独立,一个
worker
进程挂了不影响其它woker
进程的工作 -
CPU
亲和,把CPU
内核和nginx
的worker
进程绑定在一起,让每个worker
进程固定在一个CPU
上执行,从而减少CPU
的切换并提高缓存命中率提高性能
nginx的安装
注意不同的linux
的操作系统安装命令不同,以下全部在centos7.x
环境运行
安装依赖
yum install -y gcc gcc-c++ autoconf pcre pcre-devel zlib zlib-devel openssl openssl-devel
添加安装源
创建nginx.repo
文件
vi /etc/yum.repos.d/nginx.repo
添加如下内容
[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/centos/7/$basearch/
gpgcheck=0
enabled=1
安装nginx
yum install -y nginx
也有其他方式比如安装包直接安装,docker
镜像安装...
-
nginx -v
查看版本号 -
nginx -V
查看安装nginx
配置的参数。查看可执行文件,配置文件,日志文件,第三方模块文件路径 -
nginx -t
检查配置是否正确 -
rpm -ql nginx
查看nginx安装文件的详细路径
启动/关闭命令
- 启动
systemctl start nginx.service
- 重新加载配置
nginx -s reload或systemctl reload nginx.service
- 停止
systemctl stop nginx.service或nginx -s stop
- 重启
systemctl restart nginx.service或nginx -s reopen
- 开启自启
systemctl enabled nginx.service
- 关闭开机自启
systemctl disabled nginx.service
nginx模块介绍
nginx
的所有功能都是以模块的形式累加形成,模块也非常多。这包括核心模块和功能模块,针对不同的应用场景,并非所有的功能模块都要被用到。模块可参考如下3个网站
官方文档
官方文档翻译版
Nginx中文参考手册,教程
nginx处理请求的流程
- 客户端请求
- 读取
http
请求的请求行,请求头,请求体 - 根据域名确认使用哪个
server
配置 -
server_rewrite
(server
内部的重写) - 匹配
location
-
rewrite
(location
内部的重写) - 访问控制(每个
ip
每秒的并发数) - 生成内容(
return
, 硬盘, 反向代理) - 响应过滤(
gzip sub_filter
) - 打印日志(错误和访问日志)
- 返回给客户端
nginx配置解读
内置变量
-
$http_host
请求的主机名称 -
$requet_uri
请求的url地址 -
$request_method
请求的http方法 -
$request
http
的请求行 -
$remote_addr
客户端地址 -
$remote_user
客户端名称 $http_referer
$http_user_agent
-
$http_x_forwarded_for
转发客户端请求头的ip地址 -
$proxy_add_x_forwarded_for
通过(proxy_set_header X_Forwarded_For: $proxy_add_x_forwarded_for
配置透传客户端合代理ip
) -
$arg_[参数名称]
http
请求参数名称 -
$http_[HEADER]
http
的请求头 如:$http_referer
$http_user_agent
-
$send_http_[HEADER]
http
的响应头 如:$send_http_cookie
核心配置示例
整体上的配置块如下所示
main {
...
http {
upstream { ... }
server {
if() {}
location { ... }
}
}
}
更详细的核心配置如下
cat /etc/nginx
查看nginx
配置如下
user root; # 用于配置worker进程的用户和用户组(如果指定的用户不存在,则报错)
worker_processes auto; # 配置 worker进程的个数,建议和CPU核数一样
error_log /var/log/nginx/error.log notice; # 配置错误日志存放路径 [日志级别]
pid /var/run/nginx.pid; # 配置master进程的进程号和进程号ID的文件路径,位于全局块
events {
worker_connections 1024; # 每个worker进程允许最大的连接数
}
http {
charset utf-8;
include /etc/nginx/mime.types; # 设定mime类型,类型由mime.types文件定义
default_type application/octet-stream; # 默认的mime类型,如果mime.types文件找不到使用默认的文件类型
# 日志格式(自定义输出内容) 和 日志的级别
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; # 访问日志路径
# 下方3个建议同时开启,静态资源服务器应用起到优化的作用
sendfile on; # 提高处理静态资源的性能,系统读取的文件数据直接发送给网络不再经过ng。如果配置反向代理不起作用
#tcp_nopush on; # 减少网络报文段的数量,可以在达到一定的数据后一起发送。仅在使用sendfile的时候使用
tcp_nodelay on; # 在keep-alive开启的情况生效,来提高网络包传输的'实时性'和tcp_nopush的作用相反
keepalive_timeout 65; # 配置 长连接超时时间
#keepalive_requests 120; # 配置 一个长连接 可以处理的请求的个数,超过这个个数就会断开该连接
#gzip on; # 是否开启gzip压缩
#gizp_comp_level 6; # 压缩级别
#gzip_min_length 1k; # 内容超过1k才参与gzip
#gzip_http_version 1.1; # 启用gzip压缩的最小http版本
#gzip_static on; # 如果是提前`gzip`过的需要启用此配置
#gzip_types text/css appliction/javascript text/html; # 压缩的文件类型
# 其它配置文件
include /etc/nginx/conf.d/*.conf;
server {
listen 80; # 服务监听端口
server_name test.222.com test1.222.com; # 服务使用的域名可以是ip/域名/localhost,可配置多个
#access_log /var/log/nginx/host.access.log main; # 单独 为该服务定义一个日志路径,而不是使用全局的
#ssl_certificate /root/nginx/ssl/test.222.com.pem; # 证书文件地址 https需要
#ssl_certificate_key /root/nginx/ssl/test.222.com.key; # 私钥文件地址 https需要
# 定义访问改服务URI的匹配规则
location / {
root /usr/share/nginx/html; # 根目录
index index.html index.htm; # 默认访问文件
}
#error_page 404 /404.html; # 404页面
error_page 500 502 503 504 /50x.html; # 状态码500 502 503 504重定向到/50x.html
# 精确匹配
location = /50x.html {
root /usr/share/nginx/html; # 根目录
}
}
}
上述配置日志格式log_format
是含有访问ip
,访问用户,时间,请求行,请求响应状态码,访问referer
,访问客户端ua
,转发的ip
执行/var/log/nginx/access.log
可以实时在控制台查看日志,如下
上述是一个最简单的静态资源服务的nginx
配置。当你访问test.222.com
或者test1.222.com
(前提是这两个域名已经备案并添加了解析)时,nginx
就会访问匹配到上述配置的server
,在server
内部会根据访问路径命中location
。上述只配置了/
前缀命中所有路径,然后根据路径会访问/usr/share/nginx/html
目录下的文件
server配置块
server
是配置服务的,可以理解成针对域名形式的路由匹配。
根据配置的server_name
匹配优先级顺序如下所示
- 精准匹配
-
*
在前 -
*
在后 - 正则匹配
default_server
即优先级如下:
test.222.com
> *.222.com
> test.222.*
>~(\w+)\.test\.222\.com$
> default.conf
文件的配置
location匹配规则
-
location
仅匹配请求路径,忽略请求参数 - 前缀字符串
- 常规(前缀)
-
=
精准 -
^~
忽略正则的前缀匹配
- 正则匹配
-
~
大小写敏感的正则匹配 -
~*
大小写不敏感的正则匹配
-
匹配的优先级顺序如图
-
=
优先级最高;一旦成功不在查找其它项 -
^~
一旦匹配成功;不在查找其它项 - 正则表达式的优先级次之,如果多个
location
的正则匹配,则使用正则表达式最长的那个 - 常规字符串匹配类型按前缀匹配
location ~ /Test/$ {
return 200 "匹配到的第一个正则";
}
location ~* /Test/(\w+)$ {
return 200 "匹配到的最长的正则";
}
location ^~ /Test/ {
return 200 "忽略后续的正则";
}
location /Test/a {
return 200 "最长的前缀匹配";
}
location /Test {
return 200 "前缀匹配";
}
location = /Test {
return 200 "精确匹配"
}
访问下边4个地址分别得到的请求结果
/Test
-> 精确匹配
/Test/
-> 忽略后续的正则
/Test/a
-> 匹配到的最长的正则
/test/a
-> 匹配到的最长的正则
rewrite使用
可以实现url
的重写和重定向
rewrite 正则 replacement [flag]
作用域server/http
- 请求的地址如果匹配到了正则,会被后边的
replacement
替换,然后通过[flag]标识符决定后一步的处理行为
示例
rewrite ^(.*)$ https://$host$1 permanent; # 可以让http重定向到https
使用场景
-
URL
页面跳转http -> https,/a-> /b
- 兼容旧版本
-
SEO
优化(伪静态)/:id.html => /:id
- 维护提示
[flag]标识符列举
-
last
返回200 地址栏不发生变化 -
break
返回200 地址栏不发生变化 -
redirect
临时重定向; 返回302,地址栏发生变化 -
permanent
永久重定向; 返回301,地址栏发生变化
last
和break
的区别
- 当
rewrite
规则在location{}
外,break
和last
作用一样,遇到break
或last
后,其后续的rewrite/return
语句不再执行。但后续有location{}
的话,还会近一步执行location{}
里面的语句,当然前提是请求必须要匹配该location
- 当
rewrite
规则在location{}
里,遇到break
后,本location{}
与其他location{}
的所有rewrite/return
规则都不再执行。 - 当
rewrite
规则在location{}
里,遇到last
后,本location{}
里后续rewrite/return
规则不执行,但重写后的url再次从头开始执行所有规则,哪个匹配执行哪个。
前端应用场景
监控nginx
状态
stub_status on/off;
作用域范围server/location
配置示例:
location /status {
stub_status on;
}
访问该路径会看到nginx
当前的处理状态
-
Active connections
当前所有处于打开状态的连接数 -
accepts
总处理的连接数 -
handled
总成功创建握手数 -
requests
总处理的请求数 -
Reading
正在读取客户端的连接数 -
Writing
正在响应数据到客户端的数量 -
Waiting
正在等待下一次请求的驻留连接数
请求限制
需要先安装yum install -y httpd-tools
模拟请求ab -n 40 -c 20 http://127.0.0.1
-
-n
总共请求的次数 -
-c
并发的请求数,每秒请求的数量
请求连接的限制
limit_conn_zone $binary_remote_addr zone=conn_zone:10m;
作用域范围http
;定义共享区域大小
limit_conn conn_zone 1; # 指定限制域,请求连接每秒限制1个
limit_conn_status 500; # 限制拦截的状态返回500
limit_conn_log_level warn; # 失败的日志级别
limit_rate 50; # 每秒服务器只能给客户端50字节的数据
作用域范围http/server/location
请求数限制
limit_req_zone $binary_remote_addr zone=req_zone:10m rate=1r/s;
作用域范围http
;定义共享域大小,每秒一个ip
只能请求1次
limit_req zone=req_zone burst=3;
-
burst
可以暂存的最大请求数;比如某一个客户端同时发送5个请求,那么这一秒处理1个,暂存3个,失败一个。暂存3个会在将来有序被处理
访问控制
- 基于
IP
的访问控制-http_access_module
- 基于用户登录信息的访问控制
-http_auth_basic_module
location = /admin.html {
deny ip;
allow all;
}
作用域范围http/server/location
设置缓存
注意缓存仅仅设置静态资源,不要设置动态资源
expires 1h; # 设置缓存时间
add_header Cache-Control no-cache / no-store / public / private; # 设置缓存策略 no-store不缓存,no-cache协商缓存 , public可以被任何对象缓存,private只能针对个人用户不能被代理服务器缓存
支持跨域
当服务端不支持跨域并且服务端也是经过nginx
代理,可以在nginx
配置cros
跨域的支持,如下
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods GET,POST,PUT,DELETE,OPTIONS;
add_header Access-Control-Allow-Headers token,xxx;
add_header Access-Control-Allow-Credentials 'true';
add_header Access-Control-Max-Age 6h;
if ($request_method = 'OPTIONS') {
return 204;
}
可以配置http/server/location
块内
防盗链
如果你的静态资源不希望被别的的站点访问,可以设置防盗链,仅仅只支持自己的站点访问,可以配置如下
location ~* \.(gif|jpg|png)$ {
valid_referers none blocked 域名/ip; # 没有refer 具体域名/ip可以访问
if ($invalid_referer) { # 上述配置后会得到一个内置变量$invalid_referer,该变量false直接返回403
return 403; # 无效的referer返回403状态
}
}
curl -e "ip" url
模拟加referer
访问具体url
正向代理
对于访问目标来说,代理的是客户端。对于公司局域网内往往会有一个代理来访问外网以进行局域网内网络访问控制,还有vpn
,Charles
等都是正向代理的应用。nginx
配置正向代理如下:
resolver 114.114.114.114; # DNS解析
location {
proxy_pass http://$http_host$http_rui #
}
反向代理
反向代理,其实对客户端无感知的;因为客户端不需要任何配置就可以访问,只需要将请求发送到反向代理服务器,由反向代理服务器去选择目标服务器获取数据后,在返回给客户端。暴露的是代理服务器地址,隐藏了真实服务器IP
地址。
- 保护了真实的
web
服务器,web
服务器对外不可见 - 节约了有限的
IP
地址资源- 在所有的服务器之间使用私有地址(局域网内的地址)访问,不分配真正的外网的
ip
- 在所有的服务器之间使用私有地址(局域网内的地址)访问,不分配真正的外网的
- 减少
web
服务器压力,提高响应速度- 可以适当在代理服务缓存结果
- 跨域
- 请求的统一控制(权限、过滤规则)
- 等等
location / {
proxy_pass http://127.0.0.1:3000; # 真实的服务
index index.html index.htm;
proxy_pass http://xxxxx.com;
proxy_set_header Host $http_host; # 向后传递host请求头
proxy_set_header X-Real_IP $remote_addr; # 向后传递前一个客户端请求的ip地址
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 层层传递客户端和代理服务器ip
proxy_connect_timeout 90; # 连接超时时间
proxy_send_timeout 90; # 连接成功后等候服务器响应时间
proxy_read_timeout 90; # 服务器数据回传时间就是在规定时间之内服务器必须传完所有的数据
proxy_buffer_size 4k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;
...
}
注意事项
-
proxy_pass
后的url
最后加上/
就是绝对路径,localtion
中匹配的路径部分不走代理,也就是会被替换掉。
location /api/ {
proxy_pass http:/test.222.com/;
}
访问 http://xxxx/api/user
-> http:/test.222.com/user
-
proxy_pass
后的url
最后如果没有/
就是相对路径,location
中匹配的路径会走代理也就是会保留location
匹配的路径
location /api {
proxy_pass http:/test.222.com;
}
访问 http://xxxx/api/user
-> http:/test.222.com/api/user
负载均衡
- 服务器的处理能力,存储空间不足,而扩容永远也满足不了实际的问题
- 集群可以解决高并发,流量过高导致服务器压力大的问题
upstream upName {
server xxx1.com;
server xxx2.com;
server xxx3.com;
}
location / {
proxy_pass http://upName;
}
分配策略
- 轮巡
- 权重轮巡
upstream upName {
server xxx1.com weight=1;
server xxx2.com weight=2;
server xxx3.com weight=3;
}
-
ip_hash
相同的ip
始终命中固定服务器
upstream upName {
ip_hash;
server xxx1.com;
server xxx2.com;
server xxx3.com;
}
-
least_conn
哪个服务的连接数最小命中哪一个 -
url_hash
固定的url
不变命中的服务器也会固定。需要安装第三方模块才可以使用
upstream upName {
url_hash;
...
}
-
fair
按后端的响应时间划分,越快的服务被分配。需要安装第三方模块才可以使用
根据服务器的运行状态
upstream upName1 {
server xxx.com down/backup/max_conns/max_fair=3 max_fair_timeout=10s/
}
-
down
服务器挂了,不参与分配 -
backup
备份服务,其它服务挂了才会使用该服务 -
max_fair=3 max_fair_timeout=10s
服务响应失败3次休眠10s,过了这个时间段恢复正常 -
max_conns
服务链接最大数
结语
以上介绍了nginx
的知识点以及在前端的应用场景。运用到实际项目的生产环境还需针对实际问题做不同的nginx
配置。ps:虽然在稍微大一点的公司nginx
操作不属于前端职责,但我们也需要储存nginx
知识,以备不时之需~