欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  科技

Nginx反向代理负载均衡配置详解

程序员文章站 2022-06-19 10:01:40
一、Nginx特性Nginx使用可扩展的事件驱动,不是传统的过程驱动架构。在传统的Web服务器体系结构中,每个客户端连接作为一个单独的进程或线程处理,随着网站的流行度增加,并发连接数量的增加,Web服务器减慢,延迟了对用户的响应。从技术角度来看,产生一个单独的进程/线程需要将CPU切换到新的任务并创建一个新的运行时上下文,消耗额外的内存和CPU时间,从而对性能产生负面影响。Nginx开发的目标是实现10倍以上的性能,优化服务器资源的使用,同时也能够扩展和支持网站的动态增长。因此,Nginx成为最知名...

一、Nginx特性

Nginx使用可扩展的事件驱动,不是传统的过程驱动架构。
在传统的Web服务器体系结构中,每个客户端连接作为一个单独的进程或线程处理,随着网站的流行度增加,并发连接数量的增加,Web服务器减慢,延迟了对用户的响应。
从技术角度来看,产生一个单独的进程/线程需要将CPU切换到新的任务并创建一个新的运行时上下文,消耗额外的内存和CPU时间,从而对性能产生负面影响。

Nginx开发的目标是实现10倍以上的性能,优化服务器资源的使用,同时也能够扩展和支持网站的动态增长。因此,Nginx成为最知名的模块化,时间驱动,异步,单线程Web服务器和Web代理之一。

Nginx是一个高性能的Web和反向代理服务器,它具有很多非常优越的特性:
1)作为Web服务器
相比 Apache, Nginx 使用更少的资源,支持更多的并发连接,体现更高的效率,这点使 Nginx尤其受到虚拟主机提供商的欢迎。能够支持高达 50,000 个并发连接数的响应,感谢 Nginx为我们选择了 epoll and kqueue 作为开发模型。

2)作为负载均衡服务器
Nginx 既可以在内部直接支持 Rails 和 PHP,也可以支持作为 HTTP 代理服务器 对外进行服务。 Nginx 用 C 编写, 不论是系统资源开销还是 CPU 使用效率都比 Perlbal 要好的多。

3)作为邮件代理服务器
Nginx 同时也是一个非常优秀的邮件代理服务器(最早开发这个产品的目的之一也是作为邮
件代理服务器), Last.fm 描述了成功并且美妙的使用经验。

Nginx 安装非常的简单,配置文件 非常简洁(还能够支持 perl 语法), Bugs 非常少的服务器。
Nginx 启动特别容易,并且几乎可以做到 7*24 不间断运行,即使运行数个月也不需要重新启动。
你还能够在 不间断服务的情况下进行软件版本的升级。


二、Nginx架构

nginx 大量使用复用和事件通知,并专门用于分离进程的特定任务。 连接在有限数量的单线程进程称为工作(worker)的高效运行循环中处理。 在每个工作(worker)中, nginx 可以处理每秒数千个并发连接和请求。

2.1 代码结构

Nginx反向代理负载均衡配置详解

Nginx工作(worker)码包括核心和功能模块。 nginx 的核心是负责维护严格的运行循环,并在请求处理的每个阶段执行模块代码的适当部分。 模块构成了大部分的演示和应用层功能。 模块读取和写入网络和存储,转换内容,执行出站过滤,应用服务器端包含操作,并在代理启动时将请求传递给上游服务器。

nginx 的模块化架构通常允许开发人员扩展一组 Web 服务器功能,而无需修改 nginx 内核。 nginx 模块略有不同,即核心模块,事件模块,阶段处理程序,协议,可变处理程序,过滤器,上游和负载平衡器。 nginx 不支持动态加载的模块; 即在构建阶段将模块与核心一起编译。

在处理与接受,处理和管理网络连接和内容检索相关的各种操作时,nginx 在基于 Linux,Solaris 和 BSD 的操作系统中使用事件通知机制和一些磁盘 I/O 性能增强,如: kqueue, epoll,和事件端口。 目标是为操作系统提供尽可能多的提示,以便及时获取入站和出站流量,磁盘操作,读取或写入套接字,超时等异步反馈。 对于每个基于 Unix 的 nginx 运行的操作系统,大量优化了复用和高级 I/O 操作的不同方法的使用。


2.2 工作模式

Nginx不会为每一个连接生成一个进程或线程。相反,worker进程接受来自共享“listen”套接字的新请求,并在每个worker内执行高效的运行循环,以处理每个worker中的数千个连接。
worker是由操作系统内核机制完成。

启动后,将创建一组初始侦听套接字,然后worker在处理HTTP请求和响应时不断接受、读取和写入套接字。运行循环是 nginx worker代码中最复杂的部分。 它包括全面的内部调用,并且在很大程度上依赖异步任务处理的想法。 异步操作通过模块化,事件通知,广泛使用回调函数和微调定时器来实现。 总体而言,关键原则是尽可能不阻塞。

nginx 仍然可以阻塞的唯一情况是worker进程没有足够的磁盘存储

内存:绝大多数情况下,内存使用非常保守,非常有效,因为nginx不会连接一个进程或线程。
CPU:节省CPU周期,因为进程或线程没有持续的 ”创建-销毁“ 模式。

nginx 的作用是检查网络和存储的状态,初始化新连接,将其添加到运行循环中,并异步处理直到完成,此时连接被重新分配并从运行循环中删除。 结合仔细使用系统调用(syscall)和精确实现支持接口(如 pool 和 slab 内存分配器), nginx 通常可以在极端工作负载下实现中到低的CPU 使用。

在一些磁盘使用和 CPU 负载模式,应调整 nginx 工作(worker)的数量。建议:
1)如果负载模式是CPU密集型,如需处理大量TCP/IP,执行SSL或压缩,worker数量应与CPU内核数量匹配。
2)如果负载模式是磁盘IO绑定,如从存储或重代理服务不同的内容集合,worker的数量可能是核心数量的1到2倍。

现有worker模式问题,下面两种类型的行为将立即导致工作(worker)挂起的情况,同时影响到数千个连接。

  • 问题1:磁盘 I/O 上的大多数阻塞。如果没有足够的存储性能来提供特定工作(worker)生成的磁盘操作,该工作(worker)可能仍然阻止从磁盘读取/写入。
  • 问题2:与嵌入式脚本的有限支持有关。一个使用标准的 nginx 分发,只支持嵌入 Perl 脚本。一个简单的解释:关键问题是嵌入式脚本阻止任何操作或意外退出的可能性。

2.3 进程角色

nginx 在内存中运行多个进程; 有一个主进程和几个工作(worker)进程。 还有一些特殊用途的过程,特别是缓存加载器和缓存管理器。 所有进程都是单线程版本为 1.x 的 nginx。
所有进程主要使用共享内存机制进行进程间通信。主进程作为root用户运行。缓存加载器,缓存管理器和worker则无权限制用户运行。

》》主进程负责以下任务:

  • 读取和验证配置
  • 创建,绑定和关闭套接字
  • 启动,终止和维护配置的worker进程数
  • 重新配置,无需中断服务
  • 控制不间断的二进制升级(如果需要,启动新的二进制并回滚)
  • 重新打开日志文件
  • 编译嵌入式Perl脚本

》》worker进程接受和处理来自客户端的连接,提供反向代理和过滤功能,并执行几乎所有其他nginx能力。关于监视nginx实例的行为,系统管理员应该关注worker进程,因为它们是反应Web服务实际日常操作的过程。

》》缓存加载器进程负责检查磁盘缓存项目,并使用缓存元数据填充nginx的内存数据库。本质上,缓存加载器准备nginx实例来处理已经存储在磁盘上的特定分配的目录结构中的文件。它遍历目录,检查缓存内容元数据,更新共享内存的相关条目,然后在所有内筒清洁并准备使用时退出。

》》缓存管理器主要负责缓存到期和无效。在正常的nginx操作期间它保持在内存中,并且在失败的情况下由主进程重新启动。


2.4 缓存

在nginx中的缓存以文件系统上的分层数据存储的形式实现。
缓存密钥是可以配置的,并可以使用不同的请求特定参数来控制进入缓存的内筒。缓存密钥和缓存元数据存储在共享存储器段中,高速缓存加载,缓存管理器和worker可以访问它们。层次结构(级别和命名细节)通过 nginx 配置指令进行控制。 当响应写入缓存目录结构时,文件的路径和名称将从代理 URL 的 MD5 哈希导出。

将内容放入缓存的过程:

  • nginx从上游服务器读取响应时,内容首先写入缓存目录结构之外的临时文件。
  • nginx完成处理请求时,它重命名临时文件并将其转移到缓存目录。

若用于代理的临时文件目录位于另一个文件系统上,则该文件将被复制,因此建议将临时文件目录和缓存目录保存在同一个文件系统上。因此建议将临时文件目录和缓存目录保存在同一文件系统上。


三、Nginx应用

3.1 Nginx安装和操作的一些说明

1、安装
Nginx安装的时候同时需要安装一些依赖库。

  • pcre:负责做正则表达式。
  • openssl:用作MD5验证、NTPS加密。
  • zlib:用于压缩。

2、操作

  • 启动:sudo ./sbin/nginx -c ./conf/nginx.conf
  • 快速关闭服务:./sbin/nginx -s stop
  • 正常关闭服务:./sbin/nginx -s quit
  • 重新加载配置文件:./sbin/nginx -s reload
  • 重新打开日志文件:./sbin/nginx -s reopen

3.2 四层与七层负载均衡

分层模型
Nginx反向代理负载均衡配置详解

1)四层负载均衡
定义:
四层负载均衡工作在OSI模型的传输层,由于在传输层,只有TCP/UDP协议,这两种协议中除了包含源IP、目标IP以外,还包含源端口号及目的端口号。四层负载均衡服务器在接受到客户端请求后,以后通过修改数据包的地址信息(IP+端口号)将流量转发到应用服务器。
Nginx反向代理负载均衡配置详解

2)七层负载均衡
定义:
七层负载均衡工作在OSI模型的应用层,应用层协议较多,常用http、radius、dns等。七层负载就可以基于这些协议来负载。这些应用层协议中会包含很多有意义的内容。比如同一个Web服务器的负载均衡,除了根据IP加端口进行负载外,还可根据七层的URL、浏览器类别、语言来决定是否要进行负载均衡。
Nginx反向代理负载均衡配置详解
3)四层和七层的区别

  • 四层通过虚拟IP+端口接收请求,然后再分配到真实的服务器
  • 七层通过虚拟的URL或主机名接收请求,然后再分配给真实的服务器
  • 四层交换机主要分析IP层及TCP/UCP层,实现四层流量负载均衡
  • 七层交换机除了支持四层负载均衡外,还有分析应用层的信息,如HTTP协议,URI或Cookie信息
  • 四层负载均衡的本质是转发,七层负载均衡的本质是内容交换和代理

Nginx反向代理负载均衡配置详解
如果是http选择nginx做代理,如果是tcp使用haproxy。Nginx可以用于七层负载均衡。


3.3 应用

3.3.1 做负载均衡

服务器拓扑结构:
Nginx反向代理负载均衡配置详解
工作流程:
访问机器先访问路由器,然后再到Nginx,Nginx再把数据分发给同一局域网内的其他服务。
路由器也称为网关,而nginx为应用网关。路由器到nginx是通过端口映射(通过路由器或者交换机直接配置),当外部机器访问到路由器端口的时候直接对应的是nginx子网的机器。因此给人的感觉是nginx是对接在公网上。

比如:路由器对外提供的访问地址是112.93.116.78.8080,映射到nginx服务192.168.1.123.80。
Nginx反向代理负载均衡配置详解

DNS做负载均衡
一个域名映射多个IP地址,比如www.xzq.com–>通过域名解析的时候可以拿到多个IP地址(跟端口没关系),第一次响应的可能是第一个IP地址,第二次响应的可能是第二个IP地址,这里做的就是负载均衡。
该负载均衡跟开发没有什么关系,只需要配置号就行,其他不用管。

特点:响应没有那么及时,假设有一台机器宕机,需要同步到其他域名中的时候有可能会耗费10分钟之久。

》conf文件
在开发中核心的最常用的是conf文件。
conf文件的解析原理:解析conf文件中的worker_processes参数,通过源码搜索找到源码ngx_core_module函数,所有的模块都放到ngx_modules数组中。

conf文件配置说明

#每个worker_processes进程对应的连接数--每一个连接,可读可写的时候就是事件
events {
    worker_connections  1024; 
}
#http协议模块,如果是自己封装的通信协议,也可以在配置文件中作为一个模块
http { 
    server { 
#80为http默认端口,自定义端口最好大于1024
            	listen 8080; 
            	server_name  localhost; 
				#客户端请求body最大数量 网页设置小些,视频文件设置大些
				client_max_body_size 100m;	
				#要访问的网页或者文件
            	location / { 
                    root /usr/local/nginx/html/www; 
           		} 
            	location /images/ { 
                    root /usr/local/nginx/html; 
            	} 
        	} 
}

》http请求
http请求比较大的文件,有一个头range: 0–1024,都有一个对应的请求位置,如果服务器中的文件大小为500M,每次可以取25M,确定了开始和结束位置(位置由请求的客户端定义),就可以使用20个线程同时下载。比如第一个线程请求0-25,第二个线程请求26-50M…

问:20个线程,写入到同一个文件是不是回到了单线程处理?
事先已经分配好文件大小,每个线程写入到确定的位置即可。

问:磁头只有一个,写到盘里还是单线程?
磁盘SSD写入可以达到1G/s,软件写入一般比较快的100M/s。这里的瓶颈就不是磁盘的问题了。

问:断点续传是否可以分片,如果可以如何保证顺序?
断点续传也是需要分片的,但并非可以一个字节一个字节的续传:
1)多线程同时下载一个文件,需要确定每个线程的开始和结束位置。
2)断点续传,记住上一次的结束位置作为下一次的开始。

3.3.2 做代理

1、代理单台
Nginx反向代理负载均衡配置详解
A请求123,实际123会把数据传给168进行处理。123就是一个代理。

实例:
123服务器上IP地址为192.168.139.132,168服务器地址为192.168.139.133。

1)123服务的nginx.conf配置文件为:

events {
    worker_connections  1024; 
}
http { 
    server { 
            	listen 8080; 
            	server_name  localhost; 
				
            	location / { 
					proxy_pass http://192.168.139.133;
           		}  
        	} 
}

2)168服务的nginx.conf配置文件为:

events {
    worker_connections  1024; 
}
http { 
    server { 
            	listen 80; 
            	server_name  localhost; 
				
            	location / { 
					root   html;
   					 index  index.html index.htm;
           		}  
        	} 
}

3)启动123服务器Nginx,168服务器Nginx

./sbin/nginx -c ./conf/nginx.conf

4)使用网页访问123服务
Nginx反向代理负载均衡配置详解
可以看到显示的网页数据为168服务的数据。

2、代理多台
nginx.conf配置文件可以修改如下:

events {
    worker_connections  1024; 
}
http { 
		 upstream backend{
			server 192.168.139.133 weight=2;
			server 192.168.139.134 weight=1;
			}
    server { 
            	listen 80; 
            	server_name  localhost; 
				
            	location / { 
					proxy_pass http:// backend;
           		}  
        	} 
}

在网页请求Nginx服务,可以看到显示的网页不断在192.168.139.133和192.168.139.134服务之间进行切换。

指定轮询几率,weight 和访问比率成正比,用于后端服务器性能不均的情况。
那么 3次一般只会有 1 次会访问到 192.168.139.134,而有2 次会访问到192.168.139.133。

3.3.3 访问图片

1)在Nginx新建images文件夹,文件夹存放1.jpg 2.jpg 3.jpg三张图片。
Nginx反向代理负载均衡配置详解
2)修改nginx.conf 配置文件

events {
    worker_connections  1024; 
}
http { 
		 upstream backend{
			server 192.168.139.133 weight=2;
			server 192.168.139.134 weight=1;
		}
   		server { 
            	listen 80; 
            	server_name  localhost; 
				
            		location / { 
						proxy_pass http:// backend;
           			}  
				
					location /images/ { 
						root ./;
           			}
       		 } 
}

3)网页访问图片:
Nginx反向代理负载均衡配置详解

3.3.4 访问视频

1)在Nginx新建media文件夹,文件夹存放视频文件RB.mp4。
2)修改nginx.conf配置文件

events {
    worker_connections  1024; 
}
http { 
		 upstream backend{
			server 192.168.139.133 weight=2;
			server 192.168.139.134 weight=1;
		 }
    	server { 
            	listen 80; 
            	server_name  localhost; 
				
            	location / { 
					proxy_pass http:// backend;
           		}  
				
				location /images/ { 
					root ./;
           		}
				location ~ \.(mp3|mp4) { 
					root media;
           		}

        } 
}

静态资源都可以使用上面两种方式进行配置,比如css、js、png。

3.3.5 CGI公共网关接口

CGI是一个进程,当一个客户端请求Web服务器的时候,服务器把一些响应的数据转换给CGI,计算出来的结果返回给Web服务器。
Nginx反向代理负载均衡配置详解

问:CGI与后端的Server有什么区别?
CGI是对外提供输入输出流,比如std cout,printf,直接打印到网页上。Server的协议是http协议。

问:CGI到底用在哪里?在哪种场景下必须要用到CGI?
在线编译工具,当你提交代码的时候编译工具可以给你实时输出结果,这是使用CGI实现。

问:CGI与fastcgi的区别?
CGI是一请求一进程方式,fastcgi:启动进程池等待。

问:Nginx如何做CGI?
需要用到fcgi和spawn-fcgi两个工具。其中:
fcgi:CGI的库文件,我们可以通过这里的接口开发CGI。
spawn-fcgi:启动CGI的工具。

CGI编程
1)spawn-fcgi编译:解压后进到文件夹执行./configure,然后执行make,再把src文件里的spawn-fcgi拷贝到Nginx的sbin文件夹。

2)fcgi编译:解压后进到文件夹执行./configure,然后执行make。
这个时候可能会出现以下编译错误提示:
Nginx反向代理负载均衡配置详解
我们可以通过在include/fcgio.h头文件中增加#include <stdio.h>即可解决。
最后执行 sudo make install即可。

3)源码示例

  • 编码
#include <stdio.h>
#include <fcgi_stdio.h>

int main()
{
	while(0 <= FCGI_Accept())
	{
		printf("Content-type:text/html\r\n");
		printf("\r\n");
		printf("<title> Fast CGI Hello!</title>");
		printf("<h1>ZVoice cgi</h1>");
		printf("Thank you cgi\n");
	}
}
  • 编译
    编译CGI程序:gcc –o zvoice_cgi zvoice_cgi.c -lfcgi

  • 运行

./zvoice_cgi

发现程序运行失败,报找不到对应库文件错误:
Nginx反向代理负载均衡配置详解
于是从头开始检查cgi库文件的安装,从./configure到make到sudo make install,都没有问题,但是依旧报错。
这个时候我们思考一下,库文件已经安装但是调用失败,应该是系统没有识别到,这个时候我们设置动态库为系统共享,执行指令:sudo ldconfig,然后再运行程序发现程序运行成功。
Nginx反向代理负载均衡配置详解
ldconfig:动态库管理,让动态库为系统共享,把新安装的so,为系统共享。

  • 启动CGI程序:./spawn-fcgi -a 127.0.0.1 -p 9002 -f /home/ubuntu/nginx/zvoice_cgi

  • 配置Nginx的conf文件

 events {
    worker_connections  1024; 
}
http { 
		 upstream backend{
			server 192.168.139.133 weight=2;
			server 192.168.139.134 weight=1;
		}
    	server { 
            	listen 80; 
            	server_name  localhost; 
				
            	location / { 
					proxy_pass http:// backend;
           		}  
				
				location /images/ { 
					root ./;
           		}
				location ~ \.(mp3|mp4) { 
					root media;
           		}

        	} 
		server{
			listen 9000;
			location ~ \.cgi{
			fastcgi_pass  127.0.0.1:9002; 
			fastcgi_index index.cgi;
		    fastcgi_param SCRIPT_FILENAME cgi$fastcgi_script_name;
			include ../conf/fastcgi_params;
			}
		}
}
  • 重启Nginx

  • 访问网页:http://192.168.139.132:9000/zvoice_cgi.cgi
    Nginx反向代理负载均衡配置详解

本文地址:https://blog.csdn.net/locahuang/article/details/110496484

相关标签: nginx