软件介绍
与 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 说明配置成功
访问控制
负载均衡