最新一文搞定Nginx_nginx资源文件只能网页打开(1),一个回答引发热烈讨论

img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

       #root path; #根目录
       #index vv.txt; #设置默认页
       #请求转向mysvr 定义的服务器列表 
       proxy_pass  http://mysvr; 
       #拒绝的ip
       deny 127.0.0.1; 
       #允许的ip 
       allow 172.18.5.54;       
    } 
}

}


上面是nginx的基本配置,需要注意的有以下几点:


1、几个常见配置项:


1. remote\_addr 与 http\_x\_forwarded\_for 用以记录客户端的ip地址;
2. remote\_user :用来记录客户端用户名称;
3. time\_local : 用来记录访问时间与时区;
4. request : 用来记录请求的url与http协议;
5. status : 用来记录请求状态;成功是200;
6. body\_bytes\_s ent :记录发送给客户端文件主体内容大小;
7. http\_referer :用来记录从那个页面链接访问过来的;
8. http\_user\_agent :记录客户端浏览器的相关信息;


2、惊群现象:一个网路连接到来,多个睡眠的进程被同时叫醒,但只有一个进程能获得链接,这样会影响系统性能。


3、每个指令必须有分号结束。


## Nginx 反向代理与负载均衡详解


**Nginx 代理服务的配置说明**


1、设置 404 页面导向地址



error_page 404 https://www.runnob.com; #错误页
#如果被代理服务器返回的状态码为400或者大于400,
#设置的error_page配置起作用。默认为off。
proxy_intercept_errors on;


2、如果我们的代理只允许接受get,post请求方法的一种



proxy_method get; #支持客户端的请求方法。post/get;


3、设置支持的http协议版本



proxy_http_version 1.0 ; #Nginx服务器提供代理服务的http协议版本1.0,1.1,默认设置为1.0版本


4、如果你的nginx服务器给2台web服务器做代理,负载均衡算法采用轮询,那么当你的一台机器web程序iis关闭,也就是说web不能访问,那么nginx服务器分发请求还是会给这台不能访问的web服务器,如果这里的响应连接时间过长,就会导致客户端的页面一直在等待响应,对用户来说体验就打打折扣,这里我们怎么避免这样的情况发生呢。这里我配张图来说明下问题。  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20210704213348164.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDk5MTMwNA==,size_16,color_FFFFFF,t_70)  
 如果负载均衡中其中web2发生这样的情况,nginx首先会去web1请求,但是nginx在配置不当的情况下会继续分发请求道web2,然后等待web2响应,直到我们的响应时间超时,才会把请求重新分发给web1,这里的响应时间如果过长,用户等待的时间就会越长。


下面的配置是解决方案之一。



#nginx服务器与被代理的服务器建立连接的超时时间,默认60秒
proxy_connect_timeout 1;
#nginx服务器想被代理服务器组发出read请求后,等待响应的超时间,默认为60秒。
proxy_read_timeout 1;
#nginx服务器想被代理服务器组发出write请求后,等待响应的超时间,默认为60秒。
proxy_send_timeout 1;
#客户端断网时,nginx服务器是否终端对被代理服务器的请求。默认为off。
proxy_ignore_client_abort on;


5、如果使用upstream指令配置啦一组服务器作为被代理服务器,服务器中的访问算法遵循配置的负载均衡规则,同时可以使用该指令配置在发生哪些异常情况时,将请求顺次交由下一组服务器处理。



#反向代理upstream中设置的服务器组,出现故障时,被代理服务器返回的状态值。
proxy_next_upstream timeout;


状态值可以是:



error|timeout|invalid_header|http_500|http_502|http_503|http_504|http_404|off



> 
> error: 建立连接或向被代理的服务器发送请求或读取响应信息时服务器生错误。  
>  timeout: 建立连接,想被代理服务器发送请求或读取响应信息时服务器生超时。  
>  invalid\_header: 被代理服务器返回的响应头异常。  
>  off: 无法将请求分发给被代理的服务器。  
>  http\_400,…: 被代理服务器返回的状态码为400,500,502,等。
> 
> 
> 


6、如果你想通过http获取客户的真是ip而不是获取代理服务器的ip地址,那么要做如下的设置。


1.只要用户在浏览器中访问的域名绑定了 VIP VIP 下面有RS;则就用$host;host是访问URL中的域名和端口 www.taobao.com:80



proxy_set_header Host $host;


2.把源IP 【$remote\_addr,建立HTTP连接header里面的信息】赋值给X-Real-IP;这样在代码中 $X-Real-IP来获取 源IP



proxy_set_header X-Real-IP $remote_addr;


3.在nginx 作为代理服务器时,设置的IP列表,会把经过的机器ip,代理机器ip都记录下来,用 【,】隔开;代码中用 echo $x-forwarded-for |awk -F, ‘{print $1}’ 来作为源IP



proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;


7、下面是一个关于代理配置的配置文件部分,仅供参考。



include mime.types; #文件扩展名与文件类型映射表
default_type application/octet-stream; #默认文件类型,默认为text/plain
#access_log off; #取消服务日志
log_format myFormat ’ r e m o t e _ a d d r – remote\_addr– remote_addrremote_user [$time_local] $request $status $body_bytes_sent $http_referer $http_user_agent $http_x_forwarded_for’; #自定义格式
access_log log/access.log myFormat; #combined为日志格式的默认值
sendfile on; #允许sendfile方式传输文件,默认为off,可以在http块,server块,location块。
sendfile_max_chunk 100k; #每个进程每次调用传输数量不能大于设定的值,默认为0,即不设上限。
keepalive_timeout 65; #连接超时时间,默认为75s,可以在http,server,location块。
proxy_connect_timeout 1; #nginx服务器与被代理的服务器建立连接的超时时间,默认60秒
proxy_read_timeout 1; #nginx服务器想被代理服务器组发出read请求后,等待响应的超时间,默认为60秒。
proxy_send_timeout 1; #nginx服务器想被代理服务器组发出write请求后,等待响应的超时间,默认为60秒。
proxy_http_version 1.0 ; #Nginx服务器提供代理服务的http协议版本1.0,1.1,默认设置为1.0版本。
#proxy_method get; #支持客户端的请求方法。post/get;
proxy_ignore_client_abort on; #客户端断网时,nginx服务器是否终端对被代理服务器的请求。默认为off。
proxy_ignore_headers “Expires” “Set-Cookie”; #Nginx服务器不处理设置的http相应投中的头域,这里空格隔开可以设置多个。
proxy_intercept_errors on; #如果被代理服务器返回的状态码为400或者大于400,设置的error_page配置起作用。默认为off。
proxy_headers_hash_max_size 1024; #存放http报文头的哈希表容量上限,默认为512个字符。
proxy_headers_hash_bucket_size 128; #nginx服务器申请存放http报文头的哈希表容量大小。默认为64个字符。
proxy_next_upstream timeout; #反向代理upstream中设置的服务器组,出现故障时,被代理服务器返回的状态值。error|timeout|invalid_header|http_500|http_502|http_503|http_504|http_404|off
#proxy_ssl_session_reuse on; 默认为on,如果我们在错误日志中发现“SSL3_GET_FINSHED:digest check failed”的情况时,可以将该指令设置为off。


**Nginx 负载均衡详解**


在文章前面我们已经说过Nginx 配置的详解,当中nginx有很多负载均衡算法。下面我们来具体看看,首先给大家说下upstream这个配置的,这个配置是写一组被代理的服务器地址,然后配置负载均衡的算法。这里的被代理服务器地址有2中写法。



upstream mysvr {
server 192.168.10.121:3333;
server 192.168.10.122:3333;
}
server {

location ~*^.+$ {
proxy_pass http://mysvr; #请求转向mysvr 定义的服务器列表
}
}


然后,就来点实战的东西。


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



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


2、轮询:nginx默认就是轮询其权重都默认为1,服务器处理请求的顺序:ABABABABAB…



upstream mysvr {
server 127.0.0.1:7878;
server 192.168.10.121:3333;
}


3、加权轮询:跟据配置的权重的大小而分发给不同服务器不同数量的请求。如果不设置,则默认为1。下面服务器的请求顺序为:ABBABBABBABBABB…



upstream mysvr {
server 127.0.0.1:7878 weight=1;
server 192.168.10.121:3333 weight=2;
}


4、ip\_hash:nginx会让相同的客户端ip请求相同的服务器。



upstream mysvr {
server 127.0.0.1:7878;
server 192.168.10.121:3333;
ip_hash;
}


**关于nginx负载均衡配置的几个状态参数讲解。**



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



upstream mysvr {
server 127.0.0.1:7878 weight=2 max_fails=2 fail_timeout=2;
server 192.168.10.121:3333 weight=1 max_fails=2 fail_timeout=1;
}


## nginx 配置实例-反向代理


**案例一**


1、实现效果


打开浏览器,在浏览器地址栏输入地址 www.123.com,跳转到 liunx 系统 tomcat 主页面中  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20210705085826444.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDk5MTMwNA==,size_16,color_FFFFFF,t_70)


2、准备工作


1)在 liunx 系统安装 tomcat,使用默认端口 8080,tomcat 安装文件放到 liunx 系统中,解压  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20210705084801712.png)  
 **进入 tomcat 的 bin 目录中,./startup.sh 启动 tomcat 服务器**  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/2021070508491964.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDk5MTMwNA==,size_16,color_FFFFFF,t_70)  
 2)对外开放端口  
 如果防火墙打开了的需要对外开放端口命令如下



firewall-cmd --add-port=8080/tcp --permanent
firewall-cmd –reload


查看已经开放的端口号



firewall-cmd --list-all


3)在 windows 系统中通过浏览器访问 tomcat 服务器  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20210705090003119.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDk5MTMwNA==,size_16,color_FFFFFF,t_70)  
 3、访问过程的分析  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20210705090428867.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDk5MTMwNA==,size_16,color_FFFFFF,t_70)  
 4、具体配置  
 第一步 在 windows 系统的 host 文件进行域名和 ip 对应关系的配置  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20210705090729309.png)  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20210705091610528.png)


第二步 在 nginx 进行请求转发的配置(反向代理配置)



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


在HTTP下把server\_name改成IP地址,然后加上proxy\_pass http://127.0.0.1:8080;  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20210705091055842.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDk5MTMwNA==,size_16,color_FFFFFF,t_70)  
 5、最终测试  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20210705091648266.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDk5MTMwNA==,size_16,color_FFFFFF,t_70)  
 **案列二**


1、实现效果:使用 nginx 反向代理,根据访问的路径跳转到不同端口的服务中nginx 监听端口为 9001,  
 访问 http://127.0.0.1:9001/edu/ 直接跳转到 127.0.0.1:8081  
 访问 http://127.0.0.1:9001/vod/ 直接跳转到 127.0.0.1:8082


2、准备工作  
 (1)准备两个 tomcat 服务器,一个 8080 端口,一个 8081 端口  
 我们把刚刚解压的tomcat复制一份



cp -r apache-tomcat-9.0.48 tomcat8081


然后进入到配置文件下把有关的端口号都修改一下然后启动  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20210705093005266.png)  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20210705093321915.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDk5MTMwNA==,size_16,color_FFFFFF,t_70)  
 现在两个tomcat已经启动完成  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20210705094440676.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDk5MTMwNA==,size_16,color_FFFFFF,t_70)  
 (2)创建文件夹和测试页面


我们分别在两个tomcat下的webapps下面创建一个文件夹并放入一个html文件  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/2021070509491967.png)  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20210705095102193.png)  
 访问两个页面  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20210705095310837.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDk5MTMwNA==,size_16,color_FFFFFF,t_70)


3、具体配置  
 (1)找到 nginx 配置文件,进行反向代理配,在配置文件的http下配置如下  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20210705095758306.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDk5MTMwNA==,size_16,color_FFFFFF,t_70)  
 location 指令说明  
 该指令用于匹配 URL。  
 语法如下:  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20210705100259827.png)  
 1、= :用于不含正则表达式的 uri 前,要求请求字符串与 uri 严格匹配,如果匹配  
 成功,就停止继续向下搜索并立即处理该请求。  
 2、~:用于表示 uri 包含正则表达式,并且区分大小写。  
 3、~ \* :用于表示 uri 包含正则表达式,并且不区分大小写。  
 4、^~:用于不含正则表达式的 uri 前,要求 Nginx 服务器找到标识 uri 和请求字符串匹配度最高的 location 后,立即使用此 location 处理请求,而不再使用 location 块中的正则 uri 和请求字符串做匹配。



> 
> 注意:如果 uri 包含正则表达式,则必须要有 ~ 或者 ~\* 标识。
> 
> 
> 


4、最终测试结果  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20210705100119282.png)  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20210705100132816.png)


## nginx 配置实例-负载均衡


1、实现效果


(1)浏览器地址栏输入地址 http://192.168.17.129/edu/a.html,负载均衡效果,平均 8080到 8081 端口中


2、准备工作


(1)准备两台 tomcat 服务器,一台 8080,一台 8081(我们上面已经准备好了)  
 (2)在两台 tomcat 里面 webapps 目录中,创建名称是 edu 文件夹,在 edu 文件夹中创建页面 a.html,用于测试,我们只需要在8080端口的Tomcat的webapps下面创建一个edu文件夹和a.html文件既可。  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20210705101217774.png)


3、在 nginx 的配置文件中进行负载均衡的配置  
 在http下面加入



#gzip on;
upstream myserver {
server 192.168.1.108:8080;
server 192.168.1.108:8081;
}


server中修改为如下



server {
listen 80;
server_name 192.168.1.108;

    #charset koi8-r;

    #access\_log logs/host.access.log main;

    location / {
        proxy_pass  http://myserver;
        root   html;
        index  index.html index.htm;
    }

4、测试结果如下


负载均衡配置完成,请求会平均分配到8080和8081中去  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20210705102040428.png)  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20210705102057273.png)  
 **Nginx 提供了几种分配方式(策略):**


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


2、weight  
 weight 代表权,重默认为 1,权重越高被分配的客户端越多  
 指定轮询几率,weight 和访问比率成正比,用于后端服务器性能不均的情况。 例如:



upstream server_pool{
server 192.168.5.21 weight=10;
server 192.168.5.22 weight=10;
}


3、ip\_hash  
 每个请求按访问 ip 的 hash 结果分配,这样每个访客固定访问一个后端服务器,可以解决 session 的问题。 例如:



upstream server_pool{
ip_hash;
server 192.168.5.21:80;
server 192.168.5.22:80;
}


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



upstream server_pool{
server 192.168.5.21:80;
server 192.168.5.22:80;
fair;
}


## nginx 配置实例-动静分离


Nginx 动静分离简单来说就是把动态跟静态请求分开,不能理解成只是单纯的把动态页面和静态页面物理分离。严格意义上说应该是动态请求跟静态请求分开,可以理解成使用 Nginx 处理静态页面,Tomcat 处理动态页面。动静分离从目前实现角度来讲大致分为两种,一种是纯粹把静态文件独立成单独的域名,放在独立的服务器上,也是目前主流推崇的方案;另外一种方法就是动态跟静态文件混合在一起发布,通过 nginx 来分开。通过 location 指定不同的后缀名实现不同的请求转发。


通过 expires 参数设置,可以使浏览器缓存过期时间,减少与服务器之前的请求和流量。具体 Expires 定义:是给一个资源设定一个过期时间,也就是说无需去服务端验证,直接通过浏览器自身确认是否过期即可,所以不会产生额外的流量。此种方法非常适合不经常变动的资源。(如果经常更新的文件,不建议使用 Expires 来缓存),我这里设置 3d,表示在这 3 天之内访问这个 URL,发送一个请求,比对服务器该文件最后更新时间没有变化,则不会从服务器抓取,返回状态码304,如果有修改,则直接从服务器重新下载,返回状态码 200。  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20210705103323658.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDk5MTMwNA==,size_16,color_FFFFFF,t_70)  
 1、动静分离准备工作  
 在root目录下创建一个文件夹放静态资源放一张图片和一个html文件  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20210705104723871.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDk5MTMwNA==,size_16,color_FFFFFF,t_70)  
 2、具体配置



server {
listen 80;
server_name 192.168.1.108;

    #charset koi8-r;
       
    #access\_log logs/host.access.log main;
   location /www/  {
        root   /data/;
        index  index.html index.htm;
    }
   location /image/  {
        root   /data/ ;
        autoindex on;
    }       

}


3、测试结果  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20210705112200123.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDk5MTMwNA==,size_16,color_FFFFFF,t_70)


## nginx 原理与优化参数配置


**一 .nginx的工作原理**  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20210705112418951.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDk5MTMwNA==,size_16,color_FFFFFF,t_70)  
 nginx启动后会有两个进程一个为worker一个为master。  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/2021070511260315.png)  
 master将任务分配给worker,由worker完成具体的任务。  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20210705112740365.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDk5MTMwNA==,size_16,color_FFFFFF,t_70)  
 1.在nginx启动后,会有一个master进程和多个worker进程,master进程主要用来管理worker进程,包括:接受信号,将信号分发给worker进程,监听worker进程工作状态,当worker进程退出时(非正常),启动新的worker进程。基本的网络事件会交给worker进程处理。多个worker进程之间是对等的,他们同等竞争来自客户端的请求,各进程互相之间是独立的 。一个请求,只可能在一个worker进程中处理,一个worker进程,不可能处理其它进程的请求。 worker进程的个数是可以设置的,一般我们会设置与机器cpu核数一致,这里面的原因与nginx的进程模型以及事件处理模型是分不开的 。


2.当master接收到重新加载的信号会怎么处理(./nginx -s reload)?,master会重新加载配置文件,然后启动新的进程,使用的新的worker进程来接受请求,并告诉老的worker进程他们可以退休了,老的worker进程将不会接受新的,老的worker进程处理完手中正在处理的请求就会退出。


3.worker进程是如何处理用户的请求呢?首先master会根据配置文件生成一个监听相应端口的socket,然后再faster出多个worker进程,这样每个worker就可以接受从socket过来的消息(其实这个时候应该是每一个worker都有一个socket,只是这些socket监听的地址是一样的)。当一个连接过来的时候,每一个worker都能接收到通知,但是只有一个worker能和这个连接建立关系,其他的worker都会连接失败,这就是所谓的惊群现在,为了解决这个问题,nginx提供一个共享锁accept\_mutex,有了这个共享锁后,就会只有一个worker去接收这个连接。当一个worker进程在accept这个连接之后,就开始读取请求,解析请求,处理请求,产生数据后,再返回给客户端,最后才断开连接,这样一个完整的请求就是这样的了。


**nginx的事件驱动机制**


为什么几个worker进程(每一个worker进程里面其实只有一个主线程)能同时接收上万的请求呢?这是因为nginx事件处理机制是异步非阻塞的。nginx将一个请求划分为多个阶段来异步处理模块,每个阶段只是处理请求的一部分,如果请求的这一部分发生阻塞,nginx不会等待,它会处理其他的请求的某一部分。传统web服务器的每个事件消费者独占一个进程(线程)资源,这种情况对于用户规模较小的情况来说,用户响应速度快,但是当并发规模达到数十万上百万的时候,由于线程(进程)数目过多,会频繁的切换,而且当线程阻塞的时候会进行睡眠,也会造成资源的浪费,这样服务器就会产生瓶颈.


nginx服务器采用的事件驱动机制不同,他不会为每个消费事件创建一个进程或线程,这样就不会产生由于进程间频繁切换占用cpu而产生的瓶颈,而且nginx不会让事件阻塞,即采用无阻塞事件驱动模型,这样就不会因为事件阻塞使进程睡眠而造成的资源浪费.


nginx将一个请求划分成多个阶段异步处理,每个阶段仅仅完成一个请求中的一部分,当本阶段任务完成后进入下一阶段.等待事件发生不是阻塞的等待,等待事件发生时候内。



> 
> 事件发生源产生事件->事件收集器来收集分发事件(选择自己感兴趣的)->消费事件.
> 
> 
> 


**epoll库**


epoll库是Nginx服务器支持的高性能事件驱动库之一。它是公认的最好的事件驱动模型。和poll库及select库有很大的区别。  
 poll和select都是创建一个待处理事件列表,然后把这个列表发给内核,返回的时候,再去轮询检查这个列表。以判断这个事件是否发生。在描述符太多的情况下,就会明显效率低下了。  
 epoll是这么做的,它把事件描述符列表的管理交给内核复制。一旦有某个事件发生,内核将发生事件的事件描述符交给Nginx的进程,而不是将整个事件描述符列表交给进程,让进程去轮询具体是哪个描述符。epoll()避免了轮询整个事件描述符列表。所以显得更高效。


**epoll库的基本步骤:**


首先:epoll库通过相关调用通知内核创建一个有N个描述符的事件列表。然后给这个事件列表设置自己关心的事件。并把它添加到内核中。在具体的代码中还可以实现对相关调用的事件描述符列表进行修改和删除。之后,一旦设置完成就一直等待内核通知事件发生了,某一事件发生后,内核就将发生事件的描述符给epoll库,epoll库去处理事件。


**二、一个 master 和多个 woker 的好处**


(1)可以使用 nginx –s reload 热部署,利用 nginx 进行热部署操作


(2)每个 woker 是独立的进程,如果有其中的一个 woker 出现问题,其他 woker 独立的,继续进行争抢,实现请求过程,不会造成服务中断。


(3)首先,对于每个 worker 进程来说,独立的进程,不需要加锁,所以省掉了锁带来的开销,同时在编程以及问题查找时,也会方便很多。其次,采用独立的进程,可以让互相之间不会影响,一个进程退出后,其它进程还在工作,服务不会中断,master 进程则很快启动新的worker 进程。当然,worker 进程的异常退出,肯定是程序有 bug 了,异常退出,会导致当前 worker 上的所有请求失败,不过不会影响到所有请求,所以降低了风险。


**三、设置多少个 woker 合适**


Nginx 同 redis 类似都采用了 io 多路复用机制,每个 worker 都是一个独立的进程,但每个进程里只有一个主线程,通过异步非阻塞的方式来处理请求, 即使是千上万个请求也不在话下。每个 worker 的线程可以把一个 cpu 的性能发挥到极致。所以 worker 数和服务器的 cpu数相等是最为适宜的。设少了会浪费 cpu,设多了会造成 cpu 频繁切换上下文带来的损耗。


**四、连接数 worker\_connection**


第一个:发送请求,占用了 woker 的几个连接数?  
 答案:2 或者 4 个


原因是当我们访问静态资源时向nginx发出请求,nginx可以直接将静态资源返回给客户端,所以需要来回两个连接。  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20210705114836620.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDk5MTMwNA==,size_16,color_FFFFFF,t_70)


如果我们访问的是动态资源时因为nginx不支持java所以我们nginx要去访问java的服务器Tomcat这样来回就是四个请求。  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20210705114938513.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDk5MTMwNA==,size_16,color_FFFFFF,t_70)


第二个:nginx 有一个 master,有四个 woker,每个 woker 支持最大的连接数 1024,支持的最大并发数是多少?


这个值是表示每个 worker 进程所能建立连接的最大值,所以,一个 nginx 能建立的最大连接数,应该是 `worker_connections * worker_processes`。当然,这里说的是最大连接数,对于HTTP 请 求 本 地 资 源 来 说 , 能 够 支 持 的 最 大 并 发 数 量 是 `worker_connections * worker_processes`,如果是支持 http1.1 的浏览器每次访问要占两个连接,所以普通的静态访问最大并发数是: `worker_connections * worker_processes /2`,而如果是 HTTP 作 为反向代理来说,最大并发数量应该是 `worker_connections * worker_processes/4`。因为作为反向代理服务器,每个并发会建立与客户端的连接和与后端服务的连接,会占用两个连接。


## 搭建 nginx 高可用集群


单台的nginx如果宕机,会导致整个系统瘫痪,如果使用nginx集群,当一台nginx宕机,备nginx依然可以提供服务。


**集群架构图**  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20210705123112504.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDk5MTMwNA==,size_16,color_FFFFFF,t_70)  
 2、配置高可用的准备工作  
 (1)需要两台服务器 192.168.17.129 和 192.168.17.131  
 (2)在两台服务器安装 nginx  
 (3)在两台服务器安装 keepalived


3、在两台服务器安装 keepalived  
 (1)使用 yum 命令进行安装



yum install keepalived –y


查看是否安装成功: `rpm -q -a keepalived`


(2)安装之后,在 etc 里面生成目录 keepalived,有文件 keepalived.conf


4、完成高可用配置(主从配置)


把该配置文件的所有内容替换如下内容:(详细注释如下)  
 主机配置:(1)修改/etc/keepalived/keepalivec.conf 配置文件



global_defs {
notification_email {
acassen@firewall.loc
failover@firewall.loc
sysadmin@firewall.loc
}
router_id 192.168.72.129 ## 标识本节点的字符串,通常为 hostname,也可以是本机ip
}

keepalived 会定时执行脚本并对脚本执行的结果进行分析,动态调整vrrp_instance 的优先级

vrrp_script chk_http_port {
script “/usr/local/src/nginx_check.sh” ## 检测 nginx 状态的脚本路径
interval 2 # (检测脚本执行的间隔)
weight -20 ## 如果条件成立,权重-20
}

定义虚拟路由, VI_1 为虚拟路由的标示符,自己定义名称

vrrp_instance VI_1 {
state MASTER # 主节点为 MASTER, 对应的备份节点为 BACKUP
interface eth0// # 绑定虚拟 IP 的网络接口,与本机 IP 地址所在的网络接口相同, 我的是 eth0
virtual_router_id 51 # 虚拟路由的 ID 号, 两个节点设置必须一样, 可选 IP 最后一段使用, 相同的 VRID 为一个组,他将决定多播的 MAC 地址
mcast_src_ip 192.168.72.129 ## 本机 IP 地址
priority 100 #节点优先级, 值范围 0-254, MASTER 要比 BACKUP 高
advert_int 1 ## 组播信息发送间隔,两个节点设置必须一样, 默认 1s
authentication { ## 设置验证信息,两个节点必须一致
auth_type PASS
auth_pass 1111 ## 真实生产,按需求对应该过来
}
virtual _ipaddress {
192.168.17.50 ## 虚拟 ip,可以定义多个
}
}


从机配置:



global_defs {
notification_email {
acassen@firewall.loc
failover@firewall.loc
sysadmin@firewall.loc
}
router_id 192.168.72.130 ## 标识本节点的字符串,通常为 hostname
}

vrrp_script chk_http_port {
script “/usr/local/src/nginx_check.sh” ## 检测 nginx 状态的脚本路径
interval 2 # (检测脚本执行的间隔)
weight -20 ## 如果条件成立,权重-20
}
vrrp_instance VI_1 {
state BACKUP # 主节点为 MASTER, 对应的备份节点为 BACKUP
interface eth0// # 绑定虚拟 IP 的网络接口,与本机 IP 地址所在的网络接口相同, 我的是 eth0
virtual_router_id 51 # 虚拟路由的 ID 号, 两个节点设置必须一样, 可选 IP 最后一段使用, 相同的 VRID 为一个组,他将决定多播的 MAC 地址
mcast_src_ip 192.168.72.130 ## 本机 IP 地址
priority 80 #节点优先级, 值范围 0-254, MASTER 要比 BACKUP 高
advert_int 1 ## 组播信息发送间隔,两个节点设置必须一样, 默认 1s
authentication { ## 设置验证信息,两个节点必须一致
auth_type PASS
auth_pass 1111 ## 真实生产,按需求对应该过来
}
virtual _ipaddress {
192.168.17.50 ## 虚拟 ip,可以定义多个
}
}


(2)在/usr/local/src 添加检测脚本


检测脚本:nginx\_check.sh (放在keepalived.conf配置的指定位置,本机位置:/usr/local/src/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


(3)把两台服务器上 nginx 和 keepalived 启动  
 启动 nginx:`./nginx`  
 启动 keepalived:`systemctl start keepalived.service`


**参考文章**



> 
> https://blog.csdn.net/wangbiao007/article/details/82910709
> 
> 
> 



> 
> https://blog.csdn.net/fyj13925475957/article/details/105635789
> 
> 
> 



![img](https://img-blog.csdnimg.cn/img_convert/6a30ed0bc2432753eee3ce0386e80ee8.png)
![img](https://img-blog.csdnimg.cn/img_convert/84d50ea0da7c5d59c99518c03d1604be.png)

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!**

**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**

**[如果你需要这些资料,可以戳这里获取](https://bbs.csdn.net/topics/618668825)**

heck.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


(3)把两台服务器上 nginx 和 keepalived 启动  
 启动 nginx:`./nginx`  
 启动 keepalived:`systemctl start keepalived.service`


**参考文章**



> 
> https://blog.csdn.net/wangbiao007/article/details/82910709
> 
> 
> 



> 
> https://blog.csdn.net/fyj13925475957/article/details/105635789
> 
> 
> 



[外链图片转存中...(img-Z1uTkVt9-1715875844689)]
[外链图片转存中...(img-ZS6KzP8h-1715875844689)]

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!**

**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**

**[如果你需要这些资料,可以戳这里获取](https://bbs.csdn.net/topics/618668825)**

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值