早期的业务都是基于单体节点部署,由于前期访问流量不大,因此单体结构也可满足需求,但随着业务增长,流量也越来越大,那么最终单台服务器受到的访问压力也会逐步增高。时间一长,单台服务器性能无法跟上业务增长, ...
今天来和大家聊聊Nginx在我们实际应运用中的一些非常有用的点。 早期的业务都是基于单体节点部署,由于前期访问流量不大,因此单体结构也可满足需求,但随着业务增长,流量也越来越大,那么最终单台服务器受到的访问压力也会逐步增高。时间一长,单台服务器性能无法跟上业务增长,就会造成线上频繁宕机的现象发生,最终导致系统瘫痪无法继续处理用户的请求。 从上面的描述中,主要存在两个问题: ①单体结构的部署方式无法承载日益增长的业务流量。 ②当后端节点宕机后,整个系统会陷入瘫痪,导致整个项目不可用。 因此在这种背景下,引入负载均衡技术可带来的收益:
OK~,既然引入负载均衡技术可给我们带来如此巨大的好处,那么又有那些方案可供选择呢?主要有两种负载方案,「「硬件层面与软件层面」」 ,比较常用的硬件负载器有 Java开发者在线刷题神器 一、性能怪兽-Nginx概念深入浅出
先来看看 原本客户端是直接请求目标服务器,由目标服务器直接完成请求处理工作,但加入 了解了 二、Nginx环境搭建❶首先创建 [root@localhost]# mkdir /soft && mkdir /soft/nginx/ [root@localhost]# cd /soft/nginx/ 登录后复制 ❷下载 [root@localhost]# wget https://nginx.org/download/nginx-1.21.6.tar.gz 登录后复制 没有 [root@localhost]# yum -y install wget 登录后复制 ❸解压 [root@localhost]# tar -xvzf nginx-1.21.6.tar.gz 登录后复制 ❹下载并安装 [root@localhost]# yum install --downloadonly --downloaddir=/soft/nginx/ gcc-c++ [root@localhost]# yum install --downloadonly --downloaddir=/soft/nginx/ pcre pcre-devel4 [root@localhost]# yum install --downloadonly --downloaddir=/soft/nginx/ zlib zlib-devel [root@localhost]# yum install --downloadonly --downloaddir=/soft/nginx/ openssl openssl-devel 登录后复制 也可以通过 [root@localhost]# yum -y install gcc zlib zlib-devel pcre-devel openssl openssl-devel 登录后复制 执行完成后,然后 紧接着通过 [root@localhost]# rpm -ivh --nodeps *.rpm 登录后复制 ❺进入解压后的 [root@localhost]# cd nginx-1.21.6 [root@localhost]# ./configure --prefix=/soft/nginx/ 登录后复制 ❻编译并安装 [root@localhost]# make && make install 登录后复制 ❼最后回到前面的 ❽修改安装后生成的 [root@localhost]# vi conf/nginx.conf 修改端口号:listen 80; 修改IP地址:server_name 你当前机器的本地IP(线上配置域名); 登录后复制 ❾制定配置文件并启动 [root@localhost]# sbin/nginx -c conf/nginx.conf [root@localhost]# ps aux | grep nginx 登录后复制
sbin/nginx -t -c conf/nginx.conf # 检测配置文件是否正常 sbin/nginx -s reload -c conf/nginx.conf # 修改配置后平滑重启 sbin/nginx -s quit # 优雅关闭Nginx,会在执行完当前的任务后再退出 sbin/nginx -s stop # 强制终止Nginx,不管当前是否有任务在执行 登录后复制 ❿开放 [root@localhost]# firewall-cmd --zone=public --add-port=80/tcp --permanent [root@localhost]# firewall-cmd --reload [root@localhost]# firewall-cmd --zone=public --list-ports 登录后复制 ⓫在 最终看到如上的 三、Nginx反向代理-负载均衡首先通过 @Controller public class IndexNginxController { @Value("${server.port}") private String port; @RequestMapping("/") public ModelAndView index(){ ModelAndView model = new ModelAndView(); model.addObject("port", port); model.setViewName("index"); return model; } } 登录后复制 在该 前端的 <html> <head> <title>Nginx演示页面</title> <link href="nginx_style.css" rel="stylesheet" type="text/css"/> </head> <body> <div style="border: 2px solid red;margin: auto;width: 800px;text-align: center"> <div id="nginx_title"> <h1>欢迎来到熊猫高级会所,我是竹子${port}号!</h1> </div> </div> </body> </html> 登录后复制 从上可以看出其逻辑并不复杂,仅是从响应中获取了 OK~,前提工作准备就绪后,再简单修改一下 upstream nginx_boot{ # 30s内检查心跳发送两次包,未回复就代表该机器宕机,请求分发权重比为1:2 server 192.168.0.000:8080 weight=100 max_fails=2 fail_timeout=30s; server 192.168.0.000:8090 weight=200 max_fails=2 fail_timeout=30s; # 这里的IP请配置成你WEB服务所在的机器IP } server { location / { root html; # 配置一下index的地址,最后加上index.ftl。 index index.html index.htm index.jsp index.ftl; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 请求交给名为nginx_boot的upstream上 proxy_pass http://nginx_boot; } } 登录后复制 至此,所有的前提工作准备就绪,紧接着再启动 最终来看看效果: 负载均衡效果-动图演示 因为配置了请求分发的权重, Java开发者在线刷题神器 Nginx请求分发原理客户端发出的请求 请求分发原理
四、Nginx动静分离动静分离应该是听的次数较多的性能优化方案,那先思考一个问题:「「为什么需要做动静分离呢?它带来的好处是什么?」」 其实这个问题也并不难回答,当你搞懂了网站的本质后,自然就理解了动静分离的重要性。先来以淘宝为例分析看看: 淘宝首页 当浏览器输入 IDEA 工程结构 在项目上线部署时,这些静态资源会一起打成包,那此时思考一个问题:「「假设淘宝也是这样干的,那么首页加载时的请求最终会去到哪儿被处理?」」 答案毋庸置疑,首页 但此时不妨分析看看,首页 既然有这么多请求属于静态的,这些资源大概率情况下,长时间也不会出现变动,那为何还要让这些请求到后端再处理呢?能不能在此之前就提前处理掉?当然 OK~,搞清楚动静分离的必要性之后,如何实现动静分离呢?其实非常简单,实战看看。 ①先在部署 mkdir static_resources 登录后复制 ②将项目中所有的静态资源全部拷贝到该目录下,而后将项目中的静态资源移除重新打包。 ③稍微修改一下 location ~ .*\.(html|htm|gif|jpg|jpeg|bmp|png|ico|txt|js|css){ root /soft/nginx/static_resources; expires 7d; } 登录后复制 然后照常启动 其中 移除后效果动图 最后解读一下那条location规则: location ~ .*\.(html|htm|gif|jpg|jpeg|bmp|png|ico|txt|js|css) 登录后复制
综上所述,简单一句话概述:该配置表示匹配以 「最后提一嘴,也可以将静态资源上传到文件服务器中,然后location中配置一个新的upstream指向。」 Java开发者在线刷题神器 五、Nginx资源压缩建立在动静分离的基础之上,如果一个静态资源的 在 了解了 http{ # 开启压缩机制 gzip on; # 指定会被压缩的文件类型(也可自己配置其他类型) gzip_types text/plain application/javascript text/css application/xml text/javascript image/jpeg image/gif image/png; # 设置压缩级别,越高资源消耗越大,但压缩效果越好 gzip_comp_level 5; # 在头部中添加Vary: Accept-Encoding(建议开启) gzip_vary on; # 处理压缩请求的缓冲区数量和大小 gzip_buffers 16 8k; # 对于不支持压缩功能的客户端请求不开启压缩机制 gzip_disable "MSIE [1-6]\."; # 低版本的IE浏览器不支持压缩 # 设置压缩响应所支持的HTTP最低版本 gzip_http_version 1.1; # 设置触发压缩的最小阈值 gzip_min_length 2k; # 关闭对后端服务器的响应结果进行压缩 gzip_proxied off; } 登录后复制 在上述的压缩配置中,最后一个
OK~,简单修改好了 <script type="text/javascript" src="jquery-3.6.0.js"></script> 登录后复制 分别来对比下压缩前后的区别: 从图中可以很明显看出,未开启压缩机制前访问时, 注意点:①对于图片、视频类型的数据,会默认开启压缩机制,因此一般无需再次开启压缩。②对于 六、Nginx缓冲区先来思考一个问题,接入 其实也就类似电脑的内存跟不上
具体的 http{ proxy_connect_timeout 10; proxy_read_timeout 120; proxy_send_timeout 10; proxy_buffering on; client_body_buffer_size 512k; proxy_buffers 4 64k; proxy_buffer_size 16k; proxy_busy_buffers_size 128k; proxy_temp_file_write_size 128k; proxy_temp_path /soft/nginx/temp_buffer; } 登录后复制 上述的缓冲区参数,是基于每个请求分配的空间,而并不是所有请求的共享空间。当然,具体的参数值还需要根据业务去决定,要综合考虑机器的内存以及每个请求的平均数据大小。 最后提一嘴:使用缓冲也可以减少即时传输带来的带宽消耗。 七、Nginx缓存机制对于性能优化而言,缓存是一种能够大幅度提升性能的方案,因此几乎可以在各处都能看见缓存,如客户端缓存、代理缓存、服务器缓存等等,
那么在 「proxy_cache_path」:代理缓存的路径。 语法: proxy_cache_path path [levels=levels] [use_temp_path=on|off] keys_zone=name:size [inactive=time] [max_size=size] [manager_files=number] [manager_sleep=time] [manager_threshold=time] [loader_files=number] [loader_sleep=time] [loader_threshold=time] [purger=on|off] [purger_files=number] [purger_sleep=time] [purger_threshold=time]; 登录后复制 是的,你没有看错,就是这么长....,解释一下每个参数项的含义:
「proxy_cache」:开启或关闭代理缓存,开启时需要指定一个共享内存区域。 语法: proxy_cache zone | off; 登录后复制 zone为内存区域的名称,即上面中keys_zone设置的名称。 「proxy_cache_key」:定义如何生成缓存的键。 语法: proxy_cache_key string; 登录后复制 string为生成Key的规则,如 「proxy_cache_valid」:缓存生效的状态码与过期时间。 语法: proxy_cache_valid [code ...] time; 登录后复制 code为状态码,time为有效时间,可以根据状态码设置不同的缓存时间。 例如: 「proxy_cache_min_uses」:设置资源被请求多少次后被缓存。 语法: proxy_cache_min_uses number; 登录后复制 number为次数,默认为1。 「proxy_cache_use_stale」:当后端出现异常时,是否允许Nginx返回缓存作为响应。 语法: proxy_cache_use_stale error; 登录后复制 error为错误类型,可配置 「proxy_cache_lock」:对于相同的请求,是否开启锁机制,只允许一个请求发往后端。 语法: proxy_cache_lock on | off; 登录后复制 「proxy_cache_lock_timeout」:配置锁超时机制,超出规定时间后会释放请求。 proxy_cache_lock_timeout time; 登录后复制 「proxy_cache_methods」:设置对于那些HTTP方法开启缓存。 语法: proxy_cache_methods method; 登录后复制 method为请求方法类型,如GET、HEAD等。 「proxy_no_cache」:定义不存储缓存的条件,符合时不会保存。 语法: proxy_no_cache string...; 登录后复制 string为条件,例如 「proxy_cache_bypass」:定义不读取缓存的条件,符合时不会从缓存中读取。 语法: proxy_cache_bypass string...; 登录后复制 和上面 「add_header」:往响应头中添加字段信息。 语法: add_header fieldName fieldValue; 登录后复制 「$upstream_cache_status」:记录了缓存是否命中的信息,存在多种情况:
OK~,对于 http{ # 设置缓存的目录,并且内存中缓存区名为hot_cache,大小为128m, # 三天未被访问过的缓存自动清楚,磁盘中缓存的最大容量为2GB。 proxy_cache_path /soft/nginx/cache levels=1:2 keys_zone=hot_cache:128m inactive=3d max_size=2g; server{ location / { # 使用名为nginx_cache的缓存空间 proxy_cache hot_cache; # 对于200、206、304、301、302状态码的数据缓存1天 proxy_cache_valid 200 206 304 301 302 1d; # 对于其他状态的数据缓存30分钟 proxy_cache_valid any 30m; # 定义生成缓存键的规则(请求的url+参数作为key) proxy_cache_key $host$uri$is_args$args; # 资源至少被重复访问三次后再加入缓存 proxy_cache_min_uses 3; # 出现重复请求时,只让一个去后端读数据,其他的从缓存中读取 proxy_cache_lock on; # 上面的锁超时时间为3s,超过3s未获取数据,其他请求直接去后端 proxy_cache_lock_timeout 3s; # 对于请求参数或cookie中声明了不缓存的数据,不再加入缓存 proxy_no_cache $cookie_nocache $arg_nocache $arg_comment; # 在响应头中添加一个缓存是否命中的状态(便于调试) add_header Cache-status $upstream_cache_status; } } } 登录后复制 接着来看一下效果,如下: 第一次访问时,因为还没有请求过资源,所以缓存中没有数据,因此没有命中缓存。第二、三次,依旧没有命中缓存,直至第四次时才显示命中,这是为什么呢?因为在前面的缓存配置中,我们配置了加入缓存的最低条件为:「「资源至少要被请求三次以上才会加入缓存。」」 这样可以避免很多无效缓存占用空间。 缓存清理当缓存过多时,如果不及时清理会导致磁盘空间被“吃光”,因此我们需要一套完善的缓存清理机制去删除缓存,在之前的 不过天无绝人之路,我们可以通过强大的第三方模块 [root@localhost]# mkdir cache_purge && cd cache_purge 登录后复制 ②通过 [root@localhost]# wget https://github.com/FRiCKLE/ngx_cache_purge/archive/2.3.tar.gz [root@localhost]# tar -xvzf 2.3.tar.gz 登录后复制 ③再次去到之前 [root@localhost]# cd /soft/nginx/nginx1.21.6 登录后复制 ④重新构建一次 [root@localhost]# ./configure --prefix=/soft/nginx/ --add-module=/soft/nginx/cache_purge/ngx_cache_purge-2.3/ 登录后复制 ⑤重新根据刚刚构建的 [root@localhost]# make 登录后复制 ⑥删除之前 [root@localhost]# rm -rf /soft/nginx/sbin/nginx 登录后复制 ⑦从生成的 [root@localhost]# cp objs/nginx /soft/nginx/sbin/nginx 登录后复制 至此,第三方缓存清除模块 location ~ /purge(/.*) { # 配置可以执行清除操作的IP(线上可以配置成内网机器) # allow 127.0.0.1; # 代表本机 allow all; # 代表允许任意IP清除缓存 proxy_cache_purge $host$1$is_args$args; } 登录后复制 然后再重启 八、Nginx实现IP黑白名单有时候往往有些需求,可能某些接口只能开放给对应的合作商,或者购买/接入
allow xxx.xxx.xxx.xxx; # 允许指定的IP访问,可以用于实现白名单。 deny xxx.xxx.xxx.xxx; # 禁止指定的IP访问,可以用于实现黑名单。 登录后复制 要同时屏蔽/开放多个 # --------黑名单:BlocksIP.conf--------- deny 192.177.12.222; # 屏蔽192.177.12.222访问 deny 192.177.44.201; # 屏蔽192.177.44.201访问 deny 127.0.0.0/8; # 屏蔽127.0.0.1到127.255.255.254网段中的所有IP访问 # --------白名单:WhiteIP.conf--------- allow 192.177.12.222; # 允许192.177.12.222访问 allow 192.177.44.201; # 允许192.177.44.201访问 allow 127.45.0.0/16; # 允许127.45.0.1到127.45.255.254网段中的所有IP访问 deny all; # 除开上述IP外,其他IP全部禁止访问 登录后复制 分别将要禁止/开放的 http{ # 屏蔽该文件中的所有IP include /soft/nginx/IP/BlocksIP.conf; server{ location xxx { # 某一系列接口只开放给白名单中的IP include /soft/nginx/IP/blockip.conf; } } } 登录后复制 对于文件具体在哪儿导入,这个也并非随意的,如果要整站屏蔽/开放就在 当然,上述只是最简单的 九、Nginx跨域配置跨域问题在之前的单体架构开发中,其实是比较少见的问题,除非是需要接入第三方 跨域问题产生的原因产生跨域问题的主要原因就在于 「同源策略」 ,为了保证用户信息安全,防止恶意网站窃取数据,同源策略是必须的,否则 同源策略主要是指三点相同,「「协议+域名+端口」」 相同的两个请求,则可以被看做是同源的,但如果其中任意一点存在不同,则代表是两个不同源的请求,同源策略会限制了不同源之间的资源交互。 Nginx解决跨域问题弄明白了跨域问题的产生原因,接下来看看 location / { # 允许跨域的请求,可以自定义变量$http_origin,*表示所有 add_header 'Access-Control-Allow-Origin' *; # 允许携带cookie请求 add_header 'Access-Control-Allow-Credentials' 'true'; # 允许跨域请求的方法:GET,POST,OPTIONS,PUT add_header 'Access-Control-Allow-Methods' 'GET,POST,OPTIONS,PUT'; # 允许请求时携带的头部信息,*表示所有 add_header 'Access-Control-Allow-Headers' *; # 允许发送按段获取资源的请求 add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range'; # 一定要有!!!否则Post请求无法进行跨域! # 在发送Post跨域请求前,会以Options方式发送预检请求,服务器接受时才会正式请求 if ($request_method = 'OPTIONS') { add_header 'Access-Control-Max-Age' 1728000; add_header 'Content-Type' 'text/plain; charset=utf-8'; add_header 'Content-Length' 0; # 对于Options方式的请求返回204,表示接受跨域请求 return 204; } } 登录后复制 在 但如果后端是采用分布式架构开发的,有时候RPC调用也需要解决跨域问题,不然也同样会出现无法跨域请求的异常,因此可以在你的后端项目中,通过继承 十、Nginx防盗链设计首先了解一下何谓盗链:「「盗链即是指外部网站引入当前网站的资源对外展示」」 ,来举个简单的例子理解: 好比壁纸网站 那么如果我们自己是这个
valid_referers none | blocked | server_names | string ...; 登录后复制
简单了解语法后,接下来的实现如下: # 在动静分离的location中开启防盗链机制 location ~ .*\.(html|htm|gif|jpg|jpeg|bmp|png|ico|txt|js|css){ # 最后面的值在上线前可配置为允许的域名地址 valid_referers blocked 192.168.12.129; if ($invalid_referer) { # 可以配置成返回一张禁止盗取的图片 # rewrite ^/ http://xx.xx.com/NO.jpg; # 也可直接返回403 return 403; } root /soft/nginx/static_resources; expires 7d; } 登录后复制 根据上述中的内容配置后,就已经通过
十一、Nginx大文件传输配置在某些业务场景中需要传输一些大文件,但大文件传输时往往都会会出现一些 在传输大文件时, 上述配置仅是作为代理层需要配置的,因为最终客户端传输文件还是直接与后端进行交互,这里只是把作为网关层的 十二、Nginx配置SLL证书随着越来越多的网站接入 ①先去CA机构或从云控制台中申请对应的 ②下载数字证书后,完整的文件总共有三个:
③在 ④最后修改一下 # ----------HTTPS配置----------- server { # 监听HTTPS默认的443端口 listen 443; # 配置自己项目的域名 server_name www.xxx.com; # 打开SSL加密传输 ssl on; # 输入域名后,首页文件所在的目录 root html; # 配置首页的文件名 index index.html index.htm index.jsp index.ftl; # 配置自己下载的数字证书 ssl_certificate certificate/xxx.pem; # 配置自己下载的服务器私钥 ssl_certificate_key certificate/xxx.key; # 停止通信时,加密会话的有效期,在该时间段内不需要重新交换密钥 ssl_session_timeout 5m; # TLS握手时,服务器采用的密码套件 ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4; # 服务器支持的TLS版本 ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # 开启由服务器决定采用的密码套件 ssl_prefer_server_ciphers on; location / { .... } } # ---------HTTP请求转HTTPS------------- server { # 监听HTTP默认的80端口 listen 80; # 如果80端口出现访问该域名的请求 server_name www.xxx.com; # 将请求改写为HTTPS(这里写你配置了HTTPS的域名) rewrite ^(.*)$ https://www.xxx.com; } 登录后复制 OK~,根据如上配置了 十三、Nginx的高可用线上如果采用单个节点的方式部署 接下来则会通过
Keepalived+重启脚本+双机热备搭建①首先创建一个对应的目录并下载 [root@localhost]# mkdir /soft/keepalived && cd /soft/keepalived [root@localhost]# wget https://www.keepalived.org/software/keepalived-2.2.4.tar.gz [root@localhost]# tar -zxvf keepalived-2.2.4.tar.gz 登录后复制 ②进入解压后的 [root@localhost]# cd keepalived-2.2.4 [root@localhost]# ./configure --prefix=/soft/keepalived/ [root@localhost]# make && make install 登录后复制 ③进入安装目录的 [root@localhost]# cd /soft/keepalived/etc/keepalived/ [root@localhost]# vi keepalived.conf 登录后复制 ④编辑主机的 global_defs { # 自带的邮件提醒服务,建议用独立的监控或第三方SMTP,也可选择配置邮件发送。 notification_email { root@localhost } notification_email_from root@localhost smtp_server localhost smtp_connect_timeout 30 # 高可用集群主机身份标识(集群中主机身份标识名称不能重复,建议配置成本机IP) router_id 192.168.12.129 } # 定时运行的脚本文件配置 vrrp_script check_nginx_pid_restart { # 之前编写的nginx重启脚本的所在位置 script "/soft/scripts/keepalived/check_nginx_pid_restart.sh" # 每间隔3秒执行一次 interval 3 # 如果脚本中的条件成立,重启一次则权重-20 weight -20 } # 定义虚拟路由,VI_1为虚拟路由的标示符(可自定义名称) vrrp_instance VI_1 { # 当前节点的身份标识:用来决定主从(MASTER为主机,BACKUP为从机) state MASTER # 绑定虚拟IP的网络接口,根据自己的机器的网卡配置 interface ens33 # 虚拟路由的ID号,主从两个节点设置必须一样 virtual_router_id 121 # 填写本机IP mcast_src_ip 192.168.12.129 # 节点权重优先级,主节点要比从节点优先级高 priority 100 # 优先级高的设置nopreempt,解决异常恢复后再次抢占造成的脑裂问题 nopreempt # 组播信息发送间隔,两个节点设置必须一样,默认1s(类似于心跳检测) advert_int 1 authentication { auth_type PASS auth_pass 1111 } # 将track_script块加入instance配置块 track_script { # 执行Nginx监控的脚本 check_nginx_pid_restart } virtual_ipaddress { # 虚拟IP(VIP),也可扩展,可配置多个。 192.168.12.111 } } 登录后复制 ⑤克隆一台之前的虚拟机作为从(备)机,编辑从机的 global_defs { # 自带的邮件提醒服务,建议用独立的监控或第三方SMTP,也可选择配置邮件发送。 notification_email { root@localhost } notification_email_from root@localhost smtp_server localhost smtp_connect_timeout 30 # 高可用集群主机身份标识(集群中主机身份标识名称不能重复,建议配置成本机IP) router_id 192.168.12.130 } # 定时运行的脚本文件配置 vrrp_script check_nginx_pid_restart { # 之前编写的nginx重启脚本的所在位置 script "/soft/scripts/keepalived/check_nginx_pid_restart.sh" # 每间隔3秒执行一次 interval 3 # 如果脚本中的条件成立,重启一次则权重-20 weight -20 } # 定义虚拟路由,VI_1为虚拟路由的标示符(可自定义名称) vrrp_instance VI_1 { # 当前节点的身份标识:用来决定主从(MASTER为主机,BACKUP为从机) state BACKUP # 绑定虚拟IP的网络接口,根据自己的机器的网卡配置 interface ens33 # 虚拟路由的ID号,主从两个节点设置必须一样 virtual_router_id 121 # 填写本机IP mcast_src_ip 192.168.12.130 # 节点权重优先级,主节点要比从节点优先级高 priority 90 # 优先级高的设置nopreempt,解决异常恢复后再次抢占造成的脑裂问题 nopreempt # 组播信息发送间隔,两个节点设置必须一样,默认1s(类似于心跳检测) advert_int 1 authentication { auth_type PASS auth_pass 1111 } # 将track_script块加入instance配置块 track_script { # 执行Nginx监控的脚本 check_nginx_pid_restart } virtual_ipaddress { # 虚拟IP(VIP),也可扩展,可配置多个。 192.168.12.111 } } 登录后复制 ⑥新建 [root@localhost]# mkdir /soft/scripts /soft/scripts/keepalived [root@localhost]# touch /soft/scripts/keepalived/check_nginx_pid_restart.sh [root@localhost]# vi /soft/scripts/keepalived/check_nginx_pid_restart.sh #!/bin/sh # 通过ps指令查询后台的nginx进程数,并将其保存在变量nginx_number中 nginx_number=`ps -C nginx --no-header | wc -l` # 判断后台是否还有Nginx进程在运行 if [ $nginx_number -eq 0 ];then # 如果后台查询不到`Nginx`进程存在,则执行重启指令 /soft/nginx/sbin/nginx -c /soft/nginx/conf/nginx.conf # 重启后等待1s后,再次查询后台进程数 sleep 1 # 如果重启后依旧无法查询到nginx进程 if [ `ps -C nginx --no-header | wc -l` -eq 0 ];then # 将keepalived主机下线,将虚拟IP漂移给从机,从机上线接管Nginx服务 systemctl stop keepalived.service fi fi 登录后复制 ⑦编写的脚本文件需要更改编码格式,并赋予执行权限,否则可能执行失败: [root@localhost]# vi /soft/scripts/keepalived/check_nginx_pid_restart.sh :set fileformat=unix # 在vi命令里面执行,修改编码格式 :set ff # 查看修改后的编码格式 [root@localhost]# chmod +x /soft/scripts/keepalived/check_nginx_pid_restart.sh 登录后复制 ⑧由于安装 [root@localhost]# mkdir /etc/keepalived/ [root@localhost]# cp /soft/keepalived/etc/keepalived/keepalived.conf /etc/keepalived/ [root@localhost]# cp /soft/keepalived/keepalived-2.2.4/keepalived/etc/init.d/keepalived /etc/init.d/ [root@localhost]# cp /soft/keepalived/etc/sysconfig/keepalived /etc/sysconfig/ 登录后复制 ⑨将 [root@localhost]# chkconfig keepalived on [root@localhost]# systemctl daemon-reload [root@localhost]# systemctl enable keepalived.service [root@localhost]# systemctl start keepalived.service 登录后复制 其他命令: systemctl disable keepalived.service # 禁止开机自动启动 systemctl restart keepalived.service # 重启keepalived systemctl stop keepalived.service # 停止keepalived tail -f /var/log/messages # 查看keepalived运行时日志 登录后复制 ⑩最后测试一下 [root@localhost]# ip addr 登录后复制 虚拟IP-VIP 从上图中可以明显看见虚拟 Ping-VIP 外部通过 Nginx高可用性测试经过上述步骤后,
由于前面没有域名的原因,因此最初 sever{ listen 80; # 这里从机器的本地IP改为虚拟IP server_name 192.168.12.111; # 如果这里配置的是域名,那么则将域名的映射配置改为虚拟IP } 登录后复制 最后来实验一下效果: 在上述过程中,首先分别启动了 从这个过程中不难发现, 在上述过程中,我们通过手动关闭 现在再切换到另外一台机器: 此刻我们会发现,在主机 「「最终,利用Keepalived对Nginx做了主从热备之后,无论是遇到线上宕机还是机房断电等各类故障时,都能够确保应用系统能够为用户提供7x24小时服务。」」 十四、Nginx性能优化到这里文章的篇幅较长了,最后再来聊一下关于 优化一:打开长连接配置通常Nginx作为代理服务,负责分发客户端的请求,那么建议开启 upstream xxx { # 长连接数 keepalive 32; # 每个长连接提供的最大请求数 keepalived_requests 100; # 每个长连接没有新的请求时,保持的最长时间 keepalive_timeout 60s; } 登录后复制 优化二、开启零拷贝技术零拷贝这个概念,在大多数性能较为不错的中间件中都有出现,例如 sendfile on; # 开启零拷贝机制 登录后复制 零拷贝读取机制与传统资源读取机制的区别:
从上述这个过程对比,很轻易就能看出两者之间的性能区别。 优化三、开启无延迟或多包共发机制在 tcp_nodelay on; tcp_nopush on; 登录后复制
因此你的项目属于交互性很强的应用,那么可以手动开启 相反,有些项目的业务对数据的实时性要求并不高,追求的则是更高的吞吐,那么则可以开启 当然若一定时间后(一般为
注意:① 优化四、调整Worker工作进程
# 自动根据CPU核心数调整Worker进程数量 worker_processes auto; 登录后复制 工作进程的数量最高开到 同时也可以稍微调整一下每个工作进程能够打开的文件句柄数: # 每个Worker能打开的文件描述符,最少调整至1W以上,负荷较高建议2-3W worker_rlimit_nofile 20000; 登录后复制 操作系统内核( 优化五、开启CPU亲和机制对于并发编程较为熟悉的伙伴都知道,因为进程/线程数往往都会远超出系统CPU的核心数,因为操作系统执行的原理本质上是采用时间片切换机制,也就是一个CPU核心会在多个进程之间不断频繁切换,造成很大的性能损耗。 而CPU亲和机制则是指将每个 worker_cpu_affinity auto; 登录后复制 优化六、开启epoll模型及调整并发连接数在最开始就提到过: events { # 使用epoll网络模型 use epoll; # 调整每个Worker能够处理的连接数上限 worker_connections 10240; } 登录后复制 这里对于 十五、放在最后的结尾至此, |