NGINX - 高级负载均衡器、Web服务器、反向代理

发布时间 2024-01-07 18:04:39作者: 大数据老司机

一、概述

Nginx 是一个高性能的开源Web服务器,也可以用作反向代理服务器、负载均衡器和HTTP缓存。它的设计目标是提供高并发、低内存消耗和高度可伸缩性,使其成为处理大量并发连接的理想选择。以下是关于Nginx的一些关键特点和功能:

  • 高性能Nginx 的事件驱动架构和高效的内存使用使其能够处理大量并发连接,而不会消耗过多的系统资源。它被广泛用于构建高性能的Web服务器和应用程序。

  • 反向代理Nginx 可以作为反向代理服务器,将客户端的请求转发给后端的应用服务器。这对于提高应用的安全性、可伸缩性和灵活性非常有用。

  • 负载均衡Nginx 提供了负载均衡功能,可以平均分配流量到多个后端服务器,从而提高系统的稳定性和性能。负载均衡可以通过不同的算法进行配置,例如轮询、IP哈希、最小连接数等。

  • 静态文件服务和缓存Nginx 可以高效地提供静态文件服务,并支持HTTP缓存,减轻后端服务器的压力。它还能够通过gzip压缩来减小传输的数据量,提高网站的加载速度。

  • SSL/TLS支持Nginx 支持SSL/TLS协议,可以用于安全地加密传输数据。这对于保护用户隐私和确保数据完整性非常重要。

  • 模块化架构Nginx 的模块化架构允许用户根据需要添加或移除功能。它支持丰富的第三方模块,使得用户可以自定义和扩展Nginx的功能。

  • 日志记录Nginx 提供详细的访问日志和错误日志,方便管理员进行故障排除和性能调优。

  • 易于配置Nginx 的配置文件采用简洁而直观的语法,易于理解和维护。同时,它支持热加载配置,不需要重启即可生效配置更改。

  • 支持多协议:除了HTTP/HTTPSNginx 还支持其他网络协议,如SMTPIMAPPOP3等,使其具备更广泛的应用领域。

  • 活跃的社区和广泛的采用Nginx 是一个开源项目,拥有庞大的社区支持。由于其高性能和稳定性,它被广泛采用作为Web服务器和反向代理服务器。

总体而言,Nginx 是一个强大、灵活且高性能的Web服务器,适用于处理各种规模的网络流量和应用场景。

二、正向代理与反向代理解读

1)正向代理

正向代理是代理服务器位于客户端和目标服务器之间,代理服务器代表客户端向目标服务器发出请求。目标服务器不知道实际发起请求的是客户端,而是以为是代理服务器发起的。

在这里插入图片描述

使用场景:

  • 访问受限资源: 当客户端无法直接访问某些资源,但代理服务器可以访问,这时可以通过正向代理来获取目标资源。
  • 隐私保护: 客户端通过正向代理访问目标服务器,目标服务器无法直接识别客户端,从而保护了客户端的隐私。
客户端 --> 正向代理服务器 --> 目标服务器

【总结】正向代理可以通俗的理解就是需要客户端设置,面向用户的,对用户是感知的,例如:访问国外的网站,Google等,就需要配置代理。这个代理就是属于正向代理了。

2)反向代理

反向代理是代理服务器位于目标服务器和客户端之间,代理服务器代表目标服务器向客户端提供服务。客户端不知道实际提供服务的是目标服务器,而是以为是代理服务器提供的。
在这里插入图片描述

使用场景:

  • 负载均衡: 多个目标服务器提供相同服务,反向代理可以根据负载均衡算法将请求分发到不同的服务器,以提高系统性能和可用性。
  • 隐藏目标服务器: 反向代理可以隐藏后端的真实服务器,提高安全性。
客户端 --> 反向代理服务器 --> 目标服务器

【总结】反向代理跟正向代理正好相反,反向代理是代理后端服务器的,面向服务器端的,对用户是无感知的。例如:使用反向代理来实现负载均衡,将客户端的请求分发到多个服务器上,提高系统的性能和可扩展性。

三、NGINX 四层与七层代理

Nginx 可以作为四层(Layer 4)和七层(Layer 7)代理,这指的是它在 OSI 模型中的不同层次上提供代理服务的能力。
在这里插入图片描述

1)NGINX 四层代理

四层代理工作在 OSI 模型的传输层,主要基于网络协议信息(IP地址和端口号)来进行转发。

功能:

  • 基于 IP 地址和端口号: 四层代理根据源 IP 地址、目标 IP 地址、源端口号和目标端口号等信息进行转发决策。
  • 负载均衡: 可以进行四层的负载均衡,将请求分发到多个后端服务器,以提高系统的性能和可用性。

应用场景: 适用于需要基于传输层信息进行转发的场景,如负载均衡、TCP代理等。

示例配置如下:
在这里插入图片描述

2)NGINX 七层代理

七层代理工作在 OSI 模型的应用层,可以理解为能够读取和理解 HTTP/HTTPS 协议的代理。

功能:

  • 基于应用层代理: 七层代理不仅考虑网络协议信息,还能够读取和理解 HTTP 头部等应用层信息,以进行更精细的处理。
  • 反向代理: 可以用于反向代理,根据请求的 URL、域名、Cookie 等信息进行转发决策。

应用场景: 适用于需要深度理解和处理应用层协议信息的场景,如反向代理、内容缓存等。

示例配置如下:

在这里插入图片描述

四、NGINX 安装

1)yum 安装

# 安装EPEL的源
yum -y install epel-release
# 安装nginx
yum -y install nginx

# 默认路径
/usr/sbin/nginx
/etc/nginx/nginx.conf
/usr/share/nginx/html

2)源码编译安装

1、下载源码包

官方地址:http://nginx.org

wget https://nginx.org/download/nginx-1.24.0.tar.gz
tar -xf nginx-1.24.0.tar.gz

2、编译

yum install -y gcc pcre-devel openssl-devel

./configure --prefix=/usr/local/nginx --with-http_ssl_module --with-http_stub_status_module
make
make install

3)access 与 error 日志配置

1、log_format 字段讲解

在 Nginx 中,log_format 用于定义日志的格式,可以根据实际需求自定义日志的内容。以下是一些常见的 log_format 字段及其含义:

常用字段:

  • $remote_addr: 客户端的 IP 地址。

  • $remote_user: 通过 HTTP 基本认证的用户名,如果没有认证则为空。

  • $time_local: 本地时间,日志记录的时间。

  • $request: 客户端的请求行,包括请求方法、请求路径、HTTP 协议版本。

  • $status: HTTP 状态码,表示请求的处理结果。

  • $body_bytes_sent: 发送给客户端的响应正文的字节数。

  • $http_referer: 表示从哪个 URL 链接访问过来的。

  • $http_user_agent: 客户端浏览器的相关信息。

  • $http_x_forwarded_for: 客户端的真实 IP 地址,如果通过代理,则该字段表示真实的客户端 IP。

  • $request_time: 请求处理的总时间,单位为秒。

  • $upstream_response_time: 从发起请求到收到上游服务器响应的时间,用于反向代理的场景。

  • $host: 请求中的主机头字段。

  • $server_addr: 服务器 IP 地址。

  • $server_port: 服务器端口号。

以下是一个常见的 log_format 示例:

#  log_format 的默认输出格式不是 JSON。Nginx 的默认日志格式是一种非 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 参数来确保特殊字符得到适当的转义,以便生成有效的 JSON。
# 示例二(json 格式):
log_format json 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"}';

此配置定义了一个名为 main 的日志格式,包含了常见的访问信息,可以在 access_log 中引用这个格式:

server {
    listen 80;
    server_name example.com;

    location / {
        root /usr/share/nginx/html;
        index index.html;
    }
	# log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"';
    # access_log /var/log/nginx/access.log main;
    log_format json 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"}';
  access_log /var/log/nginx/access.log json;
}

在特殊字符处理中,escape 参数有以下几个选项:

  • none: 默认选项,不进行特殊字符转义。

  • json: 将特殊字符进行 JSON 转义,确保日志是有效的 JSON。

  • default: 使用默认的转义规则,对一些特殊字符进行转义。

2、配置访问日志(Access Log)

访问日志用于记录客户端请求的详细信息,如访问时间、客户端 IP、请求方法、请求路径、HTTP 状态码等。

serverlocation 块中,使用 access_log 指令配置访问日志。

access_log 指令的基本语法如下:

access_log path [format [buffer=size] [gzip[=level]] [flush=time] [if=condition]];

其中:

  • path 是指定访问日志文件的路径。
  • format 是可选的参数,用于指定日志的格式。
  • 其他参数如 buffergzipflush 等是一些进一步的配置选项,用于控制日志的缓冲、压缩、刷新等行为。

示例配置:

server {
    listen 80;
    server_name example.com;

    location / {
        root /usr/share/nginx/html;
        index index.html;
    }
    
    log_format json 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"}';
  access_log /var/log/nginx/access.log json;
}

注意:在 Nginx 中,access_log 指令不涉及日志级别的概念,因为它主要用于配置访问日志的输出方式和格式,而不是定义不同级别的日志记录。而error_log有日志级别配置。

3、配置错误日志(Error Log)

在 Nginx 配置文件中,error_log 可以在全局级别(http 块)和 server 块级别进行配置。配置在 server 块中的 error_log 会覆盖全局配置。

在 Nginx 中,error_log 指令用于配置错误日志的输出。它的基本语法如下:

error_log file [level];

其中:

  • file 是指定错误日志文件的路径。
  • level 是可选参数,用于指定错误日志的级别。如果不指定级别,默认是 error

Nginx 支持以下几个错误日志级别:

  • debug: 详细的调试信息,用于排查问题,但在生产环境中通常不建议启用,因为会产生大量日志。

  • info: 提供一般性的信息,用于记录一些关键事件。

  • notice: 用于记录一些需要注意的信息,但不是错误。

  • warn: 记录警告信息。

  • error: 记录错误信息,这是默认级别。

  • crit: 记录关键性错误信息,通常表示发生了严重的问题。

  • alert: 记录需要立即采取行动的问题,通常需要管理员干预。

  • emerg: 紧急情况,系统无法继续运行,通常需要立即采取行动。

http {
    # 其他配置...

    error_log /var/log/nginx/error.log;
}

4)nginx.conf 配置

Nginx 的主要配置文件是 nginx.conf,该文件包含了全局配置、HTTP 模块配置以及一些其他模块的配置。以下是一个简单的 nginx.conf 配置文件,并对其中的各部分进行了说明:

# 创建七层与四层配置目录
mkdir vhosts tcp_proxy

nginx.conf 配置

user nginx;  # Nginx worker 进程的运行用户
worker_processes auto;  # 根据 CPU 核数自动设置 worker 进程数
pid /usr/local/nginx/logs/nginx.pid;  # 进程 ID 文件路径

events {
    worker_connections 1024;  # 每个 worker 进程允许的最大连接数
}

http {
    include /usr/local/nginx/conf/mime.types;  # 包含 MIME 类型配置文件
    default_type application/octet-stream;  # 默认 MIME 类型

    sendfile on;  # 启用 sendfile,提高文件传输性能
    tcp_nopush on;  # 启用 tcp_nopush 优化
    tcp_nodelay on;  # 启用 tcp_nodelay 优化
    keepalive_timeout 65;  # 客户端与服务器连接的超时时间
    types_hash_max_size 2048;  # MIME 类型哈希表大小

    log_format json 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"}';

    access_log /usr/local/nginx/logs/access.log json; # 访问日志文件路径
    error_log /usr/local/nginx/logs/error.log error;  # 错误日志文件路径

    server {
        listen 80;  # 监听端口号
        server_name example.com;  # 服务器名称

        location / {
            root /usr/local/nginx/html;  # 网站根目录
            index index.html;  # 默认首页文件
        }

        # 可以添加更多的 server 块配置,用于定义不同的虚拟主机
    }

    # 可以添加更多的 server 块配置,用于定义不同的虚拟主机
}

include /usr/local/nginx/conf/vhosts/*.conf;  # 七层代理配置文件
include /usr/local/nginx/conf/tcp_proxy/*.conf;  # 七层代理配置文件

上述配置文件中的说明如下:

  • user:指定 Nginx worker 进程的运行用户。
  • worker_processes:指定 Nginx 启动的 worker 进程数,使用 auto 表示自动根据 CPU 核数设置。
  • error_log:指定错误日志文件的路径。
  • pid:指定 Nginx 进程 ID 文件的路径。
  • events:定义全局事件模块的配置,如 worker 进程的连接数等。
  • http:定义全局 HTTP 模块的配置,包括 MIME 类型、默认类型等。
  • include:包含其他配置文件,通常用于将配置分散到多个文件中以便管理。
  • server:定义虚拟主机的配置,包括监听的端口号、服务器名称、根目录等。
  • location:定义请求匹配的位置和处理规则,通常用于配置 URL 路由和反向代理。

5)启动nginx

# 检测nginx语法
nginx
# 查看nginx进程
ps -ef|grep nginx

6)配置启动脚本 nginx.service

# /usr/lib/systemd/system/nginx.service
[Unit]
Description=The nginx HTTP and reverse proxy server
After=network-online.target remote-fs.target nss-lookup.target
Wants=network-online.target

[Service]
Type=forking
PIDFile=/usr/local/nginx/logs/nginx.pid
# Nginx will fail to start if /run/nginx.pid already exists but has the wrong
# SELinux context. This might happen when running `nginx -t` from the cmdline.
# https://bugzilla.redhat.com/show_bug.cgi?id=1268621
ExecStartPre=/usr/bin/rm -f /usr/local/nginx/logs/nginx.pid
ExecStartPre=/usr/local/nginx/sbin/nginx -t
ExecStart=/usr/local/nginx/sbin/nginx
ExecReload=/usr/local/nginx/sbin/nginx -s reload
KillSignal=SIGQUIT
TimeoutStopSec=5
KillMode=process
PrivateTmp=true

[Install]
WantedBy=multi-user.target

启动

# 先把上面启动的nginx停掉
pkill -9 nginx
# 从新加载脚本配置
systemctl daemon-reload
# 开机自启
systemctl  enable nginx
# 
systemctl  start nginx
systemctl  stop nginx

7)从新加载nginx配置

# 检测配置是否正常
nginx -t
# 重新加载配置
nginx -s reload

8)nginx 日志滚动切割

Nginx 中,日志切割和滚动是通过外部工具来完成的,常见的工具包括 logrotatelogrotate 是一个用于管理日志文件的工具,它可以定期滚动、压缩和删除日志文件,以避免日志文件无限增长。

以下是一个简单的示例,演示如何使用 logrotate 配合 Nginx 进行日志切割和滚动:

1、安装 logrotate

# CentOS/RHEL
sudo yum -y install logrotate

2、创建 logrotate 配置文件

创建一个 logrotate 配置文件,例如 /etc/logrotate.d/nginx

sudo vi /etc/logrotate.d/nginx

在文件中添加以下内容:

/usr/local/nginx/logs/*.log {
    daily
    rotate 7
    missingok
    notifempty
    compress
    delaycompress
    sharedscripts
    postrotate
        if [ -f /usr/local/nginx/logs/nginx.pid ]; then
            kill -USR1 `cat /usr/local/nginx/logs/nginx.pid`
        fi
    endscript
}

这个配置文件指示 logrotate 对 /var/log/nginx/ 目录下的所有 .log 文件进行日志切割。配置中的一些关键选项包括:

  • daily:每天滚动一次日志。
  • rotate 7:保留过去 7 天的日志文件。
  • compress:使用 gzip 压缩旧的日志文件。
  • delaycompress:延迟压缩,直到下一次滚动时再进行压缩。
  • postrotateendscript:在滚动后执行的命令块,用于通知 Nginx 重新打开日志文件。
  • size :如果你使用了 size 选项来指定日志文件大小,logrotate 只有在达到指定大小时才会滚动。如果当前日志文件大小未达到设定的阈值,就不会滚动。

3、测试 logrotate

可以手动运行 logrotate 进行测试,查看是否能够正确地滚动和压缩日志文件。

# 没达到要求就不会滚动
sudo logrotate -d /etc/logrotate.d/nginx

#  如果你确实希望手动强制执行一次日志滚动,你可以使用以下命令:
sudo logrotate -f /etc/logrotate.d/nginx
# 这里的 -f 选项表示强制执行,即使认为不需要滚动也进行滚动。注意,手动滚动日志时,可能会打断正在运行的 Nginx 进程,所以最好在低流量时执行。
  • -d 选项用于调试模式,实际执行时可以去掉该选项。

logrotate 将在每天的指定时间运行,默认情况下,它通常是系统的日志轮询时间(通常是凌晨)。这样,你就可以使用 logrotate 来定期维护和管理 Nginx 的日志文件,避免日志文件不断增大导致磁盘空间耗尽。

五、四层与七层代理配置

1)四层代理配置

cd /usr/local/nginx/conf/tcp_proxy/
# vi tcp_proxy.conf

stream {
    upstream backend {
        server backend1.example.com:8080;;
        server backend2.example.com:8080;;
        # Add more backend servers as needed
    }

    server {
        listen 8080;
        proxy_pass backend;
    }
}

解释一下这个配置:

  • stream 模块用于配置四层代理。
  • upstream 块定义了后端服务器的地址和端口,你可以根据需要添加更多的后端服务器。
  • server 块定义了监听的端口(在这里是 80),并通过 proxy_pass 将流量代理到定义的后端服务器上。

重新加载配置

nginx -t 
nginx -s reload

如果报错:

nginx: [emerg] unknown directive "stream" in /usr/local/nginx/conf/tcp_proxy/tcp_proxy.conf:1 nginx: configuration file /usr/local/nginx/conf/nginx.conf test failed

安装stream模块

yum -y install epel-release
yum -y install nginx-all-modules.noarch

重新编译nginx,加入stream模块

# --with-stream=dynamic
./configure --prefix=/usr/local/nginx --with-http_ssl_module --with-http_stub_status_module --with-stream=dynamic
# 重新编译
make
make install

nginx.conf 最顶部加入:

load_module /usr/lib64/nginx/modules/ngx_stream_module.so;

如果还是报错,则直接拷贝nginx源码objs中的文件

cp ./objs/ngx_stream_module.so /usr/lib64/nginx/modules/

2)七层代理配置

在 Nginx 中进行七层代理,通常指的是 HTTP 代理,它能够理解和操作 HTTP 协议,能够进行更精细的请求分发和处理。以下是一个简单的七层代理配置示例:

cd /usr/local/nginx/conf/vhosts
vi http_proxy.conf

http {
    upstream backend {
        server backend1.example.com;
        server backend2.example.com;
        # Add more backend servers as needed
    }

    server {
        listen 80;

        location / {
            proxy_pass http://backend;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }
    }
}

这个配置的解释如下:

  • upstream 块定义了后端服务器的地址。在这里,backend1.example.combackend2.example.com 是代理请求的后端服务器。你可以根据需要添加更多的后端服务器。

  • server 块定义了监听的端口(在这里是 80),并配置了一个基本的请求代理。

  • location / 块指定了代理的路径,即所有路径。你可以根据需要修改这个路径。

  • proxy_pass 指令将请求代理到定义的后端服务器。

  • proxy_set_header 指令用于设置转发给后端服务器的一些 HTTP 头信息,以确保后端服务器能够正确获取客户端的真实信息。

这个配置允许 Nginx 接收来自客户端的 HTTP 请求,然后将这些请求代理到后端服务器上,并在代理过程中保留了一些原始的 HTTP 头信息。


NGINX - 高级负载均衡器、Web服务器、反向代理简单讲解就先到这里了,上面的内存只是nginx的最基础的部分,后部分更精彩,有任何疑问也可关注我公众号:大数据与云原生技术分享,进行技术交流,如本篇文章对您有所帮助,麻烦帮忙一键三连(点赞、转发、收藏)~