基本概念

1. 简介

高性能的 HTTP 和反向代理 Web 服务器,同时提供了 IMAP/POP3/SMTP服务,服务稳定,功能集丰富,占用内存少,并发能力强;最高 5w 并发连接。

2. 作为 HTTP 服务器,基本特性

  1. 处理静态文件,索引文件及自动索引,打开文件描述符缓冲。
  2. 无缓存的反向代理加速,简单的负载均衡和容错。
  3. FastCGI,简单地负载均衡和容错。
  4. 模块化的结构,包括 gzipping,byte ranges, chunked responses, 以及 SSI-filter 等 filter。如果由 FastCGI 或其他代理服务器处理单页中存在的多个 SSI,则这项处理可以并行运行,而不需要相互等待。
  5. 支持 SSL 和 TLSSNI 。
  • Nginx具有很高的稳定性
    • 其它HTTP服务器,当遇到访问的峰值,或者有人恶意发起慢速连接时,也很可能会导致服务器物理内存耗尽频繁交换,失去响应,只能重启服务器。例如当前apache一旦上到200个以上进程,web响应速度就明显非常缓慢了。而Nginx采取了分阶段资源分配技术,使得它的CPU与内存占用率非常低。nginx官方表示保持10,000个没有活动的连接,它只占2.5M内存,所以类似DOS这样的攻击对nginx来说基本上是毫无用处的。就稳定性而言,nginx比lighthttpd更胜一筹。
  • Nginx支持热部署。
    • 它的启动特别容易, 并且几乎可以做到7*24不间断运行,即使运行数个月也不需要重新启动。你还能够在不间断服务的情况下,对软件版本进行进行升级。
  • Nginx采用master-slave模型
    • 充分利用SMP的优势,且能够减少工作进程在磁盘I/O的阻塞延迟。当采用select()/poll()调用时,还可以限制每个进程的连接数。
  • Nginx代码质量非常高,代码很规范,手法成熟, 模块扩展也很容易
    • 特别值得一提的是强大的Upstream与Filter链。Upstream为诸如reverse proxy,与其他服务器通信模块的编写奠定了很好的基础。而Filter链最酷的部分就是各个filter不必等待前一个filter执行完毕。它可以把前一个filter的输出做为当前filter的输入,这有点像Unix的管线。这意味着,一个模块可以开始压缩从后端服务器发送过来的请求,且可以在模块接收完后端服务器的整个请求之前把压缩流转向客户端。
  • Nginx采用了一些os提供的最新特性
    • 对sendfile (Linux2.2+),accept-filter (FreeBSD4.1+),TCP_DEFER_ACCEPT (Linux 2.4+)的支持,从而大大提高了性能。

3. 反向代理

这是 Nginx 服务器作为 WEB 服务器的主要功能之一,客户端向服务器发送请求时,会首先经过 Nginx 服务器,由服务器将请求分发到相应的 WEB 服务器。正向代理是代理客户端,而反向代理则是代理服务器,Nginx 在提供反向代理服务方面,通过使用正则表达式进行相关配置,采取不同的转发策略,配置相当灵活,而且在配置后端转发请求时,完全不用关心网络环境如何,可以指定任意的IP地址和端口号,或其他类型的连接、请求等。

4. 负载均衡

这也是 Nginx 最常用的功能之一,负载均衡,一方面是将单一的重负载分担到多个网络节点上做并行处理,每个节点处理结束后将结果汇总返回给用户,这样可以大幅度提高网络系统的处理能力;另一方面将大量的前端并发请求或数据流量分担到多个后端网络节点分别处理,这样可以有效减少前端用户等待相应的时间。而 Nginx 负载均衡都是属于后一方面,主要是对大量前端访问或流量进行分流,已保证前端用户访问效率,并可以减少后端服务器处理压力。

5. Web 缓存

在很多优秀的网站中,Nginx 可以作为前置缓存服务器,它被用于缓存前端请求,从而提高 Web服务器的性能。Nginx 会对用户已经访问过的内容在服务器本地建立副本,这样在一段时间内再次访问该数据,就不需要通过 Nginx 服务器向后端发出请求。减轻网络拥堵,减小数据传输延时,提高用户访问速度。

6. 动态分离

(后期补上 暂不更新)

安装,配置与基本使用

1. 安装

关于 Nginx 的安装,分为在 Windows 平台和 Linux 平台安装,Windows 版本的 Nginx 服务器在效率上要比 Linux 版本的 Nginx 服务器差一些,而且实际使用的一般都是 Linux 平台的 Nginx 服务器。
Nginx下载地址

  1. Mainline version 开发版本
  2. Stable version 稳定版本
  3. Legacy version 旧版本
    开发版本主要用于 Nginx 软件项目的研发,稳定版本说明可以作为 Web 服务器投入商业应用。

Windows 版本安装

  1. 解压安装包
  2. 目录
    A. conf: 存放 Nginx 的主要配置文件,很多功能实现都是通过配置该目录下的 nginx.conf 文件
    B. docs: 存放 Nginx 服务器的主要文档资料,包括 Nginx 服务器的 LICENSE、OpenSSL 的 LICENSE 、PCRE 的 LICENSE 以及 zlib 的 LICENSE ,还包括本版本的 Nginx服务器升级的版本变更说明,以及 README 文档。
    C. html: 存放了两个后缀名为 .html 的静态网页文件,这两个文件与 Nginx 服务器的运行相关。
    D. logs: 存放 Nginx 服务器运行的日志文件。
    E. nginx.exe: 启动 Nginx 服务器的exe文件,如果 conf 目录下的 nginx.conf 文件配置正确的话,通过该文件即可启动 Nginx 服务器。
  3. 启动
    A. 双击,出现一闪而过的画面
    B. 浏览器中输入 localhost 或者 localhost:80 (出现 Welcome to nginx! 则启动成功)
    C. 显示的页面是上面解压目录中 html 目录下的 index.html 文件。
  4. 关闭
    A. ctrl + alt + del 打开任务管理器结束 nginx 进程
    B. nginx.exe所在目录下 cmd> nginx.exe -s stop

Linux(Centos)

  1. 选择 Centos 操作系统版本
  2. 安装 nginx 环境 + 依赖
  1. yum install gcc-c++
  2. yum install -y pcre pcre-devel
  3. yum install -y zlib zlib-devel
  4. yum install -y openssl openssl-devel
  • gcc
    • 因为安装nginx需要先将官网下载的源码进行编译,编译依赖gcc环境,如果没有gcc环境的话,需要安装gcc。
  • pcre
    • prce(Perl Compatible Regular Expressions)是一个Perl库,包括 perl 兼容的正则表达式库。nginx的http模块使用pcre来解析正则表达式,所以需要在linux上安装pcre库。
  • zlib
    • zlib库提供了很多种压缩和解压缩的方式,nginx使用zlib对http包的内容进行gzip,所以需要在linux上安装zlib库。
  • openssl
    • OpenSSL 是一个强大的安全套接字层密码库,囊括主要的密码算法、常用的密钥和证书封装管理功能及SSL协议,并提供丰富的应用程序供测试或其它目的使用。nginx不仅支持http协议,还支持https(即在ssl协议上传输http),所以需要在linux安装openssl库。
  1. 将下载好的 xxx.tar.gz文件解压
  1. tar -zxvf nginx-xxx.tar.gz
  1. 进入文件所在目录,进行编译安装

指定 /usr/local/nginx 为nginx 服务安装的目录。

  1. ./configure --prefix=/usr/local/nginx
  2. make
  3. make install
  1. 启动 nginx
  • 进入nginx 目录
  • 显示文件目录
  • 进入 sbin 目录并启动 nginx
  1. cd /usr/local/nginx
  2. ls -la
  3. cd sbin
  4. ./nginx
  • 查看 Nginx 服务是否启动
  1. ps -ef | grep nginx
  • 查看 Nginx 是否正常运行,浏览器输入 Linux 系统的 IP地址
  1. 关闭 Nginx
    A. 快速停止
  • 此方式相当于先查出nginx进程id再使用kill命令强制杀掉进程
  • kill -9 [pid]
  1. cd /usr/local/nginx/sbin
  2. ./nginx -s stop

B. 平缓停止

  • 此方式是指允许 nginx 服务将当前正在处理的网络请求处理完成,但不在接收新的请求,之后关闭连接,停止工作。
  1. cd /usr/local/nginx/sbin
  2. ./nginx -s quit
  1. 重启 Nginx
    A. 先停止再启动
  1. ./nginx -s quit
  2. ./nginx

B. 重新加载配置文件

  • 通常我们使用nginx修改最多的便是其配置文件 nginx.conf。修改之后想要让配置文件生效而不用重启 nginx,便可以使用此命令。
  1. ./nginx -s reload
  1. 检测配置文件语法是否正确
    A. 指定需要检查的配置文件
  1. nginx -t -c /usr/local/nginx/conf/nginx.conf

B. 默认检测nginx.conf 配置文件

  1. nginx -t
  1. 配置环境命令(任意位置即可启动 nginx)
  • Linux 没有消息就好消息,不提示任何信息说明启动成功。

2. 常用命令

3. nginx.conf 配置文件

  • 开头的表示注释内容,去掉所有以 # 开头的段落,精简之后的内容如下
  1. worker_processes 1;
  2. events {
  3. worker_connections 1024;
  4. }
  5. http {
  6. include mime.types;
  7. default_type application/octet-stream;
  8. sendfile on;
  9. keepalive_timeout 65;
  10. server {
  11. listen 80;
  12. server_name localhost;
  13. location / {
  14. root html;
  15. index index.html index.htm;
  16. }
  17. error_page 500 502 503 504 /50x.html;
  18. location = /50x.html {
  19. root html;
  20. }
  21. }
  22. }

nginx.conf 的主体结构

  1. worker_processes 1;
  2. events{…}
  3. http{…}

全局块

从配置文件开始到 events 块之间的内容,主要会设置一些影响nginx 服务器整体运行的配置指令,主要包括配置运行 Nginx 服务器的用户(组)、允许生成的 worker process 数,进程 PID 存放路径、日志存放路径和类型以及配置文件的引入等。

  1. worker_processes 1;
  • 这是 Nginx 服务器并发处理服务的关键配置,worker_processes 值越大,可以支持的并发处理量也越多,但是会受到硬件、软件等设备的制约

events 块

  1. events {
  2. worker_connections 1024;
  3. }
  • events 块涉及的指令主要影响 Nginx 服务器与用户的网络连接,常用的设置包括是否开启对多 work process 下的网络连接进行序列化,是否允许同时接收多个网络连接,选取哪种事件驱动模型来处理连接请求,每个 word process 可以同时支持的最大连接数等。
  • 上述例子就表示每个 work process 支持的最大连接数为 1024.
  • 这部分的配置对 Nginx 的性能影响较大,在实际中应该灵活配置。

http 块

  1. http {
  2. include mime.types;
  3. default_type application/octet-stream;
  4. sendfile on;
  5. keepalive_timeout 65;
  6. server {
  7. listen 80;
  8. server_name localhost;
  9. location / {
  10. root html;
  11. index index.html index.htm;
  12. }
  13. error_page 500 502 503 504 /50x.html;
  14. location = /50x.html {
  15. root html;
  16. }
  17. }
  • 这算是 Nginx 服务器配置中最频繁的部分,代理、缓存和日志定义等绝大多数功能和第三方模块的配置都在这里。
  • 需要注意的是:http 块也可以包括 http全局块、server 块。
  1. http 全局块
    • http全局块配置的指令包括文件引入、MIME-TYPE 定义、日志自定义、连接超时时间、单链接请求数上限等。
  2. server 块
    • 这块和虚拟主机有密切关系,虚拟主机从用户角度看,和一台独立的硬件主机是完全一样的,该技术的产生是为了节省互联网服务器硬件成本。后面会详细介绍虚拟主机的概念。
    • 每个 http 块可以包括多个 server 块,而每个 server 块就相当于一个虚拟主机。
    • 而每个 server 块也分为全局 server 块,以及可以同时包含多个 locaton 块。

A. 全局 server 块
- 最常见的配置是本虚拟机主机的监听配置和本虚拟主机的名称或IP配置。
B. location 块
- 一个 server 块可以配置多个 location 块。
- 这块的主要作用是基于 Nginx 服务器接收到的请求字符串(例如 server_name/uri-string),对虚拟主机名称(也可以是IP别名)之外的字符串(例如 前面的 /uri-string)进行匹配,对特定的请求进行处理。地址定向、数据缓存和应答控制等功能,还有许多第三方模块的配置也在这里进行。

反向代理

Nginx 服务器的反向代理服务是其最常用的重要功能,由反向代理服务也可以衍生出很多与此相关的 Nginx 服务器重要功能。

1. 代理

在Java设计模式中,代理模式是这样定义的:给某个对象提供一个代理对象,并由代理对象控制原对象的引用。 可能大家不太明白这句话,在举一个现实生活中的例子:比如我们要买一间二手房,虽然我们可以自己去找房源,但是这太花费时间精力了,而且房屋质量检测以及房屋过户等一系列手续也都得我们去办,再说现在这个社会,等我们找到房源,说不定房子都已经涨价了,那么怎么办呢?最简单快捷的方法就是找二手房中介公司(为什么?别人那里房源多啊),于是我们就委托中介公司来给我找合适的房子,以及后续的质量检测过户等操作,我们只需要选好自己想要的房子,然后交钱就行了。 代理简单来说,就是如果我们想做什么,但又不想直接去做,那么这时候就找另外一个人帮我们去做。那么这个例子里面的中介公司就是给我们做代理服务的,我们委托中介公司帮我们找房子。 Nginx 主要能够代理如下几种协议,其中用到的最多的就是做Http代理服务器。

Nginx - 图1

2. 正向代理

弄清楚什么是代理了,那么什么又是正向代理呢? 这里我再举一个例子:大家都知道,现在国内是访问不了 Google的,那么怎么才能访问 Google呢?我们又想,美国人不是能访问 Google吗(这不废话,Google就是美国的),如果我们电脑的对外公网 IP 地址能变成美国的 IP 地址,那不就可以访问 Google了。你很聪明,VPN 就是这样产生的。我们在访问 Google 时,先连上 VPN 服务器将我们的 IP 地址变成美国的 IP 地址,然后就可以顺利的访问了。 这里的 VPN 就是做正向代理的。正向代理服务器位于客户端和服务器之间,为了向服务器获取数据,客户端要向代理服务器发送一个请求,并指定目标服务器,代理服务器将目标服务器返回的数据转交给客户端。这里客户端是要进行一些正向代理的设置的。 PS:这里介绍一下什么是 VPN,VPN 通俗的讲就是一种中转服务,当我们电脑接入 VPN 后,我们对外 IP 地址就会变成 VPN 服务器的 公网 IP,我们请求或接受任何数据都会通过这个VPN 服务器然后传入到我们本机。这样做有什么好处呢?比如 VPN 游戏加速方面的原理,我们要玩网通区的 LOL,但是本机接入的是电信的宽带,玩网通区的会比较卡,这时候就利用 VPN 将电信网络变为网通网络,然后在玩网通区的LOL就不会卡了(注意:VPN 是不能增加带宽的,不要以为不卡了是因为网速提升了)。 可能听到这里大家还是很抽象,没关系,和下面的反向代理对比理解就简单了。

3. 反向代理

反向代理和正向代理的区别就是:正向代理代理客户端,反向代理代理服务器。 反向代理,其实客户端对代理是无感知的,因为客户端不需要任何配置就可以访问,我们只需要将请求发送到反向代理服务器,由反向代理服务器去选择目标服务器获取数据后,在返回给客户端,此时反向代理服务器和目标服务器对外就是一个服务器,暴露的是代理服务器地址,隐藏了真实服务器IP地址。 下面我们通过两张图来对比正向代理和方向代理:

Nginx - 图2

Nginx - 图3

理解这两种代理的关键在于代理服务器所代理的对象是什么,正向代理代理的是客户端,我们需要在客户端进行一些代理的设置。而反向代理代理的是服务器,作为客户端的我们是无法感知到服务器的真实存在的。 总结起来还是一句话:正向代理代理客户端,反向代理代理服务器。

4. Nginx 反向代理

使用 nginx 反向代理 www.123.com 直接跳转到127.0.0.1:8080

4.1 Tomcat

  1. 启动一个 tomcat,浏览器地址栏输入 127.0.0.1:8080
  2. 通过修改本地 host 文件,将 www.123.com 映射到 127.0.0.1
  1. 127.0.0.1 www.123.com
  1. vim /etc/hosts
  2. cd C/Windows/System32/drivers/etc
  • 配置完成之后,我们便可以通过 www.123.com:8080 访问到第一步出现的 Tomcat初始界面。
  • 那么如何只需要输入 www.123.com 便可以跳转到 Tomcat初始界面呢?便用到 nginx的反向代理。
  1. 在 nginx.conf 配置文件中增加如下配置
  1. server {
  2. listen 80;
  3. server_name www.123.com;
  4. location / {
  5. proxy_pass http://127.0.0.1:8080;
  6. index index.html index.htm index.jsp;
  7. }
  8. }
  • 如上配置,我们监听80端口,访问域名为www.123.com
  • 不加端口号时默认为80端口,故访问该域名时会跳转到127.0.0.1:8080路径上。
  1. 总结:其实这里更贴切的说是通过nginx代理端口,原先访问的是8080端口,通过nginx代理之后,通过80端口就可以访问了。

5. 相关指令介绍

5.1 listen

该指令用于配置网络监听。

  1. 配置监听的IP地址
  1. listen address[:port] [default_server] [setfib=number] [backlog=number] [rcvbuf=size] [sndbuf=size] [deferred]
  2. [accept_filter=filter] [bind] [ssl];
  1. 配置监听端口
  1. listen port[default_server] [setfib=number] [backlog=number] [rcvbuf=size] [sndbuf=size] [accept_filter=filter]
  2. [deferred] [bind] [ipv6only=on|off] [ssl];
  1. 配置 UNIX Domain Socket
  1. listen unix:path [default_server] [backlog=number] [rcvbuf=size] [sndbuf=size] [accept_filter=filter]
  2. [deferred] [bind] [ssl];
  1. 使用简介
  1. listen *:80 | *:8080 #监听所有80端口和8080端口
  2. listen IP_address:port #监听指定的地址和端口号
  3. listen IP_address #监听指定ip地址所有端口
  4. listen port #监听该端口的所有IP连接
  1. 具体含义
  • address
    • IP地址,如果是 IPV6地址,需要使用中括号[] 括起来,比如[fe80::1]等。
    • 链接
  • port
    • 端口号,如果只定义了IP地址,没有定义端口号,那么就使用80端口。
  • path
    • socket文件路径,如 var/run/nginx.sock等。
  • default_server
    • 标识符,将此虚拟主机设置为 address:port 的默认主机。(在 nginx-0.8.21 之前使用的是 default 指令)
  • setfib=number
    • Nginx-0.8.44 中使用这个变量监听 socket 关联路由表,目前只对 FreeBSD 起作用,不常用。
  • backlog=number
    • 设置监听函数listen()最多允许多少网络连接同时处于挂起状态,在 FreeBSD 中默认为 -1,其他平台默认为511.
  • rcvbuf=size
    • 设置监听socket接收缓存区大小。
  • sndbuf=size
    • 设置监听socket发送缓存区大小。
  • deferred
    • 标识符,将accept()设置为Deferred模式。
  • accept_filter=filter
    • 设置监听端口对所有请求进行过滤,被过滤的内容不能被接收和处理,本指令只在 FreeBSD 和 NetBSD 5.0+ 平台下有效。filter 可以设置为 dataready 或 httpready 。
  • bind
    • 标识符,使用独立的bind() 处理此address:port,一般情况下,对于端口相同而IP地址不同的多个连接,Nginx 服务器将只使用一个监听指令,并使用 bind() 处理端口相同的所有连接。
  • ssl
    • 标识符,设置会话连接使用 SSL模式进行,此标识符和Nginx服务器提供的 HTTPS 服务有关。

5.2 server_name

该指令用于虚拟主机的配置。

1. 基于名称的虚拟主机配置: server_name name …;
  • 对于name 来说,可以只有一个名称,也可以有多个名称,中间用空格隔开。而每个名字由两段或者三段组成,每段之间用“.”隔开。
  1. server_name 123.com www.123.com
  • 可以使用通配符”*”,但通配符只能用在由三段字符组成的首段或者尾端,或者由两端字符组成的尾端。
  1. server_name *.123.com www.123.*
  • 还可以使用正则表达式,用“~”作为正则表达式字符串的开始标记。
  1. server_name ~^www\d+\.123\.com$;
  1. - 该表达式“~”表示匹配正则表达式,以www开头(“^”表示开头),紧跟着一个0~9之间的数字,在紧跟“.123.co”,最后跟着“m”($表示结尾)
  • 以上匹配的顺序优先级
  1. 准确匹配 server_name
  2. 通配符在开始时匹配 server_name 成功
  3. 通配符在结尾时匹配 server_name 成功
  4. 正则表达式匹配 server_name 成功

2. 基于 IP 地址的虚拟主机配置

语法结构和基于域名匹配一样,而且不需要考虑通配符和正则表达式的问题。

  1. server_name 192.168.1.1

5.3 location

该指令用于匹配 URL。

  1. location [ = | ~ | ~* | ^~] uri {
  2. }
  1. = :用于不含正则表达式的 uri 前,要求请求字符串与 uri 严格匹配,如果匹配成功,就停止继续向下搜索并立即处理该请求。
  2. ~:用于表示 uri 包含正则表达式,并且区分大小写。
  3. ~*:用于表示 uri 包含正则表达式,并且不区分大小写。
  4. ^~:用于不含正则表达式的 uri 前,要求 Nginx 服务器找到标识 uri 和请求字符串匹配度最高的 location 后,立即使用此 location 处理请求,而不再使用 location 块中的正则 uri 和请求字符串做匹配。
  5. 注意:如果 uri 包含正则表达式,则必须要有 ~ 或者 ~* 标识。

5.4 proxy_pass

该指令用于设置被代理服务器的地址。可以是主机名称、IP地址加端口号的形式。

  1. proxy_pass URL;
  • URL 为被代理服务器的地址,可以包含传输协议、主机名称或IP地址加端口号,URI等。
  1. proxy_pass http://www.123.com/uri;

5.5 index

该指令用于设置网站的默认首页。

  1. index filename ...;
  • 后面的文件名称可以有多个,中间用空格隔开。
  1. index index.html index.jsp;
  • 通常该指令有两个作用:第一个是用户在请求访问网站时,请求地址可以不写首页名称;第二个是可以对一个请求,根据请求内容而设置不同的首页。

负载均衡

之前介绍了 Nginx 一个很重要的功能——代理,包括正向代理和反向代理。这两个代理的核心区别是:正向代理代理的是客户端,而反向代理代理的是服务器。其中又重点介绍了反向代理,以及如何通过 Nginx 来实现反向代理。那么了解了Nginx的反向代理之后,可以通过Nginx的反向代理实现另一个重要功能——负载均衡。

1. 负载均衡的由来

早期的系统架构,基本上都是如下形式
Nginx - 图4

客户端发送多个请求到服务器,服务器处理请求,有一些可能要与数据库进行交互,服务器处理完毕后,再将结果返回给客户端。

这种架构模式对于早期的系统相对单一,并发请求相对较少的情况下是比较适合的,成本也低。但是随着信息数量的不断增长,访问量和数据量的飞速增长,以及系统业务的复杂度增加,这种架构会造成服务器相应客户端的请求日益缓慢,并发量特别大的时候,还容易造成服务器直接崩溃。很明显这是由于服务器性能的瓶颈造成的问题,那么如何解决这种情况呢?

我们首先想到的可能是升级服务器的配置,比如提高CPU执行频率,加大内存等提高机器的物理性能来解决此问题,但是我们知道摩尔定律的日益失效,硬件的性能提升已经不能满足日益提升的需求了。最明显的一个例子,天猫双十一当天,某个热销商品的瞬时访问量是极其庞大的,那么类似上面的系统架构,将机器都增加到现有的顶级物理配置,都是不能够满足需求的。那么怎么办呢?

上面的分析我们去掉了增加服务器物理配置来解决问题的办法,也就是说纵向解决问题的办法行不通了,那么横向增加服务器的数量呢?这时候集群的概念产生了,单个服务器解决不了,我们增加服务器的数量,然后将请求分发到各个服务器上,将原先请求集中到单个服务器上的情况改为将请求分发到多个服务器上,将负载分发到不同的服务器,也就是我们所说的负载均衡
Nginx - 图5
负载均衡完美的解决了单个服务器硬件性能瓶颈的问题,但是随着而来的如何实现负载均衡呢?客户端怎么知道要将请求发送到那个服务器去处理呢?

2. Nginx 实现负载均衡

Nginx 服务器是介于客户端和服务器之间的中介,通过上一篇博客讲解的反向代理的功能,客户端发送的请求先经过 Nginx ,然后通过 Nginx 将请求根据相应的规则分发到相应的服务器。

Nginx - 图6

  • 静态负载均衡算法
    • 主要包括轮询算法、基于比率的加权轮询算法或者基于优先级的加权轮询算法。
  • 动态负载均衡算法
    • 主要包括基于任务量的最少连接优化算法、基于性能的最快响应优先算法、预测算法及动态性能分配算法等。
  • 静态负载均衡算法在一般网络环境下也能表现的比较好,动态负载均衡算法更加适用于复杂的网络环境。

2.1 普通轮询算法

  • Nginx 默认的轮询算法。
    • 两台相同的Tomcat服务器,通过 localhost:8080 访问Tomcat1,通过 localhost:8081访问Tomcat2,现在我们要输入 localhost 这个地址,可以在这两个Tomcat服务器之间进行交替访问。
  1. 分别修改两个Tomcat服务器的端口为8080和8081。然后再修改Tomcat的首页,使得访问这两个页面时能够区分。
  • 修改端口号文件为 server.xml

Nginx - 图7

  • 修改首页的路径为:webapps/ROOT/index.jsp

Nginx - 图8

  • 修改完成之后,分别启动这两个Tomcat服务器,然后分别输入相应的地址端口号:
  • 输入地址:localhost:8081Nginx - 图9

  • 输入地址:localhost:8080

Nginx - 图10

  1. 修改 nginx 的配置文件 nginx.conf
  1. upstream OrdinaryPolling {
  2. server 127.0.0.1:8080;
  3. server 127.0.0.1:8081;
  4. }
  5. server {
  6. listen 80;
  7. server_name localhost;
  8. location / {
  9. proxy_pass http://OrdinaryPolling;
  10. index index.html index.htm index.jsp;
  11. }
  12. }
  1. 启动 nginx。然后在浏览器输入localhost 地址,观看页面变化

Nginx - 图11

2. 基于比例加权轮询

上述两台Tomcat服务器基本上是交替进行访问的。但是这里我们有个需求: 由于Tomcat1服务器的配置更高点,我们希望该服务器接受更多的请求,而 Tomcat2 服务器配置低,希望其处理相对较少的请求。 那么这时候就用到了加权轮询机制了。

  • nginx.conf 配置文件
  1. upstream OrdinaryPolling {
  2. server 127.0.0.1:8080 weight=5;
  3. server 127.0.0.1:8081 weight=2;
  4. }
  5. server {
  6. listen 80;
  7. server_name localhost;
  8. location / {
  9. proxy_pass http://OrdinaryPolling;
  10. index index.html index.htm index.jsp;
  11. }
  12. }
  • 其实对比上面不加权的轮询方式,这里在 upstream 指令中多了一个 weight 指令。该指令用于配置前面请求处理的权重,默认值为 1。
  • 也就是说:第一种不加权的普通轮询,其实其加权值 weight 都为 1。
  • 页面相应结果

Nginx - 图12

  • 明显 8080 端口号出现的次数更多,试验的次数越多越接近我们配置的比例。

2.3 基于IP路由负载

我们知道一个请求在经过一个服务器处理时,服务器会保存相关的会话信息,比如session,但是该请求如果第一个服务器没处理完,通过nginx轮询到第二个服务器上,那么这个服务器是没有会话信息的。

  • 最典型的一个例子
    • 用户第一次进入一个系统是需要进行登录身份验证的,首先将请求跳转到Tomcat1服务器进行处理,登录信息是保存在Tomcat1 上的,这时候需要进行别的操作,那么可能会将请求轮询到第二个Tomcat2上,那么由于Tomcat2 没有保存会话信息,会以为该用户没有登录,然后继续登录一次,如果有多个服务器,每次第一次访问都要进行登录,这显然是很影响用户体验的。

这里产生的一个问题也就是集群环境下的 session 共享,如何解决这个问题?

通常由两种方法

  1. 第一种方法是选择一个中间件,将登录信息保存在一个中间件上,这个中间件可以为 Redis 这样的数据库。那么第一次登录,我们将session 信息保存在 Redis 中,跳转到第二个服务器时,我们可以先去Redis上查询是否有登录信息,如果有,就能直接进行登录之后的操作了,而不用进行重复登录。
  2. 第二种方法是根据客户端的IP地址划分,每次都将同一个 IP 地址发送的请求都分发到同一个 Tomcat 服务器,那么也不会存在 session 共享的问题。
  • 而 nginx 的基于 IP 路由负载的机制就是上诉第二种形式。
  1. upstream OrdinaryPolling {
  2. ip_hash;
  3. server 127.0.0.1:8080 weight=5;
  4. server 127.0.0.1:8081 weight=2;
  5. }
  6. server {
  7. listen 80;
  8. server_name localhost;
  9. location / {
  10. proxy_pass http://OrdinaryPolling;
  11. index index.html index.htm index.jsp;
  12. }
  13. }
  • 注意:我们在 upstream 指令块中增加了 ip_hash 指令。该指令就是告诉 nginx 服务器,同一个 IP 地址客户端发送的请求都将分发到同一个 Tomcat 服务器进行处理。

2.4 基于服务器响应时间负载分配

  • 根据服务器处理请求的时间来进行负载,处理请求越快,也就是响应时间越短的优先分配。
  • 通过增加了 fair 指令。
  1. upstream OrdinaryPolling {
  2. server 127.0.0.1:8080 weight=5;
  3. server 127.0.0.1:8081 weight=2;
  4. fair;
  5. }
  6. server {
  7. listen 80;
  8. server_name localhost;
  9. location / {
  10. proxy_pass http://OrdinaryPolling;
  11. index index.html index.htm index.jsp;
  12. }
  13. }

2.5 对不同域名实现负载均衡

  • 通过配合location 指令块我们还可以实现对不同域名实现负载均衡。
  1. upstream wordbackend {
  2. server 127.0.0.1:8080;
  3. server 127.0.0.1:8081;
  4. }
  5. upstream pptbackend {
  6. server 127.0.0.1:8082;
  7. server 127.0.0.1:8083;
  8. }
  9. server {
  10. listen 80;
  11. server_name localhost;
  12. location /word/ {
  13. proxy_pass http://wordbackend;
  14. index index.html index.htm index.jsp;
  15. }
  16. location /ppt/ {
  17. proxy_pass http://pptbackend;
  18. index index.html index.htm index.jsp;
  19. }
  20. }

动态分离

高可用集群

1. nginx 配置主从模式

2. nginx 配置双主模式