nginx实践:静态资源Web服务、代理服务、负载均衡调度器SLB和动态缓存

本章介绍nginx在静态资源、代理服务、负载均衡和动态缓存的使用

静态资源服务

核心配置和文件压缩

  1. 配置语法:文件读取

    配置:sendfile on | off。默认:sendfile off。作用域:http, server, location,if in location

    sendfile 是一种高效传输文件的模式。sendfile设置为on表示启动高效传输文件的模式。sendfile可以让Nginx在传输文件时直接在磁盘和tcp socket之间传输数据。如果这个参数不开启,会先在用户空间(Nginx进程空间)申请一个buffer,用read函数把数据从磁盘读到cache,再从cache读取到用户空间的buffer,再用write函数把数据从用户空间的buffer写入到内核的buffer,最后到tcp socket。开启这个参数后可以让数据不用经过用户buffer。

  2. 配置语法:tcp_nopush

    配置:tcp_nopush on | off

    默认:tcp_nopush off

    作用域:http, server, location

    tcp_nopush是在sendfile开启的情况下,提高网络包的传输效率。tcp_nopush指令,在连接套接字时启用Linux系统下的TCP_CORK。该选项告诉TCP堆栈附加数据包,并在它们已满或当应用程序通过显式删除TCP_CORK指示发送数据包时发送它们。 这使得发送的数据分组是最优量,并且因此提高了网络数据包的传输效率。 也就是说 tcp_nopush=on 时,结果就是数据包不会马上传送出去,等到数据包最大时,一次性的传输出去,这样有助于解决网络堵塞,虽然有一点点延迟。

  3. 配置语法:tcp_nodelay

    配置:tcp_nodelay on | off;

    默认: tcp_nodelay on;

    作用域:http, server, location

    tcp_nodelay是在 keepalive 连接下,提高网络数据包的传输实时性。tcp_nodelay选项和tcp_nopush正好相反,数据包不等待,实时发送给用户。

  4. 配置语法:gzip压缩

    压缩传输,提高传输效率。开启压缩,可以加快资源响应速度节省网络带宽资源

    gizp配置语法:

    ​ 配置:gzip on | off;

    ​ 默认:gzip off;

    ​ 作用域:http, server, location, if in location

    配置压缩比:压缩等级配置(压缩等级越高,越消耗服务器资源)

    ​ 配置:gzip_comp_level level;

    ​ 默认:gzip_comp_level 1;

    ​ 作用域: http, server, location

    gzip协议版本配置:

    ​ 配置:gzip_http_version 1.0 | 1.1;

    ​ 默认:gzip_http_version 1.1;

    ​ 作用域:http, server, location;

    压缩扩展模块:预读gzip功能 ngx_http_gzip_static_module

    ​ 配置: gzip_static on | off | always;

    ​ 默认:gzip_static off;

    ​ 作用域:http, server, location

    gunzip的压缩方式 ngx_http_gunzip_module

    ​ 配置:gunzip on | off;

    ​ 默认:gunzip off;

    ​ 作用域:http, server, location

    ​ 配置:gunzip_buffers number size;

    ​ 默认:gunzip_buffers 32 4k|16 8k;

    ​ 作用域:http, server, location;

配置示例

配置图片压缩,在/opt/work/code/images目录下准备一张图片,第一次请求先关闭gzip,禁止Chrome缓存,打开开发者工具,然后请求图片,在network里查看图片的size。开启gzip,再次请求该图片,会发现图片被压缩变小了。

1
2
3
4
5
6
7
location ~ .*\.(jpg|gif|png)$ {
            gzip on;
            gzip_http_version 1.1;
            gzip_comp_level 2;
            gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;
            root  /opt/work/code/images;
}

关于txt,html等文件,与上述同理

1
2
3
4
5
6
7
location ~ .*\.(txt|xml)$ {
            gzip on;
            gzip_http_version 1.1;
            gzip_comp_level 1;
            gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;
            root  /opt/work/code/doc;
}

配置访问压缩的静态资源

1
2
3
4
5
location ~ ^/download {
            gzip_static on;
            tcp_nopush on;
            root /opt/work/code;
}

浏览器缓存

过期检验机制

  1. 检验是否过期:Expires、Cache-Controller(max-age)
  2. 协议中的Etag头信息校验:Etag
  3. Last-Modified头信息校验:Last-Modified

expires配置

配置:expires time

默认:expires off

作用域:http,server,location,if in lacation

配置示例

1
2
3
4
location ~ .*\.(txt|xml)$ {
	expires 24h;
	root /opt/work/html;
}

对于txt、html文件设置过期时间24小时。配置好之后再去访问这些配置了expires的文件,通过浏览器的开发工具观看,可以看到,第一次请求status是200,再次请求status就变成了304,说明读取了缓存。响应头就会出现如下信息:

1
2
3
4
Cache-Control: max-age=86400
TETag: "5ee9b0ef-12d"
Expires: Sat, 20 Jun 2020 08:11:21 GMT
Last-Modified: Wed, 17 Jun 2020 05:58:07 GMT

跨域访问处理

通过add_header可以在响应头中添加Access-Controller-Allow-Origin头信息来允许客户端实现跨域访问。

配置语法

配置:add_header name value;

作用域:http,server,location,if in location;

配置示例

1
2
3
4
5
6
7
8
location / {
	#允许跨域访问所有的域名,也可以指定域名如:http://www.baidu.com
	add_header Access-Controller-Allow-Origin *;
	#允许这些方法进行跨域访问
	add_header Access-Controller-Allow-Methods GET,POST,PUT,DELETE,OPTIONS;
	root /opt/work/html;
	index index.html index.htm;
}

对于跨域访问,也可以通过服务端的代码来实现,例如Java,golang等服务端语言都可以实现。

防盗链

防盗链可以防止网站的资源被盗用。nginx可以实现简单的防盗链功能。

基于http_refer防盗链配置模块

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
location ~ .*\.(txt|xml)$ {
	valid_referers none blocked *.maishuren.top maishuren.top server_names ~\.google\. ~\.baidu\.;
    if ($invalid_referer) {
    	return 403;
    }
	gzip on;
	gzip_http_version 1.1;
	gzip_comp_level 1;
	gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;
	root  html;
}

代理服务

在现实生活中,有着代购这一现象,就是我们通过代购来购买一些东西。同样的基于nginx的代理服务就是,客户端与服务段之间是通过nginx这一代理来完成请求和响应的。如图

nginx能都代理的服务有很多,而代理服务又有正向代理和反向代理

正向代理

所谓正向代理就是顺着请求的方向进行的代理,即代理服务器他是由你配置为你服务,去请求目标服务器地址。

反向代理

所谓反向代理正好与正向代理相反,代理服务器是为目标服务器服务的,虽然整体的请求返回路线都是一样的都是Client到Proxy到Server。

使用配置:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
server {
    listen       80;
    server_name  www.xxx.com;            #外部访问的域名
    location ~ /test.html$ {
        proxy_pass http://127.0.0.1:8080;#代理转发
    }
}

#内部访问的服务
server {
    listen       8080;
    server_name  127.0.0.1;
    location / {
        root   /opt/work/html;
        index  index.html;
}

缓冲区、重定向、头信息、超时配置

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
server {
    listen       80;
    server_name  www.xxx.com;            #外部访问的域名
    location ~ /test.html$ {
        proxy_pass http://127.0.0.1:8080;#代理转发
        proxy_redirect default;
        
        proxy_set_header Host $http_host;
        proxy_set_header x-Real-IP $remote_addr;
        
        proxy_connect_timeout 30;
        proxy_send_timeout 60;
        proxy_read_timeout 60;
        
        proxy_buffer_size 32k;
        proxy_buffering on;
        proxy_buffers 4 128k;
        proxy_busy_buffers_size 256k;
        proxy_max_temp_file_size 256k;
    }
}

proxy_redirect default; 

  • 没有重定向就配置成默认,除非后端返回301情况下设置成具体重定向地址  

proxy_set_header Host $http_host;

proxy_set_header X-Real-IP $remote_addr;

  • 设置字段重新定义或附加到传递给代理服务器的请求头

proxy_connect_timeout 30;

  • 设置代理连接超时时间

proxy_read_timeout 60;

  • 设置从代理服务器读取响应的超时时间

proxy_send_timeout 60;

  • 设置向代理服务器发送请求的超时时间

proxy_buffering on;

  • 设置启用或禁用来自代理服务器的响应缓冲

proxy_buffer_size 32k;

  • 设置用于读取从代理服务器接收的响应的第一部分的缓冲区的大小

proxy_buffers 4 128k

  • 设置用于从代理服务器读取响应的缓冲区的数量和大小,用于单个连接。

proxy_busy_buffers_size 256k;

  • 设置当启用来自代理服务器的响应缓冲时,限制可能忙于向响应客户端发送响应的缓冲区的总大小,而响应尚未完全读取。

proxy_max_temp_file_size 256k;

  • 设置当启用来自代理服务器的响应缓冲,并且整个响应不适合proxy_buffer_size和proxy_buffers指令设置的缓冲区时,响应的一部分可以保存到临时文件中。 该指令设置临时文件的最大大小。 一次写入临时文件的数据大小由proxy_temp_file_write_size指令设置。

负载均衡

  1. Nginx负载均衡

  1. GSLB(全局负载均衡)

  • 调度中心节点:一个全局的调度节点;
  • 调度节点:一个局部调度节点;
  • 应用服务中心节点:一个全局的应用服务调度节点;
  • 应用服务:一个局部应用服务节点;
  • 调度中心节点管理着调度节点;
  • 应用服务中心节点管理着应用服务;
  1. SLB负载均衡

调度节点与服务节点处于一个逻辑单元里面,这样对于部分服务的实时性,影响性非常好。Nginx就是使用SLB负载均衡

  1. 四层负载均衡

    按照OSI网络模型中,第四层是传输层,传输层支持tcp/ip协议,所以只需要转发tcp/ip协议包,就可以实现负载均衡。性能十分好,只需要在最底层应用处理,不需要进行复杂的逻辑,只需要转发包就行了。

5.七层负载均衡

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

nginx负载均衡的配置

在conf.d文件夹下新建三个server配置文件:server1.conf、server2.conf、server3.conf

 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
#server1.conf
server {
    listen       8080;
    server_name  localhost;
    location / {
        root   /opt/work/html;
        index  server1.html server1.htm;
    }
}

#server2.conf
server {
    listen       8081;
    server_name  localhost;
    location / {
        root   /opt/work/html;
        index  server2.html server2.htm;
    }
}

#server3.conf
server {
    listen       8082;
    server_name  localhost;
    location / {
        root   /opt/work/html;
        index  server3.html server3.htm;
    }
}

在主配置文件nginx.conf中配置,默认是使用轮询策略

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
upstream test {
        server 192.168.74.129:8080;
        server 192.168.74.129:8081;
        server 192.168.74.129:8082;
}

include /etc/nginx/conf.d/*.conf;

server {
    listen       80;
    server_name  www.maishuren.com;
    resolver  8.8.8.8;
    location / {
        proxy_pass http://imotestoc;
        proxy_redirect default;
 
}

后端服务器在负载均衡调度中的状态

down:当前的server暂时不参与负载均衡

backup:预留的备份服务器

max_fails:允许请求失败的次数

fail_timeout:经过max_fails失败后,服务暂停的时间

max_conns:限制最大的接收连接数

示例:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
upstream test {
	server 192.168.74.129:8080 down;
    server 192.168.74.129:8081 backup;
    server 192.168.74.129:8082 max_fails=1 fail_timeout=30s;
}

include /etc/nginx/conf.d/*.conf;

server {
    listen       80;
    server_name  www.maishuren.com;
    resolver  8.8.8.8;
    location / {
        proxy_pass http://imotestoc;
        proxy_redirect default;
 
}

nginx负载均衡算法

轮询:按时间顺序逐一分配到不同的后端服务器

加权轮询:weight值越大,分配到的访问几率越高

ip_hash:每个请求按照访问的IP的hash结果分配,这样来自同一个IP的访问就会固定访问一个后端服务器

url_hash:按照访问的URL的hash结果来分配服务器,是每个URL定向到同一个后端服务器

hash关键数值:hash自定义的key

示例:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
upstream test {
	#ip_hash;
	#hash $request_uri
	server 192.168.74.129:8080;
    server 192.168.74.129:8081 weight=2;
    server 192.168.74.129:8082 weight=5;
}

include /etc/nginx/conf.d/*.conf;

server {
    listen       80;
    server_name  www.maishuren.com;
    resolver  8.8.8.8;
    location / {
        proxy_pass http://imotestoc;
        proxy_redirect default;
 
}

动态缓存

nginx缓存服务

上图描述的很清楚,当nginx开启了缓存服务时,可以缓存服务端的数据,提高响应效率

配置语法

proxy_cache_path配置语法

配置: 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];

默认: —

作用域: http

proxy_cache配置语法

配置: proxy_cache zone | off;

默认: proxy_cache off;

作用域: http, server, location

proxy_cache_valid配置语法

Syntax: proxy_cache_valid [code …] time;

Default: —

Context: http, server, location

proxy_cache_key配置语法

配置: proxy_cache_key string;

默认: proxy_cache_key $scheme$proxy_host$request_uri;

作用域: http, server, location

配置实例

 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
upstream test {
        server 192.168.74.129:8080;
        server 192.168.74.129:8081;
        server 192.168.74.129:8082;
}
    #需要首先配置 缓存目录,文件目录层级2级,空间名字 10m大小,目录最大大小(超过启动nginx自己的淘汰规则),在60分钟的时间内没有被访问就会被清理,存放临时文件
    proxy_cache_path /opt/app/cache levels=1:2 keys_zone=nginx_cache:10m max_size=10g inactive=60m use_temp_path=off;
 
server {
    listen       80;
    server_name  localhost www.maishuren.com;
    
    #如果url中包含以下路径参数,那么 cookie_nocache 的值为1-----1.设置某些访问路径不缓存
    if($request_uri ~^/(url3|login|register|password\/reset)){
        set $cookie_nocache 1;
    }
 
    location / {
        proxy_cache off;  #开启缓存,imooc_cache对应上面keys_zone=imooc_cache:10m ;关闭off
        proxy_pass http://test;
        proxy_cache_valid 200 304 12h; #200和304头信息过期时间12小时
        proxy_cache_valid any 10m;  #其他过期时间10分钟
        proxy_cache_key $host$uri$is_args$args; #定义缓存的key
        add_header  Nginx-Cache "$upstream_cache_status";#增加一个头信息
        
        
        #部分不设置缓存 cookie_nocache上面配置的参数
        #cookie_nocache不为0或者空那么是不会进行缓存的-----2.设置某些访问路径不缓存
        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; 
        include proxy_params;
    }
}

动静分离

  1. 启动一个tomcat,并编写一个index.jsp
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>  
<HTML>
    <HEAD>
        <TITLE>JSP Test Page</TITLE>
    </HEAD>
    <BODY>
        <%
            Random rand = new Random();
            out.println("<h1>Random number:</h1>");
            out.println(rand.nextInt(99)+100);
        %>
    </BODY>
</HTML>
  1. 编写nginx的html页面
 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
<html lang="en">  
<head>  
<meta charset="UTF-8" />  
<title>测试动静分离</title>  
<script src="http://libs.baidu.com/jquery/2.1.4/jquery.min.js"></script>  
</head>  
<script type="text/javascript">  
$(document).ready(function(){  
    $.ajax({  
        type: "GET",  
        url: "http://www.maishuren.com/java_test.jsp",
        success: function(data) {
            $("#get_data").html(data)
        },
        error: function() {  
            alert("fail!!!,请刷新再试!");  
        }  
    });  
});  
</script>  
<body>  
    <h1>测试动静分离</h1>
    <img src="http://www.maishuren.com/img/nginx.png-msr"/>
    <div id="get_data"><div>
</body>
</html> 
  1. 配置nginx配置文件
 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
upstream java_api{
    server 127.0.0.1:8080;
}
server {
    listen       80;
    server_name  localhost www.maishuren.com;
    #charset koi8-r;
    access_log  /var/log/nginx/log/host.access.log  main;
    root /opt/app/code;  

    location ~ \.jsp$ {
    	#转去请求动态资源的服务器
        proxy_pass http://java_api;
        index  index.html index.htm;
    }


    location ~ \.(jpg|png|gif)$ {
        expires 1h;
        gzip on;
    }

    location /{
        index  index.html index.htm;
    }
    error_page   500 502 503 504 404  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}

配置了动静分离这样可以减轻服务端的压力,当在只请求静态资源的时候,直接通过中间件就可以获取静态资源,不需要通过程序框架和逻辑再去获取。

Licensed under CC BY-NC-SA 4.0