Nginx: 动静分离、压缩、缓存、黑白名单、跨域、高可用......

单机部署的问题

    1. 单体结构的部署方式无法承受日益增长的业务流量。
    1. 当后端节点宕机后,整个系统会陷入瘫痪,导致整个项目不可用。

负载均衡技术可带来的收益

    1. 系统的高可用:当某个节点宕机后可以迅速将流量转移到其它节点。
    1. 系统的高性能:多台服务器共同对外提供服务,为整个系统提供了更高规模的吞吐。
    1. 系统的拓展性:当业务再次出现增长或萎靡时,可再加入/减少节点,灵活伸缩。

负载均衡方案

    1. 硬件层面:比较常用的硬件负载器:A10、F5等。
    1. 软件层面:Nginx等。

一、Nginx概念深入浅出

  Nginx是目前负载均衡技术中的主流方案,几乎绝大部分项目都会使用它,Nginx是一个轻量级的高性能HTTP反向代理服务器,同时它也是一个通用类型的代理服务器,支持绝大部分协议,如TCP、UDP、SMTP、HTTPS等。
  NginxRedis相同,都是基于多路复用模型构建出的产物,因此同样具备资源占用少、并发支持高的特点,在理论上单节点的Nginx可同时支持5W并发连接,而实际生产环境中,硬件基础到位再结合简单调优后确实能达到该数值。下图是引入Nginx前后,客户端请求处理流程的对比:

在这里插入图片描述
  原本客户端是直接请求目标服务器,由目标服务器直接完成请求处理工作,但加入Nginx后,所有的请求会先经过Nginx,再由Nginx进行分发到具体的服务器处理,服务器处理完成后再返回Nginx,最后由Nginx将最终的响应结果返回给客户端。
  下面进行环境搭建、动静分离、资源压缩、缓存配置、IP黑名单、高可用保障等的介绍。

二、Nginx环境搭建


    1. 首先创建Nginx的目录并进入
mkdir /soft && mkdir /soft/nginx
cd /soft/nginx
    1. 下载Nginx的安装包,可以通过FTP工具上传离线环境包,也可以通过wget命令在线获取安装包
wget https://nginx.org/download/nginx-1.21.6.tar.gz

如果没有wget命令可以通过yum命令安装

yum -y install wget
    1. 解压Nginx的压缩包
tar -xvzf nginx-1.21.6.tar.gz
    1. 下载并安装Nginx所需的依赖库和包
yum install --downloadonly --downloaddir=/soft/nginx/ gcc-c++
yum install --downloadonly --downloaddir=/soft/nginx/ pcre pcre-devel4
yum install --downloadonly --downloaddir=/soft/nginx/ zlib zlib-devel
yum install --downloadonly --downloaddir=/soft/nginx/ openssl openssl-devel

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

yum -y install gcc zlib zlib-devel pcre-devel openssl openssl-devel

执行完成后通过ls可以看到很多依赖
在这里插入图片描述
通过rpm命令依次将依赖包一个个构建,或者通过以下命令一键安装所有依赖包

rpm -ivh --nodeps *.rpm
    1. 进入解压后的Nginx目录,执行Nginx的配置脚本,为后续的安装提前配置好环境,默认位于/usr/local/nginx目录下(可自定义目录)
cd nginx-1.21.6
./configure --prefix=/soft/nginx/
    1. 编译并安装Nginx
make && make install
    1. 最后回到前面的/soft/nginx/目录,输入ls即可看见安装nginx完成后生成的文件。
    1. 修改安装后生成的conf目录下的nginx.conf配置文件:
vi conf/nginx.conf
 修改端口号:listen    80;
 修改IP地址:server_name  你当前机器的本地IP(线上配置域名);
    1. 指定配置文件并启动Nginx
sbin/nginx -c conf/nginx.conf
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,不管当前是否有任务在执行
    1. 开发80端口,并更新防火墙
firewall-cmd --zone=public --add-port=80/tcp --permanent
firewall-cmd --reload
firewall-cmd --zone=public --list-ports
    1. 在浏览器中访问步骤8中配置的ip地址,无需输入端口号
      在这里插入图片描述
      最终看到如上的Nginx欢迎界面,代表Nginx安装完成。

三、Nginx反向代理-负载均衡

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

public class IndexNginxController {
	@Value("${server.port}")
	private String port;
	
	@RequestMapping("/")
	public ModelAndView index() {
		ModelAndView mv = new ModelAndView();
		mv.addObject("port", port);
		mv.setViewName("index");
		return mv;

	}
}

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

  接下来修改一下Nginx的配置文件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服务的端口分别是8080和8090。

最终的效果如下图所展示:
https://mmbiz.qpic.cn/mmbiz_gif/7VqDzaTV5hhDrPNkSohviaXor0hSpe6QUFH46c1J9UgDsSGg0rLABRFt9Do580ayEIJ7tVXuF1ia963FsI3GvkUg/640?wx_fmt=gif&tp=wxpic&wxfrom=5&wx_lazy=1

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

3.1 Nginx请求分发原理

  客户端发出的请求192.168.12.129最终会变为:http://192.168.12.129:80/,然后再向目标ip发起请求,流程如下:
在这里插入图片描述

  1. 由于Nginx监听了192.168.12.129的80端口,所以最终该请求会找到Nginx进程。
  2. Nginx首先会根据配置的location规则进行匹配,根据客户端的请求路径/,会定位到location/{}规则。
  3. 然后根据该location中配置的proxy_pass会再找到名为nginx_bootupstream
  4. 最后根据upstream中的配置信息,将请求转发到WEB服务器进行处理,由于配置了多个WEB服务,且配置了权重比,因此Nginx会根据权重比依次分发请求。

四、Nginx动静分离

  当浏览器输入www.taobao.com访问淘宝首页时,打开开发者调试工具可以很明显的看到,首页加载会出现100+的请求数,而对于前后端不分离的项目,在进行开发时,静态资源一般会放入到resources/static/目录下。项目上线部署时,这些静态资源会一起打成包,此时,对于静态资源的访问就会对服务器造成很大压力。这些资源大概率情况下,长时间也不会出现变动,那为何还要让这些请求到后端再处理呢?能不能在此之前就提前处理掉?当然OK,因此经过分析之后能够明确一点:做了动静分离之后,至少能够让后端服务减少一半以上的并发量。 到此时大家应该明白了动静分离能够带来的性能收益究竟有多大。

接下来使用Nginx实现动静分离

    1. 先在Nginx的安装目录下创建一个目录static_resources。
mkdir static_resources
    1. 将项目中所有的静态资源全部拷贝到该目录下,然后将项目中的静态资源全部移除后重新打包。
    1. 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效果、图片等依旧有效。
  location规则解释如下:

~ 代表匹配时区分大小写
.* 代表任意字符都可以出现零次或多次,即资源名不限制
\. 代表匹配后缀分隔符.
(html|htm|gif|jpg|jpeg|bmp|png|ico|txt|js|css) 代表匹配括号里所有的静态资源类型
综上所述,该配置表示匹配以html|htm|gif|jpg|jpeg|bmp|png|ico|txt|js|css为后缀的所有资源请求

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

五、Nginx资源压缩

  建立在动静分离的基础之上,如果一个静态资源的size越小,那么传输速度就会更快,同时也会节省宽带,因此在部署项目时,也可以通过Nginx对于静态资源实现压缩传输,一方面可以节省带宽资源,第二方面也可以加快响应速度并提升系统整体吞吐。
  Nginx也提供了三个支持资源压缩的模块:ngx_http_gzip_modulengx_http_gzip_static_modulengx_http_gunzip_module,其中ngx_http_gzip_static_module属于内置模块,代表着可以直接使用该模块下的一些压缩指令,后续的资源压缩操作都基于该模块,先来看看压缩配置的一些参数/指令:
在这里插入图片描述
  了解了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;
}

六、Nginx缓冲区

  接入Nginx的项目一般请求流程为:“客户端–>Nginx–>服务端”,在这个过程中存在两个连接:“客户端–>Nginx”、“Nginx–>服务端”,那么两个不同的连接速度不一致,就会影响用户的体验(比如浏览器的加载速度跟不上服务端的响应速度)。其实也就类似电脑的内存跟不上CPU的速度,所以对于用户造成的体验感极差,因此在CPU设计时都会加入三级高速缓冲区,用于缓解CPU和内存速度不一致的矛盾。在Nginx也同样存在缓冲区的机制,主要目的就在于用来解决连接之间速度不匹配造成的问题,有了缓冲后,Nginx代理可暂存后端的响应,然后按需供给数据给客户端。先来看看一些关于缓冲区的配置项:

七、Nginx缓存机制

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

    1. 减少了再次向后端或文件服务器请求资源的宽带消耗。
    1. 降低了下游服务器的访问压力,提升系统整体吞吐。
    1. 缩短了响应时间,提升了加载速度,打开页面的速度更快。

那么在Nginx中,该如何配置代理缓存呢?以下是缓存相关的配置项:

  • proxy_cache_path: 代理缓存的路径。
    • path:

八、Nginx实现IP黑白名单

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

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


server {
    listen 80;
    server_name example.com;

    location / {
        # 允许特定的 IPIP 段访问
        allow 192.168.1.10;
        allow 10.0.0.0/8; # 允许整个 10.0.0.0/8 网段
        allow 172.16.0.0/12; # 允许整个 172.16.0.0/12 网段
        deny all; # 拒绝其他所有未明确允许的 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.0到127.255.255.255网段中的所有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.0到127.45.255.255网段中的所有IP访问
deny all; # 除上述IP外,其它IP全部禁止访问

然后将这两个文件在nginx.conf中配置即可

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

如果要整站屏蔽/开放就在http中配置,如果只需要域名屏蔽/开放就在server中配置,如果只需要针对于某一系列接口屏蔽/开放就在location中配置。

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

九、Nginx跨域配置

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

跨域问题产生的原因

  产生跨域问题的主要原因就在于同源策略,为了保证用户信息安全,防止恶意网站窃取数据,同源策略是必须的,否则cookie可用共享。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值