项目刚上线时,用户使用少,并发量小,在这种情况下,在这种情况下,一个jar包部署到一台服务器上启动就满足需求了。
随着,平台使用的用户量增多,并发量也慢慢增大,这种情况下一台服务器已经满足不了需求了。这时就会横向扩展,增加服务器。这个时候几个项目启动在不同的服务器上,用户要访问,就需要增加一个代理服务器了,通过代理服务器来帮我们转发和处理请求。
我们需要这个代理服务器可以接收用户的请求,然后将用户的请求按照规则转发到不同的服务器节点之上,并且这个过程用户是无感知的,用户不需要知道哪个服务器返回的结果。由此我们使用了Nginx。
Nginx (engine x) 是一个高性能的开源反向代理服务器,也可以用作 HTTP 服务器、负载均衡器、邮件代理服务器等。它是由伊戈尔·赛索耶夫为俄罗斯访问量第二的Rambler.ru站点开发的,第一个公开版本0.1.0发布于2004年10月4日。
Nginx的特点是占有内存少,并发能力强。由于nginx的并发能力在同类型的网页服务器中表现较好,国内有很多大公司都使用Nginx,比如百度、腾讯、淘宝等。
Nginx代码完全用C语言从头写成。官方数据测试表明能够支持高达 5万 个并发连接数的响应。
Nginx 可以作为反向代理服务器,接收客户端的请求,然后将请求转发给后端的服务器,最后将后端服务器的响应返回给客户端。这有助于隐藏后端服务器的真实 IP 地址,提高了系统的安全性。
以百度为例,百度的请求地址永远是www.baidu.com,而请求的服务器可能是深圳服务器,北京服务器,上海服务器等,其中就是通过Nginx代理服务器作为跳板访问别的服务器的。
扩展:正向代理是指代理客户端,反向代理指代理服务器端。
反向代理使用proxy_pass指令来配置,如
server {
listen 80;
location / {
proxy_pass http://192.168.243.30:5000;
}
}
当访问http://localhost:80时就会被代理到http://192.168.243.30:5000上。
还可以进一步配置成server_group的形式,为后面的负载均衡做准备:
upstream api_server {
server 192.168.243.30:5000;
server 192.168.243.30:5001;
}
server {
listen 80;
location / {
proxy_pass http://api_server;
}
}
Nginx 具有负载均衡的功能,可以将来自客户端的请求分发到多个后端服务器,以均衡服务器的负载。这有助于提高系统的可伸缩性和稳定性。
在 Nginx 中,负载均衡是通过 upstream 模块实现的。Nginx 提供的负载均衡策略有2种:内置策略和使用第三方模块实现更多的扩展策略。以下是这两种类型的一些策略:
Nginx 内置的负载均衡策略主要包括以下几种:
(1)轮询(Round Robin): 默认策略,将每个请求依次分配到不同的后端服务器上,实现简单且均匀的负载分布。
upstream api_server {
server 192.168.243.30:5000;
server 192.168.243.30:5001 weight=2 max_fails=2 fail_timeout=10;
}
扩展:
以上有3个指令可通过需要添加:
(1)weight:用于配置轮询目标的权重,默认权重都是1。如上设置目标1权重为2,则2/3的请求会被导向目标1中。
(2)max_fails:设置调用失败的次数,超过设定的次数后,nginx会认为这个目标不可用。默认为1次,如果被设置为0,健康检查会被禁用。
(3)fail_timeout:设置将目标标记为不可用的时长,默认为10秒,超过这个时间后,nginx会尝试将少部分流量导到这个目标,如果目标恢复响应,则取消其不可用标记。
(2)最小连接数(Least Connections): 将请求发送到当前连接数最少的服务器,这样可以尽量避免有些已经很繁忙的服务器过载。
upstream api_server {
least_conn;
server 192.168.243.30:5000;
server 192.168.243.30:5001;
}
(3)IP 哈希(IP Hash): 基于客户端 IP 地址的哈希算法,确保相同的客户端 IP 的请求被发送到相同的后端服务器,适用于某些需要保持会话的场景。
upstream api_server {
ip_hash;
server 192.168.243.30:5000;
server 192.168.243.30:5001;
}
(4)泳道(Least Time): 将请求发送到响应时间最短的服务器,通常用于后端服务器的性能差异比较大的情况。
Nginx 也支持通过第三方模块实现更多的负载均衡策略。例如,nginx-upsync-module
提供了动态发现和删除后端服务器的功能。
在这些扩展中,一些常见的扩展负载均衡策略包括:
加权轮询(Weighted Round Robin): 为每个后端服务器分配一个权重,以决定其接收请求的频率。
加权最小连接数(Weighted Least Connections): 将请求发送到当前连接数加权最小的服务器,考虑到服务器性能和权重。
URL 哈希(URL Hash): 基于请求的 URL 进行哈希,确保相同的 URL 请求被发送到相同的后端服务器。
自适应(Adaptive Load Balancing): 根据后端服务器的性能动态调整权重,以适应实时的负载情况。
这些扩展策略允许根据具体需求进行更灵活的配置,以满足不同应用场景的负载均衡需求。
动静分离是指将动态生成的内容(通常是由应用服务器动态生成的)与静态内容(如图片、CSS 文件、JavaScript 文件等)分开处理,从而提高网站的性能和扩展性。这通常是通过将请求分发到不同的服务器或处理路径上来实现的。
Nginx 最初是设计用于处理静态内容的,但它现在也支持 FastCGI、uWSGI、SCGI 等协议,从而可以处理动态生成的内容,如 PHP、Python 和 Java等。
以下是实现 Nginx 动静分离的主要方法:
(1)代理请求到后端应用服务器:将动态请求(如 PHP、Python、Java 等应用生成的请求)代理到后端应用服务器(如应用服务器集群)进行处理。
location /dynamic/ {
proxy_pass http://backend_dynamic_server;
}
(2)直接服务静态内容:将静态内容的请求直接由 Nginx 处理,而不必通过后端应用服务器。这通常包括图片、样式表、脚本等静态资源。还可以缓存静态内容到Nginx服务器上,从而加速后续的访问。
location /static/ {
alias /path/to/static/files;
expires 1d; # 可设置缓存过期时间,也可去掉
}
(3)路径重写:通过 Nginx 的路径重写规则,将特定路径的请求分发到后端应用服务器,而其他路径的请求直接由 Nginx 处理。
location / {
try_files $uri $uri/ /index.php?$query_string;
}
(4)CDN 集成:使用 CDN(内容分发网络)来缓存和分发静态资源,将静态内容分发到全球各地的 CDN 节点,减轻源服务器的负载。
扩展:什么是CDN?
CDN(Content Delivery Network, 内容分发网络)是为加快网络访问速度而建立在现有网络之上的分布式网络,它依靠部署在全球各地边缘节点的服务器群,通过负载均衡,内容发布,内容管理和内容存储的功能,由CDN服务器集群分担源站点服务器集群的压力,使用户可以就近获取已缓存的访问资源,避免网络拥堵,加快访问速度。与此同时,CDN是基于DNS解析进行管理的,其利用DNS技术和HTTPS协议确保了传输内容的安全性,保障用户的访问内容的安全性。
通过这些配置,Nginx 可以根据请求的类型将其动静分离,提高了系统的性能和可伸缩性。这种架构的优点在于可以通过独立扩展静态内容的服务器或 CDN 来优化性能,同时灵活配置动态内容的处理方式。
Nginx 可以用作静态内容的 HTTP 服务器。它能够高效地处理静态文件的服务请求,释放后端服务器的资源,提高网站的性能和响应速度。
举例:
(1)创建一个简单的 HTML 文件,比如
index.html
,并将其放在 Nginx 默认的静态文件目录,现在放在/var/www/html/
目录下。(2)编辑Nginx 的配置文件
nginx.conf
,确保以下内容:server { listen 80; server_name localhost; location / { root /var/www/html; index index.html; } # 可以添加更多的配置,如日志记录等 }
(3)重启Nginx,通过浏览器访问服务器http://localhost:80,可看到index.html的页面了。
Nginx 可以充当 SSL/TLS 的终端,负责加密和解密来自客户端的请求和向后端服务器发送的请求。这有助于保护数据的安全性。
以下是配置 Nginx 作为 SSL/TLS 终端的基本步骤:
(1)获取 SSL 证书和密钥:可购买 SSL 证书,也可使用免费的证书颁发机构(CA)如 Let's Encrypt 提供的证书。
(2)编辑Nginx 的配置文件
nginx.conf
:server { listen 443 ssl http2; # 指定 Nginx 监听 443 端口,并启用 SSL和http2(协议可选填) server_name yourdomain.com; # 服务名,替换为你的域名 ssl_certificate /path/to/your/certificate.crt; # SSL证书本地路径 ssl_certificate_key /path/to/your/private.key; # SSL证书私钥的路径 ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # 定义支持的 SSL/TLS 协议版本 ssl_prefer_server_ciphers on; # 告诉Nginx 优先使用服务器端定义的密码套件 ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH'; # 设置密码套件 # (可选配置) 启用 HSTS(HTTP Strict Transport Security) add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; # (可选配置) HTTP 重定向到 HTTPS server { listen 80; server_name yourdomain.com; return 301 https://$host$request_uri; } location / { # 你的其他配置项 } }
(3)检查配置并重新加载 Nginx
# 判断是否有语法错误 sudo nginx -t # 重启nginx服务 sudo service nginx reload
3.4.3 反向代理缓存
Nginx 对于静态或相对不经常更改的内容缓存到后端服务器中,从而减轻后端服务器的负担,提高系统的性能。
以下是配置Nginx反向代理缓存的基本步骤:
1、新建用于缓存文件的目录/var/cache/nginx
2、 编辑Nginx 的配置文件
nginx.conf
:# proxy_cache_path定义了缓存路径、层次、缓存名称和大小等参数。 # levels定义了缓存目录的层次结构; # keys_zone定义了缓存名称和分配的内存大小; # max_size定义了缓存的最大大小; # inactive定义了缓存文件在多久没有被访问后被视为不活跃; # use_temp_path=off表示直接在缓存路径中存储缓存文件,而不会在缓存路径下创建一个临时文件夹 proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m max_size=10g inactive=60m use_temp_path=off; server { listen 80; server_name yourdomain.com; location / { proxy_pass http://backend_server; # 指定了代理到的后端服务器地址 proxy_set_header Host $host; # 将原始请求的 Host 头传递给后端服务器。 proxy_set_header X-Real-IP $remote_addr; #将客户端真实 IP 地址传递给后端服务器。 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 将客户端的原始 IP 地址传递给后端服务器,即使请求通过多个代理。 proxy_set_header X-Forwarded-Proto $scheme; # 传递客户端请求的协议(http 或 https)给后端服务器,有助于后端服务器判断请求是否通过了 SSL/TLS。 # 启用缓存 proxy_cache my_cache; # 定义缓存的名称 proxy_cache_key "$scheme$host$request_uri"; # 定义缓存的 key,key可以确保唯一性(可选) proxy_cache_valid 200 302 10m; # 设置不同HTTP状态码的缓存时间。 proxy_cache_valid 404 1m; proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504; # 允许在后端服务器不可用时使用旧的缓存数据 proxy_cache_bypass $http_upgrade; # 防止缓存的一部分请求,如 WebSocket 请求。 } }
3.4.4 高并发处理
Nginx 采用异步事件驱动的架构,能够高效处理大量并发连接,适用于高访问量的网站和应用。
以下是 Nginx 异步事件驱动模型的一些关键特征:
事件驱动: Nginx 的设计中,所有的 I/O 操作都是异步和非阻塞的。这意味着当一个请求触发一个 I/O 操作时,Nginx 不会等待 I/O 操作完成,而是将其挂起,并继续处理其他请求。一旦 I/O 操作完成,Nginx 会通过事件回调的方式得知,然后再处理这个请求。
事件模块: Nginx 使用事件模块来管理事件的触发和处理。事件模块负责监控文件描述符上的事件,如新连接的建立、数据的到达等。Nginx 支持多种事件驱动模块,包括
epoll
(在 Linux 上的事件模型)、kqueue
(在 FreeBSD、Mac OS X 上的事件模型)等,以适应不同的操作系统。工作进程: Nginx 使用多进程的方式工作。一个主进程负责管理配置、启动子进程、接受新连接,而多个工作进程负责处理实际的请求。每个工作进程都是独立的,它们之间通过共享内存来交换信息。
无锁设计: Nginx 尽量避免使用锁,因为锁会引起阻塞,而 Nginx 旨在实现高并发和低延迟。它使用了一些无锁的数据结构,如基于原子操作的计数器和队列,以减小锁的使用。
连接池: Nginx 使用连接池来提高性能。连接池预先分配一些连接,当有新的请求到来时,Nginx 从连接池中获取一个可用连接,而不是每次请求都去创建新的连接。
定时器: Nginx 使用定时器来处理超时和一些需要延迟执行的任务。这允许 Nginx 在处理请求的同时,能够管理定时事件而不会阻塞整个进程。
这种异步事件驱动的架构使得 Nginx 能够高效地处理大量并发连接,而不会因为阻塞等待 I/O 操作而浪费系统资源。
3.4.5 HTTP/2 和 WebSocket 支持
Nginx 支持 HTTP/2,提供更高效的页面加载速度。它还支持 WebSocket 协议,使其成为实时通信应用的理想选择。
(1)HTTP/2支持:
server { listen 443 ssl http2; # 指定 Nginx 监听 443 端口,并启用 SSL和http2(协议可选填) server_name yourdomain.com; # 服务名,替换为你的域名 ssl_certificate /path/to/your/certificate.crt; # SSL证书本地路径 ssl_certificate_key /path/to/your/private.key; # SSL证书私钥的路径 # 其他SSL配置 location / { # 你的其他配置项 } }
(2)WebSocket支持:
WebSocket 是一种在单个 TCP 连接上进行全双工通信的协议。为了支持 WebSocket,可以使用
proxy_pass
来代理 WebSocket 连接。server { listen 80; server_name yourdomain.com; location /ws { proxy_pass http://backend_server; # 指定后端 WebSocket 服务器的地址 proxy_http_version 1.1; # 设置代理的 HTTP 版本 proxy_set_header Host $host; # 将原始请求的 Host 头传递给后端服务器。 proxy_set_header Upgrade $http_upgrade; #允许升级为 WebSocket 协议。 proxy_set_header Connection "upgrade"; #允许升级为 WebSocket 连接。 # 可以添加其他代理相关的配置 } # 其他配置项 }
3.4.6 邮件代理服务器
Nginx 不仅可以用于 HTTP 服务,还可以作为邮件代理服务器,支持 POP3 和 IMAP4 协议。
Nginx具有以下优点:
高性能:相比于其他Web服务器如Apache,在正常请求以及高峰请求期,可以更快地响应请求。
高可靠:Nginx采用多进程模型,分为主进程和工作进程。主进程负责监视工作进程,当工作进程异常退出时,可以快速拉起一个新的工作进程,从而为用户提供稳定服务
高并发:Nginx通常作为网关级服务,其支持的并发量通常在万级别,经过优化甚至可以达到十万级别。
易扩展:Nginx是模块化设计,具有极高的扩展性,使用者可以根据自身需求,定制开发相应模块。
热部署:Nginx提供了优雅重启以及平滑升级的方案,使用户在修改配置文件或者升级Nginx时,不会影响线上服务。
跨平台:支持Linux、Windows、macOS多种平台。