关于Nginx的所有故事!

一、Nginx

1.1 Nginx概念

Nginx是一个 Web 服务器和反向代理服务器用于 HTTP、HTTPS、SMTP、POP3 和 IMAP协议。因它的稳定性、丰富的功能集、示例配置文件和低系统资源的消耗而闻名。

1.2 工作原理

Nginx 由内核和模块组成。

Nginx 本身做的工作实际很少,当它接到一个 HTTP 请求时, 它仅仅是通过查找配置文件将此次请求映射到一个 location 模块,而此 location 中所配 置的各个指令则会启动不同的模块去完成工作,因此模块可以看做 Nginx 真正的劳动工作者。

通常一个 location 中的指令会涉及一个 handler 模块和多个 filter 模块(当然,多个 location 可以复用同一个模块)。handler 模块负责处理请求,完成响应内容的生成,而 filter 模块对响应内容进行处理。用户根据自己的需要所开发的模块都属于第三方模块。正是有了这么多模块的支撑, Nginx 的功能才会如此强大。

1.3 Nginx模块

vim /etc/nginx/conf.d/default.conf

vim /usr/local/nginx/conf/nginx.conf

nginx模块分为两种,官方和第三方,我们通过命令 nginx -V 查看 nginx已经安装的模块!
如果需要添加某个模块,需要将工作目录切换至nginx的源码包中,执行“nginx -V”命令查看之前配置时的选项进行复制,然后增加需要添加的模块配置项,进行配置并编译,将新生成的nginx命令覆盖掉原有的nginx命令,然后重载nginx服务,即可实现在线添加模块。

[root@localhost ~]# nginx -V

在这里插入图片描述

Nginx模块名称 模块作用
ngx_http_access_module 四层基于IP的访问控制,可以通过匹配客户端源IP地址进行限制
ngx_http_auth_basic_module 状态页,使用basic机制进行用户认证,在编译安装nginx的时候需要添加编译参数–withhttp_stub_status_module,否则配置完成之后监测会是提示语法错误
ngx_http_stub_status_module 状态统计模块
ngx_http_gzip_module 文件的压缩功能
ngx_http_gzip_static_module 静态压缩模块
ngx_http_ssl_module nginx 的https 功能
ngx_http_rewrite_module 实现URL地址重写,URL看起来更规范、合理
ngx_http_referer_module 防盗链功能,基于访问安全考虑
ngx_http_proxy_module 将客户端的请求以http协议转发至指定服务器进行处理
ngx_stream_proxy_module tcp负载,将客户端的请求以tcp协议转发至指定服务器处理
ngx_http_fastcgi_module 将客户端对php的请求以fastcgi协议转发至指定服务器助理
ngx_http_uwsgi_module 将客户端对Python的请求以uwsgi协议转发至指定服务器处理
ngx_http_headers_module 可以实现对头部报文添加指定的key与值
ngx_http_upstream_module 负载均衡模块,提供服务器分组转发、权重分配、状态监测、调度算法等高级功能
ngx_stream_upstream_module 后端服务器分组转发、权重分配、状态监测、调度算法等高级功能
ngx_http_fastcgi_module 实现通过fastcgi协议将指定的客户端请求转发至php-fpm处理
ngx_http_flv_module 为flv伪流媒体服务端提供支持

1、Nginx 的模块从结构上分为核心模块、基础模块和第三方模块

核心模块:HTTP 模块、EVENT 模块和 MAIL 模块;

基础模块:HTTP Access 模块、HTTP FastCGI 模块、HTTP Proxy 模块和 HTTP Rewrite 模块;

第三方模块:HTTP Upstream Request Hash 模块、Notice 模块和 HTTP Access Key 模 块。

2、Nginx 的模块从功能上分为如下三类:

Handlers(处理器模块):此类模块直接处理请求,并进行输出内容和修改 headers 信息等操作。Handlers 处理器模块一般只能有一个; 

Filters(过滤器模块):此类模块主要对其他处理器模块输出的内容进行修改操作,最后由 Nginx 输出;Proxies(代理类模块):此类模块是 Nginx 的 HTTP 

Upstream 之类的模块,这些模块主要与后端一些服务比如 FastCGI 等进行交互,实现服务代理和负载均衡等功能。

1.4 Nginx 的进程模型

在工作方式上,Nginx 分为单工作进程和多工作进程两种模式。

  • 1、在单工作进程模式下,除主进程外,还有一个工作进程,工作进程是单线程的;

  • 2、在多工作进程模式下,每个工作进程包含多个线程。Nginx 默认为单工作进程模式。

Nginx 在启动后,会有一个 master 进程和多个 worker 进程

master 进程主要用来管理 worker 进程,主要包含:接收来自外界的信号,向各 worker 进程发送信号,监控 worker进程的运行状态,当 worker 进程退出后(异常情况下),会自动 重新启动新的 worker 进程master进程充当整个进程组与用户的交互接口,同时对进程进行监护。它不需要处理网络事件,不负责业务的执行,只会通过管理worker
进程来实现重启服务、平滑升级、更换日志文件、配置文件实时生效等功能。

二、Nginx优缺点

2.1 优点

跨平台、配置简单。

非阻塞、高并发连接

处理 2-3 万并发连接数,官方监测能支持 5 万并发。

内存消耗小

开启 10 个 Nginx 才占 150M 内存

成本低廉,且开源。

稳定性高,宕机的概率非常小。

2.2 Nginx主要功能

  • 1)正向、反向代理

  • 2)负载均衡、分流

  • 3)充当一个虚拟主机(绑定host)

1、工作在网络的7层之上,可以针对http应用做一些分流的策略,比如针对域名、目录结构,它的正则规则比HAProxy更为强大和灵活,这也是它目前广泛流行的主要原因之一,Nginx单凭这点可利用的场合就远多于LVS了。

2、Nginx对网络稳定性的依赖非常小,理论上能ping通就就能进行负载功能,这个也是它的优势之一

3、Nginx安装和配置比较简单,测试起来比较方便,它基本能把错误用日志打印出来。

4、可以承担高负载压力且稳定,在硬件不差的情况下一般`能支撑几万次的并发量,负载度较小`    (比LVS)

5、Nginx可以`通过端口检测到服务器内部的故障`,比如根据服务器处理网页返回的状态码、超时等等,并且会把返回错误的请求重新提交到另一个节点,不过其中缺点就是`不支持url来检测`。比如用户正在上传一个文件,而处理该上传的节点刚好在上传过程中出现故障,Nginx会把上传切到另一台服务器重新处理。

6、Nginx不仅仅是一款优秀的负载均衡器/反向代理软件,它同时也是功能强大的Web应用服务器。LNMP也是近几年非常流行的web架构,在高流量的环境中稳定性也很好。

7、Nginx现在作为Web反向加速缓存越来越成熟了,速度比传统的Squid服务器更快,可以用作为反向代理加速器。

8、Nginx可作为中层反向代理使用,这一层面Nginx基本上无对手,唯一可以对比Nginx的就只有 lighttpd了,不过 lighttpd目前还没有做到Nginx完全的功能,配置也不那么清晰易读,社区资料也远远没Nginx活跃。

9、Nginx也可作为`静态网页和图片服务器`,这方面的性能也无对手。还有Nginx社区非常活跃,第三方模块也很多。

2.3 缺点

Nginx的缺点是:

Nginx仅能支持http、https和Email协议,这样就在适用范围上面小些,这个是它的缺点。
对后端服务器的健康检查,只支持通过端口来检测,不支持通过url来检测。不支持Session的直接保持,但能通过ip_hash来解决。

2.4 正向代理与反向代理的区别

2.4.1 正向代理

是一个位于客户端和目标服务器之间的服务器,为了从目标服务器取得内容,客户端向代理发送一个请求并指定目标服务器,然后代理向目标服务器转交请求并将获得的内容返回给客户端。代理服务器和客户端处于同一个局域网内。

比如说我要访问谷歌,于是我就告诉它让它帮我转发。

2.4.2 反向代理

实际运行方式是代理服务器接受网络上的连接请求。它将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给网络上请求连接的客户端 。代理服务器和目标服务器处于同一个局域网内。

比如说我要访问taobao,对我来说不知道图片、json、css 是不是同一个服务器返回回来的,但是我不关心,是反向代理 处理的,我不知道目标服务器。

反向代理置:vim /usr/local/nginx/conf/nginx.conf

在这里插入图片描述

2.5 Nginx如何处理HTTP请求的?

它结合多进程机制(单线程)和异步非阻塞方式。

1)多进程机制(单线程)

服务器每当收到一个客户端时,就有 服务器主进程 ( master process )生成一个 子进程( worker process )出来和客户端建立连接进行交互,直到连接断开,该子进程就结束了。

2)异步非阻塞机制

每个工作进程 使用 异步非阻塞方式 ,可以处理 多个客户端请求 。 运用了epoll模型,提供了一个队列,排队解决。

当某个 工作进程 接收到客户端的请求以后,调用 IO 进行处理,如果不能立即得到结果,就去 处理其他请求 (即为 非阻塞 );而 客户端 在此期间也 无需等待响应 ,可以去处理其他事情(即为 异步 )。

当 IO 返回时,就会通知此 工作进程 ;该进程得到通知,暂时 挂起 当前处理的事务去 响应客户端请求。

2.6 Nginx的master和worker

这跟Nginx的多进程、单线程有关。(一个进程只有一个主线程)。

为什么要用单线程?

采用单线程来异步非阻塞处理请求(管理员可以配置Nginx主进程的工作进程的数量),不会为每个请求分配cpu和内存资源,节省了大量资源,同时也减少了大量的CPU的上下文切换,所以才使得Nginx支持更高的并发。

简单过程:

主程序 Master process 启动后,通过一个 for 循环来 接收 和 处理外部信号 ;

主进程通过 fork() 函数产生 worker 子进程 ,每个子进程执行一个 for循环来实现Nginx服务器对事件的接收和处理 。

详细过程:

1、Nginx 在启动后,会有一个 master 进程和多个相互独立的 worker 进程。
2、master 接收来自外界的信号,先建立好需要 listen 的 socket(listenfd) 之后,然后再 fork 出多个 worker进程,然后向各worker进程发送信号,每个进程都有可能来处理这个连接。
3、所有 worker 进程的 listenfd会在新连接到来时变得可读 ,为保证只有一个进程处理该连接,所有 worker 进程在注册 listenfd 读事件前抢占accept_mutex ,抢到互斥锁的那个进程注册 listenfd 读事件 ,在读事件里调用 accept 接受该连接。
4、当一个 worker 进程在 accept 这个连接之后,就开始读取请求、解析请求、处理请求,产生数据后,再返回给客户端
,最后才断开连接。

2.7 Nginx常用命令

启动 nginx 。

停止 nginx -s stop 或 nginx -s quit 。

重启 nginx -s reload 或 service nginx reload 。

重载指定配置文件 .nginx -c /usr/local/nginx/conf/nginx.conf 。

查看 nginx 版本 nginx -v 。

2.8 Nginx动静态资源分离

动态资源、静态资源分离,是让动态网站里的动态网页根据一定规则把不变的资源和经常变的资源区分开来

比如说 js、css、hrml从A服务器返回。图片 从B服务器返回,其他请求从Tomcat服务器C返回。

后台应用分开部署,提高用户访问静态代码的速度。而且现在还有CDN服务,不需要限制于服务器的带宽。

2.9 nginx是如何实现高并发的?

nginx之所以可以实现高并发,与它采用的epoll模型有很大的关系。epoll模型采用异步非阻塞的事件处理机制。这种机制可让nginx进程同时监控多个事件。

简单来说,就是异步非阻塞,使用了epoll模型和大量的底层代码优化。如果深入一点的话,就是nginx的特殊进程模型和事件模型的设计,才使其可以实现高并发。

1.进程模型

它是采用一个master进程和多个worker进程的工作模式。
1、master进程主要负责收集、分发请求。当一个请求过来时,master拉起一个worker进程负责处理这个请求。;
2、master进程也要负责监控worker的状态,保证高可靠性;
3、worker进程议案设置为和CPU核心数一致或者其二倍。nginx的worker进程和Apache的不一样。apache的进程在同一时间只能处理一个请求,所以它会开启很多个进程,几百甚至几千个。而nginx的worker进程在同一时间可以处理的请求数只受内存限制,因此可以处理更多请求。

2.事件模型
nginx是异步非阻塞的。

一个master进程,多个worker进程,每个worker进程可以处理多个请求。每进来一个request,都会有worker进程去处理。但不是全程的处理,那么处理到的程度就是可能发生阻塞的地方,比如向后端服务器转发request,并等待请求返回。那么,在等待期间,这个处理的worker不会这么傻等着,他会在发送完请求后,注册一个事件:“如果upstream返回了,告诉我一声,我再接着干”。于是它就去休息了,此时,如果再有request进来,它就可以很快再按这种方式处理。而一旦后端服务器返回了,就会触发这个事件,worker才会来接手,这个request才会接着往下走。
由于nginx的的这个工作性质决定了每个请求大部分的生命都是在网络传输中,所以实际上花费在nginx服务器上的时间并不多,这就是它几进程就能解决高并发的秘密所在。

三、Nginx优化

配置nginx的proxy缓存;

对静态页面开启压缩功能,如br压缩或者gzip压缩;

调整nginx运行工作进程个数,最多开启8个,8个以上话性能就不会再提升了,而且稳定性变得更低,所以8个足够用了;

调整nginx运行CPU的亲和力;

修改nginx最多可打开的文件数,若超过系统限制的最多打开文件数(ulimit -n命令查看系统的最多打开文件数),还需要修改系统默认的文件数;

修改单个worker的最大连接数;

开启高效传输;

设置连接超时时间,以便保护服务器资源,因为建立连接也是需要消耗资源的;

优化fastCGI的一个超时时间,也可以根据实际情况对其配置缓存动态页面;

expires缓存调优,主要针对图片、css、js等元素更改较少的情况下使用。

配置防盗链;

优化内核参数,如进程可以同时打开的最大句柄数;开启tcp重用机制,以便允许TIME_WAIT sockets重新用于新的TCP连接....

1、隐藏版本号

隐藏Nginx版本号有两种方式:

第一种是修改Nginx源码文件,指定不显示版本号

第二种是修改Nginx的主配置文件

[root@localhost ~]# curl -I http://20.0.0.6   ### 查看网站版本号
HTTP/1.1 200 OK    
Server: nginx/1.15.9                 ### 版本号
Date: Sun, 06 Sep 2020 05:52:47 GMT

1)修改配置文件方式

将Nginx的配置文件中的server_tokens选项值设置为off,如果有该配置项,加上即可

[root@localhost ~]# vim /usr/local/nginx/conf/nginx.conf
http {                                         
    include       mime.types;
    default_type  application/octet-stream;
    server_tokens off;        ###此处新增代码,含义是将版本号关闭  
    
[root@localhost ~]# nginx -t  ### 检查配置是否正常
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful

[root@localhost ~]# systemctl restart nginx.service  ### 重启服务

测试:然后用Wireshark抓包软件抓包测试一下,版本号还能看到吗

法二:

2)设置版本信息

Nginx源码文件/opt/nginx-1.15.9/src/core/nginx.h包含了版本信息,可以随意设置,然后重新编译安装,隐藏版本信息。

[root@localhost ~]# vim /opt/nginx-1.15.9/src/core/nginx.h 
#define NGINX_VERSION      "1.1.1"   ### 修改版本号
#define NGINX_VER          "IIS" NGINX_VERSION   ### 修改服务器类型
[root@localhost ~]# cd /opt/nginx-1.15.9/
[root@localhost nginx-1.15.9]# 
./configure \
--prefix=/usr/local/nginx \
--user=nginx \
--group=nginx \
--with-http_stub_status_module

[root@localhost nginx-1.15.9]# make -j3 && make install

[root@localhost nginx-1.15.9]# cd /usr/local/nginx/conf/

[root@localhost conf]# vi nginx.conf
http {
    include       mime.types;
    default_type  application/octet-stream;
    server_tokens on;   ### 打开版本号
[root@localhost conf]# systemctl restart nginx.service ###重启

[root@localhost conf]# curl -I http://20.0.0.6

HTTP/1.1 200 OK
Server: IIS 1.1.1       ### 版本号和服务器类型已经更改
Date: Sun, 06 Sep 2020 06:34:21 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Sun, 06 Sep 2020 06:14:14 GMT
Connection: keep-alive
ETag: "5f547e36-264"
Accept-Ranges: bytes

2、修改用户与组

1)指定用户与组参数

configure编译过程中指定用户和组参数为nginx

[root@localhost ~]# cd /opt/nginx-1.15.9/

[root@localhost nginx-1.15.9]# ./configure \
--prefix=/usr/local/nginx \
--user=nginx \
--group=nginx \
--with-http_stub_status_module

2)配置用户与组

修改Nginx配置文件的Nginx指定用户与组

[root@localhost opt]# cd /usr/local/nginx/conf/

[root@localhost conf]# vi nginx.conf
user  nginx nginx;         ### 修改用户为nginx,组为nginx

[root@localhost conf]# systemctl restart nginx

[root@localhost conf]# ps aux |grep nginx
root      23044  0.0  0.0  20560   628 ?        Ss   02:40   0:00 nginx: master process /usr/local/nginx/sbin/nginx
nginx     23045  0.0  0.0  23100  1396 ?        S    02:40   0:00 nginx: worker process
root      23059  0.0  0.0 112708   976 pts/0    S+   02:41   0:00 grep --color=auto nginx

重启Nginx查看进程运行情况,主进程由root账户创建,子进程由Nginx创建。

3、配置网页缓存时间

1、以图片作为缓存对象,上传51xit.jpg图片到/usr/local/nginx/html的工作目录,访问http://20.0.0.6/51xit.jpg,用wireshark工具进行抓包,查看响应报文,没有图片的缓存信息查看报文没有缓存信息

2、修改Nginx的配置文件,在新location段加入expires参数,指定缓存的时间1d一天

[root@localhost ~]# vi /usr/local/nginx/conf/nginx.conf
        location ~ \.(gif|jpg|jepg|png|bmp|ico)$ {
         root html;
         expires 1d;  ### 指定缓存时间1天
        }

3、重启Nginx服务,访问wireshark抓包

[root@localhost ~]# systemctl restart nginx ### 重启nginx服务

测试:在/usr/local/nginx/html里面添加一张51xit.jpg图片,然后wireshark抓包查看一下缓存时间对不对

4、日志分割

日志切割 随着Nginx运行时间的增加, 产生的日志也会逐渐增加,为了方便掌握Nginx的运行 状态, 需要时刻关注Nginx日志文件。太大的日志文件对监控是一个大灾难,不便于分析排查,需要定期的进行日志文件的切割。

##编写脚本/opt/feng e.sh##

把Nginx的日志文件/usr/local/nginx/logs/access.log移动到, 目录/var/log/ng in x下面, 以当前时间做为日志文件的名称, 然后用kill-USR1创建新的日志文件/usr/local/nginx/logs/access.log, 最后删除30天之前的日志文件。

[root@localhost ~]# vi /opt/fenge.sh
#!/bin/bash
# Filename: fenge.sh
d=$(date -d "-1 day" "+%Y%m%d")
logs_path="/var/log/nginx"
pid_path="/usr/local/nginx/logs/nginx.pid"
[ -d $logs_path ] || mkdir -p $logs_path
mv /usr/local/nginx/logs/access.log ${logs_path}/test.com-access.log-$d
kill -USR1 $(cat $pid_path)
find $logs_path -mtime +30 |xargs rm -rf

---------------上面解释----------------------------------------------------------------

#!/bin/bash
# Filename: fenge.sh
d=$(date -d "-1 day" "+%Y%m%d")
logs_path="/var/log/nginx"                        ###分割到nginx目录去
pid_path="/usr/local/nginx/logs/nginx.pid"       ###重新生成新的日志文件
[ -d $logs_path ] || mkdir -p $logs_path       ###如果没有nginx目录就会创建
mv /usr/local/nginx/logs/access.log ${logs_path}/test.com-access.log-$d   ###把原有路径的日志文件移出来,改成那天的日期名字
kill -USR1 $(cat $pid_path)                            ###结束当时的进程,生成一个新pid,然后生成新的日志文件
find $logs_path -mtime +30 |xargs rm -rf    ###找到30天之前的删除掉

------------------------------------------------------------------------------------------

[root@localhost ~]# chmod +x /opt/fenge.sh  ###给执行权限

[root@localhost opt]# ./fenge.sh           ### 执行分割脚本

[root@localhost opt]# ls /var/log/nginx/
test.com-access.lo  test.com-access.log-20200905     ###按日期分割了日志文件

[root@localhost opt]# cat /usr/local/nginx/logs/access.log   ###原来的位置文件重新创建

########设置crotab任务,定期执行脚本自动进行日志分割#########
[root@localhost opt]# crontab -e
30 1 * * * /opt/fenge.sh

5、设置连接超时

在企业网站中,为了避免同一个客户长时间占用连接,造成资源浪费,可设置相应的连 接超时参数, 实现控制连接访问时间。可以修改配置文件nginx.conf, 设置keepalive_timeout 超时时间。

[root@localhost opt]# vi /usr/local/nginx/conf/nginx.conf
    keepalive_timeout  65 180;  ### 默认65秒,设置超时180秒
    client_header_timeout 80;
    client_body_timeout 80;

[root@localhost opt]# systemctl restart nginx  ###重启nginx服务

测试:浏览器输入20.0.0.6,然后wireshark抓包查看一下连接超时时间

##########深入优化##############

6、更改进程数

在高并发环境中,需要启动更多的Nginx进程以保证快速响应,用以处理用户的请求,避免造成阻塞。使用ps aux命令查看Nginx运行进程的个数。

[root@localhost ~]# ps aux |grep nginx
root      76128  0.0  0.0  20560   628 ?        Ss   03:26   0:00 nginx: master process /usr/local/nginx/sbin/nginx
nginx     76129  0.0  0.0  23100  1652 ?        S    03:26   0:00 nginx: worker process
root      76201  0.0  0.0 112708   972 pts/0    S+   03:33   0:00 grep --color=auto nginx

其中master是Nginx的主进程,开启了1个,worker 是子进程,进程也是开启了1个。

修改Nginx的配置文件的worker_processes参数, 一般设为CPU的个数或者核数, 在高并发的情况下可设置为CPU个数或者核数的2倍, 可以查看CPU的核数以确定参数

[root@localhost ~]# cat /proc/cpuinfo |grep -c "physical"  ###查看CPU的核数以确定参数。

8

[root@localhost ~]# vi /usr/local/nginx/conf/nginx.conf

worker_processes  8;   ###根据刚刚查的核数,把数字改成8.

修改完后,重启服务,使用ps aux查看运行进程数的变化情况。

[root@localhost ~]# ps aux|grep nginx  ### 可以看到现在是8个进程

root      76329  0.0  0.0  20560   700 ?        Ss   03:40   0:00 nginx: master process /usr/local/nginx/sbin/nginx

nginx     76330  0.0  0.0  23100  1404 ?        S    03:40   0:00 nginx: worker process

nginx     76331  0.0  0.0  23100  1404 ?        S    03:40   0:00 nginx: worker process

nginx     76332  0.0  0.0  23100  1404 ?        S    03:40   0:00 nginx: worker process

nginx     76333  0.0  0.0  23100  1404 ?        S    03:40   0:00 nginx: worker process

nginx     76334  0.0  0.0  23100  1404 ?        S    03:40   0:00 nginx: worker process

nginx     76335  0.0  0.0  23100  1404 ?        S    03:40   0:00 nginx: worker process

nginx     76336  0.0  0.0  23100  1404 ?        S    03:40   0:00 nginx: worker process

nginx     76337  0.0  0.0  23100  1404 ?        S    03:40   0:00 n

7、配置网页压缩

[root@localhost ~]# vi /usr/local/nginx/conf/nginx.conf

    gzip  on;

    gzip_buffers 4 64k;

    gzip_http_version 1.1;

    gzip_comp_level 2;

    gzip_min_length 1k;

    gzip_vary on;

    gzip_types text/plain text/javascript application/x-javascript text/css text/xml application/xml application/xml+rss;

###上面的配置解释###

gzip on:开启gzip压缩输出; 

gzip_min_length 1k:用于设置允许压缩的页面最小字节数;

gzip_buffers 416k:表示申请4个单位为16k的内存作为压缩结果流缓存,默认值 是申请与原始数据大小相同的内存空间来存储gzip压缩结果; 

Zip_http_version 1.0:用于设置识别http协议版本, 默认是1.1,目前大部分浏览 器已经支持gzip解压,但处理最慢,也比较消耗服务器CPU资源; 

Gzip_comp_level 2:用来指定gzip压缩比, 1压缩比最小, 处理速度最快; 9压缩 比最大,传输速度快,但处理速度最慢,使用默认即可;

Gzip_types text/plain:压缩类型, 是对哪些网页文档启用压缩功能;

Gzip_vary on:选项可以让前端的缓存服务器缓存经过gzip压缩的页面
[root@localhost ~]# vi /usr/local/nginx/html/index.html 
 <h1>xxxxxx</h1>  ###在这里面随便加东西,让index.html大于1k就行

测试:浏览器输入20.0.0.6/index.html,然后wireshark抓包查看一下压缩情况。

8、配置防盗链

\###防盗链需要准备两台主机模拟盗链###

20.0.0.6   www.51xit.top    源主机

20.0.0.5   www.52xit.top    盗链主机

### 修改windows的 C:\Windows\System32\drivers\etc\host文件,设置域名和映射关系

20.0.0.6 www.51xit.top

20.0.0.5 www.52xit.top

###在盗链主机的工作目录编写盗链页面index.html,即盗源主机的图片###

[root@localhost ~]# cd /usr/local/httpd/htdocs/

[root@localhost htdocs]# vi index.html 
<html>
<head>
<title>--盗图测试--</title>
</head>
<body><h1>盗图页面</h1>
<img src=http://20.0.0.6/51xit.jpg />
</body>
</html>

测试:浏览器输入20.0.0.5,查看能不能正常盗链

###在主机配置Nginx防盗链###

[root@localhost ~]# cd /usr/local/nginx/conf/

[root@localhost conf]# vi nginx.conf
        location ~* \.(gif|jpg|jepg|png|bmp|ico)$ {
         valid_referers none blocked *.51xit.top 51xit.top;
         if ($invalid_referer) {
           rewrite ^/ https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=202451072,4165552475&fm=26&gp=0.jpg;
        }
}

[root@localhost conf]# systemctl restart nginx

测试:浏览器输入20.0.0.5,查看能不能防止盗链!!!

9、FPM参数优化

####################安装PHP环境#####

yum -y install \
libjpeg \
libjpeg-devel \
libpng libpng-devel \
freetype freetype-devel \
libxml2 \
libxml2-devel \
zlib zlib-devel \
curl curl-devel \
openssl openssl-devel

#######上传php-7.1.10.tar.bz2包到opt目录下#####

cd /opt
tar xjvf php-7.1.10.tar.bz2
cd php-7.1.10
./configure \
--prefix=/usr/local/php \
--with-apxs2=/usr/local/httpd/bin/apxs \
--with-mysql-sock=/usr/local/mysql/mysql.sock \
--with-mysqli \
--with-zlib \
--with-curl \
--with-gd \
--with-jpeg-dir \
--with-png-dir \
--with-freetype-dir \
--with-openssl \
--enable-mbstring \
--enable-xml \
--enable-session \
--enable-ftp \
--enable-pdo \
--enable-tokenizer \
--enable-zip
make -j3 && make install

cp php.ini-development /usr/local/php/lib/php.ini

vi /usr/local/php/lib/php.ini

mysqli.default_socket = /usr/local/mysql/mysql.sock

date.timezone = Asia/Shanghai

[root@localhost php-7.1.10]# /usr/local/php/bin/php -m //验证安装的模块

[root@localhost php-7.1.10]# vi /etc/httpd.conf //在合适位置新增

AddType application/x-httpd-php .php    ###添加
AddType application/x-httpd-php-source .phps   ###添加
<IfModule dir_module> 
    DirectoryIndex index.php index.html  ###找到这个添加
</IfModule>

[root@localhost php-7.1.10]# rm -f /usr/local/httpd/htdocs/index.html ###删除

[root@localhost php-7.1.10]#  vi /usr/local/httpd/htdocs/index.php  ###创建新的
<?php
phpinfo();
?>

[root@localhost php-7.1.10]# systemctl restart httpd.service
测试:20.0.0.6

#####FPM参数优化###

[root@localhost php-7.1.10]# cd /usr/local/php/etc/php-fpm.d

[root@localhost etc]# vi www.conf
pm=dynamic
pm.max_children=20
pm.start_servers=5
pm.min_spare_servers=2
pm.max_spare_servers=8

FPM启动时有5个进程,最小空闲2个进程,最大空闲8个进程,最多可以有20个进程存在。

一、pm.max_children多大合适?

这个值原则上是越大越好, php-cgi的进程多了就会处理的很快, 排队的请求就会很少。

设置”max children”也需要根据服务器的性能进行设定。

计算方式如下:

一般来说一台服务器正常情况下每一个php-cgi所耗费的内存在20M~30M左右, 因此我的”max_children”我设置成40个,

20M*40=800M也就是说在峰值的时候所有PHP-CGI所耗内存在800M以内, 低于我的有效内存2Gb。

而如果我的”max_children”设置的较小, 比如5-10个, 那么php-cgi就会“很累“, 处理速度也很慢, 等待的时间也较长,占用的CPU也很高。

如果长时间没有得到处理的请求就会出现504 Gateway Time-out这个错误, 而正在处理的很累的那几个php-cgi如果遇到了问题就会出现502Bad gateway这个错误。

max_children较好的设置方式根据req/s(吞吐率, 单位时间里服务器处理的最大请求数, 单位req/s) 来设置, 若程序是100D req/s的处理能力, 那么就设置100比较好, 这是动态来调整的。

10、内核优化

默认的Linux内核参数考虑的是最通用的场景,不符合用于支持高并发访问的Web服务器的定义,所以需要修改Linux内核参数,使得Nginx可以拥有更高的性能。

内核优化基本上会根据业务特点来进行调整,当Nginx作为静态Web内容服务器、反向代理服务器或是提供图片缩略功能(实时压缩图片)的服务器时,其内核参数的调整都是不同的。这里只针对最通用的、使Nginx支持更多并发请求的TCP网络参数做简单说明。

首先,需要修改/etc/sysctl.conf来更改内核参数

net.ipv4.tcp_max_tw_buckets = 6000   timewait 的数量,默认是180000。

net.ipv4.ip_local_port_range = 1024 65000   允许系统打开的端口范围。

net.ipv4.tcp_tw_recycle = 1   启用timewait 快速回收。

net.ipv4.tcp_tw_reuse = 1   开启重用。允许将TIME-WAIT sockets 重新用于新的TCP 连接。

net.ipv4.tcp_syncookies = 1   开启SYN Cookies,当出现SYN 等待队列溢出时,启用cookies 来处理。

net.core.somaxconn = 262144web   应用中listen 函数的backlog 默认会给我们内核参数的net.core.somaxconn 限制到128,而nginx 定义的NGX_LISTEN_BACKLOG 默认为511,所以有必要调整这个值。

net.core.netdev_max_backlog = 262144   每个网络接口接收数据包的速率比内核处理这些包的速率快时,允许送到队列的数据包的最大数目。

net.ipv4.tcp_max_orphans = 262144   系统中最多有多少个TCP 套接字不被关联到任何一个用户文件句柄上。如果超过这个数字,孤儿连接将即刻被复位并打印出警告信息。这个限制仅仅是为了防止简单的DoS 攻击,不能过分依靠它或者人为地减小这个值,更应该增加这个值(如果增加了内存之后)。

net.ipv4.tcp_max_syn_backlog = 262144   记录的那些尚未收到客户端确认信息的连接请求的最大值。对于有128M 内存的系统而言,缺省值是1024,小内存的系统则是128。

net.ipv4.tcp_timestamps = 0   时间戳可以避免序列号的卷绕。一个1Gbps 的链路肯定会遇到以前用过的序列号。时间戳能够让内核接受这种“异常”的数据包。这里需要将其关掉。

net.ipv4.tcp_synack_retries = 1   为了打开对端的连接,内核需要发送一个SYN 并附带一个回应前面一个SYN 的ACK。也就是所谓三次握手中的第二次握手。这个设置决定了内核放弃连接之前发送SYN+ACK 包的数量。

net.ipv4.tcp_syn_retries = 1   在内核放弃建立连接之前发送SYN 包的数量。

net.ipv4.tcp_fin_timeout = 1   如果套接字由本端要求关闭,这个参数决定了它保持在FIN-WAIT-2 状态的时间。对端可以出错并永远不关闭连接,甚至意外当机。缺省值是60 秒。2.2 内核的通常值是180 秒,3你可以按这个设置,但要记住的是,即使你的机器是一个轻载的WEB 服务器,也有因为大量的死套接字而内存溢出的风险,FIN- WAIT-2 的危险性比FIN-WAIT-1 要小,因为它最多只能吃掉1.5K 内存,但是它们的生存期长些。

net.ipv4.tcp_keepalive_time = 30   当keepalive 起用的时候,TCP 发送keepalive 消息的频度。缺省是2 小时。

下面贴一个完整的内核优化设置:

vi /etc/sysctl.conf CentOS5.5中可以将所有内容清空直接替换为如下内容:

net.ipv4.ip_forward = 0
net.ipv4.conf.default.rp_filter = 1
net.ipv4.conf.default.accept_source_route = 0
kernel.sysrq = 0
kernel.core_uses_pid = 1
net.ipv4.tcp_syncookies = 1
kernel.msgmnb = 65536
kernel.msgmax = 65536
kernel.shmmax = 68719476736
kernel.shmall = 4294967296
net.ipv4.tcp_max_tw_buckets = 6000
net.ipv4.tcp_sack = 1
net.ipv4.tcp_window_scaling = 1
net.ipv4.tcp_rmem = 4096 87380 4194304
net.ipv4.tcp_wmem = 4096 16384 4194304
net.core.wmem_default = 8388608
net.core.rmem_default = 8388608
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.core.netdev_max_backlog = 262144
net.core.somaxconn = 262144
net.ipv4.tcp_max_orphans = 3276800
net.ipv4.tcp_max_syn_backlog = 262144
net.ipv4.tcp_timestamps = 0
net.ipv4.tcp_synack_retries = 1
net.ipv4.tcp_syn_retries = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_mem = 94500000 915000000 927000000
net.ipv4.tcp_fin_timeout = 1
net.ipv4.tcp_keepalive_time = 30
net.ipv4.ip_local_port_range = 1024 65000

使配置立即生效可使用如下命令: /sbin/sysctl -p

四、Nginx负载均衡

1、四层和七层

1)四层负载
四层就是基于IP+端口的负载均衡,通过虚拟IP+端口接收请求,然后再分配到真实的服务器;

2)七层负载
七层就是基于URL等应用层信息的负载均衡,通过虚拟的URL或主机名接收请求,然后再分配到真实的服务器。

3)二层、三层负载
基于MAC地址的二层负载均衡:二层负载均衡会通过一个虚拟MAC地址接收请求,然后再分配到真实的MAC地址;
基于IP地址的三层负载均衡:三层负载均衡会通过一个虚拟IP地址接收请求,然后再分配到真实的IP地址;

2、热备

如果你有2台服务器,当一台服务器发生事故时,才启用第二台服务器给提供服务。服务器处理请求的顺序:AAAAAA突然A挂啦,BBBBBBBBBBBBBB…

upstream mysvr { 
 server 127.0.0.1:7878; 
 server 192.168.10.121:3333 backup; #热备 
 }

3、负载均衡策略(算法)

Nginx 默认提供的负载均衡策略:

1)轮询(默认)round_robin

每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动剔除。

虽然这种方式简便、成本低廉。但缺点是:可靠性低和负载分配不均衡。

例如:

upstream backserver { 
	server 192.168.0.14; 
	server 192.168.0.15; 
} 

2)权重 weight

weight的值越大分配到的访问概率越高,主要用于后端每台服务器性能不均衡的情况下,达到合理的资源利用率。

配置方式:

upstream backserver { 
	server 192.168.0.14 weight=8; 
	server 192.168.0.15 weight=10; 
} 

3)IP 哈希 ip_hash

ip_hash: 来自同一个IP的请求会分发到相同的后端服务器

每个请求按访问 ip 的 hash 结果分配,这样每个访客固定访问一个后端服务器,可以解决 session 共享的问题。

当然,实际场景下,一般不考虑使用 ip_hash 解决 session 共享。

例如:

upstream backserver { 
	ip_hash; 
	server 192.168.0.14:88; 
	server 192.168.0.15:80; 
} 

4)最少连接 least_conn

把请求转发给连接数较少的后端服务器。轮询算法是把请求平均的转发给各个后端,使它们的负载大致相同;但是,有些请求占用的时间很长,会导致其所在的后端负载较高。这种情况下,least_conn这种方式就可以达到更好的负载均衡效果。

#动态服务器组
    upstream backserver {
        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
    }

5)fair(第三方)
按后端服务器的响应时间来分配请求,响应时间短的优先分配。

upstream backserver { 
	server server1; 
	server server2; 
	fair; 
} 

6)url_hash(第三方)
按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,后端服务器为缓存时比较有效。

upstream backserver { 
	server squid1:3128; 
	server squid2:3128; 
	hash $request_uri; 
	hash_method crc32; 
} 

补充:

sticky:通过nginx-sticky模块,来实现cookie黏贴的方式将来自同一个客户端的请求发送到同一个后端服务器上处理,这样一定程度上可以解决多个后端服务器的session会话同步的问题;
round-robin(RR):轮询,每个请求按时间顺序依次分配到不同的后端服务器,如果后端某台服务器死机,自动剔除故障系统,使用户访问不受影响;
weight:轮询权重,weight的值越大分配到的访问概率就越高,主要用于后端每台服务器性能不均衡的情况下,或者仅仅为在主从的情况下设置不同的权重,达到合理有效的利用主机资源。
least_conn:请求被发送到当前活跃连接最少的realserver上,会考虑到weight的值;
ip_hash:每个请求按照IP的哈希结果分配,使来自同一个IP的访客固定访问后端服务器,可以有效的解决动态网页存在的session共享问题。
fair:比weight、ip_hash更加智能的负载均衡算法,fair算法可以根据页面的大小和加载时间长短智能地进行负载均衡,也就是根据后端服务器的响应时间来分配请求,相应时间短的优先分配。nginx本身不支持fair,如果需要使用这种调度算法,则必须安装upstream_fair模块。
url_hash:按访问的URL的哈希结果来分配请求,使每个URL定向到后端服务器,可以进一步提高后端缓存服务器的效率。同样,nginx本身不支持url_hash,如果需要这种调度算法,则必须安装nginx的hash软件包。

4、负载均衡状态

在nginx upstream模块中,可以设定每台后端服务器在负载均衡调度中的状态。

常用的状态有:

down:表示当前的server暂时不参与负载均衡;
backup:预留的备份机器。当其他所有的非backup机器出现故障或者繁忙的时候,才会请求backup机器,因此这台机器的访问压力最低;
max_fails:允许请求失败的次数,默认为1,当超过最大次数时,返回proxy_next_upstraem模块定义的错误;
fail_timeout:请求失败超时时间,在经历了max_fails次失败后,暂停服务的时间。max_fails和fail_timeout可以一起使用。

猜你喜欢

转载自blog.csdn.net/weixin_59663288/article/details/125125647
今日推荐