深入理解Nginx(一)——安装、命令与配置

Posted by 皮皮潘 on 12-21,2021

本博文主要从安装、常用命令以及配置文件常用配置项三个角度着手,对于Nginx进行生态这篇博文主要从安装、常用命令以及配置文件常用配置项三个角度着手,对于Nginx的使用进行一个入门级的介绍,Nginx本身的架构及源码请看后续的博文。

Nginx安装

最简单的Nginx安装方式,就是通过apt-get或者yum进行install然后基于systemctl相关的命令对于Nginx的生命周期进行控制就行了,

但是由于Nginx自定义模块的特性,在Nginx的生态中产生了大量的第三方模块,如果想要将第三方模块加入Nginx来扩展Nginx的功能,那么就必须要通过编译Nginx源代码的方式来安装Nginx,因此本节主要讲解如何编译Nginx源代码来安装Nginx

编译安装最简单的步骤如下:

wget nginx源码 && cd nginx-XXX-XXX && ./configure && make && make install

其中configure命令进行了环境检测、参数的解析、中间目录的生成以及一些C源代码和Makefile文件的生成,make命令根据configure命令生成的Makefile文件进行编译,并生成目标文件以及最终的二进制文件,make install命令将make生成的最终二进制文件以及相关文件按照在configure命令配置的参数(--prefix)部署到执行的安装目录

可以看出configure命令对于自定义Nginx起到了至关重要的作用,接下来将详细介绍configure命令的关键参数

路径相关的参数

参数名称意义
--prefixnginx安装部署后的根目录,默认:/usr/local/nginx
--conf-path配置文件的放置路径,默认:/conf/nginx.conf
--error-log-patherror日志文件的放置路径,默认:/logs/error.log
--pid-pathpid文件的放置路径,其中存放Nginx master的进程ID,从而在运行一些命令的时候可以转换成信号发送给对应的master进程,默认:/logs.nginx.pid
--lock-pathlock文件的放置路径,该lock文件主要用于进程间的同步,以及解决多个worker进程监听同一个端口引起的“惊群”现象,默认:/logs/nginx.lock
--builddirbuild临时文件放置的目录,默认:/objs
--http-log-pathaccess日志放置的位置,默认:/logs/access.log

模块相关的参数

参数名称意义
--without-xxx-module将默认安装进Nginx的模块从Nginx中去除
--with-xxx-module将默认不安装进Nginx的模块加入到Nginx中
--add-module将自定义的第三方模块加入Nginx,该参数需要执行第三方模块所在的路径,且该路径下需要有对应的configure文件,具体细节会在之后的博文中给出
--user指定worker进程运行时所属的用户,因为master进程需要有管理worker进程生命周期的能力,因此不要将启动worker进程的用户设为root

上述参数仅仅是个人认为比较重要的参数,更加详细的参数可以通过运行./configure --help进行查看

常用命令

在完成了Nginx的安装之后,可以通过/sbin/nginx的二进制文件对于Nginx服务器进行启停以及运维,常用命令如下

nginx // 正常启动Nginx
nginx -c /xxx/nginx.conf // 指定配置文件启动Nginx
nginx -s stop // 强制停止服务 等价于 kill -s SIGTERM <pid>
nginx -s quit // 优雅停止服务也即正常处理完当前所有请求再停止服务 等价于 kill -s SIGQUIT <pid>
nginx -s reload // 重新读取配置文件并生效 等价于 kill - s SIGHUP <pid>
nginx -s reopen // 重新打开日志文件,这样可以先把当前日志文件改名,再重新打开新的日志文件从而完成日志文件分段 等价于 kill -s SIGUSR1
nginx -s SIGUSR2 <pid> // 平滑升级Nginx:首先将旧的二进制文件Nginx替换掉,然后发送SIGUSR2信号给原来的Nginx进程,此时原来的Nginx进程会自动地开启新的Master进程和新的Worker进程,然后关闭所有的旧的Master进程以及旧的Worker进程
nginx -h

常用配置项

在完成了Nginx的安装并熟悉了对应的常用命令之后,就需要通过编写配置文件的方式,去配置Nginx服务器,使它成为:静态资源服务器、反向代理服务器、邮件代理服务器等,其中配置文件其实就是一个普通的文本文件,其中规定了一定的语法格式:

  1. 块配置项:块配置项由一个块配置项名和一对大括号组成,标识大括号内的配置项同时生效
  2. 配置项:最基本的配置项语法格式如下配置项名 配置项值1 配置项值2 ...;,其中配置项值可以是数字、字符串值以及KV对(key=value),每行配置项的结尾需要加上分号
  3. 配置项的单位:
    • 空间单位:k,m
    • 时间单位:ms,s,m,h,d,w,M,y
  4. 变量:许多模块在解析请求时都会提供多个变量,可以通过$XXX的方式使用变量,如在log_format中

其实上述的配置项名又被成为指令或者Command,它们都是由各个模块定义的,同时只有在配置文件中出现对应的配置项名时对应的模块才会在运行时被启用,模块的详细介绍将会在后续的博文中给出

在熟悉了配置文件的语法格式之后,接下来介绍一些常用的配置项

基本配置

语法默认意义
master_process on | offon是否以master/worker方式工作
include /path/file 嵌入其他配置文件(直接将对应的内容写入)
user username [groupname]user nobody nobodyworker进程的用户及用户组
worker_processer number1worker的进程个数,由于Nginx是基于事件驱动的,因此该值一般和CPU核数相同
worker_cpu_affinity cpumask [cpumask...] 绑定进程到指定的CPU内核,cpumask如下表示:0100代表四个核心中的第二个核心
worker_priority nice0Worker进程优先级,如果系统Nginx占有更多的系统资源,那么可以把这个值调得低一点
use [kqueue|epoll|select|poll]Nginx自动选择最合适的事件模型,Linux下是epoll选择事件模型

HTTP配置

http {
    gzip on;
    
    upstream test {
        server test1.com;
        server test2.com;
        ...
    }
    
    upstream test2{
        ...
    }
    
    server {
        listen 80;
        server_name www.test.com;
        location ~*  .(jpg|jped|gif)$ {
            root /opt/picture;
            ...
        }
        location /proxy {
            proxy_pass http://test;
        }
    }
    
    server {
        ...
    }
}

HTTP的配置都在http配置项的块中,大致如上所示

虚拟主机与请求定位

在配置文件,可以按照server_name并通过server块来定义虚拟主机,每个server块就是一个虚拟主机,它只处理相对应的主机域名请求,也即可以让同一个ip+端口,通过不同的域名来访问不同的服务

  1. 监听端口:listen address:port [default | [backlog=num | rcvbuf=size | sndbuf=size]],linsten参数决定了Nginx服务如何监听端口,其中其他参数意义如下:

    1. default:当一个请求无法匹配任意一个主机域名时,就会使用默认的虚拟主机
    2. backlog=num:标识TCP中backlog队列的大小,在TCP建立三次握手过程中,当进程还没有accept对应的socket,这是backlog队列就会防止这些新连接,如果backlog队列已满,则拒绝新的客户端通过三次握手建立连接
    3. rcvbuf=size:设置ServerSocket对应的内核的输入缓冲区
    4. sndbuf=size:设置ServerSocket对应的内核的输出缓冲区
  2. 主机名称:server_name name [name...] ,在开始处理一个HTTP请求时,Nginx会取出header中的Host与每个server中的server_name进行匹配来决定由哪一个server块来处理这个请求

  3. location:location [=|~|~*|^~|@] {uri},location会尝试根据用户请求中的URI来匹配对应的表达式,然后选择location块中的配置来处理用户请求:

    1. = 表示把URI作为字符串来与uri参数做完全匹配
    2. ~ 表示只需要URI前半部分与uri参数匹配即可,同时~也是默认的匹配符
    3. ~ 表示采用正则表达式进行匹配,且对应的字母大小写敏感
    4. ~* 表示采用正则表达式进行匹配,且对应的字母大小写不敏感
    5. @ 表示仅仅用作服务内部请求之间的重定向,不直接面向用户的请求

文件路径

  1. 以root方式设置资源路径:root path,会把用户请求的URI直接拼接到对应的Path上,如:location /download {root /opt/;}此时请求/download/test会得到对应的/opt/download/test文件
  2. 以alias方式设置资源路径:alias path,会location作为别名,然后把location之外的URL拼接上去,如:location /download {alias /opt/download;}此时请求/download/test会得到对应的/opt/download/test文件
  3. 访问首页:index file ...,有时访问站点的URI是/,这时不对应任何一个文件而是对应目录,因此需要返回index定义的文件来作为返回
  4. try_files: try_files path1 [path2...] uri,尝试按照顺序访问每一个path,如果可以有效地读取则返回对应的文件,如果所有path都找不到就重定向到对应的uri参数

MIME类型设置

语法:types ;
定义MIME type到文件扩展名的映射:

types {
    text/html html;
    image/gif gif;
    text/html conf;
}

基于types的定义就可以通过文件扩展名去设置响应中Header的content-type从而让浏览器接收到响应时知道如何处理对应的数据

对客户端请求的限制

  1. 按HTTP方法名以及IP限制用户请求:limit_except method {...},实例如下,限制除了192.168.1.0/32的ip都不允许发起GET请求:
limit_except GET {
    allow 192.168.1.0/32;
    deny all;
}
  1. HTTP请求包体的最大值:client_max_body_size size
  2. 下载限速:limit_rate speed; limit_rate_after size,当响应大小超过size后限速为对应的speed

负载均衡设置

upstream块定义了一个上游服务器的集群,便于反向代理中的proxy_pass使用,在upstream块内部使用server配置项指定集群的节点,除了对应的节点名字(域名、IP地址+端口或UNIX句柄)之外还可以跟下列参数:

  1. weight=number
  2. max_fails=number
  3. fail_timeout=number

反向代理设置

在location块中使用proxy_pass配置项即可实现反向代理,这里需要注意的是URL的截断问题,这里称用户的请求为URL,proxy_pass后面的配置值为url,location后配的配置值为URI:

  1. url只是host:
    • 结尾带/:URL会将与URI匹配之后的部分原样拼接到url后面,这里需要注意URL和URI的匹配会将 / 也带上
    • 结尾不带/:URL会整个加到url后面,相当于仅仅是修改了host
  2. url包含路径:无论结尾带不带/,URL会将与URI匹配之后的部分加到url后面
  3. URI是一个正则表达式:此时url就不能以/结束了,也不能包含路径了,否则配置文件会报错

另外默认情况下反向代理是不会转发请求中的Host头部的,如果需要妆发那么需要加上proxy_set_header Host $host,对应的proxy_set_header指令也可以设置其他转发的Header