一、 Nginx 基础
Nginx优势
1.支持高并发请求,官方测试Nginx能够支撑5万并发连接,实际生产环境中可以支撑2~4万并发连接数。主要是Nginx使用了最新的epoll(Linux2.6内核)和kqueue(freeBSD)网路I/O模型,而Apache使用的是传统的Select模型,Apache比较稳定的Prefork模式为多进程模式,需要经常派生子进程,所以消耗的CPU等服务器资源要比Nginx高很多。
2.内存消耗少,Nginx处理请求是异步非阻塞的,一般情况下,10 000个非活跃的HTTP Keep-Alive连接在Nginx中仅消耗2.5MB的内存,这是Nginx支持高并发连接的基础。
3.Nginx的设计具备极高的扩展性,而且可以跨平台使用。它完全是由多个不同功能、不同层次、不同类型且耦合度极低的模块组成。比如对某一个模块修复Bug或进行升级时,可以专注模块自身而不考虑其他
4.高可靠性,用于反向代理,宕机概率微乎其微。官方提供的常用模块都非常稳定,每个worker进程相对独立,master进程在1个worker进程出错时可以快速“拉起”新的worker子进程提供服务。
5.支持热部署,可以在7×24小时不间断服务的前提下,升级Nginx的可执行文件。即使,运行数个月也不需要重新启动。
6.最自由的BSD许可协议,BSD许可协议不只是允许用户免费使用Nginx,它还允许用户在自己的项目中直接使用或修改Nginx源码,然后发布。
7.工作在网络的7层之上,可以针对http应用做一些分流的策略,比如针对域名、目录结构,它的正则规则比HAProxy更为强大和灵活
8.Nginx安装和配置比较简单,测试起来比较方便,它基本能把错误用日志打印出来。
9.Nginx社区非常活跃,高性能的第三方模块也很多。
10.Nginx可作为Web反向加速缓存、静态网页和图片服务器
Nginx缺陷
1.Nginx仅能支持http、https和Email协议
2.对后端服务器的健康检查,只支持通过端口来检测,不支持通过url来检测
3.Nginx非常适合处理静态页面和反向代理,但对于动态请求性能比较差,如果有需要可以使用Apache代替.
4.不支持带参数的动态链接&二级目录的链接,诸如:二级目录http://www.sudone.com/download/,带参数的动态链接http://www.sudone.com/cart?page=5,这些情况都需要写rewrite才能正确保存。
5.Nginx缓存内部没有缓存过期和清理的任何机制,这些缓存的文件会永久性地保存在机器上,如果要缓存的东西非常多,那就会撑暴整个硬盘空间。为此可以使用一个shell脚本定期清理.
6.只能缓存200状态码,因此后端返回301/302/404等状态码都不会缓存,假如恰好有一个访问量很大的伪静态链接被删除,那就会不停穿透导致后端承载不小压力。
7.Nginx不会自动选择内存或硬盘作为存储介质,一切由配置决定.
安装Nginx软件
方法一:线上安装(效率快,标准安装)
apt-get install -y build-essential libssl-dev libtool libpcre3 libpcre3-dev make openssl zlib1g-dev
apt-get install nginx -y
线上安装的标准路径 : /usr/sbin/
/etc/init.d 所有都是启动脚本文件(系统启动时会自动执行)
/etc/init.d/nginx shell编写的启动脚本
方法二:线下安装包(定制标准高):本地安装包编译安装,安装时注意看 INSTALL&README 文件
解压pcre(pcre是nginx安装时的依赖) : tar -zxvf pcre-8.39.tar.gz
安装pcre : ./configure && make && make install
./configure : 编译前的预先配置(检查系统的环境) make : 编译c源码文件 make install : 安装,将编译后的文件拷贝/软链接到安装的起始路径
解压nginx : tar -zxvf nginx-1.10.2.tar.gz
安装nginx : cd nginx-1.10.2/
sudo ./configure --prefix=/data/server/nginx --without-http_gzip_module --prefix : 安装的起始路径(绝对路径)
sudo make
sudo make install
检查效果 :netstat -tnulp | grep nginx 浏览器查看
nginx简单操作
/usr/sbin/nginx -t 检查
/usr/sbin/nginx 开启
/usr/sbin/nginx -s stop 关闭
/usr/sbin/nginx -s reload 重启
nginx三种启动方式
systemctl start|stop|reload| nginx # 真正还是调用 /usr/sbin/nginx 的二进制可执行文件(推荐)
/etc/init.d/nginx start|stop|reload| # 启动脚本
/usr/sbin/nginx # 启动二进制的可执行文件
注 : 前两种启动方式依赖于标准化安装方式(线上安装)
nginx移除
查看和nginx相关软件(通过apt-get安装的软件) : dpkg --get-selections|grep nginx
移除nginx,包括相关文件
apt-get --purge remove nginx
apt-get --purge remove nginx-common
apt-get --purge remove nginx-core
# 自动移除全部相关文件
sudo apt-get --purge autoremove nginx
Nginx配置简介
nginx软件目录:
工作目录: /etc/nginx
执行文件: /usr/sbin/nginx
日志目录: /var/log/nginx
启动文件: /etc/init.d/nginx
web目录: /var/www/html/,首页文件是 index.nginx-debian.html
/usr/share/nginx/html/ 首页文件是 index.html
nginx配置文件:
默认文件(默认的nginx全局配置文件):
/etc/nginx/nginx.conf
其他目录:
/etc/nginx/sites-available
/etc/nginx/sites-enabled
/etc/nginx/conf.d
文件结构:
全局配置段
http配置段
server配置段 项目或者应用
location配置段 url配置
/etc/nginx/sites-enabled/default
server {
listen 80 default_server; # 监听ipv4的全地址访问端口
listen [::]:80 default_server; # 监听IPV6的全地址访问端口
root /var/www/html # 指明静态文件所在的文件夹
index index.html index.htm index.nginx-debian.html # 静态文件查找先后顺序
# 路由映射
localtion / { # 此处的/可以匹配所有url
try_files $uri $uri/ =404; # 根据root指明的静态文件所在处,制定映射规则
}
}
/etc/nginx/nginx.conf
全局配置段 :
user 设置使用用户(worker)
worker_processes 进行增大并发连接数的处理 跟cpu保持一致 八核设置八个
error_log nginx的错误日志
pid nginx服务启动时候pid
events 定义事件相关的属性
worker_connections 一个进程允许处理的最大连接数
use 定义使用的内核模型
http 主要配置server通用的一些配置
http配置段详解
include mime.types; # 文件扩展名与文件类型映射表
default_type application/octet-stream; # 默认文件类型
sendfile on; # 开启高效文件传输模式。
autoindex on; # 开启目录列表访问,合适下载服务器,默认关闭。
tcp_nopush on; # 防止网络阻塞
tcp_nodelay on; # 防止网络阻塞
keepalive_timeout 120; # 长连接超时时间,单位是秒
gzip on; # 开启gzip压缩输出
access_log /var/log/nginx/access.log; # 成功连接的日志文件
error_log /var/log/nginx/error.log; # 失败连接的日志文件
include /etc/nginx/conf.d/*.conf; # 额外包含的配置文件
include /etc/nginx/sites-enabled/*; # 额外包含的配置文件
read() : 将数据读取到内核层,再将数据复制到用户层,最后给到应用层
http配置段中的sendfile on; 直接跳过读取数据时需要经过的三层,将内核层的数据直接通过socket.send()进行发送
http配置段中的tcp nopush on; 需要发送的数据量比较少时会暂停发送,积攒一定数量的数据包后再发送
http配置段中的tcp_nodelay on; 不延迟发送,与上一个互斥,默认以后一个为准(tcp_nodelay on)
http配置项中包含的额外配置文件有多少个server,就有多少个虚拟访问站点(浏览器输入的端口号)
Server常见配置属性 : 有多少个server,就有多少个虚拟访问站点(浏览器输入的端口号),实质底层是:创建一个server就创建一个监听套接字socket.socket()
常见样式
server {
listen 端口; # 监听的端口号,主要用作于匹配
server_name 主机名; # 当前虚拟站点的名字(域名/IP),主要用作于匹配,若给定值为 _ 表示非法域名
root /var/data/test; # 定义匹配到当前server请求url的html文件所在根目录(目录前缀)
index index.html index.htm; # 定义响应请求时返回的文件名或格式,指定索引文件名
return 404; # 定义响应请求时返回的状态码
return 302 http://www.baidu.com; # 临时重定向
# 根据Server匹配到的请求路径和关键字去响应和处理
localtion = / {
# 精准匹配
root /home/python/Desktop/test/test_html;
}
localtion ^~ /hello.html {
# 优先匹配
root /home/python/Desktop/test/hello_html
}
localtion ~ ^.*\.html$ { # 匹配以小写html结尾的路由
# 普通正则匹配,大小写敏感
root /home/python/Desktop/test/lower_match_html
}
localtion ~* ^.*\.Html$ { # 匹配以大写或小写html结尾的路由
# 普通正则匹配,大小写不敏感
root /home/python/Desktop/test/match_html
}
localtion /love/ {
# 通用匹配
root /home/python/Desktop/test/all_html
}
localtion / {
# 所有路由均可被正确匹配
root /home/python/Desktop/test/all_html
}
}
匹配优先级 : 精准匹配 > 优先匹配 > 正则匹配 > 通用匹配
注 : localtion在匹配路由时,仅仅是判断访问的路由是否符合条件,若匹配成功并不会去掉已匹配成功的路由前缀
localtion匹配路由时,如果匹配规则已经全部匹配完成并成功,但已成功匹配的url路径后面还有uri,也可匹配成功
root 会将匹配成功后的uri直接拼接到完整url之上,即:若成功匹配 hello.html,则完整url为 : http://127.0.0.1:2220/static/hello.html
url : 统一资源定位符,拥有完整的http协议,ip地址,端口,路径上的查询字符串参数,例如 http://127.0.0.1:10088/static/hello.html?name=xxx
uri : 剔除掉 http协议 & ip & port & 查询参数,例如 /static/hello.html
localtion的功能属性 :
基本属性
location / {
root /var/www/html; # 指定响应请求的文件所在路径
index index.php index.html index.htm; # 指定响应请求的默认文件名称
expires 7d; # 指定响应请求的文件过期时间,一般用于静态文件
try_files $uri $uri/ =404; # 如果root指定的路径下有查找的文件,就返回,否则报错
}
临时跳转
location = /test/ {
return 302 http://sswang.com/; # 访问旧url的时候,临时跳转到新url,两个url均不失效
}
访问控制
location /nginx-status {
stub_status on; # 开启nginx的状态页面,默认关闭
allow 192.168.8.14; # 允许的访问地址
deny all; # 默认进制所有访问
} # 注意 : 该功能依赖于ngx_http_stub_status_module 模块(默认没有安装,需要定制化安装)
目录列表
location /upload {
alias /var/www/upload; # 指定查看文件列表路径(绝对路径)
autoindex on; # 开启目录自动索引
autoindex_exact_size off; # 默认on,显示文件确切大小(bytes)。off表示显示文件的大概大小(kB/MB/...)
autoindex_localtime on; # 默认off,显示的文件时间为GMT时间。on表示显示文件的服务器时间
} # 注意 : 该alias指定的目录下,不允许出现index属性指定的索引文件(index.html)。
alias & root 区别 :
root 表示 location 匹配内容的相对路径,会直接将匹配成功的uri拼接在,它其后指定的相对路径后面
alias 表示 一个绝对路径,而且必须以"/"结尾,会将匹配成功的uri剔除,再拼接剩余uri在其后指定的绝对路径后面
一般情况下,在 location / 中配置root, 在 location /other 中配置alias
URL尾部的 / 注意事项
1 location的四种匹配规则中有无"/"不受影响。/user/等同/user。
2 对于访问网站域名(http://sswang.com/),尾部有无"/"不受影响。因为浏览器会自动补全"/"。
3 对于访问网站域名后面的路径(http://sswang.com/other/)。尾部的"/"很重要。
URL尾部带有"/"表示目录; 没有"/"表示文件,而且文件找不到的话,会发生重定向,自动补全 /
/other/:表示服务器会自动去该目录下找对应的默认索引文件(index.html)。
/other:表示服务器会先去找other文件,找不到的话会将other当成目录,重定向到/other/,去该目录下找默认索引文件(index.html)。
4. alias会将匹配成功的uri剔除后再拼接在其指定的静态目录后面,alias指定的静态目录最后必须加上 / ; root会将匹配成功的uri一起拼接其指定的静态目录后面
例如两者同时匹配 /static/ 都能够匹配成功的话,root : /home/python/Desktop/test/static/22.html , alias : /home/python/Desktop/test/22.html
try_files : 响应时按顺序查找try_files后指定的响应内容,找到则返回file内容,否则的话进行内部重定向(uri)或返回状态码(code)。
常见用法 :
try_files $uri $uri/ =404; 如果能找到指定的uri那么就返回相应的内容,找不到再自动加上斜杠当作目录仅需查找,若还是找不到返回错误状态码404
try_files /1.html /2.html /6.html; 如果能找到指定的文件1/2.html那么就返回相应的内容,否则的话返回6.html文件内容
try_files $uri @backup; 如果能找到指定的uri那么就返回相应的内容,否则的话就内部重定向到后端名称为@backup的location,详例见下
server {
listen 10020;
localtion /1.html {
root /home/python/Desktop/test;
try_files $uri $uri/ @backend; # 如果前两种未找到,内部重定向到@backend
}
localtion @backend {
return 302 http://www.baidu.com; # 重定向到百度
}
}
二 Nginx 进阶
正向代理 & 反向代理
区别
从用途上来讲:
正向代理-为局域网客户端向外访问Internet服务。可以使用缓冲特性减少网络使用率。
反向代理-为局域网服务器向外提供Internet服务。可以使用负载平衡提高客户访问量。还可以基于高级URL策略和管理技术对服务进行高质量管控。
从安全性来讲:
正向代理-必须采取安全措施确保内网客户端通过它访问外部网站。隐藏客户端的身份
反向代理-对外提供服务是透明的,客户端并不知道自己访问的是一个代理。隐藏服务端的身份
简化来说 :
反向代理,代表的是服务端(饭馆,厨师提供服务[做菜]通过服务员传递给客户端)
正向代理,代表的是客户端(VPN服务器,国内浏览器通过VPN服务器访问国外服务器)
nginx 代理模块属性 : proxy_pass & proxy_set_header
官方资料:http://www.nginx.cn/doc/standard/httpproxy.html
proxy_pass 用于设置被代理服务器的地址和被映射的URI,地址可以使用主机名或IP加端口号的形式
官方代码示例
location / {
proxy_pass http://localhost:8000; # 设定请求跳转后的地址,可以使用hostname或IP:Port形式
proxy_set_header X-Real-IP $remote_addr; # 在请求头中设置当前访问后端服务器的浏览器原始请求的真实IP地址
}
proxy_pass 属性后面的路径最后是否加上斜杠的区别 :
a. proxy_pass属性后面的路径不加斜杠,将所有uri拼接到proxy_pass所指定的路径后面
b. proxy_pass属性后面的路径加上斜杠,剔除掉已匹配成功的uri,将之后的uri拼接到proxy_pass所指定的路径后面
nginx代理实践
四层代理(传输层) : 根据 ip+port 分发代理
七层代理(应用层) : 根据 ip+port+协议具体信息 分发代理
负载均衡
概念
当请求超级多时,通过nginx多种负载均衡算法,将大数量的请求分发到不同的后端服务器上,减轻其中某个/某些服务器压力,将请求让多台服务器一起分担
nginx负载均衡主要分为 : 四层负载 & 七层负载
四层负载均衡,主要通过报文中的目标地址和端口,再加上负载均衡设备设置的服务器选择方式,决定最终选择的内部服务器。
七层负载均衡,也称“内容交换”,主要通过报文中真正有意义的应用层内容,再加上负载均衡设备设置的服务器选择方式,决定最终选择的内部服务器。
七层负载均衡可以对客户端的请求和服务器的响应进行任意意义上的修改(例如客户请求中的Header重写,服务器响应中的关键字过滤或者内容插入等功能。)
负载均衡模块属性 : upstream
官方资料:http://www.nginx.cn/doc/standard/httpupstream.html
定义一个后端服务地址的集合列表,每个后端服务使用一个server命令表示;upstream {} 和 Server {} 两部分内容属于平级关系。
官方代码示例
upstream backend {
server backend1.example.com weight=5;
server backend2.example.com:8080;
server unix:/tmp/backend3;
}
server {
location / {
proxy_pass http://backend;
}
}
upstream模块的常用状态
down: 表示当前server主机暂时不参与负载均衡。
backup:后备主机,当所有非backup机器出现故障或者繁忙的时候,才会请求backup机器。
max_fails:允许请求的最大失败数,默认为1,配合fail_timeout一起使用
fail_timeout:经历max_fails次失败后,暂停服务的时间,默认为10s。
down
backup
max_fails & fail_timeout
负载均衡调度算法
内置策略:nginx自带的算法
雨露均沾型:轮训、加权轮训、哈希
定向服务型:ip_hash、least_conn、cookie、route、lean、需配合缓存使用才有效果
商业类型:ntlm、least_time、queue、stick
扩展策略:各种结合业务场景自定义的算法或者第三方算法
自定义算法
第三方算法:fair、url_hash
常用算法
轮询(默认):请求按顺序逐一分配到不同的后端服务器。
weight:指定轮询权重,值越大,分配到的几率就越高,适用于后端服务器性能不均衡情况。
ip_hash:按访问IP的哈希结果分配请求,分配后访客访问固定后端服务器,有效的解决动态网页会话共享问题。
fair:基于后端服务器的响应时间来分配请求,响应时间短的优先分配。
url_hash:按访问URL的哈希结果分配请求,使同URL定向到同一台后端服务器,可提高后端缓存服务器的效率。
weight
ip_hash
url_hash
日志解析
Nginx默认提供了两个日志文件 access.log和error.log,通过access.log可以得到用户请求的相关信息;通过error.log可以获取某个web服务故障或其性能瓶颈等信息。
官方介绍:http://nginx.org/en/docs/http/ngx_http_log_module.html
/etc/nginx/nginx.conf
40 access_log /var/log/nginx/access.log;
41 error_log /var/log/nginx/error.log;
nginx日志属性设置的完整格式是:
access_log[属性名称] /var/log/nginx/access.log[存储位置] 日志格式[位置为空表示使用默认的combined 日志格式。通过log_format设置的]
默认日志格式 : nginx配置文件是按照 分号; 来确定一行指令,以下是一行指令。 日志格式需要定义在 http 配置项中 或者 /etc/nginx/conf.d 的server配置项正上方
log_format combined '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent"';
默认日志格式的样式 :
# tail /var/log/nginx/access.log
192.168.8.14 - - [12/Nov/2018:08:24:18 -0800] "GET /favicon.ico HTTP/1.0" 404 580 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko)Chrome/55.0.2883.87 Safari/537.36"
log_format : 文件格式 combined : 文件名 远程访问主机地址 : $remote_addr 访问时间 : $time_local 客户端的身份 : $http_user_agent
nginx常用内置变量 : nginx常用的内置变量主要是用来分析日志中的http记录的,我们可以根据内置的变量精确的获取相关的信息
默认变量
$remote_addr 前一台主机的ip地址,不一定是真实的客户端IP
$remote_user 用于记录远程客户端的用户名称(一般为“-”)
$time_local 用于记录访问时间和时区
$request 用于记录请求的url以及请求方法
$status 响应状态码,例如:200成功、404页面找不到等。
$body_bytes_sent 给客户端发送的文件主体内容字节数
$http_referer 可以记录用户是从哪个链接访问过来的
$http_user_agent 用户所使用的代理(一般为浏览器)
其他常用变量
$request_uri 包含请求参数的原始URI,不包含主机名
$uri 不带请求参数的当前URI,不包含主机名
$http_x_forwarded_for 可以记录客户端IP,通过代理服务器来记录客户端的ip地址
$http_x_real_ip 可以记录客户端IP,通过代理服务器来记录客户端的ip地址
$args 这个变量等于请求行中的参数,同$query_string
$host 请求主机头字段,否则为服务器名称。
$scheme HTTP方法(如http,https)
$document_uri 与$uri相同
$document_root 当前请求文件配置文件中html的根目录即root值
$request_filename 当前请求的文件路径,由root或alias指令与URI请求生成
开启 --with-http_realip_module 功能,用于获取代理前面客户端的真实IP
设定日志格式的方法: log_format 格式名称 "日志表现样式" ; 使用日志格式的方法: access_log 日志路径 格式名称;
输出的日志信息 & 日志记录流程
注意:如果生产中出现了多级代理,
在第一层代理上添加 proxy_set_header X-Real-IP $remote_addr;属性
在所有代理上必须添加 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;属性
真实主机上使用 real_ip_header X-Forwarded-For;属性