CodeAshen's blog CodeAshen's blog
首页
  • Spring Framework

    • 《剖析Spring5核心原理》
    • 《Spring源码轻松学》
  • Spring Boot

    • Spring Boot 2.0深度实践
  • Spring Cloud

    • Spring Cloud
    • Spring Cloud Alibaba
  • RabbitMQ
  • RocketMQ
  • Kafka
  • MySQL8.0详解
  • Redis从入门到高可用
  • Elastic Stack
  • 操作系统
  • 计算机网络
  • 数据结构与算法
  • 云原生
  • Devops
  • 前端
  • 实用工具
  • 友情链接
关于
收藏
  • 分类
  • 标签
  • 归档
  • Reference
GitHub (opens new window)

CodeAshen

后端界的小学生
首页
  • Spring Framework

    • 《剖析Spring5核心原理》
    • 《Spring源码轻松学》
  • Spring Boot

    • Spring Boot 2.0深度实践
  • Spring Cloud

    • Spring Cloud
    • Spring Cloud Alibaba
  • RabbitMQ
  • RocketMQ
  • Kafka
  • MySQL8.0详解
  • Redis从入门到高可用
  • Elastic Stack
  • 操作系统
  • 计算机网络
  • 数据结构与算法
  • 云原生
  • Devops
  • 前端
  • 实用工具
  • 友情链接
关于
收藏
  • 分类
  • 标签
  • 归档
  • Reference
GitHub (opens new window)
  • RabbitMQ

  • RocketMQ

  • Kafka

  • Nginx

    • 第01章-基础篇
    • 第02章-场景实践篇
      • 2.1 静态资源web服务
        • 2.1.1 静态资源服务场景-CDN
        • 2.1.2 配置语法
        • 文件读取
        • tcp_nopush
        • tcp_nodelay
        • 压缩
        • 2.1.3 Nginx用于浏览器缓存
        • 浏览器缓存机制
        • Nginx配置缓存
        • 2.1.4 跨站访问
        • 2.1.5 防盗链
      • 2.2 代理服务
        • 2.2.1 正向代理与反向代理
        • 2.2.2 代理模式和模块介绍
        • 2.2.3 配置语法
      • 2.3 负载均衡调度器SLB
        • 2.3.1 负载均衡介绍及划分
        • 2.3.2 Nginx负载均衡配置
        • 2.3.3 Nginx调度算法
      • 2.4 动态缓存
        • 2.4.1 缓存分类和代理缓存
        • 2.4.2 缓存配置
        • 2.4.3 请求分片
    • 第03章-深度学习篇
    • 第04章-架构篇
  • 中间件
  • Nginx
CodeAshen
2023-02-10
目录

第02章-场景实践篇

# 2.1 静态资源web服务

image-20201230175949359

# 2.1.1 静态资源服务场景-CDN

image-20201230180215662

Nginx资源存储中心会把静态资源分发给“北京Nginx”,“湖南Nginx”,“山东Nginx”。

然后北京User发送静态资源请求,通过CDN,找到离自己最近的“北京Nginx”。

# 2.1.2 配置语法

# 文件读取

Syntax:      sendfile on | off;
Default:     sendfile off;
Context:     http, server, location, if in location
1
2
3

引:—with-file-aio 异步文件读取

# tcp_nopush

作用:sendfile开启的情况下,提高网络包的传输效率

把多个包整合,一次性发送,大文件传输推荐打开

Syntax:      tcp_nopush on | off;
Default:     tcp_nopush off;
Context:     http, server, location
1
2
3

# tcp_nodelay

作用:keepalive连接下,提高网络包的传输实时性

Syntax:      tcp_nodelay on | off;
Default:     tcp_nodelay on;
Context:     http, server, location
1
2
3

# 压缩

(1) 压缩开关

作用:传输压缩

Syntax:      gzip on | off;
Default:     gzip off;
Context:     http, server, location, if in location
1
2
3

image-20201230193145042

(2) 压缩比

Syntax:      gzip_comp_level level;
Default:     gzip_comp_level 1;
Context:     http, server, location
1
2
3

压缩比越高传输的数据包越小,但是压缩本身也会消耗服务端性能,需综合考虑

(3) 压缩内容

除了“text/html”之外,还为指定的MIME类型响应进行压缩。通配符“*”匹配任何MIME类型。“text/html”类型的响应总是被压缩的。

Syntax:      gzip_types mime-type ...;
Default:     gzip_types text/html;
Context:     http, server, location
1
2
3

(4) 压缩需要的版本

设置压缩响应所需的请求的最低HTTP版本

Syntax:      gzip_http_version 1.0 | 1.1;
Default:     gzip_http_version 1.1;
Context:     http, server, location
1
2
3

(5) 预读压缩

优先响应原本已有的压缩文件,而不是压缩后再返回。

例如,请求指定路径的 index.html,先检查该路径下是否存在 index.html.gz,如果存在直接响应该压缩文件,而不进行压缩了。节约了压缩时间,提高效率。

Syntax:      gzip_static on | off | always;
Default:     gzip_static off;
Context:     http, server, location
1
2
3

扩展Nginx压缩模块

  • http_gzip_static_module:预读gzip功能
  • http_gunzip_module:应用支持gunzip的压缩方式

# 2.1.3 Nginx用于浏览器缓存

# 浏览器缓存机制

浏览器缓存是基于HTTP协议定义的缓存机制(如:Expires;Cache-control等)

浏览器无缓冲场景:

image-20201231103949045

浏览器有缓存场景:

image-20201231104714049

缓存过期校验机制:

校验点 依赖的Header
校验是否过期 Expires、Cache-Control(max-age)
协议中Etag头信息校验 Etag
Last-Modified头信息校验 Last-Modified

缓存过期校验步骤:

  1. 本地客户端通过Expires、Cache-Control(max-age)字段校验本地缓存是否过期。

  2. 通过Etag头信息校验服务器缓存是否过期,如果不过期,不走第三步,否则执行下一步。

  3. 通过Last-Modified头信息校验服务器缓存是否过期,如果不过期,直接返回,否则请求服务端。

    1. Expires出现在Http1.0版本;Cache-Control(max-age)出现在Http1.1版本;
    2. Etag的值是一串字符串,在一秒时间内更新的话,服务端是无法识别的,这个时候就需要Etag校验
    3. Last-Modified的值是具体时间:年-月-日 时:分:秒。Last-Modified用来跟服务端的缓存文件进行校验,如果服务端缓存文件在新的时间有新的更新,客户端请求的时间就会跟服务端缓存文件时间对比,这个时候就会出现客户端请求的时间跟服务端请求的时间不一致。 这样的话,服务端就会把最新的文件返回给客户端,这个利用的就是请求头中的Last-Modified头信息进行校验的。

image-20201231105859259

# Nginx配置缓存

Nginx使用expires配置,在响应头中添加:Cache-Control、Expires头信息,实现缓存

Syntax:      expires [modified] time;
             expires epoch | max | off;
Default:     expires off;
Context:     http, server, location, if in location
1
2
3
4

开启expires

#设置缓存时间为30s
location ~ \.(html,htm)$ {
    expires 30s;
    root /opt/app/html;
}
1
2
3
4
5

第一次请求:

######################  请求头  ######################
#服务器设置缓存时间为30s
Cache-Control: max-age=30
#最后修改时间,之后的请求都会放在If-Modified-Since里带上
Last-Modified: Thu, 31 Dec 2020 03:24:48 GMT
#之后的请求都会放在If-None-Match里带上
ETag: "5fed4480-1e"
#缓存过期时间,每次都是 本次响应时间点+设置的过期时间
Expires: Thu, 31 Dec 2020 05:19:19 GMT
1
2
3
4
5
6
7
8
9

第二次请求:

######################  请求头  ######################
#这个0是由浏览器加的,浏览器控制每次都让服务器做过期校验,决定返回的响应状态码
Cache-Control: max-age=0
#第二次请求开始带上,校验Etag是否过期
If-None-Match: "5fed4480-1e"
#第二次请求开始带上,校验资源是否更改
If-Modified-Since: Thu, 31 Dec 2020 03:24:48 GMT

######################  响应码  ######################
304 Not Modified
######################  响应头  ######################
Cache-Control: max-age=30
ETag: "5fed4480-1e"
Expires: Thu, 31 Dec 2020 05:24:46 GMT
1
2
3
4
5
6
7
8
9
10
11
12
13
14

未开启expires

第一次请求:

######################  响应头  ######################
ETag: "5fed6c59-a"
Last-Modified: Thu, 31 Dec 2020 06:14:49 GMT
1
2
3

第二次请求:

######################  请求头  ######################
Cache-Control: max-age=0
If-Modified-Since: Thu, 31 Dec 2020 06:14:49 GMT
If-None-Match: "5fed6c59-a"

######################  响应码  ######################
304 Not Modified
######################  响应头  ######################
ETag: "5fed6c59-a"
Last-Modified: Thu, 31 Dec 2020 06:14:49 GMT
1
2
3
4
5
6
7
8
9
10

# 2.1.4 跨站访问

image-20201231143844649

为什么浏览器禁止跨域访问不安全?容易出现CSRF攻击!

image-20201231173341105

Nginx通过添加Access-Control-Allow-Origin响应头开启跨站访问

Syntax:      add_header name value [always];
Default:     —
Context:     http, server, location, if in location
1
2
3

配置示例

location ~ .*\.(html|htm)$ {
    add_header Access-Control-Allow-Methods GET,POST,PUT,DELETE,OPTIONS;
    add_header Access-Control-Allow-Origin *;
    root /opt/app/html
}
1
2
3
4
5

# 2.1.5 防盗链

防止资源被盗用

Nginx可以使用http_refer配置防盗链,该指令会根据Referer Header头的内容分配一个值为0或1给变量$invalid_referer。如果Referer Header头不符合valid_referers指令设置的有效Referer,变量$invalid_referer将被设置为1。

Syntax:      valid_referers none | blocked | server_names | string ...;
Default:     —
Context:     server, location
1
2
3

该指令的参数可以为下面的内容:

  • none:表示无Referer值的情况。
  • blocked:表示Referer值被防火墙进行伪装。
  • server_names:表示一个或多个主机名称。0.5.33版本后server_names中可以使用通配符"*"

配置示例

location ~ .*\.(jpg|png|gif)$ {
    # 验证规则
    valid_referers none blocked server_names
               *.example.com example.* www.example.org/galleries/
               ~\.google\.;
    # 校验不通过返回403
    if ($invalid_referer) {
        return 403;
    }
    root /opt/app/images;
}
1
2
3
4
5
6
7
8
9
10
11

# 2.2 代理服务

image-20201231182733547

# 2.2.1 正向代理与反向代理

代理区别在于代理的对象不一样。正向代理代理的对象是客户端,反向代理代理的对象是服务端

正向代理,是在用户端的。比如需要访问某些国外网站,我们可能需要购买vpn。

并且vpn是在我们的用户浏览器端设置的(并不是在远端的服务器设置)。

浏览器先访问vpn地址,vpn地址转发请求,并最后将请求结果原路返回来。

image-20210104163625353

反向代理是作用在服务器端的,是一个虚拟ip(VIP)。对于用户的一个请求,会转发到多个后端处理器中的一台来处理该具体请求。

大型网站都有DNS(域名解析服务器),load balance(负载均衡器)等。

image-20210104163724546

# 2.2.2 代理模式和模块介绍

Nginx可支持的代理协议:

img

反向代理

常见的Nginx作为反向代理支持的协议:

img

反向代理模式与Nginx代理模块

反向代理模式 Nginx配置模块
http、websocket、https ngx_http_proxy_module
fastcgi ngx_httpfastcgi_module
uwsgi ngx_http_uwsgi_module
grpc ngx_http_v2_module

正向代理

常见的Nginx作为正向代理支持的协议

img

注意:

  • 不能支持使用HTTPS协议
  • Nginx使用HTTP协议作为正向代理的协议
  • Nginx使用正向代理范围比较窄

# 2.2.3 配置语法

Syntax:      proxy_pass URL;
Default:     —
Context:     location, if in location, limit_except
1
2
3

配置示例

location /name/ {
    proxy_pass http://127.0.0.1:8080/$request_uri;
}
1
2
3

补充配置

1、缓存相关配置

启用或禁用代理服务器响应的缓冲。

Syntax:		proxy_buffering on | off;
Default:	proxy_buffering on;
Context:	http, server, location
1
2
3

扩展:proxy_buffer size、proxy_buffers、proxy_busy_ buffers_size

2、跳转重定向

修改被代理服务器返回的响应头中的location头域跟refresh头域数值

Syntax:		proxy_redirect default;
			proxy_redirect off;
			proxy_redirect redirect replacement;
Default:	proxy_redirect default;
Context:	http, server, location
1
2
3
4
5

https://blog.csdn.net/u010391029/article/details/50395680

3、头信息

更改或新增传递给代理服务器的请求头

Syntax:		proxy_set_header field value;
Default:	proxy_set_header Host $proxy_host;
			proxy_set_header Connection close;
Context:	http, server, location
1
2
3
4

扩展:proxy_hide_header、proxy_set_body

4、超时

定义用于与代理服务器建立连接的超时。请注意,此超时通常不能超过75秒。

Syntax:		proxy_connect_timeout time;
Default:	proxy_connect_timeout 60s;
Context:	http, server, location
1
2
3

扩展:proxy_read_timeout、proxy_send_timeout

# 2.3 负载均衡调度器SLB

# 2.3.1 负载均衡介绍及划分

image-20210104181905203

按作用范围可划分为 GSLB 和 SLB

1、GSLB(全局负载均衡)

GSLB 是英文Gobal Server Load Balance的缩写,意思是全局负载均衡。

作用:实现在广域网(包括互联网)上不同地域的服务器间的流量调配,保证使用最佳的服务器服务离自己最近的客户,从而确保访问质量。

image-20210104182040699

  • 调度中心节点:一个全局的调度节点;
  • 调度节点:一个局部调度节点;
  • 应用服务中心节点:一个全局的应用服务调度节点;
  • 应用服务:一个局部应用服务节点;

调度中心节点管理着调度节点;应用服务中心节点管理着应用服务;

举例:

第一步:张三请求局部调度节点,局部调度节点则返回服务地址给张三; 第二步:张三根据局部调度节点返回的服务地址,请求局部应用服务,局部应用服务则返回结果给张三。

2、SLB(服务器负载均衡)

image-20210104182358524

调度节点与服务节点处于一个逻辑单元里面,这样对于部分服务的实时性、响应性是非常好的。

按七层网络模型课划分为 四层负载均衡 和 七层负载均衡

1、四层负载均衡,即传输层负载均衡

image-20210104182619957

按照网络OSI模型可以分为四层负载均衡和七层负载均衡;

四层负载均衡:在OSI模型里面的传输层,传输层能支持到tcp/ip协议,所以只需要转发tcp/ip协议的包,就可以实现负载均衡。

优势:性能非常好,只需要在最底层应用处理,而不需要进行一些复杂的逻辑,只需要包的转发就行

2、七层负载均衡,处理应用层,如:http信息

image-20210104182704000

七层负载均衡主要是在应用层使用,所以它可以完成很多应用层的协议请求,比如HTTP协议的负载均衡,它可以实现HTTP信息的改写,头信息的改写,应用规则的控制。

Nginx是典型的七层负载均衡SLB。

# 2.3.2 Nginx负载均衡配置

Nginx负载均衡配置是基于 proxy_pass 和 upstream 实现的。如下图:upstream server就相当于配置的虚拟服务池。

image-20210104185540581

upstream配置

定义一组服务器。服务器可以在不同的端口上侦听。此外,可以混合使用侦听TCP和UNIX域套接字的服务器。

Syntax:		upstream name { ... }
Default:	—
Context:	http
1
2
3

配置示例

# 定义一组服务器
upstream lucifer {
	server 127.0.0.1:8081;
	server 127.0.0.1:8082;
	server 127.0.0.1:8083;
}

server {
	listen 80;
	
	location / {
		# 使用upstream定义的服务器组负载均衡
		proxy_pass http://lucifer
	}
	
	......
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

upstream详解

官方示例

upstream backend {
	# 加权重
    server backend1.example.com weight=5;
    # 指定最大失败次数和暂停服务时间
    server 127.0.0.1:8080       max_fails=3 fail_timeout=30s;
    # socket方式
    server unix:/tmp/backend3;
	# 备份节点
    server backup1.example.com  backup;
}
1
2
3
4
5
6
7
8
9
10

附加配置项含义:

配置 含义
down 当前的server暂时不参与负载均衡
backup 预留的备份服务器
max_fails 允许请求失败的次数
fail_timeout 经过max_fails失败后,服务暂停的时间
max_conns 限制最大的接收的连接数

# 2.3.3 Nginx调度算法

调度方式 解释
轮询 按时间顺序逐一分配到不同的后端服务器
加权轮询 weight值越大,分配到的访问几率越高
ip_hash 每个请求按访问IP的hash结果分配,这样来自同一个IP的固定访问一个后端服务器
url_hash 按照访问的URL的hash结果来分配请求,是每个URL定向到同一个后端服务器
least_conn 最少链接数,那个机器连接数少就分发
hash关键数值 hash自定义的key

1、weight加权轮询配置

upstream lucifer {
	server 127.0.0.1:8081;
	server 127.0.0.1:8082 weight=5;
	server 127.0.0.1:8083;
}
1
2
3
4
5

2、ip_hash配置

upstream lucifer {
	ip_hash;
	server 127.0.0.1:8081;
	server 127.0.0.1:8082;
	server 127.0.0.1:8083;
}
1
2
3
4
5
6

3、url_hash配置

upstream lucifer {
	hash $request_uri;
	server 127.0.0.1:8081;
	server 127.0.0.1:8082;
	server 127.0.0.1:8083;
}
1
2
3
4
5
6

# 2.4 动态缓存

# 2.4.1 缓存分类和代理缓存

缓存可分为服务端缓存、代理缓存、客户端缓存,Nginx配置缓存是代理缓存。

image-20210105100929611

image-20210105100946619

image-20210105100910044

Nginx代理缓存生效流程:

img

  1. 客户端第一次向Nginx请求数据a;
  2. 当Nginx发现缓存中没有数据a时,会向服务端请求数据a;
  3. 服务端接收到Nginx发来的请求,则返回数据a到Nginx,并且缓存在Nginx;
  4. Nginx返回数据a给客户端应用;
  5. 客户端第二次向Nginx请求数据a;
  6. 当Nginx发现缓存中存在数据a时,则不会请求服务端,直接将缓存中的数据放回给客户端。

# 2.4.2 缓存配置

1、proxy_cache_path

设置缓存的路径和其他参数。

Syntax:		proxy_cache_path path [levels=levels] [use_temp_path=on|off] keys_zone=name:size [inactive=time] [max_size=size] [min_free=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];
Default:	—
Context:	http
1
2
3

2、proxy_cache

定义用于缓存的共享内存区域。

Syntax:		proxy_cache zone | off;
Default:	proxy_cache off;
Context:	http, server, location
1
2
3

3、proxy_cache_valid

为不同的响应状态码设置缓存时间。

Syntax:		proxy_cache_valid [code ...] time;
Default:	—
Context:	http, server, location
1
2
3

4、proxy_cache_key

定义用于缓存的key。

Syntax:		proxy_cache_key string;
Default:	proxy_cache_key $scheme$proxy_host$request_uri;
Context:	http, server, location
1
2
3

5、proxy_no_cache

配置不缓存的条件。如果字符串参数中至少有一个值不为空且不等于“0”,则不会缓存响应。

Syntax:		proxy_no_cache string ...;
Default:	—
Context:	http, server, location
1
2
3

7、配置实例

# 定义服务器组
upstream lucifer { 
	server 116.62.103.228:8001; 
	server 116.62.103.228:8002; 
	server 116.62.103.228:8003;
}	

# 缓存路径 缓存目录层次结构级别 定义key空间名和大小 目录最大容量 不活跃失效时间 关闭临时文件
proxy_cache_path /opt/app/cache levels=1:2 keys_zone=lucifer_cache:10m max_size=10g inactive=60m use_temp_path=off; 

server { 

	# 如果请求uri符合条件,则设置$cookie_nocache值为1
	if($request_uri ~ ^/(url3|login|register|password\/reset)) { 
		set $cookie_nocache 1;
	}
	
	location / { 
		# 使用定义的key空间
		proxy_cache lucifer_cache; 
		proxy_pass http://lucifer; 
		# 针对不同的响应状态码设置缓存时间
		proxy_cache_valid 200 304 12h; 
		proxy_cache_valid any 10m; 
		# 设置缓存key
		proxy_cache_key $host$uri$is_args$args; 
		# 加入头信息以直观感受是否命中缓存
		add_header Nginx-Cache "$upstream_cache_status"; 
		# 配置不缓存的条件,只要有一个参数不为0,就不缓存
		proxy_no_cache $cookie_nocache $arg_nocache $arg_comment;
		proxy_no_cache $http_pragma $http_authorization;
		
		# 配置出现指定错误时,跳过本台服务器去尝试下一台服务器
		proxy_next_upstream error timeout invalid_header http_ 500 http_502 http_503 http_504; 
	}
	
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

8、场景配置补充说明

如何清理指定缓存?

  • 方式一:rm -rf 缓存目录内容
  • 方式二:第三方扩展模块ngx_cache_purge

# 2.4.3 请求分片

ngx_http_slice_module模块将一个请求拆分为子请求,每个子请求返回一定范围的响应。

默认情况下不生成此模块,应使用--with-http\u slice\u module配置参数启用它。

image-20210105114035661

  • 优点:每个子请求收到的数据都会形成一个独立的文件,一个请求断了,其他请求不会收到影响。
  • 缺点:当文件很大或者slice设置很小时,可能会导致文件描述符耗尽等情况。

配置语法:

Syntax:		slice size;
Default:	slice 0;
Context:	http, server, location
1
2
3

配置实例:

location / {
    slice             1m;
    proxy_cache       cache;
    proxy_cache_key   $uri$is_args$args$slice_range;
    proxy_set_header  Range $slice_range;
    proxy_cache_valid 200 206 1h;
    proxy_pass        http://localhost:8000;
}
1
2
3
4
5
6
7
8

此示例中,响应被分为1m的可缓存片。

编辑 (opens new window)
上次更新: 2023/06/04, 12:34:19
第01章-基础篇
第03章-深度学习篇

← 第01章-基础篇 第03章-深度学习篇→

最近更新
01
第01章-RabbitMQ导学
02-10
02
第02章-入门RabbitMQ核心概念
02-10
03
第03章-RabbitMQ高级特性
02-10
更多文章>
Theme by Vdoing | Copyright © 2020-2023 CodeAshen | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式