linux运维之路之nginx
软件介绍
与 Apache软件类似, Nginx ( “engme x")是一个开源的,支持高性能、高并发的 WWW服务器和代理服务软件。它是由俄罗斯人 Igor Sysoev开发的,最初被应用在勘罗斯的大型网站 www.rambler.ru 上,后来作者将源代码以类BSD许可证的形式开源出来供全球使用。
Nginx因具有高并发(特别是静态资源)
、占用系统资源少
等特性,且功能丰富而逐渐流行起来。
在功能应用发面,Nginx不但是一个优秀的Web服务软件,还具有反向代理负载均衡功
能和缓存
服务功能。在反向代理负载均衡功能方面,它类似于大名鼎鼎的LVS负载均衡及Haproxy等专业代理软件,但是Nginx部署起来更为简单、方便;在缓存服务功能方面,它又类似于Squid等专业的缓存服务软件。
Nginx 的官方介绍见 http://nginx.org/en
nginx软件特性
HTTP服务器的特色及优点:
- 支持高并发:能支持几万并发连接(特别是静态小文件业务环境)
- 资源消耗少:在3万并发连接下,开启10个Nginx线程消耗的内存不到200MB
- 可以做HTTP反向代理及加速缓存、即负载均衡功能,内置对RS节点服务器健康检查功能这相当于专业的Haproxy软件或LVS的功能。
- 具备Squid等专业缓存软件等的缓存功能。
- 支持异步网络I/O事件横型epoll(Linux2.6+)
nginx的安装
nginx的安装可参考上一篇博文,这里不再啰嗦了。介绍几个nginx管理的命令吧。
启动
$ /usr/local/nginx/sbin/nginx
重新加载
$ /usr/local/nginx/sbin/nginx -s reload
检查语法
$ /usr/local/nginx/sbin/nginx -t
杀死进程
$ pkill nginx 或者 $ killall nginx # 如果现实没有killall命令,执行:yum install -y psmisc
nginx配置文件详解
nginx.conf配置文件全局结构大致如下:
- 全局配置(user,worker_process,error_log,pid)
- events(网络连接部分,worker_connections)
- http(最重要的部分,大部分功能都在这里)
- server(虚拟主机相关,在http块里)
- location(server里面)
全局配置部分
user nobody; # 定义运行nginx服务的用户,还可以加上组,如 user nobody nobody; worker_processes 1; # 定义nginx子进程数量,即提供服务的进程数量,该数值建议和服务cpu核数保持一致。 # 除了可以定义数字外,还可以定义为auto,表示让系统自动调整。 error_log logs/error.log; # 定义错误日志的路径,可以是相对路径(相对prefix路径的),也可以是绝对路径。 # 该配置可以在此处定义,也可以定义到http、server、location里。 error_log logs/error.log notice; # 定义错误日志路径以及日志级别. # 错误日志级别:常见的错误日志级别有[debug|info|notice|warn|error|crit|alert|emerg],级别越高记录的信息越少。 # 如果不定义默认是error pid logs/nginx.pid; # 定义nginx进程pid文件所在路径,可以是相对路径,也可以是绝对路径。 worker_rlimit_nofile 100000; # 定义nginx最多打开文件数限制。如果没设置的话,这个值为操作系统(ulimit -n)的限制保持一致。 # 把这个值设高,nginx就不会有“too many open files”问题了。
events配置部分
worker_connections 1024;
定义每个work_process同时开启的最大连接数,即允许最多只能有这么多连接。
accept_mutex on;
当某一个时刻只有一个网络连接请求服务器时,服务器上有多个睡眠的进程会被同时叫醒,这样会损耗一定的服务器性能。Nginx中的accept_mutex设置为on,将会对多个Nginx进程(worker processer)接收连接时进行序列化,防止多个进程争抢资源。 默认就是on。
multi_accept on;
nginx worker processer可以做到同时接收多个新到达的网络连接,前提是把该参数设置为on。
默认为off,即每个worker process一次只能接收一个新到达的网络连接。
use epoll;
Nginx服务器提供了多个事件驱动器模型来处理网络消息。
其支持的类型有:select、poll、kqueue、epoll、rtsing、/dev/poll以及eventport
。
- select:只能在Windows下使用,这个事件模型不建议在高负载的系统使用
- poll:Nginx默认首选,但不是在所有系统下都可用
- kqueue:这种方式在FreeBSD 4.1+, OpenBSD2.9+, NetBSD 2.0, 和 MacOS X系统中是最高效的
- epoll: 这种方式是在Linux 2.6+内核中最高效的方式
- rtsig:实时信号,可用在Linux 2.2.19的内核中,但不适用在高流量的系统中
- /dev/poll: Solaris 7 11/99+,HP/UX 11.22+, IRIX 6.5.15+, and Tru64
UNIX 5.1A+操作系统最高效的方式 - eventport: Solaris 10最高效的方式
http配置部分
- 官方文档 http://nginx.org/en/docs/
- 参考链接: https://segmentfault.com/a/11...
- 参考链接: https://segmentfault.com/a/11...
- 参考链接:http的header https://kb.cnblogs.com/page/9...
常见配置:
include mime.types; //cat conf/mime.types
定义nginx能识别的网络资源媒体类型(如,文本、html、js、css、流媒体等)
default_type application/octet-stream;
定义默认的type,如果不定义改行,默认为text/plain.
log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"';
定义nginx日志格式,其中main为日志格式的名字,后面的为nginx的内部变量组成的一串字符串。
access_log logs/access.log main;
定义日志的路径以及采用的日志格式,该参数可以在server配置块中定义。
sendfile on;
是否调用sendfile函数传输文件,默认为off,使用sendfile函数传输,可以减少user mode和kernel mode的切换,从而提升服务器性能。对于普通应用设为 on,如果用来进行下载等应用磁盘IO重负载应用,可设置为off,以平衡磁盘与网络I/O处理速度,降低系统的负载。
sendfile_max_chunk 128k;
该参数限定Nginx worker process每次调用sendfile()函数传输数据的最大值,默认值为0,如果设置为0则无限制。
tcp_nopush on;
当tcp_nopush设置为on时,会调用tcp_cork方法进行数据传输。
使用该方法会产生这样的效果:当应用程序产生数据时,内核不会立马封装包,而是当数据量积累到一定量时才会封装,然后传输。这样有助于解决网络堵塞问题。默认值为on。举例:快递员收快递、发快递,包裹累积到一定量才会发,节省运输成本。
keepalive_timeout 65 60;
该参数有两个值,第一个值设置nginx服务器与客户端会话结束后仍旧保持连接的最长时间,单位是秒,默认为75s。
第二个值可以省略,它是针对客户端的浏览器来设置的,可以通过curl -I看到header信息中有一项Keep-Alive: timeout=60,如果不设置就没有这一项。
第二个数值设置后,浏览器就会根据这个数值决定何时主动关闭连接,Nginx服务器就不操心了。但有的浏览器并不认可该参数。
send_timeout
这个超时时间是发送响应的超时时间,即Nginx服务器向客户端发送了数据包,但客户端一直没有去接收这个数据包。
如果某个连接超过send_timeout定义的超时时间,那么Nginx将会关闭这个连接。
client_max_body_size 10m;
浏览器在发送含有较大HTTP包体的请求时,其头部会有一个Content-Length字段,client_max_body_size是用来限制Content-Length所示值的大小的。
这个限制包体的配置不用等Nginx接收完所有的HTTP包体,就可以告诉用户请求过大不被接受。会返回413状态码。
例如,用户试图上传一个1GB的文件,Nginx在收完包头后,发现Content-Length超过client_max_body_size定义的值,
就直接发送413(Request Entity Too Large)响应给客户端。
gzip on;
是否开启gzip压缩。
gzip_min_length 1k;
设置允许压缩的页面最小字节数,页面字节数从header头得content-length中进行获取。默认值是20。建议设置成大于1k的字节数,小于1k可能会越压越大。
gzip_buffers 4 16k;
设置系统获取几个单位的buffer用于存储gzip的压缩结果数据流。4 16k代表分配4个16k的buffer。
gzip_http_version 1.1;
用于识别 http 协议的版本,早期的浏览器不支持 Gzip 压缩,用户会看到乱码,所以为了支持前期版本加上了这个选项。
如果你用了Nginx反向代理并期望也启用Gzip压缩的话,由于末端通信是http/1.1,故请设置为 1.1。
gzip_comp_level 6;
gzip压缩比,1压缩比最小处理速度最快,9压缩比最大但处理速度最慢(传输快但比较消耗cpu)
gzip_types mime-type ... ;
匹配mime类型进行压缩,无论是否指定,”text/html”类型总是会被压缩的。在conf/mime.conf里查看对应的type。
示例:gzip_types text/plain application/x-javascript text/css text/html application/xml;
gzip_vary on;
和http头有关系,会在响应头加个 Vary: Accept-Encoding ,可以让前端的缓存服务器缓存经过gzip压缩的页面,例如,用Squid缓存经过Nginx压缩的数据。
gzip_proxied any;
Nginx作为反向代理的时候启用,决定开启或者关闭后端服务器返回的结果是否压缩,匹配的前提是后端服务器必须要返回包含”Via”的 header头。
以下为可用的值:
off
- 关闭所有的代理结果数据的压缩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
- 无条件启用压缩
nginx服务优化
虚拟主机
1、虚拟主机概念
虚拟主机指的是,在web服务里是一个独立的网站站点,这个站点对应独立的域名,也可能是IP或端口,具有独立的程序及资源目录,可以独立地对外提供服务供用户访问。Nginx软件是使用一个server{}
标签来标识一个虚拟主机的。一个web服务里可以有多个虚拟主机标签对,即可同时支持多个虚拟主机站点。
2、虚拟主机类型
常见的虚拟主机类型分三种
- 基于域名的虚拟主机
- 基于端口的虚拟主机
- 基于IP的虚拟主机
基于域名的虚拟主机是通过不同域名区分不同的虚拟主机,是企业应用最广泛的虚拟主机类型。
基于端口的虚拟主机是通过不同端口区分不同的虚拟主机,常用于公司内部的网站,比如不希望用户访问的网站后台等。
基于IP地址的虚拟主机是通过不同IP地址区分不同的虚拟主机,不常用很少见。
3、基于域名的虚拟主机配置
第一、编辑nginx配置文件nginx.conf
,找到http{}
块,在http{}块里面添加server{}
标签,一个server{}代表一个虚拟主机。默认nginx.conf中有一个server{},这里修改一下,并配置两个基于域名的虚拟主机。
配置内容如下:
server { listen 80; server_name www.syushin.com; location / { root html/com; index index.html index.htm; } } server { listen 80; server_name www.syushin.org; location / { root html/org; index index.html index.htm; } }
可以看到基于域名的虚拟是在server_name中定义。
第二、创建域名对应的站点目录及文件。
$ mkdir ../html/com ../html/org $ echo "I am syushin.com" >> ../html/com/index.html $ echo "I am syushin.org" >> ../html/org/index.html
第三、配置域名解析linux下
echo "192.168.30.7 www.syushin.com www.syushin.org" >> /etc/hosts
windows下
找到域名解析文件,通常在C:\Windows\System32\drivers\etc\hosts
添加内容:192.168.30.7 www.syushin.com www.syushin.org
第四、检查nginx语法,重新加载
$ /usr/local/nginx/sbin/nginx -t $ /usr/local/nginx/sbin/nginx -s reload
第五、测试
linux下用curl命令测试
[root@lnmp conf]$ curl www.syushin.com I am syushin.com [root@lnmp conf]$ curl www.syushin.org I am syushin.org
windows下用浏览器访问
这样就可以实现基于域名的虚拟主机了,用户输入不同的域名,访问不同的站点内容。而基于端口的虚拟主机是在server{}标签里的listen处修改监听的端口,比如listen 8080;
或者listen 8090;
基于IP地址也是在listen里修改,格式如下:192.168.30.7:80;
或者192.168.30.8:81
都很简单,就不再实际操作了。
规范优化nginx配置文件
nginx主配置文件是nginx.conf
,可以将主配置文件包含所有虚拟主机的子配置文件统一放入extra目录里。
使用include
参数实现,它可以放在nginx配置文件的任何地方,用法示例如下:
$ include extra/web01.conf
下面是我的使用方案:$ vim nginx.conf
在http{}删除默认的server{}标签,使用include extra/*.conf;
http { include mime.types; default_type application/octet-stream; ...(这里省略) include extra/*.conf; #就是这一行 }
创建虚拟主机配置保存的目录
$ mkdir /usr/local/nginx/conf/extra
进入extra目录,创建虚拟主机配置文件。
$ vim web01.conf # 内容如下 server { listen 80; server_name localhost; index index.html index.htm ; root html; }
这样通过主配置文件加上include包含的配置使得Nginx配置更加简单,清晰,规范。
域名重定向
在一个虚拟主机上有多个域名的时候,可以针对这多个域名做域名重定向。即访问A域名,浏览器会跳转到B域名。
server { listen 80; server_name www.syushin.com blog.syushin.cc; if ($host = 'blog.syushin.cc' ) { rewrite /(.*) http://syushin.com/$1 permanent; } index index.html index.htm index.php; root html/web01; }
虚拟主机配置如上:其中if语句就是域名重定向的配置了。$host变量就是域名,当访问域名是blog.syushin.cc的时候,就将域名跳转到www.syushin.com。
测试:
[root@lnmp ~]$ curl -x127.0.0.1:80 www.syushin.com -I HTTP/1.1 200 OK # 正常访问状态码200 Server: nginx/1.14.2 Date: Sun, 10 Mar 2019 13:00:16 GMT Content-Type: text/html Content-Length: 12 Last-Modified: Sun, 10 Mar 2019 12:38:09 GMT Connection: keep-alive ETag: "5c850531-c" Accept-Ranges: bytes [root@lnmp ~]$ curl -x127.0.0.1:80 blog.syushin.cc -I HTTP/1.1 301 Moved Permanently # 状态码301 Server: nginx/1.14.2 Date: Sun, 10 Mar 2019 13:00:25 GMT Content-Type: text/html Content-Length: 185 Connection: keep-alive Location: http://www.syushin.com/ # 重定向域名
用户认证
nginx访问日志
nginx访问日志就是用户访问网站的记录。可以针对不同格式记录日志。
配置nginx访问日志格式(这里只使用其中一部分):
# 在nginx主配置文件中的http{}块里定义 log_format main '$remote_addr $http_x_forwarded_for [$time_local]' ' $host "$request_uri" $status' ' "$http_referer" "$http_user_agent"';
参数说明:
变量 | 描述 |
---|---|
$remote_addr | 客户端IP(公网IP) |
$http_x_forwarded_for | 代理服务器的IP |
$time_local | 服务器本地时间 |
$host | 访问主机名(域名) |
$request_url | 访问的url地址 |
$status | 状态码 |
$http_referer | referer |
$http_user_agent | user_agent |
虚拟主机配置文件爬配置nginx访问日志保存目录以及使用主配置文件里的日志格式:
server { listen 80; server_name www.syushin.com blog.syushin.cc; if ($host = 'blog.syushin.cc' ) { rewrite /(.*) http://www.syushin.com/$1 permanent; } index index.html index.htm index.php; root html/web01; location ~ \.php$ { include fastcgi_params; fastcgi_pass unix:/tmp/php-fcgi.sock; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME /usr/local/nginx/html$fastcgi_script_name; } access_log /var/log/nginx/syushin_access.log main; # 这一行就是配置访问日志 }
创建日志文件目录
$ mkdir -p /var/log/nginx
检查语法、重新加载
[root@lnmp conf]$ $ /usr/local/nginx/sbin/nginx -t nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful [root@lnmp conf]$ /usr/local/nginx/sbin/nginx -s reload
测试,浏览器访问一次域名和在本地curl一下,查看是否有日志生成。
[root@lnmp nginx]$ curl -x127.0.0.1:80 blog.syushin.cc <html> <head><title>301 Moved Permanently</title></head> <body bgcolor="white"> <center><h1>301 Moved Permanently</h1></center> <hr><center>nginx/1.14.2</center> </body> </html> [root@lnmp nginx]$ cat syushin_access.log 192.168.30.1 - [11/Mar/2019:12:55:01 +0800] www.syushin.com "/" 304 "-" "Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko" 127.0.0.1 - [11/Mar/2019:12:56:32 +0800] blog.syushin.cc "/" 301 "-" "curl/7.29.0"
这样配置访问日志就成功了。
日志切割
生产环境下,访问日志的量是很大的,如果把访问日志都放在一个文件里是会有很大影响的。因此将nginx访问日志进行切割是很有必要的。
如何切割日志?Linux有个日志切割工具logrotate。它的配置文件在/etc/logrotate.conf
查看配置文件
# see "man logrotate" for details # rotate log files weekly weekly # keep 4 weeks worth of backlogs rotate 4 # create new (empty) log files after rotating old ones create # use date as a suffix of the rotated file dateext # uncomment this if you want your log files compressed #compress # RPM packages drop log rotation information into this directory include /etc/logrotate.d # no packages own wtmp and btmp -- we'll rotate them here /var/log/wtmp { monthly create 0664 root utmp minsize 1M rotate 1 } /var/log/btmp { missingok monthly create 0600 root utmp rotate 1 }
其中weekly
表示按周切割;rotate 4
表示一次存储4个归档文件,对于第5个归档文件,时间最久的文档会被覆盖;create
以指定的权限创建全新的日志文件,同时logrotate也会重命名原始日志文件。dataext
表示以日期为格式命令新的日志文件
/var/log/wtmp { monthly create 0664 root utmp minsize 1M rotate 1 }
上面代码块表示针对/var/log/wtmp这个目录下做日志切割,时间为一个月,只对文件大小大于1M文件进行切割。
对于nginx的日志切割
如果是yum安装的nginx,logrotate已经有默认的切割策略了/etc/logrotate.d/nginx
。
而编译安装的nginx就没有,需要手动定义,也可以用这个日志配置
$ cat /etc/logrotate.d/nginx /var/log/nginx/*.log { daily rotate 5 missingok notifempty create 644 www www postrotate if [ -f /application/nginx/logs/nginx.pid ]; then kill -USR1 `cat /application/nginx/logs/nginx.pid` fi endscript }
logrotate工具对于防止因庞大的日志文件而耗尽存储空间是十分有用的。配置完毕后,进程是全自动的,可以长时间在不需要人为干预下运行。除了样例之外,自己还可以定制不同的样式满足需求。
访问日志不记录静态文件
在访问日志里,过滤掉一些图片、js、css等的请求日志。因为这样的日志没有多大意义,而且会占用很大的磁盘空间。
配置,编辑虚拟主机配置文件,添加location:
location ~* \.(png|jpeg|jpg|gif|js|css|bmp)$ { access_log off; }
上面规则表示凡是匹配到以.png|jpeg|jpg|gif|js|css|bmp
结尾的文件,访问日志功能就关闭,即不记录访问静态文件的访问记录。*
号表示不区分大小写,.
号前面需要只用转义字符,|
表示或者。
测试
在虚拟主机站点目录里添加资源文件test.png,然后curl访问一下、再查看日志是否有记录这条访问记录,如果没有则表示配置成功。
清空日志
$ > /var/log/nginx/syushin_access.log
创建以png结尾的文件
$ touch /usr/local/nginx/html/web01/test.png
访问
# 成功访问 [root@lnmp web01]$ curl -x127.0.0.1:80 www.syushin.com/test.png -I HTTP/1.1 200 OK Server: nginx/1.14.2 Date: Mon, 11 Mar 2019 05:19:58 GMT Content-Type: image/png Content-Length: 0 Last-Modified: Mon, 11 Mar 2019 05:16:14 GMT Connection: keep-alive ETag: "5c85ef1e-0" Accept-Ranges: bytes
查看日志
[root@lnmp web01]# cat /var/log/nginx/syushin_access.log [root@lnmp web01]#
无日志记录,说明配置成功。
防盗链
盗链是指服务提供商自己不提供服务的内容,通过技术手段绕过其它有利益的最终用户界面(如广告),直接在自己的网站上向最终用户提供其它服务提供商的服务内容,骗取最终用户的浏览和点击率。受益者不提供资源或提供很少的资源,而真正的服务提供商却得不到任何的收益。
防盗链就是防止上面情况的。常见的盗链是图片盗链,音频盗链,文件盗链。
Referer 防盗链
Referer在HTTP协议里有特殊的用途,当浏览器向服务器发送请求时,一般会带上
Referer头,告知服务器该请求是从哪个页面链接过来的。Referer经常被用于页面访问统计、图片防盗链等。
配置图片防盗链
location ~ \.(png|gif|jpeg|bmp|mp3|mp4|flv)$ { valid_referers none blocked server_name *.syushin.com; if ($invalid_referer){ return 403; } }
valid referers
指的是白名单内的域名可以引用站点图片none
表示空referer,即直接打开站点的图片,而不是从其他网站打开本站点的图片文件,因此对直接访问站点内容的不做限制。blocked
指的是非法链接server_name
就是虚拟主机域名
后面的*.syushin.com
就是白名单域名
这样配置后,当从其他网站引用本站的图片的时候,就引用不了了。
测试:使用curl -e
选项测试,-e
指定referer
$ curl -I -e "http://www.aaa.com/1.txt" http://www.syushin.com/test.png
出现403说明配置成功