目录
Nginx是什么?
Nginx能干嘛?
Nginx的优势是什么?
什么是反向代理?
1. 正向代理
2.反向代理
什么是负载均衡?
什么是动静分离?
Nginx下载安装
1. 官网下载地址:https://nginx.org/en/download.html
2. 安装nginx所需要的四个依赖包
3.安装nginx
4.nginx启动,停止,重新加载等常用命令
5.登录到nginx的默认页面
6.处理防火墙问题
7.最后
实现功能的前置准备
1.新建maven项目
2.项目结构
3.pom文件
4. yml
5. 主启动
6.Controller
7.本地测试
8.打Jar包
9.修改YML中端口号 再次打成jar 包
10.将项目部署到linux
Nginx实现反向代理
1. Nginx配置文件的基本介绍
2. 修改配置文件实现反向代理
3. 解释location 的匹配规则
Nginx实现负载均衡
1.修改配置文件
2.测试
3.其他几种策略的说明
Nginx实现动静分离
1.准备资源
2.修改配置
3.测试
结语
前言:很多小伙伴在学习新技术的时候会出现一种情况,就是恨不得一上来就撸代码HelloWord开干,然后几个功能实现一下,打完收工。我觉得可以在优化一下这种方式,代码固然重要,但是理论也必不可少。毕竟面试的时候,你能否清晰的表达很多程度上影响薪资水平。所以我们不能成为只会撸代码的憨憨,要成为一名德智体美劳均衡发展的小朋友才行。
在敲代码之前,一定要花时间理解下理解下前面的基础理论知识,这很重要!很重要!很重要!重要的话说三遍。好了我们正式开始!
Nginx是什么?
Nginx 是一个高性能的HTTP和反向代理web服务器。
这里没有什么可理解的,但你必须知道,死记硬背即可。
Nginx能干嘛?
1.实现反向代理
2.实现负载均衡
3.实现动静分离
关于这几个名词后续会有详细解释,这里先有个印象即可。
Nginx的优势是什么?
1. Nginx为性能优化而开发,专注于提升效率。具有稳定性高、资源消耗少,占有内存低,并发能力强等特点。
2. Nginx 能经受高负荷的考验,有报告表明能支持高达50000个并发连接数。
3. Nginx 支持热部署,启动速度特别迅速,因此可以在不间断服务的情况下,对软件版本或者配置进行升级,即使运行数月也无需重新启动,几乎可以做到7x24小时不间断地运行。
这里不需要全部记住,但是如果问到这里,你要能说出几条来。
什么是反向代理?
学习Nginx就一定要理解这个概念,我们之所以使用Nginx最重要的一个点就是为了使用反向代理功能。我们使用正向代理和反向代理对比着理解,这里先抛出概念后续详解。
所谓正向代理,代理的是客户端。而反向代理,代理的是服务器端。
1. 正向代理
场景1:
正向代理是客户端的代理,服务器不知道真正的客户端是谁,主要是用来解决访问限制问题
2.反向代理
场景2:
反向代理是服务器的代理,客户端不知道真正的服务器是谁。反向代理主要是提供负载均衡、隐藏真实服务器、安全防护等作用。
相信看完两个案例后,各位小伙伴都可以很轻松的理解什么是正向代理,什么是反向代理。这时在回顾下我刚开始抛出的概念: 所谓正向代理,代理的是客户端。而反向代理,代理的是服务器端。是不是有了更深的体会?
什么是负载均衡?
使用某种策略(轮询、随机、权重),将这些请求均匀的发到每台机器上以此来分摊压力?而不是说A服务器处理99%的请求,跑到CPU起火。B、C服务器处理1%不到的请求,就好像没有运行一样闲的划水。这样不好吧。上诉将将庞大请求量均衡分摊的策略就是我们的负载均衡。
什么是动静分离?
将动态请求和静态请求区分访问
首先我们先要知道Tomcat处理动态页面才是他的强项,而他处理静态页面却并不是最优解。如果不使用动静分离策略,动静态页面全部交给tomcat完成也是可以的,但并不高效。我们动静分离是将动态页面比如jsp、php全部交给tomcat处理。而静态页面就有Nginx自己处理。以此来提升系统的整体性能。
Nginx下载安装
在实际工作当中这些中间件的安装部署肯定是在linux上的,从来没有听说哪个项目是在windows上部署运行的。所以我们的安装教程也是针对linux。但是也不排除有暂时还没有接触过linux的小伙伴,想先学nginx。如果有安装在windows的小伙伴可以看看下面这篇教程。
Nginx Windows详细安装部署教程
下面进入正题linux系统安装nginx
1. 官网下载地址:https://nginx.org/en/download.html
下载完之后,你会得到一个nginx-1.12.2.tar.gz 的文件。将该文件上传至你的linux系统中。准备后续安装。
2. 安装nginx所需要的四个依赖包
nginx想要运行,除了安装nginx自身软件外,还需要安装4个额外的依赖包,我们先将这四个依赖包安装好,在进行后续nginx的安装。
--直接输入该条命令下载安装四个依赖包即可
[root@VM-12-13-centos ~]# yum -y install gcc pcre pcre-devel zlib zlib-devel openssl openssl-devel
我这里是因为已经下载过给出的提示,没有下载过的小伙伴应该是会给出安装成功的相关提示。
3.安装nginx
我个人习惯,将所有外部下载的软件,统一存放在usr目录下为其单独创建的文件夹中。以便后续统一管理。你要是想要存放到其他文件夹也是可以的。只是注意命令会和我的有些许不同,以你的路径为准即可。
--1.进入usr目录
[root@VM-12-13-centos ~]# cd /usr
--2.在usr目录中创建名为nginx的文件夹,存放之前下载好的软件
[root@VM-12-13-centos usr]# mkdir nginx
--3.将之前下载好的nginx安装文件上传至我们新建的文件夹中
--这里不是命令操作,我就不演示了
--4.解压安装文件(注意这里不能直接复制。解压的文件名要和你下载的文件名一致)
[root@VM-12-13-centos nginx]# tar zxvf nginx-1.12.2.tar.gz
--5.解压好会生成新文件夹,进入该文件夹。(同样这里也是以你解压好生成的文件夹为主)
[root@VM-12-13-centos nginx]# cd nginx-1.12.2
--6.检查文件 这里./XXX 命令的意思是在执行当前目录中XXX文件的意思。
[root@VM-12-13-centos nginx-1.12.2]# ./configure
--7.编译
[root@VM-12-13-centos nginx-1.12.2]# make
--8.编译并安装
[root@VM-12-13-centos nginx-1.12.2]# make install
4.nginx启动,停止,重新加载等常用命令
nginx安装好后,默认的安装路径是/usr/local/nginx。我们需要进入安装路径的sbin目录来做相应的启动和停止相关操作
--1.进入nginx的默认安装目录中的sbin文件夹
[root@VM-12-13-centos nginx-1.12.2]# cd /usr/local/nginx/sbin
--2.启动nginx
[root@VM-12-13-centos sbin]# ./nginx
--3.停止nginx
[root@VM-12-13-centos sbin]# ./nginx -s stop
--4.重新加载
[root@VM-12-13-centos sbin]# ./nginx -s reload
--5.查看版本
[root@VM-12-13-centos sbin]# ./nginx -v
--6.查看nginx是否启动成功
[root@VM-12-13-centos sbin]# ps -ef | grep nginx
5.登录到nginx的默认页面
安装并启动成功后,使用你 linux 的ip地址输入到浏览器上,如果出现该页面表示你安装成功了。
6.处理防火墙问题
有的同学可能会遇到明明已经启动了nginx但是在浏览器上却访问不到的情况。这很有可能是由于linux防火墙的原因造成的,由于这篇文章主要讲述nginx,所以防火墙就不具体展开了,我这边提供几个简单的命令。大家可以先直接粗暴的关闭防火墙。等学习完nginx的相关功能后在开启防火墙即可。
--1.查看防火墙状态
systemctl status firewalld.service
--2.关闭防火墙
systemctl stop firewalld.service
--3.开启防火墙
systemctl start firewalld.service
--4.禁止防火墙自启动
systemctl disable firewalld.service
--5.防火墙随系统开启启动
systemctl enable firewalld.service
如果有童鞋和我一样使用的是在阿里或者腾讯租的云服务器,那么上面的方法是无效的,你需要在你的云服务器控制台中的防火墙页面,开通你需要访问的端口权限才行。
这里以腾讯云为例子:
7.最后
安装过程中由于版本或系统不一致的原因,很有可能会出现这样那样不可预知的问题,如果顺利当前最好,但要是出现问题也不要着急,耐心去网上搜索下,一定会找到解决的办法。这也是锻炼个人解决问题的能力。相信各位小伙伴的能力,加油!
实现功能的前置准备
为了更直观的实现nginx的相关功能,我们需要先搭建一个简单的SpringBoot项目,这里重点不是业务逻辑,而是配合测试nginx的反向代理功能。我将代码展示出来各位快速复制搭建一下。
1.新建maven项目
2.项目结构
这里不需要一定按我的结构来,只是为了让大家看的清晰一点。
3.pom文件
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.6.13</version>
<relativePath/>
</parent>
<dependencies>
<!--下面三个是SpringBoot项目的基础依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
4. yml
server:
port: 8006
spring:
application:
name: nginx-test
5. 主启动
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class BootStart {
public static void main(String[] args) {
SpringApplication.run(BootStart.class,args);
}
}
6.Controller
建了两个controller。都没有逻辑只是输出了端口号,和你调用方法名以及你输入的入参。
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController()
@RequestMapping("/order")
@Slf4j
public class OrderController {
@Value("${server.port}")
private String port;
@GetMapping(value = "/getOrderId/{id}")
public String getOrderId(@PathVariable("id") long id) {
String rs="端口号为:"+port+",你进入的是order/getOrderId/id 路径"+id;
log.info(rs);
return rs;
}
@GetMapping(value = "/getOrderInfo/{id}")
public String getOrderInfo(@PathVariable("id") long id) {
String rs="端口号为:"+port+",你进入的是order/getOrderInfo/id 路径"+id;
log.info(rs);
return rs;
}
@GetMapping(value = "/getOrderHeader/{id}")
public String getorder(@PathVariable("id") long id) {
String rs="端口号为:"+port+",你进入的是order/getOrderHeader/id 路径"+id;
log.info(rs);
return rs;
}
}
同上,也没有逻辑,辅助测试nginx而已
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/payment")
@Slf4j
public class PaymentController {
@Value("${server.port}")
private String port;
@GetMapping(value = "/getPaymentId/{id}")
public String getPaymentId(@PathVariable("id") long id) {
String rs="端口号为:"+port+",你进入的是order/getPaymentId/id 路径"+id;
log.info(rs);
return rs;
}
@GetMapping(value = "/getPaymentInfo/{id}")
public String getPaymentInfo(@PathVariable("id") long id) {
String rs="端口号为:"+port+",你进入的是order/getPaymentInfo/id 路径"+id;
log.info(rs);
return rs;
}
@GetMapping(value = "/getPaymentHeader/{id}")
public String getPaymentHeader(@PathVariable("id") long id) {
String rs="端口号为:"+port+",你进入的是order/getPaymentHeader/id 路径"+id;
log.info(rs);
return rs;
}
}
7.本地测试
测试地址 :localhost:8006/payment/getPaymentId/07
测试地址 :localhost:8006/order/getOrderId/15
8.打Jar包
修改名称为:testNginx-8006
9.修改YML中端口号 再次打成jar 包
端口修改成8008。(后续测试负载均衡会用到)
server:
port: 8008
spring:
application:
name: nginx-test
这里再测试一下,地址端口改为8008即可。
测试地址 :localhost:8008/payment/getPaymentId/07
测试地址 :localhost:8008/order/getOrderId/15
修改名称为:testNginx-8008。
这时我们就有了两个不同端口的jar包。
10.将项目部署到linux
10.1 创建data文件夹将两个jar包上传进去
--进入主目录
[root@VM-12-13-centos ~]# cd /
--在主目录中创建data子目录
[root@VM-12-13-centos /]# mkdir data
--进入data目录
[root@VM-12-13-centos /]# cd /data
--在data目录中在创建javaCode目录
[root@VM-12-13-centos data]# mkdir javaCode
--进入javaCode,而后将我们的两个jar包上传至其中
[root@VM-12-13-centos data]# cd javaCode
将两个jar包上传后,我们linux中的文件结构就是这样的
10.2 运行两个jar包
--运行 8006
[root@VM-12-13-centos javaCode]# nohup java -jar testNginx-8006.jar > testNginx8006.log 2>&1 &
--运行 8008
[root@VM-12-13-centos javaCode]# nohup java -jar testNginx-8008.jar > testNginx8008.log 2>&1 &
正常情况下,运行成功都会给你进程id,如下图
同时我们记录了日志。
10.3 测试
部署运行后,我们访问下看是否运行成功。
注:还是要记得处理下linux防火墙问题。我前面已经有过说明这里就不再赘述。快速定位到说明处---Ctrl+f 搜索:处理防火墙问题
Nginx实现反向代理
到这里终于要开始实现功能了,nginx的相关功能实现其实就是玩他的配置文件。所以我们先了解下nginx配置文件的基本组成结构,让大家先有个概念在去做相应的配置。这样会事半功倍。
1. Nginx配置文件的基本介绍
1.1 Nginx配置文件位置
nginx的配置文件在其安装路径的conf文件夹中,名字是nginx.conf。还记得我之前说的默认安装路径吗?我们在进入到该目录。看一样配置文件先。
--1.进入nginx的默认安装目录下的conf文件夹
[root@VM-12-13-centos /]# cd /usr/local/nginx/conf
--2.使用vim编辑器查看配置文件内容
[root@VM-12-13-centos conf]# vim nginx.conf
1.2 Nginx配置文件说明
知道配置文件的大概结构有 全局块,events块,以及http块。而http块中又可以分成http全局块,和httpServer块即可。后续随着功能的实现对于其理解自然会逐渐加深。
//1.全局块,影响服务器运行的配置指令
worker_processes 1; //工作进程数量。根据硬件调整,通常等于CPU数量或者2倍于CPU。
//2.events块,服务器与用户网络连接
events {
worker_connections 1024; //每个工作进程的最大连接数量。根据硬件调整
}
//http块 http块被分为http全局块、server 块
//http块是重点,后续的配置大部分都是配置http块实现功能。
http {
//http的全局块
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
//http的server块 每一个server段都是一个虚拟主机,一个http中可以有多个server
server {
listen 80;
server_name localhost;
location / {
root html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
2. 修改配置文件实现反向代理
之前我们搭建部署好了项目,我们需要实现的将请求发送到nginx 上后由nginx将请求转发到我们的项目中。实现反向代理。表面上请求nginx,实际请求我我们自己的项目。
2.1 修改配置文件http块中的server块实现功能
--1.首先进入nginx安装目录的sbin中
[root@VM-12-13-centos /]# cd /usr/local/nginx/sbin
--2.使用vim编辑器打开nginx.conf配置文件
[root@VM-12-13-centos sbin]# vim ../conf/nginx.conf
2.2修改配置文件:
#这是http块下的server块中的内容。千万注意位置不要改错。
listen 80; #nginx监听的端口。你可以配置成其他端口
server_name 监控80端口; #自定义名称。
location ~ /order { #请求路径中有order的都会匹配进入到8006端口
proxy_pass http://127.0.0.1:8006;
#只要条件匹配进入这个location中,nginx就会将请求转发到对应的IP和端口中。
}
location ~ /payment { #请求路径中有payment 的都会匹配进入到8008端口
proxy_pass http://127.0.0.1:8008;
}
说明:这里是因为条件所限,只有一台服务器才蹩脚的用nginx将请求又转发给了自己所在的服务器。只是端口不同而已。大家活学活用,理解就好。要是未来真的有多台服务器。只需要将127.0.0.1的本地ip 改成其他服务器的ip端口,就可以真正实现请求转发。
2.3 重新加载nginx使配置文件生效
--重新加载nginx
[root@VM-12-13-centos sbin]# ./nginx -s reload
2.4 测试反向代理
使用自己的ip地址来测试
测试地址:XXX.XXX.XXX.X/payment/getPaymentId/07
XXX.XXX.XXX.X/order/getOrderHeader/15
测试成功。我们访问没有带端口号,也就是使用的默认80端口。nginx帮我们完成了反向代理,将请求按匹配规则转发到了8006 和8008端口。
3. 解释location 的匹配规则
3.1 配置文件中匹配过程说明
匹配大概分成两步。
1.根据你的匹配功能,选择进入哪一个location 。
2.将你请求后的路径匹配到location 中ip地址的后面。
以下图的配置为例说明:
比如我们linux的ip是 115.58.176.105 (胡诌的)。现在nginx 监听的端口是80。按上图配置。我们现在请求 115.58.176.105/order/getOrderHeader/15。
因为请求中包括order,所以会进入 ~ /order 这个location。这里就对标了我们之前总结的第一步根据匹配规则选择location。然后进行第二步将路径拼接到该location中配置的ip地址后面。那么我们实际请求的地址就变成了 127.0.0.1:8006/order/getOrderHeader/15。 这样就完成了我们反向代理的功能。
3.2 匹配规则的几种写法
= | 精确匹配 |
^~ | 非正则匹配 |
~ | 正则匹配(区分大小写) |
~* | 正则匹配(不区分大小写) |
!~ | 正则不匹配(区分大小写) |
!~* | 正则不匹配(不区分大小写) |
Nginx实现负载均衡
在实现完反向代理后,在此基础上在实现负载均衡就相对容易了。
1.修改配置文件
--1.首先还是进入sbin目录
[root@VM-12-13-centos /]# cd /usr/local/nginx/sbin
--2.使用vim 打开配置文件
[root@VM-12-13-centos sbin]# vim ../conf/nginx.conf
配置文件
http { 注意是还是在http块中。
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
upstream quote { #这是我们新加的配置块,quote是自定义名称。
# 要转发到的服务器,如ip、ip:端口号、域名、域名:端口号
server 127.0.0.1:8008 ;
server 127.0.0.1:8006 ;
}
server {
listen 80;
server_name 监控80端口;
location ~ /order {
proxy_pass http://quote;
#之前我们是直接些反向代理的ip端口。现在我们改成新增的upstream 块名称
}
#后面内容忽略
这里应该比较好理解。之前我们location中直接写明了需要代理的ip及端口。但是现在中间多了一层,我进入location后,我们先找到了名字叫quote 的upstream 块(也就是我们为了完成负载均衡新增的upstream 块),然后发现里面配置了两条ip和端口。那么在这种情况下nginx会自动使用轮询策略,来实现我们的负载均衡功能。
2.测试
现在在根据我们linux的ip来测试负载均衡功能,注意记得每次改完配置文件都记得要重新加载下nginx使配置文件生效。[root@VM-12-13-centos sbin]# ./nginx -s reload
你的ip地址/order/getOrderInfo/01 来测试请求。发现端口在一直变化。表示实现负载均衡成功。
3.其他几种策略的说明
3.1 轮询
默认情况就是轮询。我们上面以及实现过,这里就不在赘述。
3.1 权重
这里有遇到一个坑,我之前写成了这样( server 127.0.0.1:8008 weigh = 1;) 就是在=号的前面或者后面加上了空格,就一直报错。大家注意下。
upstream quote {
#least_conn;
# 要转发到的服务器,如ip、ip:端口号、域名、域名:端口号
server 127.0.0.1:8008 weigh=1;
server 127.0.0.1:8006 weigh=3;
}
解释:所以权重之和为4,那么他们分别的权重就 1/4和3/4。后续权重为3/4的端口,会接受都更多的请求
3.2 iphash
就是说每一个ip只会同一台机器。如上面的配置,虽然我们配置了权重,但是在此测试访问后,却只能一直访问一个端口了。原因就是我们的ip一直是同一个。所以就只能访问同一台机器。
upstream quote {
ip_hash;
# 要转发到的服务器,如ip、ip:端口号、域名、域名:端口号
server 127.0.0.1:8008 weight=1 ;
server 127.0.0.1:8006 weight=3 ;
}
3.3 least_conn
将请求发送到目前最小连接数的机器上去。就是谁比较闲让谁干活。
upstream quote {
least_conn;
# 要转发到的服务器,如ip、ip:端口号、域名、域名:端口号
server 127.0.0.1:8008 weight=1 ;
server 127.0.0.1:8006 weight=3 ;
}
3.4 fair
按照请求时长、页面大小智能化分配请求。这里需要下载而外的插件,就不在演示。日常工作中前面介绍的几种方式应该满足绝大多数的需求。如果有兴趣的小伙伴也可以网上 了解下fair 的实现方式。
Nginx实现动静分离
实现功能,我在linux 中存入一些静态资源,当客户端需要访问这些静态资源的时候,就不需要tomcat了,而是直接由我们的nginx自己来处理。
1.准备资源
在我们之前建的data文件夹中,创建static,再在static中创建两个文件夹,html和img。在其中分别放入一个html网页,和一张图片
2.修改配置
在我们刚刚配置实现的负载均衡location下面在加上两个新的location来实现我们的动静分离。如果有请求匹配进了我们/img 或者/html 的location 之后,nginx会自己找到并处理在本地路径中静态资源直接渲染展示给客户端。
注意:现在location中的内容不在是之前的proxy_pass,而是变成了root。
server {
listen 80;
server_name 监控80端口;
location ~ /order {
proxy_pass http://quote;
}
location ~ /img {
root /data/static;
}
location ~ /html {
root /data/static;
}
3.测试
你的IP地址/html/test.html
你的IP地址/img/test.jpg
测试成功。这里在解释下匹配过程。以 你的IP地址/html/test.html为例子
首先我们路径中有html,所以匹配进了~ /html的location中。然后进行路径的拼接,将/html/test.html拼接到location配置的路径前。也就变成了 /data/static/html/test.html 完整的路径。nginx根据路径在本地找到该静态资源,处理展示给了客户端。
结语
文章到这里就结束了,相信看到这里的小伙伴,对于nginx的理解和使用都有了必要的了解。我还是重复下开头的话,理论很重要