基于Nginx的负载均衡技术研究与实现

一、下载安装及使用

1、版本

日期

版本

CHANGES

NGINX

NGINX/WINDOWS

2018.6.27

MainLine(开发版)

CHANGES

1.15.0

1.15.0

2018.6.27

Stable(稳定版)

1.14

1.14.0

1.14.0

2018.6.27

Legacy(过期版)

1.12

1.12.2

1.12.2

2、下载安装

下载地址:http://nginx.org/en/download.html

下载并解压即可,windows和linux类似。

3、常用命令

windows中使用cd命令跳转到nginx.exe目录

start nginx

启动nginx

tasklist /fi “imagename eq nginx.exe”

启动后查看进程

nginx -s stop

快速停止

nginx -s quit

完整有序的停止

nginx -s reload

修改配置后重新加载生效

nginx -s reopen

重新打开日志文件

nginx -t -c /path/to/nginx.conf

测试配置文件是否正确

4、已知问题

  • 尽管可以开启多个工作进程运行,但是实际上只有一个在处理请求

  • 一个工作进程可以同时处理最多1024个并发连接

  • 不支持UDP代理方式

注意:在windows中,不要双击nginx.exe来开启,而应该使用命令,否则会导致修改配置后重启、停止、无效,这时需手动在任务管理器中关闭所有nginx进程。

5、未来趋势

  • 作为系统服务运行

  • 使用I/O完成端口作为事件模型

  • 使用单进程多线程的模型

6、中文文档

http://tengine.taobao.org/nginx_docs/cn/docs/

 二、配置

1、配置文件

配置文件:conf/nginx.conf

2、配置项

配置项

说明

user

 

全局生效,启动用户/组

work_processes

1

全局生效,启动的工作进程数量;auto是启动与当前CPU线程相同的进程数

pid

logs/nginx.pid

全局生效,可以是绝对路径

error_log

logs/error.log

错误日志路径

error_log

logs/error.log notice

日志记录级别

error_log

logs/error.log info

 

worker_rlimit_nofile

65535

nginx工作进程最大打开文件数

events{}

 

全局生效,主要影响nginx服务器与用户的网络连接,比如是否允许同时接受多个网络连接,使用哪种事件驱动模型处理请求,每个工作进程可以同时支持的最大连接数,是否开启对多工作进程下的网络连接进行序列化等

event.work_connections

1024

设置nginx可以接受的最大并发,不能大于操作系统能打开的最大的文件句柄数

http{}

 

Nginx服务器配置中的重要部分,缓存、代理和日志格式定义等绝大多数功能和第三方模块都可以在这设置,http块可以包含多个server块,而一个server块中又可以包含多个location块,server块可以配置文件引入、MIME-Type定义、日志自定义、是否启用sendfile、连接超时时间和单个链接的请求上限等。

http.include

mime.types

文件扩展名与文件类型映射表

http.default_type

application/octet-stream

默认文件类型

http.log_format

   

http.access_log

logs/access.log main

 

http.client_header_timeout

4k

用于指定来自客户端请求头的headerbuffer大小,对于大多数请求,1kb的缓冲区大小已经足够,如果自定义了消息头部或有更大的cookie,可以增加缓冲区大小

http.sendfile

on

是否调用sendfile函数(零copy方式)来输出文件,普通应用打开,可以大幅提升nginx的读文件性能,如果服务器是下载的就需要关闭

http.sendtime_out

10s

http核心模块指令,指定了发送给客户端应答后的超时时间,Timeout是指没有进入完整established状态,只完成了两次握手,如果超过这个时间客户端没有任何响应,nginx将关闭与客户端的连接。

http.server.location.sendfile_max_chunk

512k

Nginx工作进程每次调用sendfile()传输的数据最大不能超出这个值,0表示表示无限制。

http.tcp_nopush

on

 

http.keepalive_timeout

65

长连接超时时间,单位是秒

http.gzip

on

打开或关闭gzip功能,on | off

http.gzip_buffers

32 4k

第一个参数是Nginx服务器向服务器申请的缓存空间的个数

第二个参数是每个缓存空间的大小

http.gzip_comp_level

4

压缩级别,1-9

http.gzip_disable

MSIE[1-6]\.

使用正则表达式匹配关闭数据包的压缩

http.gzip_http_version

1.0|1.1

对使用http1.0和1.1的请求进行压缩

http.gzip_min_length

1024

最少压缩的数据包大小

http.gzip_proxied

off | any

在Nginx 服务器作为反向代理的时候有效,用于设置nginx服务器是否对后端返回的结果进行gzip压缩

off为关闭,any为压缩所有后端服务器返回的数据

http.gzip_types

text/plain application/x-javascript text/css  application/xml

设置Nginx服务器可以根据响应页面的类型进行选择性的打开或关闭gzip功能

一般设置

http.gzip_vary

on | off

用于设置是否在使用gzip功能时发送带有"vary:Accept-Encoding"头域的响应头部,该头域的主要功能时要告诉客户端数据已经在服务器进行了压缩,默认设置为off

http.server

 

一个虚拟机主机,可以包含自己的全局块,同时也可以包含多个locating模块。比如本虚拟机监听的端口、本虚拟机的名称和IP配置,多个server 可以使用一个端口,比如都使用8090端口提供web服务

http.server.listen

 

server的全局配置,配置监听的端口

http.server.server_name

localhost

本server的名称,当访问此名称的时候nginx会调用当前serevr内部的配置进程匹配

http.server.charset

   

http.server.access_log

   

http.server.location

 

location其实是server的一个指令,为nginx服务器提供比较多而且灵活的指令,都是在location中提现的,主要是基于nginx接受到的请求字符串,对用户请求的UIL进行匹配,并对特定的指令进行处理,包括地址重定向、数据缓存和应答控制等功能都是在这部分实现,另外很多第三方模块的配置也是在location模块中配置

http.server.location.root

 

相当于默认页面的目录名称,默认是相对路径,可以使用绝对路径配置

http.server.location.index

 

默认页面的名称

http.server.error_page

 

错误页面的文件名称

3、扩展配置

每个配置文件中的指令,均以“;”结尾

  • 绑定Nginx工作进程到不同CPU上

默认Nginx是不进行绑定的,绑定并不能够使当前进程独占一核,但可以保证该进程不会运行在其他核上,因此,绑定使进程减少在CPU间的跳转,减少资源分配与回收,从而有效提升nginx服务器的性能。

#确认CPU的核心数量(linux)

grep precess /proc/cpuinfo | wc -l

#4个线程CPU的配置

worker_processes 4;

worker_cpu_affinity 0001 0010 01001000;

#8个线程CPU的配置

worker_processes 8;

worker_cpu_affinity 0000000100000010 00000100 00001000 00010000 00100000 01000000 10000000;

  • 配置文件的引入

include file;#file是要导入的文件,支持相对路径,一般在html目录里面,可以使用通配符*批量导入

nginx.conf:

include/usr/local/nginx/conf.d/*.conf;

/usr/local/nginx/conf.d/abc.conf:

server {

       listen      8081;

       server_namewww.caini.cn;

       location/ {

       roothtml;

       indexindex1.html  index.htm;

}

error_page 500 502 503 504/50x.html;

location = /50x.html {

       roothtml;

}

}

4、优化配置

  • 网络连接优化

events{

    accept_mutex on;#优化同一时刻只有一个请求而避免多个睡眠进程被唤醒的设置,on为防止被同时唤醒,默认为off,因此nginx刚安装完以后要进行适当的优化。

}

  • 设置是否允许同时接受多个网络连接

events {

accept_mutex on;

multi_accept on;#打开同时接受多个新网络连接请求的功能。

}

  • 隐藏版本号

server_tokensoff;#在http模块中配置,防止被黑客利用攻击

  • 选择事件驱动模型

events {

accept_mutex on;

multi_accept on;

use epoll; #使用epoll事件驱动,因为epoll的性能相比其他事件驱动(select/poll)要好很多

}

三、原理机制

1、Web请求机制

1、多进程方式:服务器没接受到一个客户端请求就有服务器的主进程生成一个子进程响应客户端,直到用户关闭连接,这样的优势是处理速度快,子进程之间相互独立,但是如果访问过大会导致服务器资源耗尽而无法提供请求。

2、多线程方式:与多进程方式类似,但是每收到一个客户端请求会有服务进程派生出一个线程来个客户方进行交互,一个线程的开销远远小于一个进程,因此多线程方式在很大程度减轻了web服务器对系统资源的要求,但是多线程也有自己的缺点,即当多个线程位于同一个进程内工作的时候,可以相互访问同样的内存地址空间,所以他们相互影响,一旦主进程挂掉则所有子线程都不能工作了,IIS服务器使用了多线程的方式,需要间隔一段时间就重启一次才能稳定。

2、同步和异步、阻塞和非阻塞

同步:进程发出数据后,等内核返回响应以后才继续下一个请求,即如果内核一直不返回数据,那么进程就一直等,直到天荒地老,死机error。

异步:进程发出数据后,不等内核返回响应,接着处理下一个请求,Nginx是异步的。

阻塞:IO调用不能立即返回结果,即一个进程发起的IO请求不能得到立即满足时,进程就要一直等到内核响应,内核要把数据从IO设备复制到内核空间,再返回给进程,这是阻塞。

非阻塞:IO调用可以立即返回结果,一个进程发起的IO进程不能立即满足时,不在等待,而是一遍一遍的轮训查看IO是否完成。

同步阻塞:程序进程向内核发送IO请求后一直等待内核响应,如果内核处理请求的IO操作不能立即返回,则进程将一直等待并不再接受新的请求,并由进程轮训查看IO是否完成,完成后进程将IO结果返回给Client,在IO没有返回期间进程不能接受其他客户的请求,而且是有进程自己去查看IO是否完成,这种方式简单,但是比较慢,用的比较少。

同步非阻塞:进程向内核发送请IO求后一直等待内核响应,如果内核处理请求的IO操作不能立即返回IO结果,进程将不再等待,而且继续处理其他请求,但是仍然需要进程隔一段时间就要查看内核IO是否完成。

异步阻塞:event-diver,进程向内核发送IO调用后,不用等待内核响应,可以继续接受其他请求,内核收到进程请求后进行的IO如果不能立即返回,就由内核等待结果,直到IO完成后内核再通知进程,此方式比较占用内核,因此也很少使用。

异步非阻塞:AIO,进程向内核发送IO调用后,不用等待内核响应,可以继续接受其他请求,内核调用的IO如果不能立即返回,内核会继续处理其他事物,直到IO完成后将结果通知给内核,内核在将IO完成的结果返回给进程,期间进程可以接受新的请求,内核也可以处理新的事物,因此相互不影响,可以实现较大的同时并实现较高的IO复用,因此异步非阻塞使用最多的一种通信方式。

2、Nginx的事件驱动模型

select

select库是在linux和windows平台都基本支持的事件驱动模型库,并且在接口的定义也基本相同,只是部分参数的含义略有差异,最大并发限制1024,只最早期的事件驱动模型。

poll

在Linux 的基本驱动模型,windows不支持此驱动模型,是select的升级版,取消了最大的并发限制,在编译nginx的时候可以使用--with-poll_module和--without-poll_module这两个指定是否编译select库。

epoll

epoll是库是Nginx服务器支持的最高性能的事件驱动库之一,是公认的非常优秀的事件驱动模型,它和select和poll有很大的区别,epoll是poll的升级版,但是与poll的效率有很大的区别.

epoll的处理方式是创建一个待处理的事件列表,然后把这个列表发给内核,返回的时候在去轮训检查这个表,以判断事件是否发生,epoll支持一个进程打开的最大事件描述符的上限是系统可以打开的文件的最大数,同时epoll库的IO效率不随描述符数目增加而线性下降,因为它只会对内核上报的“活跃”的描述符进行操作。

rtsig

不是一个常用事件驱动,最大队列1024,不是很常用

kqueue

用于支持BSD系列平台的高效事件驱动模型,主要用在FreeBSD 4.1及以上版本、OpenBSD 2.0级以上版本,NetBSD级以上版本及Mac OS X 平台上,该模型也是poll库的变种,因此和epoll没有本质上的区别,都是通过避免轮训操作提供效率。

/dev/poll

用于支持unix衍生平台的高效事件驱动模型,主要在Solaris 平台、HP/UX,该模型是sun公司在开发Solaris系列平台的时候提出的用于完成事件驱动机制的方案,它使用了虚拟的/dev/poll设备,开发人员将要见识的文件描述符加入这个设备,然后通过ioctl()调用来获取事件通知,因此运行在以上系列平台的时候请使用/dev/poll事件驱动机制。

eventpoll

该方案也是sun公司在开发Solaris的时候提出的事件驱动库,只是Solaris 10以上的版本,该驱动库看防止内核崩溃等情况的发生。

3、Nginx进程的功能和进程间通信

  • 主进程的功能

  • 读取Nginx 配置文件并验证其有效性和正确性

  • 建立、绑定和关闭socket连接

  • 按照配置生成、管理和结束工作进程

  • 接受外界指令,比如重启、升级及退出服务器等指令

  • 不中断服务,实现平滑升级,重启服务并应用新的配置

  • 开启日志文件,获取文件描述符

  • 不中断服务,实现平滑升级,升级失败进行回滚处理

  • 编译和处理perl脚本

  • 工作进程的功能

  • 接受处理客户的请求

  • 将请求以此送入各个功能模块进行处理

  • IO调用,获取响应数据

  • 与后端服务器通信,接收后端服务器的处理结果

  • 缓存数据,访问缓存索引,查询和调用缓存数据

  • 发送请求结果,响应客户的请求

  • 接收主程序指令,比如重启、升级和退出等

  • 主进程和工作进程之间的通信

  • 工作进程是有主进程生成的,主进程使用fork()函数,在Nginx服务器启动过程中主进程根据配置文件决定启动工作进程的数量,然后建立一张全局的工作表用于存放当前未退出的所有的工作进程,主进程生成工作进程后会将新生成的工作进程加入到工作进程表中,并建立一个单向的管道并将其传递给工作进程,该管道与普通的管道不同,它是由主进程指向工作进程的单项通道,包含了主进程向工作进程发出的指令、工作进程ID、工作进程在工作进程表中的索引和必要的文件描述符等信息。

  • 主进程与外界通过信号机制进行通信,当接收到需要处理的信号时,它通过管道向相关的工作进程发送正确的指令,每个工作进程都有能力捕获管道中的可读事件,当管道中有可读事件的时候,工作进程就会从管道中读取并解析指令,然后采取相应的执行动作,这样就完成了主进程与工作进程的交互。

  • 工作进程和工作进程之间的通信

  • 工作进程之间的通信原理基本上和主进程与工作进程之间的通信是一样的,只要工作进程之间能够取得彼此的信息,建立管道即可通信,但是由于工作进程之间是完全隔离的,因此一个进程想要直到另外一个进程的状态信息就只能通过主进程来设置了。

  • 为了实现工作进程之间的交互,主进程在生成工作进程只之后,在工作进程表中进行遍历,将该新进程的ID以及针对该进程建立的管道句柄传递给工作进程中的其他进程,为工作进程之间的通信做准备,当工作进程1向工作进程2发送指令的时候,首先在主进程给它的其他工作进程工作信息中找到2的进程ID,然后将正确的指令写入指向进程2的管道,工作进程2捕获到管道中的事件后,解析指令并进行相关操作,这样就完成了工作进程之间的通信。

4、缓存和代理

  • 缓存

  • memcached缓存数据库常用数据

  • xcache缓存php编译的结果,可以在多个进程间共享xcode结果

  • nginx的缓存是缓存opcode处理后的结果,避免客户端请求同一个页面而导致程序每次都处理一下,即再访问同一个页面,直接使用处理后的缓存即可直接返回

  • 代理

  • 正向代理:工作在用户前端,用户请求的所有内容都经过代理服务器。

  • 反向代理:工作在服务器前端,只代理请求服务器的客户端请求,被期代理的服务器叫做“代理服务器”或者“上游服务器”。

5、负载均衡

5.1负载均衡的概念及原理

通过反向代理客户端的请求到一个服务器群组,通过某种算法,将客户端的请求按照自定义的有规律的一种调度调度给后端服务器。

Nginx的负载均衡使用upstream定义服务器组,后面跟着组名,组名后面是大括号包起来的是服务器列表,每个服务器使用server开头,后面跟定义的服务器名字,服务器IP:PORT、参数

5.2负载均衡的作用

转发功能:按照一定的算法【权重、轮询】,将客户端请求转发到不同应用服务器上,减轻单个服务器压力,提高系统并发量。

故障转移:通过心跳检测的方式,判断应用服务器当前是否可以正常工作,如果服务器宕掉,自动将请求发送到其他应用服务器。

恢复添加:如果检测到发生故障的应用服务器恢复工作,自动将其添加到处理用户请求队伍中。 

5.3Nginx的upstream支持的调度算法

  • 轮询(默认)

每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动删除。

  • 权重(weight)

指定轮询几率,weight和访问比率成正比,用于后端服务器性能不均的情况。

  • 哈希(ip_hash)

每个请求按ip的hash结果分配,这样每个访客固定访问一个后端服务器,可以解决session保持问题。

  • fair(第三方)

可以依据页面大小和加载时间长短智能地进行负载均衡,也就是根据后端服务器的响应时间来分配请求,响应时间短的优先分配,Nginx本身是不支持fair的,如果需要使用这种算法,必须下载Nginx的upstream_fair模块。

  • url_hash(第三方)

按照url的hash结果来分配请求,使每个url定向到同一个后端服务器,可以进一步提高后端缓存服务器的效率,Nginx本身不支持url_hash,如果需要使用这种算法,必须下载Nginx的hash软件包。

  • least_conn

根据后端服务器的连接状况进行分配客户请求,连接最少的服务器将被有限分配客户端请求。

5.4注意事项

应用系统的高可用性保证,除了提供多台服务器来发布相同的服务,添加负载均衡服务器分发请求来保证各台服务器相对饱和的处理请求之外,负载均衡服务器的高可用性同样重要。 

 四、详细设计与实现

1、配置Nginx的负载均衡与分发策略 

具体配置说明

listen 80

监听80端口

server_name localhost

用户访问的网址为localhost

location /jeesitepro

配置需要负载均衡的网站,通过正则表达式匹配

当前和项目的server.xml文件中Context的path属性一致即可

 

 

proxy_pass http://tomcatserver1

所有请求通过反向代理服务器,在服务器将请求转发给目的主机时,读取upstream为tomcatserver1的地址中的分发策略,以此分发请求

upstream tomcatserver1

后端服务器组,名称为tomcatserver1

默认以轮询调度算法调用组内后端服务器

ip_hash

采用ip_hash调度算法

server localhost:8081

一台后端服务器

server localhost:8082

一台后端服务器

通过上述配置,如果2个分发服务器性能相同,那么将通过客户端IP地址的hash值来分配后端服务器,实现有条件的负载均衡。

2、其他配置

server 192.168.72.49:8082 down

表示该server暂时不参与负载

server 192.168.72.49:8083 weight=2

默认weight为1,值越大,权重越大

server 192.168.72.49:8084 max_fails=2

默认允许请求失败的次数为1,超过最大次数时,返回proxy_next_upstream模块定义的错误

server 192.168.72.49:8085 backup

所有非backup服务器down或忙时,请求backup

server 192.168.72.49:8086 fail_timeout=1s

max_fails次失败后,暂停的时间

ip_hash

实现会话保持功能,即将某个客户端的请求定向到组内的同一台服务器,保证客户端和服务器之间建立稳定的会话,只有服务器处于无效状态时,会话才会被转发给组内其他的服务器

3、实现效果

你可能感兴趣的:(负载均衡,架构)