简单的 nginx 学习

简单的 nginx 学习

在这里插入图片描述

1. nginx的安装

1.1 下载安装包

官网下载对应的nginx包,推荐使用稳定版本,上传nginx到linux系统

image-20240826092005306

image-20240826092131780

1.2 安装依赖环境

  • 安装gcc环境

    yum install gcc-c++
    

    image-20240826092339311

  • 安装PCRE库,用于解析正则表达式

    yum install -y pcre pcre-devel
    

    image-20240826092507080

  • zlib压缩和解压缩依赖

    yum install -y zlib zlib-devel
    

    image-20240826092605666

  • SSL 安全的加密的套接字协议层,用于HTTP安全传输,也就是https

    yum install -y openssl openssl-devel
    

    image-20240826092646367

  • 解压,需要注意,解压后得到的是源码,源码需要编译后才能安装

    tar -zxvf nginx-1.26.2.tar.gz
    

    image-20240826093033962

  • 编译之前,先创建nginx临时目录,如果不创建,在启动nginx的过程中会报错

    mkdir /var/temp/nginx -p
    
  • 在nginx目录,输入如下命令进行配置,目的是为了创建makefile文件

    ./configure \
    --prefix=/usr/local/nginx \
    --pid-path=/var/run/nginx/nginx.pid \
    --lock-path=/var/lock/nginx.lock \
    --error-log-path=/var/log/nginx/error.log \
    --http-log-path=/var/log/nginx/access.log \
    --with-http_gzip_static_module \
    --http-client-body-temp-path=/var/temp/nginx/client \
    --http-proxy-temp-path=/var/temp/nginx/proxy \
    --http-fastcgi-temp-path=/var/temp/nginx/fastcgi \
    --http-uwsgi-temp-path=/var/temp/nginx/uwsgi \
    --http-scgi-temp-path=/var/temp/nginx/scgi
    

    image-20240826094707296

    命令解释
    prefix指定nginx安装目录
    pid-path指向nginx的pid
    lock-path锁定安装文件,防止被恶意篡改或误操作
    error-log错误日志
    http-log-pathhttp日志
    with-http_gzip_static_module启用gzip模块,在线实时压缩输出数据流
    http-client-body-temp-path设定客户端请求的临时目录
    http-proxy-temp-path设定http代理临时目录
    http-fastcgi-temp-path设定fastcgi临时目录
    http-uwsgi-temp-path设定uwsgi临时目录
    http-scgi-temp-path设定scgi临时目录
  • make编译以及install安装

    make
    

    image-20240826095203001

    make install
    

    image-20240826095228587

  • 启动服务

    # 进入到nginx安装目录
    cd /usr/local/nginx/sbin
    # 启动服务
    ./nginx
    # 停止服务
    ./nginx -s stop
    # 重新加载
    ./nginx -s reload
    

    image-20240826095739466

  • 打开浏览器,访问虚拟机所处内网ip即可打开nginx默认页面,显示如下便表示安装成功

    image-20240826095822563

    注意事项:
    如果在云服务器安装,需要开启默认的nginx端口:80
    如果在虚拟机安装,需要关闭防火墙
    本地win或mac需要关闭防火墙

2. 首页访问过程

查看 nginx/conf 下的 nginx.conf文件

server {
    # 监听端口
    listen  80;
    # 监听服务ip地址
    server_name  localhost;

    # 映射地址, /映射到下面配置地址
    location / {
    	# 相对目录地址 html与conf目录同级
        root   html;
        index  index.html index.htm;
	}

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
    	root   html;
    }
}

上面访问过程如下:

客户端请求http://192.168.138.129:80/ => Nginx服务器 => 监听80端口 => 找到对应服务server => 映射路由地址 / => HTML资源

3. nginx基础认知

3.1 nginx进程模型

同步与异步,阻塞与非阻塞

  • 同步阻塞: 客户端发送请求给服务端,此时服务端处理任务时间很久,则客户端则被服务端堵塞了,所以客户端会一直等待服务端的响应,此时客户端不能做其他任何事,服务端也不会接受其他客户端的请求。这种通信机制比较简单粗暴,但是效率不高。

  • 同步非阻塞: 客户端发送请求给服务端,此时服务端处理任务时间很久,这个时候虽然客户端会一直等待响应,但是服务端可以处理其他的请求,过一会回来处理原先的。这种方式很高效,一个服务端可以处理很多请求,不会在因为任务没有处理完而堵着,所以这是非阻塞的。

  • 异步阻塞: 客户端发送请求给服务端,此时服务端处理任务时间很久,但是客户端不会等待服务器响应,它可以做其他的任务,等服务器处理完毕后再把结果响应给客户端,客户端得到回调后再处理服务端的响应。这种方式可以避免客户端一直处于等待的状态,优化了用户体验,其实就是类似于网页里发起的ajax异步请求。

  • 异步非阻塞: 客户端发送请求给服务端,此时服务端处理任务时间很久,这个时候的任务虽然处理时间会很久,但是客户端可以做其他的任务,因为他是异步的,可以在回调函数里处理响应;同时服务端是非阻塞的,所以服务端可以去处理其他的任务,如此,这个模式就显得非常的高效了。

    进程模型架构图

    image-20240826102647762

    主要分为两个进行模块

    image-20240826101707174

  • master: 主进程,领导者,数量为1

    管理worker,如果worker异常停止master则会重新启动,一般master发送信号到worker服务

    ./nginx -s stop
    ./nginx -s quit
    ./nginx -s reload
    # 检查修改配置文件是否正确
    ./nginx -t
    
  • worker:工作进程,为领导者服务,默认数量为1

    可以修改,在nginx.conf文件中,修改worker_processes即可,重新加载nginx后发现worker数量已经修改

    # 检查修改配置文件是否正确
    nginx -t 
    # 重新加载
    nginx -s reload
    

    image-20240826102123496

  • worker数量设置

    nginx的worker进程数量通常设置为与服务器的CPU核心数量相等。如果你的服务器有多个CPU或者超线程(HT)技术,通常推荐设置为CPU核心数的2倍,或者如果你的应用是CPU密集型的,那么worker数可以设置为CPU核心数的1.5-2倍。

    设置worker进程数量的指令是worker_processes,在Nginx配置文件中(通常是nginx.conf),你可以找到或添加这样的行:

    # 设置为auto会让Nginx自动检测CPU核心数量。
    worker_processes auto; # 或者具体的CPU核心数量
    # 假设你的服务器有4个CPU核心,如果你想手动指定,可以替换为具体的数字,例如:
    worker_processes 4; 
    

3.2 nginx处理web请求

3.2.1 nginx的worker的抢占机制

nginx的worker的抢占机制处理流程图:

image-20240826103200932

处理过程具体如下:

  • 服务启动,首先创建(fork)三个worker进程
  • client发起请求,三个worker发起争抢,此处使用互斥锁(锁与client是对应的),worker1抢到,则2,3则不进行处理
  • worker1完整处理好请求,返回客户端响应数据,则释放锁信息
3.2.2 服务器处理机制对比

传统服务器的事件处理流程图:

image-20240826103828351

处理过程如下:

  • master创建多个worker
  • client1请求worker1但是请求阻塞了,client2,3则不可以进行处理,则需要worker2进行处理
  • 如果请求特别耗时,并且请求量大,则需要很多worker进行处理

nginx服务器事件处理流程图:

image-20240826104301408

处理过程如下:

  • master创建多个worker,接收服务请求

  • client1发送请求到worker1,发现阻塞了,client2来了,没有关系,worker使用的是epoll异步模型,多路复用,不会阻塞,可以先处理client2,3请求

  • 一个worker一般可以处理6~8万个请求,在nginx.conf配置文件中,可以配置worker的连接模型以及连接数,默认为1024

    image-20240826104831307

3.3 nginx 配置文件结构

nginx结构图如下:

image-20240826105016026

具体配置文件结构格式如下配置文件所示

# 设置worker进程的用户,指的linux中的用户,会涉及到nginx操作目录或文件的一些权限,默认为nobody
user root;
# worker进程工作数设置,一般来说CPU有几个,就设置几个,或者设置为N-1也行
worker_processes  2;
# nginx 日志级别debug | info | notice | warn | error | crit | alert | emerg,错误级别从左到右越来越大
error_log  logs/error.log  notice;
# 设置nginx进程 pid
pid		logs/nginx.pid;

# 设置工作模式
events {
    # 默认使用epoll
    use epoll;
    # 每个worker允许连接的客户端最大连接数
    worker_connections  1024*10;
}

# http 是指令块,针对http网络传输的一些指令配置
http {
    # include 引入外部配置,提高可读性,避免单个配置文件过大
    # 也可以导入其他server信息,将server信息设置为单个server.conf文件,进行导入 include server1.conf
    include       mime.types;
    # 设定日志格式,main 为定义的格式名称,如此 access_log 就可以直接使用这个变量了
	log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';
    # sendfile使用高效文件传输,提升传输性能。启用后才能使用tcp_nopush,是指当数据表累积一定大小后才发送,提高了效率。
    sendfile        on;
    tcp_nopush      on;
    # gzip启用压缩,html/js/css压缩后传输会更快
    gzip 			on;
    # default_type 指令用来配置 Nginx 响应前端请求默认的 MIME 类型。默认是 text 文本。
    default_type  application/octet-stream;
    # keepalive_timeout设置客户端与服务端请求的超时时间,保证客户端多次请求的时候不会重复建立新的连接,节约资源损耗。
    keepalive_timeout  65;
    # server可以在http指令块中设置多个虚拟主机
    server {
    	# 监听端口
        listen       80;
    	# localhost、ip、域名
        server_name  localhost;
    	# 请求路由映射,匹配拦截
        location / {
    		# 请求位置
            root   html;
    		# 首页设置
            index  index.html index.htm;
        }
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
	server ......
}

日志参数配置详情:

参数名参数意义
$remote_addr客户端ip
$remote_user远程客户端用户名,一般为:’-’
$time_local时间和时区
$request请求的url以及method
$status响应状态码
$body_bytes_send响应客户端内容字节数
$http_referer记录用户从哪个链接跳转过来的
$http_user_agent用户所使用的代理,一般来时都是浏览器
$http_x_forwarded_for通过代理服务器来记录客户端的ip

3.4 pid打开失败处理

偶尔执行nginx命令的时候会提示 pid没有等问题,具体解决方式如下所示

image-20240827085855164

  • 执行 ./nginx -s reload 提示 /var/run/nginx/nginx.pid failed 没有那个文件或者目录, 我们则重新创建对应目录即可

    mkdir /var/run/nginx
    
  • 执行 ./nginx -s reload 发现提示我们 invalid PID number in /var/run/nginx/nginx.pid ,我们则手动指定nginx.conf配置文件即可

    # 配置nginx配置文件目录
    ./nginx -c /usr/local/nginx/conf/nginx.conf
    # 重启nginx
    ./nginx -s reload
    

3.5 nginx常用命令

  • 关闭命令

    # 快速关闭
    ./nginx -s stop
    # 优雅停止,执行完用户请求再停止,针对http请求
    ./nginx -s quit
    
  • 配置文件修改检查命令

    # 检查配置文件修改是否正确
    ./nginx -t
    
  • 检查版本号

    # 版本信息
    ./nginx -v
    # 具体信息包含版本信息
    ./nginx -V
    
  • 帮助命令

    # 帮助命令
    ./nginx -h
    ./nginx -?
    
  • 指定自定义配置文件

    ./nginx -c /usr/local/nginx/conf/nginx.conf
    

3.6 日志备份切割

3.6.1 手动切割

正常以天作为切割单位,创建一个shell可执行文件:cut_my_log.sh,内容为:

#!/bin/bash
LOG_PATH="/var/log/nginx/"
# 获取昨天日期时间
RECORD_TIME=$(date -d "yesterday" +%Y-%m-%d+%H:%M)
PID=/var/run/nginx/nginx.pid
mv ${LOG_PATH}/access.log ${LOG_PATH}/access.${RECORD_TIME}.log
mv ${LOG_PATH}/error.log ${LOG_PATH}/error.${RECORD_TIME}.log

cut_my_log.sh添加可执行的权限:

# 添加执行权限
chmod +x cut_my_log.sh
# 执行切割
./cut_my_log.sh
3.6.2 自动切割

自动切割日志需要使用定时任务,需要安装定时任务

yum install crontabs

使用crontab -e 编辑并且添加一个新的定时任务

crontab -e
# 编辑内容新增如下内容:
*/1 * * * * /usr/local/nginx/sbin/cut_my_log.sh
# 退出后重启定时模块
service crond restart

crontab常用命令如下:

命令作用
service crond start启动服务
service crond stop关闭服务
service crond restart重启服务
service crond reload重新载入配置
crontab -e编辑任务
crontab -l查看任务列表

cron表达式是,分为5或6个域,每个域代表一个含义,如下所示:

星期
取值范围0-590-231-311-121-72019、2020…

常用表达式如下:

  • 每分钟 */1 * * * *
  • 每日凌晨 59 23 * * *
  • 每日凌晨1点 0 1 * * *

3.7 搭建静态资源服务器

上传前端服务dist以及一个mp3文件到服务器目录

image-20240826142316953

开始配置nginx.conf配置文件

# 我使用的是root用戶操作,所以需要修改use属性
use root;

# 在nginx.conf的http模块下,引入静态资源conf
include static.conf

image-20240826151125869

编辑 static.conf

server {
    listen       90;
    server_name  localhost;
    # 资源源码
    location / {
        root   /root/nginx/dist;
        index  index.html;
    }
    # 最后拼接的路径为 /root/nginx,location后面路径会拼接到root地址后面
    location /nginx {
        root   /root/;
    }
}

最后进行访问 http://192.168.138.129:90/

image-20240826151200312
image-20240826151225458

也可以使用別名进行设置

server {
    listen       90;
    server_name  localhost;
    # 资源源码
    location / {
        root   /root/nginx/dist;
        index  index.html;
    }
    # 使用别名访问,当访问/static时候,会转发到alias路径
    location /static {
        # root   /root/;
        alias /root/nginx;
    }
}

再次访问 http://192.168.138.129:90/static/gwr.mp3 结果如下所示

image-20240826151903644

3.8 Gzip提高请求效率

开启 gzip 压缩功能,提高传输效率,提高带宽,gzip与server平级

# 开启gzip
gizp on
# 限制最小压缩,小于1个字节文件不会被压缩
gzip_min_length 1;
# 设置压缩级别(压缩比,文件越大压缩越多,但是cpu会占用过多)
gzip_comp_level 3;
# 压缩类型
gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-http-php image/jpeg image/gif image/png application/json;

image-20240826153610016

3.9 location配置

3.9.1 locaton匹配规则
  • 前缀匹配

    前缀匹配:默认的匹配方式,不带修饰符,匹配 URI 的前缀
    location /api {
        # 处理 /api 及其子路径的请求
    }
    
  • 精准匹配 =

    location = / {
        root   html;
        index index.html;
    }
    # = 具体某一个文件,最终访问路径 ip:port/root/nginx/gwr.mp3
    location = /nginx/gwr.mp3 {
        root   /root;
    }
    
  • 正则表达式

    # `~*` 正则表达式不区分大小写,访问路径 ip:port/root/nginx/xxx.mp3|xxx.jpg|xxx.jpeg
    location ~* \.(mp3|png|jpg|jpeg) {
        root   /root/nginx;
    }
    # `~` 正则表达式区分大小写
    location ~ \.(mp3|png|jpg|jpeg) {
        root   /root/nginx;
    }
    # `^~` 正则表达式以某个字符开头请求,请求路径为 ip:port/root/nginx/xxx.mp3 ......
    location ^~ /nginx {
        root   /root;
    }
    
  • 目录匹配

    # 以斜杠 / 结尾的匹配模式,用于匹配特定的目录。
    location /images/ {
        # 处理 /images/ 目录下的请求
    }
    

    location /images/其匹配规则如下:
    精确匹配:如果请求路径完全匹配 /images/,则会进入该 location 块。
    前缀匹配:如果请求路径以 /images/ 开头,则也会进入该 location 块。

    具体来说,以下几种情况都会匹配到 location /images/:

    • /images/
    • /images/image1.jpg
    • /images/subdir/image2.png

    因此,location /images/ 要求请求路径必须以 /images/ 开头,但不一定是完全相同的路径,以我们公司测试环境为例,页面请求路径信息如下所示

    http://ip:8901/queryModel/query/launderMoneyCustomer/countData
    

    image-20240829085609816

    对应的nginx配置信息如下,其接收客户端以/queryModel/ 为开始的请求,根据规则匹配转发到 http://ip:11200/dics/demo/queryModel/,此路径为网关地址,后期网关会解析此访问路径

    具体的nginx.conf主配置如下:

    # 用户配置,指定运行 Nginx 的用户
    user  root;
    
    # 设置工作进程数,自动根据系统核心数来决定
    worker_processes  auto;
    
    # 启用正则表达式的 JIT 编译,以加快处理速度
    pcre_jit on;
    
    # 错误日志配置,只记录警告及以上级别的错误
    error_log  logs/error.log warn;
    # PID 文件位置
    pid        logs/nginx.pid;
    
    # 事件模块配置
    events {
        # 每个工作进程的最大并发连接数
        worker_connections  65535;
    }
    
    # HTTP 部分配置
    http {
        # 包含 MIME 类型文件
        include       mime.types;
        # 默认 MIME 类型
        default_type  application/octet-stream;
    
        # 分别配置main,json两种日志格式配置,后面方便使用
        log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                          '$status $body_bytes_sent "$http_referer" '
                          '"$http_user_agent" "$http_x_forwarded_for"';
    
        # JSON 格式的日志格式
        log_format json escape=json
          '{"@timestamp":"$time_iso8601",'
          '"host":"$hostname",'
          '"server_ip":"$server_addr",'
          '"client_ip":"$remote_addr",'
          '"xff":"$http_x_forwarded_for",'
          '"domain":"$host",'
          '"url":"$uri",'
          '"referer":"$http_referer",'
          '"args":"$args",'
          '"upstreamtime":"$upstream_response_time",'
          '"responsetime":"$request_time",'
          '"request_method":"$request_method",'
          '"status":"$status",'
          '"size":"$body_bytes_sent",'
          '"request_length":"$request_length",'
          '"protocol":"$server_protocol",'
          '"upstreamhost":"$upstream_addr",'
          '"upstreamtime":"$upstream_response_time",'
          '"upstreamstatus":"$upstream_status",'
          '"file_dir":"$request_filename",'
          '"http_user_agent":"$http_user_agent"'
        '}';
    
        # 访问日志配置,使用 JSON 格式
        access_log  logs/access.log  json;
    
        # 启用 sendfile 优化
        sendfile        on;
    
        # TCP 无推送选项(已注释)
        # tcp_nopush     on;
    
        # 保持连接的超时时间
        keepalive_timeout  120;
    
        # 启用 gzip 压缩(已注释)
        # gzip  on;
    
        # FastCGI 缓冲区大小 固定配置即可
        fastcgi_buffer_size 128k;
        fastcgi_buffers 8 128k;
        fastcgi_busy_buffers_size 128k;
        fastcgi_temp_file_write_size 128k;
    
        # 客户端请求头缓冲区大小 固定配置即可
        client_header_buffer_size 128k;
        # 客户端请求体缓冲区大小 固定配置即可
        client_body_buffer_size 4m;
        # 允许请求头中包含下划线 固定配置即可
        underscores_in_headers on;
        
        # 定义一个服务器块
        server {
            # 监听端口 8000
            listen       8000;
            # 服务器名称
            server_name localhost;
            
        	# 处理 /vts_metrics 请求,非必要配置
            location /vts_metrics {
                # 显示虚拟主机流量状态
                vhost_traffic_status_display;
                # 设置显示格式为 HTML
                vhost_traffic_status_display_format html;
            }
            # 处理 /sts_metrics 请求,非必要配置
            location /sts_metrics {
                # 显示流媒体服务器流量状态
                stream_server_traffic_status_display;
                # 设置显示格式为 HTML
                stream_server_traffic_status_display_format html;
            }
        }
        # 包含其他虚拟主机配置文件
        include vhosts/*.conf;
    }
    
    

    具体的转发规则在nginx.conf同目录的/vhosts目录下如下,其中一个credit.conf的内容如下:

    # 定义一个服务器块
    server {
        # 监听端口 8901 上的 IPv4 连接
        listen       8901;
        # 监听端口 8901 上的 IPv6 连接
        listen  [::]:8901;
        
        # 设置服务器名称,用于虚拟主机区分
        server_name  localhost;
        
        # 设置默认文档根目录
        root  html/front-credit;
        # 指定默认索引文件
        index  index.html index.htm;
    
        # 处理 /download 路径下的请求
        location /download {
            # 设置索引文件
            index  index.html index.htm;
            # 设置文档根目录为 /data/htdocs
            root /data/htdocs;
        }
        
        # 处理 /queryModel/ 路径下的请求,有多个模块,除路径其余基本相同,此处只记录一个
        location /queryModel/ {
            # 将请求代理到后端服务器
            proxy_pass http://ip:11200/dics/demo/queryModel/;
            # 关闭自动重定向
            proxy_redirect off;
            
            # 设置代理请求头
            proxy_set_header HOST $host;  # 设置 Host 头为客户端请求中的 Host
            proxy_set_header X-Real-IP $remote_addr;  # 设置 X-Real-IP 头为客户端的真实 IP 地址
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;  # 设置 X-Forwarded-For 头为客户端的真实 IP 地址(如果经过多个代理)
            
            # 使用 HTTP/1.1 版本进行代理
            proxy_http_version 1.1;
            # 设置代理请求头 Connection 为 "Keep-Alive"
            proxy_set_header Connection "Keep-Alive";
            
            # 设置代理相关的超时时间
            proxy_connect_timeout   60;  # 建立连接的超时时间
            proxy_send_timeout      120;  # 发送数据的超时时间
            proxy_read_timeout      120;  # 接收数据的超时时间
        }
        
        # 设置访问日志文件的位置和格式
        access_log  logs/dics-credit.log json;
    }
    
    

    gateway网关获取到请求信息,进行路径信息切割替换,最终转发到query模块后端服务,gateway具体的配置参数如下表所示

    image-20240829090120337

    我们测试环境还有另一个前端服务配置信息如下,此处记录一下方便日后复习:

    # 定义一个服务器块(server block)
    	server {
    	    # 监听端口8905上的IPv4连接
    	    listen       8905;
    	    # 同时监听端口8905上的IPv6连接
    	    listen  [::]:8905;
    	    
    	    # 设置服务器名称,用于虚拟主机区分
    	    server_name  localhost;
    	    
    	    # 设置默认文档根目录
    	    root   html/front-clm;
    	    # 指定默认索引文件
    	    index  index.html index.htm;
    	
    	    # 定义一个位置块(location block),处理以"/api/"开头的所有请求
    	    location /api/ {
    	        # 将请求代理到后端服务器
    	        proxy_pass http://xxx.xxx.xxx.xxx:18602/;
    	        # 关闭自动重定向
    	        proxy_redirect off;
    	        
    	        # 设置代理请求头
    	        proxy_set_header HOST $host;  # 设置Host头为客户端请求中的Host
    	        proxy_set_header X-Real-IP $remote_addr;  # 设置X-Real-IP头为客户端的真实IP地址
    	        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;  # 设置X-Forwarded-For头为客户端的真实IP地址(如果经过多个代理)
    	        
    	        # 使用HTTP/1.1版本进行代理
    	        proxy_http_version 1.1;
    	        # 设置代理请求头Connection为"Keep-Alive"
    	        proxy_set_header Connection "Keep-Alive";
    	        
    	        # 设置代理相关的超时时间
    	        proxy_connect_timeout   60;  # 建立连接的超时时间
    	        proxy_send_timeout      120;  # 发送数据的超时时间
    	        proxy_read_timeout      120;  # 接收数据的超时时间
    	    }
    	    
    	    # 设置访问日志文件的位置和格式
    	    access_log  logs/dics-clm.log json;
    	}
    

    由上面的配置逻辑,我们可以整理出具体的请求逻辑如下:

    1. 客户端发起请求 http://ip:8901/queryModel/query/launderMoneyCustomer/countData 到nginx服务
    2. nginx服务匹配 /queryModel/路径转发到网关,请求变为 http://ip:11200/dics/demo/queryModel/query/launderMoneyCustomer/countData
    3. 请求网关根据切割要求切割/dics/demo/queryModel,请求变为 http://query-server:port/query/launderMoneyCustomer/countData,其中query-server为gateway获取注册到nacos上的服务名称
3.9.2 location 的优先级

当有多个 location 块匹配同一个请求时,nginx 会根据以下规则来确定使用哪个 location 块:

  1. 首先检查是否有精确匹配 (=)。

  2. 如果没有,检查是否有带有正则表达式的匹配 (~ ~*),并使用第一个匹配的规则。

  3. 如果没有正则表达式匹配,则使用最长的前缀匹配。

3.9.3 location 的应用场景

location 块可以用于多种场景,以下是一些例子:

  • 静态资源服务

    这个 location 块用于服务 /usr/share/nginx/html/static/ 目录下的静态文件

    # 访问/static/目录信息转发到别名路径下,获取静态资源
    location /static/ {
        alias /usr/share/nginx/html/static/;
    }
    
  • 代理转发

    所有以 /api/ 开头的请求都会被代理到后端服务器,我们配合

    # 定义一个名为 tomcats 的 upstream,用于负载均衡多个后端服务器
    upstream tomcats {
        # 添加三个后端服务器地址
        server 192.168.138.129:8081;
        server 192.168.138.129:8082;
        server 192.168.138.129:8083;
    }
    
    # 配置一个 Nginx 服务器块
    server {
        # 监听 8080 端口
        listen       8080;
        # 设置服务器名称
        server_name  localhost;
    
        # 配置 location 块来处理根路径的请求
        location / {
            # 将请求代理到前面定义的 tomcats 上游服务器组
            proxy_pass http://tomcats;
        }
    }
    
  • 错误页面重定向

    当发生 404 错误时,Nginx 会重定向到 /404.html 页面

    # 当发生 404 错误时,返回 /404.html 页面
    error_page 404 /404.html;
    
    location = /404.html {
        # 指定 404 页面的根目录为 /usr/share/nginx/html
        root /usr/share/nginx/html;
        # 该 location 块仅对内部重定向有效,外部请求无法直接访问这个路径
        internal;
    }
    
  • 基于请求方法的处理

    根据请求方法的不同,将请求重写到不同的 location块进行处理。

    location /api {
        if ($request_method = POST) {
            # 如果请求方法是 POST,则重写请求路径到 /api/post
            rewrite ^ /api/post last;
        }
    }
    
    location /api/post {
        # 处理 POST 请求
    }
    
  • 限制访问

    这个 location 块限制只有来自特定 IP 范围的请求才能访问 /restricted/ 路径。

    location /restricted/ {
        # 允许来自 192.168.138.0/24 子网的请求访问该路径(192.168.138.1~192.168.138.254)
        allow 192.168.138.0/24;
    
        # 拒绝所有其他客户端的请求
        deny all;
    }
    
3.9.4 location 的嵌套

location 块可以嵌套,这意味着你可以在一个 location 块内部定义另一个 location 块。这通常用于对特定的路径进行更细粒度的控制

在这个例子中,/admin 路径下的请求首先匹配外层的 location /,然后进一步匹配内层的 location /admin,如果请求的文件以 .php 结尾,则还会匹配最内层的 location ~ .php$。

location / {
    # 默认处理
    location /admin {
        # 对 /admin 路径的特殊处理
        location ~ \.php$ {
        	# 对 /admin 路径下 PHP 文件的处理
        }
    }
}
3.9.5 location的指令

在 location 块内部,你可以使用各种指令来控制请求的处理方式,例如:

  1. proxy_pass:将请求代理到后端服务器。

  2. rewrite:重写请求的 URI。

  3. try_files:尝试不同的文件或路径,直到找到一个存在的。

  4. root 和 alias:设置请求文件的基本目录。

  5. index:指定目录索引文件。

  6. autoindex:启用或禁用目录列表。

  7. error_page:定义错误页面。

  8. auth_basic 和 auth_basic_user_file:设置 HTTP 基本认证

下面我们编写一个示例配置文件:

server {
    # listen 80;:指定 Nginx 监听 HTTP 请求的端口号,这里是 80 端口,即标准的 HTTP 端口。
    listen 80;

    # 定义服务器名,当客户端请求的Host与这个名称匹配时,就会使用这个server块的配置。
    server_name example.com;

    # 设置网站的根目录,所有未命名的 location 块(即默认的 location /)都会从这个目录下寻找资源
    root /var/www/html;

    # 这个 location 块精确匹配根路径 /,并且配置了 index index.html;,这意味着当访问根路径时,Nginx 会自动寻找 /var/www/html 目录下的 index.html 文件来响应请求。
    location = / {
        # 设置默认索引文件为 index.html
        index index.html;
    }

    # 这个 location 块用于处理所有以 /static/ 开头的请求
    location /static/ {
        # 将请求的 URI 替换为指定的路径,也就是说,所有对 /static/ 的请求都会映射到实际的目录 /var/www/static/
        alias /var/www/static/;
    }

    # 代理到后端应用服务器,这个 location 块用于处理所有以 /api/ 开头的请求。
    location /api/ {
        # 将所有匹配的请求代理到名为 backend_server 的后端服务器。通常,backend_server 需要在 http 或 upstream 块中定义
        proxy_pass http://backend_server;

        # 设置代理请求的 Host 头部为客户端的原始请求中的 Host 值。
        proxy_set_header Host $host;
        # 设置 X-Real-IP 头部为客户端的 IP 地址。
        proxy_set_header X-Real-IP $remote_addr;
        # 设置 X-Forwarded-For 头部,这是一个用于标识请求来源的链式头部,可以追踪请求穿过多个代理的路径
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        # 设置 X-Forwarded-Proto 头部为请求使用的协议(http 或 https)
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    # 这个 location 块使用正则表达式匹配所有以 .php 结尾的文件
    location ~ \.php$ {
        # 包含一个外部配置文件,通常这个文件包含了处理 PHP 文件所需的 FastCGI 参数
        include snippets/fastcgi-php.conf;

        # 指定 FastCGI 传递的目标,这里是 PHP-FPM 监听的 Unix Socket 文件
        fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
    }

    # 定义当发生 404 错误时,Nginx 应该返回哪个页面
    error_page 404 /404.html;

    # 这个 location 块精确匹配 /404.html 路径
    location = /404.html {
        # 设置 /404.html 文件的根目录,因为这是一个内部重定向,所以需要明确指定根目录。
        root /var/www/html;

        # 标记这个 location 块只能从内部重定向访问,而不能直接通过外部请求访问
        internal;
    }
}

3.10 DNS域名解析

具体解析流程参考如下:

image-20240826161732259

用户请求到后端服务的过程参考如下

image-20240826161631992

后续可以本地修改hosts文件,也可以使用工具switch-hosts进行修改

4. nginx进阶知识

4.1 nginx跨域

跨域如何发生的,我本地打开浏览器访问慕课网,在慕课网中操作,发起ajax请求,访问网站网址都是www.imooc.com开头,没有跨域问题,但是现在我发起了一个访问淘宝的请求,此时发生跨域问题,因为请求地址前缀修改为www.tabobao.com。

image-20240827084509120

我们需要实现CORS跨域共享(Corss-Origin Resource Sharing),允许浏览器向夸Origin的服务器发起js请求获取资源信息,具体的实现方式如下

  • Jsonp
  • SpringBoot Cors
  • Nginx

使用nginx进行跨域配置

server {
    listen       90;
    server_name  localhost;

    #允许跨域请求的域,*代表所有
    add_header 'Access-Control-Allow-Origin' *;
    #允许带上cookie请求
    add_header 'Access-Control-Allow-Credentials' 'true';
    #允许请求的方法,比如 GET/POST/PUT/DELETE
    add_header 'Access-Control-Allow-Methods' *;
    #允许请求的header
    add_header 'Access-Control-Allow-Headers' *;

    # 资源源码
    location / {
        root   /root/nginx/dist;
        index  index.html;
    }
    # 使用别名访问,当访问/static时候,会转发到alias路径
    location /static {
        # root   /root/;
        alias /nginx/root/;
    }
}

这段代码与springboot代码功能相似,SpringBoot实现如下:

/**
 * 设置跨域配置信息
 */
@Bean
public CorsFilter corsFilter() {
    CorsConfiguration corsConfiguration = new CorsConfiguration();
    // 允许所有来源的跨域请求
    corsConfiguration.addAllowedOrigin("*");
    // 允许发送凭证(cookies等)
    corsConfiguration.setAllowCredentials(true);
    // 允许所有请求方法(GET, POST, PUT, DELETE等)
    corsConfiguration.addAllowedMethod("*");
    // 允许所有请求头
    corsConfiguration.addAllowedHeader("*");
    // 暴露所有头部信息
    corsConfiguration.addExposedHeader("*");
    UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource();
    // 将跨域配置信息应用到所有路径
    configSource.registerCorsConfiguration("/**", corsConfiguration);
    return new CorsFilter(configSource);
}

4.2 静态资源防盗链

可以验证发起请求的请求域名是否复核要求,符合要求则继续向下进行请求,否则返回 404

server {
    listen       90;
    server_name  localhost;

    # 允许跨域请求的域,*代表所有
    add_header 'Access-Control-Allow-Origin' *;
    # 允许带上cookie请求
    add_header 'Access-Control-Allow-Credentials' 'true';
    # 允许请求的方法,比如 GET/POST/PUT/DELETE
    add_header 'Access-Control-Allow-Methods' *;
    # 允许请求的header
    add_header 'Access-Control-Allow-Headers' *;

    # 资源防盗链,对源站点验证,只有xxx.com后缀域名发起请求才能通过验证
    valid_referers *.xxx.com; 
    # 非法引入会进入下方判断
    if ($invalid_referer) {
        # 自定义码
        return 409;
    }
    
    # 资源源码
    location / {
        root   /root/nginx/dist;
        index  index.html;
    }
    # 使用别名访问,当访问/static时候,会转发到alias路径
    location /static {
        # root   /root/;
        alias /nginx/root/;
    }
}

因为域名不匹配,原有地址访问mp3资源现在已经不能进行访问了 http://192.168.138.129:90/static/gwr.mp3

image-20240827091123440

4.3 nginx模块化体系

主要模块如下图所示:

image-20240827091932911

具体模块执行作用:

  • event module: 事件机制,操作系统执行机制默认epoll模式
  • phase handler: 处理客户端的一些请求,还要处理响应内容的响应
  • out filter: 在phase handler处理之后,把内容进行一些自己处理过滤,再响应到浏览器端,比如gzip
  • upstream: 反向代理模块,将真正的请求转发到真实的服务器地址去响应真实的内容
  • load balancer: 负载均衡器,实现集群,实现负载均衡算法等
  • extend module: 集成模块,实现第三方内容模块

4.4 网络模型

Nginx负载均衡的时候,其实Nginx是七层负载均衡,后续我们还会涉及到LVS,是四层负载均衡,七层和四层是什么概念呢?这就必须提到网络模型。网络模型是计算机网络基础的一部分内容,一般大学计算机系都会讲到此知识点,并且会作为考点;其实在面试过程中有时候也会被问到。所以我们还是有必要来复习或学习一下这块的一些重要知识的。

网络模型就是 OSI(Open System Interconnect),意思为开放网络互联,是由国际标准化组织(ISO)和国际电报电话咨询委员会(CCITT)共同出版的,他是一种网络互联模型,也是一种规范。

网络模型分为七层,也就是当用户发起请求到服务器接收,会历经七道工序,或者说用户利用互联网发送消息给另一个用户,也会历经七道工序。这七层可以分为如下:

层级名称说明
第七层应用层与用户行为交互
第六层表示层定义数据格式以及数据加密
第五层会话层创建、管理以及销毁会话
第四层传输层创建、管理请求端到响应端(端到端)的连接
第三层网络层请求端的IP地址
第二层数据链路层提供介质访问与链路管理
第一层物理层传输介质,物理媒介

以上七层每层可以与上下相邻层进行通信。每一层都是非常复杂的,我们不在这里深究,我们以举例的形式来阐述每一层是干嘛的。

  • 应用层

    这是面向用户的,最靠近用户,为了让用户和计算机交互,在计算机里会有很多软件,比如eclipse,idea,qq,nginx等,这些都是应用软件,用户可以通过这些应用软件和计算机交互,交互的过程其实就是接口的调用,应用层为用户提供了交互的接口,以此为用户提供交互服务。那么在这一层最常见的协议有:HTTP,HTTPS,FTP,SMTP,POP3等。Nginx在本层,为七层负载均衡。

    举例:我要寄一封信给远在天边的老外LiLei,我会打开快递软件下单,这个时候我是用户,快递软件就是应用服务,是建立在计算机上的,提供给用户交互的一种服务或称之为手段。

  • 表示层

    该层提供数据格式编码以及加密功能,确保请求端的数据能被响应端的应用层识别。

    举例:我写中文给LiLei,他看不懂,这个时候我就会使用翻译软件把中文翻译成英文,随后信中涉及到一些比较隐私的信息我会加密一下,这个时候翻译软件和加密器就充当了表示层的作用,他用于显示用户能够识别的内容。

  • 会话层

    会话可以理解为session,请求发送到接受响应的这个过程之间存在会话,会话层就充当了这一过程的管理者,从创建会话到维护会话最后销毁会话。

    举例:我每次写信给LiLei都会记录在一个小本本上,寄信时间日期,收信时间日期,这本小本本上存有每次通信记录,这个小本本就相当于是一个会话的管理者。又或者说,我们平时在打电话,首先需要拨打电话,这是建立会话,对方接听电话,此时正在通话(维持并管理会话),通话结束后会话销毁,那么这也是一次会话的生命周期。

  • 传输层

    该层建立端到端的连接,他提供了数据传输服务,在传输层通信会涉及到端口号,本层常见的协议为TCP、UDP,LVS就是在传输层,也就是四层负载均衡。

    举例:我和LiLei通信过程中会借助快递公司,快递公司会分配快递员取件和寄件,那么这个快递员则充当传输层的作用。

  • 网络层

    网络通信的时候必须要有本机IP和对方的IP,请求端和响应端都会有自己的IP的,IP就相当于你家地址门牌号,在网络上云服务器有固定的公网IP,普通计算机也有,只不过是动态IP,运营商每天会分配不同的IP给你的计算机。所以网络层也能称之为IP层,IP是互联网的基础根本。能提供IP分配的设备则为路由器或交换机。

    举例:对于拥有固定IP的云服务来说,他们都是由腾讯云、阿里云等这样的供应商提供的,他们为云服务器提供固定ip;电信、移动、联调等运营商为你的计算机动态分配ip,每天都不同;则这些供应商和运营商都是网络层。同理,快递员由物流公司分配和管理,那么物流公司就是网络层咯。

  • 数据链路层

    这一层会提供计算机MAC地址,通信的时候会携带,为了确保请求投递正确,所以他会验证检测MAC地址,以确保请求响应的可靠性。

    举例:快递员在投递派送的时候,他(或客服)会预先提前打电话给你,确认你家地址对不对、有没有人、货到付款有没有准备好钱等等,这个时候快递员(或客服)就充当了数据链路层的职责。

  • 物理层

    端到端请求响应过程中的媒介,物理介质,比如网线、中继器等等设备,都是你在端到端交互过程中不可缺少的基础设备。

    举例:快递员在投递的过程中,你写的信会历经一些交通运输工具,比如首先通过飞机运输到国外,在海关统一拿到信以后会通过汽车运输到LiLei所在城市的物流集散地,最后快递员通过三轮电频车寄到LiLei家里,这个时候,飞机、汽车、三轮电瓶车都是物理层的媒介。
    以上就是七层网络模型,大家理解其意义即可。需要注意的是Nginx存在于第七层,属于七层负载均衡;而第四层会有LVS,属于四层负载均衡。而关于七层和四层的区别我会在下一节来说一说。

4.5 集群负载均衡

4.5.1 基础环境

负载均衡图逻辑图:

image-20240827094442426

我们使用tomcat构建集群进行负载集群测试,三个tomcat服务使用不同端口号,在同一服务器上分别是

  • tomcat1 http://192.168.138.129:8081/
  • tomcat2 http://192.168.138.129:8082/
  • tomcat3 http://192.168.138.129:8083/

我们使用后docker进行启动服务,分别启动启动三台tomcat服务

docker run --name tomcat1 -it -d -p 8081:8080 tomcat:8.5.32
docker run --name tomcat2 -it -d -p 8082:8080 tomcat:8.5.32
docker run --name tomcat3 -it -d -p 8083:8080 tomcat:8.5.32

image-20240827100753478

访问地址tomcat首页信息http://192.168.138.129:8081/ ~ http://192.168.138.129:8083/

image-20240827100831282

修改nginx.conf配置文件,我们将配置配在新的tomcat.conf中,复制原有的static.conf,并且在nginx.confincloud tomcat.conf

# 定义一个名为 tomcats 的 upstream,用于负载均衡多个后端服务器
upstream tomcats {
    # 添加三个后端服务器地址
    server 192.168.138.129:8081;
    server 192.168.138.129:8082;
    server 192.168.138.129:8083;
}

# 配置一个 Nginx 服务器块
server {
    # 监听 8080 端口
    listen       8080;
    # 设置服务器名称
    server_name  localhost;

    # 配置 location 块来处理根路径的请求
    location / {
        # 将请求代理到前面定义的 tomcats 上游服务器组
        proxy_pass http://tomcats;
    }
}

我们通过新配置的tomcat地址进行访问,http://192.168.138.129:8080/

image-20240827102619240

4.5.2 轮训策略
  • 默认请求策略轮训,不需要配置即生效

    image-20240827104237854

  • 加权重轮训,根据服务器节点配置,进行权重分配

    image-20240827104601877

    具体配置非常检点,既在upstream 配置server后面加上weight即可,权重weight默认都为1,权重越小,服务获取流量越小

    # 定义一个名为 tomcats 的 upstream,用于负载均衡多个后端服务器
    upstream tomcats {
        # 添加三个后端服务器地址
        server 192.168.138.129:8081 weight=1;
        server 192.168.138.129:8082 weight=2;
        server 192.168.138.129:8083 weight=5;
    }
    

    upstream还有其他指令参数如下

    • max_conns 现在每台server连接数

      # worker进程设置1个,便于测试观察成功的连接数
      worker_processes  1;
      
      upstream tomcats {
          # 添加三个后端服务器地址
          server 192.168.138.129:8081 max_conns=2;
          server 192.168.138.129:8082 max_conns=2;
          server 192.168.138.129:8083 max_conns=2;
      }
      
    • slow_start 慢启动,此配置为商业版配置,需要付费使用

      upstream tomcats {
          # 添加三个后端服务器地址,设置该服务器的慢启动时间为 60 秒。在这段时间内,服务器将逐渐增加接收的请求量。
          server 192.168.138.129:8081 weight=2 slow_start=60s;
          server 192.168.138.129:8082 weight=2;
          server 192.168.138.129:8083 weight=2;
      }
      
    • down 用于标记服务不可用

      upstream tomcats {
          # 添加三个后端服务器地址
          server 192.168.138.129:8081 down;
          server 192.168.138.129:8082 max_conns=2;
          server 192.168.138.129:8083 max_conns=2;
      }
      
    • backup 表示当前服务器节点是备用机,只有在其他的服务器都宕机以后,自己才会加入到集群中,被用户访问到:

      upstream tomcats {
          # 添加三个后端服务器地址
          server 192.168.138.129:8081 backup;
          server 192.168.138.129:8082 max_conns=2;
          server 192.168.138.129:8083 max_conns=2;
      }
      

      注意backup参数不能使用在hashrandom load balancing

    • max_fails:表示失败几次,则标记server已宕机,剔出上游服务。fail_timeout:表示失败的重试时间。

      # 则代表在15秒内请求某一server失败达到2次后,则认为该server已经挂了或者宕机了,随后再过15秒,这15秒内不会有新的请求到达刚刚挂掉的节点上,
      # 而是会请求到正常运作的server,15秒后会再有新请求尝试连接挂掉的server,如果还是失败,重复上一过程,直到恢复。
      upstream tomcats {
          # 添加三个后端服务器地址
          server 192.168.138.129:8081 backup;
          server 192.168.138.129:8082 max_conns=2 max_fails=2 fail_timeout=15s;
          server 192.168.138.129:8083 max_conns=2 max_fails=2 fail_timeout=15s;
      }
      
    • keepalived : 设置长连接处理的数量,节省创建连接资源

      proxy_http_version:设置长连接http版本为1.1

      proxy_set_header:清除connection header 信息

      upstream tomcats {
              server 192.168.138.129:8081 backup;
              server 192.168.138.129:8082 max_conns=2;
              server 192.168.138.129:8083 max_conns=2;
              keepalive 32;
      }
      
      server {
          listen       8080;
          server_name  localhost;
      
          location / {
              proxy_pass  http://tomcats;
              proxy_http_version 1.1;
              proxy_set_header Connection "";
      	}
      }
      
      
  • ip_hash 负载均衡策略

    策略实现略缩过程图:

    image-20240827112252742

    ip_hash 可以保证用户访问可以请求到上游服务中的固定的服务器,前提是用户ip没有发生更改。使用ip_hash的注意点:不能把后台服务器直接移除,只能标记down.

    # 定义一个名为 tomcats 的 upstream,用于负载均衡多个后端服务器
    upstream tomcats {
        # 使用
        ip_hash;
        # 添加三个后端服务器地址
        server 192.168.138.129:8081;
        server 192.168.138.129:8082;
        server 192.168.138.129:8083;
    }
    
    # 配置一个 Nginx 服务器块
    server {
        # 监听 8080 端口
        listen       8080;
        # 设置服务器名称
        server_name  localhost;
    
        # 配置 location 块来处理根路径的请求
        location / {
            # 将请求代理到前面定义的 tomcats 上游服务器组
            proxy_pass http://tomcats;
        }
    }
    

    使用ip_hash的时候,如果节点增加减少会发生请求取模重新计算,为了解决这种情况,出现了一致性hash算法,简单的实现原理图如下

    image-20240827133837935

    服务器减少逻辑如下,如果节点3挂了,受影响的只有在节点2~节点3访问的用户,而且后期这些用户访问的节点将变更为节点4

    image-20240827134033139

    增加节点的情况下,只有红框中标注的人受影响,这样可以保证最少的人受影响

    image-20240827134218115

    nginx 1.18.0 后版本可以直接使用hash指令 配置一致性hash 并且支持故障转移 只需要修改配置文件

    upstream tomcats{
        hash $request_uri consistent;
        server 192.168.138.129:8082;
        server 192.168.138.129:8083;
    }
    
  • url_hash,使用请求的 hash(url) % node_counts =index,

    # 定义一个名为 tomcats 的 upstream,用于负载均衡多个后端服务器
    upstream tomcats {
        # 使用url_hash算法
        hash $request_uri;
        # 添加三个后端服务器地址
        server 192.168.138.129:8081;
        server 192.168.138.129:8082;
        server 192.168.138.129:8083;
    }
    
  • least_conn 最小连接数,哪一台服务器的连接数少,便去请求哪一台服务器

    # 定义一个名为 tomcats 的 upstream,用于负载均衡多个后端服务器
    upstream tomcats {
        # 使用最小连接数算法
    	least_conn;
        # 添加三个后端服务器地址
        server 192.168.138.129:8081;
        server 192.168.138.129:8082;
        server 192.168.138.129:8083;
    }
    

4.6 缓存信息

整体缓存操作过程图:

image-20240827140542017

浏览器缓存可以在nginx中控制,我们访问浏览器,发现请求接口返回状态码为304,则表示他使用的是缓存信息

image-20240827143735702

我们可以在location中设置过期时间,设置浏览器缓存,具体配置如下:

server {
    listen       90;
    server_name  localhost;

    #允许跨域请求的域,*代表所有
    add_header 'Access-Control-Allow-Origin' *;
    #允许带上cookie请求
    add_header 'Access-Control-Allow-Credentials' 'true';
    #允许请求的方法,比如 GET/POST/PUT/DELETE
    add_header 'Access-Control-Allow-Methods' *;
    #允许请求的header
    add_header 'Access-Control-Allow-Headers' *;

    # 资源源码
    location / {
        root   /root/nginx/dist;
        index  index.html;
    	# 设置资源过期时间,浏览器缓存过期时间10s
    	expires 10s;
    	# 设置晚上10点半过期
    	expires @22h30m
    	# 距离现在时间一个小时之前,缓存已经失效
    	expires -1h;
    	# 不设置缓存
    	expires epoch;
    	# 关闭缓存
    	expires off;
    	# 最大缓存时间,永不过期
    	expires max
    }
}

设置反向代理缓存信息,减少nginx服务器请求目标服务器

# 定义一个名为 tomcats 的 upstream,用于负载均衡多个后端服务器
upstream tomcats {
    server 192.168.138.129:8081;
    server 192.168.138.129:8082;
    server 192.168.138.129:8083;
}

# 配置一个 Nginx 服务器块
server {
    # 监听 8080 端口
    listen       8080;
    # 设置服务器名称
    server_name  localhost;

    # 配置 location 块来处理根路径的请求
    location / {
        # 将请求代理到前面定义的 tomcats 上游服务器组
        proxy_pass http://tomcats;
    
    	# 启用缓存,和keys_zone一致
        proxy_cache mycache;
        # 针对200304状态码缓存时间为8小时
        proxy_cache_valid   200 304 8h;
    }
}

# proxy_cache_path 设置缓存目录
#       keys_zone 设置共享内存以及占用空间大小
#       max_size 设置缓存大小
#       inactive 超过此时间则被清理
#       use_temp_path 临时目录,使用后会影响nginx性能
proxy_cache_path /usr/local/nginx/upstream_cache keys_zone=mycache:5m max_size=1g inactive=1m use_temp_path=off;

页面 http://192.168.138.129:8080/ 访问后,观察目录/usr/local/nginx/upstream_cache中已经有缓存信息

image-20240827145708867

image-20240827145631999

4.7 https配置

要在nginx中配置https,就必须安装ssl模块,也就是: http_ssl_module,新增ssl模块(原来的那些模块需要保留)

./configure \
--prefix=/usr/local/nginx \
--pid-path=/var/run/nginx/nginx.pid \
--lock-path=/var/lock/nginx.lock \
--error-log-path=/var/log/nginx/error.log \
--http-log-path=/var/log/nginx/access.log \
--with-http_gzip_static_module \
--http-client-body-temp-path=/var/temp/nginx/client \
--http-proxy-temp-path=/var/temp/nginx/proxy \
--http-fastcgi-temp-path=/var/temp/nginx/fastcgi \
--http-uwsgi-temp-path=/var/temp/nginx/uwsgi \
--http-scgi-temp-path=/var/temp/nginx/scgi  \
--with-http_ssl_module

进行重新编译

make
make install

需要使用腾讯云或者阿里云进行域名网站备案,然后开启ssl后证书。获取之后下ssl证书 *.crt 和 私钥 *.key 拷贝到/usr/local/nginx/conf目录中,注意我们申请的一般是学习使用为免费,有效期是1年,域名只有一级域名有效。

image-20240827151132629

配置HTTPS,新增 server 监听 443 端口,配置之后重新加载nginx既可使用https访问服务了,具体配置如下:

server {
    # https默认端口
    listen       443;
    server_name  localhost;

    # 开启ssl
    ssl     on;
    # 配置ssl证书
    ssl_certificate      1_www.imoocdsp.com_bundle.crt;
    # 配置证书秘钥
    ssl_certificate_key  2_www.imoocdsp.com.key;

    # ssl会话cache
    ssl_session_cache    shared:SSL:1m;
    # ssl会话超时时间
    ssl_session_timeout  5m;

    # 配置加密套件,写法遵循 openssl 标准
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
    ssl_prefer_server_ciphers on;
    
    location / {
        proxy_pass http://tomcats/;
        index  index.html index.htm;
    }
}

腾讯云Nginx配置https文档地址:https://cloud.tencent.com/document/product/400/35244

5.nginx 高可用

高可用集群类型有很多种类,常用的种类如下:

  • 负载均衡(LB):包括 LVS、HAProxy、nginx(http/upstream, stream/upstream),用于分配网络流量。
  • 高可用集群(HA):例如数据库、Redis 等,确保服务持续可用。 高性能集群(HPC):专注于提供强大的计算能力。

我们使用的nginx高可用简单示意过程图如下所示:

image-20240827152216745

5.1 keepalived基本概念

我们测试环境使用的是keepalived进行热备实现,keepalived 概念如下

负载均衡是一种在真实集群之间分配 IP 流量的方法 服务器,提供一个或多个高可用性虚拟服务。在设计负载均衡拓扑时,必须考虑负载均衡器本身以及后面的真实服务器的可用性。

Keepalived 为负载均衡和高可用性提供了框架, 框架依赖于众所周知且广泛使用的 Linux 虚拟服务器(IPVS)内核模块,提供第 4 层负载均衡。 Keepalived 实现了一组健康检查器,以动态和自适应的方式 根据服务器池的运行状况维护和管理负载均衡的服务器池。

高可用性是通过虚拟冗余路由协议实现的 (VRRP)。VRRP是路由器故障切换的基础砖块。keepalived也 实现了一组到 VRRP 有限状态机的钩子 提供低级和高速协议交互。每个Keepalived 框架可以单独使用,也可以一起使用,以提供弹性基础设施。

keepalived具体的作用如下:

  • 组件是免费组件
  • LVS系统的健康检查
  • 实施 VRRPv2 堆栈以处理负载均衡器故障切换

VRRP 相关概念如下具体解释如下

专业名称解释
Virtual Router虚拟路由器
虚拟路由器标识VRID(0-255) ,唯一标识虚拟路由器
VIPVirtual IP 虚拟ip
物理路由器master :主设备
backup :备用设备
priority :优先级
安全认证方式无认证或简单字符认证或采用预共享密钥以及MD5 认证。
工作模式主/备:单虚拟路由器模式
主/主:分为主/备(虚拟路由器 1)和备/主(虚拟路由器 2)两种情况。

5.2 keepalived双机主备原理

配置keepalived后,用户不再直接访问nginx,而是通过虚拟ip访问nginx,选择nginx的主master节点进行访问,如果master节点出现什么问题无法访问,keepalived会自动切换访问备用nginx服务节点,保证服务高可用HA

image-20240827154521064

5.3 keepalived安装

我们虚拟主机配置信息如下

服务名称主机ip端口
keepalived192.168.138.129
keepalived_backup192.168.138.130
nginx1192.168.138.129
nginx2192.168.138.130

keepalived下载地址 https://www.keepalived.org/download.html ,我们本次使用的是 2.3.0 版本

image-20240827155426584

上传 keepalived-2.3.0.tar.gz 到预订目标服务器,192.168.138.129

image-20240827155959968

解压tar包,解压后进入到解压出来的目录,看到会有configure,那么就可以做配置了(配置安装和nginx一模一样)

tar -zxvf keepalived-2.3.0.tar.gz

进入到keepalived包中,进行调用 ./configure配置

# prefix:keepalived安装的位置
# sysconf:keepalived核心配置文件所在位置,固定位置,改成其他位置则keepalived启动不了,/var/log/messages中会报错
./configure --prefix=/usr/local/keepalived --sysconf=/etc

配置过程中可能会出现警告信息,如下所示,需要安装libnl/libnl-3依赖

image-20240828102934618

yum -y install libnl libnl-devel

image-20240828103034733

再次执行 ./configure命令,发现错误已经不提示了,正常安装成功

./configure --prefix=/usr/local/keepalived --sysconf=/etc

image-20240828103149676

开始进行安装

make && make install

进入到/etc/keepalived,该目录下为keepalived核心配置文件,如果找不到使用命令whereis keepalived进行查找

image-20240828103439790

5.4 keepalived核心配置

我们查看keepalived配置文件内容/etc/keepalived/keepalived.conf.sample文件中,我们复制一个keepalived.conf.sample到keepalived.conf

cd /etc/keepalived
cp keepalived.conf.sample keepalived.conf

我们使用命令查看vim keepalived.conf文件,进行内容整理

  • 全局配置信息

    global_defs {
       # 配置通知邮件的相关设置
       # 当发生故障切换时,Keepalived会向下面定义的邮箱地址发送通知邮件
       notification_email {
         acassen@firewall.loc
         failover@firewall.loc
         sysadmin@firewall.loc
       }
       # 定义发送邮件的发件人地址
       notification_email_from Alexandre.Cassen@firewall.loc
       # 指定SMTP服务器的IP地址
       smtp_server 192.168.200.1
       # 设置SMTP连接超时时间(秒)
       smtp_connect_timeout 30
       # 定义路由器ID,用于标识运行Keepalived服务的主机
       # 此ID在集群中必须是全局唯一的
       router_id LVS_DEVEL
       # 禁用对通告消息中IP地址的检查
       vrrp_skip_check_adv_addr
       # 启用严格的VRRP模式
       vrrp_strict
       # 设置发送免费ARP的间隔时间为0秒,意味着禁用此功能
       vrrp_garp_interval 0
       # 设置发送GARP消息的间隔时间为0秒,意味着禁用此功能
       vrrp_gna_interval 0
    }
    

    我们对其进行修改,删除无用配置信息,最终修改后如下

    global_defs {
       # 定义路由器ID,用于标识运行Keepalived服务的主机
       router_id keep_129
    }
    
  • VRRP实例信息

    # 计算机节点
    vrrp_instance VI_1 {
        # 设置当前实例的状态为MASTER,当前129位主节点master,备用机则为BACKUP
        state MASTER
        # 指定使用的网络接口
        interface eth0
        # 设置虚拟路由器的ID,保证主备一致
        virtual_router_id 51
        # 设置优先级,值越大优先级越高
        priority 100
        # 设置VRRP通告间隔时间(秒)
        advert_int 1
        # 配置身份验证
        authentication {
            # 设置认证类型为密码认证
            auth_type PASS
            # 设置认证密码
            auth_pass 1111
        }
        # 配置虚拟IP地址列表
        virtual_ipaddress {
            192.168.200.16
            192.168.200.17
            192.168.200.18
        }
        # 允许接收发送到上述VIP的流量
        accept
    }
    

    删除无用信息,修改后信息如下

    # 计算机节点
    vrrp_instance VI_1 {
        # 设置当前实例的状态为MASTER,当前129位主节点master,备用机则为BACKUP
        state MASTER
        # 指定使用的网络接口
        interface ens33
        # 设置虚拟路由器的ID,保证主备一致
        virtual_router_id 51
        # 优先级,master挂掉了,值越大优先级越高,越高几率成为master
        priority 100
        # 主备之间检查时间间隔,VRRP通告间隔时间(秒)
        advert_int 1
        # 配置身份验证,防止非法节点的进入
        authentication {
            # 设置认证类型为密码认证
            auth_type PASS
            # 设置认证密码
            auth_pass 1111
        }
        # 配置虚拟IP地址列表
        virtual_ipaddress {
            192.168.138.160
        }
        # 允许接收发送到上述VIP的流量
        accept
    }
    
  • 启动keepalived服务

    进入到/usr/local/keepalived/sbin目录,执行./keepalived即可

    cd /usr/local/keepalived/sbin
    ./keepalived
    

    查看keepalived是否正常启动,查看虚拟ip是否正常

    ps -ef | grep keepalived
    ip addr
    

    image-20240828110635099

5.5 注册keepalive为系统服务

之前已经配置了虚拟ip 192.168.138.160,那么我们便可以使用这个ip访问我们的nginx首页

image-20240828112407210

拷贝/root/keepalived/keepalived-2.3.0/keepalived/etc/init.d/keepalived配置文件到系统/etc/init.d目录下,以及拷贝sysconfig/keepalived/etc/sysconfig/目录下,如果提示是否覆盖,选择覆盖即可

cd /root/keepalived/keepalived-2.3.0/keepalived/etc
cp init.d/keepalived /etc/init.d/
cp sysconfig/keepalived /etc/sysconfig/

执行系统命令,将keepalived注册为系统服务

systemctl daemon-reload
# 启动/重启/停止 start/restart/stop
systemctl start keepalived.service
# 检查keepalived是否注册为系统服务
systemctl -l | grep keepalived

image-20240828134318290

5.6 keepalived双机主备配置

我们使用129服务已经设置了keepalived的主master节点,现在设置130为从节点,按照129安装keepalived同样在130节点上安装keepalived,从节点设置也是非常简单,主要配置如下

global_defs {
   # 唯一标识符,全局唯一
   router_id keep_130
}

vrrp_instance VI_1 {
    # 备用节点
    state BACKUP
    interface ens33
    virtual_router_id 51
    priority 80
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    # 对外提供虚拟ip,与主节点相同
    virtual_ipaddress {
        192.168.138.160
    }

    # 允许接收发送到上述VIP的流量
    accept
}

启动keepalived服务,然后查看ip信息,发现160还没有上来,这是因为主节点还在,备用节点还没有提供服务

cd /usr/local/keepalived/sbin
./keepalived

image-20240828135937338

我们停止129对应的keepalived服务,然后再次观察ip信息,发现160虚拟ip已经出现了,再次访问则显示访问的就是130的nginx服务了,因为160对应的ip已经是130上的keepalived提供的了

# 129停止keepalived服务
systemctl stop keepalived

image-20240828140300757

image-20240828140240356

之后我们再次启动keepalived服务,模拟129服务恢复,发现再次访问160重新切换回了129服务器,并且查看130对应的ip,发现160虚拟ip已经消失不见了

systemctl start keepalived

image-20240828140541009

image-20240828140704224

5.7 配置nginx7*24不间断提供服务

我们需要编写简单的脚本,主要是监听nginx服务是否正常,如果不正常则尝试进行重启,如果重启失效,则切备用的nginx对外提供服务,具体实现过程如下:

  • 增加Nginx重启检测脚本

    vim /etc/keepalived/check_nginx_alive_or_not.sh
    
    #!/bin/bash
    
    A=`ps -C nginx --no-header |wc -l`
    # 判断nginx是否宕机,如果宕机了,尝试重启
    if [ $A -eq 0 ];then
        /usr/local/nginx/sbin/nginx
        # 等待一小会再次检查nginx,如果没有启动成功,则停止keepalived,使其启动备用机
        sleep 3
        if [ `ps -C nginx --no-header |wc -l` -eq 0 ];then
            killall keepalived
        fi
    fi
    
  • 增加运行权限

    chmod +x /etc/keepalived/check_nginx_alive_or_not.sh
    
  • 配置keepalived监听nginx脚本

    ! Configuration File for keepalived
    
    global_defs {
        # 定义路由器ID,用于标识运行Keepalived服务的主机,要求全局唯一
        router_id LVS_DEVEL
    }
    
    # 定义一段自定义脚本
    vrrp_script check_nginx_alive {
        script "/etc/keepalived/check_nginx_alive_or_not.sh"
        interval 2 # 每隔两秒运行上一行脚本
        weight 10 # 如果脚本运行成功,则升级权重+10
        # weight -10 # 如果脚本运行失败,则升级权重-10
    }
    
    # 计算机节点
    vrrp_instance VI_1 {
        # 设置当前实例的状态为MASTER,当前129位主节点master,备用机则为BACKUP
        state MASTER
        # 指定使用的网络接口
        interface ens33
        virtual_router_id 51
        priority 100
        advert_int 1
        authentication {
            auth_type PASS
            auth_pass 1111
        }
    	
    	# 监听脚本
        track_script {
            # 追踪 nginx 脚本
            check_nginx_alive
        }
    	# 提供虚拟ip
        virtual_ipaddress {
            192.168.138.160
        }
    
        # Allow packets addressed to the VIPs above to be received
        accept
    }
    

    然后重启keepalived服务,停止nginx服务然后再次访问nginx页面,发现129nginx还是在提供服务,那么已经实现了nginx的自动检测功能

    systemctl restart keepalived
    /usr/local/nginx/sbin/nginx -s stop
    

    image-20240828143416155

这种配置其实也有问题,我们的keepalived以及nginx如果都不出问题,则我们的备用服务器则永远不会被访问到,整体设计存在一个资源浪费的问题,这时候我们需要使用双主热备,架构图如下,两个nginx互为主备

image-20240828145923853

5.8 双主热备实现

服务器可以使用双主热备进行实现,这里以他腾讯云为例子,上海节点有两个独立的云服务器,他们都拥有独立的ip

image-20240828152043677

点击云解析,进行域名解析,域名解析需要先进行备案,我们查看wxfanhual.com这个域名,点击进行查看

image-20240828152118730

我们可以看到我们在这个域名下,配置了两个ip,并且使用主机记录为www以及类型A访问就会映射到两个不同的ip

image-20240828152311924

我们点击负载均衡,查看负载均衡配置信息为均等负载,就是轮训,我们也可以对负载逻辑进行修改,重新分配权重信息

image-20240828152506332

image-20240828152607868

我们点击域名设置,里面会有一个DNS服务器信息,我们购买域名之后,会提供DNS服务器,域名经过DNS服务器解析之后获取到不同的ip,然后再展示服务器中不同的内容的。

image-20240828152818587

我们本地具体应该如何配置呢,其实就是配置两组不同的主备配置,既129与130服务器keepalived互为主备,具体配置如下:

  • 主节点配置信息

    global_defs {
       router_id keep_129
    }
    
    vrrp_instance VI_1 {
        state MASTER
        interface ens33
        virtual_router_id 51
        priority 100
        advert_int 1
        authentication {
            auth_type PASS
            auth_pass 1111
        }
        virtual_ipaddress {
            192.168.138.160
        }
    }
    
    vrrp_instance VI_2 {
        state BACKUP
        interface ens33
        virtual_router_id 52
        priority 80
        advert_int 1
        authentication {
            auth_type PASS
            auth_pass 1111
        }
        virtual_ipaddress {
            192.168.138.170
        }
    }
    
  • 备用节点配置

    global_defs {
       router_id keep_130
    }
    
    vrrp_instance VI_1 {
        state BACKUP
        interface ens33
        virtual_router_id 51
        priority 80
        advert_int 1
        authentication {
            auth_type PASS
            auth_pass 1111
        }
        virtual_ipaddress {
            192.168.138.160
        }
    }
    
    vrrp_instance VI_2 {
        state MASTER
        interface ens33
        virtual_router_id 52
        priority 100
        advert_int 1
        authentication {
            auth_type PASS
            auth_pass 1111
        }
        virtual_ipaddress {
            192.168.138.170
        }
    }
    
  • 重启服务

    # 重启Keepalived
    systemctl restart keepalived
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值