开源反向代理工具-Nginx

目录

一、Nginx简介

二、Nginx工作原理

1.事件驱动模型

2.Master-Worker多进程架构

3.反向代理和负载均衡

4.高并发处理

5.静态资源缓存

6.模块化设计

三、Nginx执行流程

1.接收请求

2.选择服务器块(server block)

3.选择位置块(location block)

4.处理重写规则(rewrite directives) 

 5.处理访问控制

6.处理代理或静态文件

7.执行过滤器

8.发送响应

9.记录日志

四、Nginx常用配置

1.反向代理负载均衡

 2.日志输出

输出格式

输出字段

3.重写功能

rewrite

 return

 4.缓存控制

浏览器缓存控制

代理缓存控制

5.访问控制


一、Nginx简介

        NGINX 是一种高性能的反向代理服务器、负载均衡器和 HTTP 缓存服务器。它的设计初衷是为了应对高并发和低资源消耗,尤其适合处理大量的短连接请求。NGINX 的高效性能来自其事件驱动架构和异步非阻塞的处理方式。

二、Nginx工作原理

1.事件驱动模型

        Nginx使用的是一种基于事件的异步非阻塞模型,也就是它能够在处理客户端请求时,不会因为等待某个操作(如I/O操作)而阻塞整个进程。相比传统的基于线程或进程的模型(如Apache),这种方式极大地提高了资源利用率。
        事件循环:Nginx采用事件驱动机制管理连接,当有事件发生时,它会被通知并执行相应的操作。例如,一个新的客户端连接会触发accept事件,数据的读取会触发read事件。
        异步非阻塞:在等待I/O操作时(如从磁盘读取文件或向客户端发送数据),不会阻塞其他操作。即使正在处理大量请求,单个请求的延迟也会尽可能保持较低。

2.Master-Worker多进程架构

        Nginx采用了Master-Worker进程模型,Master进程负责管理Worker进程(包括启动、停止和监控等),而Worker进程负责处理实际的客户端请求。
        Master进程:负责配置加载、管理Worker进程等。
        Worker进程:负责处理客户端的连接。每个Worker进程独立处理请求,并且它们之间不共享任何状态。通过这种设计,NGINX能够在不锁住资源的情况下处理大量并发请求。

3.反向代理和负载均衡

        Nginx主要用于反向代理服务器,即它会接收客户端的请求,转发到后端服务器,并将后端服务器的响应返回给客户端。这使得NGINX成为一个强大的负载均衡器,可以将流量分配给多个后端服务器,以实现更高的可用性和扩展性。
        反向代理:Nginx接受客户端请求,将请求转发给后端服务器,并返回后端服务器的响应。
        负载均衡算法:它支持多种负载均衡策略,比如轮询(RoundRobin)、权重轮询(Weighted Round Robin)、IP 哈希(IP Hash)、最少连接(LeastConnections)以及第三方模块提供的Fair、URL Hash等。

4.高并发处理

        Nginx由于其事件驱动模型和多进程架构,特别适合处理高并发连接。例如,在高并发场景下,Nginx可以在一个工作进程中处理成千上万的连接,而不会因为线程或进程上下文切换导致性能下降。

5.静态资源缓存

        Nginx还可以作为一个静态内容服务器,特别擅长处理静态资源如图片、CSS、JavaScript文件的缓存。通过缓存策略,它可以极大地减少后端服务器的负载,并提升整体的响应速度。

6.模块化设计

        Nginx支持高度模块化,用户可以根据需求选择或编写自定义的模块。例如,使用SSL模块处理HTTPS请求,或者使用Gzip模块进行压缩等。

三、Nginx执行流程

        在 NGINX 中,处理客户端请求时,它的执行顺序主要遵循以下几个阶段。NGINX 的执行流程是基于事件驱动的,因此它对请求的处理遵循模块化的方式。每个请求会经过一系列预定义的阶段,确保请求按照正确的顺序被处理。

1.接收请求

        NGINX通过其事件驱动的架构接收到客户端请求。此时,主进程负责接收连接,并将请求分配给一个可用的工作进程(Worker)。请求被交给Worker后,进入请求处理流程。

2.选择服务器块(server block)

        NGINX首先会在配置文件中根据客户端请求的主机名和端口号,查找最合适的server块来处理请求。如果请求中包含了匹配的server_name和listen端口,NGINX将确定使用哪个server块来继续处理请求。
>按照listen指令和server_name指令来匹配。
>如果没有明确匹配的server_name,则使用default的server块。

3.选择位置块(location block)

        在确定了合适的server块后,NGINX接下来会根据请求的URI路径,查找最匹配的location块。location匹配返回顺序如下(重要):

 精确匹配

 如果使用=符号开头的location,表示精确匹配整个URI。
这种匹配优先级最高,如果找到,则立即使用该location,并停止进一步的匹配。

location = / {
    # 处理根路径的请求
}

带^~的前缀匹配

^~表示如果某个前缀匹配成功,不再进行正则表达式匹配,即优先匹配前缀。
这是用来指示NGINX优先使用前缀匹配而不是正则匹配的方式。

location ^~ /static/ {
    # 匹配所有以/static/开头的URI,并停止继续查找正则表达式匹配
}

正则表达式匹配

正则表达式匹配用于更加复杂的匹配规则。正则匹配在前缀匹配之后进行。
~用于大小写敏感的正则表达式匹配。
~*用于大小写不敏感的正则表达式匹配。
正则表达式从上到下匹配,不同的正则表达式在Nginx配置文件中的出现顺序,会影响匹配结果。

location ~ \.php$ {
    # 匹配所有以.php结尾的请求 (大小写敏感)
}
location ~* \.(jpg|jpeg|png)$ {
    # 匹配所有以.jpg, .jpeg, .png结尾的请求 (大小写不敏感)
}

前缀匹配(常规匹配)

NGINX默认情况下按前缀匹配。即URI以某个字符串开头,匹配定义的location块。
NGINX会找到最长的前缀匹配,所以常规匹配在Nginx配置文件中没有先后顺序要求。 

location /images/ {
    # 处理以 /images/ 开头的所有请求,不包括/images/1/
}

location /images/1/ {
    # 处理以/images/1/开头的所有请求
}

 通用匹配

如果没有其他location块匹配到URI,/会作为兜底匹配项。这是最通用的匹配,表示匹配所有请求。

location / {

# 匹配所有没有被其他 location 块处理的请求

}

4.处理重写规则(rewrite directives) 

        如果在server或location块中有rewrite指令,Nginx将在此时执行重写规则,改变URI并可能重新选择一个合适的location。重写规则允许修改请求的URI或跳转到其他处理方式。

 5.处理访问控制

        在处理完重写后,NGINX会检查任何访问控制相关的配置,比如IP限制、允许/禁止访问的规则(allow和deny指令)。如果请求被拒绝,NGINX会返回相应的错误响应。

6.处理代理或静态文件

        根据location块的配置,NGINX可能会执行不同的操作,如:
静态文件处理:如果请求的是静态文件,NGINX会直接从文件系统中读取并返回该文件。
反向代理:如果proxy_pass配置存在,NGINX会将请求转发给后端服务器,并将后端的响应返回给客户端。
FastCGI/uwsgi等应用层处理:如果配置了FastCGI、uwsgi等,NGINX会将请求转发给这些处理器。

7.执行过滤器

        NGINX可能会对响应进行多种过滤处理,比如:压缩响应数据(如启用了gzip)、添加或修改响应头信息、其他响应内容的处理。这些过滤器按照一定的顺序执行,确保响应在返回客户端之前被适当修改。

8.发送响应

        在完成请求处理后,NGINX将结果返回给客户端。响应可以是:来自后端服务器的动态内容;从缓存或文件系统中获取的静态内容;错误页面(如404或500)等。

9.记录日志

        最后,Nginx会根据配置将请求的处理结果记录到访问日志中(如access_log和error_log),便于后续分析和排错。

四、Nginx常用配置

1.反向代理负载均衡

        轮询(Round Robin),默认算法,将请求依次分发到每台服务器

upstream backend {
    server backend1.example.com;
    server backend2.example.com;
}

server {
    location /api {
        proxy_pass http://backend/api ;
    }
}

        权重轮询(Weighted Round Robin),根据权重分配请求,权重越高,分配的请求越多

upstream backend {
    server backend1.example.com weight=3;
    server backend2.example.com weight=1;
}

server {
    location /api {
        proxy_pass http://backend/api ;
    }
}

        IP 哈希(IP Hash),根据客户端的IP地址进行哈希计算,将请求分发到固定的服务器上

upstream backend {
    ip_hash;
    server backend1.example.com;
    server backend2.example.com;
}

server {
    location /api {
        proxy_pass http://backend/api ;
    }
}

        最少连接数(Least Connections),将请求分发到当前连接数最少的服务器上 

upstream backend {
    least_conn;
    server backend1.example.com;
    server backend2.example.com;
}

server {
    location /api  {
        proxy_pass http://backend/api ;
    }
}

        Fair,第三方模块,智能负载均衡算法,根据后端服务器的响应时间和负载情况来分配请求。与传统的轮询算法不同,Fair策略会优先将请求分配给响应时间较短、负载较轻的服务器,从而提高整体系统的性能和响应速度

upstream backend {
    fair;
    server backend1.example.com;
    server backend2.example.com;
}

server {
    location /api  {
        proxy_pass http://backend/api ;
    }
}

        URL Hash,第三方模块,通过对请求的URL进行哈希计算,将请求分配到特定的服务器上。这种策略特别适用于需要提高缓存命中率的场景

upstream backend {
    hash $request_uri;
    server backend1.example.com;
    server backend2.example.com;
}

server {
    location /api  {
        proxy_pass http://backend/api ;
    }
}

 2.日志输出

输出格式

        Nginx的日志输出为JSON格式是一个常见的需求,因为JSON格式的日志便于日志管理工具(如 ELK Stack)解析和分析。为了让Nginx以JSON格式输出日志,可以按照以下步骤配置:

        备份并编辑Nginx配置文件(通常是 /etc/nginx/nginx.conf

        修改 log_format 指令,将其格式化为 JSON 格式

http {
    log_format json_combined escape=json '{'
                                      '"time_local": "$time_local",'
                                      '"remote_addr": "$remote_addr",'
                                      '"remote_user": "$remote_user",'
                                      '"request": "$request",'
                                      '"status": "$status",'
                                      '"body_bytes_sent": "$body_bytes_sent",'
                                      '"http_referer": "$http_referer",'
                                      '"http_user_agent": "$http_user_agent",'
                                      '"http_x_forwarded_for": "$http_x_forwarded_for",'
                                      '"request_time": "$request_time",'
                                      '"upstream_response_time": "$upstream_response_time",'
                                      '"upstream_addr": "$upstream_addr",'
                                      '"upstream_status": "$upstream_status",'
                                      '"host": "$host"'
                                      '}';

    access_log /var/log/nginx/access.log json_combined;
}

输出字段

         Nginx默认的日志输出字段太少,不便于排查问题,流量分析等,我们可以添加输出的字段,例如:

$host:请求主机头字段,否则为服务器名称

$upstream_status:记录上游服务器返回的HTTP状态码
$upstream_addr:记录处理请求的上游服务器的地址
$upstream_response_time:记录从上游服务器接收到响应的时间
$http_x_forwarded_for: 客户端的真实ip(非常有用,根据返回的ip层级数量,可以筛选安全攻击事件)

$server_addr:服务器地址,在完成一次系统调用后可以确定这个值
$server_name:服务器名称
$server_port:请求到达服务器的端口号

$request_uri:包含请求参数的原始URI

$http_user_agent:客户端agent信息

$request_body:记录POST请求的body内容,这对于调试和监控非常有帮助

3.重写功能

rewrite

        Nginx的rewrite指令用于基于正则表达式修改请求的URI。它可以在serverlocationif块中使用,并支持多种标志(flags)来控制重写行为,以下是一些关键知识点和配置示例:

rewrite  [pattern]  [replacement]  [flags];

pattern:要匹配的URI模式可以使用正则表达式。
replacement:重写后的URI。
flags:控制重写行为的标志如last、break、redirect、permanent等。

其中几种flags的说明如下:

last:停止处理当前的重写规则,并重新发起一个新的请求来匹配新的location。这意味着重写后的URL会被重新解析并匹配新的location块。
break:停止处理当前的重写规则,但不会重新发起新的请求。这意味着重写后的URL不会被重新解析,只会在当前的location块内继续处理。
redirect:返回302临时重定向。
permanent:返回301永久重定向。

两个示例

location /old-url/ {
    rewrite ^/old-url/(.*)$  /new-url/$1  permanent;
}

#将所有以/old-url开头的请求重写为/new-url开头,并返回301永久重定向

if ($http_user_agent ~* "iPhone") {
    rewrite ^(.*)$  /mobile$1  break;

#iPhone用户的请求进行重写为/mobile开头

 return

        Nginx的return指令用于立即返回一个HTTP状态码和可选的响应体。它可以在serverlocation块中使用,常用于简单的重定向或返回特定的状态码:

server {
    listen 80;
    server_name example.com;
    return 301 https://$server_name$request_uri;
}

#将所有HTTP请求重定向到HTTPS,并返回301永久重定向

 4.缓存控制

浏览器缓存控制

        浏览器缓存可以通过设置HTTP头部字段来实现,主要包括强缓存和协商缓存

        强缓存指的是浏览器在缓存有效期内直接从缓存中读取资源,而不与服务器进行任何通信。可以通过以下指令配置:

location / {
    expires 30d;  # 设置缓存时间为30天
    add_header Cache-Control "public, max-age=2592000";  # 30天的秒数
}

        协商缓存指的是浏览器在每次请求资源时,都会向服务器确认资源是否更新。常用的HTTP头部字段包括Last-Modified和ETag 

location / {
    add_header Last-Modified $date_gmt;
    add_header ETag $request_uri;
    if_modified_since exact;
    etag on;
}

代理缓存控制

        Nginx还可以作为反向代理服务器缓存后端服务器的响应。首先,定义缓存的路径和一些参数:

proxy_cache_path /data/nginx/cache levels=1:2 keys_zone=my_cache:10m max_size=10g inactive=60m use_temp_path=off;

#/data/nginx/cache:缓存文件存储的路径。

#levels=1:2:缓存目录的层级结构,防止单个目录中包含过多文件。

#keys_zone=my_cache:10m:定义一个共享内存区域,用于存储缓存键和元数据。

#max_size=10g:缓存的最大大小。

#inactive=60m:未被访问的缓存项在60分钟后会被删除。

#use_temp_path=off:将缓存文件直接写入最终目录,避免不必要的数据复制

然后,在需要缓存的location块中启用代理缓存:

server {
    listen 80;
    server_name example.com;

    location / {
        proxy_cache my_cache;
        proxy_pass http://backend_server;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_cache_valid 200 302 10m;
        proxy_cache_valid 404 1m;
        proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
    }
}

#proxy_cache my_cache:启用之前定义的缓存区域。

#proxy_pass http://backend_server:将请求转发到后端服务器。

#proxy_set_header:设置一些头部信息。

#proxy_cache_valid:定义不同响应状态码的缓存时间。

#proxy_cache_use_stale:在后端服务器出现错误或超时时,使用过期的缓存内容。

5.访问控制

        Nginx提供了强大的访问控制功能,可以通过 allowdeny指令来基于IP地址进行访问控制。通过这些指令,你可以允许或禁止特定IP地址或IP段访问你的Nginx服务器资源。allowdeny可以在httpserverlocation 块中使用,以下是几个示例

location /admin {
    deny all;          # 禁止所有 IP 访问
    allow 192.168.1.1; # 允许特定 IP 访问
}

location / {
    allow all;           # 允许所有 IP 访问
    deny 192.168.1.100;  # 禁止特定 IP 访问

http {
    allow 192.168.1.0/24; # 全局允许指定 IP 段访问
    deny all;             # 全局禁止其他 IP 访问

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

炸裂狸花猫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值