静态资源服务器和动静分离

负责接收静态资源请求,根据url从文件存储中获取并返回给客户端,常用于动静分离。

静态资源是指无需服务器动态生成的文件资源,比如视频、html、图片等。

针对静态资源的配置,主要有两个切入点:

  • 针对内容压缩

  • 浏览器缓存

  • 跨域访问

  • 防盗链

针对内容压缩

sendfile、tcp_nopush、tcp_nodelay

# sendfile,文件零拷贝读取
Syntax: sendfile on|off;
Default: sendfile off;
Context: http, server, location, if in location

# tcp_nopush
# 当使用sendfile时,tcp_nopush才起作用,于tcp_nodelay是互斥的
# 开启后,有数据包不会立即传送出去,而是等到等待传送的数据包达到最大时,一次性传输出去,有利于解决网络阻塞
Syntax: tcp_nopush on|off;
Default: tcp_nopush off;
Context: http, server, location

# tcp_nodelay
# 无等待,立即发送包,在实时性高的情况下可以开启,与tcp_nopush互斥
# 默认开启
# 常用于keepalive 连接下,提高网络包的传输实时性
Syntax: tcp_nodelay on|off;
Default: tcp_nodelay on;
Context: http, server, location

http_gzip_static_module

此模块用于预读gzip压缩文件:

location ~ ^/download {
    # 开启此功能
    gzip_static on;
    root /usr/share/nginx/gzipfile;
}

在请求/download/index.html的时候,此模块会先从root下寻找文件index.html.gz,如果找不到才会去寻找index.html文件。

gz文件需要预先生成,生成可以使用gzip命令:

gzip ./index.html 
> ls
index.html.gz

那么在浏览器请求/download/index.html,会展示index.html.gz解压后的html文件的内容。

http_gunzip_module

部分浏览器不支持gzip压缩,可以使用此模块,此处不再演示。

示例配置

server {
    listen       80;
    server_name  116.62.103.228 jeson.imooc.com;
    
    # 打开`sendfile`零拷贝机制
    sendfile on;
    # 多个包打包在一起,一起发送,大文件推荐打开, 可提高网路包的传输效率
    #tcp_nopush on;
    # 实时发送,在是实时性较高的需求中,需要打开(需要连接是keepalived长连接)
    #tcp_nodelay on
    
    #charset koi8-r;
    access_log  /var/log/nginx/log/static_access.log  main;

    # 图片资源匹配
    location ~ .*\.(jpg|gif|png)$ {
        # 打开gzip压缩,发送之前会对资源进行gzip压缩,浏览器接收到时会进行解压,效果可以比对文件传输的大小
        gzip on;
        # gizp的http协议的版本
        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  /usr/share/nginx/img;
    }
	
    # 文本资源匹配
    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  /usr/share/nginx/doc;
    }

    # download开头的路径匹配
    location ~ ^/download {
        # 来自 http_gzip_static_module,具有预读gzip功能,需要预先将文件压缩放入磁盘
        gzip_static on;
        tcp_nopush on;
        root /usr/share/nginx/gzipfile;
    }

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

浏览器缓存

使用浏览器缓存静态资源的两个好处:

  • 不用实时从服务器中获取,减少了服务端资源消耗

  • 客户端可以从本地直接读取,响应延时更低

HTTP协议缓存支持

功能Header

HTTP1.0 记录过期时间,超过指定时间会失效

Expire

HTTP1.1 最大期限,用于替代1.0,超过最大期限会失效

Cache-Control(max-age)

最后修改时间校验比较,值为时间,只能精确到秒,秒级别的更新无效

Last-Modified

判断Etag是否过期,类似Last-Modified,是一个信息摘要字符串,不同就说明已经过期

Etag

Etag 与 Last-Modified 缓存策略下,当缓存处于有效状态时,请求静态资源的响应状态将会变为304。nginx默认采用此种缓存方式

Expire与Cache-Control 的优先级大于 Last-Modified 和 Etag

expires 配置浏览器缓存

# expires 语句会为响应添加 Cache-Control、Expires头
# time代表缓存时间周期
Syntax: expires [modified] time;
	   expires epoch | max | off;
Default: expires off;
Context: http, server, location, if in location

示例配置

location ~ .*\.(htm|html)$ {
    # 缓存有效期为1天
    expires 24h;
    root /usr/share/nginx/html;
}

此时可以看到,Cache-Control已经变为86400,单位为秒,即24h

跨域访问

浏览器是不允许ajax跨域访问,但是JS等资源有可能位于CDN中,并且域名不同,此时就需要nginx的跨域访问支持。虽然跨域访问不安全(CSRF攻击),但是出于软件结构设计、业务形态等种种原因,仍需要跨域访问支持。

HTTP对跨域的支持

HTTP协议提供了Access-Control-Allow-Origin头,此头的值由服务端返回给客户端,告诉客户端可以进行跨站访问。

使用add_header添加跨域头

# 给当前响应添加头,name代表头名称,value代表值
Syntax: add_header name value [always];
Default: 
Context: http, server, location, if in location

示例配置

location ~ .*\.(htm|html)$ {
	add_header Access-Control-Allow-Origin http://www.baidu.com;
    # add_header Access-Control-Allow-Origin *; # 所有都可以跨域,会发生CSRF攻击
    add_header Access-Control-Allow-Methods GET,POST,PUT,OPTIONS;
    root /usr/share/nginx/html;
}

防盗链

防盗链就是防止网站资源被盗用:

  • 防止网站资源被爬取

  • 大量伪用户访问网站资源,占用网站性能

防盗链的设置思路

  • 区别哪些请求是非正常用户请求

基于http_refer防盗链

$http_refer代表此请求来源处,如果此请求不是本网站的,就不允许访问,这样就能防止其他网站使用自己网站的图片、视频等资源。

# 校验refer是否合法,此处可配置多个值,使用空格隔开
# none:允许没有refer信息
# blocked: 允许refer信息不是标准的uri(不是以http://域名开头)
# servernames 允许的ip、域名
# 还支持正则匹配
Syntax: valid_referers none|blocked|servernames|regex ...;
Default: 
Context: server, location

示例配置

# 图片资源匹配
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;
    # 允许请求没有refer信息
    # 允许不标准的refer信息
    # 允许ip为 192.168.173.165 的请求
    # 其他都不允许,返回403
    valid_referers none blocked 192.168.173.165;
    if ($invalid_referer) {
        return 403;
    }
    root  /usr/share/nginx/img;
}

动静分离

动静分离是指,通过中间件将动态请求与静态请求分离,从而分离资源,减少不必要的请求消耗,减少请求延时。

在动静不分离之前,一个静态请求需要经过一下几个部分才能获取到:

中间件(Nginx) -> 程序框架(Spring) -> 程序逻辑 -> 数据资源

在东京分离之后,静态请求将会直接由中间件处理,所以效率更高:

中间件(Nginx) -> 数据资源

并且,如果一方出现问题,另一方不会受到影响。

动静分离配置不再演示

最后更新于