介绍
Nginx作为静态资源的HTTP server,他可以接收客户端 REQ:jpeg、htm、flv这种静态资源的请求,然后直接通过静态资源的存储,得到这些文件返回给客户端,这种方式是一个典型的比较高效的传输模式。这种场景常常会应用在静态资源的请求,处理,以及动静分离。
一、静态资源
那么什么是静态资源?就是非服务器动态运行生成的文件:
类型 | 种类 |
浏览器端渲染 | HTML、CSS、JS |
图片 | JPEG、GIF、PNG |
视频 | FLV、MPEG |
文件 | TXT等任意下载文件 |
动态生成:我们需要经过服务端的解释器进行一些比较复杂的逻辑运算,对应的数据进行封装,再去返回给用户
非服务器动态生成:客户端直接请求,服务端从文件系统直接就可以找到文件返回给用户
二、CDN场景
CDN全称为内容分发网络,我们在请求静态资源的时候常常会用到。
对于CDN来说,我们要求的是传输延迟的最小化。
配置语法:sendfile:
Syntax: sendfile on|off;Default: sendfile off;Context: http,server,location,if in location
对于nginx读取文件的方式,除了sendfile这种内核优化方式外,也用到了--with-file-aio异步文件读取方式。
配置语法:tcp_nopush:
Syntax: tcp_nopush on|off;Default: tcp_nopush off;Context: http,server,location
作用:sendfile开启的情况下,提高网络包的传输效率。把多个包整体进行整合,一次性发送出去给用户端,这个对于报文的处理,提升了网络的传输的效率。
配置语法:tcp_nodelay:
Syntax: tcp_nodelay on|off;Default: tcp_nodelay off;Context: http,server,location
作用:该网络包尽量不要等待,实时性的发送给用户,keepalive连接下,提高网络包的传输实时性。
配置语法:gzip压缩:
Syntax: gzip on|off;Default: gzip off;Context: http,server,location,if in location
作用:压缩传输,需要对nginx进行静态资源的压缩,减小不必要的网络资源的消耗和传输的等待。如下图:
配置语法:gzip_comp_level压缩比:
Syntax: gzip_comp_level level;Default: gzip_comp_level 1;Context: http,server,location
作用:level越大,文件压缩比率更大,传输的文件也就越小,但是压缩本身也需要消耗服务端的性能。
配置语法:gzip_comp_level http的版本:
Syntax: gzip_http_version 1.0|1.1;Default: gzip_http_version 1.1;Context: http,server,location
作用:目前主流的http都是1.1的版本。
扩展Nginx压缩模块:
http_gzip_static_module // 预读gzip功能http_gunzip_module // 应用支持gunzip的压缩方式,为了解决很少一部分浏览器无法支持gzip压缩
场景演示
新建code文件:
[root@node1 log]# cd /opt/app/code/[root@node1 code]# lsadmin.html black.html doc download images red.html submodule.html[root@node1 code]# cd images/[root@node1 images]# lswei.png[root@node1 images]# cd ../doc[root@node1 doc]# lsaccess.txt[root@node1 doc]# cd ../download/[root@node1 download]# lstest.img.gz[root@node1 download]#
wei.png:验证图片压缩
access.txt:验证文本压缩
test.img.gz:验证download
配置文件:
server { listen 80; server_name 192.168.x.xxx node1; sendfile on; #charset koi8-r; access_log /var/log/nginx/log/static_access.log main; 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/app/code/images; } 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/app/code/doc; } location ~ ^/download { gzip_static on; tcp_nopush on; root /opt/app/code; }
在没有打开gzip的情况下和打开gzip情况下访问:
http://192.168.x.xxx/wei.pnghttp://192.168.x.xxx/access.txthttp://192.168.x.xxx/test.img //当gzip_static off情况下回找不到文件报错,on会保存原文件
对比压缩前后的大小。
三、浏览器缓存原理
浏览器是有自己的缓存机制的,是基于HTTP协议的缓存机制(如:Expires,cache-control等)。实现浏览器的缓存就是依赖的HTTP头信息来跟服务端进行验证。
校验过期机制:
校验是否过期 | Expires、Cache-Control(max-age) |
协议中Etag头信息校验 | Etag |
Last-Modified头信息校验 | Last-Modified |
1. 校验本地缓存是否过期(本地缓存文件里面的http头信息)
Expires:http1.0版本
Cache-Control:http1.1版本
max-age:周期,表示缓存文件在多久时间内表示过期
2. 如果本地缓存过期了,进行Etag和Last-Modified验证(相同,都是向服务端进行验证)
向服务端先进行Etag验证,判断Etag是否过期,因为Last-Modified只能精确到秒,在1秒内的更新服务端是无法识别的
Etag是一串特殊的字符串,所以服务端也会保留一串特殊的字符串,来进行与Etag进行校验
3. Last-Modified校验
Last-Modified是一个具体的年与日时分秒,用来跟服务端文件和本地文件进行校验
如果本地文件在该时间周期有更新,那么服务端对应的文件的时间就会更新,出现客户端与服务端文件时间不一致,这样的话服务端就会返回最新的文件给客户端。
整体流程如下:
配置语法:expires:
Syntax: expires[modified]time; expires epoch|max|off;Default: expires offContext: http,server,location,if in location
expires的原理就是对客户端的response报文的头信息里面添加Cache-Control和Expires头。
场景演示
新建code:test_expires.html:
duan admin
Hello Word!
增加配置:
location ~ .*\.(htm|html)$ { #expires 24h; root /opt/app/code/html; }
访问测试:
http://192.168.x.xxx/test_expires.html
第一次访问:
第二次访问:
第二次访问多了Cache-Control:max--age=0。这个是浏览器自己加进去的,max--age=0或者max--age<0表示每一次请求都要向服务端进行一次校验,看文件有没有更新,如果有更新则返回200,如果没有更新,则返回304。
修改配置:打开过期时间:
location ~ .*\.(htm|html)$ { #expires 24h; root /opt/app/code/html; }
发现在Response Headers里面多加了两个头:
Cache-Control:max--age=86400(秒)
Expires: Thu, 02 Apr 2020 15:26:53 GMT
但是客户端浏览器遵循自己设置的Cache-Control:max--age=0,去请求服务端。
四、跨站访问
理论上浏览器都会禁止网站进行一个页面进行跨站式访问。跨站式访问:浏览器访问一个服务端,一个页面里面当访问a时,同时会访问b(ajax),浏览器一般是会禁止的,主要是出于安全的考虑。
为什么浏览器禁止跨域访问?原因是不安全,容易出现CSRF攻击。
一般一个用户去访问一个正规的网站A,A会返回给用户session,cookie等信息,存放在客户端,当客户一不小心点到了一些非法的网站B,这时网站B就可以给用户response一些带有恶意的请求,让用户去请求网站A,这样就形成了跨站访问。
打开跨站访问配置:
Syntax: add_header name value[always];Default: --Context: http,server,location,if in location
浏览器会判断头信息:Access-Control-Allow-Origin,看是否允许跨站访问。
跨站演示
新建test_oringin.html:
测试ajax和跨域访问
测试跨域访问
新增配置:
location ~ .*\.(htm|html)$ { #add_header Access-Control-Allow-Origin *; #add_header Access-Control-Allow-Methods GET,POST,PUT,DELETE,OPTIONS; #expires 24h; root /opt/app/code/html; }
五、防盗链
防盗链的目的是防止网站资源被盗用,防盗链设置的首要方式是区别哪些请求是非正常的用户请求。
基于http_refer防盗链配置模块。配置语法:
Syntax: valid_referers none|blocked|server_names|string...;Default: --Context: server,location
场景演示
新建test_refer.html:
imooc1
在不配置http_refer防盗链测试refer功能:
http://192.168.x.xxx/test_refer.html
添加http_refer配置:
location ~ .*\.(jpg|gif|png)$ { #valid_referers none blocked 192.168.x.xxx ~/google\./; //支持正则方式 valid_referers none blocked 192.168.x.xxx; if ($invalid_referer) { return 403; } root /opt/app/code/images; }
valid_referers:表示允许那些信息过来访问
none:表示允许没有带refer信息的请求过来
blocked:表示refer信息不是标准http://,也是不允许访问的
ip:表示只允许该ip过来访问
$invalid_referer:如果没有设置ip,$invalid_referer变量值就会为1,返回403
访问测试:
// 不带refer信息[root@node1 conf.d]# curl -I http://192.168.x.xxx/wei.pngHTTP/1.1 200 OKServer: nginx/1.16.1Date: Thu, 02 Apr 2020 15:21:43 GMTContent-Type: image/pngContent-Length: 244044Last-Modified: Tue, 08 Aug 2017 09:17:25 GMTConnection: keep-aliveETag: "598981a5-3b94c"Accept-Ranges: bytes// 带refer信息[root@node1 conf.d]# curl -e "http://www.baidu.com" -I http://192.168.x.xxx/wei.pngHTTP/1.1 403 Forbidden // 防盗链起作用Server: nginx/1.16.1Date: Thu, 02 Apr 2020 15:22:11 GMTContent-Type: text/htmlContent-Length: 153Connection: keep-alive// 改成配置的可访问的ip[root@node1 conf.d]# curl -e "http://192.168.x.xxx" -I http://192.168.x.xxx/wei.pngHTTP/1.1 200 OKServer: nginx/1.16.1Date: Thu, 02 Apr 2020 15:23:17 GMTContent-Type: image/pngContent-Length: 244044Last-Modified: Tue, 08 Aug 2017 09:17:25 GMTConnection: keep-aliveETag: "598981a5-3b94c"Accept-Ranges: bytes
推荐阅读
Nginx学习(五):Nginx请求限制
Nginx学习(六):Nginx访问控制
JVM调优小结
看完本文有收获?请转发分享给更多人
关注「并发编程之美」,一起交流Java学习心得