Nginx进阶
服务优化
经过一段时间的学习和操作,我们发现两个问题,一个是每次操作完配置文件后,都需要到sbin目录下操作nginx的命令,第二个是如果系统重启,需要手动再去开启nginx服务。那么,针对这两个问题,我们对Nginx服务进行优化
- 配置nginx命令的系统环境变量
- 将nginx服务配置成开机自启动
nginx配置成系统服务
-
在
/usr/lib/systemd/system
目录下添加nginx.service
文件,内容如下[Unit] Description=nginx web service Documentation=http://nginx.org/en/docs/ After=network.target [Service] Type=forking PIDFile=/usr/local/nginx/logs/nginx.pid ExecStartPre=/usr/local/nginx/sbin/nginx -t -c /usr/local/nginx/conf/nginx.conf ExecStart=/usr/local/nginx/sbin/nginx ExecReload=/usr/local/nginx/sbin/nginx -s reload ExecStop=/usr/local/nginx/sbin/nginx -s stop PrivateTmp=true [Install] WantedBy=default.target
-
添加完成后,如果有权限问题,需要进行权限设置
chmod 755 /usr/lib/systemd/system/nginx.service
-
测试使用系统命令来操作Nginx服务
启动:systemctl start nginx 停止:systemctl stop nginx 重启:systemctl restart nginx 重新加载配置文件:systemctl reload nginx 查看nginx状态:systemctl status nginx 开启自启动:systemctl enable nginx
-
测试注意事项:
先停止原来的服务,然后用上面的启动命令启动后测试
配合
ps -ef |grep nginx
命令 测试是否重启成功,可以观察master进程id是否变化测试reload是否成功,观察是否master进程不变,worker进程号改变
配置环境变量
-
打开
/etc/profile
文件,再最后加上nginx的环境变量配置... ... # PATH就是环境变量 windows下各个环境变量分隔符是分号,linux下是冒号 export PATH=$PATH:/usr/local/nginx/sbin
-
使配置文件生效
source /etc/profile
-
测试
nginx -V
Nginx静态资源部署
Nginx静态资源概述
我们通过url去浏览器访问资源,实际上就是通过浏览器发送一个http请求实现从客户端发送请求到服务端获取所需内容后并把内容回显展示在页面的一个过程。这个过程中,我们所请求到的内容分为两种类型,一类是静态资源,另一类是动态资源。静态资源即在服务器端真实存在并且能直接拿来展示的一些文件,比如常见的如html页面、css文件、js文件、图片、视频等资源。动态资源即值在服务端真实存在但是要想获取需要经过一定的业务逻辑处理,根据不同的条件展示在页面不同的这一部分内容。
Nginx处理静态资源的内容,需要考虑一下几个问题
- 静态资源的配置指令
- 静态资源的配置优化
- 静态资源的压缩配置指令
- 静态资源的缓存处理
- 静态资源的访问控制,包括跨域问题和防盗链问题
Nginx静态资源配置相关指令
listen:用来配置监听端口
语法:listen address[:port][default_server]...;
listen port [default_server]
默认值:listen *:80|*:8000
配置在server块中
listen的配置比较灵活,常用的设置方式如下:
listen 127.0.0.1:8000; # 监听指定的IP和端口
listen 127.0.0.1; # 监听指定IP的所有端口
listen 8000; # 监听指定端口上的连接
listen *:8000; # 监听指定端口上的连接
default_server属性是标识符,用来将此虚拟主机设置成默认主机。即如果没有匹配到对应的address:port,则会默认执行的。如果不加这个标识符,使用的是第一个server。
server_name:用来设置虚拟主机服务名称
语法:server_name name...
支持配多个,空格分隔,默认server_name "";
server_name的配置方式有三种:
-
精准匹配
server { listen 80; server_name www.itcm.cn www.dyne.com; ... }
-
通配符匹配
server_name中支持通配符"*",但需要注意的是通配符不能出现在域名的中间,只能出现在首段或尾段,如:
server { listen 80; server_name *.itcm.cn www.dyne.*; ... }
-
正则表达式匹配
server_name中可以使用正则表达式,并且使用~作为正则表达式字符串的开始标记。
注意 ~后面不能加空格,括号可以取值
server{ listen 80; server_name ~^www\.(\w+)\.com$; ... }
匹配执行顺序(这个顺序为优先级,最终是只会匹配到一个):
-
准确匹配server_name
-
通配符在开始时匹配server_name成功
-
通配符在结束时匹配server_name成功
-
正则表达式匹配server_name成功
-
被默认的default_server处理,如果没有指定默认找第一个server
location:用来设置请求的URI
语法:location [ = | ~ | ~* | ^* | ^~ | @ ]uri{...}
uri变量是待匹配的请求字符串,可以不包括正则表达式,也可以包括正则表达式,nginx在搜索匹配location的时候,是先使用不包含正则表达是匹配,找到一个匹配度最高的,然后通过包含正则表达式的进行匹配,如果匹配到直接访问,匹配不到,就使用刚才匹配度最高的location来处理请求
-
不带符号的
即location后面不带任何符号,直接跟uri,那么只有以指定的模式开头即可
如:
location /abc
那么你访问路径/abc
、/abcdef
、/abc/aa
、/abc?name=cm
都能匹配到 -
=:用于不包含正则表达式的uri前,必须与指定模式精确匹配
精确匹配,如:
location =/abc
,那么只能匹配到/abc
、abc?p1=v1...
-
~:用于表示当前uri中包含了正则表达式,并且区分大小写
如:
location ~^/abc\w$
-
~*:用于表示当前uri中包含了正则表达式,并且不区分大小写
如:
location ~*^/abc\w$
-
^~:功能和不带符号一致,唯一的区别在于,如果匹配成功,那么停止搜索其他模式
如:
location ^~/abc\w$
设置请求资源目录:root/alias
root:设置请求的根目录
语法:root path
默认值:html
可以在http、server、location三个块中
path为Nginx服务器接收到请求以后查找资源的根目录路径
alias:用来更改location的URI
语法:alias path
path为修改后的根路径
结论:
- root处理的结果:root路径+location路径
- alias的处理结果:使用alias路径替换location
举例:
# rootlocation /images { root /usr/local/nginx/html; }# aliaslocation /images { alias /usr/local/nginx/html; }
以上两种方式,如果后台请求的是10.0.0.203/images/abc.jpg
那么访问到服务器查找图片的地址:
- root:
/usr/local/nginx/html/images/abc.jpg
- alias:
/usr/local/nginx/html/abc.jpg
**ps:**如果location路径是以/结尾,则alias也必须是以/结尾
index:设置网站的默认首页
语法:index file
默认值:index index.html
可以是html文件也可以是图片等资源文件
index后面可以跟多个设置,如果访问的时候没有指定具体访问的资源,则会依次进行查找
如默认配置中:
location / { root html; index index.html index.htm; }
error_page:设置网站的错误页面
语法:error_page code ... [=[response]] uri;
当匹配到对应的错误码之后,处理方式可以有以下几种配置方式
-
指定具体跳转的地址
server { error_page 404 http://www.itcm.com;}
-
指定重定向地址
server { error_page 404 /50x.html; error_page 500 502 503 504 /50x.html; location =/50x.html { root html; }}
-
使用location的@符合完成错误信息展示
server { error_page 404 @jump_to_error; location @jump_to_error { default_type text/plain; return 404 'Not Found Page ...'; }}
**ps:**可选配置参数 =response,代表将响应状态吗更改为其他,如检测到响应状态码是404的时候,将状态码改为200,这样前端浏览器获取的状态码就是200了。
server { error_page 404 =200 http://www.itcm.com;}
静态资源优化配置
Nginx对静态资源进行优化配置,可以从以下三个配置进行优化
sendfile on;tcp_nopush on;tcp_nodeplay on;
sendfile:用来开启高效的文件传输模式
语法:sendfile on|off
默认值:off,可以配置在http、server、location… 但是一般都配置http
请求静态资源的过程:客户端通过网络接口向服务端发送请求,操作系统将这些客户端的请求传递给服务端应用程序,服务端应用程序会处理这些请求,请求处理完成以后,操作系统还需要将处理得到的结果通过网络适配器传递回去。
tcp_nopush:该指令必须在sendfile打开的状态下才会生效,主要是用来提升网络包的传输效率
语法:tcp_nopush on|off
,默认值为off,可以配置在http、server、location
tcp_nodelay:该指令必须在keep-alive连接开启的情况下才生效,来提高网络包传输的实时性
语法:tcp_nodelay on|off
,默认值为on,可以配置在http、server、location
简单可以理解为,服务端向客户端返回数据的时候,tcp_nopush是先将数据放入缓冲区,存满了再发,而tcp_nodelay则时有数据就发,那么这两者看上去时互斥的,为什么我们建议把这两个同时打开呢?
因为在linux2.5.9之后的版本中,这两者是可以兼容的,三个指令(包括sendfile)都开启的好处是,sendfile可以开启高效的文件传输模式,tcp_nopush开启可以确保在发送到客户端之前的数据包已经充分"填满",这大大的减少了网络开销,并加快了文件发送的速度,然后,当它达到最后一个可能因为没有“填满”而暂停的数据包时,Nginx会忽略tcp_nopush参数,然后tcp_nodelay强制套接字发送数据。由此可知,tcp_nopush和tcp_nodelay可以一起设置,比单独配置tcp_nodelay具有更高的性能,因此优化Nginx静态资源处理,建议三个都设置on
Nginx静态资源压缩
经过上面的优化后,我们还需要思考一个问题,当我们传输的文件非常大的时候,能不能像我们在电脑上传输文件一样,先压缩,对方收到压缩包后,再解压缩呢?如果可以压缩大的数据包,那么数据包小了之后,传输速度也就更快了。当然Nginx中也是有压缩模块的。
在Nginx的配置文件中,可以通过配置gzip来对静态资源进行压缩,相关指令可以配置在http块,也可以配置在location和server块中,涉及到以下三个模块
- ngx_http_gzip_module - nginx安装时默认会安装的内置模块
- ngx_http_gzip_static_module - 需要自己手动安装
- ngx_http_gunzip_module - 需要自己手动安装
Gzip模块配置指令
以下的几个指令都来自ngx_http_gzip_module模块,该模块会在nginx安装的时候内置到nginx的安装环境中,也就是说我们可以直接使用这些指令。
gzip:该指令用于开启或者关闭gzip功能
语法:gzip on|off
默认值:off,位置:http、server、location …
测试:访问一个html目录下的js文件,测试时,因为浏览器也自带缓存,可以勾选disable_cache,以达到测试效果
**ps:**以下指令都是基于这个gzip指令开启的前提下,否则无效
gzip_types:该指令可以根据响应页的MIME类型选择性的开启Gzip压缩功能
语法:gzip_types mime-type ...;
默认配置:gzip_types text/html;
位置:http、server、location
所配置的mime-type的值可以在mime.types文件中进行查找,也可以使用 * 代表所有,不建议使用*配置,根据自己的需求来配置所要压缩的类型,配置多个,中间用空格分隔开即可
所以上面我们只设置了gzip on
没有达到压缩效果,就是因为默认的压缩类型是text/html
这里我们配置上js的类型gzip_types application/javascript
,效果如下:
gzip_comp_level:该指令用于设置Gzip压缩程度,级别从1-9,程度由低到高,效率自然是由高到低。默认值就是1
语法:gzip_comp_level level
,位置:http、server、location,一般建议设置中间值,比如6,因为有些文件已经压缩的很小了,再加大级别,既浪费cpu资源,压缩提升也不高。如我们测试的文件,从6改为9,压缩文件只缩小了零点几KB
gzip_vary:该指令用于设置使用Gzip压缩发送的文件是否携带
Vary:Accept-Encoding
头域的响应头部,也就是告诉接收方,所发送的数据经过了Gzip压缩处理
语法:gzip_vary on|off
默认:off ,位置:http、server、location
gzip_buffers:该指令用于处理请求压缩的缓冲区数量和大小
语法:gzip_buffers number size
默认配置:gzip_buffers 32 4k | 16 8k;
(和操作系统有关)位置:http、server、location
number:指定Nginx服务器向系统申请缓存空间个数
size:每个缓存空间的大小
主要实现的是申请number个大小为size的内存空间,这个值的设定一般会和服务器的操作系统有关,所以建议此项不设置,使用默认值即可
gzip_disable:针对不同种类的客户端,选择性的开启和关闭Gzip功能
语法:gzip_disable regex ...;
位置:http、server、location
regex:根据客户端的浏览器标识(user-agent)来设置,支持正则表达式。指定的浏览器标识不使用Gzip,该指令主要是用来排除一些不支持Gzip的浏览器(一些低版本的浏览器不支持,如果不禁用压缩功能,页面会乱码)。 gzip_disable "MSIE [1-6]\.";
(对IE6以及以下的版本都不进行压缩)
gzip_http_version:针对不同的HTTP协议版本,可以选择性开启和关闭Gzip功能
语法:gzip_http_version 1.0|1.1;
默认值:1.1 ,位置:http、server、location
用于指定使用Gzip的HTTP最低版本,使用默认值即可
gzip_min_length:该指令针对传输数据的大小,可以选择性的开启和关闭Gzip功能
语法:gzip_min_length length;
默认:20,位置:http、server、location
ps:nginx计量大小单位:bytes,即字节,默认20就是20字节,1k或者1K代表千字节,1m或者1M代表兆字节
Gzip压缩功能对大文件压缩效果明显,但是对数据比较小的,可能会出现压缩后反而变大的情况,因此我们需要根据响应内容的大小来决定是否使用Gzip功能,响应页面的大小可以通过头信息中的content-Length来获取,但是如果使用了Chunk编码动态压缩,该指令将被忽略,建议设置为1k或者以上
gzip_proxied:该指令设置是否对服务端返回的结果进行Gzip压缩
此配置设计到反向代理
语法:gzip_proxied off|expired|no-cache|no-store|private|no_last_modified|no_etag|auth|any
默认值:gzip_proxied off
,位置:http、server、location
- off:关闭对后台服务器返回的结果的Gzip压缩
- expired:如果header信息中包含
Expires
,启用压缩 - no-cache:如果header信息中包含
Cache-Control:no-cache
,启用压缩 - no-store:如果header信息中包含
Cache-Control:no-store
,启用压缩 - private:如果header信息中包含
Cache-Control:private
,启用压缩 - no_last_modified:如果header信息中不包含
Last-Modified
,启用压缩 - no_etag:如果header信息中不包含
ETag
,启用压缩 - auth:如果header信息中包含
Authorization
,启用压缩 - any:无条件压缩
配置案例:
一般我们对gzip的配置都是通用的,所以单独创建一个文件,然后include到nginx.conf中即可:
nginx_gzip.conf :
gzip on;gzip_types *;gzip_comp_level 6;gzip_min_length 1024;gzip_buffers 4 16k;gzip_http_version 1.1;gzip_vary on;gzip_disable "MSIE [1-6]\.";gzip_proxied off;
nginx.conf的http块中添加一行:include nginx_gzip.conf;
Gzip和sendfile共存问题
sendfile开启之后,在读取磁盘上的静态资源文件的时候,减少了拷贝次数,可以不经过用户进程将静态资源文件通过网络设备发送出去,但是Gzip对资源压缩,是需要经过用户进程进行操作的,所以Gzip会让sendfile功能失效
解决思路是:在访问静态资源文件之前,就压缩好并存储为.gz后缀名文件,这样如果需要返回压缩文件,直接去找对应文件的.gz文件即可
当然,Nginx也提供了解决该问题的模块和指令,即ngx_http_gzip_static_module模块的gzip_static指令
所以使用这个命令之前,我们需要新增ngx_http_gzip_static_module这个模块,此操作在第二节有教程
gzip_static: 检查于访问资源文件同名的.gz文件,response中以gzip相关的header返回.gz文件的内容
语法:gzip_static on | off | always
默认值:off
位置:http、server、location
ps:on 会检查浏览器是否支持这个gzip,支持才发送压缩文件,always则不做检查,直接发送压缩文件
新增ngx_http_gzip_static_module模块:
-
nginx -V :先查出原配置参数,保持到自己的文本工具中备用
-
进入到nginx的源码安装目录:/root/nginx/core/nginx-1.16.1,执行命令
make clean
清空之前编译的内容 -
通过configure命令指定参数,在原配置参数基础上加上新增的配置
./configure --prefix=/usr/local/nginx --sbin-path=/usr/local/nginx/sbin/nginx --modules-path=/usr/local/nginx/modules --conf-path=/usr/local/nginx/conf/nginx.conf --error-log-path=/usr/local/nginx/logs/error.log --http-log-path=/usr/local/nginx/logs/access.log --pid-path=/usr/local/nginx/logs/nginx.pid --lock-path=/usr/local/nginx/logs/nginx.lock --with-http_gzip_static_module
-
执行
make
命令编译 -
编译完成后,将objs下新生成的二进制文件:nginx,拷贝到nginx安装目录下的sbin下即可
cp objs/nginx /usr/local/nginx/sbin
-
执行命令:
make upgrade
测试使用:
测试此功能要关闭gzip,即gzip off
-
访问test.js
-
使用gzip命令:
gzip test.js
生成压缩文件:test.js.gz
-
再次访问test.js
总结:生成.gz文件必须手动处理,生成文件后,即当存在对应的.gz文件且gzip_static开启的状态下,就会返回对应的压缩文件,且返回的头部信息含有:Content-Encoding: gzip
、Vary: Accept-Encoding
这两条信息
静态资源缓存处理
什么是缓存?
缓存(Cache),原指访问速度比一般随机存取存储器(RAM)快的一种高速存储器,通常它不像系统主存那样使用DRAM技术,而使用的是昂贵的SRAM技术。缓存的设置是所有现代计算机系统发挥高性能的重要因素之一。
什么是Web缓存?
Web缓存是指一个Web资源(如HTML页面、图片、JS等)存在于Web服务器和客户端(浏览器)之间的副本。缓存会根据进来的请求保存输出的副本,当下一个请求来的时候,如果是相同的URL,缓存会根据缓存机制决定是直接使用副本响应访问请求还是向资源服务器再次发送请求。比较常见的就是浏览器会缓存访问过网站的网页,当再次访问这个URL的时候,如果网页还没有更新,就不会再次下载网页,而是直接使用本地缓存的网页。只有当网站明确标识资源已经更新,浏览器才会再次下载网页。
web缓存的种类
- 客户端缓存 : 如浏览器
- 服务端缓存: 如Nginx、Redis、Memcached等
浏览器缓存
为了节约网络的资源加速浏览,浏览器在用户磁盘上对最近请求过的文档进行存储,当访问者再次请求这个页面的时候,浏览器就可以从本地磁盘显示文档,这样就可以加速页面的显示
使用浏览器缓存的优点
- 成本最低的一种缓存实现
- 减少网络带宽消耗
- 降低服务端的压力
- 减少网络延迟,加速网页打开的速度,提升用户体验
HTTP协议中和页面缓存相关的字段:
- Expires:缓存过期的日期和时间
- Cache-Control:设置和缓存相关的配置信息
- Last-Modified:请求资源最后修改的时间
- ETag:请求变量的实体标签的当前值,比如文件的MD5值
浏览器缓存的执行流程:
tips: 如果想要演示强缓存,只能在新的标签页中打开相同的链接才能有效,可以通过network看出响应码200是灰色的,响应头等信息也是缓存的,当然要把Disable cache
取消勾选,否则不会走缓存
弱缓存:
硬缓存:
Nginx配置浏览器缓存相关指令
expires:用来控制页面缓存,可以通过该指令控制HTTP响应中的
Expires
和Cache-Control
# 配置方式一expires [modified] time# 配置方式二expires epoch|max|off
默认值:expires off;
- time:可以整数也可以是负数,指定过期时间,如果是负数,Cache-Control则为no-cache,如果为整数或0,则Cache-Control的值为max-age=time;
- epoch:指定Expires的是为’1 January,1970,00:00:01 GMT’(1970-01-01 00:00:00),Cache-Control的值no-cache
- max:指定Expires的值为’31 December,2037 23:59:59 GMT’(2037-12-31 23:59:59),Cache-Control的值为10年
add_header:用来添加指定的响应头和响应值
语法:add_header name value [always];
如Cache-Control作为响应头信息,可以设置如下值:
Cache-Control值 | 说明 |
---|---|
must-revalidate | 可缓存但必须再向服务器进行确认 |
no-cache | 缓存钱必须确认其有效性 |
no-store | 不缓存请求或者响应的任何内容 |
no-transform | 代理不可更改媒体类型 |
public | 可向任意地方提供响应的缓存 |
private | 仅向特定用户返回响应 |
proxy-revalidate | 要求中间缓存服务器对缓存的响应有效性再进行确认 |
max-age=<秒> | 响应最大Age值 |
s-maxage=<秒> | 公共缓存服务器响应最大Age值 |
配置案例(仅语法参考):
location ~ .*\.(html|js|css|png)$ { expires max; add_header Cache-Control no-store;}