0%

nginx学习笔记:安装及配置文件

写在前面

nginx是一个高性能的http和反向代理服务器,也是IMAP/POP3/SMTP服务器,由俄国大牛开发,于2004年10月4日发布第一个版本。目前,Nginx与Apache、IIS三分天下,约占全球web服务市场的三成。国内很多大型网站,如百度、京东、新浪、网易、腾讯、淘宝均采用nginx。

nginx的特点:占用内存少、并发能力强、系统稳定、功能集丰富,随着时代的发展,还支持均衡负载、缓存加速、SSL、流媒体(FLV/mp4)服务。

淘宝基于nginx开发了tengine,继承了Nginxx-1.8.1的所有特性,并兼容Nginx的配置,在此基础上,针对大访问量网站的需求,添加了很多高级功能和特性。

从这则笔记开始,详细整理nginx的相关用法。

nginx 安装

nginx既可以使用yum安装,也可以使用源码包安装,两者各有利弊。

yum安装一行命令行就可以搞定,必须在线安装,缺点是安装的版本比较老,且不能够自定义启用或禁用指定的模块。

源码包安装相对复杂,但是可以根据需要下载指定版本,自定义启用或者禁用功能模块。同时,如果安装机器不能上网的话,只能使用源码包进行安装。

yum安装nginx最新稳定版本

注:yum最新的稳定版本是1.14,最便捷的方式是通过yum工具进行安装。

  • 使用epel源进行安装(只能安装nginx1.12)
1
2
3
yum install -y epel-release

yum install -y nginx
  • 使用nginx官方源进行安装
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
vi /etc/yum.repos.d/nginx.repo

//增加以下内容
[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=0
enabled=1

//保存退出后,执行以下命令查看nginx
yum list | grep -i nginx

//为了避免冲突,可以先将epel源更名
mv vi /etc/yum.repos.d/epel.repo /etc/yum.repos.d/epel.repo.bak

//执行以下命令进行安装
yum install -y nginx

安装完成后,执行以下命令启动服务

1
systemctl start nginx

TroubleShooting:如果服务无法启动,检查防火墙设置,是否开启的80端口。

源码包安装

  • 编译安装
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
//下载源码包
wget https://nginx.org/download/nginx-1.14.0.tar.gz

//解压
tar -zxvf nginx-1.14.0.tar.gz

//安装依赖包
yum install -y gcc gcc-c++ pcre pcre-devel zlib zlib-devel openssl openssl-devel

/创建安装目录
mkdir -p /usr/local/nginx

//创建用户
groupadd nginx
useradd -M -s /sbin/nologin -g nginx nginx

//进入源码包
cd nginx-1.14.0

//编译参数
./configure \
--prefix=/usr/local/nginx \
--pid-path=/usr/local/nginx/logs/nginx.pid \
--lock-path=/var/lock/nginx.lock \
--user=nginx \
--group=nginx \
--with-http_ssl_module \
--with-http_flv_module \
--with-http_stub_status_module \
--with-http_gzip_static_module \
--with-pcre

//编译安装
make && make install
  • 设置开机启动
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
//编辑启动脚本
vim /etc/init.d/nginx

//加入以下内容
#!/bin/bash
# chkconfig: - 30 21
# description: http service.
# Source Function Library
. /etc/init.d/functions
# Nginx Settings

NGINX_SBIN="/usr/local/nginx/sbin/nginx"
NGINX_CONF="/usr/local/nginx/conf/nginx.conf"
NGINX_PID="/usr/local/nginx/logs/nginx.pid"
RETVAL=0
prog="Nginx"

start() {
echo -n $"Starting $prog: "
mkdir -p /dev/shm/nginx_temp
daemon $NGINX_SBIN -c $NGINX_CONF
RETVAL=$?
echo
return $RETVAL
}

stop() {
echo -n $"Stopping $prog: "
killproc -p $NGINX_PID $NGINX_SBIN -TERM
rm -rf /dev/shm/nginx_temp
RETVAL=$?
echo
return $RETVAL
}

reload(){
echo -n $"Reloading $prog: "
killproc -p $NGINX_PID $NGINX_SBIN -HUP
RETVAL=$?
echo
return $RETVAL
}

restart(){
stop
start
}

configtest(){
$NGINX_SBIN -c $NGINX_CONF -t
return 0
}

case "$1" in
start)
start
;;
stop)
stop
;;
reload)
reload
;;
restart)
restart
;;
configtest)
configtest
;;
*)
echo $"Usage: $0 {start|stop|reload|restart|configtest}"
RETVAL=1
esac
exit $RETVAL

//更改脚本权限
chmod a+x /etc/init.d/nginx

//启动脚本
chkconfig --add nginx
chkconfig nginx on

nginx常用编译选项说明

编译选项 含义
–prefix=PATH 指定nginx的安装目录,默认 /usr/local/nginx
–conf-path=PATH 设置nginx.conf配置文件的路径。nginx允许使用不同的配置文件启动,通过命令行中的-c选项。默认为prefix/conf/nginx.conf
–sbin-path=PATH 指定nginx二进位制可执行文件的路径,如果不指定,则会依赖于prefix路径。
–user=username 设置nginx工作进程的用户。安装完成后,可以随时在nginx.conf配置文件更改user指令。默认的用户名是nobody。
–with-pcre 设置PCRE库的源码路径,如果已通过yum方式安装,使用–with-pcre自动找到库文件。使用–with-pcre=PATH时,需要从PCRE网站下载pcre库的源码并解压,剩下的就交给Nginx的./configure和make来完成。perl正则表达式使用在location指令和 ngx_http_rewrite_module模块中。
–with-zlib=PATH 指定 zlib的源码解压目录。在默认就启用的网络传输压缩模块ngx_http_gzip_module时需要使用zlib 。
–with-http_ssl_module 使用https协议模块。默认情况下,该模块没有被构建。前提是openssl与openssl-devel已安装
–with-http_stub_status_module 用来监控 Nginx 的当前状态
–with-http_realip_module 通过这个模块允许我们改变客户端请求头中客户端IP地址值(例如X-Real-IP 或 X-Forwarded-For),意义在于能够使得后台服务器记录原始客户端的IP地址
–add-module=PATH 添加第三方外部模块,如nginx-sticky-module-ng或缓存模块。每次添加新的模块都要重新编译(Tengine可以在新加入module时无需重新编译)

nginx 配置文件

根据安装方式的不同,源码包安装的nginx配置目录在/usr/local/nginx/conf;通过yum安装的配置目录在/etc/nginx/conf/

其中,主要包括四个部分:

  • global:全句配置

  • events:网络连接相关

  • http:与http协议相关的部分

  • server:虚拟主机相关的部分,在http当中;

nginx.conf全局配置

  • user nobody;
1
定义运行nginx服务的用户,还可以加上组,如 user nobody nobody;
  • worker_processes 1;
1
2
定义nginx子进程数量,即提供服务的进程数量,该数值建议和服务cpu核数保持一致。
除了可以定义数字外,还可以定义为auto,表示让系统自动调整。
  • error_log logs/error.log;
1
2
3
定义错误日志的路径,可以是相对路径(相对prefix路径的),也可以是绝对路径。

该配置可以在此处定义,也可以定义到http、server、location里
  • error_log logs/error.log notice;
1
2
3
4
5
定义错误日志路径以及日志级别.

常见的错误日志级别有[debug|info|notice|warn|error|crit|alert|emerg],级别越高记录的信息越少。如果不定义默认是error

debug级别只有在编译安装时指定了--with-debug选项,才可以使用。
  • pid logs/nginx.pid;
1
定义nginx进程pid文件所在路径,可以是相对路径,也可以是绝对路径。
  • worker_rlimit_nofile 100000;
1
2
3
定义nginx最多打开文件数限制。如果没设置的话,这个值为操作系统(ulimit -n)的限制保持一致。把这个值设高,nginx就不会有“too many open files”问题了。

该选项对于反向代理服务器尤为重要
  • include文件
1
2
3
include /usr/local/nginx/conf/vhost/*.conf

一般在配置文件的结尾,定义一个文件夹/usr/local/nginx/conf/vhost/ 如果一台机器上存在多个虚拟主机,可以为每个虚拟机设置不同的配置文件,以增加其可读性。

events配置部分

  • worker_connections 1024;
1
定义每个work_process同时开启的最大连接数,即允许最多只能有这么多连接。
  • accept_mutex on;
1
默认为on。当某一个时刻只有一个网络连接请求服务器时,会对多个Nginx进程(worker processer)接收连接时进行序列化,只有一个进程被唤醒即可,防止多个进程争抢资源,节约系统资源。
  • multi_accept on;
1
2
默认为off,即每个worker process一次只能接收一个新到达的网络连接。
当设置为on时,可以同时接收多个新到达的网络连接,在处理高并发任务时非常有用。
  • use epoll;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Nginx服务器提供了多个事件驱动器模型来处理网络消息。支持的类型有:

* select:只能在Windows下使用,这个事件模型不建议在高负载的系统使用

* poll:Nginx默认首选,但不是在所有系统下都可用

* kqueue:这种方式在FreeBSD 4.1+, OpenBSD2.9+, NetBSD 2.0, 和 MacOS X系统中是最高效的

* epoll: 这种方式是在Linux 2.6+内核中最高效的方式(centos首选)

* 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配置部分

文件识别及日志相关

  • MIME-Type
1
2
3
4
5
include       mime.types;  
定义nginx能识别的网络资源媒体类型(如,文本、html、js、css、流媒体等);可以通过cat conf/mime.types进行查看

default_type application/octet-stream;
定义默认的type,如果不定义改行,默认为text/plain.
  • log_format
1
2
3
4
5
log_format main  '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';

其中main为日志格式的名字,后面的为nginx的内部变量组成的一串字符串。
  • access_log logs/access.log main;
1
定义日志的路径以及采用的日志格式,该参数可以在server配置块中定义。

socket相关

  • sendfile on;
1
2
3
是否调用sendfile函数传输文件,默认为off,使用sendfile函数传输,可以减少user mode和kernel mode的切换,从而提升服务器性能。

对于普通应用设为 on,如果用来进行下载等应用磁盘IO重负载应用,可设置为off,以平衡磁盘与网络I/O处理速度,降低系统的负载。
  • sendfile_max_chunk 128k;
1
该参数限定Nginx worker process每次调用sendfile()函数传输数据的最大值,默认值为0,如果设置为0则无限制。
  • tcp_nopush on;
1
当tcp_nopush设置为on时,会调用tcp_cork方法进行数据传输,即:当应用程序产生数据时,内核不会立马封装包,而是当数据量积累到一定量时才会封装,然后传输。这样有助于解决网络堵塞问题。

client buffer

  • keepalive_timeout 65 60;
1
2
3
该参数有两个值,第一个值设置nginx服务器与客户端会话结束后仍旧保持连接的最长时间,单位是秒,默认为75s。

第二个值可以省略,它是针对客户端的浏览器来设置的,可以通过curl -I看到header信息中有一项Keep-Alive: timeout=60。设置后,浏览器就会根据这个数值决定何时主动关闭连接,Nginx服务器就不操心了。但有的浏览器并不认可该参数。
  • send_timeout
1
发送响应的超时时间,即Nginx服务器向客户端发送了数据包,但客户端一直没有去接收这个数据包,超过send_timeout定义的超时时间,那么Nginx将会关闭这个连接。
  • client_max_body_size 10m;
1
2
3
限制发送http包的大小,浏览器在发送含有较大HTTP包体的请求时,其头部会有一个Content-Length字段,client_max_body_size是用来限制Content-Length所示值的大小的。

当客户端上传文件时,Nginx在收完包头后,发现Content-Length超过client_max_body_size定义的值,就直接发送413(Request Entity Too Large)响应给客户端。
  • gzip on; 以下几项都是与网页压缩相关的配置
1
是否开启gzip压缩。
  • gzip_min_length 1k;
1
设置允许压缩的页面最小字节数,页面字节数从header头得content-length中进行获取。默认值是20。建议设置成大于1k的字节数,小于1k可能会越压越大。
  • gzip_buffers 4 16k;
1
设置系统获取几个单位的buffer用于存储gzip的压缩结果数据流。4 16k代表分配4个16k的buffer。
  • gzip_http_version 1.1;
1
2
3
用于识别 http 协议的版本,早期的浏览器不支持 Gzip 压缩,用户会看到乱码,所以为了支持前期版本加上了这个选项。

如果在使用Nginx反向代理的同时启动Gzip压缩,需设置为 1.1。
  • gzip_comp_level 6;
1
gzip压缩比,1压缩比最小处理速度最快,9压缩比最大但处理速度最慢,因此去中间值。
  • gzip_types mime-type … ;
1
2
3
匹配mime类型进行压缩,无论是否指定,”text/html”类型总是会被压缩的。在conf/mime.conf里查看对应的type。

示例:gzip_types text/plain application/x-javascript text/css text/html application/xml;
  • gzip_proxied any;
1
2
3
4
5
6
7
8
9
10
11
12
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 - 无条件启用压缩
  • gzip_vary on;
1
和http头有关系,会在响应头加个 Vary: Accept-Encoding ,可以让前端的缓存服务器缓存经过gzip压缩的页面,例如,用Squid缓存经过Nginx压缩的数据。

proxy buffer 代理模块相关

  • proxy_buffering
1
2
3
4
默认为 on,定义是否开启对后端response的缓冲
```

- proxy_connect_timeout

默认为60秒,指定一个连接到代理服务器的超时时间,单位为秒,需要注意的是这个时间最好不要超过75秒。

1
2

- proxy_read_timeout

默认为60秒,决定读取后端服务器应答的超时时间,单位为秒,它决定nginx将等待多久时间来取得一个请求的应答。超时时间是指两次连续读操作之间的超时时间。某些情况下代理服务器将花很长的时间来获得页面应答(例如如当接收一个需要很多计算的报表时),可以在不同的location里面设置不同的值。

1
2

- proxy_send_timeout

默认为60秒,设置代理服务器转发请求的超时时间,单位为秒,超时时间为两次连续写操作之间的超时时间,如果超过这个时间代理服务器没有数据转发到被代理服务器,nginx将关闭连接

1
2

- proxy_buffer_size

缓存response的第一部分,通常是header,默认proxy_buffer_size 被设置成 proxy_buffers 里一个buffer 的大小,当然可以设置更小些。

1
2

- proxy_buffers

默认proxy_buffers 8 4k或8k;

前面一个是num,后面一个是每个buffer的size.Nginx将会尽可能的读取后端服务器的数据到buffer,直到proxy_buffers设置的所有buffer们被写满或者数据被读取完(EOF),此时Nginx开始向客户端传输数据,会同时传输这一整串buffer们。如果数据很大的话,Nginx会接收并把他们写入到temp_file里去,大小由proxy_max_temp_file_size 控制。

1
2
3


- proxy_max_temp_file_size

默认情况下proxy_max_temp_file_size值为1024MB,也就是说后端服务器的文件不大于1G都可以缓存到nginx代理硬盘中,如果超过1G,那么文件不缓存,而是直接中转发送给客户端.如果proxy_max_temp_file_size设置为0,表示不使用临时缓存。

1
2

- proxy_busy_buffers_size

一旦proxy_buffers设置的buffer被写入,直到buffer里面的数据被完整的传输完(传输到客户端),这个buffer将会一直处 在busy状态,我们不能对这个buffer进行任何别的操作。所有处在busy状态的buffer size加起来不能超过proxy_busy_buffers_size,所以proxy_busy_buffers_size是用来控制同时传输到客户端的buffer数量的。

1
2

- proxy_temp_file_write_size

指定每次写temp file的大小

1
2

- proxy_temp_path

指定缓冲代理服务器response的临时文件夹

1
2
3
4
5
6
7

### server部分配置


server{} 包含在http{}内部,每一个server{}都是一个虚拟主机配置文件(站点)。

以下为nginx.conf配置文件中server{}部分的内容。

    server {
    listen       80;  //监听端口为80,可以自定义其他端口,也可以加上IP地址,如,listen 127.0.0.1:8080;
    server_name  localhost; //定义网站域名,可以写多个,用空格分隔。
    #charset koi8-r; //定义网站的字符集,一般不设置,而是在网页代码中设置。
    #access_log  logs/host.access.log  main; //定义访问日志,可以针对每一个server(即每一个站点)设置它们自己的访问日志。

    ##在server{}里有很多location配置段
    location / {
        root   html;  //定义网站根目录,目录可以是相对路径也可以是绝对路径。
        index  index.html index.htm; //定义站点的默认页。
    }

    #error_page  404              /404.html;  //定义404页面

    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;  //当状态码为500、502、503、504时,则访问50x.html
    location = /50x.html {
        root   html;  //定义50x.html所在路径
    }

    # proxy the PHP scripts to Apache listening on 127.0.0.1:80
    #
    #定义访问php脚本时,将会执行本location{}部分指令
    #location ~ \.php$ {
    #    proxy_pass   http://127.0.0.1;  //proxy_pass后面指定要访问的url链接,用proxy_pass实现代理。
    #}

    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
    #
    #location ~ \.php$ {
    #    root           html;
    #    fastcgi_pass   127.0.0.1:9000;  //定义FastCGI服务器监听端口与地址,支持两种形式,1 IP:Port, 2 unix:/path/to/sockt
    #    fastcgi_index  index.php;
    #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;  //定义SCRIPT_FILENAME变量,后面的路径/scripts为上面的root指定的目录
    #    include        fastcgi_params; //引用prefix/conf/fastcgi_params文件,该文件定义了fastcgi相关的变量
    #}

    # deny access to .htaccess files, if Apache's document root
    # concurs with nginx's one
    # 
    #location ~ /\.ht {   //访问的url中,以/.ht开头的,如,www.example.com/.htaccess,会被拒绝,返回403状态码。
    #    deny  all;  //这里的all指的是所有的请求。
    #}
}


# another virtual host using mix of IP-, name-, and port-based configuration
#
#server {
#    listen       8000;  //监听8000端口
#    listen       somename:8080;  //指定ip:port
#    server_name  somename  alias  another.alias;  //指定多个server_name

#    location / {
#        root   html;
#        index  index.html index.htm;
#    }
#}


# HTTPS server
#
#server {
#    listen       443 ssl;  //监听443端口,即ssl
#    server_name  localhost;

### 以下为ssl相关配置
#    ssl_certificate      cert.pem;    //指定pem文件路径
#    ssl_certificate_key  cert.key;  //指定key文件路径

#    ssl_session_cache    shared:SSL:1m;  //指定session cache大小
#    ssl_session_timeout  5m;  //指定session超时时间
#    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;   //指定ssl协议
#    ssl_ciphers  HIGH:!aNULL:!MD5;  //指定ssl算法
#    ssl_prefer_server_ciphers  on;  //优先采取服务器算法
#    location / {
#        root   html;
#        index  index.html index.htm;
#    }
#}

`

Nginx的工作原理

web请求机制

nginx支持高并发,是一种非常高效的http服务器。要理解他的web请求机制,需要先了解数据通信机制和进程调用的相关内容。

通信机制

可以分为同步、异步两种方式。 同步、异步发生在当客户端发起请求后,服务端处理客户端的请求时。

  • 同步机制,是指客户端发送请求后,需要等待服务端(内核)返回信息后,再继续发送下一个请求。在这种模式中,所有的请求在服务器端得到同步,即发送方和接收方对请求的处理步调是一致的。

  • 异步机制,是指客户端发出一个请求后,不等待服务端(内核)返回信息,就继续发送下一个请求。在异步机制中,所有来自发送方的请求形成一个队列,接收方处理完后再通知发送方。

进程调用

进程调用有两种状态,阻塞与非阻塞,发生在IO调度过程中。

  • 阻塞方式下,进程/线程在获取最终结果之前,被系统挂起了,也就是所谓的阻塞了,在阻塞过程中该进程什么都干不了,直到最终结果反馈给它时,它才恢复运行状态。

  • 非阻塞方式和阻塞相反,进程/线程在获取最终结果之前,并没有进入被挂起的状态,而是继续执行新的任务。当有最终结果时,进程再把结果交给客户端。

Nginx之所以支持高并发,是因为采用了异步非阻塞的机制,依靠事件驱动模型来实现这种机制的。

事件驱动模型中,一个进程(线程)就可以了。

对于web服务器来说,客户端A的请求连接到服务端时,服务端的某个进程(Nginx worker process)会处理该请求,此进程在没有返回给客户端A结果时,它又去处理了客户端B的请求。

服务端把客户端A以及客户端B发来的请求作为事件交给了“事件收集器”,而“事件收集器”再把收集到的事件交由“事件发送器”发送给“事件处理器”进行处理。

最后“事件处理器”处理完该事件后,通知服务端进程,服务端进程再把结果返回给客户端A、客户端B。

在这个过程中,服务端进程做的事情属于用户级别的,而事件处理这部分工作属于内核级别的。也就是说,事件驱动模型是需要操作系统内核来作为支撑的。

Nginx的事件驱动模型,支持select、poll、epoll、rtsig、kqueue、/dev/poll、eventport等。其中,linux平台上最常用的poll和epoll。

nginx组织机构

Nginx服务器使用 master/worker 多进程模式。

主进程(Master process)启动后,会接收和处理外部信号;

主进程启动后通过fork() 函数产生一个或多个子进程(work process),每个子进程会进行进程初始化、模块调用以及对事件的接收和处理等工作。

具体而言,

主进程主要负责:

  • 读取Nginx配置文件并验证其有效性和正确性

  • 建立、绑定和关闭socket

  • 按照配置生成、管理工作进程

  • 接收外界指令,比如重启、关闭、重载服务等指令

  • 日志文件管理

子进程主要负责:

  • 接收客户端请求

  • 将请求依次送入各个功能模块进行过滤处理

  • IO调用,获取响应数据

  • 与后端服务器通信,接收后端服务器处理结果

  • 数据缓存,访问缓存索引,查询和调用缓存数据

  • 发送请求结果,响应客户端请求

  • 接收主进程指令,如重启、重载、退出等

参考文档

-------------本文结束感谢您的阅读-------------
坚持原创技术分享,您的支持将鼓励我继续创作!