爬梯:Nginx全解析
学习整理自:B站尚硅谷
系统平台:centos 7
Nginx
1、基本概念
百科:
Nginx (engine x) 是一个高性能的HTTP和反向代理web服务器,同时也提供了IMAP/POP3/SMTP服务。Nginx是由伊戈尔·赛索耶夫为俄罗斯访问量第二的Rambler.ru站点(俄文:Рамблер)开发的,第一个公开版本0.1.0发布于2004年10月4日。
Nginx是一款轻量级的Web服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,在BSD-like 协议下发行。其特点是占有内存少,并发能力强。
正向代理
客户端通过配置代理服务器的信息,访问国外的网站。
对于客户端来说他访问的是代理服务器,而代理服务器再访问国外的网站
反向代理
客户端不需要配置代理服务器直接访问访问代理服务器,而代理服务器将请求引导至真实的应用服务器。
反向的意思是,代理服务器代理了应用服务器,而非常理中的客户端。
图解:
负载均衡
将大量的请求分发到各台服务器上,将访问负担均衡开来
图解:
动静分离
为了加快网站的解析速度,把动态页面和静态页面由不同的服务器来解析,加快客户端的解析速度
图解:
2、安装、常用命令及配置文件
安装
Nginx需要PCRE运行环境
- 安装PCRE
PCRE官方下载地址:https://sourceforge.net/projects/pcre/files/pcre/8.44/pcre-8.44.tar.gz/download
[aaa@qq.com opt]# wget http://downloads.sourceforge.net/project/pcre/pcre/8.44/pcre-8.44.tar.gz
# ...
[aaa@qq.com opt]# tar zxvf pcre-8.44.tar.gz
# ...
[aaa@qq.com pcre-8.44]# ./configure
# ...
[aaa@qq.com pcre-8.44]# make && make install
# ...
[aaa@qq.com opt]# pcre-config --version
8.44
如果configure失败的话可以尝试以下命令:
yum install gcc gcc-c++ autoconf automake
- 安装Nginx
我从win下载了压缩包拖进去的
[aaa@qq.com opt]# tar zxvf nginx-1.18.0.tar.gz
# ...
[aaa@qq.com nginx-1.18.0]# ./configure
# ...
[aaa@qq.com nginx-1.18.0]# make && make install
# ...
[aaa@qq.com nginx-1.18.0]# /usr/local/nginx/sbin/nginx -v
nginx version: nginx/1.18.0
如果configure失败的话可以尝试以下命令:
yum install -y zlib-devel
安装完成~
启动并访问:
[aaa@qq.com nginx-1.18.0]# /usr/local/nginx/sbin/nginx
[aaa@qq.com nginx-1.18.0]# ps -ef|grep nginx
root 38148 1 0 05:07 ? 00:00:00 nginx: master process /usr/local/nginx/sbin/nginx
nobody 38149 38148 0 05:07 ? 00:00:00 nginx: worker process
root 38162 3793 0 05:09 pts/0 00:00:00 grep --color=auto nginx
[aaa@qq.com nginx-1.18.0]#
nginx默认监听80端口
常用命令
# 查看版本
[aaa@qq.com ~]# /usr/local/nginx/sbin/nginx -v
nginx version: nginx/1.18.0
# 启动
[aaa@qq.com ~]# /usr/local/nginx/sbin/nginx
# 关闭
[aaa@qq.com ~]# /usr/local/nginx/sbin/nginx -s stop
# 重新加载,平滑重启
[aaa@qq.com ~]# /usr/local/nginx/sbin/nginx -s reload
# 测试配置文件是否正确
[aaa@qq.com ~]# /usr/local/nginx/sbin/nginx -t [config name]
配置文件
/usr/local/nginx/cinf/nginx.conf
全局块
从配置文件开始到events块之间的内容,主要是设置nginx服务器整体运行,主要包括:
- 配置运行Nginx服务器的用户(组)
- 允许生成的worker process数
- 进程PID存放路径
- 日志存放路径、类型以及配置文件的引入等
Nginx.cof
#user nobody; # 配置运行Nginx服务器的用户(组)
worker_processes 1; # 进程数,并发量
#error_log logs/error.log; # 日志存放路径
#error_log logs/error.log notice; # 日志类型
#error_log logs/error.log info; # 日志类型
#pid logs/nginx.pid; # 进程PID存放路径
events{ }
主要配置Nginx服务器与用户的网络连接,常用设置包括:
- 是否开启对多work process下的网络连接进行序列化
- 是否允许同事接收多个网络连接
- 选取事件驱动模型来处理连接请求
- 每个word process可以同时支持的最大连接数等
这部分配置对Nginx的性能影响较大,在实际中应灵活配置
Nginx.cof
events {
# 表示每个work process支持的最大连接数为 1024个
worker_connections 1024;
}
http{ }
可以配置Nginx的代理、缓存和日志定义等大多数功能和第三方模块
包括两部分:http全局快、server块
- http 全局块
http全局快配置的指令包括文件引入、MIME-TYPE定义、日志自定义、链接超时时间、单链接请求数上限等
nginx.conf
http{
include mime.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 logs/access.log main;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
#gzip on;
}
- server 块
这块和虚拟主机有密切关系,虚拟主机从用户角度看,和一*立的硬件主机完全相同,该技术的产生是为了节省互联网服务器硬件成本。
每个http块可以包含多个server块,而每个server块就相当于一个虚拟主机。
而每个server块也分为全局server块,及同时包含多个location块
- 全局server块
最常见的配置是本虚拟机的监听配置和本虚拟机的名称或IP配置
- location块
一个server块可以配置多个location块。
这块的主要作用是基于Nginx服务器接收到的请求字符串(例如 server_name/uri-string),对虚拟主机名称(IP别名)之外的字符串(如:/uri-string)进行匹配,对特定的请求进行处理。地址定向、数据缓存或应答控制等功能,还有许多第三方模块的配置也在这里配置。
location [ = | ~ | ~* | ^~ ] uri {
}
- = :全值严格匹配,如果匹配成功则停止继续向下搜索并立即处理该请求;
- ~ : 用于匹配uri中正则表达式,区分大小写;
- ~* :用于匹配uri中正则表达式,不区分大小写;
- ^~ :用匹配uri中不包含的正则表达式,nginx服务器找到匹配度最高的location后,才会使用对应的规则来处理此请求。(也就是可能要全部location都匹配一遍才处理的意思)
nginx.conf
http{
server {
listen 80; #监听端口
server_name localhost;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
root html;
index index.html index.htm;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}
# another virtual host using mix of IP-, name-, and port-based configuration
#
#server {
# listen 8000;
# listen somename:8080;
# server_name somename alias another.alias;
# location / {
# root html;
# index index.html index.htm;
# }
#}
# HTTPS server
#
#server {
# listen 443 ssl;
# server_name localhost;
# ssl_certificate cert.pem;
# ssl_certificate_key cert.key;
# ssl_session_cache shared:SSL:1m;
# ssl_session_timeout 5m;
# ssl_ciphers HIGH:!aNULL:!MD5;
# ssl_prefer_server_ciphers on;
# location / {
# root html;
# index index.html index.htm;
# }
#}
}
3、反向代理
准备工作
安装启动Tomcat
# ...检查jdk
[aaa@qq.com logs]# java -version
# ...解压tomcat
[aaa@qq.com opt]# tar -vxf apache-tomcat-8.5.58.tar.gz
# ...启动tomcat
[aaa@qq.com opt]# /opt/apache-tomcat-8.5.58/bin/startup.sh
# ...查看tomcat日志
[aaa@qq.com opt]# tail -f /opt/apache-tomcat-8.5.58/log/catalina.out
启动防火墙,添加80端口和8080端口协议
[aaa@qq.com opt]# systemctl enable firewalld.service
Created symlink from /etc/systemd/system/dbus-org.fedoraproject.FirewallD1.service to /usr/lib/systemd/system/firewalld.service.
Created symlink from /etc/systemd/system/basic.target.wants/firewalld.service to /usr/lib/systemd/system/firewalld.service.
[aaa@qq.com opt]# systemctl start firewalld.service
[aaa@qq.com opt]# firewall-cmd --state
running
[aaa@qq.com opt]# firewall-cmd --zone=public --permanent --add-port=8080/tcp
success
[aaa@qq.com opt]# firewall-cmd --zone=public --permanent --add-port=80/tcp
success
[aaa@qq.com opt]# systemctl-cmd --reload
success
[aaa@qq.com opt]# firewall-cmd --list-all
public (default, active)
interfaces: eno16777736
sources:
services: dhcpv6-client ssh
ports: 15672/tcp 80/tcp 6379/tcp 5672/tcp 8080/tcp
masquerade: no
forward-ports:
icmp-blocks:
rich rules:
[aaa@qq.com opt]#
反向代理实例(一)
简单IP转发
修改Nginx.conf
到这一步,已经完成了对8080的转发配置
反向代理实例(二)
使用正则判断更精细的uri进行分发
准备工作
启动两个tomcat,分别监听8080、8081
# ...创建两个文件夹
[aaa@qq.com opt]# mkdir tomcat8080
[aaa@qq.com opt]# mkdir tomcat8081
# ...先停止tomcat
[aaa@qq.com opt]# /opt/apache-tomcat-8.5.58/bin/shutdown.sh
# ...拷贝两份tomcat
[aaa@qq.com opt]# cp -r apache-tomcat-8.5.58/. tomcat8080
[aaa@qq.com opt]# cp -r apache-tomcat-8.5.58/. tomcat8081
# ...修改tomcat8081端口
[aaa@qq.com opt]# vi tomcat8081/conf/server.xml
<Server port="8006" shutdown="SHUTDOWN">
<Connector port="8081" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
# ...启动
[aaa@qq.com opt]# tomcat8080/bin/startup.sh
[aaa@qq.com opt]# tomcat8081/bin/startup.sh
# ...防火墙
[aaa@qq.com opt]# firewall-cmd --zone=public --permanent --add-port=8081/tcp
success
[aaa@qq.com opt]# systemctl-cmd --reload
success
加入静态页面到 webapps/
8080
8081
正式修改nginx.conf
# 在http块中加入
# 监听9001端口,转发到location。“~”表示正则匹配
# 当连接中含有hello则转发到8080
# 如:http://192.168.0.106:9001/hello/a.html
# 转发到:http://127.0.0.1:8080/hello/a.html
server {
listen 9001;
server_name 192.168.0.106;
location ~ /hello/ {
proxy_pass http://127.0.0.1:8080;
}
location ~ /hi/ {
proxy_pass http://127.0.0.1:8081;
}
}
# ...测试配置文件是否编写正确
[aaa@qq.com opt]# /usr/local/nginx/sbin/nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
# ...平滑重启,重新加载配置文件信息
[aaa@qq.com opt]# /usr/local/nginx/sbin/nginx -s reload
# ...防火墙
[aaa@qq.com opt]# firewall-cmd --zone=public --permanent --add-port=9001/tcp
success
[aaa@qq.com opt]# firewall-cmd --reload
success
开放9001端口后测试:
hello
hi
4、负载均衡
将请求按一定规则分发到不同的应用服务器,实现负载的均衡
准备工作
准备两台tomcat,分别监听8080、8081,并放入一个路径相同的静态页面
…/webapps/ssx/stone.html
正式配置 nginx.conf
在http块中,加入upstream块,并将server块代理到这个upstream块
upstream mystream{
server 127.0.0.1:8080; # 负载的服务器1地址
server 127.0.0.1:8081; # 负载的服务器2地址
}
server {
listen 80;
server_name 192.168.1.106;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
root html;
proxy_pass http://mystream; # 使用多个server处理请求
index index.html index.htm;
}
......
}
# 测试 重启
[aaa@qq.com ssx]# /usr/local/nginx/sbin/nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
[aaa@qq.com ssx]# /usr/local/nginx/sbin/nginx -s reload
测试
将会在8080、8081间选择
负载规则
负载均衡既是将负载分摊到不同的服务单元,既保证服务器的可用性,有保证用户体验。
- 轮询(默认)
每个请求按先后顺序逐一分配到不同的应用服务器上,如果应用服务器宕机,能自动剔除。
- weight
weight代表权重,默认为1,权重越高被分配请求的几率就越大。
upstream server_pool{
server 192.168.0.106 weight=2;
server 192.168.0.107 weight=3;
server 192.168.0.108 weight=5;
}
- ip_hash
每个请求按照访问ip(即Nginx的前置服务器或者客户端IP)的hash结果分配,即某个访客的后续的请求都访问这一个server,从而解决应用session不一致的问题。
upstream server_pool{
ip_hash;
server 192.168.0.106;
server 192.168.0.107;
server 192.168.0.108;
}
- fair(第三方)
按后端服务器的响应时间来分配请求,相应时间短的优先分配
upstream server_pool{
server 192.168.0.106;
server 192.168.0.107;
server 192.168.0.108;
fair;
}
5、动静分离
基本概念
动静分离指的是,匹配判断动态请求和静态请求,然后区别对待,分开处理,目的还是为了提高服务的响应速度、用户的体验。
现在比较主流的分离方式是,将动态请求放在一台服务器上,静态请求放在另一台服务器上。
- location 指定不同的后缀名实现请求类型的判断,转发请求;
- expires 设置浏览器缓存过期时间。使用浏览器缓存可以加快响应速度,降低请求流量。这个过期时间,无需到应用服务端验证,浏览器自身确认是否过期。
准备工作
在服务器放一张图
/opt/images/sailboat.png
正式配置 nginx.conf
没有匹配到png的请求正常访问tomcat
匹配到 .png的请求访问目录
测试
6、高可用集群
基础概念
应用服务器可能会宕机,所以配置了多台,那么nginx也可能会宕机,所以也有一定的需要配置高可用集群。
集群结构图:
集群配置
- 两台nginx服务器 192.168.0.106、192.168.0.107
- keepalived软件
# 安装keepalived
[aaa@qq.com opt]# yum install keepalived -y
[aaa@qq.com opt]# rpm -q -a keepalived
keepalived-1.3.5-16.el7.x86_64
keepalived配置文件
[aaa@qq.com opt]# ls /etc/keepalived/
keepalived.conf
! Configuration File for keepalived
global_defs { # 全局配置
notification_email {
aaa@qq.com
aaa@qq.com
aaa@qq.com
}
notification_email_from aaa@qq.com
smtp_server 192.168.0.106
smtp_connect_timeout 30
router_id LVS_DEVEL # 路由ID,服务器名。/etc/hosts
}
# 脚本
vrrp_script chk_http_port {
script "/usr/local/src/nginx_check.sh"
interval 2 # 检测脚本执行的间隔
weight 2 # 权重。意思是当脚本执行成立,则此服务的权重 +2 。若配置的是负数,则减2
}
# 虚拟机配置
vrrp_instance VI_1 {
state MASTER # MASTER:主服务器 BACKUP:备用服务器
interface eno16777736 # 网卡 ifconfig查看
virtual_router_id 51 #主、备机的virtual_router_id必须相同
priority 100 # 主、备机取不同的优先级,主机取较大值,备机取较小值。一般主机配置100
advert_int 1 # 时间间隔、心跳。每隔1s发送一个心跳包,检测服务器是否存活
authentication { # 校验权限的方式
auth_type PASS # 密码方式
auth_pass 1111 # 密码是 1111
}
virtual_ipaddress {
192.168.0.110 # VRRP H虚拟地址。可绑定多个。
}
}
检测脚本
检测nginx是否存活,如果死掉则关闭keepalived。目的是让另一台keepalived检测到。
#!/bin/bash
A='ps -C nginx -no-header |wc -1'
if [ $A -eq 0 ];then
/usr/local/nginx/sbin/nginx
sleep 2
if [ 'ps -C nginx --no-header |wc -1' -eq 0 ];then
killall keepalived
fi
fi
两台机器都要修改keepalived.conf、添加脚本文件。
脚本文件不用改,配置文件需要修改网卡和priority。
启动和测试
1. 启动
[aaa@qq.com src]# /usr/local/nginx/sbin/nginx
[aaa@qq.com src]# systemctl start keepalived.service
[aaa@qq.com src]# ps -ef|grep keepalived
root 18055 1 0 10:06 ? 00:00:00 /usr/sbin/keepalived -D
root 18057 18055 0 10:06 ? 00:00:00 /usr/sbin/keepalived -D
root 18058 18055 0 10:06 ? 00:00:00 /usr/sbin/keepalived -D
root 18148 2665 0 10:06 pts/0 00:00:00 grep --color=auto keepalived
2. 测试-访问虚拟主机 192.168.0.110
成功进入主Nginx配置的tomcat!
3. 测试-停掉主Nginx,再访问110
请求正常访问,进入了备机nginx,没有配置转发端口,所以不跳tomcat
此时备机上的绑定了虚拟ip 192.168.0.110
至此,Nginx的集群已经全部完成。
撒花~~
7、Nginx工作原理(性能调优)
Master&Worker
[aaa@qq.com src]# ps -ef|grep nginx
root 18485 1 0 10:35 ? 00:00:00 nginx: master process /usr/local/nginx/sbin//nginx
nobody 18486 18485 0 10:35 ? 00:00:00 nginx: worker process
root 18488 14574 0 10:35 pts/0 00:00:00 grep --color=auto nginx
Nginx启动之后,可以看到是有两个进程的。
Marster:分配任务;
Worker:接收命令,具体执行任务,可以有多个。每个woker是一个独立的进程!
工作原理图:
当有新的请求到来时,Master得到新任务,由多个Woker进行争抢执行新任务。
Nginx热部署原理:
修改nginx配置文件平滑加载的命令:
./nginx -s reload
原理是:比如此时有个四个woker存活,而worker1正在执行请求任务,另外三个woker空闲,执行了 reload之后,三个空闲的woker去加载了新的nginx.conf,当有新的任务进来时,三个空闲的woker使用的是新nginx.conf去执行任务。而当woker1执行完任务后,会自行去加载新配置文件,再参与争抢下一个任务。
性能调优
因为每个woker是一个独立的进程,所以当一个woker进程销往并不会对nginx的服务造成影响!
同redis类似都采用io多路复用机制,每个woker进程都只有一个主线程,通过异步非阻塞的方式来处理请求,即使成千上万个请求也可支持。所以关键点在于设置多少个woker进程数,才能充分发挥cpu资源。
1. worker_processes
通常cpu有多少核就配置多少个进程
2. worker_cpu_affinity
开启cpu多核配置:
-
2核cpu,开启两个进程
worker_processes 2; worker_cpu_affinity 01 10;
解释:01表示启用第一个cpu内核、10表示启用第二个cpu内核。意思是第一个进程对应第一个cpu内核,第二个进程表示第二个内核。
-
2核cpu,开启四个进程
worker_processes 4; worker_cpu_affinity 01 10 01 10;
-
4核cpu,开启两个进程
worker_processes 2; worker_cpu_affinity 0101 1010;
解释:0101表示开启第一个和第三个内核,1010表示开启第二个和第四个内核。
-
4核cpu,开启四个进程
worker_processes 4; worker_cpu_affinity 0001 0010 0100 1000;
-
8核cpu,开启8个进程
worker_processes 8; worker_cpu_affinity 00000001 00000010 00000100 00001000 00010000 00100000 01000000 10000000;
worker_processes最多开启8个,8个以上性能提升不会再提升了,而且稳定性变得更低,所以8个进程够用了。
规律:2核是 01,四核是0001,8核是00000001,有多少个核,就有几位数,1表示该内核开启,0表示该内核关闭。
配置完之后可以重启nginx,用ab工具或者wrk工具,可以进行性能测试,在服务器上执行top
,然后按1,就可以看到cpu工作情况,如果多个cpu内核的利用率差不多,就证明nginx已经成功利用了多核cpu,测试结束后,cpu内核的负载都同时降低。
3. worker_connection
连接数考题:客户端发送一条请求,占用了worker的几个连接数?
答案:2或4个;
解释:1:客户端链接到nginx服务器的请求;2、nginx返回客户端的请求;3:nginx服务器访问tomcat服务器的请求;4、tomcat服务器返回nginx服务器的请求;当访问的内容在nginx服务器上则答案是2条,当访问的内容在外部服务器上则答案是4条;
并发数考题:当前Nginx有一个Master,有四个Worker,每个Worker支持最大连接数是1024,那么当前Nginx支持的最大并发数是多少?
答案:2048或1024个;
解释:当前最大请求数:4个woker * 1024连接数 / ( 2|4 ) = 2048 | 1024
至此可以按照实际情况,计算调试出最合适的连接数配置。
上一篇: nginx实践
下一篇: nginx集群实践配置