服务端相关 / 08 Nginx 配置初步(上)

Nginx 配置初步(上)

本节的目标是了解 Nginx 的基本配置。关于 Nginx 的配置,主要是以下 5 个方面:

  • 初始配置
  • 基本语法
  • http 服务配置
  • tcp/udp
  • 反向代理

每个部分其实有比较多的扩展内容,今天我们会讲解初始配置以及配置文件的基本语法,后续的 http 服务配置、tcp/udp 配置和反向代理配置会在下一节中介绍。

1. 初始配置

在前面搭建好 Nginx 环境后,编译的 Nginx 根路径为 /root/nginx,那么对应的配置文件为 /root/nginx/conf/nginx.conf ,直接用 cat 命令查看这里的配置文件内容(删除掉了原配置文件中的英文注释,并对主要配置项增加中文注释):

    $ cat /root/nginx/conf/nginx.conf

    # 启动的worker进程数
    worker_processes  1;

    # 设置每个worker进程的最大连接数,它决定了Nginx的并发能力
    events {
        worker_connections  1024;
    }

    # http块配置
    http {
        include      mime.types;
        default_type  application/octet-stream;

        # 注释了日志格式的配置,使用默认
        ...

        sendfile        on;

        # 重要参数,是一个请求完成之后还要保持连接多久,不是请求时间多久,
        # 目的是保持长连接,减少创建连接过程给系统带来的性能损耗
        keepalive_timeout  65;

        # server块配置
        server {
            # 监听80端口
            listen       80;
            server_name  localhost;

            # 匹配url /,会在html目录下,访问index.html或index.htm文件
            location / {
                root   html;
                index  index.html index.htm;
            }

            # 指定500 502 503 504出错的错误页面
            error_page   500 502 503 504  /50x.html;
            location = /50x.html {
                root   html;
            }
        }
    }  

案例 1

修改 worker_processes 指令的参数,比如改为 2,再启动 Nginx,观察 Nginx 的进程,相比原来为 1 时的变化?

Nginx 默认会启动一个 Master 进程(也可以无 Master 启动),可以把 Master 可以看做是包工头,主要的工作就是招募工人(生成 Worker 进程)并监督他们干活。worker_processes 指令用于控制 Worker 进程的数目,也就是所谓的工人数。我们用ps可以看到,当 worker_processes 指令参数为 2 时,worker 进程会变成 2 个。通常情况下,我们会把 worker 进程数会设置成系统的 cpu 核数(这里要看大家的机器配置而定)这样 worker 进程会分配到各个 cpu 核心上去执行请求处理,真正做到并行处理。
图片描述

案例 2

我们请求在页面上请求 80 端口,会出现 Nginx 的默认页面,也就是 html 目录下的那个 index.html 页面;另外直接访问http://localhost/50x.html 时候,会出现针对状态码为 50x 异常页面。接下来,我们添加一个简单的请求访问接口,模拟 500 异常,然后会将请求重定向到这个异常页面。

在上述默认配置的 server 块中,我们添加一个新的匹配路径,如下:

location /internal_error {
    return 500;
}

return 指令一般用于对请求的客户端直接返回响应状态码。在该作用域内 return 指令之后的所有 Nginx 配置都是无效的。

可以使用在 server、location 以及 if 配置中。 除了支持跟状态码,还可以跟字符串或者 url 链接,比如写成这样的形式:

return 200 ‘hello, world’

这样,使用 -s reload 热加载 Nginx 后,我们直接在浏览器中敲 http://ip/internal_error, 就可以看到50x的异常页面了。
图片描述

2. 基本语法

接下来,我将会介绍 Nginx 配置文件的通用语法,想深入学习一些指令的用法,可以多多上官网进行查阅。

2.1 配置文件有指令和指令块构成

例如前面的默认 Nginx.conf 示例中,下面一行就是一个指令:

worker_processes  1;

而使用花括号包围起来的就是一个指令块,比如 http 指令块:

http {
    # 继续指令或者指令块,如http指令块可以包括server指令块
    ...
}

对于具体指令的参数、含义以及指令可以放入的指令块等信息都可以在官方查到;

2.2 每个指令块以分号(;)结尾

这个在默认的 Nginx.conf 中都有体现,如果是没有分号结尾启动 Nginx 或者执行 -t 检查时会报错;

2.3 include 语句允许组合多个配置文件以提升可维护性

这个比较常用,因为在大型网站中使用 Nginx 监听的端口比较多,同时也会存在各种复杂的请求处理,如果都写在同一个 Nginx.conf中,会使得 Nginx 的配置文件变得异常复杂,难以维护。

此时,比较好的方法是使用 include,对配置文件进行按功能,或者按端口等任意的方式进行划分,将对应的处理指令写到另一个文件中,而主配置文件只要使用 include 指令包含该文件或者该文件所在的目录即可,比如如下的写法也是可以的:

include /etc/nginx/conf.d/*.conf;

2.4 使用 # 符号添加注释

使用 # 符号给配置文件添加注释可以提高配置文件的可读性, 这个和代码添加注释是一个道理。

2.5 使用 $ 符号使用变量

Nginx 有内置变量和自定义变量两种。内置变量往往代表着客户端请求头的内容,如 $http_user_agent , ​ $http_cookie 等。Nginx 支持的常用内置变量有:

变量名 内容
$arg_name 请求中的参数名,比如请求http://localhost?a=x&b=y, 则 $arg_a 表示的就是字符串’x’
$args 请求中的参数值
$binary_remote_addr 客户端地址的二进制形式, 固定长度为4个字节
$body_bytes_sent 传输给客户端的字节数,响应头不计算在内
$bytes_sent 传输给客户端的字节数
$content_length “Content-Length” 请求头字段
$remote_addr 客户端地址
$remote_user 用于 HTTP 基础认证服务的用户名
$request_body 客户端的请求主体
$request_length 请求的长度 (包括请求的地址, http请求头和请求主体)
$request_method HTTP 请求方法
$request_time 处理客户端请求使用的时间,从读取客户端的第一个字节开始计时
$request_uri 这个变量等于包含一些客户端请求参数的原始 URI ,它不包含主机名
$server_addr 服务器端地址, 注意:为了避免访问 linux 系统内核,应将ip地址提前设置在配置文件中
$status HTTP 响应代码
$time_local 服务器时间
$uri 请求中的当前 URI, 不带请求参数,且不包含主机名

2.6 案例:体验 Nginx 的 include 指令和内置变量

我们准备三个配置文件,分别为主配置文件 Nginx.conf 和次配置文件 8080.conf、8088.conf,在 Nginx 根目录下的 conf 目录中,新建 conf.d 目录,然后将 8080.conf、8088.conf 两个文件放到此处。通过cat命令查看三个配置文件内容,如下:
图片描述

$ cat 8080.conf

server {
	listen       8080;
	server_name   localhost;
	
	location / {
		default_type text/html;
		return 200 'hello, 8080\n';
	}
}

$ cat 8088.conf

server {
    listen       8088;
    server_name   localhost;

    location / {
        default_type text/html;
        return 200 'hello, 8088\n';
    }
}

$ cat nginx.conf

 ...
http: {
    ...
        server: {
        ...
            # 前面的不变化,但是我们需要变化两个地方
            location / {
            default_type text/html;
            # 自定义变量
            set $limit_rate 10k;
            return 200  '
                arg_a: $arg_a, arg_b: $arg_b, args: $args
                connection: $connection, connection_requests: $connection_requests
                cookie_a: $cookie_a
                uri: $uri, document_uri: $document_uri, request_uri: $request_uri
                request: $request , request_id: $request_id
                server: $server_addr, $server_name, http_host: $http_host,
                limit_rate: $limit_rate, hostname: $hostname,
                content_length: $content_length
                status: $status, body_bytes_sent: $body_bytes_sent, bytes_sent: $bytes_sent
                time: $request_time, $msec, $time_iso8601, $time_local\n';
        }
    }
    ...

        # 包含其他配置文件,包括了8080.conf和8088.conf
        include conf.d/*.conf;
}

准备好这三个三个配置文件后,直接启动 Nginx,可以发现 Nginx 服务分别监听了 80、8080 和 8088 端口。这说明 include 指令生效了,8080.conf、8088.conf 配置被包含进来了。

当然我们也可以去掉这个 include 指令再看看 Nginx 会不会监听 8080 和 8088 端口,来个终极确认。最后我们在服务器上使用 curl 命令来模拟 Http 请求访问服务器的 8080 和 8088 端口,看是否会有对应的相应文本输出。最后请求 80 端口,带上相应的参数,具体操作以及打印结果如下:

[root@server ~]# cd /root/nginx/sbin
# 如果Nginx服务已经启动,使用 -s reload 重新加载配置,否则直接使用 ./nginx 启动Nginx服务 
[root@server sbin]# ./nginx -s reload
[root@server sbin]# curl http://localhost:8080
hello, 8080
[root@server sbin]# curl http://localhost:8088
hello, 8088
# 一定要使用双引号包含整个URL,不然后面的b参数会被漏掉
[root@server sbin]# curl "http://localhost:80?a=xxxx&b=yyyy"

    arg_a: xxxx, arg_b: yyyy, args: a=xxxx&b=yyyy 
    connection: 27, connection_requests: 1 
    cookie_a:   
    uri: /, document_uri: /, request_uri: /?a=xxxx&b=yyyy 
    request: GET /?a=xxxx&b=yyyy HTTP/1.1 , request_id: 3784dd519727856c17b38e2ec9f2c8a1 
    server: 127.0.0.1, , http_host: localhost, 
    limit_rate: 10240, hostname: server, 
    content_length:  
    status: 200, body_bytes_sent: 0, bytes_sent: 0 
    time: 0.000, 1581417768.174, 2020-02-11T18:42:48+08:00, 11/Feb/2020:18:42:48 +0800

3. 小结

今天我们简单了解了下 Nginx 的配置文件以及相应的语法规则。但是我们仅仅简单介绍了 Nginx 一些简单的语法并完成了几个简单的案例,接下来我们将简单学习 Nginx 的 Http 配置以及反向代理等常用配置。