# Nginx学习笔记(一)
> 最近部署前后端分离项目时和部署自己第二代博客Halo到服务器时接触到了Nginx,其中的nginx.conf配置文件不是很懂,采过不少坑。感觉有必要学习总结一下Nginx,看一看Nginx究竟是个什么东东?Nginx还挺好用的,反向代理属实好用。下面就开始梳理学习Nginx吧。让我们先了解一下概念,大致知道Nginx是怎么回事。
### Nginx是什么?
![Nginx](https://mybolg-typora.oss-cn-beijing.aliyuncs.com/%20blogPic/202112051337677.png)
Nginx (engine x) 是一个高性能的HTTP和反向代理服务器,也是一个IMAP/POP3/SMTP服务器。而且支持热部署,几乎可以做到 7 * 24 小时不间断运行,即使运行几个月也不需要重新启动,还能在不间断服务的情况下对软件版本进行热更新。性能是Nginx最重要的考量,其占用内存少、并发能力强、能支持高达 5w 个并发连接数。
Nginx 解决了服务器的C10K(就是在一秒之内连接客户端的数目为10k即1万)问题。它的设计不像传统的服务器(Tomcat)那样使用线程处理请求,而是一个更加高级的机制—事件驱动机制,是一种异步事件驱动结构。(Tomcat默认最大并发连接数150)
### Nginx特点
跨平台:可以在大多数Linux系统编译运行。而且也有Windows的移植版本。
配置异常简单:非常的简单,易上手。
非阻塞、高并发连接:数据复制时,磁盘I/O的第一阶段是非阻塞的。官方测试能支持5万并发连接,实际生产中能跑2~3万并发连接数(得益于Nginx采用了最新的epoll事件处理模型(消息队列)。
Nginx代理和后端Web服务器间无需长连接;
Nginx接收用户请求是异步的,即先将用户请求全部接收下来,再一次性发送到后端Web服务器,极大减轻后端Web服务器的压力。
发送响应报文时,是边接收来自后端Web服务器的数据,边发送给客户端。
网络依赖性低,理论上只要能够ping通就可以实施负载均衡,而且可以有效区分内网、外网流量。
支持内置服务器检测。Nginx能够根据应用服务器处理页面返回的状态码、超时信息等检测服务器是否出现故障,并及时返回错误的请求重新提交到其它节点上。
采用Master/worker多进程工作模式
内存消耗小、成本低廉(比F5硬件负载均衡器廉价太多)、节省带宽、稳定性高等特点。
### Nginx功能
Nginx的功能包括基本HTTP功能和扩展功能。和Apache服务器一样,Nginx服务器为了提供更多的功能并且能够有效地扩展这些功能。每一个模块都提供了一个功能,通过编译这些功能模块来实现功能的扩展。
1. 提供静态文件和index文件,处理静态文件,索引文件以及自动索引,打开文件描述符缓存;
2. 使用缓存加速反向代理,反向代理加速(无缓存),简单的负载均衡和容错;
3. 使用缓存机制加速远程FastCGI,简单的负载均衡和容错;
4. 模块化的结构。过滤器包括gzipping,byte ranges,chunked responses,以及 SSI-filter。在SSI过滤器中,到同一个 proxy 或者 FastCGI 的多个子请求并发处理;
5. 支持SSL 和 TLS SNI 支持;
6. IMAP/POP3代理服务功能;
7. 使用外部 HTTP 认证服务器重定向用户到 IMAP/POP3 后端;
8. 使用外部 HTTP 认证服务器认证用户后连接重定向到内部的 SMTP 后端;
9. 基于名称和基于IP的虚拟服务器;
10. 支持Keep-alive和管道连接;
11. 灵活的配置和重新配置、在线升级的时候不用中断客户访问的处理;
12. 访问日志的格式,缓存日志写入和快速日志轮循;
13. 3xx-5xx错误代码重定向;
14. 速度限制
这些功能列举这么多。其实总结起来,就有三大特点,也是重要的使用场景。
- 静态资源服务,通过本地文件系统提供服务;
- 反向代理服务,延伸出包括缓存、负载均衡等;
- API 服务, OpenResty ;
对于前端来说 Node.js 并不陌生, Nginx和 Node.js 的很多理念类似, HTTP 服务器、事件驱动、异步非阻塞等,且 Nginx的大部分功能使用 Node.js 也可以实现,但 Nginx和 Node.js 并不冲突,都有自己擅长的领域。Nginx 擅长于底层服务器端资源的处理(静态资源处理转发、反向代理,负载均衡等), Node.js 更擅长上层具体业务逻辑的处理,两者可以完美组合。
用一张图表示Nginx在架构中的使用:
![Nginx架构使用图jpg](https://mybolg-typora.oss-cn-beijing.aliyuncs.com/%20blogPic/202112051416536.jpg)
从这张图可以看出,客户端的HTTP请求并不是直接访问应用服务器, 而是通过最前面的Nginx反向代理将Http请求分发到具体服务器。
### Nginx反向代理
> 咋一看,反向代理,不太懂。了解反向代理之前,先聊一聊正向代理。!
正向代理:
![正向代理](https://mybolg-typora.oss-cn-beijing.aliyuncs.com/%20blogPic/202112051949362.jpg)
VPN”翻墙“就是典型的正向代理。在这里正向代理"代理"的是客户端,而且客户端是知道访问目标的,对于服务端(访问目标)并不知道客户端是通过VPN访问的。通过此图可以看出,客户端在进行“翻墙”操作的时候,通过代理服务器,将我们的HTTP请求转发到真实需要访问服务端。(代理服务器一般指局域网内部的机器通过代理服务器发送请求到互联网上的服务器,代理服务器一般作用在客户端。)
> PS:私自搭建VPN或未备案甚至制售VPN有可能涉嫌非法犯罪
反向代理:
![反向代理](https://mybolg-typora.oss-cn-beijing.aliyuncs.com/%20blogPic/202112052009812.jpg)
当我们在外网访问百度的时候,其实会进行一个转发,代理到内网去,这就是所谓的反向代理,即反向代理“代理”的是服务器端,而且这一个过程对于客户端而言是透明的。
反向代理服务器作用在服务器端,它在服务器端接收客户端的请求,然后将请求分发给具体的服务器进行处理,然后再将服务器的相应结果反馈给客户端。Nginx就是一个反向代理服务器软件。
总结:**正向代理作用于客户端,反向代理作用于服务端**
### Nginx负载均衡
在多个应用实例间做负载均衡是一个被广泛使用的技术,用于优化资源效率,最大化吞吐量,减少延迟和容错。
nginx可以作为一个非常高效的HTTP负载均衡器来分发请求到多个应用服务器,并提高web应用的性能,可扩展性和可靠性。
##### 什么是负载均衡?
早期的系统架构单一,客户端直接发送多个请求到服务器,服务器处理请求,有一些可能要与数据库进行交互,服务器处理完毕后,再将结果返回给客户端。这种架构模式相对单一,在早期请发请求比较少的时候还可以应付。现在,高并发访问和海量数据,以及系统业务相当复杂的情况下,如果还使用这种简单的架构,恐怕服务器直接崩溃。
有什么解决办法呢?首先想到的是,提升服务器的物理性能,使用顶级配置。但是,即使使用性能最优异的服务器依旧不能满足日益增长的业务的需求。因此,“质量不行,数量凑”,那就多部署几台服务器。这时集群的概念产生了,负载均衡的概念产生了。那么,负载均衡就是将原有巨大的访问请求作用到一台服务器的压力分摊到各个服务器上。官方一点的概念:负载均衡,英文名称为Load Balance,其含义就是指将负载(工作任务)进行平衡、分摊到多个操作单元上进行运行,例如FTP服务器、Web服务器、企业核心应用服务器和其它主要任务服务器等,从而协同完成工作任务。
#### 负载均衡方法
nginx支持以下负载均衡机制(或者方法):
- round-robin/轮询: 到应用服务器的请求以round-robin/轮询的方式被分发
- least-connected/最少连接:下一个请求将被分派到活动连接数量最少的服务器
- ip-hash/IP散列: 使用hash算法来决定下一个请求要选择哪个服务器(基于客户端IP地址)
### Nginx动静分离
动静分离是指在 web 服务器架构中,将静态页面与动态页面或者静态内容接口和动态内容接口分开不同系统访问的架构设计方法,进而提示整个服务的访问性和可维护性。
- 动静分离将网站静态资源(HTML,JavaScript,CSS,img等文件)与后台应用分开部署,提高用户访问静态代码的速度,降低对后台应用访问。这里我们将静态资源放到nginx中,动态资源转发到tomcat服务器中。
- 因此,动态资源转发到tomcat服务器我们就使用到了前面讲到的反向代理。
动静分离从目前实现角度来讲大致分为两种:
一种是纯粹把静态文件独立成单独的域名,放在独立的服务器上,也是目前主流推崇的方案;这种做法就是下图展示的示意结构。
另外一种方法就是动态跟静态文件混合在一起发布,通过 Nginx 来分开。
![image-20211206120114647](https://mybolg-typora.oss-cn-beijing.aliyuncs.com/%20blogPic/202112061201668.png)
如果存放静态资源的服务器负载过高或空间不足,可以使用OSS+CDN对网站进行优化,实行动静分离。
### Nginx安装(Linux)
> **在linux下安装nginx,首先需要安装 gcc-c++编译器。然后安装nginx依赖的pcre和zlib包。确保上述安装成功后,才可安装nginx。**
1.先安装gcc-c++编译器
```shell
yum install gcc-c++
yum install -y openssl openssl-devel
```
2.再安装pcre包
```shell
yum install -y pcre pcre-devel
```
3.再安装zlib包
```shell
yum install -y zlib zlib-devel
```
> **下面进行nginx的安装**
1.在/usr/local/下创建文件nginx文件
```shell
mkdir /usr/local/nginx
```
2.在网上下nginx包上传至Linux(https://nginx.org/download/),也可以直接下载
```shell
wget https://nginx.org/download/nginx-1.19.9.tar.gz
```
3.解压并进入nginx目录
```shell
tar -zxvf nginx-1.19.9.tar.gz
cd nginx-1.19.9
```
4.使用nginx默认配置
```shell
./configure
```
5.编译安装
```shell
make
make install
```
6.查找安装路径
```shell
whereis nginx
```
7.进入sbin目录,可以看到有一个可执行文件nginx,直接**./nginx**执行就OK了。
```
./nginx
```
9.查看是否启动成功
```shell
ps -ef | grep nginx
```
![img](https://img2020.cnblogs.com/blog/2128586/202105/2128586-20210525122954107-155562798.png)
10.然后在网页上访问自己的IP就可以了默认端口为80(出现如下欢迎界面就成功了!)
![img](https://img2020.cnblogs.com/blog/2128586/202105/2128586-20210525123013524-2133888199.png)
> **注意问题**
如以上步骤都完成且没有问题的话,就做如下操作
> 防火墙
```shell
查看防火墙是否开启
systemctl status firewalld
```
![img](https://img2020.cnblogs.com/blog/2128586/202105/2128586-20210525123037019-946505205.png)
启动防火墙后,默认没有开启任何端口,需要手动开启端口。**nginx默认是80端口**
```shell
手动开启端口命令
firewall-cmd --zone=public --add-port=80/tcp --permanent
命令含义: --zone #作用域 --add-port=80/tcp #添加端口,格式为:端口/通讯协议 --permanent #永久生效,没有此参数重启后失效
```
开启后需要重启防火墙才生效
```shell
systemctl restart firewalld.service
```
查看防火墙是否开启了80端口的访问
```shell
firewall-cmd --list-all
```
![img](https://img2020.cnblogs.com/blog/2128586/202105/2128586-20210525123123133-488824264.png)
**开启后再次访问!!**
> 端口占用
如果启动后出现了如下的问题就是**80端口**被占用
![img](https://img2020.cnblogs.com/blog/2128586/202105/2128586-20210525123156598-1768819004.png)
可以用下面这个命令进行查看80端口被谁占用
```shell
netstat -tunlp | grep 80
```
![img](https://img2020.cnblogs.com/blog/2128586/202105/2128586-20210525123219035-1996362499.png)
这里因为我之前开启了的是被**nginx.master**或者**nginx.woeker**占用就不用管,如果不是这个的话那就把那个进程关闭掉
```
kill -9 进程号
```
**关闭之后重启nginx再次访问!!**
Nginx学习笔记(一)