Nginx 高级篇

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

Nginx 高级篇

一、 负载均衡

1、 负载均衡概述

负载均衡Load Balance它在网络现有结构之上可以提供一种廉价、有效、透明的方法来扩展网络设备和服器的带宽并可以在一定程度上增加吞吐量、加强网络数据处理能力、提高网络的灵活性和可用性等。用官网说它充当着网络流中“交通指挥官”的角色“站在”服务器前处理所有服务器端和客户端之间的请求从而最大度地提高响应速率和容量利用率同时确保任何服务器都没有超负荷工作。如果单个服务器出现故障负载均衡方法会将流量重定向到其余的集群服务器以保证服务的稳定性。当新的服务器添加到服务器组后也可通过负均衡的方法使其开始自动处理客户端发来的请求。

负载均衡的作用

  • 解决服务器高并发的压力提高应用程序的处理性能
  • 提供故障转移实现高可用
  • 通过添加或减少服务器数量增强网站的可扩展性
  • 在负载均衡器上进行过滤可以提高系统的安全性

2、 处理方式

2.1 用户手动选择

这种方式比原始主要实现的方式就是在网站主页上面提供不同线路、不同服务连接方式让用户来选择自己访问的具体服务器来实现负载均衡。

如蓝奏云

2.2 DNS 轮询

DNS域名系统服务协议是一种分布式网络目录服务主要有用于域名与 IP 地址的相互转换

大多数域名注册商都支持对同一个主机名添加多条 A 记录这就是 DNS 轮询DNS 服务器将解析请求按照 A 记录的顺序随机分配到不同的 IP 上这样就能完成简单的负载均衡。DNS 轮询的成本非常低在一些不重要的服务器被经常使用。

使用 DNS 来实现轮询不需要投入过多的成本虽然 DNS 轮询成本低廉但是 DNS 负载均衡存在明显的缺点

  1. 可靠性低

    各大宽带接入商会将众多的 DNS 存放在缓存中以节省访问时间导致 DNS 不会实时更新。

    Windows 刷新 DNS 的命令ipconfig/flushdns

  2. 负载均衡不均衡

    其会导致某几台服务器负荷很低而另外几台服务器负荷很高处理请求的速度慢配置高的服务器分配到的请求少而配置低的服务器分配到的请求多。

2.3 四 / 七层负载均衡

OSI开放式系统互联模型这个是有国际标准化 ISO 指定的一个不基于具体机型、操作系统或公式的网络体系结构。该模型将网络通信的工作分为七层。

  • 四层负载均衡OSI 七层模型中的传输层主要是基于 IP + PORT 的负载均衡
  • 七层负载均衡在音乐层主要是基于虚拟的 URL 或主机 IP 的负载均衡

3、 七层负载均衡

Nginx 要实现七层负载均衡需要用到 proxy_pass 代理模块配置。Nginx 默认安装支持这个模块我们不需要再做任何处理。Nginx 的负载均衡是在 Nginx 的反向代理的基础上把用户的请求根据指定的算法分发到一组【upstream 虚拟服务池】

3.1 七层负载均衡指令

3.1.1 upstream

该指令是用来定义一组服务器它们可以是监听不同端口的服务器并且也可以是同时监听 TCP 和 Unix Socket 的服务器。服务器可以指定不同的权重默认为 1。

语法默认值位置
upstream name {…}-http
3.1.2 server

该指令是用来指定后端服务器的名称和一些参数可以使用域名、IP、端口或者 Unix Socket。

语法默认值位置
server name [paramerters]-upstream

3.2 实现流程

使用示例

server {
	listen		9001;
    server_name 	localhost;
    default_type 	text/html;
    location / {
    	return 200 "port=9001";
    }
}
server {
	listen		9002;
    server_name 	localhost;
    default_type 	text/html;
    location / {
    	return 200 "port=9002";
    }
}
upstream backend {
	server localhost:9001;
    server localhost:9002;
}
server {
	listen  	80;
    server_name localhost;
    location /	{
    	proxy_pass http://backend;  # backend 为服务组的名称
    }
}

3.3 负载均衡的状态

代理服务器在负责负载均衡调度中的状态有以下几个

状态描述
down当前 server 暂时不参与负载均衡
backup预留的备份服务器
max_fails允许请求失败的次数
fail_timeout经过 max_fails 失败后服务暂停时间
max_conns限制最大的接收数
3.3.1 down

将服务器标记为永久不可用那么该服务器将不参与负载均衡

upstream backend {
	server localhost:9001 down;
    server localhost:9002;
}
server {
	listen  	80;
    server_name localhost;
    location /	{
    	proxy_pass http://backend;  # backend 为服务组的名称
    }
}

该状态一般会对需要停机维护的服务器进行设置。

3.3.2 backup

将该服务器标记为备份服务器当主服务器不可用时将用来传递请求。

upstream backend {
	server localhost:9001 backup;  # 备份服务器
    server localhost:9002 down;  
    server localhost:9003;  # 主服务器
}
server {
	listen  	80;
    server_name localhost;
    location /	{
    	proxy_pass http://backend;  # backend 为服务组的名称
    }
}

此时需要将 9003 端口的访问禁止调来模拟唯一能对外提供访问的服务宕机以后backup 的备份服务器就要开始对外提供服务此时为了测试验证我们需要使用防火墙来进行拦截。

这时我们需要使用 ufw 工具来对防火墙进行控制

sudo apt install ufw  # 安装 ufw
ufw enadble  # 开启防火墙
ufw deny 9003/tcp  # 关闭 9003 端口
ufw allow 9001:9002/tcp  # 允许开启 9001 和 9002
ufw allow http  # 开放http

这里我使用的是 ubuntu 系统

3.3.3 max_conns

max_conns=number其用来设置代理服务器同时活动链接的最大数量默认为 0 表示不限制使用该配置可以根据后端服务器处理请求的并发量来进行设置防止后端服务器被压垮。

3.3.4 max_fails & fail_timeout

max_fails=number设置允许请求代理服务器失败的次数默认为 1 。

fail_timeout=time设置经过 max_fails 失败后服务暂停的时间默认是 10 秒。

upstream backend {
	server localhost:9001 backup;  # 备份服务器
    server localhost:9002 down;  
    server localhost:9003 max_fails=3 fail_timeout=15;  # 主服务器
}
server {
	listen  	80;
    server_name localhost;
    location /	{
    	proxy_pass http://backend;  # backend 为服务组的名称
    }
}

3.4 负载均衡策略

学完负载均衡的相关指令后我们已经可以实现将用户的请求分发到不同的服务器上那么除了采用默认的分配方式以外我们还能采用什么样的负载算法

算法名称说明
轮询默认方式
weight权重方式
ip_hash依据 ip 分配方式
least_conn依据最少连接方式
url_hash依据 URL 分配方式
fair依据响应时间方式
3.4.1 轮询

其是 upstream 模块负载均衡默认的策略。每个请求会按时间顺序逐个分配到不同的后端服务器。轮询不需要额外的配置。

upstream backend {
	server localhost:9001; 
    server localhost:9002;  
    server localhost:9003;  
}
server {
	listen  	80;
    server_name localhost;
    location /	{
    	proxy_pass http://backend;
    }
}
3.4.2 weight

weight=number用来设置服务器的权重默认为 1 权重数据越大被分配到请求的几率越大该权重值主要是针对实际工作环境中不同的后端服务器硬件配置进行调整的所有此策略比较适合服务器的硬件配置差别比较大的情况。

upstream backend {
	server localhost:9001 weight=10;    
    server localhost:9002;  
    server localhost:9003; 
}
server {
	listen  	80;
    server_name localhost;
    location /	{
    	proxy_pass http://backend;
    }
}
3.4.3 ip_hash

当后端的多台动态应用服务器做负载均衡时ip_hash 指令能够将某个客户端 IP 的请求通过哈希算法定位到同一台后端服务器上。这样当来自某一个 IP 的用户在后端 Web 服务器 A 上登录后当访问该站点的其他 URL 能够访问的还是后端 Web 服务器 A。

语法默认值位置
ip_hash;-upstream
upstream backend {
    ip_hash;
	server localhost:9001;    
    server localhost:9002;  
    server localhost:9003; 
}
server {
	listen  	80;
    server_name localhost;
    location /	{
    	proxy_pass http://backend;
    }
}
3.4.4 least_conn

最少连接把请求转发给连接数较少的后端服务器轮询算法是把请求平均的转发给各个后端使它们的负载大致相同但是有些请求占用的时间很长会导致其所在的后端负载较高。这种情况下least_conn 这种方式就可以达到更好的负载均衡效果。

upstream backend {
    least_conn;
	server localhost:9001;    
    server localhost:9002;  
    server localhost:9003; 
}
server {
	listen  	80;
    server_name localhost;
    location /	{
    	proxy_pass http://backend;
    }
}

此负载均衡策略适合请求处理时间长短不一造成服务器过载的情况。

3.4.5 url_hash

按访问 url 的 hash 结果来分配请求使每个 url 定向到同一个后端服务器要配合缓存命中来使用。同一个资源多次请求可能会到达不同的服务器上导致不必要的多次下载缓存命中率不高以及一些资源时间的浪费。而使用 url_hash 可以使得同一个 url 也就是同一个资源请求会到达同一台服务器一旦缓存了资源再此收到请求就可以从缓存中读取。

upstream backend {
    url_hash &request_uri;
	server localhost:9001;    
    server localhost:9002;  
    server localhost:9003; 
}
server {
	listen  	80;
    server_name localhost;
    location /	{
    	proxy_pass http://backend;
    }
}
3.4.6 fair

fair 采用的不是内建负载均衡使用的轮询的均衡算法而是可以根据页面大小、加载事件长短智能的进行负载均衡。那么如何使用第三方模块的 fair 负载均衡策略

upstream backend {
    fair;
	server localhost:9001;    
    server localhost:9002;  
    server localhost:9003; 
}
server {
	listen  	80;
    server_name localhost;
    location /	{
    	proxy_pass http://backend;
    }
}

但是直接使用会报错因为 fair 属于第三方模块实现的负载均衡。需要添加nginx-upstream-fair如何添加呢

  1. 下载 nginx-upstream-fair模块https://github.com/gnosek/nginx-upstream-fair.git

    cd
    git clone https://github.com/gnosek/nginx-upstream-fair.git
    
  2. 使用 ./confirgure命令将资源添加到 Nginx 模块中

    nginx -V  # 复制原来的配置参数
    cd /root/nginx-1.22.1/  # 进入 Nginx 安装目录
    ./configure old_args -add-module=/root/nginx-upstream-fair  # 添加第三方模块
    make  # 进行编译
    mv objs/nginx /usr/local/nginx/sbin/  # 将编译后的 Nginx 替换原来的 Nginx
    make upgrade  # 进行在线升级
    

    在编译过程中会发现编译失败了

    我们需要运行

    vim src/http/ngx_http_upstream.h
    

    找到对应位置添加图片中的内容然后再进行一次编译就可以了。

4、 四层负载均衡

Nginx 增加了 stream 模块用来实现四层协议的转发、代理、负载均衡等。stream 模块的用法跟 http 的用法类似允许我们配置一组 TCP 或者 UDP 等协议的监听然后通过 proxy_pass 来转发我们的请求通过 upstream 添加多个后端服务实现负载均衡。

四层协议负载均衡的实现一般都会用到 LVS、HAProxy、F5等而 Nginx 的配置相对来说更简单更能快速完成工作。四层负载均衡不经常使用了解即可。

Nginx 默认是没有编译这个模块的需要使用到 stream 模块那么需要在编译的时候加上 --with-stream和添加一般模块的步骤类似。

4.1 四层负载均衡指令

4.1.1 stream

该指令提供在其中指定流服务器指令的配置文件上下文和 http 同级。

语法默认值位置
stream{…}-main
4.1.2 upstream

该指令和 http 的upstream 指令是类似的。

4.2 使用示例

stream {
    upstream redisbackend {
    	server localhost:6379;  # 第一台 Redis 服务器
        server localhost:6378;  # 第二台 Redis 服务器
    }
    server {
    	listen 81;  
        proxy_pass redisbackend;  
    }
}
stream {
    upstream flaskbackend {
    	server localhost:8080;  # flask 服务器
    }
    server {
    	listen 82;
        proxy_pass flaskbackend;
    }
}
http {
	server {
        listen       80;
        server_name  localhost;

        charset koi8-r;

        access_log  logs/host.access.log  main;

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

一个 81 端口绑定了两台 redis 服务器同时将 82 端口绑定到 flask 服务器上面。

二、 Nginx 缓存集成

1、 缓存的概念

缓存就是数据交换的缓冲区当用户要获取数据的时候会先从缓存中去查询获取数据如果缓存中有就会直接返回给用户如果缓存中没有则会发送请求从服务器重新查询数据将数据返回给用户的同时将数据放入缓存下次用户就会直接从缓存中获取数据。

缓存的应用场景

场景作用
操作系统磁盘缓存减少磁盘机械操作
数据库缓存减少文件系统的 IO 操作
应用程序缓存减少对数据库的查询
Web 服务器缓存减少对应用服务器请求次数
浏览器缓存减少与后台的交互次数

缓存的优点

  1. 减少数据传输节省网络流量加快响应速度提升用户体验
  2. 减轻服务器压力
  3. 提供服务端的高可用性

缓存的缺点

  1. 数据不一致
  2. 增加成本

2、 缓存相关指令

Nginx 的 Web 缓存服务器主要是使用 ngx_http_proxy_module模块相关指令集来完成。

2.1 proxy_cache_path

该指令用于设置缓存文件的存放路径

语法默认值位置
proxy_cache_path path [levels=number]
keys_zone=zone_name:zone_size [inactive=time][max_size=size];
-http

path缓存路径地址如/usr/local//proxy_cache

levels指定该缓存空间对应的目录最多可设置三层每层取值为 1 | 2如

levels=1:2  缓存空间有两层目录第一次是 1 个字母第二次是 2 个字母  
# 最终存储路径为 /usr/local//proxy_cache/d/07

keys_zone用来为这个缓存区设置名称和指定大小

inactive指定缓存的珊瑚橘多次时间未被访问就将被删除

max_size设置最大缓存空间如果缓存空间存满默认会覆盖缓存时间最长的资源

2.2 proxy_cache

该指令用来开启或关闭代理缓存如果是开启则自定义使用哪个缓存区来进行缓存。

语法默认值位置
proxy_cache zone_name | off;proxy_cache off;http、server、location

zone_name指定使用缓存区的名称

2.3 proxy_cache_key

该指令用来设置 Web 缓存的 Key 值Nginx 会根据 Key 值 MD5 哈希存缓存。

语法默认值位置
proxy_cache_key key;proxy_cache s c h e m e scheme schemeproxy_host$request_uri;http、server、location

2.4 proxy_cache_valid

该指令用来对不同返回状态码的 URL 设置不同的缓存时间

语法默认值位置
proxy_cache_valid [code …] time;-http、server、location

2.5 proxy_cache_min_uses

该指令用来设置资源被访问多少次后被缓存

语法默认值位置
proxy_cache_min_uses number;proxy_cache_min_uses 1;http、server、location

2.6 proxy_cache_methods

该指令用户设置缓存哪些 HTTP 方法

语法默认值位置
proxy_cache_methods GET | HEAD | POST;proxy_cache_methods GET HESAD;http、server、location

默认缓存 HTTP 的 GET 和 HEAD 方法不缓存 POST 方法。

3、 Nginx 缓存的清除

3.1 删除缓存目录

rm -rf /usr/local/proxy_cache/...

3.2 使用扩展模块

使用模块ngx_cache_purge

  1. 下载资源包https://github.com/FRiCKLE/ngx_cache_purge.git

    git clone https://github.com/FRiCKLE/ngx_cache_purge.git
    
  2. 进行安装

    nginx -V  # 查询 Nginx 的配置参数
    ./configure old_args --add-module=/root/nginx-1.22.1/modules/ngx_cache_purge
    make  
    mv objs/nginx /usr/local/nginx/sbin/
    make upgrade
    
语法默认值位置
proxy_cache_purge zone_name proxy_cache_key-http、server、location

具体的使用方式可以查看https://github.com/FRiCKLE/ngx_cache_purge

4、 设置资源不缓存

并不是所有的数据都适合缓存比如说一些经常发生变化的数据。

这时候需要使用到如下两个指令

  1. proxy_no_cache

    该指令是用来定义不将数据进行缓存的条件。

    语法默认值位置
    proxy_no_cache string …;-http、server、location
    proxy_no_cache $cookie_nocache $arg_nocache $arg_comment;
    
    • $cookie_nocache

      指的是当前请求的 Cookie 中键的名称为 nocache 对应的值

    • $arg_nocache

      指的是当前请求的参数中属性名为 nocache 的值

    • $arg_comment

      指的是当前请求的参数中属性名为 comment 的值

  2. proxy_cache_bypass

    该指令是用来设置不从缓存中获取数据的条件

    语法默认值位置
    proxy_cache_bypass string …;-http、server、location
    proxy_cache_bypass $cookie_nocache $arg_nocache $arg_comment;
    

上述两个指令都有一个指定条件这个条件可以是多个并且多个条件中至少有一个不为空且不等于 0则条件满足成立。

使用示例

http{
    proxy_cache_path /usr/local/nginx/proxy_cache levels=2:1 keys_zone=temp:200m inactive=1d max_szie=20g;  
    upstream backend {
    	server localhost:8080;
    }
    server {
        location / {
            # 如果请求的文件为 js 文件不进行缓存
            if ($request_uri ~ /.*\.js$) {
                set $nocache 1;
            }
            proxy_cache temp;  
            proxy_cache_key temp_;
            proxy_cache_min_uses 5;  
            proxy_cache_valid 200 5d;
            proxy_cache_valid 404 30s;
            proxy_cache_valid any 1m;
            proxy_no_cache $nocache;
            proxy_cache_bypass $nocache;
            proxy_pass http://backend/;
          }
        location /purge(/.*) {
        	proxy_cache_purge temp  temp_;
        }
    }
}

三、 Nginx 实现动静分离

1、 概念

什么是动静分离

  • 动后台应用程序的业务处理
  • 静网站静态资源
  • 分离将两者进行分开部署访问提供用户进行访问。举例说明就是以后所有和静态资源相关的内容都交给 Nginx 来部署访问非静态内容则交给类似于 Flask 的服务器来部署访问。

为什么要静态分离

  • Nginx 在处理静态资源的时候效率非常高而且 Nginx 的并发访问量也是名列前茅的而 Flask 等服务器则相对比较弱一些所以把静态文件交给 Nginx 后可以减轻 Flask 服务器的访问压力并提高静态资源的访问速度。
  • 动静分离后减低了动态资源和静态资源的耦合度。如果动态资源宕机了也不影响动态资源的展示。

如果实现动静分离

  • 实现动静分离的方式很多比如静态资源化可以部署到 CDN、Nginx 等服务器上动态资源可以部署到 Flask 等上面这里使用Nginx + Flask 来实现动静分离。

2、 需求分析

我们需要将动态的链接发送到 Flask静态的访问直接通过 Nginx 来进行处理。

http {
    include       mime.types;
    default_type  application/octet-stream;

    sendfile        on;

    keepalive_timeout  65;
    upstream flaskservice{
        server localhost:8080;
    }

    server {
        listen       80;
        server_name  localhost;
        location ~/.*\.(html|htm|js|css|ico|png|jpg|gif|svg|txt) {
                root /root/www/static;
        }
        location /demo{
                proxy_pass http://flaskservice;
        }
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
}

四、 Nginx 实例

1、 Nginx 制作下载站点

首先我们要清除什么是下载站点

  • 我们先来看一下网站https://nginx.org/download/
  • 这个网站主要就是用来提供用户来下载相关资源的网站就叫做下载站点。

如何制作下载站点

  • Nginx 使用的是模块 ngx_http_autoindex_module来实现的该模块处理以斜杆结尾的请求并生成目录列表。
  • Nginx 编译的时候会自动加载该模块但是该模块默认是关闭的我们需要使用下面的指令来完成对应的配置

指令

  1. autoindex启用或禁用目录列表输出

    语法默认值位置
    autoindex on | off;autoindex off;http、server、location
  2. autoindex_exact_size对应 HTML 格式指定是否在目录列表展示文件的详细大小

    默认为 on显示出文件的确切大小单位是 bytes改为 off 后显示出文件的大概大小单位是 kb 或者 Mb 或者 GB。

  3. autoindex_format设置目录列表的格式

    语法默认值位置
    autoindex_format html | xml | json | jsonp;autoindex_format html;http、server、location
  4. autoindex_localtime对应 HTML 格式是否在目录列表上显示时间

    默认为 off 显示的文件时间为 GMT 时间改为 on 后显示的文件时间为文件的服务器时间。

location /download {
    root /root/www;
	autoindex on;
    autoindex_localtime on;
}

在 www 目录下有一个download 目录同时由于在root 目录下需要在全局块中添加 user root;

2、 用户认证

对于系统资源的访问我们往往需要限制谁能访问谁不能访问。这块就是我们通常所说的认证部分认证需要做的就是根据用户输入的用户名和密码来判定用户是否为合法用户如果是则放行如果不是则拒绝访问。

Nginx 对应用户认证是通过 ngx_http_auth_basic_module模块来实现的它允许通过使用“ HTTP 基本身份验证”协议验证用户名和密码来限制对资源的访问。默认情况下 Nginx 是已经安装了这个模块。如果没有则使用 --without-http_auth_basic_module

该模块的指令比较简单

  1. auth_basic使用“ HTTP 基本认证”协议启用用户名和密码的验证

    语法默认值位置
    auth_basic string | off;auth_basic off;http、server、location、limit_except

    开启后服务端会返回 401指定的字符串会返回到客户端给用户以提示信息但是不同的浏览器对内容的展示不一致。

  2. auth_basic_user_file指定用户名和密码所在的文件

    语法默认值位置
    auth_basic_user_file file;-http、server、location、limit_except

    指定文件路径还文件中的用户名和密码的设置密码需要进行加密。可以采用工具自动生成

# 下载站点的相关配置
location /download {
    root /root/www;
    autoindex on;
    autoindex_localtime on;
    auth_basic "please inpute your auth";
    auth_basic_user_file htpasswd;
}

生成用户名和密码的文件

# 我们使用 htpasswd 工具生成
yum install -y httpd-tools

cd /usr/local/nginx/conf
htpasswd -c htpasswd username  # 创建一个新文件记录用户名和密码
htpasswd -b htpasswd username password  # 在指定文件新增一个用户名和密码
htpasswd -D htpasswd username  # 从指定文件删除一个用户信息
htpasswd -v htpasswd username  # 验证用户名和密码是否正确
阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: nginx