Nginx一网打尽:动静分离、压缩、缓存、黑白名单、跨域、高可用、性能优化…

  • 引言
  • 一、性能怪兽-Nginx概念深入浅出
  • 二、Nginx环境搭建
  • 三、Nginx反向代理-负载均衡
  • 四、Nginx动静分离
  • 五、Nginx资源压缩
  • 六、Nginx缓冲区
  • 七、Nginx缓存机制
  • 八、Nginx实现IP黑白名单
  • 九、Nginx跨域配置
  • 十、Nginx防盗链设计
  • 十一、Nginx大文件传输配置
  • 十二、Nginx配置SLL证书
  • 十三、Nginx的高可用
  • 十四、Nginx性能优化
  • 十五、放在最后的结尾

 

Nginx一网打尽:动静分离、压缩、缓存、黑白名单、跨域、高可用、性能优化...

# 引言

Nginx一网打尽:动静分离、压缩、缓存、黑白名单、跨域、高可用、性能优化...

早期的业务都是基于单体节点部署,由于前期访问流量不大,因此单体结构也可满足需求,但随着业务增长,流量也越来越大,那么最终单台服务器受到的访问压力也会逐步增高。时间一长,单台服务器性能无法跟上业务增长,就会造成线上频繁宕机的现象发生,最终导致系统瘫痪无法继续处理用户的请求。

从上面的描述中,主要存在两个问题:
①单体结构的部署方式无法承载日益增长的业务流量。
②当后端节点宕机后,整个系统会陷入瘫痪,导致整个项目不可用。

 

因此在这种背景下,引入负载均衡技术可带来的收益:

 

  • 系统的高可用:当某个节点宕机后可以迅速将流量转移至其他节点。

  • 系统的高性能:多台服务器共同对外提供服务,为整个系统提供了更高规模的吞吐。

  • 系统的拓展性:当业务再次出现增长或萎靡时,可再加入/减少节点,灵活伸缩。

OK~,既然引入负载均衡技术可给我们带来如此巨大的好处,那么又有那些方案可供选择呢?主要有两种负载方案,硬件层面与软件层面,比较常用的硬件负载器有A10、F5等,但这些机器动辄大几万乃至几十万的成本,因此一般大型企业会采用该方案,如银行、国企、央企等。

而成本有限,但依旧想做负载均衡的项目,那么可在软件层面实现,如典型的Nginx等,软件层的负载也是本文的重点,毕竟Boss们的准则之一就是:能靠技术实现的就尽量不花钱。

 

Nginx一网打尽:动静分离、压缩、缓存、黑白名单、跨域、高可用、性能优化...

# 性能怪兽-Nginx概念深入浅出

Nginx一网打尽:动静分离、压缩、缓存、黑白名单、跨域、高可用、性能优化...

Nginx是目前负载均衡技术中的主流方案,几乎绝大部分项目都会使用它,Nginx是一个轻量级的高性能HTTP反向代理服务器,同时它也是一个通用类型的代理服务器,支持绝大部分协议,如TCP、UDP、SMTP、HTTPS等。


Nginx一网打尽:动静分离、压缩、缓存、黑白名单、跨域、高可用、性能优化...

Nginx与之前谈及的《Redis》相同,都是基于多路复用模型构建出的产物,因此它与Redis同样具备资源占用少、并发支持高的特点,在理论上单节点的Nginx同时支持5W并发连接,而实际生产环境中,硬件基础到位再结合简单调优后确实能达到该数值。

 

先来看看Nginx引入前后,客户端请求处理流程的对比:


Nginx一网打尽:动静分离、压缩、缓存、黑白名单、跨域、高可用、性能优化...

 

原本客户端是直接请求目标服务器,由目标服务器直接完成请求处理工作,但加入Nginx后,所有的请求会先经过Nginx,再由其进行分发到具体的服务器处理,处理完成后再返回Nginx,最后由Nginx将最终的响应结果返回给客户端。

 

了解了Nginx的基本概念后,再来快速搭建一下环境,以及了解一些Nginx的高级特性,如动静分离、资源压缩、缓存配置、IP黑名单、高可用保障等。

 

 

Nginx一网打尽:动静分离、压缩、缓存、黑白名单、跨域、高可用、性能优化...

# Nginx环境搭建

Nginx一网打尽:动静分离、压缩、缓存、黑白名单、跨域、高可用、性能优化...

❶首先创建Nginx的目录并进入:

[root@localhost]# mkdir /soft && mkdir /soft/nginx/[root@localhost]# cd /soft/nginx/

❷下载Nginx的安装包,可以通过FTP工具上传离线环境包,也可通过wget命令在线获取安装包:

[root@localhost]# wget https://nginx.org/download/nginx-1.21.6.tar.gz

没有wget命令的可通过yum命令安装:

[root@localhost]# yum -y install wget

❸解压Nginx的压缩包:

[root@localhost]# tar -xvzf nginx-1.21.6.tar.gz

❹下载并安装Nginx所需的依赖库和包:

[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

也可以通过yum命令一键下载(推荐上面哪种方式):

[root@localhost]# yum -y install gcc zlib zlib-devel pcre-devel openssl openssl-devel

执行完成后,然后ls查看目录文件,会看一大堆依赖:


Nginx一网打尽:动静分离、压缩、缓存、黑白名单、跨域、高可用、性能优化...

紧接着通过rpm命令依次将依赖包一个个构建,或者通过如下指令一键安装所有依赖包:

[root@localhost]# rpm -ivh --nodeps *.rpm

❺进入解压后的nginx目录,然后执行Nginx的配置脚本,为后续的安装提前配置好环境,默认位于/usr/local/nginx/目录下(可自定义目录):

[root@localhost]# cd nginx-1.21.6[root@localhost]# ./configure --prefix=/soft/nginx/

❻编译并安装Nginx:

[root@localhost]# make && make install

❼最后回到前面的/soft/nginx/目录,输入ls即可看见安装nginx完成后生成的文件。

❽修改安装后生成的conf目录下的nginx.conf配置文件:

[root@localhost]# vi conf/nginx.conf    修改端口号:listen    80;  修改IP地址:server_name  你当前机器的本地IP(线上配置域名);

❾制定配置文件并启动Nginx:

[root@localhost]# sbin/nginx -c conf/nginx.conf[root@localhost]# ps aux | grep nginx

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,不管当前是否有任务在执行

❿开放80端口,并更新防火墙:

[root@localhost]# firewall-cmd --zone=public --add-port=80/tcp --permanent[root@localhost]# firewall-cmd --reload[root@localhost]# firewall-cmd --zone=public --list-ports

⓫在Windows/Mac的浏览器中,直接输入刚刚配置的IP地址访问Nginx:


Nginx一网打尽:动静分离、压缩、缓存、黑白名单、跨域、高可用、性能优化...
最终看到如上的Nginx欢迎界面,代表Nginx安装完成。

 

 

Nginx一网打尽:动静分离、压缩、缓存、黑白名单、跨域、高可用、性能优化...

# Nginx反向代理-负载均衡

Nginx一网打尽:动静分离、压缩、缓存、黑白名单、跨域、高可用、性能优化...

首先通过SpringBoot+Freemarker快速搭建一个WEB项目:springboot-web-nginx,然后在该项目中,创建一个IndexNginxController.java文件,逻辑如下:

@Controllerpublic 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;    }}

在该Controller类中,存在一个成员变量:port,它的值即是从application.properties配置文件中获取server.port值。当出现访问/资源的请求时,跳转前端index页面,并将该值携带返回。

 

前端的index.ftl文件代码如下:

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

从上可以看出其逻辑并不复杂,仅是从响应中获取了port输出。

 

OK~,前提工作准备就绪后,再简单修改一下nginx.conf的配置即可:

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;    }}

至此,所有的前提工作准备就绪,紧接着再启动Nginx,然后再启动两个web服务,第一个WEB服务启动时,在application.properties配置文件中,将端口号改为8080,第二个WEB服务启动时,将其端口号改为8090。

最终来看看效果:


Nginx一网打尽:动静分离、压缩、缓存、黑白名单、跨域、高可用、性能优化...

因为配置了请求分发的权重,8080、8090的权重比为2:1,因此请求会根据权重比均摊到每台机器,也就是8080一次、8090两次、8080一次……

 

 

Nginx一网打尽:动静分离、压缩、缓存、黑白名单、跨域、高可用、性能优化...

Nginx请求分发原理

Nginx一网打尽:动静分离、压缩、缓存、黑白名单、跨域、高可用、性能优化...

 

客户端发出的请求192.168.12.129最终会转变为:http://192.168.12.129:80/,然后再向目标IP发起请求,流程如下:


Nginx一网打尽:动静分离、压缩、缓存、黑白名单、跨域、高可用、性能优化...

  • 由于Nginx监听了192.168.12.129的80端口,所以最终该请求会找到Nginx进程;

  • Nginx首先会根据配置的location规则进行匹配,根据客户端的请求路径/,会定位到location /{}规则;

  • 然后根据该location中配置的proxy_pass会再找到名为nginx_boot的upstream;

  • 最后根据upstream中的配置信息,将请求转发到运行WEB服务的机器处理,由于配置了多个WEB服务,且配置了权重值,因此Nginx会依次根据权重比分发请求。

 

 

Nginx一网打尽:动静分离、压缩、缓存、黑白名单、跨域、高可用、性能优化...

# Nginx动静分离

Nginx一网打尽:动静分离、压缩、缓存、黑白名单、跨域、高可用、性能优化...

动静分离应该是听的次数较多的性能优化方案,那先思考一个问题:为什么需要做动静分离呢?它带来的好处是什么?其实这个问题也并不难回答,当你搞懂了网站的本质后,自然就理解了动静分离的重要性。先来以淘宝为例分析看看:


Nginx一网打尽:动静分离、压缩、缓存、黑白名单、跨域、高可用、性能优化...

当浏览器输入www.taobao.com访问淘宝首页时,打开开发者调试工具可以很明显的看到,首页加载会出现100+的请求数,而正常项目开发时,静态资源一般会放入到resources/static/目录下:


Nginx一网打尽:动静分离、压缩、缓存、黑白名单、跨域、高可用、性能优化...

在项目上线部署时,这些静态资源会一起打成包,那此时思考一个问题:假设淘宝也是这样干的,那么首页加载时的请求最终会去到哪儿被处理?答案毋庸置疑,首页100+的所有请求都会来到部署WEB服务的机器处理,那则代表着一个客户端请求淘宝首页,就会对后端服务器造成100+的并发请求。毫无疑问,这对于后端服务器的压力是尤为巨大的。

但此时不妨分析看看,首页100+的请求中,是不是至少有60+是属于*.js、*.css、*.html、*.jpg…..这类静态资源的请求呢?答案是Yes。

既然有这么多请求属于静态的,这些资源大概率情况下,长时间也不会出现变动,那为何还要让这些请求到后端再处理呢?能不能在此之前就提前处理掉?当然OK,因此经过分析之后能够明确一点:做了动静分离之后,至少能够让后端服务减少一半以上的并发量。到此时大家应该明白了动静分离能够带来的性能收益究竟有多大。

 

OK~,搞清楚动静分离的必要性之后,如何实现动静分离呢?其实非常简单,实战看看。

 

①先在部署Nginx的机器,Nginx目录下创建一个目录static_resources:

mkdir static_resources

②将项目中所有的静态资源全部拷贝到该目录下,而后将项目中的静态资源移除重新打包。

 

③稍微修改一下nginx.conf的配置,增加一条location匹配规则:

location ~ .*.(html|htm|gif|jpg|jpeg|bmp|png|ico|txt|js|css){    root   /soft/nginx/static_resources;    expires 7d;}

然后照常启动nginx和移除了静态资源的WEB服务,你会发现原本的样式、js效果、图片等依旧有效,如下:


Nginx一网打尽:动静分离、压缩、缓存、黑白名单、跨域、高可用、性能优化...

其中static目录下的nginx_style.css文件已被移除,但效果依旧存在(绿色字体+蓝色大边框):


Nginx一网打尽:动静分离、压缩、缓存、黑白名单、跨域、高可用、性能优化...

最后解读一下那条location规则:
location ~ .*.(html|htm|gif|jpg|jpeg|bmp|png|ico|txt|js|css)
~代表匹配时区分大小写
.*代表任意字符都可以出现零次或多次,即资源名不限制
.代表匹配后缀分隔符.
(html|…|css)代表匹配括号里所有静态资源类型
综上所述,简单一句话概述:该配置表示匹配以.html~.css为后缀的所有资源请求。

最后提一嘴,也可以将静态资源上传到文件服务器中,然后location中配置一个新的upstream指向。

 

 

Nginx一网打尽:动静分离、压缩、缓存、黑白名单、跨域、高可用、性能优化...

# Nginx资源压缩

Nginx一网打尽:动静分离、压缩、缓存、黑白名单、跨域、高可用、性能优化...

建立在动静分离的基础之上,如果一个静态资源的Size越小,那么自然传输速度会更快,同时也会更节省带宽,因此我们在部署项目时,也可以通过Nginx对于静态资源实现压缩传输,一方面可以节省带宽资源,第二方面也可以加快响应速度并提升系统整体吞吐。

 

在Nginx也提供了三个支持资源压缩的模块ngx_http_gzip_module、ngx_http_gzip_static_module、ngx_http_gunzip_module,其中ngx_http_gzip_module属于内置模块,代表着可以直接使用该模块下的一些压缩指令,后续的资源压缩操作都基于该模块,先来看看压缩配置的一些参数/指令:

 

参数项 释义 参数值
gzip 开启或关闭压缩机制 on/off;
gzip_types 根据文件类型选择性开启压缩机制 image/png、text/css…
gzip_comp_level 用于设置压缩级别,级别越高越耗时 1~9(越高压缩效果越好)
gzip_vary 设置是否携带Vary:Accept-Encoding头域的响应头部 on/off;
gzip_buffers 设置处理压缩请求的缓冲区数量和大小 数量 大小,如16 8k;
gzip_disable 针对不同客户端的请求来设置是否开启压缩 如 .*Chrome.*;
gzip_http_version 指定压缩响应所需要的最低HTTP请求版本 如1.1;
gzip_min_length 设置触发压缩的文件最低大小 如512k;
gzip_proxied 对于后端服务器的响应结果是否开启压缩 off、expired、no-cache…

了解了Nginx中的基本压缩配置后,接下来可以在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;}

在上述的压缩配置中,最后一个gzip_proxied选项,可以根据系统的实际情况决定,总共存在多种选项:

 

  • off:关闭Nginx对后台服务器的响应结果进行压缩。

  • expired:如果响应头中包含Expires信息,则开启压缩。

  • no-cache:如果响应头中包含Cache-Control:no-cache信息,则开启压缩。

  • no-store:如果响应头中包含Cache-Control:no-store信息,则开启压缩。

  • private:如果响应头中包含Cache-Control:private信息,则开启压缩。

  • no_last_modified:如果响应头中不包含Last-Modified信息,则开启压缩。

  • no_etag:如果响应头中不包含ETag信息,则开启压缩。

  • auth:如果响应头中包含Authorization信息,则开启压缩。

  • any:无条件对后端的响应结果开启压缩机制。

 

OK~,简单修改好了Nginx的压缩配置后,可以在原本的index页面中引入一个jquery-3.6.0.js文件:

<script type="text/javascript" src="jquery-3.6.0.js"></script>

分别来对比下压缩前后的区别:
Nginx一网打尽:动静分离、压缩、缓存、黑白名单、跨域、高可用、性能优化...
从图中可以很明显看出,未开启压缩机制前访问时,js文件的原始大小为230K,当配置好压缩后再重启Nginx,会发现文件大小从230KB→69KB,效果立竿见影!

注意点:
①对于图片、视频类型的数据,会默认开启压缩机制,因此一般无需再次开启压缩。
②对于.js文件而言,需要指定压缩类型为application/javascript,而并非text/javascript、application/x-javascript。

 

 

Nginx一网打尽:动静分离、压缩、缓存、黑白名单、跨域、高可用、性能优化...

# Nginx缓冲区

Nginx一网打尽:动静分离、压缩、缓存、黑白名单、跨域、高可用、性能优化...

先来思考一个问题,接入Nginx的项目一般请求流程为:“客户端→Nginx→服务端”,在这个过程中存在两个连接:“客户端→Nginx、Nginx→服务端”,那么两个不同的连接速度不一致,就会影响用户的体验(比如浏览器的加载速度跟不上服务端的响应速度)。


其实也就类似电脑的内存跟不上CPU速度,所以对于用户造成的体验感极差,因此在CPU设计时都会加入三级高速缓冲区,用于缓解CPU和内存速率不一致的矛盾。在Nginx也同样存在缓冲区的机制,主要目的就在于:用来解决两个连接之间速度不匹配造成的问题,有了缓冲后,Nginx代理可暂存后端的响应,然后按需供给数据给客户端。先来看看一些关于缓冲区的配置项:

 

  • proxy_buffering:是否启用缓冲机制,默认为on关闭状态。

  • client_body_buffer_size:设置缓冲客户端请求数据的内存大小。

  • proxy_buffers:为每个请求/连接设置缓冲区的数量和大小,默认4 4k/8k。

  • proxy_buffer_size:设置用于存储响应头的缓冲区大小。

  • proxy_busy_buffers_size:在后端数据没有完全接收完成时,Nginx可以将busy状态的缓冲返回给客户端,该参数用来设置busy状态的buffer具体有多大,默认为proxy_buffer_size*2。

  • proxy_temp_path:当内存缓冲区存满时,可以将数据临时存放到磁盘,该参数是设置存储缓冲数据的目录。

    • path是临时目录的路径。

    • 语法:proxy_temp_path path;

  • proxy_temp_file_write_size:设置每次写数据到临时文件的大小限制。

  • proxy_max_temp_file_size:设置临时的缓冲目录中允许存储的最大容量。

  • 非缓冲参数项:

    • proxy_connect_timeout:设置与后端服务器建立连接时的超时时间。

    • proxy_read_timeout:设置从后端服务器读取响应数据的超时时间。

    • proxy_send_timeout:设置向后端服务器传输请求数据的超时时间。

 

具体的nginx.conf配置如下:

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一网打尽:动静分离、压缩、缓存、黑白名单、跨域、高可用、性能优化...

# Nginx缓存机制

Nginx一网打尽:动静分离、压缩、缓存、黑白名单、跨域、高可用、性能优化...

对于性能优化而言,缓存是一种能够大幅度提升性能的方案,因此几乎可以在各处都能看见缓存,如客户端缓存、代理缓存、服务器缓存等等,Nginx的缓存则属于代理缓存的一种。对于整个系统而言,加入缓存带来的优势额外明显:

 

  • 减少了再次向后端或文件服务器请求资源的带宽消耗。

  • 降低了下游服务器的访问压力,提升系统整体吞吐。

  • 缩短了响应时间,提升了加载速度,打开页面的速度更快。

 

那么在Nginx中,又该如何配置代理缓存呢?先来看看缓存相关的配置项:

 

  • proxy_cache_path:代理缓存的路径。

    • path:缓存的路径地址。

    • levels:缓存存储的层次结构,最多允许三层目录。

    • use_temp_path:是否使用临时目录。

    • keys_zone:指定一个共享内存空间来存储热点Key(1M可存储8000个Key)。

    • inactive:设置缓存多长时间未被访问后删除(默认是十分钟)。

    • max_size:允许缓存的最大存储空间,超出后会基于LRU算法移除缓存,Nginx会创建一个Cache manager的进程移除数据,也可以通过purge方式。

    • manager_files:manager进程每次移除缓存文件数量的上限。

    • manager_sleep:manager进程每次移除缓存文件的时间上限。

    • manager_threshold:manager进程每次移除缓存后的间隔时间。

    • loader_files:重启Nginx载入缓存时,每次加载的个数,默认100。

    • loader_sleep:每次载入时,允许的最大时间上限,默认200ms。

    • loader_threshold:一次载入后,停顿的时间间隔,默认50ms。

    • purger:是否开启purge方式移除数据。

    • purger_files:每次移除缓存文件时的数量。

    • purger_sleep:每次移除时,允许消耗的最大时间。

    • purger_threshold:每次移除完成后,停顿的间隔时间。

    • 语法: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:开启或关闭代理缓存,开启时需要指定一个共享内存区域。

    • zone为内存区域的名称,即上面中keys_zone设置的名称。

    • 语法:proxy_cache zone | off;

  • proxy_cache_key:定义如何生成缓存的键。

    • string为生成Key的规则,如$scheme$proxy_host$request_uri。

    • 语法:proxy_cache_key string;

  • proxy_cache_valid:缓存生效的状态码与过期时间。

    • code为状态码,time为有效时间,可以根据状态码设置不同的缓存时间。

    • 例如:proxy_cache_valid 200 302 30m;

    • 语法:proxy_cache_valid [code …] time;

  • proxy_cache_min_uses:设置资源被请求多少次后被缓存。

    • number为次数,默认为1。

    • 语法:proxy_cache_min_uses number;

  • proxy_cache_use_stale:当后端出现异常时,是否允许Nginx返回缓存作为响应。

    • error为错误类型,可配置timeout|invalid_header|updating|http_500…。

    • 语法:proxy_cache_use_stale error;

  • proxy_cache_lock:对于相同的请求,是否开启锁机制,只允许一个请求发往后端。

    • 语法:proxy_cache_lock on | off;

  • proxy_cache_lock_timeout:配置锁超时机制,超出规定时间后会释放请求。

    • proxy_cache_lock_timeout time;

  • proxy_cache_methods:设置对于那些HTTP方法开启缓存。

    • method为请求方法类型,如GET、HEAD等。

    • 语法:proxy_cache_methods method;

  • proxy_no_cache:定义不存储缓存的条件,符合时不会保存。

    • string为条件,例如$cookie_nocache $arg_nocache $arg_comment;

    • 语法:proxy_no_cache string…;

  • proxy_cache_bypass:定义不读取缓存的条件,符合时不会从缓存中读取。

    • 和上面proxy_no_cache的配置方法类似。

    • 语法:proxy_cache_bypass string…;

  • add_header:往响应头中添加字段信息。

    • 语法:add_header fieldName fieldValue;

  • $upstream_cache_status:记录了缓存是否命中的信息,存在多种情况:

    • MISS:请求未命中缓存。

    • HIT:请求命中缓存。

    • EXPIRED:请求命中缓存但缓存已过期。

    • STALE:请求命中了陈旧缓存。

    • REVALIDDATED:Nginx验证陈旧缓存依然有效。

    • UPDATING:命中的缓存内容陈旧,但正在更新缓存。

    • BYPASS:响应结果是从原始服务器获取的。

    • PS:这个和之前的不同,之前的都是参数项,这个是一个Nginx内置变量。

 

OK~,对于Nginx中的缓存配置项大概了解后,接着来配置一下Nginx代理缓存:

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;        }    }}

接着来看一下效果,如下:
Nginx一网打尽:动静分离、压缩、缓存、黑白名单、跨域、高可用、性能优化...
第一次访问时,因为还没有请求过资源,所以缓存中没有数据,因此没有命中缓存。第二、三次,依旧没有命中缓存,直至第四次时才显示命中,这是为什么呢?因为在前面的缓存配置中,我们配置了加入缓存的最低条件为:资源至少要被请求三次以上才会加入缓存。这样可以避免很多无效缓存占用空间。

 

 

Nginx一网打尽:动静分离、压缩、缓存、黑白名单、跨域、高可用、性能优化...

缓存清理

Nginx一网打尽:动静分离、压缩、缓存、黑白名单、跨域、高可用、性能优化...

当缓存过多时,如果不及时清理会导致磁盘空间被“吃光”,因此我们需要一套完善的缓存清理机制去删除缓存,在之前的proxy_cache_path参数中有purger相关的选项,开启后可以帮我们自动清理缓存,但遗憾的是:purger系列参数只有商业版的NginxPlus才能使用,因此需要付费才可使用。

 

不过天无绝人之路,我们可以通过强大的第三方模块ngx_cache_purge来替代,先来安装一下该插件:


①首先去到Nginx的安装目录下,创建一个cache_purge目录:

[root@localhost]# mkdir cache_purge && cd cache_purge

②通过wget指令从github上拉取安装包的压缩文件并解压:

[root@localhost]# wget https://github.com/FRiCKLE/ngx_cache_purge/archive/2.3.tar.gz[root@localhost]# tar -xvzf 2.3.tar.gz

③再次去到之前Nginx的解压目录下:

[root@localhost]# cd /soft/nginx/nginx1.21.6

④重新构建一次Nginx,通过–add-module的指令添加刚刚的第三方模块:

[root@localhost]# ./configure --prefix=/soft/nginx/ --add-module=/soft/nginx/cache_purge/ngx_cache_purge-2.3/

⑤重新根据刚刚构建的Nginx,再次编译一下,但切记不要make install:

[root@localhost]# make

⑥删除之前Nginx的启动文件,不放心的也可以移动到其他位置:

[root@localhost]# rm -rf /soft/nginx/sbin/nginx

⑦从生成的objs目录中,重新复制一个Nginx的启动文件到原来的位置:

[root@localhost]# cp objs/nginx /soft/nginx/sbin/nginx

至此,第三方缓存清除模块ngx_cache_purge就安装完成了,接下来稍微修改一下nginx.conf配置,再添加一条location规则:

location ~ /purge(/.*) {  # 配置可以执行清除操作的IP(线上可以配置成内网机器)  # allow 127.0.0.1; # 代表本机  allow all; # 代表允许任意IP清除缓存  proxy_cache_purge $host$1$is_args$args;}

然后再重启Nginx,接下来即可通过http://xxx/purge/xx的方式清除缓存。

 

 

Nginx一网打尽:动静分离、压缩、缓存、黑白名单、跨域、高可用、性能优化...

# Nginx实现IP黑白名单

Nginx一网打尽:动静分离、压缩、缓存、黑白名单、跨域、高可用、性能优化...

有时候往往有些需求,可能某些接口只能开放给对应的合作商,或者购买/接入API的合作伙伴,那么此时就需要实现类似于IP白名单的功能。而有时候有些恶意攻击者或爬虫程序,被识别后需要禁止其再次访问网站,因此也需要实现IP黑名单。那么这些功能无需交由后端实现,可直接在Nginx中处理。

 

Nginx做黑白名单机制,主要是通过allow、deny配置项来实现:

allow xxx.xxx.xxx.xxx; # 允许指定的IP访问,可以用于实现白名单。deny xxx.xxx.xxx.xxx; # 禁止指定的IP访问,可以用于实现黑名单。

要同时屏蔽/开放多个IP访问时,如果所有IP全部写在nginx.conf文件中定然是不显示的,这种方式比较冗余,那么可以新建两个文件BlocksIP.conf、WhiteIP.conf:

# --------黑名单: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全部禁止访问

分别将要禁止/开放的IP添加到对应的文件后,可以再将这两个文件在nginx.conf中导入:

http{    # 屏蔽该文件中的所有IP    include /soft/nginx/IP/BlocksIP.conf;  server{    location xxx {        # 某一系列接口只开放给白名单中的IP        include /soft/nginx/IP/blockip.conf;     } }}

对于文件具体在哪儿导入,这个也并非随意的,如果要整站屏蔽/开放就在http中导入,如果只需要一个域名下屏蔽/开放就在sever中导入,如果只需要针对于某一系列接口屏蔽/开放IP,那么就在location中导入。

当然,上述只是最简单的IP黑/白名单实现方式,同时也可以通过ngx_http_geo_module、ngx_http_geo_module第三方库去实现(这种方式可以按地区、国家进行屏蔽,并且提供了IP库)。

 

Nginx一网打尽:动静分离、压缩、缓存、黑白名单、跨域、高可用、性能优化...

# Nginx跨域配置

Nginx一网打尽:动静分离、压缩、缓存、黑白名单、跨域、高可用、性能优化...

 

跨域问题在之前的单体架构开发中,其实是比较少见的问题,除非是需要接入第三方SDK时,才需要处理此问题。但随着现在前后端分离、分布式架构的流行,跨域问题也成为了每个Java开发必须要懂得解决的一个问题。

 

跨域问题产生的原因

 

产生跨域问题的主要原因就在于同源策略,为了保证用户信息安全,防止恶意网站窃取数据,同源策略是必须的,否则cookie可以共享。由于http无状态协议通常会借助cookie来实现有状态的信息记录,例如用户的身份/密码等,因此一旦cookie被共享,那么会导致用户的身份信息被盗取。


同源策略主要是指三点相同,协议+域名+端口 相同的两个请求,则可以被看做是同源的,但如果其中任意一点存在不同,则代表是两个不同源的请求,同源策略会限制了不同源之间的资源交互。

 

Nginx解决跨域问题

 

弄明白了跨域问题的产生原因,接下来看看Nginx中又该如何解决跨域呢?其实比较简单,在nginx.conf中稍微添加一点配置即可:

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;    }}

在nginx.conf文件加上如上配置后,跨域请求即可生效了。

但如果后端是采用分布式架构开发的,有时候RPC调用也需要解决跨域问题,不然也同样会出现无法跨域请求的异常,因此可以在你的后端项目中,通过继承HandlerInterceptorAdapter类、实现WebMvcConfigurer接口、添加@CrossOrgin注解的方式实现接口之间的跨域配置。

 

 

Nginx一网打尽:动静分离、压缩、缓存、黑白名单、跨域、高可用、性能优化...

# Nginx防盗链设计

Nginx一网打尽:动静分离、压缩、缓存、黑白名单、跨域、高可用、性能优化...

首先了解一下何谓盗链:盗链即是指外部网站引入当前网站的资源对外展示,来举个简单的例子理解:

好比壁纸网站X站、Y站,X站是一点点去购买版权、签约作者的方式,从而积累了海量的壁纸素材,但Y站由于资金等各方面的原因,就直接通过<img src=”X站/xxx.jpg” />这种方式照搬了X站的所有壁纸资源,继而提供给用户下载。

那么如果我们自己是这个X站的Boss,心中必然不爽,那么此时又该如何屏蔽这类问题呢?那么接下来要叙说的防盗链 登场了!

 

Nginx的防盗链机制实现,跟上篇文章《HTTP/HTTPS》中分析到的一个头部字段:Referer有关,该字段主要描述了当前请求是从哪儿发出的,那么在Nginx中就可获取该值,然后判断是否为本站的资源引用请求,如果不是则不允许访问。

 

Nginx中存在一个配置项为valid_referers,正好可以满足前面的需求,语法如下:

 

  • valid_referers none | blocked | server_names | string …;

    • none:表示接受没有Referer字段的HTTP请求访问。

    • blocked:表示允许http://或https//以外的请求访问。

    • 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实现了最基本的防盗链机制,最后只需要额外重启一下就好啦!当然,对于防盗链机制实现这块,也有专门的第三方模块ngx_http_accesskey_module实现了更为完善的设计,感兴趣的小伙伴可以自行去看看。

PS:防盗链机制也无法解决爬虫伪造referers信息的这种方式抓取数据。

 

 

Nginx一网打尽:动静分离、压缩、缓存、黑白名单、跨域、高可用、性能优化...

# Nginx大文件传输配置

Nginx一网打尽:动静分离、压缩、缓存、黑白名单、跨域、高可用、性能优化...

 

在某些业务场景中需要传输一些大文件,但大文件传输时往往都会会出现一些Bug,比如文件超出限制、文件传输过程中请求超时等,那么此时就可以在Nginx稍微做一些配置,先来了解一些关于大文件传输时可能会用的配置项:

 

配置项 释义
client_max_body_size 设置请求体允许的最大体积
client_header_timeout 等待客户端发送一个请求头的超时时间
client_body_timeout 设置读取请求体的超时时间
proxy_read_timeout 设置请求被后端服务器读取时,Nginx等待的最长时间
proxy_send_timeout 设置后端向Nginx返回响应时的超时时间

 

在传输大文件时,client_max_body_size、client_header_timeout、proxy_read_timeout、proxy_send_timeout这四个参数值都可以根据自己项目的实际情况来配置。

上述配置仅是作为代理层需要配置的,因为最终客户端传输文件还是直接与后端进行交互,这里只是把作为网关层的Nginx配置调高一点,调到能够“容纳大文件”传输的程度。


当然,Nginx中也可以作为文件服务器使用,但需要用到一个专门的第三方模块nginx-upload-module,如果项目中文件上传的作用处不多,那么建议可以通过Nginx搭建,毕竟可以节省一台文件服务器资源。但如若文件上传/下载较为频繁,那么还是建议额外搭建文件服务器,并将上传/下载功能交由后端处理。

 

 

Nginx一网打尽:动静分离、压缩、缓存、黑白名单、跨域、高可用、性能优化...

# Nginx配置SLL证书

Nginx一网打尽:动静分离、压缩、缓存、黑白名单、跨域、高可用、性能优化...

 

随着越来越多的网站接入HTTPS,因此Nginx中仅配置HTTP还不够,往往还需要监听443端口的请求,但在上篇《HTTP/HTTPS》中谈到过,HTTPS为了确保通信安全,所以服务端需配置对应的数字证书,当项目使用Nginx作为网关时,那么证书在Nginx中也需要配置,接下来简单聊一下关于SSL证书配置过程:

 

  • ①先去CA机构或从云控制台中申请对应的SSL证书,审核通过后下载Nginx版本的证书。

  • ②下载数字证书后,完整的文件总共有三个:.crt、.key、.pem:

    • .crt:数字证书文件,.crt是.pem的拓展文件,因此有些人下载后可能没有。

    • .key:服务器的私钥文件,及非对称加密的私钥,用于解密公钥传输的数据。

    • .pem:Base64-encoded编码格式的源证书文本文件,可自行根需求修改拓展名。

  • ③在Nginx目录下新建certificate目录,并将下载好的证书/私钥等文件上传至该目录。

  • ④最后修改一下nginx.conf文件即可,如下:

# ----------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后,你的网站即可通过https://的方式访问,并且当客户端使用http://的方式访问时,会自动将其改写为HTTPS请求。

 

 

Nginx一网打尽:动静分离、压缩、缓存、黑白名单、跨域、高可用、性能优化...

# Nginx的高可用

Nginx一网打尽:动静分离、压缩、缓存、黑白名单、跨域、高可用、性能优化...

线上如果采用单个节点的方式部署Nginx,难免会出现天灾人祸,比如系统异常、程序宕机、服务器断电、机房爆炸、地球毁灭….哈哈哈,夸张了。但实际生产环境中确实存在隐患问题,由于Nginx作为整个系统的网关层接入外部流量,所以一旦Nginx宕机,最终就会导致整个系统不可用,这无疑对于用户的体验感是极差的,因此也得保障Nginx高可用的特性。

接下来则会通过keepalived的VIP机制,实现Nginx的高可用。
VIP并不是只会员的意思,而是指Virtual IP,即虚拟IP。

keepalived在之前单体架构开发时,是一个用的较为频繁的高可用技术,比如MySQL、Redis、MQ、Proxy、Tomcat等各处都会通过keepalived提供的VIP机制,实现单节点应用的高可用。

 

Keepalived+重启脚本+双机热备搭建

 

①首先创建一个对应的目录并下载keepalived安装包(提取码:s6aq)到Linux中并解压:

[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

②进入解压后的keepalived目录并构建安装环境,然后编译并安装:

[root@localhost]# cd keepalived-2.2.4[root@localhost]# ./configure --prefix=/soft/keepalived/[root@localhost]# make && make install

③进入安装目录的/soft/keepalived/etc/keepalived/并编辑配置文件:

[root@localhost]# cd /soft/keepalived/etc/keepalived/[root@localhost]# vi keepalived.conf

④编辑主机的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    }}

⑤克隆一台之前的虚拟机作为从(备)机,编辑从机的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.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    }}

⑥新建scripts目录并编写Nginx的重启脚本,check_nginx_pid_restart.sh:

[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    fifi

⑦编写的脚本文件需要更改编码格式,并赋予执行权限,否则可能执行失败:

[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

⑧由于安装keepalived时,是自定义的安装位置,因此需要拷贝一些文件到系统目录中:

[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/

⑨将keepalived加入系统服务并设置开启自启动,然后测试启动是否正常:

[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 # 重启keepalivedsystemctl stop keepalived.service # 停止keepalivedtail -f /var/log/messages # 查看keepalived运行时日志

⑩最后测试一下VIP是否生效,通过查看本机是否成功挂载虚拟IP:

[root@localhost]# ip addr

Nginx一网打尽:动静分离、压缩、缓存、黑白名单、跨域、高可用、性能优化...

从上图中可以明显看见虚拟IP已经成功挂载,但另外一台机器192.168.12.130并不会挂载这个虚拟IP,只有当主机下线后,作为从机的192.168.12.130才会上线,接替VIP。最后测试一下外网是否可以正常与VIP通信,即在Windows中直接ping VIP:

Nginx一网打尽:动静分离、压缩、缓存、黑白名单、跨域、高可用、性能优化...

外部通过VIP通信时,也可以正常Ping通,代表虚拟IP配置成功。

 

Nginx高可用性测试

经过上述步骤后,keepalived的VIP机制已经搭建成功,在上个阶段中主要做了几件事:

 

  • 一、为部署Nginx的机器挂载了VIP。

  • 二、通过keepalived搭建了主从双机热备。

  • 三、通过keepalived实现了Nginx宕机重启。

 

由于前面没有域名的原因,因此最初server_name配置的是当前机器的IP,所以需稍微更改一下nginx.conf的配置:

sever{    listen    80;    # 这里从机器的本地IP改为虚拟IP  server_name 192.168.12.111;  # 如果这里配置的是域名,那么则将域名的映射配置改为虚拟IP}

最后来实验一下效果:

Nginx一网打尽:动静分离、压缩、缓存、黑白名单、跨域、高可用、性能优化...

在上述过程中,首先分别启动了keepalived、nginx服务,然后通过手动停止nginx的方式模拟了Nginx宕机情况,过了片刻后再次查询后台进程,我们会发现nginx依旧存活。

从这个过程中不难发现,keepalived已经为我们实现了Nginx宕机后自动重启的功能,那么接着再模拟一下服务器出现故障时的情况:


Nginx一网打尽:动静分离、压缩、缓存、黑白名单、跨域、高可用、性能优化...

在上述过程中,我们通过手动关闭keepalived服务模拟了机器断电、硬件损坏等情况(因为机器断电等情况=主机中的keepalived进程消失),然后再次查询了一下本机的IP信息,很明显会看到VIP消失了!

现在再切换到另外一台机器:192.168.12.130来看看情况:

Nginx一网打尽:动静分离、压缩、缓存、黑白名单、跨域、高可用、性能优化...

此刻我们会发现,在主机192.168.12.129宕机后,VIP自动从主机飘移到了从机192.168.12.130上,而此时客户端的请求就最终会来到130这台机器的Nginx上。

最终,利用Keepalived对Nginx做了主从热备之后,无论是遇到线上宕机还是机房断电等各类故障时,都能够确保应用系统能够为用户提供7×24小时服务。

 

 

Nginx一网打尽:动静分离、压缩、缓存、黑白名单、跨域、高可用、性能优化...

# Nginx性能优化

Nginx一网打尽:动静分离、压缩、缓存、黑白名单、跨域、高可用、性能优化...

到这里文章的篇幅较长了,最后再来聊一下关于Nginx的性能优化,主要就简单说说收益最高的几个优化项,在这块就不再展开叙述了,毕竟影响性能都有多方面原因导致的,比如网络、服务器硬件、操作系统、后端服务、程序自身、数据库服务等,对于性能调优比较感兴趣的可以参考之前《JVM性能调优》中的调优思想

 

优化一:打开长连接配置

 

通常Nginx作为代理服务,负责分发客户端的请求,那么建议开启HTTP长连接,用户减少握手的次数,降低服务器损耗,具体如下:

upstream xxx {    # 长连接数    keepalive 32;    # 每个长连接提供的最大请求数    keepalived_requests 100;    # 每个长连接没有新的请求时,保持的最长时间    keepalive_timeout 60s;}

优化二、开启零拷贝技术

 

零拷贝这个概念,在大多数性能较为不错的中间件中都有出现,例如Kafka、Netty等,而Nginx中也可以配置数据零拷贝技术,如下:

sendfile on; # 开启零拷贝机制

零拷贝读取机制与传统资源读取机制的区别:

 

  • 传统方式:硬件–>内核–>用户空间–>程序空间–>程序内核空间–>网络套接字

  • 零拷贝方式:硬件–>内核–>程序内核空间–>网络套接字

 

从上述这个过程对比,很轻易就能看出两者之间的性能区别。

 

优化三、开启无延迟或多包共发机制

 

在Nginx中有两个较为关键的性能参数,即tcp_nodelay、tcp_nopush,开启方式如下:

tcp_nodelay on;tcp_nopush on;

TCP/IP协议中默认是采用了Nagle算法的,即在网络数据传输过程中,每个数据报文并不会立马发送出去,而是会等待一段时间,将后面的几个数据包一起组合成一个数据报文发送,但这个算法虽然提高了网络吞吐量,但是实时性却降低了。

因此你的项目属于交互性很强的应用,那么可以手动开启tcp_nodelay配置,让应用程序向内核递交的每个数据包都会立即发送出去。但这样会产生大量的TCP报文头,增加很大的网络开销。

相反,有些项目的业务对数据的实时性要求并不高,追求的则是更高的吞吐,那么则可以开启tcp_nopush配置项,这个配置就类似于“塞子”的意思,首先将连接塞住,使得数据先不发出去,等到拔去塞子后再发出去。设置该选项后,内核会尽量把小数据包拼接成一个大的数据包(一个MTU)再发送出去.

当然若一定时间后(一般为200ms),内核仍然没有积累到一个MTU的量时,也必须发送现有的数据,否则会一直阻塞。

tcp_nodelay、tcp_nopush两个参数是“互斥”的,如果追求响应速度的应用推荐开启tcp_nodelay参数,如IM、金融等类型的项目。如果追求吞吐量的应用则建议开启tcp_nopush参数,如调度系统、报表系统等。

注意:
①tcp_nodelay一般要建立在开启了长连接模式的情况下使用。
②tcp_nopush参数是必须要开启sendfile参数才可使用的。

 

优化四、调整Worker工作进程

 

Nginx启动后默认只会开启一个Worker工作进程处理客户端请求,而我们可以根据机器的CPU核数开启对应数量的工作进程,以此来提升整体的并发量支持,如下:

# 自动根据CPU核心数调整Worker进程数量worker_processes auto;

工作进程的数量最高开到8个就OK了,8个之后就不会有再大的性能提升。

同时也可以稍微调整一下每个工作进程能够打开的文件句柄数:

# 每个Worker能打开的文件描述符,最少调整至1W以上,负荷较高建议2-3Wworker_rlimit_nofile 20000;

操作系统内核(kernel)都是利用文件描述符来访问文件,无论是打开、新建、读取、写入文件时,都需要使用文件描述符来指定待操作的文件,因此该值越大,代表一个进程能够操作的文件越多(但不能超出内核限制,最多建议3.8W左右为上限)。

 

优化五、开启CPU亲和机制

 

对于并发编程较为熟悉的伙伴都知道,因为进程/线程数往往都会远超出系统CPU的核心数,因为操作系统执行的原理本质上是采用时间片切换机制,也就是一个CPU核心会在多个进程之间不断频繁切换,造成很大的性能损耗。

 

而CPU亲和机制则是指将每个Nginx的工作进程,绑定在固定的CPU核心上,从而减小CPU切换带来的时间开销和资源损耗,开启方式如下:

worker_cpu_affinity auto;

优化六、开启epoll模型及调整并发连接数

 

在最开始就提到过:Nginx、Redis都是基于多路复用模型去实现的程序,但最初版的多路复用模型select/poll最大只能监听1024个连接,而epoll则属于select/poll接口的增强版,因此采用该模型能够大程度上提升单个Worker的性能,如下:

events {    # 使用epoll网络模型    use epoll;    # 调整每个Worker能够处理的连接数上限    worker_connections  10240;}

这里对于select/poll/epoll模型就不展开细说了,后面的IO模型文章中会详细剖析。

 

 

Nginx一网打尽:动静分离、压缩、缓存、黑白名单、跨域、高可用、性能优化...

# 放在最后的结尾

Nginx一网打尽:动静分离、压缩、缓存、黑白名单、跨域、高可用、性能优化...

 

至此,Nginx的大部分内容都已阐述完毕,关于最后一小节的性能优化内容,其实在前面就谈到的动静分离、分配缓冲区、资源缓存、防盗链、资源压缩等内容,也都可归纳为性能优化的方案。

作者:竹子爱熊猫

来源:juejin.cn/post/7112826654291918855

适合小白的 Nginx 学习手册

 
Nginx 是一个高性能的 HTTP 和反向代理服务器,特点是占用内存少,并发能力强,事实上 Nginx 的并发能力确实在同类型的网页服务器中表现较好。

适合小白的 Nginx 学习手册 ( 收藏了 )

Nginx 专为性能优化而开发,性能是其最重要的要求,十分注重效率,有报告 Nginx 能支持高达 50000 个并发连接数。

01

Nginx 知识网结构图

Nginx 的知识网结构图如下:

适合小白的 Nginx 学习手册 ( 收藏了 )

02

反向代理

正向代理:局域网中的电脑用户想要直接访问网络是不可行的,只能通过代理服务器来访问,这种代理服务就被称为正向代理。
适合小白的 Nginx 学习手册 ( 收藏了 )
反向代理:客户端无法感知代理,因为客户端访问网络不需要配置,只要把请求发送到反向代理服务器,由反向代理服务器去选择目标服务器获取数据,然后再返回到客户端。
此时反向代理服务器和目标服务器对外就是一个服务器,暴露的是代理服务器地址,隐藏了真实服务器 IP 地址。
适合小白的 Nginx 学习手册 ( 收藏了 )
03
负载均衡
客户端发送多个请求到服务器,服务器处理请求,有一些可能要与数据库进行交互,服务器处理完毕之后,再将结果返回给客户端。
普通请求和响应过程如下图:
适合小白的 Nginx 学习手册 ( 收藏了 )
但是随着信息数量增长,访问量和数据量飞速增长,普通架构无法满足现在的需求。
我们首先想到的是升级服务器配置,可以由于摩尔定律的日益失效,单纯从硬件提升性能已经逐渐不可取了,怎么解决这种需求呢?
我们可以增加服务器的数量,构建集群,将请求分发到各个服务器上,将原来请求集中到单个服务器的情况改为请求分发到多个服务器,也就是我们说的负载均衡。
图解负载均衡:
适合小白的 Nginx 学习手册 ( 收藏了 )
假设有 15 个请求发送到代理服务器,那么由代理服务器根据服务器数量,平均分配,每个服务器处理 5 个请求,这个过程就叫做负载均衡。

04

动静分离

为了加快网站的解析速度,可以把动态页面和静态页面交给不同的服务器来解析,加快解析的速度,降低由单个服务器的压力。
动静分离之前的状态:
适合小白的 Nginx 学习手册 ( 收藏了 )
动静分离之后:
适合小白的 Nginx 学习手册 ( 收藏了 )
06
Nginx安装

Nginx 如何在 Linux 安装

参考链接:
https://blog.csdn.net/yujing1314/article/details/97267369

Nginx 常用命令

查看版本:
./nginx -v
启动:
./nginx
关闭(有两种方式,推荐使用 ./nginx -s quit):
 ./nginx -s stop
 ./nginx -s quit
重新加载 Nginx 配置:
./nginx -s reload

Nginx 的配置文件

配置文件分三部分组成:
①全局块
从配置文件开始到 events 块之间,主要是设置一些影响 Nginx 服务器整体运行的配置指令。
并发处理服务的配置,值越大,可以支持的并发处理量越多,但是会受到硬件、软件等设备的制约。
适合小白的 Nginx 学习手册 ( 收藏了 )
②events 块
影响 Nginx 服务器与用户的网络连接,常用的设置包括是否开启对多 workprocess 下的网络连接进行序列化,是否允许同时接收多个网络连接等等。
支持的最大连接数:
适合小白的 Nginx 学习手册 ( 收藏了 )
③HTTP 块
诸如反向代理和负载均衡都在此配置。
location[ = | ~ | ~* | ^~] url{

}
location 指令说明,该语法用来匹配 url,语法如上
  • =:用于不含正则表达式的 url 前,要求字符串与 url 严格匹配,匹配成功就停止向下搜索并处理请求。
  • ~:用于表示 url 包含正则表达式,并且区分大小写。
  • ~*:用于表示 url 包含正则表达式,并且不区分大小写。
  • ^~:用于不含正则表达式的 url 前,要求 Nginx 服务器找到表示 url 和字符串匹配度最高的 location 后,立即使用此 location 处理请求,而不再匹配。
  • 如果有 url 包含正则表达式,不需要有 ~ 开头标识。

07

反向代理实战

①配置反向代理

目的:在浏览器地址栏输入地址 www.123.com 跳转 Linux 系统 Tomcat 主页面。
②具体实现
先配置 Tomcat,因为比较简单,此处不再赘叙,并在 Windows 访问:
适合小白的 Nginx 学习手册 ( 收藏了 )
具体流程如下图:
适合小白的 Nginx 学习手册 ( 收藏了 )
修改之前:
适合小白的 Nginx 学习手册 ( 收藏了 )
配置如下:
适合小白的 Nginx 学习手册 ( 收藏了 )
再次访问:
适合小白的 Nginx 学习手册 ( 收藏了 )
③反向代理 2
目标:
  • 访问 http://192.168.25.132:9001/edu/ 直接跳转到 192.168.25.132:8080
  • 访问 http://192.168.25.132:9001/vod/ 直接跳转到 192.168.25.132:8081
准备:配置两个 Tomcat,端口分别为 8080 和 8081,都可以访问,端口修改配置文件即可。
适合小白的 Nginx 学习手册 ( 收藏了 )
适合小白的 Nginx 学习手册 ( 收藏了 )
新建文件内容分别添加 8080!!!和 8081!!!
适合小白的 Nginx 学习手册 ( 收藏了 )
适合小白的 Nginx 学习手册 ( 收藏了 )
响应如下图:
适合小白的 Nginx 学习手册 ( 收藏了 )
适合小白的 Nginx 学习手册 ( 收藏了 )
具体配置如下:
适合小白的 Nginx 学习手册 ( 收藏了 )
重新加载 Nginx:
./nginx -s reload
访问:
适合小白的 Nginx 学习手册 ( 收藏了 )
适合小白的 Nginx 学习手册 ( 收藏了 )
实现了同一个端口代理,通过 edu 和 vod 路径的切换显示不同的页面。
反向代理小结
第一个例子:浏览器访问 www.123.com,由 host 文件解析出服务器 ip 地址 192.168.25.132 www.123.com。
然后默认访问 80 端口,而通过 Nginx 监听 80 端口代理到本地的 8080 端口上,从而实现了访问 www.123.com,最终转发到 tomcat 8080 上去。
第二个例子:
  • 访问 http://192.168.25.132:9001/edu/ 直接跳转到 192.168.25.132:8080
  • 访问 http://192.168.25.132:9001/vod/ 直接跳转到 192.168.25.132:8081
实际上就是通过 Nginx 监听 9001 端口,然后通过正则表达式选择转发到 8080 还是 8081 的 Tomcat 上去。
08
负载均衡实战
①修改 nginx.conf,如下图:
适合小白的 Nginx 学习手册 ( 收藏了 )
适合小白的 Nginx 学习手册 ( 收藏了 )
②重启 Nginx:
./nginx -s reload
③在 8081 的 Tomcat 的 webapps 文件夹下新建 edu 文件夹和 a.html 文件,填写内容为 8081!!!!
④在地址栏回车,就会分发到不同的 Tomcat 服务器上:
适合小白的 Nginx 学习手册 ( 收藏了 )
适合小白的 Nginx 学习手册 ( 收藏了 )
负载均衡方式如下:
  • 轮询(默认)。
  • weight,代表权,权越高优先级越高。
  • fair,按后端服务器的响应时间来分配请求,相应时间短的优先分配
  • ip_hash,每个请求按照访问 ip 的 hash 结果分配,这样每一个访客固定的访问一个后端服务器,可以解决 Session 的问题。

适合小白的 Nginx 学习手册 ( 收藏了 )

适合小白的 Nginx 学习手册 ( 收藏了 )

适合小白的 Nginx 学习手册 ( 收藏了 )

 

09
动静分离实战

什么是动静分离?把动态请求和静态请求分开,不是讲动态页面和静态页面物理分离,可以理解为 Nginx 处理静态页面,Tomcat 处理动态页面。

动静分离大致分为两种:
  • 纯粹将静态文件独立成单独域名放在独立的服务器上,也是目前主流方案。
  • 将动态跟静态文件混合在一起发布,通过 Nginx 分开。

动静分离图析:

适合小白的 Nginx 学习手册 ( 收藏了 )
实战准备,准备静态文件:
适合小白的 Nginx 学习手册 ( 收藏了 )
适合小白的 Nginx 学习手册 ( 收藏了 )
配置 Nginx,如下图:
适合小白的 Nginx 学习手册 ( 收藏了 )

Nginx 高可用

如果 Nginx 出现问题:
适合小白的 Nginx 学习手册 ( 收藏了 )
解决办法:
适合小白的 Nginx 学习手册 ( 收藏了 )
前期准备:
  • 两台 Nginx 服务器
  • 安装 Keepalived
  • 虚拟 ip

安装 Keepalived:

[root@192 usr]yum install keepalived -y
[root@192 usr]rpm -q -a keepalived
keepalived-1.3.5-16.el7.x86_64
修改配置文件:
[root@192 keepalived]# cd /etc/keepalived
[root@192 keepalived]# vi keepalived.conf
分别将如下配置文件复制粘贴,覆盖掉 keepalived.conf,虚拟 ip 为 192.168.25.50。
对应主机 ip 需要修改的是:
  • smtp_server 192.168.25.147(主)smtp_server 192.168.25.147(备)
  • state MASTER(主) state BACKUP
global_defs {
   notification_email {
     acassen@firewall.loc
     failover@firewall.loc
     sysadmin@firewall.loc
   }
   notification_email_from Alexandre.Cassen@firewall.loc
   smtp_server 192.168.25.147
   smtp_connect_timeout 30
   router_id LVS_DEVEL # 访问的主机地址
}

vrrp_script chk_nginx {
  script “/usr/local/src/nginx_check.sh”  # 检测文件的地址
  interval 2   # 检测脚本执行的间隔
  weight 2   # 权重
}

vrrp_instance VI_1 {
    state BACKUP    # 主机MASTER、备机BACKUP    
    interface ens33   # 网卡
    virtual_router_id 51 # 同一组需一致
    priority 90  # 访问优先级,主机值较大,备机较小
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.25.50  # 虚拟ip
    }
}
启动代码如下:
[root@192 sbin]# systemctl start keepalived.service
适合小白的 Nginx 学习手册 ( 收藏了 )
访问虚拟 ip 成功:
适合小白的 Nginx 学习手册 ( 收藏了 )
关闭主机 147 的 Nginx 和 Keepalived,发现仍然可以访问。

原理解析

适合小白的 Nginx 学习手册 ( 收藏了 )
如下图,就是启动了一个 master,一个 worker,master 是管理员,worker是具体工作的进程。
适合小白的 Nginx 学习手册 ( 收藏了 )
worker 如何工作?如下图:
适合小白的 Nginx 学习手册 ( 收藏了 )
小结
worker 数应该和 CPU 数相等;一个 master 多个 worker 可以使用热部署,同时 worker 是独立的,一个挂了不会影响其他的。

全栈开发者社区

来源:https://reurl.cc/5oOQ3R

转自:https://mp.weixin.qq.com/s/4zGk7ulcdKcu7loyoFFE3g

就是要让你搞懂Nginx,这篇就够了!

来自:CSDN,作者:渐暖°

链接:https://blog.csdn.net/yujing1314/article/details/107000737

 

 

Nginx 是一个高性能的 HTTP 和反向代理服务器,特点是占用内存少,并发能力强,事实上 Nginx 的并发能力确实在同类型的网页服务器中表现较好。

 

Nginx 专为性能优化而开发,性能是其最重要的要求,十分注重效率,有报告 Nginx 能支持高达 50000 个并发连接数。

Nginx 知识网结构图

Nginx 的知识网结构图如下:

就是要让你搞懂Nginx,这篇就够了!

反向代理

 

正向代理:局域网中的电脑用户想要直接访问网络是不可行的,只能通过代理服务器来访问,这种代理服务就被称为正向代理。

就是要让你搞懂Nginx,这篇就够了!

反向代理:客户端无法感知代理,因为客户端访问网络不需要配置,只要把请求发送到反向代理服务器,由反向代理服务器去选择目标服务器获取数据,然后再返回到客户端。

此时反向代理服务器和目标服务器对外就是一个服务器,暴露的是代理服务器地址,隐藏了真实服务器 IP 地址。

就是要让你搞懂Nginx,这篇就够了!

负载均衡

 

客户端发送多个请求到服务器,服务器处理请求,有一些可能要与数据库进行交互,服务器处理完毕之后,再将结果返回给客户端。

普通请求和响应过程如下图:

就是要让你搞懂Nginx,这篇就够了!

但是随着信息数量增长,访问量和数据量飞速增长,普通架构无法满足现在的需求。

我们首先想到的是升级服务器配置,可以由于摩尔定律的日益失效,单纯从硬件提升性能已经逐渐不可取了,怎么解决这种需求呢?

我们可以增加服务器的数量,构建集群,将请求分发到各个服务器上,将原来请求集中到单个服务器的情况改为请求分发到多个服务器,也就是我们说的负载均衡。

图解负载均衡:

就是要让你搞懂Nginx,这篇就够了!

假设有 15 个请求发送到代理服务器,那么由代理服务器根据服务器数量,平均分配,每个服务器处理 5 个请求,这个过程就叫做负载均衡。

 

动静分离

为了加快网站的解析速度,可以把动态页面和静态页面交给不同的服务器来解析,加快解析的速度,降低由单个服务器的压力。

动静分离之前的状态:

就是要让你搞懂Nginx,这篇就够了!

动静分离之后:

就是要让你搞懂Nginx,这篇就够了!

Nginx 如何在 Linux 安装

参考链接:
https://blog.csdn.net/yujing1314/article/details/97267369

Nginx 常用命令

查看版本:
./nginx -v
启动:
./nginx
关闭(有两种方式,推荐使用 ./nginx -s quit):
 ./nginx -s stop
 ./nginx -s quit
重新加载 Nginx 配置:
./nginx -s reload

Nginx 的配置文件

配置文件分三部分组成:

 

①全局块

从配置文件开始到 events 块之间,主要是设置一些影响 Nginx 服务器整体运行的配置指令。

并发处理服务的配置,值越大,可以支持的并发处理量越多,但是会受到硬件、软件等设备的制约。
就是要让你搞懂Nginx,这篇就够了!
②events 块

影响 Nginx 服务器与用户的网络连接,常用的设置包括是否开启对多 workprocess 下的网络连接进行序列化,是否允许同时接收多个网络连接等等。

支持的最大连接数:
就是要让你搞懂Nginx,这篇就够了!
③HTTP 块
诸如反向代理和负载均衡都在此配置。
location[ = | ~ | ~* | ^~] url{

}

location 指令说明,该语法用来匹配 url,语法如上

  • =:用于不含正则表达式的 url 前,要求字符串与 url 严格匹配,匹配成功就停止向下搜索并处理请求。

  • ~:用于表示 url 包含正则表达式,并且区分大小写。

  • ~*:用于表示 url 包含正则表达式,并且不区分大小写。

  • ^~:用于不含正则表达式的 url 前,要求 Nginx 服务器找到表示 url 和字符串匹配度最高的 location 后,立即使用此 location 处理请求,而不再匹配。

  • 如果有 url 包含正则表达式,不需要有 ~ 开头标识。

 

反向代理实战

 

①配置反向代理

 

目的:在浏览器地址栏输入地址 www.123.com 跳转 Linux 系统 Tomcat 主页面。

②具体实现

先配置 Tomcat,因为比较简单,此处不再赘叙,并在 Windows 访问:
就是要让你搞懂Nginx,这篇就够了!

具体流程如下图:

就是要让你搞懂Nginx,这篇就够了!

修改之前:

就是要让你搞懂Nginx,这篇就够了!

配置如下:

就是要让你搞懂Nginx,这篇就够了!

再次访问:

就是要让你搞懂Nginx,这篇就够了!

③反向代理 2

 

目标:

  • 访问 http://192.168.25.132:9001/edu/ 直接跳转到 192.168.25.132:8080

  • 访问 http://192.168.25.132:9001/vod/ 直接跳转到 192.168.25.132:8081

准备:配置两个 Tomcat,端口分别为 8080 和 8081,都可以访问,端口修改配置文件即可。

就是要让你搞懂Nginx,这篇就够了!

就是要让你搞懂Nginx,这篇就够了!

新建文件内容分别添加 8080!!!和 8081!!!

就是要让你搞懂Nginx,这篇就够了!

就是要让你搞懂Nginx,这篇就够了!

响应如下图:

就是要让你搞懂Nginx,这篇就够了!

就是要让你搞懂Nginx,这篇就够了!

具体配置如下:

就是要让你搞懂Nginx,这篇就够了!

重新加载 Nginx:

./nginx -s reload

 

访问:

就是要让你搞懂Nginx,这篇就够了!

就是要让你搞懂Nginx,这篇就够了!

实现了同一个端口代理,通过 edu 和 vod 路径的切换显示不同的页面。

反向代理小结

第一个例子:浏览器访问 www.123.com,由 host 文件解析出服务器 ip 地址
192.168.25.132 www.123.com。

然后默认访问 80 端口,而通过 Nginx 监听 80 端口代理到本地的 8080 端口上,从而实现了访问 www.123.com,最终转发到 tomcat 8080 上去。

第二个例子:

  • 访问 http://192.168.25.132:9001/edu/ 直接跳转到 192.168.25.132:8080

  • 访问 http://192.168.25.132:9001/vod/ 直接跳转到 192.168.25.132:8081

实际上就是通过 Nginx 监听 9001 端口,然后通过正则表达式选择转发到 8080 还是 8081 的 Tomcat 上去。

 

负载均衡实战

 

①修改 nginx.conf,如下图:
就是要让你搞懂Nginx,这篇就够了!

就是要让你搞懂Nginx,这篇就够了!

②重启 Nginx:
./nginx -s reload

③在 8081 的 Tomcat 的 webapps 文件夹下新建 edu 文件夹和 a.html 文件,填写内容为 8081!!!!

④在地址栏回车,就会分发到不同的 Tomcat 服务器上:

就是要让你搞懂Nginx,这篇就够了!

就是要让你搞懂Nginx,这篇就够了!

负载均衡方式如下:

  • 轮询(默认)。

  • weight,代表权,权越高优先级越高。

  • fair,按后端服务器的响应时间来分配请求,相应时间短的优先分配

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

就是要让你搞懂Nginx,这篇就够了!

就是要让你搞懂Nginx,这篇就够了!

就是要让你搞懂Nginx,这篇就够了!

动静分离实战

什么是动静分离?把动态请求和静态请求分开,不是讲动态页面和静态页面物理分离,可以理解为 Nginx 处理静态页面,Tomcat 处理动态页面。

动静分离大致分为两种:

  • 纯粹将静态文件独立成单独域名放在独立的服务器上,也是目前主流方案。

  • 将动态跟静态文件混合在一起发布,通过 Nginx 分开。

 

动静分离图析:

就是要让你搞懂Nginx,这篇就够了!

实战准备,准备静态文件:

就是要让你搞懂Nginx,这篇就够了!

就是要让你搞懂Nginx,这篇就够了!

配置 Nginx,如下图:
就是要让你搞懂Nginx,这篇就够了!

Nginx 高可用

如果 Nginx 出现问题:
就是要让你搞懂Nginx,这篇就够了!
解决办法:

就是要让你搞懂Nginx,这篇就够了!

前期准备:

  • 两台 Nginx 服务器

  • 安装 Keepalived

  • 虚拟 ip

 

安装 Keepalived:

[root@192 usr]yum install keepalived -y
[root@192 usr]rpm -q -a keepalived
keepalived-1.3.5-16.el7.x86_64
修改配置文件:
[root@192 keepalived]# cd /etc/keepalived
[root@192 keepalived]# vi keepalived.conf

分别将如下配置文件复制粘贴,覆盖掉 keepalived.conf,虚拟 ip 为 192.168.25.50。

对应主机 ip 需要修改的是:

  • smtp_server 192.168.25.147(主)smtp_server 192.168.25.147(备)

  • state MASTER(主) state BACKUP(备)
global_defs {
   notification_email {
     acassen@firewall.loc
     failover@firewall.loc
     sysadmin@firewall.loc
   }
   notification_email_from Alexandre.Cassen@firewall.loc
   smtp_server 192.168.25.147
   smtp_connect_timeout 30
   router_id LVS_DEVEL # 访问的主机地址
}

vrrp_script chk_nginx {
  script "/usr/local/src/nginx_check.sh"  # 检测文件的地址
  interval 2   # 检测脚本执行的间隔
  weight 2   # 权重
}

vrrp_instance VI_1 {
    state BACKUP    # 主机MASTER、备机BACKUP    
    interface ens33   # 网卡
    virtual_router_id 51 # 同一组需一致
    priority 90  # 访问优先级,主机值较大,备机较小
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.25.50  # 虚拟ip
    }
}

 

启动代码如下:
[root@192 sbin]# systemctl start keepalived.service

就是要让你搞懂Nginx,这篇就够了!

访问虚拟 ip 成功:
就是要让你搞懂Nginx,这篇就够了!

关闭主机 147 的 Nginx 和 Keepalived,发现仍然可以访问。

原理解析

就是要让你搞懂Nginx,这篇就够了!

如下图,就是启动了一个 master,一个 worker,master 是管理员,worker是具体工作的进程。

就是要让你搞懂Nginx,这篇就够了!
worker 如何工作?如下图:

就是要让你搞懂Nginx,这篇就够了!

小结

worker 数应该和 CPU 数相等;一个 master 多个 worker 可以使用热部署,同时 worker 是独立的,一个挂了不会影响其他的。

 

转自:https://mp.weixin.qq.com/s/0IkKgthJdnC_UorZGS5Z0Q

Nginx通关攻略

1. Nginx简介

1.1 Nginx 概述

  • NGINX是一个免费、开源、高性能、轻量级的HTTP和反向代理服务器,也是一个电子邮件(IMAP/POP3)代理服务器,其特点是占有内存少,并发能力强。Nginx 因为它的稳定性、丰富的模块库、灵活的配置和较低的资源消耗而闻名 。目前应该是几乎所有项目建设必备。

  • Nginx由内核和一系列模块组成,内核提供web服务的基本功能,如启用网络协议,创建运行环境,接收和分配客户端请求,处理模块之间的交互。Nginx的各种功能和操作都由模块来实现。Nginx的模块从结构上分为核心模块、基础模块和第三方模块。

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

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

    第三方模块:HTTP Upstream Request Hash模块、Notice模块和HTTP Access Key模块及用户自己开发的模块

    这样的设计使Nginx方便开发和扩展,也正因此才使得Nginx功能如此强大。Nginx的模块默认编译进nginx中,如果需要增加或删除模块,需要重新编译Nginx,这一点不如Apache的动态加载模块方便。如果有需要动态加载模块,可以使用由淘宝网发起的web服务器Tengine,在nginx的基础上增加了很多高级特性,完全兼容Nginx,已被国内很多网站采用。

  • Nginx有很多扩展版本

    • 开源版  nginx.org
    • 商业版 NGINX Plus
    • 淘宝网发起的Web服务器 Tengine
    • 基于Nginx和Lua的Web平台 OpenResty

1.2 Nginx 作为 web 服务器

Web服务器也称为WWW(WORLD WIDE WEB)服务器,主要功能是提供网上信息浏览服务,常常以B/S(Browser/Server)方式提供服务。

  • 应用层使用HTTP协议。
  • HTML文档格式。
  • 浏览器统一资源定位器(URL)。

Nginx 可以作为静态页面的 web 服务器,同时还支持 CGI 协议的动态语言,比如 perl、php 等,但是不支持 java。Java 程序一般都通过与 Tomcat 配合完成。

作为一名Java猿帅,肯定要理解下Nginx和Tomcat的区别了:

Nginx、Apache和Tomcat

  • Nginx—— 由俄罗斯程序员Igor Sysoev所开发的轻量级、高并发HTTP服务器;

  • Apache HTTP Server Project,一个Apache基金会下的HTTP服务项目,和Nginx功能类似;

  • Apache Tomcat ,则是Apache基金会下的另外一个项目,是一个Application Server,更准确的说是一个

    servlet应用容器,与Apache HTTP Server和Nginx相比,Tomcat能够动态的生成资源并返回到客户端;

Apache HTTP Server和Nginx本身不支持生成动态页面,但它们可以通过其他模块来支持(例如通过Shell、PHP、Python脚本程序来动态生成内容);

一个 HTTP Server 关心的是 HTTP 协议层面的传输和访问控制,所以在 Apache/Nginx 上你可以看到代理、负载均衡等功能。客户端通过 HTTP Server 访问服务器上存储的资源(HTML 文件、图片文件等等)。通过 CGI 技术,也可以将处理过的内容通过 HTTP Server 分发,但是一个 HTTP Server 始终只是把服务器上的文件如实的通过 HTTP 协议传输给客户端。

而应用服务器,则是一个应用执行的容器。它首先需要支持开发语言的运行(对于 Tomcat 来说,就是 Java),保证应用能够在应用服务器上正常运行。其次,需要支持应用相关的规范,例如类库、安全方面的特性。对于 Tomcat 来说,就是需要提供 JSP/Sevlet 运行需要的标准类库、Interface 等。为了方便,应用服务器往往也会集成 HTTP Server 的功能,但是不如专业的 HTTP Server 那么强大,所以应用服务器往往是运行在 HTTP Server 的背后,执行应用,将动态的内容转化为静态的内容之后,通过 HTTP Server 分发到客户端。

1.3 正向代理

正向代理:如果把局域网外的 Internet 想象成一个巨大的资源库,则局域网中的客户端要访 问 Internet,则需要通过代理服务器来访问,这种代理服务就称为正向代理。

正向代理“代理”的是客户端

比如在家办公期间,需要连公司的 VPN 办公,这个就是所谓的”正向代理“。还有我们访问 google也是。

Nginx通关攻略

1.4 反向代理 与 负载均衡

反向代理正好与正向代理相反,反向代理是指以代理服务器来接收Internet上的连接请求,然后将请求转发到内部网络上的服务器,并将服务器上得到的结果返回给客户端,此时代理服务器对外表现就是一个服务器,客户端对代理是无感知的。

反向代理“代理”的是服务端

再比如,你想本本分分的在“优酷”上看个“爱情片”,youku.com会把你的请求分发到存放片片的那台机器上,这个就是所谓的”反向代理“。

Nginx通关攻略

为什么使用反向代理

  • 保护和隐藏原始资源服务器
  • 加密和SSL加速
  • 通过缓存静态资源,加速Web请求
  • 实现负载均衡

负载均衡

地址重定向

Nginx 的Rewrite主要的功能就是实现URL重写

比如输入360.com  跳转到了360.cn,baidu.cn跳转到了baidu.com

1.5 动静分离

为了加快网站的解析速度,可以把动态页面和静态页面由不同的服务器来解析,加快解析速度,降低原来单个服务器的压力。这里指的就是让动态程序(Java、PHP)去访问应用服务器,让缓存、图片、JS、CSS等去访问Nginx。


2. Nginx 安装

  1. 下载Nginx

    wget http://nginx.org/download/nginx-1.16.1.tar.gz
    
  2. 安装需要编译的插件

    yum install gcc c++
    yum install -y pcre pcre-devel
    yum install -y zlib zlib-devel
    yum install -y openssl openssl-devel
    
    • 用于编译c、c++代码的GCC;

    • 用c语言编写的正则表达式函数库Pcre(使用rewrite模块);

    • 用于数据压缩的函式库的Zlib;

    • 安全套接字层密码库OpenSSL(启用SSL支持)

  3. 解压、配置(Nginx支持各种配置选项,文末一一列出 Nginx配置选项 )、编译、安装nginx

    tar -zxvf nginx-1.15.tar.gz cd nginx-1.16.1
    cd nginx-1.16.1
    ./configure
    make && sudo make install
    
  4. 启动、重启、关闭

    cd /usr/local/nginx/
    cd sbin
    ./nginx
    #关闭命令
    ./nginx -s stop
    #重启,热部署
    ./nginx -s reload
    #修改配置文件后也别嘚瑟,反正我会动不动就写错,检查修改的nginx.conf配置是否正确
    ./nginx -t
    
    Nginx通关攻略
  5. 验证(浏览器输入ip)

    Nginx通关攻略

3. 配置文件

nginx.conf 配置文件主要分为三部分:全局块、events块、https块。

Nginx配置语法:

  • 配置文件由指令和指令块构成
  • 每条指令以分号(;)结尾,指令和参数间以空格符分隔
  • 指令块以大括号{}将多条指令组织在一起
  • include语句允许组合多个配置文件以提高可维护性
  • 使用 # 添加注释
  • 使用 $ 定义变量
  • 部分指令的参数支持正则表达式

3.1 全局块

全局配置部分用来配置对整个server都有效的参数。主要会设置一些影响 nginx 服务器整体运行的配置指令,主要包括配置运行 Nginx 服务器的用户(组)、允许生成的 worker process 数,进程 PID 存放路径、日志存放路径和类型以 及配置文件的引入等。示例:

user nobody;
worker_processes  4;
error_log  /data/nginx/logs/error.log  notice;

3.2 events 块

events 块涉及的指令主要影响 Nginx 服务器与用户的网络连接,常用的设置包括是否开启对多 work process 下的网络连接进行序列化,是否允许同时接收多个网络连接,选取哪种事件驱动模型来处理连接请求,每个 word process 可以同时支持的最大连接数等。

events {
#每个 work process 支持的最大连接数为 1024.
    worker_connections  1024;
}

3.3 http 块

这算是 Nginx 服务器配置中最频繁的部分,代理、缓存和日志定义等绝大多数功能和第三方模块的配置都在这里。需要注意的是:http 块也可以包括 http 全局块、server 块。

3.3.1 http 全局块

http 全局块配置的指令包括文件引入、MIME-TYPE 定义、日志自定义、连接超时时间、单链接请求数上限等。

http {
    include       mime.types;
    default_type  application/octet-stream;
sendfile        on;
keepalive_timeout  65;
3.3.2 server 块

这块和虚拟主机有密切关系,虚拟主机从用户角度看,和一台独立的硬件主机是完全一样的,该技术的产生是为了 节省互联网服务器硬件成本。

每个 http 块可以包括多个 server 块,而每个 server 块就相当于一个虚拟主机。

而每个 server 块也分为全局 server 块,以及可以同时包含多个 locaton 块。

  • 全局 server 块

    也被叫做“虚拟服务器”部分,它描述的是一组根据不同server_name指令逻辑分割的资源,这些虚拟服务器响应HTTP请求,因此都包含在http部分。最常见的配置是本虚拟机主机的监听配置和本虚拟主机的名称或 IP 配置。

    server {
      listen       80;
      #server_name也支持通配符,*.example.com、www.example.*、.example.com
      server_name  localhost;
      #charset koi8-r;
      #access_log  logs/host.access.log  main;
    
  • location 块

    一个 server 块可以配置多个 location 块。

    这块的主要作用是基于 Nginx 服务器接收到的请求字符串(例如 server_name/uri-string),对虚拟主机名称 (也可以是 IP 别名)之外的字符串(例如 前面的 /uri-string)进行匹配,对特定的请求进行处理。地址定向、数据缓存和应答控制等功能,还有许多第三方模块的配置也在这里进行。

    location 指令说明

    该指令用于匹配 URL。

    语法如下:location [ = | ~ | ~* | ^~] uri{}

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

    当一个请求进入时,URI将会被检测匹配一个最佳的location。

     location / {
     root   html;
        index  index.html index.htm;
        }
      
      #error_page  404              /404.html;
      
      # redirect server error pages to the static page /50x.html
      #
      error_page   500 502 503 504  /50x.html;
      location = /50x.html {
      root   html;
      }
      location / {
          #try_files指令将会按照给定的参数顺序进行匹配尝试
          try_files $uri $uri/ /index.html;
      }
    
    • 没有正则表达式的location被作为最佳的匹配,独立于含有正则表达式的location顺序;
    • 在配置文件中按照查找顺序进行正则表达式匹配。在查找到第一个正则表达式匹配之后结束查找。由这个最佳的location提供请求处理。
    • = :该修饰符使用精确匹配并且终止搜索。
    • ~:该修饰符使用区分大小写的正则表达式匹配。
    • ~*:该修饰符使用不区分大小写的正则表达式匹配。
    • ^~:用于不含正则表达式的 uri 前,要求 Nginx 服务器找到标识 uri 和请求字 符串匹配度最高的 location 后,立即使用此 location 处理请求,而不再使用 location 块中的正则 uri 和请求字符串做匹配。

nginx.conf 详细配置

#定义Nginx运行的用户和用户组
user www www;

#nginx进程数,通常设置成和cpu的数量相等
worker_processes 4;

#全局错误日志定义类型,[debug | info | notice | warn | error | crit]
#error_log  /data/nginx/logs/error.log;
#error_log  /data/nginx/logs/error.log  notice;

#日志文件存放路径 access_log path [format [buffer=size | off]]
access_log /data/nginx/logs/lazyegg.com/web/access.log combinedio;

#进程pid文件
#pid        logs/nginx.pid;

#指定进程可以打开的最大描述符:数目
#工作模式与连接数上限
##这个指令是指当一个nginx进程打开的最多文件描述符数目,理论值应该是最多打开文件数(ulimit -n)与nginx进程数相除,但是nginx分配请求并不是那么均匀,所以最好与ulimit -n 的值保持一致。
#这是因为nginx调度时分配请求到进程并不是那么的均衡,所以假如填写10240,总并发量达到3-4万时就有进程可能超过10240了,这时会返回502错误。
worker_rlimit_nofile 65535;

#################################  events  ###############################
events {
    #参考事件模型,use [ kqueue | rtsig | epoll | /dev/poll | select | poll ]; epoll模型
    use epoll
    #单个进程最大连接数(最大连接数=连接数+进程数)
    worker_connections  1024;
    
    #keepalive 超时时间
    keepalive_timeout 60;
    
    #客户端请求头部的缓冲区大小。
    client_header_buffer_size 4k;
    
    #这个将为打开文件指定缓存,默认是没有启用的,max指定缓存数量,建议和打开文件数一致,inactive是指经过多长时间文件没被请求后删除缓存。
    open_file_cache max=65535 inactive=60s;
    #这个是指多长时间检查一次缓存的有效信息。
    open_file_cache_valid 80s;
        #open_file_cache指令中的inactive参数时间内文件的最少使用次数,如果超过这个数字,文件描述符一直是在缓存中打开的,如上例,如果有一个文件在inactive时间内一次没被使用,它将被移除。
    open_file_cache_min_uses 1;
    
    #语法:open_file_cache_errors on | off 默认值:open_file_cache_errors off 使用字段:http, server, location 这个指令指定是否在搜索一个文件是记录cache错误.
    open_file_cache_errors on;
}

##############################   http    ##################################

#设定http服务器,利用它的反向代理功能提供负载均衡支持
http{
    #文件扩展名与文件类型映射表
    include mime.types;
    
    #默认文件类型
    default_type application/octet-stream;
    
    #默认编码
    charset utf-8;
    
    #服务器名字的hash表大小
    server_names_hash_bucket_size 128;
    
    #客户端请求头部的缓冲区大小。
    client_header_buffer_size 32k;
    
    #客户请求头缓冲大小。
    large_client_header_buffers 4 64k;
    
    #允许客户端请求的最大单个文件字节数
    client_max_body_size 8m;
    
    #开启高效文件传输模式,sendfile指令指定nginx是否调用sendfile函数来输出文件,对于普通应用设为 on,如果用来进行下载等应用磁盘IO重负载应用,可设置为off,以平衡磁盘与网络I/O处理速度,降低系统的负载。注意:如果图片显示不正常把这个改成off。
    sendfile on;
    
    #开启目录列表访问,适合下载服务器,默认关闭。
    autoindex on;
    
    #此选项允许或禁止使用socke的TCP_CORK的选项,此选项仅在使用sendfile的时候使用
    tcp_nopush on;
     
    tcp_nodelay on;
    
    #长连接超时时间,单位是秒
    keepalive_timeout 120;
    
    #FastCGI相关参数是为了改善网站的性能:减少资源占用,提高访问速度。下面参数看字面意思都能理解。
    fastcgi_connect_timeout 300;
    fastcgi_send_timeout 300;
    fastcgi_read_timeout 300;
    fastcgi_buffer_size 64k;
    fastcgi_buffers 4 64k;
    fastcgi_busy_buffers_size 128k;
    fastcgi_temp_file_write_size 128k;
    
    #gzip模块设置
    gzip on; #开启gzip压缩输出
    gzip_min_length 1k;    #最小压缩文件大小
    gzip_buffers 4 16k;    #压缩缓冲区
    gzip_http_version 1.0; #压缩版本(默认1.1,前端如果是squid2.5请使用1.0)
    gzip_comp_level 2;     #压缩等级
    gzip_types text/plain application/x-javascript text/css application/xml;    #压缩类型,默认就已经包含textml,所以下面就不用再写了,写上去也不会有问题,但是会有一个warn。
    gzip_vary on;

    #开启限制IP连接数的时候需要使用
    #limit_zone crawler $binary_remote_addr 10m;
    
        #负载均衡配置
    upstream lazyegg.net {
  
        #upstream的负载均衡,weight是权重,可以根据机器配置定义权重。weigth参数表示权值,权值越高被分配到的几率越大。
        server 192.168.80.121:80 weight=3;
        server 192.168.80.122:80 weight=2;
        server 192.168.80.123:80 weight=3;

        #nginx的upstream目前支持4种方式的分配
        #1、轮询(默认)
        #每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动剔除。
        #2、weight
        #指定轮询几率,weight和访问比率成正比,用于后端服务器性能不均的情况。
        #例如:
        #upstream bakend {
        #    server 192.168.0.14 weight=10;
        #    server 192.168.0.15 weight=10;
        #}
        #2、ip_hash
        #每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器,可以解决session的问题。
        #例如:
        #upstream bakend {
        #    ip_hash;
        #    server 192.168.0.14:88;
        #    server 192.168.0.15:80;
        #}
        #3、fair(第三方)
        #按后端服务器的响应时间来分配请求,响应时间短的优先分配。
        #upstream backend {
        #    server server1;
        #    server server2;
        #    fair;
        #}
        #4、url_hash(第三方)
        #按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,后端服务器为缓存时比较有效。
        #例:在upstream中加入hash语句,server语句中不能写入weight等其他的参数,hash_method是使用的hash算法
        #upstream backend {
        #    server squid1:3128;
        #    server squid2:3128;
        #    hash $request_uri;
        #    hash_method crc32;
        #}

        #tips:
        #upstream bakend{#定义负载均衡设备的Ip及设备状态}{
        #    ip_hash;
        #    server 127.0.0.1:9090 down;
        #    server 127.0.0.1:8080 weight=2;
        #    server 127.0.0.1:6060;
        #    server 127.0.0.1:7070 backup;
        #}
        #在需要使用负载均衡的server中增加 proxy_pass http://bakend/;

        #每个设备的状态设置为:
        #1.down表示单前的server暂时不参与负载
        #2.weight为weight越大,负载的权重就越大。
        #3.max_fails:允许请求失败的次数默认为1.当超过最大次数时,返回proxy_next_upstream模块定义的错误
        #4.fail_timeout:max_fails次失败后,暂停的时间。
        #5.backup:其它所有的非backup机器down或者忙的时候,请求backup机器。所以这台机器压力会最轻。

        #nginx支持同时设置多组的负载均衡,用来给不用的server来使用。
        #client_body_in_file_only设置为On 可以讲client post过来的数据记录到文件中用来做debug
        #client_body_temp_path设置记录文件的目录 可以设置最多3层目录
        #location对URL进行匹配.可以进行重定向或者进行新的代理 负载均衡
    }
    
       #虚拟主机的配置
    server {
        #监听端口
        listen 80;

        #域名可以有多个,用空格隔开
        server_name lazyegg.net;
        #默认入口文件名称
        index index.html index.htm index.php;
        root /data/www/lazyegg;

        #对******进行负载均衡
        location ~ .*.(php|php5)?$
        {
            fastcgi_pass 127.0.0.1:9000;
            fastcgi_index index.php;
            include fastcgi.conf;
        }
         
        #图片缓存时间设置
        location ~ .*.(gif|jpg|jpeg|png|bmp|swf)$
        {
            expires 10d;
        }
         
        #JS和CSS缓存时间设置
        location ~ .*.(js|css)?$
        {
            expires 1h;
        }
         
        #日志格式设定
        #$remote_addr与$http_x_forwarded_for用以记录客户端的ip地址;
        #$remote_user:用来记录客户端用户名称;
        #$time_local:用来记录访问时间与时区;
        #$request:用来记录请求的url与http协议;
        #$status:用来记录请求状态;成功是200,
        #$body_bytes_sent :记录发送给客户端文件主体内容大小;
        #$http_referer:用来记录从那个页面链接访问过来的;
        #$http_user_agent:记录客户浏览器的相关信息;
        #通常web服务器放在反向代理的后面,这样就不能获取到客户的IP地址了,通过$remote_add拿到的IP地址是反向代理服务器的iP地址。反向代理服务器在转发请求的http头信息中,可以增加x_forwarded_for信息,用以记录原有客户端的IP地址和原来客户端的请求的服务器地址。
        log_format access '$remote_addr - $remote_user [$time_local] "$request" '
        '$status $body_bytes_sent "$http_referer" '
        '"$http_user_agent" $http_x_forwarded_for';
         
        #定义本虚拟主机的访问日志
        access_log  /usr/local/nginx/logs/host.access.log  main;
        access_log  /usr/local/nginx/logs/host.access.404.log  log404;
         
        #对 "/connect-controller" 启用反向代理
        location /connect-controller {
            proxy_pass http://127.0.0.1:88; #请注意此处端口号不能与虚拟主机监听的端口号一样(也就是server监听的端口)
            proxy_redirect off;
            proxy_set_header X-Real-IP $remote_addr;
             
            #后端的Web服务器可以通过X-Forwarded-For获取用户真实IP
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
             
            #以下是一些反向代理的配置,可选。
            proxy_set_header Host $host;

            #允许客户端请求的最大单文件字节数
            client_max_body_size 10m;

            #缓冲区代理缓冲用户端请求的最大字节数,
            #如果把它设置为比较大的数值,例如256k,那么,无论使用firefox还是IE浏览器,来提交任意小于256k的图片,都很正常。如果注释该指令,使用默认的client_body_buffer_size设置,也就是操作系统页面大小的两倍,8k或者16k,问题就出现了。
            #无论使用firefox4.0还是IE8.0,提交一个比较大,200k左右的图片,都返回500 Internal Server Error错误
            client_body_buffer_size 128k;

            #表示使nginx阻止HTTP应答代码为400或者更高的应答。
            proxy_intercept_errors on;

            #后端服务器连接的超时时间_发起握手等候响应超时时间
            #nginx跟后端服务器连接超时时间(代理连接超时)
            proxy_connect_timeout 90;

            #后端服务器数据回传时间(代理发送超时)
            #后端服务器数据回传时间_就是在规定时间之内后端服务器必须传完所有的数据
            proxy_send_timeout 90;

            #连接成功后,后端服务器响应时间(代理接收超时)
            #连接成功后_等候后端服务器响应时间_其实已经进入后端的排队之中等候处理(也可以说是后端服务器处理请求的时间)
            proxy_read_timeout 90;

            #设置代理服务器(nginx)保存用户头信息的缓冲区大小
            #设置从被代理服务器读取的第一部分应答的缓冲区大小,通常情况下这部分应答中包含一个小的应答头,默认情况下这个值的大小为指令proxy_buffers中指定的一个缓冲区的大小,不过可以将其设置为更小
            proxy_buffer_size 4k;

            #proxy_buffers缓冲区,网页平均在32k以下的设置
            #设置用于读取应答(来自被代理服务器)的缓冲区数目和大小,默认情况也为分页大小,根据操作系统的不同可能是4k或者8k
            proxy_buffers 4 32k;

            #高负荷下缓冲大小(proxy_buffers*2)
            proxy_busy_buffers_size 64k;

            #设置在写入proxy_temp_path时数据的大小,预防一个工作进程在传递文件时阻塞太长
            #设定缓存文件夹大小,大于这个值,将从upstream服务器传
            proxy_temp_file_write_size 64k;
        }
        
        #本地动静分离反向代理配置
        #所有jsp的页面均交由tomcat或resin处理
        location ~ .(jsp|jspx|do)?$ {
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_pass http://127.0.0.1:8080;
        }
    }
}

4. Nginx 配置实例

4.1 反向代理demo1

实现效果:使用 nginx 反向代理,访问 test.com 直接跳转到自己的机器 127.0.0.1:8080

  1. 启动一个 tomcat,浏览器地址栏输入 127.0.0.1:8080,出现如下界面
Nginx通关攻略
  1. 通过修改本地 host 文件(C:WindowsSystem32driversetc),添加127.0.0.1 www.12345.com将 www.12345.com 映射到自己的机器ip上

  2. 配置完成之后,我们便可以通过 www.test.com:8080 访问到第一步出现的 Tomcat 初始界面。那么如何只需要输入 www.12345.com 便可以跳转到 Tomcat 初始界面呢?便用到 nginx 的反向代理。

  3. 修改nginx.conf 配置文件,增加如下配置 proxy_pass

    server {
        listen       80;
        server_name  localhost;
        #charset koi8-r;
        #access_log  logs/host.access.log  main;
        location / {
               proxy_pass http://127.0.0.1:8080;
        }

  1. 如上配置,我们监听 80 端口,访问域名为 www.12345.com,不加端口号时默认为 80 端口,故访问该域名时会跳转到 127.0.0.1:8080 路径上。在浏览器端输入 www.12345.com 结果如下:
Nginx通关攻略

4.2 反向代理demo2

实现效果:使用 nginx 反向代理,根据访问的路径跳转到不同端口的服务中

访问 http://127.0.0.1/java/ 直接跳转到 127.0.0.1:8080

访问 http://127.0.0.1/egg/ 直接跳转到 127.0.0.1:8081

  1. 在服务器上起两个tomcat,修改其中一个端口号为8081;在tomcat/webapps/目录下的各加两个文件夹,并随便写个html页面),我建的是java/index.html和egg/index.html

  2. 修改nginx.conf,在http块中添加serve{}

    server {
            listen       80;
            server_name  localhost;
    
            location ~ /java/ {
                proxy_pass http://127.0.0.1:8080;
            }
    
            location /egg/ {
                proxy_pass http://127.0.0.1:8081;
            }
    }
    
  3. 重启nginx,验证效果

    Nginx通关攻略

4.3 Nginx 配置-负载均衡

随着互联网信息的爆炸性增长,负载均衡(load balance)已经不再是一个很陌生的话题, 顾名思义,负载均衡即是将负载分摊到不同的服务单元,既保证服务的可用性,又保证响应足够快,给用户很好的体验。快速增长的访问量和数据流量催生了各式各样的负载均衡产品, 很多专业的负载均衡硬件提供了很好的功能,但却价格不菲,这使得负载均衡软件大受欢迎, nginx 就是其中的一个,在 linux 下有 Nginx、LVS、Haproxy 等等服务可以提供负载均衡服务。

Nginx的负载均衡是proxy模块和upstream模块搭配实现的。upstream模块将会启用一个新的配置区段,在该区段定义了一组上游服务器。

实现效果:配置负载均衡

  1. 同时启动两个Tomcat(为了方便验证效果,修改tomcat端口号的同时,顺便将Tomcat默认欢迎页面apache-tomcat-9.0.29/webapps/ROOR目录下的index.jsp修改下,看下8081欢迎页的“蛋蛋”没)

    Nginx通关攻略
  2. 修改nginx.conf

    http {
        upstream myserver {
            server localhost:8080;
            server localhost:8081;
        }
        server {
            listen 80;
            location / {
                proxy_pass http://myserver;
            }
        }
    }
    
  3. 重启nginx,验证效果(默认轮询的方式,每次打开新窗口,8080和8081会交替出现,同一个窗口的话需要关闭浏览器缓存)

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;
     }
    

4.4 Nginx 配置-动静分离

Nginx 动静分离简单来说就是把动态跟静态请求分开,不能理解成只是单纯的把动态页面和静态页面物理分离。严格意义上说应该是动态请求跟静态请求分开,可以理解成使用 Nginx 处理静态页面,Tomcat 处理动态页面。动静分离从目前实现角度来讲大致分为两种, 一种是纯粹把静态文件独立成单独的域名,放在独立的服务器上,也是目前主流推崇的方案;另外一种方法就是动态跟静态文件混合在一起发布,通过 nginx 来分开。通过 location 指定不同的后缀名实现不同的请求转发。通过 expires 参数设置,可以使浏览器缓存过期时间,减少与服务器之前的请求和流量。具体 Expires 定义:是给一个资 源设定一个过期时间,也就是说无需去服务端验证,直接通过浏览器自身确认是否过期即可, 所以不会产生额外的流量。此种方法非常适合不经常变动的资源。(如果经常更新的文件, 不建议使用 Expires 来缓存),我这里设置 3d,表示在这 3 天之内访问这个 URL,发送 一个请求,比对服务器该文件最后更新时间没有变化,则不会从服务器抓取,返回状态码 304,如果有修改,则直接从服务器重新下载,返回状态码 200。

Nginx通关攻略
  1. 服务器找个目录存放自己的静态文件

    Nginx通关攻略
  2. 修改nginx.conf

        server {
            listen       80;
            server_name  localhost;
            location /static/ {
                root   /usr/data/www;
            }
            location /image/ {
                 root /usr/data/;
                 autoindex on;
            }
    
  3. ./nginx -s reload,验证效果

    Nginx通关攻略

添加监听端口、访问名字 重点是添加 location, 最后检查 Nginx 配置是否正确即可,然后测试动静分离是否成功,之需要删除后端 tomcat 服务器上的某个静态文件,查看是否能访问,如果可以访问说明静态资源 nginx 直接返回 了,不走后端 tomcat 服务器

4.5  Nginx的Rewrite

Rewrite是Nginx服务器提供的一个重要的功能,它可以实现URL重写和重定向功能。

场景:

  • URL访问跳转,支持开发设计。页面跳转、兼容性支持(新旧版本更迭)、展示效果(网址精简)等
  • SEO优化(Nginx伪静态的支持)
  • 后台维护、流量转发等
  • 安全(动态界面进行伪装)

该指令是通过正则表达式的使用来改变URI。可以同时存在一个或多个指令。需要按照顺序依次对URL进行匹配和处理。

该指令可以在server块或location块中配置,其基本语法结构如下:

rewrite regex replacement [flag];
  1. 采用反向代理demo2中的例子,修改nginx.conf(只多加了一行rewrite)

    server {
            listen       80;
            server_name  localhost;
    
            location /java/ {
                proxy_pass http://127.0.0.1:8080;
                rewrite ^/java /egg/ redirect;
            }
    
            location /egg/ {
                proxy_pass http://127.0.0.1:8081;
            }
    }
    
    
  2. ./nginx -s reload,验证效果(输入ip/java/被重定向到了egg)

    Nginx通关攻略

rewrite指令可以在server块或location块中配置,其基本语法结构如下:

rewrite regex replacement [flag];
  • rewrite的含义:该指令是实现URL重写的指令。
  • regex的含义:用于匹配URI的正则表达式。
  • replacement:将regex正则匹配到的内容替换成 replacement。
  • flag: flag标记,flag有如下值:
    • last: 本条规则匹配完成后,继续向下匹配新的location URI 规则。(不常用)
    • break: 本条规则匹配完成即终止,不再匹配后面的任何规则(不常用)。
    • redirect: 返回302临时重定向,浏览器地址会显示跳转新的URL地址。
    • permanent: 返回301永久重定向。浏览器地址会显示跳转新的URL地址。
rewrite ^/(.*) http://www.360.cn/$1 permanent;

4.6 Nginx 高可用

如果将Web服务器集群当做一个城池,那么负载均衡服务器就相当于城门。如果“城门”关闭了,与外界的通道就断了。如果只有一台Nginx负载服务器,当故障宕机的时候,就会导致整个网站无妨访问。所以我们需要两台以上Nginx来实现故障转移和高可用。

Nginx通关攻略

配置高可用

双机热备方案

这种方案是国内企业中最为普遍的一种高可用方案,双机热备其实就是指一台服务器在提供服务,另一台为某服务的备用状态,当一台服务器不可用另外一台就会顶替上去。

keepalived是什么?

Keepalived软件起初是专为LVS负载均衡软件设计的,用来管理并监控LVS集群系统中各个服务节点的状态,后来又加入了可以实现高可用的VRRP (Virtual Router Redundancy Protocol ,虚拟路由器冗余协议)功能。因此,Keepalived除了能够管理LVS软件外,还可以作为其他服务(例如:Nginx、Haproxy、MySQL等)的高可用解决方案软件

故障转移机制

Keepalived高可用服务之间的故障切换转移,是通过VRRP 来实现的。在 Keepalived服务正常工作时,主 Master节点会不断地向备节点发送(多播的方式)心跳消息,用以告诉备Backup节点自己还活着,当主 Master节点发生故障时,就无法发送心跳消息,备节点也就因此无法继续检测到来自主 Master节点的心跳了,于是调用自身的接管程序,接管主Master节点的 IP资源及服务。而当主 Master节点恢复时,备Backup节点又会释放主节点故障时自身接管的IP资源及服务,恢复到原来的备用角色。

实现

  1. 准备两台安装Nginx和keepaliver(yum install keepalived -y)的服务器

  2. 修改两台服务器上的/etc/keepalived/keepalived.conf

    #主机
    #检测脚本
    vrrp_script chk_http_port {
        script "/usr/local/src/check_nginx.sh" #心跳执行的脚本,检测nginx是否启动
        interval 2                          #(检测脚本执行的间隔,单位是秒)
        weight 2                            #权重
    }
    #vrrp 实例定义部分
    vrrp_instance VI_1 {
        state MASTER            # 指定keepalived的角色,MASTER为主,BACKUP为备
        interface ens33         # 当前进行vrrp通讯的网络接口卡(当前centos的网卡) 用ifconfig查看你具体的网卡
        virtual_router_id 66    # 虚拟路由编号,主从要一直
        priority 100            # 优先级,数值越大,获取处理请求的优先级越高
        advert_int 1            # 检查间隔,默认为1s(vrrp组播周期秒数)
        #授权访问
        authentication {
            auth_type PASS #设置验证类型和密码,MASTER和BACKUP必须使用相同的密码才能正常通信
            auth_pass 1111
        }
        track_script {
            chk_http_port            #(调用检测脚本)
        }
        virtual_ipaddress {
            192.168.16.150            # 定义虚拟ip(VIP),可多设,每行一个
        }
    }
    
    # 备机
    #检测脚本
    vrrp_script chk_http_port {
        script "/usr/local/src/check_nginx.sh" #心跳执行的脚本,检测nginx是否启动
        interval 2                          #(检测脚本执行的间隔)
        weight 2                            #权重
    }
    #vrrp 实例定义部分
    vrrp_instance VI_1 {
        state BACKUP                        # 指定keepalived的角色,MASTER为主,BACKUP为备
        interface ens33                      # 当前进行vrrp通讯的网络接口卡(当前centos的网卡) 用ifconfig查看你具体的网卡
        virtual_router_id 66                # 虚拟路由编号,主从要一直
        priority 99                         # 优先级,数值越大,获取处理请求的优先级越高
        advert_int 1                        # 检查间隔,默认为1s(vrrp组播周期秒数)
        #授权访问
        authentication {
            auth_type PASS #设置验证类型和密码,MASTER和BACKUP必须使用相同的密码才能正常通信
            auth_pass 1111
        }
        track_script {
            chk_http_port                   #(调用检测脚本)
        }
        virtual_ipaddress {
            192.168.16.150                   # 定义虚拟ip(VIP),可多设,每行一个
        }
    }
    
  3. 新建检测脚本(chmod 775 check_nginx.sh)

    #!/bin/bash
    #检测nginx是否启动了
    A=`ps -C nginx --no-header |wc -l`
    if [ $A -eq 0 ];then    #如果nginx没有启动就启动nginx
          systemctl start nginx                #重启nginx
          if [ `ps -C nginx --no-header |wc -l` -eq 0 ];then    #nginx重启失败,则停掉keepalived服务,进行VIP转移
                  killall keepalived
          fi
    fi
    
  4. 启动Nginx和keepalived(systemctl start keepalived.service)

  5. 模拟Nginx故障(关闭主服务器Nginx),验证,仍可以通过配置的虚拟ip访问,ok

5. Nginx 原理与优化参数配置

Nginx默认采用多进程工作方式,Nginx启动后,会运行一个master进程和多个worker进程。其中master充当整个进程组与用户的交互接口,同时对进程进行监护,管理worker进程来实现重启服务、平滑升级、更换日志文件、配置文件实时生效等功能。worker用来处理基本的网络事件,worker之间是平等的,他们共同竞争来处理来自客户端的请求

Nginx通关攻略

master-workers 的机制的好处

  1. 可以使用nginx-s reload 热部署
  2. 每个worker是独立的进程,不需要加锁,省掉了锁带来的开销。采用独立的进程,可以让互相之间不会影响,一个进程退出后,其它进程还在工作,服务不会中断,master 进程则很快启动新的 worker 进程。

需要设置多少个 worker

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

#设置 worker 数量。
 worker_processes 4
#work 绑定 cpu(4 work 绑定 4cpu)。
 worker_cpu_affinity 0001 0010 0100 1000
#work 绑定 cpu (4 work 绑定 8cpu 中的 4 个) 。
 worker_cpu_affinity 0000001 00000010 00000100 00001000

连接数 worker_connection

这个值是表示每个 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通关攻略

6. Nginx模块开发

由于Nginx的模块化特性,所以可以支持模块配置,也可以自定义模块,Nginx的模块开发,程序员目前还不需要太深入

Nginx模块分类

Nginx通关攻略

Nginx配置选项

解压nginx后的配置操作示例

./configure --prefix=/usr/local/nginx --with-http_stub_status_module --with-pcre  --with-http_ssl_module
选项 解释
–prefix=<path> Nginx安装的根目录,所有其他安装路径都要依赖于该选项
–sbin- path=<path> 指定Nginx二进制文件的路径
–conf-path=<path> 指定nginx.conf配置文件的路径
–error-log- path=<path> 指定错误文件的路径
–user=name worker进程运行的用户
–group=<group> worker进程运行的组
–with-http_ssl_module 使用https协议模块。默认情况下该模块没有被构建。前提是openssl与openssl-devel已安装
–with-http_image_filter_module 该模块被用作图像过滤器使用,将图像投递给客户前先进行过滤(需要libgd库)
–with-http_stub_status_module 启用这个模块会收集Nginx自身状态信息,常用来做监控
–with-mail 启用mail模块,默认没有被激活
–without-http_autoindex_module 禁用:如果一个目录没有index文件,该模块能收集文件并列出
–add-module=<path> 添加第三方外部模块,每次添加新的模块都要重新编译

7. Nginx 面试题

恭喜你顺利来到大猿帅面试阶段,没有夹道欢迎

  • Nginx功能,你们项目中用到的Nginx?

    反向代理服务器

    实现负载均衡

    做静态资源服务器

    作为http server

  • Nginx常用命令有哪写?

    启动nginx    ./sbin/nginx停止nginx    ./sbin/nginx -s stop   ./sbin/nginx -s quit重载配置      ./sbin/nginx -s reload(平滑重启) service nginx reload重载指定配置文件    ./sbin/nginx -c  /usr/local/nginx/conf/nginx.conf查看nginx版本  ./sbin/nginx -v检查配置文件是否正确  ./sbin/nginx -t显示帮助信息  ./sbin/nginx  -h

  • Nginx常用配置?

    worker_processes 4;   #工作进程数
    work_connections 65535; #每个进程的并发能力
    error_log  /data/nginx/logs/error.log;  #错误日志
    
  • Nginx是如何实现高并发的?

    Nginx 采用的是多进程(单线程) & 多路IO复用模型,,异步,非阻塞.

    一个主进程master,多个工作进程worker,每个工作进程可以处理多个请求

    master进程主要负责收集、分发请求。每当一个请求过来时,master就拉起一个worker进程负责处理这个请求。同时master进程也负责监控woker的状态,保证高可靠性

    在nginx中的work进程中,为了应对高并发场景,采取了Reactor模型(也就是I/O多路复用,NIO):

    **I/O 多路复用模型:**在 I/O 多路复用模型中,最重要的系统调用函数就是 select(其他的还有epoll等),该方法的能够同时监控多个文件描述符的可读可写情况(每一个网络连接其实都对应一个文件描述符),当其中的某些文件描述符可读或者可写时,select 方法就会返回可读以及可写的文件描述符个数。

    nginx work进程使用 I/O 多路复用模块同时监听多个 FD(文件描述符),当 accept、read、write 和 close 事件产生时,操作系统就会回调 FD 绑定的事件处理器,这时候work进程再去处理相应事件,而不是阻塞在某个请求连接上等待。这样就可以实现一个进程同时处理多个连接。

    • 每一个worker进程通过I/O多路复用处理多个连接请求;
    • 为了减少进程切换(需要系统调用)的性能损耗,一般设置worker进程数量和CPU数量一致。
  • nginx和apache的区别?

    轻量级,同样起web 服务,比apache 占用更少的内存及资源抗并发,nginx 处理请求是异步非阻塞的,而apache 则是阻塞型的,在高并发下nginx 能保持低资源低消耗高性能高度模块化的设计,编写模块相对简单最核心的区别在于apache是同步多进程模型,一个连接对应一个进程;nginx是异步的,多个连接(万级别)可以对应一个进程

  • nginx 的 upstream支持的负载均衡方式?

  • 轮询(默认)

  • weight  :指定权重

  • ip_hash :每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器

  • 第三方:fair、url_hash

  • Nginx常见的优化配置有哪些?

  1. 调整worker_processes : 指Nginx要生成的worker数量,最佳实践是每个CPU运行1个工作进程
  2. 最大化worker_connections :
  3. 启用Gzip压缩 : 压缩文件大小,减少了客户端http的传输带宽,因此提高了页面加载速度
  4. 为静态文件启用缓存
  5. 禁用access_logs : 访问日志记录,它记录每个nginx请求,因此消耗了大量CPU资源,从而降低了nginx性能

参考:

《Nginx核心知识100讲》《精通Nginx》https://juejin.im/post/5c1616186fb9a049a42ef21d《尚硅谷Nginx》

转自:https://mp.weixin.qq.com/s/me2_GvawL-DzSe1xmpaWvw

看完这篇还不了解 Nginx,那我就哭了!

作者:蔷薇Nina

www.cnblogs.com/wcwnina/p/8728391.html

想必大家一定听说过 Nginx,若没听说过它,那么一定听过它的”同行”Apache 吧!

Nginx 的产生

Nginx 同 Apache 一样都是一种 Web 服务器。基于 REST 架构风格,以统一资源描述符(Uniform Resources IdentifierURI 或者统一资源定位符(Uniform Resources LocatorURL 作为沟通依据,通过 HTTP 协议提供各种网络服务。

然而,这些服务器在设计之初受到当时环境的局限,例如当时的用户规模,网络带宽,产品特点等局限并且各自的定位和发展都不尽相同。这也使得各个 Web 服务器有着各自鲜明的特点。

Apache 的发展时期很长,而且是毫无争议的世界第一大服务器。它有着很多优点:稳定、开源、跨平台等等。

它出现的时间太长了,它兴起的年代,互联网产业远远比不上现在。所以它被设计为一个重量级的。

它不支持高并发的服务器。在 Apache 上运行数以万计的并发访问,会导致服务器消耗大量内存。

操作系统对其进行进程或线程间的切换也消耗了大量的 CPU 资源,导致 HTTP 请求的平均响应速度降低。

这些都决定了 Apache 不可能成为高性能 Web 服务器,轻量级高并发服务器 Nginx 就应运而生了。

俄罗斯的工程师 Igor Sysoev,他在为 Rambler Media 工作期间,使用 C 语言开发了 Nginx。

Nginx 作为 Web 服务器一直为 Rambler Media 提供出色而又稳定的服务。然后呢,Igor Sysoev 将 Nginx 代码开源,并且赋予自由软件许可证。

由于以下这几点,所以,Nginx 火了

 

  • Nginx 使用基于事件驱动架构,使得其可以支持数以百万级别的 TCP 连接。

  • 高度的模块化和自由软件许可证使得第三方模块层出不穷(这是个开源的时代啊

  • Nginx 是一个跨平台服务器,可以运行在 Linux、WindowsFreeBSDSolarisAIXMac OS 等操作系统上。

  • 这些优秀的设计带来的极大的稳定性。

Nginx 的用武之地

Nginx 是一款自由的、开源的、高性能的 HTTP 服务器和反向代理服务器;同时也是一个 IMAP、POP3、SMTP 代理服务器。

Nginx 可以作为一个 HTTP 服务器进行网站的发布处理,另外 Nginx 可以作为反向代理进行负载均衡的实现。
 
关于代理
 
说到代理,首先我们要明确一个概念,所谓代理就是一个代表、一个渠道;此时就涉及到两个角色,一个是被代理角色,一个是目标角色。

被代理角色通过这个代理访问目标角色完成一些任务的过程称为代理操作过程;如同生活中的专卖店,客人到 adidas 专卖店买了一双鞋,这个专卖店就是代理,被代理角色就是 adidas 厂家,目标角色就是用户。
 
正向代理
 
说反向代理之前,我们先看看正向代理,正向代理也是大家最常接触到的代理模式,我们会从两个方面来说关于正向代理的处理模式,分别从软件方面和生活方面来解释一下什么叫正向代理。

在如今的网络环境下,我们如果由于技术需要要去访问国外的某些网站,此时你会发现位于国外的某网站我们通过浏览器是没有办法访问的。

此时大家可能都会用一个操作 FQ 进行访问,FQ 的方式主要是找到一个可以访问国外网站的代理服务器,我们将请求发送给代理服务器,代理服务器去访问国外的网站,然后将访问到的数据传递给我们!

上述这样的代理模式称为正向代理,正向代理最大的特点是客户端非常明确要访问的服务器地址;服务器只清楚请求来自哪个代理服务器,而不清楚来自哪个具体的客户端;正向代理模式屏蔽或者隐藏了真实客户端信息。

来看个示意图(我把客户端和正向代理框在一块,同属于一个环境,后面我有介绍):

看完这篇还不了解 Nginx,那我就哭了!

客户端必须设置正向代理服务器,当然前提是要知道正向代理服务器的 IP 地址,还有代理程序的端口。

如下图:

看完这篇还不了解 Nginx,那我就哭了!

总结来说:正向代理,”它代理的是客户端”,是一个位于客户端和原始服务器(Origin Server之间的服务器,为了从原始服务器取得内容,客户端向代理发送一个请求并指定目标(原始服务器

然后代理向原始服务器转交请求并将获得的内容返回给客户端。客户端必须要进行一些特别的设置才能使用正向代理。
正向代理的用途:
  • 访问原来无法访问的资源,如 Google。

  • 可以做缓存,加速访问资源。

  • 对客户端访问授权,上网进行认证。

  • 代理可以记录用户访问记录(上网行为管理),对外隐藏用户信息。

反向代理

明白了什么是正向代理,我们继续看关于反向代理的处理方式,举例如我国的某宝网站,每天同时连接到网站的访问人数已经爆表,单个服务器远远不能满足人民日益增长的购买欲望了。

此时就出现了一个大家耳熟能详的名词:分布式部署;也就是通过部署多台服务器来解决访问人数限制的问题。

某宝网站中大部分功能也是直接使用 Nginx 进行反向代理实现的,并且通过封装 Nginx 和其他的组件之后起了个高大上的名字:Tengine。

有兴趣的童鞋可以访问 Tengine 的官网查看具体的信息:

http://tengine.taobao.org/

那么反向代理具体是通过什么样的方式实现的分布式的集群操作呢,我们先看一个示意图(我把服务器和反向代理框在一块,同属于一个环境,后面我有介绍):

看完这篇还不了解 Nginx,那我就哭了!

通过上述的图解大家就可以看清楚了,多个客户端给服务器发送的请求,Nginx 服务器接收到之后,按照一定的规则分发给了后端的业务处理服务器进行处理了。

此时请求的来源也就是客户端是明确的,但是请求具体由哪台服务器处理的并不明确了,Nginx 扮演的就是一个反向代理角色。

客户端是无感知代理的存在的,反向代理对外都是透明的,访问者并不知道自己访问的是一个代理。因为客户端不需要任何配置就可以访问。

反向代理,”它代理的是服务端”,主要用于服务器集群分布式部署的情况下,反向代理隐藏了服务器的信息。

反向代理的作用:
  • 保证内网的安全,通常将反向代理作为公网访问地址,Web 服务器是内网。

  • 负载均衡,通过反向代理服务器来优化网站的负载。

项目场景

通常情况下,我们在实际项目操作时,正向代理和反向代理很有可能会存在同一个应用场景中,正向代理代理客户端的请求去访问目标服务器,目标服务器是一个反向单利服务器,反向代理了多台真实的业务处理服务器。

具体的拓扑图如下:

看完这篇还不了解 Nginx,那我就哭了!

截了一张图来说明正向代理和反向代理二者之间的区别,如下图:

看完这篇还不了解 Nginx,那我就哭了!

图解:
  • 在正向代理中,Proxy 和 Client 同属于一个 LAN(图中方框内),隐藏了客户端信息。

  • 在反向代理中,Proxy 和 Server 同属于一个 LAN(图中方框内),隐藏了服务端信息。

实际上,Proxy 在两种代理中做的事情都是替服务器代为收发请求和响应,不过从结构上看正好左右互换了一下,所以把后出现的那种代理方式称为反向代理了。
负载均衡

我们已经明确了所谓代理服务器的概念,那么接下来,Nginx 扮演了反向代理服务器的角色,它是依据什么样的规则进行请求分发的呢?不用的项目应用场景,分发的规则是否可以控制呢?

这里提到的客户端发送的、Nginx 反向代理服务器接收到的请求数量,就是我们说的负载量。

请求数量按照一定的规则进行分发,到不同的服务器处理的规则,就是一种均衡规则。

所以将服务器接收到的请求按照规则分发的过程,称为负载均衡。

负载均衡在实际项目操作过程中,有硬件负载均衡和软件负载均衡两种,硬件负载均衡也称为硬负载,如 F5 负载均衡,相对造价昂贵成本较高。

但是数据的稳定性安全性等等有非常好的保障,如中国移动中国联通这样的公司才会选择硬负载进行操作。

更多的公司考虑到成本原因,会选择使用软件负载均衡,软件负载均衡是利用现有的技术结合主机硬件实现的一种消息队列分发机制。

看完这篇还不了解 Nginx,那我就哭了!

Nginx 支持的负载均衡调度算法方式如下:
 
①weight 轮询(默认接收到的请求按照顺序逐一分配到不同的后端服务器,即使在使用过程中,某一台后端服务器宕机,Nginx 会自动将该服务器剔除出队列,请求受理情况不会受到任何影响。

这种方式下,可以给不同的后端服务器设置一个权重值(weight,用于调整不同的服务器上请求的分配率。

权重数据越大,被分配到请求的几率越大;该权重值,主要是针对实际工作环境中不同的后端服务器硬件配置进行调整的。

②ip_hash:每个请求按照发起客户端的 ip 的 hash 结果进行匹配,这样的算法下一个固定 ip 地址的客户端总会访问到同一个后端服务器,这也在一定程度上解决了集群部署环境下 Session 共享的问题。

③fair:智能调整调度算法,动态的根据后端服务器的请求处理到响应的时间进行均衡分配。

响应时间短处理效率高的服务器分配到请求的概率高,响应时间长处理效率低的服务器分配到的请求少,它是结合了前两者的优点的一种调度算法。

但是需要注意的是 Nginx 默认不支持 fair 算法,如果要使用这种调度算法,请安装 upstream_fair 模块。

④url_hash:按照访问的 URL 的 hash 结果分配请求,每个请求的 URL 会指向后端固定的某个服务器,可以在 Nginx 作为静态服务器的情况下提高缓存效率。

同样要注意 Nginx 默认不支持这种调度算法,要使用的话需要安装 Nginx 的 hash 软件包。
 

Web 服务器对比

 

几种常用 Web 服务器对比如下图:
看完这篇还不了解 Nginx,那我就哭了!