第五节:Nginx动静分离、缓存配置、性能调优、集群配置

一. Nginx动静分离

1. 准备

 1个web程序:部署在7061端口,启动 【dotnet NginxWeb.dll --urls="http://*:7061" --ip="127.0.0.1" --port=7061】

    Nginx程序:监听7000端口

2. 目的

 比如单独启动部署在7061端口下的web程序,进行访问,我们会发现,除了请求的加载,还有很多静态 css、js、图片等资源的加载,这些资源的加载也是占服务器带宽的,假设带宽为1m,几个大图片直接就占满了。

   所以这里引入动静分离,将静态资源单独隔离出来,不占据主服务器的带宽,同时也有利于静态资源做缓存处理。 

3. 实操

方案1:在Nginx同一个Server实现动静分离

剖析:

    将wwwroot文件夹从发布包中单独处理出来,然后通过location配置绝对地址,实现静态资源的分离。

    缺点:动静资源在一个虚拟主机中,那么静态资源和动态资源共享同一个资源,如果静态或者动态资源访问量比较大,把资源消耗殆尽,动态和静态资源互相会进行影响,导致系统整体上性能下降。

代码分享:

worker_processes  1;
events {
    worker_connections  1024;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
    server {
        listen       7000;        #监听端口
        server_name  test1;         #随意配置一个地址即可,优先走代理
        
        #动态资源
        location / {
             proxy_pass http://localhost:7061;   #代理地址
        }	
        #静态资源
        location ~ \.(ico|js|css|png|jpg|mp4)$ {
            root C:/Users/Administrator/Desktop/publish/wwwroot;
        }
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }  
    }
}

 

方案2:在Nginx多个Server下实现动静分离

剖析:

  使用主机7000端口监听动态资源,使用主机7001端口监听静态资源,在7000的主机下通过代理的形式链接 静态资源: proxy_pass http://localhost:7001;   #代理地址

       缺点:虽然是两个Sever,但这都是虚拟,还是在一台服务器上,一台服务器的承受能力毕竟是有限的。

代码分享:

worker_processes  1;
events {
    worker_connections  1024;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;

    #1.动态资源Server
    server {
        listen       7000;        #监听端口
        server_name  test1;         #随意配置一个地址即可,优先走代理

        #动态资源
        location / {
             proxy_pass http://localhost:7061;   #代理地址
        }
        #静态资源--指向静态代理Server
        location ~ \.(ico|js|css|png|jpg|mp4)$ {
            proxy_pass http://localhost:7001;   #代理地址
        }
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }  
    }
	
    #2.静态资源Server
    server {
        listen       7001;        #监听端口
        server_name  test2;         #随意配置一个地址即可,优先走代理
        #静态资源
        location ~ \.(ico|js|css|png|jpg|mp4)$ {
            root C:/Users/Administrator/Desktop/publish/wwwroot;
        }
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }  
    }
}

方案3:在多个Nginx下实现动静分离

代码分享:

  即两个Nginx程序,部署在不同服务器,一个处理动态资源,一个处理静态资源,在动态资源的nginx中通过 proxy_pass http://xxxxx:xxxx; 代理到静态资源的服务器上即可。

  nginx_dynamic

  nginx_static

剖析:

      多个nginx部署在多个服务器上,减轻压力,避免同一台服务器上进行资源竞争。

 

 

 

 

 

二. Nginx缓存配置

1.  背景

 分析一个电商网站的详情页面,如下图,设计到很多微服务:商品详情页HTML页面渲染、价格服务、促销服务、库存状态/配送至服务、广告词服务、预售/秒杀服务、评价服务、试用服务、推荐服务、商品介绍服务、各品类相关的一些特殊服务。

常见的解决方案:

 前端通过ajax动态加载,服务端则把这些文案以html的形式缓存到Redis中,如下图:

剖析: 

  一个详情页html  主体达平均150 kb, 那么在500QPS 已接近千M局域网宽带极限,所以必须减少内网通信。

 

2. Nginx缓存

    相关模块【ngx_http_proxy_module】    http://nginx.org/en/docs/http/ngx_http_proxy_module.html

 针对上面占满内网带宽的情况,可以在Ngxin这一层做静态文件缓存,然后后台维护商品的时候删除缓存(修改商品→删除缓存),架构图如下:

3. 配置说明

其它补充:

proxy_set_header Host $host;      #用于后端的real server区分不同的虚拟主机;

proxy_set_header X-Real-IP $remote_addr;    #记录客户端真实ip地址,而不是代理服务器地址,需要后端web服务器开启日志相应功能接收;

proxy_cache_methods GET HEAD;    #表示对客户端请求的GET 和 HEAD方法进行缓存;

proxy_cache_revalidate on;     #本地缓存过期会检查后端服务器该缓存是否存在,避免后端重传占据带宽;

proxy_cache_valid 200 302 10m;
proxy_cache_valid 404 1m;
proxy_cache_valid any 1m;
#针对于不同的响应码进行缓存不同的时间设定;

proxy_cache_min_uses 1;    #某一个请求被响应多少次才会被缓存,默认是1,可以将该值设置为大一些;

proxy_cache_use_stale error timeout invalid_header http_500 http_502 http_503 http_504;   #指明哪种场景可以使用过期缓存,提升用户体验;

 

4. 实操

  这里对一个web页面进行缓存,不进行redis的存储。

剖析:

 (1). 首先在nginx的根目录下创建文件夹 ypfCache/nginx , 用来存放缓存。

   (2). 启动7061端口的web程序,启动nginx程序,访问nginx,发现缓存目录下多了个文件。

   (3). 关闭7061端口的web程序,重新访问nginx,继续可以访问,说明缓存成功了。     

 

代码分享:

worker_processes  1;
events {
    worker_connections  1024;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;

	#缓存声明
	proxy_cache_path ypfcache/nginx/ levels=1:2 keys_zone=mycache:64m;

    server {
        listen       7000;        #监听端口
        server_name  test1;         #随意配置一个地址即可,优先走代理

        location / {
             proxy_pass http://localhost:7061;   #代理地址
			 
            #缓存相关配置
            proxy_cache mycache;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_cache_methods GET HEAD;
            proxy_cache_revalidate on;
            proxy_cache_valid 200 302 10m;
            proxy_cache_valid 404 1m;
            proxy_cache_valid any 1m;
            proxy_cache_min_uses 1;
            proxy_cache_use_stale error timeout invalid_header http_500 http_502 http_503 http_504;
        }
		
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }  
    }
}

 

 

三. Nginx性能调优

1. worker_processes number

 每个worker进程都是单线程的进程,它们会调用各个模块以实现多种多样的功能。如果这些模块确认不会出现阻塞式的调用,那么,有多少CPU内核就应该配置多少个进程;反之,如果有可能出现阻塞式调用,那么需要配置稍多一些的worker进程。例如,如果业务方面会致使用户请求大量读取本地磁盘上的静态资源文件,而且服务器上的内存较小,以至于大部分的请求访问静态资源文件时都必须读取磁盘(磁头的寻址是缓慢的),而不是内存中的磁盘缓存,那么磁盘I/O调用可能会阻塞住worker进程少量时间,进而导致服务整体性能下降。

2. 每个worker 进程的最大连接数

 语法:worker_connections number; 默认:worker_connections 1024

3. worker_cpu_affinity cpumask[cpumask……] 绑定Nginx worker进程到指定的CPU内核

  为什么要绑定worker进程到指定的CPU内核呢?假定每一个worker进程都是非常繁忙的,如果多个worker进程都在抢同一个CPU,那么这就会出现同步问题。反之,如果每一个worker进程都独享一个CPU,就在内核的调度策略上实现了完全的并发。 例如,如果有4颗CPU内核,就可以进行如下配置: worker_processes 4; worker_cpu_affinity 1000 0100 0010 0001; 注意 worker_cpu_affinity配置仅对Linux操作系统有效。

4. Nginx worker 进程优先级设置

 语法:worker_priority nice; 默认:worker_priority 0; 优先级由静态优先级和内核根据进程执行情况所做的动态调整(目前只有±5的调整)共同决定。nice值是进程的静态优先级,它的取值范围是–20~+19,–20是最高优先级,+19是最低优先级。因此,如果用户希望Nginx占有更多的系统资源,那么可以把nice值配置得更小一些,但不建议比内核进程的nice值(通常为–5)还要小

5. Nginx worker进程可以打开的最大句柄描述符个数

 语法: worker_rlimit_nofile limit; 默认: 更改worker进程的最大打开文件数限制。如果没设置的话,这个值为操作系统的限制。设置后你的操作系统和Nginx可以处理比“ulimit -a”更多的文件,所以把这个值设高,这样nginx就不会有“too many open files”问题了。

6. 是否打开accept锁

 语法:accept_mutex[on|off] 默认:accept_mutext on; accept_mutex是Nginx的负载均衡锁,当某一个worker进程建立的连接数量达到worker_connections配置的最大连接数的7/8时,会大大地减小该worker进程试图建立新TCP连接的机会,accept锁默认是打开的,如果关闭它,那么建立TCP连接的耗时会更短,但worker进程之间的负载会非常不均衡,因此不建议关闭它。

7. 使用accept锁后到真正建立连接之间的延迟时间

 语法:accept_mutex_delay Nms;  默认:accept_mutex_delay 500ms;  在使用accept锁后,同一时间只有一个worker进程能够取到accept锁。这个accept锁不是堵塞锁,如果取不到会立刻返回。如果只有一个worker进程试图取锁而没有取到,他至少要等待accept_mutex_delay定义的时间才能再次试图取锁。

 

四. Nginx集群

1. 准备两台服务器

 【192.168.140.1】

 【192.168.140.2】

2.  Nginx的安装

  两台服务器上均进行nginx的安装,步骤详见 https://www.cnblogs.com/yaopengfei/p/13766324.html

 

3. Keepalive的安装

(1). 两个服务器均进行安装keepalive

【yum install keepalived】

(2). 修改配置文件

【cd /etc/keepalived/keepalived.conf】

查看代码

global_defs {

   notification_email { # keepalived服务宕机异常出现的时候,发送通知邮件 可以是多个   acassen@firewall.loc  #  收件人邮箱1

 failover@firewall.loc #  收件人邮箱2

 sysadmin@firewall.loc #  收件人邮箱3
   }

   notification_email_from Alexandre.Cassen@firewall.loc  #邮件发件人

   smtp_server 192.168.200.1  # 邮件服务器地址

   smtp_connect_timeout 30   # 超时时间

   router_id LVS_DEVEL   # 机器标识 局域网内唯一即可

   vrrp_skip_check_adv_addr # 默认是不跳过检查。检查收到的VRRP通告中的所有地址可能会比较耗时,设置此命令的意思是,如果通告与接收的上一个通告来自相同的master路由器,则不执行检查(跳过检查)。

   #vrrp_strict   # 严格遵守VRRP协议。下列情况将会阻止启动Keepalived:1. 没有VIP地址。2. 单播邻居。3. 在VRRP版本2中有IPv6地址。

   vrrp_garp_interval 0  # 小数类型,单位秒,在一个网卡上每组gratuitous arp消息之间的延迟时间,默认为0,一个发送的消息=n组 arp报文

   vrrp_gna_interval 0 # 小数类型,单位秒, 在一个网卡上每组na消息之间的延迟时间,默认为0

}
vrrp_instance VI_1 {
state MASTER  # 服务器状态 MASTER是主服务器  BACKUP是备份服务器 主服务器的priority要比备份服务器大

interface ens33 # 通信端口 通过ip addr可以看到 根据自己的机器配置

virtual_router_id 51  # vrrp实例id  keepalived集群,实例id必须一致

priority 100  # 权重比 主服务器的priority要比备份服务器大

advert_int 1  # 心跳间隔  单位秒  keepalived多机器集群 通过心跳检测,如果发送心跳没反应 就立刻接管;

authentication { # 服务器之间通信密码

    auth_type PASS

    auth_pass 1111

}

virtual_ipaddress { # 自定义虚拟IP 

    192.168.91.199

}
}

(3).  进行启动

【systemctl start keepalived.service】 启动
【systemctl stop keepalived.service】 关闭
【systemctl restart keepalived.service】重启

(4). 日志查看

【tail -f /usr/local/nginx/logs/access.log】

【tail -f /var/log/messages】

(5). 进程查看

【ps -ef|grep keep】

 

4. 配置Nginx重启脚本

(1). 创建脚本,nginx_restart.sh

#!/bin/bash
echo 'xxxxxx'
count_nginx=`ps -ef|grep -w nginx|grep -v grep|wc -l`
echo $count_nginx
if [ $count_nginx -eq 0 ];then
/usr/local/nginx/sbin/nginx
sleep 2
if [ `ps -ef|grep -w nginx|grep -v grep|wc -l` -eq 0 ];then
    systemctl stop keepalived.service
fi  
fi

(2). keepalived配置中添加如下内容

vrrp_script chk_http_port {
     script "/root/nginx_restart.sh" #脚本地址
     interval 2 #检测脚本执行的间隔
     weight 2 #比重
}

 

 

 

 

!

  • 作       者 : Yaopengfei(姚鹏飞)
  • 博客地址 : http://www.cnblogs.com/yaopengfei/
  • 声     明1 : 如有错误,欢迎讨论,请勿谩骂^_^。
  • 声     明2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。
 
posted @ 2022-08-10 16:05  Yaopengfei  阅读(361)  评论(1编辑  收藏  举报