nginx相比较与apache最明显的优势是轻量级、高并发,配置也相当于apache更简洁。本节内容将介绍nginx的相关功能配置,包括nginx的并发优化、负载均衡、平滑升级、nginx限流、配置管理(自动索引、缓存配置、日志轮询、禁用不必要日志、站点目录和文件限制、中文乱码解决、限制IP)、nginx重定向、防盗链等。
Nginx默认没有开启利用多核cpu,我们可以通过增加worker_cpu_affinity配置参数来充分利用多核cpu的性能;
cpu是任务处理,计算最关键的资源,cpu核越多,性能就越好;
2核cpu,开启2个进程 设定worker_cpu_affinity 01 10(将cpu和worker数目绑定);
4个cpu,开启4个进程 设定worker_cpu_affinity 0001 0010 0100 1000
worker_connections:设定每一个worker进程能并发处理(发起)的最大连接数为65535(包含所有连接数),不能超过最大文件打开数;
要求内核支持最大文件打开数>系统支持最大文件打开数>Worker支持最大文件打开数
查看真机内核支持的最大文件打开数
ulimit -a #用来显示当前的用户可以打开文件的限制,可以看到系统支持的最大文件打开数为1024
为了便于实验效果,首先修改server1的cpu的个数为2,内存为1024;
用cpu的个数控制nginx的work进程个数;
vim /usr/local/nginx/conf/nginx.conf // worker_processes 2; ##工作进程数 最大不超过CPU个数 events { worker_connections 1024; ##单个工作进程并发连接数 } //
在真实主机中
ab -c1 -n 10000 http://172.25.254.1/index.php ##-c1表示并发用户数为1 ,可以理解为开启了1个工作线程或进程 -n 10000表示请求总数为100000
当修改并发用户数为10
ab -c1 -n 10000 http://172.25.254.1/index.php
server1中
sysctl -a | grep file #查看内核支持的最大文件打开数.,sysctl命令用于运行时配置内核参数,这些参数位于/proc/sys目录下 ///fs.file-max = 97714 free -m # Mem:表示物理内存 -/+ buffers/cached:表示物理内存缓存 Swap:表示硬盘交换分区
实验环境:
三台虚拟机
server1:nginx反向代理+负载均衡主机
将配置好的server1中nginx复制到server2和server3中。
server1:
vim /usr/local/nginx/conf/nginx.conf 18 upstream westos { # 负载均衡器upstream 19 server 172.25.254.2:80; 20 server 172.25.254.3:80; 21 } 123 server { 124 listen 80; 125 server_name www.westos.org; 126 127 location / { 128 proxy_pass http://westos; # 反向代理器proxy_pass 129 } 130 } 131 }##注意http的后括号
注意:
在http加入upstream模块,设定反向代理负载均衡器westos;upstream表示负载服务器池
location 指令的作用:根据用户请求的URI来执行不同的应用,URI就是根据用户请求到的网址URL进行匹配;
server_name :代理的服务域名;
location:设定当外部访问www.westos.org这个域名时,nginx会把所有请求都发送到upstream定义的服务器节点池(westos)
修改配置文件之后,习惯性的用nginx -t 进行语法检测
没问题之后:nginx -s reload 刷新nginx服务!!
若是报错会提示哪写的有问题,可以直接修改:
切换到/usr/local中,
scp -r nginx/ server2:/usr/local/注意复制目录 scp -r nginx/ server3:/usr/local/
server2:
建立软链接以便全局使用nginx,编辑配置文件,将server1中的设定修改回默认值,写入发布内容,在本次尝试是否能访问。
ln -s /usr/local/nginx/sbin/nginx /usr/local/sbin/ ##建立软链接以便全局使用nginx cd /usr/local/nginx/sbin/ ls cd ..(nginx) cd conf/ vim nginx.conf /// #user nobody; ##注释掉 worker_processes auto; events { worker_connections 1024; ##改回默认 } /// nginx -t ##检测语法 cd ..(nginx) cd html/ ls echo server2 > index.html ##把server2的发布目录写为server2 nginx curl localhost ##显示server2
server3:
和server2进行同样的操作,
测试:
配置完成之后,在真机上对快照进行地址解析,ping通www.westos.org之后便可以使用curl命令查看server主机的发布文件。进行测试:
vim /etc/hosts
curl www.westos.org
结果如下:
负载均衡成功
如果不成功只出现server2,3其中一个,很可能是火墙没有关闭导致
在server1主机中修改配置文件,增加server2主机的权重,检测语法,重启服务。
###server1------改变权重
cd /usr/local/nginx/conf/ vim nginx.conf /// http { upstream westos { server 172.25.254.2:80 weight=2; ##增加权重 server 172.25.254.3:80 ; /// nginx -t nginx -s reload
在真机上作测试时,server2和server3主机则几乎与权重等比出现。权重大的则等比显示.
ip_hash:通过客户端请求ip进行hash,再通过hash值选择后端server;
当你服务端的一个特定url路径会被同一个用户连续访问时,如果负载均衡策略还是轮询的话,那该用户的多次访问会被打到各台服务器上,这显然并不高效(会建立多次http链接等问题)。所以,此类场景可以考虑采用nginx提供的ip_hash策略。既能满足每个用户请求到同一台服务器,又能满足不同用户之间负载均衡。
vim nginx.conf /// http { upstream westos { ip_hash; /// nginx -t nginx -s reload
在server3主机中关闭nginx服务,以模仿后端该主机出现问题的情况,此时在真机做检测时,则只有server2主机的发布文件。
当server2主机也出现问题时,真机则会报错502,显示服务器错误。
当所有后端主机都出现问题时,备用机可以暂时运行,但是风险很高,需要及时修理后端服务器。
在server1主机中设定负载均衡中本机可以作为备用机,检测语法,重启服务。
vim nginx.conf /// http { # ip_hash; ##注释 server localhost:80 backup; ##备用机 /// nginx -t nginx -s reload cd .. cd html/ ls echo helloworld > index.html
当两台后端服务器都不能使用时,则显示server1备用机的发布文件
如果后端主机恢复,则不会访问备用机。
1.版本升级:
平滑的意义在于:升级nginx版本的时候不需要关闭服务,可以实现边使用边更新,毫不影响使用体验
在server1主机中,修改配置文件,设定工作进程数为2,安装一个比当前版本高的nginx,重新编译(configure–makefile–make三步曲)。
下载nginx新版本软件,正常执行./configure和make但不要执行make install。
因为我们前面使用的是1.20版本
现在我们实验需要准备1.21版本!
server1
cd /usr/local/nginx/conf/ vim nginx.conf /// user nginx; worker_processes 2; ##设定工作进程数为2 worker_cpu_affinity 01 10; /// nginx -s reload
make之后备份旧程序,并拷贝新程序。
make cd objs/ ls-->nginx cd /usr/local/nginx/sbin/ ls-->nginx cp nginx nginx.old ##备份原程序 cd cd nginx-1.21.1/ ls cd objs/ \cp -f nginx /usr/local/nginx/sbin/ ##拷贝新程序
此时objs目录就会生成新的nginx二进制文件a
将nginx旧版本文件进行备份,将新生成的nginx文件覆盖安装目录下的旧的nginx,此时curl查看发现仍然是旧版本的nginx.
获取当前nginx主进程pid,即master进程。开启新版本。关闭worker进程但保留主进程master
ps ax | grep nginx ##获取当前nginx主进程pid,即master进程 kill -USR2 22602 ##开启新版本 ps ax | grep nginx curl localhost -I ##显示新版本号 kill -WINCH 22602 ##关闭worker进程但保留主进程
因为有时候我们会发现新版本并没有旧版本用着顺手,那么关闭worker进程但保留主进程就是为了回退,即就是关闭工作端worker,保留master
ps ax | grep nginx curl localhost -I ##此时依旧显示新版本号
2.版本回退
还原nginx程序:# cp -f nginx.old nginx
唤醒原进程:# kill -HUP 旧版本id
回收新版本的worker进程: kill -WINCH 新版本id
关闭新版本主进程: kill -QUIT 29761
cd /usr/local/nginx/sbin/ ls \cp -f nginx.old nginx ##还原nginx程序 kill -HUP 22602 ##唤醒原进程 ps ax | grep nginx kill -WINCH 1040 ##回收新版本的worker进程 kill -QUIT 1040 ##关闭新版本主进程 ps ax | grep nginx curl localhost -I
有时nginx并不支持一些算法,当我们需要使用时,则需要进行扩展。
比如sticky模块,nginx本身不支持,当在配置文件中写入并调用时,会报错。
cd /usr/local/nginc/conf vim nginx.conf /// http { upstream westos { sticky; server 172.25.254.2:80 weight=2; /// nginx -t ##失败,因为sticky不支持,需进行扩展
所以我们需要对nginx进行扩展,先将sticky注释掉,并停止服务。
iptables -t nat -I POSTROUTING -s 172.25.24.0/24 -j MASQUERADE ##火墙策略(真机)
下载sticky软件包并解压。
[root@server1 ~]# scp -r root@172.25.254.72:/iso/nginx-goodies-nginx-sticky-module-ng-08a395c66e42.zip . yum install -y unzip unzip nginx-goodies-nginx-sticky-module-ng-08a395c66e42.zip ls
安装好之后切入nginx目录,清理缓存,执行configure->make。
cd nginx-1.20.1/ make clean ##清理缓存 ./configure --prefix=/usr/local/nginx --with-http_ssl_module --with-http_stub_status_module --with-threads --with-file-aio --add-module=/root/nginx-goodies-nginx-sticky-module-ng-08a395c66e42 make
将nginx复制到sbin并覆盖,切入配置目录,编辑配置文件,取消对sticky的注释并检测语法,但是此时sticky模块会与backup冲突,所以检测失败。
ls cd objs/ \cp -f nginx /usr/local/nginx/sbin/ ##复制覆盖文件,\表示告诉shell不要去查alias,直接执行原本的cp vim nginx.conf nginx -t
需要将之前的设定注释或删掉,重新检测语法,并开启服务。
vim nginx.conf /// http { upstream westos { sticky; server 172.25.254.2:80; server 172.25.254.3:80; #server localhost:80 backup; /// nginx -t nginx
nginx可以通过limit_conn_zone 和limit_req_zone两个组件对客户端访问目录和文件的访问频率和次数进行限制.
实验准备:先建立一个目录,下载一个图片,进行测试。
真机
使用ab命令做压力测试,设定总共有10个请求(-n),由10个用户(-c)并发来发送请求;
可以看到请求都成功处理。
ab -c10 -n 10 http://172.25.24.1/download/vim.jpg ##并发用户数为10,请求总数为10,失败0个
cd /usr/local/nginx/conf/ vim nginx.conf /// #gzip on; limit_conn_zone $binary_remote_addr zone=addr:10m; server { ... location /download/ { limit_conn addr 1; } /// nginx -s reload
$binary_remote_addr :表示通过remote_addr这个标识来做限制
zone=addr:10m :表示生成一个大小为10M,名字为addr的内存区域
设定客户端访问/download目录内容时,启用限制并发的模块;
limit_conn addr 1; 限制并发数为1
在真机进行压力测试,因为被限流,所以1个请求被拒
继续修改配置文件,设定 limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;
$binary_remote_addr 表示保存客户端IP地址的二进制形式;
rate=1r/s表示允许相同标识的客户端的访问频次,这里限制的是每秒1次请求;
limit_req的参数,zone=one 表示这个参数对应的全局设置就是one的那个内存区域
在真机可以看到只有一个请求被处理。
显然这样并不合适,请求仅限于符合limit_req_zone 指令中定义的速率。如果请求数量超过指定的速率并且共享内存区域已满,NGINX 将响应错误。由于流量往往是突发的,因此在流量突发期间返回错误以响应客户端请求并不是最好的情况。
排队(超过指定数量则排队访问)
将 limit_req 指令的burst参数设置等待以指定速率处理的最大请求数,超出zone限制的请求会被放入数目为5的队列中
虽然超过了所设置的只允许一秒一个请求,但可以被放入队列中,一秒处理一个,最后用了9秒处理完客户端的请求.
无延迟
nodelay表示不限制单个请求间的时间;
burst=5 nodelay:表示这5个请求立马处理,不能延迟,相当于特事特办。不过,即使这5个突发请求立马处理结束,后续来了请求也不会立马处理。
在真机中,执行压力测试,只能通过5个,其余被拒绝。
下载东西时看到的网速快慢,就是限制带宽。
由于图片的大小为444k,因为限制的速度为50k,所以一张图片请求大概需要8s,那么5次请求大概需要40秒左右。
压力测试
设定并发数为5,则可以8s处理完成
客户端如果直接访问server1的nginx默认发布目录里的download目录,会报错
路径完整才可以成功访问。
编辑主配置文件,autoindex on:为download目录加入自动索引功能。
实现了download目录下的文件的自动索引.
Nginx expire缓存配置: 缓存可以降低网站带宽,加速用户访问,缓存365天;
html表示默认发布目录
在真机中,使用curl命令访问素材文件,可以看到缓存至2022年。
写一个shell脚本,脚本内容表示: 进入到nginx的日志目录,修改access.log名字为access_$(date +%F -d -1day).log;
kill -USR1 :重新生成新的日志文件
cd /opt/ ##第三方软件安装位置 vim nginx.sh /// #!/bin/bash cd /usr/local/nginx/logs && mv access.log access_$(date +%F -d -1day).log kill -USR1 `cat /usr/local/nginx/logs/nginx.pid` ///
给脚本执行权限,执行脚本,切入到日志目录,产生日志。
chmod +x nginx.sh ./nginx.sh cd /usr/local/nginx/logs/ ls --> access_2021-08-31.log ##生成日志
这样可以节省磁盘IO的消耗,设定访问图片等文件时,不记录日志,节省磁盘空间;
启用nginx status配置,设定只允许本机(server1)访问.
cd ..(nginx) cd conf/ vim nginx.conf /// location ~ .*\.(gif|jpg|png)$ { expires 365d; root html; } ##在这个位置的下面加入设定 location /status { stub_status on; access_log off; } /// nginx -t nginx -s reload
此时在浏览器中访问该目录,在日志目录中不会生成日志记录。
但当在真机中使用curl命令访问该目录时,会产生日志文件。
在配置文件中设定指定目录只能本机访问,拒绝其他所有请求。
cd conf/ vim nginx.conf /// location /status { stub_status on; access_log off; allow 127.0.0.1; deny all; } /// nginx -t nginx -s reload
注:172.0.0.1是回送地址,localhost是本地DNS解析的127.0.0.1的域名,在hosts文件里可以看到。
一般我们通过ping 127.0.0.1来测试本地网络是否正常。其实从127.0.0.1~127.255.255.255,这整个都是回环地址。
当在server1本机访问时,允许访问。
当在真机访问status目录时,拒绝访问,报错403,资源不可用,服务器理解客户的请求,但拒绝处理。
nginx默认不支持中文字符,在浏览器访问时,中文会变成乱码。
在nginx发布文件中加入一行中文,在浏览器中试访问,为乱码。
cd ..(nginx) cd html/ vim index.html /// helloworld 欢迎 ///
#在浏览器访问时中文是乱码
但是在server1本机中,可以使用curl命令查看本地的发布文件,是可以正常显示中文的。
编辑配置文件,设定nginx支持中文字符,并重启服务。
此时在浏览器中访问172.25.24.1,可以看到中文正常显示。
在真机中对server1主机进行地址解析,使用curl命令访问时,也可以看到发布文件。
拒绝访问,报错500
切入配置目录,编辑配置文件,设定在访问本机时,返回500,重启服务。此时使用curl命令访问本机,会显示http报错500。
cd /usr/local/nginx/conf/ vim nginx.conf /// server { listen 80; server_name localhost; return 500; /// nginx -s reload curl -I localhost ##HTTP/1.1 500 Internal Server Error
将所有访问重定向至指定域名
设定将所有访问请求重定向至指定域名,重启服务。此时使用curl命令访问本机,会显示访问地址为http://www.westos.org。
HTTP状态的码301: 301 代表永久性转移(Permanently Moved)
网页测试,输入172.5.254.1回车重定向到www.westos.org
80端口重定向到443端口,修改配置文件,设定需要被加密的网址;
设定证书和密钥都为cert.pem,
vim nginx.conf /// server { listen 443 ssl; server_name www.westos.org; ssl_certificate cert.pem; ssl_certificate_key cert.pem; 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; } } server { listen 80; server_name www.westos.org; rewrite ^/(.*)$ https://www.westos.org/$1 permanent; #location / { # proxy_pass http://westos; # } } ///
加入重定向
生成证书,并移动到配置目录中,检测语法,重启服务。此时检测端口。
cd /etc/pki/tls/certs make cert.pem ##生成证书 mv cert.pem /usr/local/nginx/conf nginx -t nginx -s reload netstat -antlup | grep 443
查看443端口已经打开
访问测试:发现成功对地址进行了加密
网页测试
www.westos.org 重定向bbs.westos.org
设定基于域名的虚拟主机部分:
server_name bbs.westos.org; 域名
root /bbs; 站点根目录,即网站程序放的目录
location / { 默认访问的location标签段
index index.html; 首页
}
在 /html/下建立bbs目录;给index.html文件写入内容
在配置文件nginx.conf加入重定向:当客户端访问www.westos.org/bbs时,重定向到bbs.westos.org
刷新服务后,访问测试,可以看到重定向成功.
cd ..(nginx) cd html mkdir bbs mv bbs/ / vim nginx.conf /// server { listen 80; server_name www.westos.org; #rewrite ^/(.*)$ https://www.westos.org/$1 permanent; rewrite ^/bbs$ http://bbs.westos.org permanent; ##^/bbs$表示匹配以/开头,bbs结尾,,比如www.westos.org/bbs,如果后加其他url,则不能重定向 rewrite ^/(.*)$ http://bbs.westos.org/$1 permanent; ##^/(.*)$表示匹配以/开头,$结尾,后面可以加url,比如www.westos.org/bbs/bbs.html #location / { # proxy_pass http://westos; # } } server { listen 80; server_name bbs.westos.org; location / { root /bbs; index index.html; } } /// nginx -s reload
真机测试
网页测试
bbs.westos.org 重定向www.westos.org
设定网页根目录位于 /bbs;站点根目录位于 html下的bbs;加入重定向策略
将/bbs目录的内容,复制到nginx的html目录
vim nginx.conf /// server { listen 80; server_name www.westos.org; #rewrite ^/(.*)$ https://www.westos.org/$1 permanent; #rewrite ^/bbs$ http://bbs.westos.org permanent; #rewrite ^/(.*)$ http://bbs.westos.org/$1 permanent; if ($host = "bbs.westos.org") { rewrite ^/(.*)$ http://www.westos.org/bbs/$1 permanent; } #server { ##全部注释 # listen 80; # server_name bbs.westos.org; # # location / { # root /bbs; # index index.html; # } # } /// nginx -s reload
在真机先做地址解析,然后查看
网页测试
在server2的nginx默认发布目录创建一个盗链文件
server2
cd /usr/local/nginx/html vim test.html ##盗链文件,盗取server1主机的图片 /// <html> <body> <img src = "http://www.westos.org/download/vim.jpg"> </body> </html> ///
此时在真机浏览器中可以直接访问server1的图片,也可以也可以通过访问server2,访问到server1主机的图片
设定防盗链
在server1的配置文件中设定当被访问时,返回403报错或者显示指定防盗链图片,重启服务。
###server1 vim nginx.conf /// server { listen 80; server_name www.westos.org; location ~ \.(jpg|png)$ { valid_referers none blocked www.westos.org; if ($invalid_referer) { #return 403; ##返回403 rewrite ^/ http://172.25.24.1/daolian.jpg; ##显示指定图片 } } /// nginx -s reload
此时server2访问原本的盗链文件时会显示盗链