概要
上篇说明了nginx的安装,本篇记录一下安装之后第一需要关心的nginx配置文件,外加自己的一些理解。同样阅读时间差不多5分钟。
nginx版本
nginx version: nginx/1.10.3
built by gcc 4.8.3 20140911 (Red Hat 4.8.3-9) (GCC)
built with OpenSSL 1.0.1k-fips 8 Jan 2015
配置文件默认位置
nginx的默认配置文件的位置/etc/nginx/nginx.conf
[root]# cd /etc/nginx/
[root]# ls
conf.d fastcgi.conf fastcgi_params koi-utf mime.types nginx.conf scgi_params uwsgi_params win-utf
default.d fastcgi.conf.default fastcgi_params.default koi-win mime.types.default nginx.conf.default scgi_params.default uwsgi_params.default
注意:修改完配置文件的话,需要重启nginx。可以用nginx -s reload来重启。
第一段配置
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /var/run/nginx.pid;
以上这一段指定了用什么用户启动worker进程(注意用root用户启动nginx的时候,只是启动一个master进程,master进程会再用user nginx来启动worker子进程)。
work_process指定启动多少个worker。
error_log指定nginx的error_log的位置。
pid指定nginx的进程号保存位置。
如果worker数量为1,如下图:
[root]# lsof -nP -i | grep LISTEN| grep 80
nginx 16111 root 6u IPv4 8577034 0t0 TCP *:80 (LISTEN)
nginx 16111 root 7u IPv6 8577035 0t0 TCP *:80 (LISTEN)
nginx 16113 nginx 6u IPv4 8577034 0t0 TCP *:80 (LISTEN)
nginx 16113 nginx 7u IPv6 8577035 0t0 TCP *:80 (LISTEN)
我们可以看到16111是master进程,16113是worker进程,他们的用户分别是root和nginx
如果worker数量为2, 如下图:
[root]# lsof -nP -i | grep LISTEN| grep 80
nginx 16111 root 6u IPv4 8577034 0t0 TCP *:80 (LISTEN)
nginx 16111 root 7u IPv6 8577035 0t0 TCP *:80 (LISTEN)
nginx 16208 nginx 6u IPv4 8577034 0t0 TCP *:80 (LISTEN)
nginx 16208 nginx 7u IPv6 8577035 0t0 TCP *:80 (LISTEN)
nginx 16209 nginx 6u IPv4 8577034 0t0 TCP *:80 (LISTEN)
nginx 16209 nginx 7u IPv6 8577035 0t0 TCP *:80 (LISTEN)
我们发现会有两个worker的进程16208和16209。
第二段配置
# Load dynamic modules. See /usr/share/doc/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;
events {
worker_connections 1024;
}
include可以包含其他模块(这里的include我理解是想包进和http模块平行的其他模块,由于nginx主要我们的用途是http,所以一般不需要其他模块)的conf文件进来,并且/usr/share/nginx/modules/这个目录初始是不存在的。
work_connections是每一个worker的最大并行连接数量,注意该值不能大于ulimit -a的open files的数量。
第三段配置
这一段我们看http模块的配置
http {
# 定义一个变量名为main的log格式
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
# 定义access_log, 并使用main的格式, 这个配置作用于在server区块中没有定义access_log的场合。如果server区块中自行定义了access_log,则此处的配置对于那个server不起效
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
# 单位为秒,设置为0的话,就是disable
keepalive_timeout 65;
# 用来存储一些类型以及MIME的数据的散列表的大小
types_hash_max_size 2048;
# 定义了http的response的mime的类型,应该会存储到types_hash里面去
include /etc/nginx/mime.types;
# 定义http的response的默认MIME type
default_type application/octet-stream;
# Load modular configuration files from the /etc/nginx/conf.d directory.
# See http://nginx.org/en/docs/ngx_core_module.html#include
# for more information.
include /etc/nginx/conf.d/*.conf;
# 默认的index文件
index index.html index.htm;
比较重要的参数我写在了代码的注释上面。
其实说穿了,这些配置是http的全局配置,接下去第四段的server模块的配置(俗称虚拟主机)才是最重要的。很多全局配置都可以在server模块中另外再配置一遍。换一句话说,如果某一个server模块中没有配置access_log,那么不是说这个server模块就不打印access的log了,而是被全局配置的access_log给兜住了。
顺便贴一个官方全参数解释:http://nginx.org/en/docs/http/ngx_http_core_module.html
sendfile,tcp_nopush, tcp_nodelay这三个参数可以参见https://t37.net/nginx-optimization-understanding-sendfile-tcp_nodelay-and-tcp_nopush.html , 其主要功能是和linux内核的sendfile以及tcp的socket的机制相关,用来调优。
第四段配置
这里是重头戏的虚拟主机的配置(server模块)。
它的配置会直接决定了nginx的行为动作的逻辑。比如哪个域名用哪个server的配置,这个server的服务目录,以及是否需要进行反向代理等(如何设置反向代理的内容我放到另外的关于nginx+gunicorn的架构篇去)。
server {
# 监听80端口,并且这个server block被指定为default_server。即过来的请求中的host如果都没有命中任何server的server_name的值的话,就用这个server来处理过来的请求
listen 80 default_server;
# ipv6
listen [::]:80 default_server;
# server_name用来匹配request中的host的值,如果host的值命中这个server_name的话,就用这个server的配置来处理该http请求
server_name localhost;
# 这个虚拟主机的root目录
root /usr/share/nginx/html;
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
# 路由规则,另外细讲
location / {
}
# redirect server error pages to the static page /40x.html
#
error_page 404 /404.html;
location = /404.html {
}
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
我们可以定义多一个server的区域。从而可以让不同的server的区域负责不同端口和不同server_name的请求。比如我的机器的公网ip是aa.aa.aa.aa,我有一个域名bbb.com也解析到这台机器上。那么我就可以定义两个server模块。
# server1
server {
listen 80;
server_name aa.aa.aa.aa;
# 其他略
}
# server2
server {
listen 80;
server_name bbb.com;
# 其他略
}
# server3
server {
listen 80 default_server;
server_name localhost
# 其他略
}
当有一个人用http://aa.aa.aa.aa 来访问我的时候,server1的配置就会起效果, 当有一个人用http://bbb.com 来访问我的时候,server2的配置就会起效果。当用http://localhost (只能在本机)来访问我的时候,server3就会起效果。
当用http://127.0.0.1 (只能在本机)来访问我的时候,虽然没有一个server_name的配置是127.0.0.1,但也不会尴尬,因为server3是default_server, 没有匹配任何server_name的请求只要能到达本机,那么就派server3去处理。
当请求找到了负责自己的server模块后,那么location就会担当起路径的路由功能。location的配置非常的强大和灵活,这里不展开。
就说一下这里用到的。
server_name bbb.com
root /usr/share/nginx/html;
# 匹配所有/开头的path
location / {
}
如果请求的url是http://bbb.com/a/b.html,那么以上的三行配置就决定了服务器的动作逻辑是到本地目录的/usr/share/nginx/html/a/b.html找到这个文件,然后返回给客户端。
error_page 404 /404.html;
location = /404.html {
# 在这里可以定义新的404.html的位置
# 比如
alias /xxx/yyy/zzz/404.html
}
当找不到/usr/share/nginx/html/a/b.html文件的时候,会返回404,那么上面的这段又会起作用。
它指定当发生404的时候,返回/404.html, 而location = 表示只有命中/404.html的时候,走大括号内的逻辑
结语
本篇先写到这里。关于location的详细使用规则,我也实际没有用到太多,所以这里就只提我自己用到的。反向代理的部分我在另外的架构篇再说明。