---
url: /diary/nginx/index.md
description: Nginx 入门到精通学习笔记，包括基本概念、配置语法、反向代理、负载均衡、动静分离等核心功能详解。
---
## nginx基本概念

*Nginx* (engine x) 是一个高性能的[HTTP](https://baike.baidu.com/item/HTTP)
和[反向代理](https://baike.baidu.com/item/反向代理/7793488)
web服务器，同时也提供了IMAP/POP3/SMTP[服务](https://baike.baidu.com/item/服务/100571)
。Nginx是由伊戈尔·赛索耶夫为[俄罗斯](https://baike.baidu.com/item/俄罗斯/125568)
访问量第二的Rambler.ru站点（俄文：Рамблер）开发的，第一个公开版本0.1.0发布于2004年10月4日。

其特点是占有内存少，[并发](https://baike.baidu.com/item/并发/11024806)能力强，有报告表明能支持高达 50,000 个并发连接数。

### 正向代理

如果把局域网外的internet想象成一个巨大的资源库，则局域网中的客户端要访问internet，则需要通过代离服务器来访问，这种代理服务就称为正向代理。

图解：

```
userA➡➡➡➡➡➡➡❌➡➡➡➡➡➡➡google.com

⬇		                     ⬆						

➡➡➡➡代理服务器(www.abc.com)➡➡➡➡⬆
```

在客户端（浏览器）配置代理服务器，通过代理服务器进行互联网访问。

### 反向代理

反向代理，其实客户端对代理是无感知的，因为客户端不需要任何配置就可以访问，我们只需要将请求发送到反向代理服务器，由反向代理服务器去选择目标服务器获取数据后，再返回给客户端，此时反向代理服务器和目标服务器对外就是一个服务器，暴露的是代理服务器的地址，隐藏了真实服务器的ip地址。

图解:

```
                        ↗	192.168.10.1:80

userB➡➡反向代理服务器➡➡➡➡192.168.10.1:81

       chaospring.com）	↘    192.168.10.1:82
```

### 负载均衡

单个服务器解决不了，增加服务器的数量，然后将请求分发到各个服务器上，将原先请求集中到单个服务器上的情况改为将请求分发到多个服务器上，将负载分发到不同的服务器，也就是我们所说的负载均衡。

#### 旧模式

```
      请求		 请求
客户端➡➡➡➡➡➡服务端➡➡➡➡➡➡数据库
⬆	  响应  ⬇ ⬆  响应	 ⬇
⬅⬅⬅⬅⬅⬅⬅   ⬅⬅⬅⬅⬅⬅⬅
```

并发大时，会出现性能瓶颈。

解决方法：提升硬件配置。

#### 负载均衡

```
                    ↗	   8001服务器
客户端➡➡反向代理服务器➡➡➡➡➡➡➡➡8002服务器
           9001	    ↘	   8003服务器
```

将请求平均分担到3台服务器，就叫负载均衡。

### 动静分离

为了加快网站的解析速度，可以把动态页面和静态页面由不同的服务器来解析，加快解析速度，降低原来单个服务器的压力。

图解：

```
客户端➡➡反向代理服务器➡➡➡➡➡➡➡➡➡➡8002服务器（动态资源）
        9001			↘    8003服务器（静态资源）
```

动态资源：如jsp servlet

静态资源：如css js img

## nginx安装和常用命令

### linux中安装

1.使用远程连接工具连接linux系统

2.进入官网http://nginx.org/en/download.html，下载

3.安装nginx相关依赖

* 开启yum：

  ```shell
  yum -y install gcc zlib zlib-devel pcre-devel openssl openssl-devel
  ```

* 下载并解压安装包

  ```shell
  //创建一个文件夹
  cd /usr/local
  mkdir nginx
  cd nginx
  //下载tar包
  wget https://nginx.org/download/nginx-1.18.0.tar.gz
  tar -xvf nginx-1.18.0.tar.gz
  ```

* 安装nginx

  ```shell
  //进入nginx目录
  cd /usr/local/nginx
  //进入目录
  cd nginx-1.18.0
  //执行命令
  ./configure
  //执行make命令
  make
  //执行make install命令
  make install
  ```

* 配置nginx.conf

  ```shell
  # 打开配置文件
  vi /usr/local/nginx/conf/nginx.conf
  ```

* 启动

  ```shell
  cd /usr/local/nginx/sbin
  ./config
  ```

### 常用命令

使用nginx操作命令前提条件：必须进入nginx的目录

```shell
cd /usr/local/nginx/sbin
```

1.查看nginx版本号

```shell
./nginx -v
nginx version: nginx/1.18.0
```

2.启动nginx

```shell
./nginx
```

3.关闭nginx

```shell
./nginx -s stop
```

4.重新加载nginx

> 修改/usr/local/nginx/conf/nginx.conf配置文件后 要重加载

```shell
./nginx -s reload
```

## nginx配置文件

> 配置文件
>
> /usr/local/nginx/conf/nginx.conf

配置文件由三部分组成：

### 全局块

从配置文件开始到 events 块之间的内容，主要会设置一些影响nginx 服务器整体运行的配置指令，主要包括配置运行 Nginx
服务器的用户（组），允许生成的 worke process 数，进程 PID 存放路径，日志存放路劲和类型以及配置文件的引入等。

```nginx
#user  nobody;
worker_processes  1;  #worker_processes 值越大，可以支持的并发处理量也越多
# 这是nginx 服务器并发处理服务的关键配置，worker_processes 值越大，可以支持的并发处理量也越多，但是会收到硬件、软件等设备的制约。
#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;
#pid        logs/nginx.pid;
```

### events块

events 块涉及的指令主要影响 Nginx 服务器与用户的网络连接，常用的设置包括是否开启对多 worker\_processes
下的网络连接进行序列化，是否允许同时接受多个网络连接，选取哪种事件驱动模型来处理连接请求，每个 worker\_processes
可以同时支持的最大连接数等。

比如：

```nginx
events {
    worker_connections  1024;
}
```

表示每个 worker\_processes 支持的最大连接数为 1024。

这部分的配置对Nginx的性能影响较大，在实际中应该灵活配置。

### http块

这是 Nginx 服务器配置中最频繁的部分，代理、缓存和日志定义等绝大多数功能和第三方模块的配置都在这里。

> http块也可以包括 http 全局块、server块。

#### http 全局块

http全局块配置的指令包括文件引入，MINME-TYPE 定义、日志自定义、连接超时时间、单链接请求数上限等。

```nginx
include       mime.types;
default_type  application/octet-stream;

#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  logs/access.log  main;

sendfile        on;
#tcp_nopush     on;

#keepalive_timeout  0;
keepalive_timeout  65;

#gzip  on;
```

### server块

这块和虚拟主机有密切关系，虚拟主机从用户角度看，和一台独立的硬件主机是完全一样的，该技术的产生是为了节省互联网服务器硬件成本。

每个 http块 可以包括多个 server块 ，而每个 server块 就相当于一个虚拟主机。

而每个 server块 也分为全局 server块 ，以及可以同时包含多个 location块。

```nginx
server {
	listen       70; #代理服务器的端口
	server_name  localhost;  #代理服务器的ip地址
	location / {
		root   html;
		index  index.html index.htm;
	}
	error_page   500 502 503 504  /50x.html;
	location = /50x.html {
		root   html;
	}
}
```

## nginx配置实例--反向代理

1. 准备工作

   一个8080为端口的tomcat服务器。

   > centos7查看已对外开放的端口：

   ```shell
    firewall-cmd --list-all
   ```

   对外开放访问端口命令

   ```shell
   firewall-cmd --add-port=8080/tcp --permanent
   firewall-cmd --reload
   ```

2. 配置反向代理

   * 实例一

     在nginx进行请求转发的配置

     ```shell
     vi /usr/local/nginx/conf/nginx.conf
     ```

     在 server块 里修改：

     ```nginx
     server{  
         listen       80;
         server_name  nginx.chaospring.com;

         #charset koi8-r;

         #access_log  logs/host.access.log  main;

         location / {
        
             root   html;
        
             proxy_pass http://127.0.0.1:8080;
        
             index  index.html index.ht
         }
     }
     ```

   * 实例二

     * 实现效果

       1. 使用 nginx 反向代理，根据访问的路径跳转到不同端口的服务中 nginx 监听端口为 9001。
       2. 访问 http://192.168.17.129:9001/edu/ 直接跳转到 127.0.0.1:8080
       3. 访问 http:// 192.168.17.129:9001/vod/ 直接跳转到 127.0.0.1:8081

     * 准备工作

       1. 准备两个 tomcat 服务器，一个 8080 端口，一个 8081 端口
       2. 创建文件夹和测试页面

     * 具体配置

       1. 找到 nginx 配置文件，进行反向代理配置

          ```nginx
          server {
              listen       9001;
              server_name  nginx2.chaospring.com;

              location ~ /edu/ {
                  proxy_pass http://127.0.0.1:8080;
              }

              location ~ /vod/ {
                  proxy_pass http://127.0.0.1:8081;
              }
          }
          ```

       2. 开放对外访问的端口号 9001 8080 8081

     * location 说明

       location ~ /vod/ { }

       1. \=: 用于不含正则表达式的 uri 前， 要求请求字符串和 uri 严格匹配，如果匹配成功，就停止继续向下搜索并立即处理该请求。

       2. \~: 用与表示 uri 包含正则表达式，并且区分大小写

       3. \~\*：用于表示 uri 包含正则表达式，并且不区分大小写。

       4. ^~：用与不含正则表达式的 uri 前，要求 Nginx 服务器找到表示 uri 和请求字符串匹配度最高的 location 后，立即使用此
          location 处理请求，而不再使用 location 块中的正则 uri 和请求字符串做匹配

          注意：如果 uri 包含正则表达式，则必须要有 ~  或者 ~\* 标识。

## nginx配置实例--负载均衡

### 配置

1. 实现效果

   浏览器地址栏输入地址 http://nginx3.chaospring.com/edu/a.html，负载均衡效果，平均 8080 和 8081 端口中

2. 准备工作

   * 准备两台 tomcat 服务器，一台 8080，一台 8081
   * 在两台 tomcat 里面 webapps 目录中，创建名称是 edu 文件夹，在 edu 文件夹中创建 页面 a.html，用于测试

3. 实现负载均衡

   在http块中加入：

   ```nginx
   upstream myserver{
   	server 127.0.0.1:8080;
   	server 127.0.0.1:8081;
   }
   ```

   在server块中加入：

   ```nginx
   server {
   	listen       9002;
   	server_name  45.77.**.**;

   	location / {
       	proxy_pass https://myserver;
   	}
   }
   ```

### 负载均衡分配策略

1. 轮询（默认）

   每个请求按时间顺序注意分配请求，如果某个服务器down掉，能自动删除。

2. 权重 weight

   weight 代表权重，默认为 1，权重越高被分配的客户端越多。

   ```nginx
   upstream myserver{
   	server 127.0.0.1:8080 weight=5;
   	server 127.0.0.1:8081 weight=10;
   }
   #8081 比 8080 分配多一倍
   ```

3. ip\_hash

   每个请求按访问 ip 的 hash 结果分配，这样每个访客固定访问一个后端服务器，可以解决 session 共享的问题。

   ```
   upstream myserver{
   	ip_hash;
   	server 127.0.0.1:8080;
   	server 127.0.0.1:8081;
   }
   ```

4. fair(第三方)

   按后端服务器的响应时间来分配

   ```nginx
   upstream myserver{
   	server 127.0.0.1:8080;
   	server 127.0.0.1:8081;
   	fair;
   }
   ```

## nginx配置实例--动静分离

1. 放置静态文件

   /data/image/1.jpg

   /data/www/a.html

2. 配置文件

3. ```nginx
   server {
       listen       9002;
       server_name  45.77.**.**;

       location /www/ {    #/www/ 目录
           root /data/; #动态资源很路径
       }
           
       location /image/ {   #/image/ 目录
           root /data/;
           autoindex on; #列出访问目录 作用不大
       }
    }
   ```

4. 重启nginx

## nginx配置-高可用集群

### 条件

（1）需要两台 nginx 服务器

（2）需要 keepalived

```sh
yum install keepalived –y
```

（3）需要虚拟 ip

### 完成高可用配置（主从配置）

1. 修改/etc/keepalived/keepalivec.conf 配置文件

   ```
   global_defs {
    notification_email {
    acassen@firewall.loc
    failover@firewall.loc
    sysadmin@firewall.loc
    }
    notification_email_from Alexandre.Cassen@firewall.loc
    smtp_server 192.168.17.129  #nginx服务器1
    smtp_connect_timeout 30
    router_id LVS_DEVEL  #定义唯一id 可用本机ip 否则在host里配置映射关系
   }
   vrrp_script chk_http_port {  #检测是否还活着
    script "/usr/local/src/nginx_check.sh"
    interval 2 #检测脚本执行的间隔 2秒一次
    weight 2   #当前服务器权重
   }
   vrrp_instance VI_1 {
    state BACKUP # 备份服务器上将 MASTER 改为 BACKUP
    interface eth0 //网卡名字
    virtual_router_id 51 # 主、备机的 virtual_router_id 必须相同
    priority 90 # 主、备机取不同的优先级，主机值较大，备份机值较小
    advert_int 1
    
    authentication { 权限校验
    auth_type PASS
    auth_pass 1111
    }
    virtual_ipaddress {
    192.168.17.50 // VRRP H 虚拟地址
    }
   }

   ```

   网卡名字查找

   ```shell
   ipconfig
   ```

   ```shell
   ifconfig
   eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
   ```

   eth0：为我的网卡名字

2. 在/usr/local/src 添加检测脚本nginx\_check.sh

   ```shell
   #!/bin/bash
   A=`ps -C nginx –no-header |wc -l`
   if [ $A -eq 0 ];then
    /usr/local/nginx/sbin/nginx
    sleep 2
    if [ `ps -C nginx --no-header |wc -l` -eq 0 ];then
    killall keepalived
    fi
   fi
   ```

3. 把两台服务器上 nginx 和 keepalived 启动

   ```shell
   #启动 nginx：
   ./nginx
   #启动 keepalived：
   systemctl start keepalived.service
   ```

## nginx原理

### mater 和 worker

一个 master 和多个 woker 有什么好处 ？

（1）可以使用 nginx –s reload 热部署，利用 nginx 进行热部署操作

（2）每个 woker 是独立的进程，如果有其中的一个 woker 出现问题，其他 woker 独立的， 继续进行争抢，实现请求过程，不会造成服务中断

### 设置多少个 woker 合适

worker 数和服务器的 cpu 数相等是最为适宜的

### 连接数 worker\_connection

1. 第一个：发送请求，占用了 woker 的几个连接数？

   * 2 或者 4 个

2. 第二个：nginx 有一个 master，有四个 woker，每个 woker 支持最大的连接数 1024，支持的 最大并发数是多少？
   * 普通的静态访问最大并发数是： worker\_connections \* worker\_processes /2 = 2048
   * 而如果是 HTTP 作 为反向代理来说，最大并发数量应该是 worker\_connections \* worker\_processes/4 = 1024

## 常见问题

1. 解决Nginx: `[error] open() ＂/usr/local/Nginx/logs/Nginx.pid" failed（2:No such file or directory）`

   问题原因：环境问题

   ```shell
   /usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf
   ```

   使用nginx -c的参数指定nginx.conf文件的位置

   ```shell
   [root@localhost nginx]# cd logs/
   [root@localhost logs]# ll
   总用量 12
   -rw-r--r-- 1 root root 1246 12月 9 18:10 access.log
   -rw-r--r-- 1 root root 516 12月 10 15:39 error.log
   -rw-r--r-- 1 root root 5 12月 10 15:38 nginx.pid
   ```
