<h2><center>Nginx基础</center></h2>

------

## 一：简介

Nginx的官方网站：www.nginx.org

### 1. 介绍

​	nginx（engine x）是一个高性能的开源的HTTP和反向代理web服务，同时提供IMAP/POP3/SMTP服务。

​	nginx是一款轻量级的Web服务器/反向代理服务器及电子邮件（IMAP/POP3）代理服务器。在BSD-like协议下发行。其特点是占有内存少，并发能力强，事实上nginx的并发能力在同类型的网页服务器中表现较好。

​	nginx处理高并发能力是十分强大的，能经受高负载，支持高达50,000个并发连接数。

​	nginx支持热部署，启动简单。

​	nginx的功能：web服务器、代理服务器、负载均衡器。

​	nginx有模块化组成，支持异步，非阻塞。

### 2. 异步，非阻塞

​	每进来一个request，会有一个worker进程去处理。但不是全程的处理，处理到什么程度呢？处理到可能发生阻塞的地方，比如向上游（后端）服务器转发request，并等待请求返回。那么，这个处理的worker不会这么一直等着，他会在发送完请求后，注册一个事件：“如果upstream返回了，告诉我一声，我再接着干”。于是他就休息去了。这就是异步。此时，如果再有request 进来，他就可以很快再按这种方式处理。这就是非阻塞和IO多路复用。而一旦上游服务器返回了，就会触发这个事件，worker才会来接手，这个request才会接着往下走。这就是异步回调。

案例：

​	客户（发送方）向收款员（接收方）付款（发送请求）后在等待收款员找零的过程中，还可以做其他事情，比如打电话、聊天等；而收款员在等待收款机处理交易（IO操作）的过程中还可以帮助客户将商品打包，当收款机产生结果后，收款员给客户结账（响应请求）。在四种方式中，这种方式是发送方和接收方通信效率最高的一种。



#### 同步异步

​	同步与异步的重点在消息统治的方式上，也就是调用结果通知的方式。

​	同步：当一个同步调用发出去后，调用者要一直等待调用结果的通知后，才能进行后续的执行。

​	异步：当一个异步调用发出去后，调用者不能立即得到调用结果的返回。

​	异步调用要想获得结果，一般有两种方式：

- 主动轮询异步调用的结果。
- 被调用方通过callback来通知调用方调用结果。

案例：

​	同步取快递：小明收到快递将送达的短信，在楼下一直等到快递送达。

​	异步取快递：小明收到快递将送达的短信，快递到楼下后，小明在下楼去取。

​	异步取快递，小明知道快递到达楼下有两种方式：

- 不停的电话问快递小哥到了没有，即主动轮询
- 快递小哥到楼下后，打电话通知小明，然后小明下楼取快递，即回调通知。



#### 阻塞非阻塞

​	阻塞与非阻塞在于进/线程等待消息时候的行为，也就是在等待消息的时候，当前进/线程是挂起还是非挂起状态。

​	阻塞：阻塞调用在发出去后，在消息返回之前，当前进/线程会被挂起，直到有消息返回，当前进/线程才会被激活。

​	非阻塞：非阻塞调用在发出去后，不会阻塞当前进/线程，而会立即返回。

案例：

​	阻塞取快递：小明收到快递即将送达的信息后，什么事都不做，一直专门等快递。

​	非阻塞取快递：小明收到快递即将送达的信息后，等快递的时候，还一边敲代码、一边刷微信。



**同步与异步，重点在于消息通知的方式；阻塞与非阻塞，重点在于等消息时候的行为。**

所以，就有了下面4种组合方式：

- 同步阻塞：小明收到信息后，啥都不干，等快递；
- 同步非阻塞：小明收到信息后，边刷微博，边等着取快递；
- 异步阻塞：小明收到信息后，啥都不干，一直等着快递员通知他取快递；
- 异步非阻塞：小明收到信息后，边刷着微博，边等快递员通知他取快递。



#### I/O多路复用





### 3. 内部结构

​	nginx启功是，会产生两种类型的进程，一个是主程序（Master），一个或多个工作进程（Worker）。主进程并不处理网络请求，主要负责调度工作进程，也就是：加载配置、启动工作进程及非停升级。所以，nginx启动以后，查看操作系统的进程列表，我们就能看到至少有两个nginx进程。

```bash
# ps -aux | grep nginx
root       3021  0.0  0.0  49076  1092 ?        Ss   09:55   0:00 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
nginx      3022  0.0  0.1  51556  2112 ?        S    09:55   0:00 nginx: worker process
nginx      3023  0.0  0.1  51556  2128 ?        S    09:55   0:00 nginx: worker process
nginx      3024  0.0  0.1  51556  2356 ?        S    09:55   0:00 nginx: worker process
nginx      3025  0.0  0.1  51556  2100 ?        S    09:55   0:00 nginx: worker process
```

​	服务器实际处理网络请求及响应的是工作进程（worker），在类UNIX系统上，nginx可以配置多个worker，而每一个worker进程都可以同时处理数以千计的网络请求。

​	模块化设计。nginx的worker，包括核心和功能性模块，核心模块负责维持一个运行循环（run-loop），执行网络请求处理的不同阶段的模块功能，如网络重写、存储读写、内容传输、外出过滤，以及将请求发往上游服务器等。而其代码的模块化设计，也使得我们可以根据需要对功能模块进行适当的选择和修改，编译成具有特定功能的服务器。

​	事件驱动、异步及非阻塞，可以说是nginx得以获得高并发、高性能的关键因素，同时也得益于对Linux、Solaris及类BSD等操作系统内核中事件通知及I/O性能增强功能的采用，如kqueue、epoll及event ports。

​	代理（proxy）设计，可以说是nginx深入骨髓的设计，无论是对于HTTP，还是对于FastCGI、memcache、Redis等的网络请求或响应，本质上都采用了代理机制。所以，nginx天生就是高性能的代理服务器。



## 二：文件详解

### 1. nginx编译参数

```shell
--prefix=/etc/nginx                           //指向安装目录
--sbin-path=/usr/sbin/nginx                   
--modules-path=/usr/lib64/nginx/modules       
--conf-path=/etc/nginx/nginx.conf             //指定配置文件
--error-log-path=/var/log/nginx/error.log     //指定错误日志
--http-log-path=/var/log/nginx/access.log     //指定访问日志
--pid-path=/var/run/nginx.pid                 //指定pid文件
--lock-path=/var/run/nginx.lock               //指定lock文件
--http-client-body-temp-path=/var/cache/nginx/client_temp     //设定http客户端请求临时文件路径
--http-proxy-temp-path=/var/cache/nginx/proxy_temp            //设定http代理临时文件路径
--http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp        //设定http fastcgi临时文件路径
--http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp            //设定http uwsgi临时文件路径
--http-scgi-temp-path=/var/cache/nginx/scgi_temp              //设定http scgi临时文件路径
--user=nginx 
--group=nginx 
--with-compat 
--with-file-aio 
--with-threads 
--with-debug                              //启用debug日志
--with-pcre-jit                           //编译PCRE包含“just-in-time compilation”
--with-ipv6                               //启用ipv6支持
--with-http_addition_module               //作为一个输出过滤器，支持不完全缓冲，分部分响应请求
--with-http_auth_request_module           //实现基于一个子请求的结果的客户端授权。如果该子请求返回的2xx响应代码，所述接入是允许的。如果它返回401或403中，访问被拒绝与相应的错误代码。由子请求返回的任何其他响应代码被认为是一个错误。
--with-http_dav_module                    //增加PUT,DELETE,MKCOL：创建集合,COPY和MOVE方法 默认关闭，需编译开启
--with-http_flv_module 
--with-http_geoip_module                  //使用预编译的MaxMind数据库解析客户端IP地址，得到变量值
--with-http_gunzip_module                 //它为不支持“gzip”编码方法的客户端解压具有“Content-Encoding: gzip”头的响应。
--with-http_gzip_static_module            //在线实时压缩输出数据流
--with-http_image_filter_module           //传输JPEG/GIF/PNG 图片的一个过滤器）（默认为不启用。gd库要用到）
--with-http_mp4_module 
--with-http_random_index_module 
--with-http_realip_module                 //允许从请求标头更改客户端的IP地址值，默认为关
--with-http_secure_link_module 
--with-http_slice_module 
--with-http_ssl_module                    //启用ssl支持
--with-http_stub_status_module            //获取nginx自上次启动以来的状态
--with-http_spdy_module                   //SPDY可以缩短网页的加载时间
--with-http_sub_module                    //允许用一些其他文本替换nginx响应中的一些文本
--with-http_v2_module 
--with-http_xslt_module                   //过滤转换XML请求
--with-mail                               //启用POP3/IMAP4/SMTP代理模块支持
--with-mail_ssl_module                    //启用ngx_mail_ssl_module支持启用外部模块支持
--with-stream 
--with-stream_realip_module 
--with-stream_ssl_module 
--with-stream_ssl_preread_module 
--with-cc-opt='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -fPIC' 
--with-ld-opt='-Wl,-z,relro -Wl,-z,now -pie'
```

### 2. Nginx配置文件详解

​	nginx.conf的组成:nginx.conf一共由三部分组成，分别为：全局块、events块、http块。

​	在http块中又包含http全局块、多个server块。

​	每个server块中又包含server全局块以及多个location块。

```shell
# 全局参数设置
user  nginx;
worker_processes  auto;  #设置nginx启动进程的数量，一般设置成与逻辑cpu数量相同 
注意：
1.物理cpu数：主板上实际插入的cpu数量，可以数不重复的 physical id 有几个（physical id）
2.cpu核数：单块CPU上面能处理数据的芯片组的数量，如双核、四核等 （cpu cores）
3.逻辑cpu数：一般情况下，逻辑cpu=物理CPU个数×每颗核数

error_log  /var/log/nginx/error.log notice;   #指定错误日志 
pid        /var/run/nginx.pid;   


events {
    worker_connections  1024;                  #设置一个进程的最大并发连接数 
}


http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;     #如果MIME文件未定义，浏览器默认下载。

    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  /var/log/nginx/access.log  main;   #设置访问日志的位置和格式 

    sendfile        on;       #是否调用sendfile函数输出文件，一般设置为on，若nginx是用来进行磁盘IO负载应用时，可以设置为off，降低系统负载 
    #tcp_nopush     on;       # 合并数据包减少网络调用

    keepalive_timeout  65;    #设置长连接的超时时间

    #gzip  on;                #是否开启gzip压缩，将注释去掉开启

    include /etc/nginx/conf.d/*.conf;  #加载子配置文件
}
```



## 三：Nginx虚拟主机

### 1. 什么是虚拟主机

​	虚拟主机是一种特殊的软硬件技术，它可以将网络上的每一台计算机分成多个虚拟主机，每个虚拟主机可以独立对外提供www服务，这样就可以实现一台主机对外提供多个web服务，每个虚拟主机之间是独立的，互不影响。

![](http://182.92.143.66:40072/directlink/img/nginx/image-202502220001.png)

### 2. 虚拟主机类型

- 基于域名的虚拟主机
- 基于IP的虚拟主机
- 基于端口的虚拟主机

### 3. 基于域名的虚拟主机

创建虚拟主机配置文件：

```bash
[root@test ~]# vim /etc/nginx/conf.d/test.conf
server {
	listen 80;
	server_name www.wxin.com;
	location / {
		root /usr/share/nginx/web1;
		index index.html index.htm;
	}
}

server {
	listen 80;
	server_name www.wxin1.com;
	location / {
		root /usr/share/nginx/web2;
		index index.html index.htm;
	}
}
```

创建网站发布目录（在/usr/share/nginx/下），并创建对应的网站：

```bash
[root@test ~]# mkdir /usr/share/nginx/web1
[root@test ~]# mkdir /usr/share/nginx/web2
[root@test ~]# echo "web1" > /usr/share/nginx/web1/index.html
[root@test ~]# echo "web2" > /usr/share/nginx/web2/index.html
```

重新加载配置文件：

```bash
[root@test ~]# nginx -s reload
```

客户端配置路由映射（本地域名解析）：

```bash
[root@test ~]# vim /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.159.130  www.wxin.com
192.168.159.130  www.wxin1.com
```

测试访问：

```bash
[root@test ~]# curl www.wxin.com
web1
[root@test ~]# curl www.wxin1.com
web2
```



### 4. 基于IP的虚拟主机

添加IP地址：

```bash
[root@test ~]# ifconfig ens33:1 192.168.159.131/24
[root@test ~]# ifconfig
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.159.130  netmask 255.255.255.0  broadcast 192.168.159.255
        inet6 fe80::9e8b:2599:99f6:4087  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:0a:e2:2b  txqueuelen 1000  (Ethernet)
        RX packets 546698  bytes 785195981 (748.8 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 159219  bytes 9799907 (9.3 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

ens33:1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.159.131  netmask 255.255.255.0  broadcast 192.168.159.255
        ether 00:0c:29:0a:e2:2b  txqueuelen 1000  (Ethernet)

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 148  bytes 13994 (13.6 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 148  bytes 13994 (13.6 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
```

配置通过IP区分的虚拟机：

```bash
[root@test ~]# vim /etc/nginx/conf.d/test.conf
server {
    listen 192.168.159.130:80;
    server_name www.wxin.com;
    location / {
        root /usr/share/nginx/web1;
        index index.html index.html;
    }
}

server {
    listen 192.168.159.131:80;
    server_name www.wxin1.com;
    location / {
        root /usr/share/nginx/web2;
        index index.html index.html;
    }
}
```

重新加载配置文件：

```bash
[root@test ~]# nginx -s reload
```

创建网站：同上

测试访问：

```bash
[root@test ~]# curl http://192.168.159.130
web1
[root@test ~]# curl http://192.168.159.131
web2
```



### 5. 基于端口的虚拟主机

创建虚拟主机配置文件：

```bash
[root@test ~]# vim /etc/nginx/conf.d/test.conf
server {
    listen 80;
    server_name www.wxin.com;
    location / {
        root /usr/share/nginx/web1;
        index index.html index.html;
    }
}

server {
    listen 8080;
    server_name www.wxin.com;
    location / {
        root /usr/share/nginx/web2;
        index index.html index.html;
    }
}
```

创建网站：同上

重新加载配置文件：

```bash
[root@test ~]# nginx -s reload
```

测试访问：

```bash
[root@test ~]# curl www.wxin.com
web1
[root@test ~]# curl www.wxin.com:8080
web2
```

