据说让你抓狂的Nginx性能调优,我却这么轻松就搞定了

前言

nginx 是一个轻量级的、基于http的、高性能的反向代理的服务器和静态web服务器。

正向代理和反向代理

不管是正向代理还是反向代理都是基于客户端来说的。

  • 正向代理

    • 特点

      • 正向代理是对客户端的代理

      • 正向代理是架设在客户端的主机

      • 客户端在使用正向代理服务器时是要知道访问的目标服务的地址

    • 案例

      • 隐藏真正的访问者

        • 向服务端隐藏真正的访问者。对于服务端来说,真正的访问者时代理服务器。起到了隐藏客户端的作用。例如:实际生活中的短信轰炸,你根本不知道是谁给你发的短信;ddos攻击也是这个原理,使用很多‘肉鸡’机器来攻击我们的服务器,我们无法查找真正的攻击源。
      • 翻墙

        • 由于很多复杂的原因,导致服务器A不能直接访问服务器B,但是服务器C可以访问服务器B,而服务器A又可以访问服务器C;这时,服务器C作为服务起A的代理服务器对B进行访问。目前的翻墙软件就是使用这个原理。
      • 提速

        • 同上原理一样,服务器A访问服务器B速度过慢,而服务器C访问服务器B很快,服务器A访问服务器C很快。则使用代理服务器提高效率。
      • 缓存

        • 增加客户端缓存,减少对服务器的请求资源的压力。例如maven的nexus就是一个典型的客户端缓存例子。
      • 授权

        • 例如,在公司中,需要对员工电脑进行外网监控授权,则也是使用这种客户端正向代理服务器。
  • 反向代理

    • 特点

      • 反向代理是对服务端的代理

      • 反向代理是架设在服务端的主机

      • 客户端端访问的时候不知道真正服务主机的地址

    • 案例

      • 保护隐藏真正的服务

        • 客户端只能访问服务端代理服务器,而真正的服务端是不能直接访问的,保护了服务端。
      • 分布式路由

        • 根据客户端不同的请求,将请求路由到不同的服务端去。
      • 负载均衡

        • 服务端均摊客户端的请求,保证服务端的高可用。
      • 动静分离

        • 例如图片、静态页面、css、js等,都为静态资源,将其放到对应目录下,客户端加载静态资源时,就不会请求到服务端,而只会将动态资源的请求发送到服务端,减轻服务端的压力。
      • 数据缓存

        • 反向代理同正向代理一样具有数据缓存的功能,都是为了减少服务端的压力。

负载均衡

1、nginx的负载均衡策略有两种:内置策略和扩展策略

2、内置策略:轮询、权重轮询、IP hash、least_conn

3、扩展策略:自己想怎么实现就怎么实现

轮询

轮询是upstream默认的负载均衡策略,每个请求会按时间顺序逐一分配到不同的服务器

参数如下:

例子:

#动态服务器组
upstream dynamic_zuoyu {
    server localhost:8080;  #tomcat 7.0
    server localhost:8081;  #tomcat 8.0
    server localhost:8082 backup;  #tomcat 8.5
    server localhost:8083 max_fails=3 fail_timeout=20s;  #tomcat 9.0
}

注:此策略适合服务器配置相当,无状态且短平快的服务使用

权重

权重的方式,是在轮询基础上制定轮询的几率;权重分配越高,需要处理的请求越多;此策略也可和ip_hash、least_conn结合使用。

例子:

#动态服务器组
upstream dynamic_zuoyu {
    server localhost:8080 weight=2;  #tomcat 7.0
    server localhost:8081;  #tomcat 8.0
    server localhost:8082 backup;  #tomcat 8.5
    server localhost:8083 max_fails=3 fail_timeout=20s;  #tomcat 9.0
}

注:此策略适合服务器硬件配置差异比较大时使用

ip_hash

ip哈希的方式,基于客户端IP来分配,确保统一IP地址的客户端请求都到同一台服务器,保证session会话。可以解决session不能跨域的问题

例子:

#动态服务器组
upstream dynamic_zuoyu {
    ip_hash;    #保证每个访客固定访问一个后端服务器
    server localhost:8080 weight=2;  #tomcat 7.0
    server localhost:8081;  #tomcat 8.0
    server localhost:8082;  #tomcat 8.5
    server localhost:8083 max_fails=3 fail_timeout=20s;  #tomcat 9.0
}

注:此策略适合服务器解决session不能跨域的问题时使用

least_conn

最少连接方式,将请求转发给连接数较少的服务端。由于轮询的方式是平均将请求转发给各个服务器,使得负载大致相同。但是也存在其中某些请求的链路过长,占用时间长,导致某一些服务器的负载较高。所以最少连接的方式可以平衡轮询会出现的这种问题

例子:

#动态服务器组
 upstream dynamic_zuoyu {
     least_conn;    #把请求转发给连接数较少的后端服务器
     server localhost:8080   weight=2;  #tomcat 7.0
     server localhost:8081;  #tomcat 8.0
     server localhost:8082 backup;  #tomcat 8.5
     server localhost:8083   max_fails=3 fail_timeout=20s;  #tomcat 9.0
 }

注:此策略适合请求时间长短不一造成服务器负载的情况时使用

fair(第三方,需要单独安装插件)

按照服务器的响应时间来分配请求,响应时间短的服务器优先分配(能者多劳)

例子:

#动态服务器组
upstream dynamic_zuoyu {
    server localhost:8080;  #tomcat 7.0
    server localhost:8081;  #tomcat 8.0
    server localhost:8082;  #tomcat 8.5
    server localhost:8083;  #tomcat 9.0
    fair;    #实现响应时间短的优先分配
}

url_hash(第三方,需要单独安装插件)

按照url哈希来分配请求到服务器,使得相同的url每次到的服务器一致,这样也可以减轻对服务器的压力(配合缓存命中来使用)

例子:

#动态服务器组
upstream dynamic_zuoyu {
    hash $request_uri;    #实现每个url定向到同一个后端服务器
    server localhost:8080;  #tomcat 7.0
    server localhost:8081;  #tomcat 8.0
    server localhost:8082;  #tomcat 8.5
    server localhost:8083;  #tomcat 9.0
}

注:此策略适合同一个资源多次请求的情况时使用

静态web服务器

前后端分离

location / {
    root   /data/paibo_web_8081_css; #前端代码存放路径
    index  index.html index.htm;
}

静态资源(文件、图片等)

location /upfile/ {
    root /home/audit_files/; #文件存放路径
    index index.html;
}

Nginx的下载与安装

#下载gcc编译器
yum -y install gcc gcc-c++

#下载PCRE
yum -y install pcre-devel openssl-devel

#下载nginx,官方网站是 http://nginx.org ,自己找到需要的版本,右键复制下载链接
wget http://nginx.org/download/nginx-1.19.2.tar.gz

#解压
tar -zxvf nginx-1.19.2.tar.gz

#生成makefile。使用./configure --help查看各个模块的使用情况,使用--without-http_ssi_module的方式关闭不需要的模块。可以使用--with-http_perl_modules方式安装需要的模块
cd nginx-1.19.2

./configure --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module 

#编译安装
make && make install

#进入到安装目录
cd /usr/local/nginx/

#将 /usr/local/nginx/sbin/nginx 软连接到 /usr/local/sbin 下,就可以在任意地方使用nginx命令
ln -s /usr/local/nginx/sbin/nginx /usr/local/sbin/

#修改配置文件
vim /usr/local/nginx/conf/nginx.conf

#测试nginx配置文件是否正常
nginx -t

#启动nginx
nginx

#关闭防火墙
systemctl stop firewalld
systemctl disable firewalld

#外部访问,nginx默认监听80端口
192.168.198.98:80

#重新载入配置文件
nginx -s reload

#重启nginx
nginx -s reopen

#停止nginx
nginx -s stop

Nginx+Keepalived实现高可用

#在两台服务器安装nginx,参考<Nginx的下载与安装>
#我这里用的是下面两台服务器,为了区分,做了以下修改
192.168.198.6 #编辑index.html,<h1>Welcome to nginx! 2</h1>
192.168.198.98 #编辑index.html,<h1>Welcome to nginx! 1</h1>

#两台服务器都需要执行以下操作

#下载keepalived安装包
cd /data/soft/
wget https://www.keepalived.org/software/keepalived-2.1.0.tar.gz

#解压安装包
tar -zxvf keepalived-2.1.0.tar.gz

#编译安装
cd keepalived-2.1.0
./configure --prefix=/usr/local/keepalived
make && make install

#keepalived启动脚本变量引用文件,默认文件路径是/etc/sysconfig/,也可以不做软链接,直接修改启动脚本中文件路径即可(安装目录下)
cp /usr/local/keepalived/etc/sysconfig/keepalived  /etc/sysconfig/keepalived

#将keepalived主程序加入到环境变量(安装目录下)
cp /usr/local/keepalived/sbin/keepalived /usr/sbin/keepalived

#keepalived启动脚本(源码目录下),放到/etc/init.d/目录下就可以使用service命令便捷调用
cp /data/soft/keepalived-2.1.0/keepalived/etc/init.d/keepalived  /etc/init.d/keepalived

#将配置文件放到默认路径下
mkdir /etc/keepalived
cp /usr/local/keepalived/etc/keepalived/keepalived.conf /etc/keepalived/keepalived.conf

#加为系统服务
chkconfig –add keepalived

#开机启动
chkconfig keepalived on

#查看开机启动的服务
chkconfig –list

#启动、关闭、重启
service keepalived start|stop|restart

######################### 至此,安装完成;以下就是在keepalived.conf做HA的配置 #########################
vim /etc/keepalived/keepalived.conf

##### master #####
! Configuration File for keepalived
# 全局定义块
global_defs {
   router_id redis-rocketMQ     #标志本节点的字符串,建议使用hostname
}
# keepalived 会定时执行脚本并对脚本执行的结果进行分析,动态调整 vrrp_instance 的优先级。如果脚本执行结果为 0,并且 weight 配置的值大于 0,则优先级相应>的增加。如果脚本执行结果非 0,并且 weight配置的值小于 0,则优先级相应的减少。其他情况,维持原本配置的优先级,即配置文件中 priority 对应的值。
vrrp_script chk_nginx {
    script "/etc/keepalived/nginx_check.sh"     #检测 nginx 状态的脚本路径
    interval 2                                  #检测时间间隔
    weight -20                                  #如果条件成立,权重-20
}

# 定义虚拟路由,VI_1 为虚拟路由的标示符,自己定义名称
vrrp_instance VI_1 {
    state MASTER                #主节点为MASTER,备用节点为BACKUP
    interface eno16777736       #与本机网卡名称一致
    virtual_router_id 51        #虚拟路由的id号,两个节点必须设置一样
    mcast_src_ip 192.168.198.98
    priority 100                #设置优先级,值范围 0~254,master要比backup高
    nopreempt                   #优先级高的设置 nopreempt 解决异常恢复后再次抢占的问题
    advert_int 1                #组播信息发送间隔,节点必须设置一致
    authentication {            #设置验证信息,节点必须设置一致
        auth_type PASS
        auth_pass 1111
    }
    #将 track_script 块加入 instance 配置块
    track_script {
        chk_nginx               #执行 Nginx 监控的服务
    }
    virtual_ipaddress {         #虚拟节点池,节点必须设置一样
        192.168.198.111         #虚拟ip,可设置多个
    }
}

##### backup #####
! Configuration File for keepalived

global_defs {
   router_id zk_alone
}
vrrp_script chk_nginx {
    script "/etc/keepalived/nginx_check.sh"
    interval 2
    weight -20
}
vrrp_instance VI_1 {
    state BACKUP
    interface eno16777736
    virtual_router_id 51
    mcast_src_ip 192.168.198.6
    priority 90
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    track_script {
        chk_nginx
    }
    virtual_ipaddress {
        192.168.198.111
    }
}

#编写 Nginx 状态检测脚本
#ps -C nginx | wc -l,查看当前有多少个nginx进程
#逻辑:如果 nginx 停止运行,尝试启动,如果无法启动则杀死本机的 keepalived 进程, keepalied将虚拟 ip 绑定到 BACKUP 机器上
vi /etc/keepalived/nginx_check.sh

#!/bin/bash
A=`ps -C nginx –no-header |wc -l`
if [ $A -eq 0 ];then
/usr/local/nginx/sbin/nginx
sleep 2
if [ `ps -C nginx --no-header |wc -l` -eq 0 ];then
    killall keepalived
fi
fi

#赋权限
chmod +x /etc/keepalived/nginx_check.sh

#启动 两台Keepalived
service keepalived start

#访问虚拟IP
192.168.198.111 # Welcome to nginx! 1

######################### HA测试 #########################
#由于我们写了一个自动启动nginx的脚本再keepalived中,故关闭时,先关闭keepalived,再关闭nginx
192.168.198.98
service keepalived stop
nginx -s stop
#再次访问192.168.198.111查看变化 Welcome to nginx! 2

192.168.198.98
service keepalived start #由于有启动nginx的脚本,故省去启动nginx的操作
#再次访问192.168.198.111查看变化 Welcome to nginx! 1

Nginx高并发处理原理

高并发一般是由多进程、多线程和异步机制来处理的,而正好nginx采用了这三种有效的处理高并发的方式。

Nginx的进程模型

​ 进程模型采用Master/Worker 方式。当 nginx 启动的时候,会创建一个 Master 进程,Master进程会根据nginx.conf配置文件中相应的配置项来fork出多个worker子进程去处理请求(怎么处理也是根据配置文件中相应的配置文件)。

​ Master进程负责管理Worker进程的生命周期、处理网络事件、接收外界信号等。由于Master进程可以fork出多个Worker进程,所以说Nginx是多进程的。

Nginx的线程模型

​ 线程模型是指worker进程用于接收和处理客户端请求。每个worker进程可以同时处理多个用户请求。


Nginx的异步处理模型

​ 异步处理模式是指nginx处理请求的时候是采用I/O多路复用技术(select | poll | epoll 模型),即多个 I/O 可以复用一个进程。当 worker 进程接收到客户端的请求后,会调用服务端对其请求进行处理,如果没有立即得到响应结果, worker 进程没有阻塞,而是去处理其他请求,知道有请求被服务端处理完成并返回响应结果。

​ 这里的 worker 进程默认就是采用 epoll 多路复用机制来对服务端进行处理的。当服务端返回响应结果时,回调 epoll 多路复用器,epoll 告知 worker 进程,worker 会挂起当前正在处理的线程,去获取响应结果返回客户端,完成后再去执行被挂起的线程。整个过程中不会出现等待的情况,所以理论上Ngnix的一个进程就可以处理无限数量的连接,而且无需轮询。

​ 注:worker 进程接收客户端请求不是采用的 epoll 模型,而是互斥锁机制;只有对服务端的请求和响应采用的是 epoll 模型。

Nginx的特点

高并发

一个nginx的默认并发量为1024,是因为默认一个woker进程,每个进程处理量为1024,故1*1024;但是,在硬件条件满足的条件下,nginx可以支持5~10w的并发量。具体做法如下:

####################### 操作系统配置 start #######################
#查看当前会话中所有的linux核心配置,而我们只需要关注open file这项
ulimit -a

#查看linux系统的“进程最大可打开文件数的设置”,默认时1024
ulimit -n

#修改“进程最大可打开文件数的设置”
vim /etc/security/limit.conf

#添加下面两行
soft nofile 65535 #应用软件级别限制的最大可打开文件数的限制
hard nofile 65535 #操作系统级别限制的最大可打开文件数的限制

#文件保存后不会马上生效,所以还得更改当前会话级别的配置
ulimit -n 65535
####################### 操作系统配置 end #######################

####################### nginx配置 start #######################
#修改nginx配置文件(下面两行)
vim /src/local/nginx/conf/nginx.conf

user root root;
worker_processes 4;
worker_rlimit_nofile 65535; #这行,看这里看这里
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;

#pid logs/nginx.pid;
events {
    use epoll;
    worker_connections 65535; #这行,看这里看这里
}

#热部署重新加载配置文件
nginx -s reload
####################### nginx配置 end #######################

####################### 验证配置是否正确 start #######################
#查看当前nginx进程信息
ps -ef | grep nginx

root     103734      1  0 13:27 ?        00:00:00 nginx: master process nginx
nobody   103735 103734  0 13:27 ?        00:00:00 nginx: worker process
root     105129   3066  0 14:50 pts/0    00:00:00 grep --color=auto nginx

#注意,也是看open files这项
cat /proc/103735/limits
####################### 验证配置是否正确 start #######################

####################### max client计算方式 start #######################
max client = worker_processes * worker_connections
或
max client = worker_processes * worker_connections / 4

#第一种很好理解,进程数*每个进程并发数
#第二种为什么要除以4呢?是因为在nginx官网有这么一段话
Since a browser opens 2 connections by default to a server and nginx uses the fds (file descriptors) from the same pool to connect to the upstream backend。
#就是说,浏览器会建立两条链接到nginx,而nginx也会建立两条链接到服务端,故就是4
####################### max client计算方式 end #######################

低消耗

一万个非活跃性链接,消耗内存仅暂用2.5M,故对于一般的dos攻击不受影响,但是ddos还是有问题。

热部署

可以在7*24小时不间断服务提供,进行版本和配置平滑升级

#命令
nginx -s reload

####################### 命令过程解析 start #######################
1、当上面的命令一执行,如果发现配置文件已更改,会创建一个新的主进程
2、当前所有的worker进程不会再接收新的请求并把当前正在处理的请求执行完就关闭
3、master主进程会创建新的worker进程来接收并处理新的请求
####################### 命令过程解析 end #######################

高可用

之所以实现高可用,是因为在nginx中,woker都一个一个的进程,就算其中某个进程挂掉了,也对其他的进程没得影响,而且其他的进程会接替出问题的进程。

高扩展

由于nginx是模块化集成,故在我们使用中,缺少什么模块我们就安装什么模块(模块一般分为C语言扩展模块和Lua脚本扩展模块)

#下载模块
git clone https://github.com/agentzh/echo-nginx-module

#放入指定位置
mv echo-nginx-module-master /usr/local/nginx/echo-nginx-module

#就用这个命令生成新的makefile
./configure 
--prefix=/usr/local/nginx 
--with-http_stub_status_module 
--with-http_ssl_module 
--add-module=/usr/local/nginx/echo-nginx-module

#编译(这里只需要make,一定不要执行make install,不然会被覆盖)
make

#备份原文件
cp /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx.bak

#替换nginx二进制文件
cp /usr/local/nginx/objs/nginx /usr/local/nginx/sbin/nginx

#重新建立软连接,检测配置文件并平滑启动
ln -s /usr/local/nginx/sbin/nginx /usr/local/bin/nginx
nginx -t
nginx -s reload

Nginx配置文件详解

整体结构

全局块

配置影响nginx的全局指令。包括:

  • 配置运行nginx的服务器用户组

  • worker process数

  • nginx进程

  • pid存放路径

  • 错误日志存放路径

  • 配置文件的引入

events块

配置影响nginx服务器或与用户的网络连接。包括:

  • 设置网络连接的序列化(惊群)

  • 是否允许同时接收多个网络连接

  • 选择事件驱动模型

  • 设置最大连接数

http块

可以嵌套多个server模块,配置代理、缓存、日志定义等和第三方模块的配置。包括:

  • 定义MIMI-Type

  • 自定义服务日志格式

  • 允许sendfile方式传输文件

  • 连接超时时间

  • 单连接请求数上限

server块

配置虚拟主机相关参数。包括:

  • 配置网络监听

  • 配置基于名称的虚拟主机

  • 配置基于IP的虚拟主机

location块

配置请求的路由,以及页面和其他静态资源的处理。包括:

  • location配置

  • 请求根目录配置更改

  • URL

  • 网站默认首页配置

配置清单例析

总结

文章到这里就结束了!Nginx 是一个高性能的 HTTP 和反向代理服务器,特点是占用内存少,并发能力强,事实上 Nginx 的并发能力确实在同类型的网页服务器中表现较好。Nginx 专为性能优化而开发,性能是其最重要的要求,十分注重效率,有报告 Nginx 能支持高达 50000 个并发连接数。

最后

大家看完有什么不懂的可以在下方留言讨论.
谢谢你的观看。
觉得文章对你有帮助的话记得关注我点个赞支持一下!

作者:麒麟才子
链接:https://juejin.cn/post/6912616466513100807

推荐阅读更多精彩内容