写点什么

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

作者:C++后台开发
  • 2022-12-03
    湖南
  • 本文字数:5760 字

    阅读完需:约 19 分钟

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 部署在多个服务器上,减轻压力,避免同一台服务器上进行资源竞争。


更多 C++后台开发技术点知识内容包括 C/C++,Linux,Nginx,ZeroMQ,MySQL,Redis,MongoDB,ZK,流媒体,音视频开发,Linux 内核,TCP/IP,协程,DPDK 多个高级知识点。

C/C++Linux服务器开发高级架构师/C++后台开发架构师免费学习地址

【文章福利】另外还整理一些C++后台开发架构师 相关学习资料,面试题,教学视频,以及学习路线图,免费分享有需要的可以点击领取



二. 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/bashecho 'xxxxxx'count_nginx=`ps -ef|grep -w nginx|grep -v grep|wc -l`echo $count_nginxif [ $count_nginx -eq 0 ];then/usr/local/nginx/sbin/nginxsleep 2if [ `ps -ef|grep -w nginx|grep -v grep|wc -l` -eq 0 ];then    systemctl stop keepalived.servicefi  fi
复制代码


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


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


原文链接:第三节:Nginx 动静分离、缓存配置、性能调优、集群配置 - Yaopengfei - 博客园

用户头像

C/C++后台开发技术交流qun:720209036 2022-05-06 加入

还未添加个人简介

评论

发布
暂无评论
Nginx动静分离、缓存配置、性能调优、集群配置_nginx_C++后台开发_InfoQ写作社区