笔记Nginx

7次阅读

共计 5316 个字符,预计需要花费 14 分钟才能阅读完成。

负载均衡及其架构原理

写在前面:

架构是一个比较宏观的概念,是控制、管理代码层面实现这一面更好地工作的过程。接下来请先看看几个版本的架构示意图。

单机 Tomcat


如上图所示,理论上单个 Tomcat 并发容量是 200~300 左右, 经过优化后的最多 500。虽然单机 Tomcat 开发部署简单,但出点故障就不行了,例如出现单点故障后应用服务就不可以访问了。

多 Tomcat、DNS 轮询架构

如上图所示,提供备用 11.4 IP,当 IP 请求来的时候进行 IP 轮询,第一个请求走 12.3,第二个请求走 11.4,下一个请求又走 12.3 依次轮询。这样不仅解决了单点故障的问题, 容量也提升了。但还是存在一些缺点,例如:

  1. 多个 Tomcat 应用暴露到外网,造成安全隐患,入口不集中。
  2. 如果其中一个 Tomcat 挂了,请求的的 IP 刚好进到坏的 Tomcat, 还是不可以访问,会导致用户流失。

负载均衡 架构


此架构图我们在浏览器和 Tomcat 之间加了请求分发工具和负载均衡设备。将请求入口集中在 nignx 下管理,用 nignx 的反向代理 / 负载均衡的典型算法,随机将请求分发到不同的 Tomcat。外网仅暴露一个接口,而 Tomcat 没有暴露到外网,上面的所遇到的问题也得到了比较好的解决。但这样的架构离完美无缺还差的很远,因为请求分发、负载均衡的设备只设置了一台,只要存在单台,那么单点故障也会存在。而且这是一个重要节点,负责一切请求,一旦出故障,所有服务不可用。所以就衍生了下一个架构.

负载均衡架构 2

双机热备,解决了负载均衡的单机 BUG 问题。但是对外同一时刻只有一个在服务,一个负责请求,另外一个随时待命,每隔一段时间做一次心跳检测负载均衡是否都存活。假如其中一个挂了,就要把虚拟 IP 改到另外一个负载均衡设备(Nginx),这样就可以继续提供服务了,体现了高可用性。

这样的架构算是还比较满意,但有存在的缺点:

  1. 一台工作一台待命,如果其中一挂了另外一台才开始工作,利用低且浪费资源。
  2. 请求分发设备有流量并发上限。

接下来我们一起来看看一套比较完善的方案

负载均衡架构 3

这一套方案是基于双机热备 + DNS 轮询,在 DNS 供应商做些手脚,户输入域名通过浏览器访问 DNS 服务器,得到一个虚拟 IP,通过虚拟 IP 进入相应的双机热备份,下一个请求来了,就通过轮询,用下一个虚拟 IP 又进入了另外一个虚拟 IP 对应的双机热备份。

最后,在实际开发中这一套方案可以承受起几百万的访问量,但还是以实际压力测试和单点故障测试数据为准。单机 Tomcat 跑一个应用的美好时代一去不复返,但一个成熟的产品一天 24 小时都要不停机运行。

常见负载均衡设备优缺点及 Tomcat 压力测试

负载均衡实现方式

硬件方面

F5(硬件设备)实现

优点:非常快,可靠性高,并发量大

缺点:成本高,不方便,最致命的是不能将动态请求和静态请求分离

软件方面
  1. Linux 的 LVS(基于 Linux 系统 IP 层面的负载均衡)
  2. 优点:可靠性非常高,简单易用,并发量大

缺点:不能将动态请求和静态请求分离(很少用)

  1. apache http server

优点:可靠性高,可以动静请求分离

缺点:效率低

  1. Nginx

简介:这是一种反向代理软件,反响代理:将庞大的 Tomcat 服务器的 IP 隐藏,真正在工作的是 Nginx(即服务器隐藏了,找了个代理),正向代理:即隐藏用户 IP。

优点:非常快,可靠性高并发量大,更重要的是可以实现动态请求和静态请求分离

负载均衡所存在的问题:session ID 会发生变化

Nginx 动静分离

原理:Nginx 动静分离简单来说就是把动态跟静态请求分开,不能理解成只是单纯的把动态页面和静态页面物理分离。严格意义上说应该是动态请求跟静态请求分开,可以理解成使用 Nginx 处理静态页面,Tomcat、Resin 出来动态页面。

Tomcat 压力测试

测试软件:jemeter

步骤:

1. 创建一个简单的 Servlet 工程,打包成 war 并部署到 Tomcat

ServletDemo 类

test.jsp

2. 下载 jemeter

网址:https://jmeter.apache.org/dow… 解压然后 bin 目录下双击 jmeter.bat.

3. 添加线程组并填写参数

4. 添加 Http 请求并填写参数

5. 添加监听想要查看的选项

6. 简单 servlet 项目测试结果:

图形结果图

察看结果树

聚合报告结果

7. 超多条线程演示

测试过程中可以偷偷查看一下任务管理器的数据因为线程数高了有些时候会导致电脑卡顿。

最后来看一下 6000 条线程下的聚合报告

当线程数很高的时候,Tomcat 承受不聊了(受业务影响),其中 Error 代表错误率,Throughput 代表 Tomcat 的吞吐量。所以说 Tomcat 承受能力是有限的。

如果有兴趣你可以到的 Tomcat 安路径下 servlet.xml 修改一些配置继续测试。当然也可以通过这里进行一些相关优化。

Nginx 负载均衡实战

Nginx 下载解压

地址:http://nginx.org/ 找 stable version 版的下载,尽量不要下载最新的

准备两台 tomcat

复制 Tomcat 并修改可以修改的端口(文件在 conf 的 server.xml)。同时分别对应两个 Tomcat 的学习项目做个标记,比如第一台 tomcat 访问成功的界面显示“Hello,Tomcat 1 shide”,第二台同理。这里记录一下我第二台 Tomcatserver.xml 的端口修改,以防时回查时忘记。

8005→8015
8080→8090
8009→8019
8443→8453

修改 nginx 的配置文件(nginx.conf)

在文件中添加两个东西

1.
   upstream    test-service{
       server    localhost:8080;
       server    localhost:8090;
}
# upstream 表示上游服务器,test-service 填的是服务器集群名,这里取 test-service。2.
proxy_pass http://test-service;
# 意思是只有 test-service 下面的 tomcat 才能通过我的反向代理。

启动两个 Tomcat 和 Nginx

在浏览器输入上一篇文章的项目访问路径:http://localhost/test_war/test

首先会看到下图情况:

刷新一下结果如下图

发现每刷新一次浏览器 Nginx 就将请求发送到另一个 Tomcat,这体现出了负载均衡的轮询算法。接下来就介绍几种常见的负载均衡算法。

常见负载均衡算法解析

1.轮询 RoundRobin

很公平的原则,即每次过来的请求都会分配到相应的 tomcat,大家一次排队各入各的位置。如果没位置了又从头开始。

2.随机算法

通过过一定范围的随机数来分发请求给相应的 tomcat. 当请求量很大时,接近轮询。

3.源地址哈希

通过请求来源的 IP 计算相应的 hashCode 来分发给相应的 Tomcat, 只要 IP 不发生变动,请求分发的 Tomcat 也就固定了。

4.加权轮询

在轮询的基础上增加权重,比如,现在是 tomcat1,tomcat2, 此时 tomcat2 加权重 4,那么轮询的顺序即 tomcat1,tomcat2,tomcat2,tomcat2,tomcat2,tomcat2。

5.加权随机法

跟加权轮询类似一样的做法。比如,tomcat1,tomcat2,此时 tomcat2 增加权重为 4,那么 tomcat1,tomcat2,tomcat2,tomcat2,tomcat2,tomcat2, 那么 tomcat 随机分发的时候分发的几率就增大。

6.最小连接数法

根据后端服务器当前的连接情况,动态的选取当前积压连接数最少的一台服务器来处理当前请求。

负载均衡带来的问题

Nginx 负载均衡实战回顾,我们采用了轮询以及另外几种常见的负载均衡算法实现了 Nginx 的效果,接下来我们分别对两个 Tomcat 稍微改造一下。

操作:在界面上显示 session ID

启动 Tomcat 和 nginx 并输入路径结果如下图,刷新界面之后会发现请求会分发到另一个 tomcat 上,sessionId 也会发生变化,再刷回到 tomcat1 的时候 sessionId 也会发生变化。所以这就出现了 sessionId 不一致的问题,大部分系统是要求用户登录的,由于 session 的问题会导致用户登陆之后每一次请求都可能要重新登录,显然用户体验极差!!!

Session 共享问题解决方案

方案一:

Tomcat)之间进行 session 同步

即应用服务器 Tomcat 之间 session 同步共享, 但是应用服务器本身能力有限,再加 session 同步会带来网络开销。(具体操作百度:N 个 tomcat 之间实现 Session 共享)。

方案二:

基于(轮询 和 源地址哈希)算法(适合一般)

要设置 ip hash 算法(修改 Nginx 的 conf 文件:ip_hash)请求定位到同一台应用服务器,不切换 tomcat。

修改之后重启 nginx 访问界面,多刷新几遍看看 session 是否会发生变化?

很显然 session 没有发生变化,同个浏览器内打开新标签访问路径也是同一个 session。这方案虽然解决的 session 问题,但是不容灾了。因为如果定位到的那台应用服务器挂了,那么用户是无法访问的。

方案三:

外置集中管理 session(主流,其实就是类似单点登录)

利用 NoSQL 数据库、Redis 实现 session 外置集中管理,将用户每次登录之后的 sessionId 保存到 NoSQL 数据库或者 Redis 中,sessionid 是可以标识一个用户的,我们可以用用户的灯登录信息(账号密码、时间戳)生成一个 token 并设置加密、解密,用户登录之后将 token 存到 tomcat 外面,需要用到 session 的时候就到外置的集中管理中取,为了请求能分发到相应用服务器,从外置集中管理中取 token 校验即可。这样就解决的 session 共享问题。

Nginx 动静分离

简单理解:动态请求是要访问数据库并进行后端服务操作的,而静态资源(HTML,JavaScript,CSS,img 等文件)与后台应用分开部署,提高用户访问静态代码的速度,降低对后台应用访问。

演示演示

项目改造

1. 在 tomcat1(我这里没有改,把 8.5 当作是 1 了)的 webappstest_war 下创建 static 文件夹并添加一张图

2. 在 jsp 界面引用这张图片

3. 启动 tomcat 1 并访问效果如下图

4. 把静态资源文件放在 nginx 的 html 下并修改 nginx.conf 文件

这里要注意请求的路径必须和 tomcat 的下面一致

       location ~ \.(gif|jpg|jpeg|png|bmp|swf)$ {root   html;}

然后重启 nginx 并访问界面还会看到原来的界面。

关于双机热备

刚开始架构图那里所提到的负载均衡的双机热备的存活检测方案其实就是 keepalive 这个玩意,官网只提供 Linux 版本的,弄起来还是比较麻烦的,要想深入了解的还是百度咯。

这里贴上心跳检测原理图

主要是中间这个玩意,左右两边的主备 nginx 设备绑定到同一个 Keepalive,Keepalive 会根据上游请求的虚拟 ip 转发给主 Nginx,定时检测主 Nginx 是否存活,否就立马将 ip 转到备用的 Nginx。

理论知识总结

算法篇

1. 轮询 (默认)
每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器 down 掉,能自动剔除。
2.weight
指定轮询几率,weight 和访问比率成正比,用于后端服务器性能不均的情况。
3.ip_hash
每个请求按访问 ip 的 hash 结果分配,这样每个访客固定访问一个后端服务器,可以解决 session 的问题
4.fair(第三方)
按后端服务器的响应时间来分配请求,响应时间短的优先分配。
5. 按访问的 url 的 hash 结果来分配请求,使每个 url 定向到同一个后端服务器,后端服务器为缓存时比较有效。

四层、七层负载均衡

所谓四层就是基于 ip+ 端口的负载均衡;

七层就是基于 URL 等应用层信息的负载均衡;

同理,还有基于 MAC 地址的二层负载均衡和基于 IP 地址的三层负载均衡;

换句话说,二层负载均衡会通过一个虚拟 MAC 地址接收请求,然后在分配到真实的 MAC 地址,三层负载均衡会通过一个虚拟 IP 地址接收请求,然后再分配到真实的 IP 地址,四层通过虚拟 IP+ 端口接收请求,然后再分配到真实的服务器;

七层通过虚拟机的 URL 或主机名接受请求,然后再分配到真实的服务器。

优缺点:

七层负载均衡也称为“内容交换”,也就是主要通过文中的正真有意义的应用层内容,再加上负载均衡设备设置的服务器选择方式,决定最终选择的内部服务器。

以常见的 TCP 为例,负载均衡设备如果要根据真正的应用层内容再选择服务器,只能先代理最终的服务器和客户端建立连接(三次握手)后,才可能接收到客户端发送的真正应用层内容的报文,然后再根据报文中的特定字段,再加上负载均衡设备设置的服务器选择方式,,决定最终选择的内部服务器,负载均衡设备在这种情况下,更类似于一个代理服务器,负载均衡和前端的客户端以及以后端的服务器会建立 TCP 连接,所以从这个技术原理上来看,七层负载均衡对负载均衡的设备要求更高,处理能力、精确率更加友好。

正文完
 0