• 分布式计算实验1 负载均衡


    一、实验内容

      重现课上老师演示的基于Nginx负载均衡实验。

    二、实验原理

    1. 负载均衡提出的背景

      随着Internet的快速发展和业务量的不断提高,基于网络的数据访问流量迅速增长,一些数据中心的瞬时数据通信量甚至可高达几十Gb每秒。同时,服务器网站借助基于HTTP,FTP,SMTP等协议的应用,为访问者提供了越来越丰富的内容和信息,这导致服务器逐渐被海量数据淹没。此外,大部分网站(尤其是电商、交通部门)都需要提供不间断的24小时服务,任何服务中断或关键数据丢失都会造成不可估量的高额商业损失。这些,都对应用服务提出了高性能和高可靠性的需求。

      然而,相对于网络技术的迅速发展,服务器的处理器速度和内存访问速度的增长却是比较缓慢的。网络带宽增长的同时带来的用户数量的增长,使得服务器资源消耗严重,进而导致服务器成为了网络瓶颈,传统的单机模式,也往往成为网络故障点。

      为了解决这一尴尬局面,人们提出了服务器负载均衡策略。

    2. 负载均衡的含义及其优点

      多台服务器通过网络设备相连组成一个服务器集群,每台服务器都提供相同或相似的网络服务。服务器集群前端部署一台负载均衡设备,该负载均衡器负责根据已配置的负载均衡策略将来自外网中各用户的请求在内网中的服务器集群中分发,从而实现对多台服务器资源的充分利用与合理分配调度,最终可提升分布式系统的数据处理与通信效率。

      负载均衡有以下几个优点:

      (1) 成本较低:按照业务量配置服务器即可,已有资源不会浪费,若要新增资源也无需选择昂贵的高端设备;

      (2) 可扩展性:当业务量增长时,系统可通过增加服务器来满足需求,且不影响已有业务,不降低服务质量;

      (3) 高可靠性:单台服务器故障时,由负载均衡设备将后续业务转向其他服务器,不影响后续业务提供,保证24小时业务不中断;

      (4) 负载均衡优化了客户端请求在服务器集群内部的分配方式,减小了服务器之间发生负载不平衡现象发生的概率,提高了系统的反应速度与总体性能。

    3. 负载均衡的工作方式

      如下图所示,假设在某一时刻客户端 j j j向某网站发送了一个请求 R 1 R1 R1 R 1 R1 R1首先通过网关及Internet发送至负载均衡器(根据负载均衡器的外网IP);然后,该网站的负载均衡器采用某种负载均衡策略将 R 1 R1 R1通过内网IP分配给服务器集群中的某个服务器 i i i;待服务器 i i i根据 R 1 R1 R1传递来的参数完成客户端 j j j的请求后,服务器 i i i将客户端 j j j需要的资源数据 A 1 A1 A1传递给负载均衡器;最后,负载均衡器再把 A 1 A1 A1传递给客户端 j j j,完成一次服务。

      此后,每当负载均衡器接收到来自某一客户端的请求后,就重复以当前的负载均衡策略将请求发送给服务器集群中的某一服务器让其处理请求,最后再将相应的资源返回给客户端,通过该方式充分利用所有服务器的资源,实现整个服务器集群的负载均衡,提高系统处理海量请求数据的效率和容错能力。

    4. 常用的负载均衡策略

      (1) 随机;

      (2) 轮询;

      (3) 固定权重;

      (4) IP哈希;

      (5) 最少TCP连接数;

      (6) 最小响应时间。

    5. Nginx

      Nginx是开源、高性能、高可靠的Web和反向代理服务器,而且支持热部署,几乎可以做到7 * 24小时不间断运行,即使运行几个月也不需要重新启动,还能在不间断服务的情况下对软件版本进行热更新。性能是Nginx最重要的考量,其占用内存少、并发能力强、能支持高达5w个并发连接数,最重要的是,Nginx是免费的并可以商业化,配置使用也比较简单。

      Nginx的特点:

      (1) 高并发、高性能;

      (2) 模块化架构使得它的扩展性非常好;

      (3) 异步非阻塞的事件驱动模型这点和Node.js相似;

      (4) 相对于其它服务器来说它可以连续几个月甚至更长而不需要重启服务器使得它具有高可靠性;

      (5) 热部署、平滑升级;

      (6) 完全开源,生态繁荣。

      Nginx的主要应用场景:

      (1) 静态资源服务,通过本地文件系统提供服务;

      (2) 反向代理服务,延伸出包括缓存、负载均衡等;

      (3) API服务,OpenResty。

      Nginx主要配置项介绍:

      (1) server模块:server是一切的开始,代表一个代理的出现,里边包括两大配置项listen(监听的端口)和server_name(监听的地址),还包括了location和其他配置项。

      (2) location模块:location是Nginx的精华,Nginx就是通过拦截到的请求去对配置好的location块进行请求代理的。被代理的url去对location后边的字符串(或正则)进行匹配,根据一定的规则选择走哪个location。

      (3) proxy_pass:proxy_pass是用来对请求进行转发的,一般用来代理后台服务,就是把请求进行重定向。

      (4) upstream模块:用于设置负载均衡的具体实施策略以及server集群的定义,如IP、端口号、权重等等。

    三、实验步骤

      Step1:下载Nginx并解压

      通过http://nginx.org/en/download.html下载Nginx,选择Stable version稳定版本:

      下载完成后,将nginx-1.20.2文件夹解压到目标路径。

      Step2:验证Nginx服务能否正常启动

      进入目标路径中的nginx-1.20.2文件夹运行cmd,输入start nginx启动nginx,然后在浏览器地址栏中输入localhost:80并按下回车,若页面返回如下图所示的提示信息,则说明nginx服务启动成功。

      Step3:用JavaScript实现服务器端

      在本次实验中,我创建了5个服务器,分别监听本地IP 127.0.0.1的2401, 2402, 2403, 2404, 2405端口。实现server 1的js代码如下(其余3个服务器的实现代码不再展示):

    // 请求NodeJs自带的http模块,并赋值给http变量
    var http = require('http');
    
    function requestListener(request, response) {
      console.log("Request received.");
      // 打印收到的请求头
      console.log(request.headers);
      // 向请求的客户端发送响应头,HTTP状态码200表示请求成功
      response.writeHead(200, {"Content-Type": "text/html"});
      // 输出提示信息
      response.write("Hello, this is server 1.");
      // 结束服务
      response.end();
    };
    // 构造server端
    // http.createServer()会返回一个对象,该对象有一个listen方法,这个方法有一个Number类型的参数,指定了HTTP服务器监听的端口号
    var server = http.createServer(requestListener);
    // 监听2401端口
    server.listen(2401);
    // 输出该服务器的运行状态
    console.log('Server 1 is running at http://127.0.0.1:2401... ');
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

      配置完服务器端后,在js文件所在文件夹中运行cmd,输入node s1.js,运行server 1,其余四个server的开启方式类似。

      Step4:修改nginx.conf文件

      1. 轮询方式:

    # 配置负载均衡方式为默认的轮询方式
    upstream webservers {
            server 127.0.0.1:2401;
            server 127.0.0.1:2402;
            server 127.0.0.1:2403;
            server 127.0.0.1:2404;
            server 127.0.0.1:2405;
        }
        server {
            listen  2400;
            server_name  localhost;
    		# 设置代理转发
            location / {
                proxy_pass http://webservers;
            }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

      2. 随机分发:

    # 配置负载均衡方式为随机分发方式
    upstream webservers {
    	random;
        server 127.0.0.1:2401;
        server 127.0.0.1:2402;
        server 127.0.0.1:2403;
        server 127.0.0.1:2404;
        server 127.0.0.1:2405;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

      3. 固定权重:

    # 配置负载均衡方式为固定权重方式
    upstream webservers {
        server 127.0.0.1:2401 weight = 40;
        server 127.0.0.1:2402 weight = 20;
        server 127.0.0.1:2403 weight = 20;
        server 127.0.0.1:2404 weight = 10;
        server 127.0.0.1:2405 weight = 10;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

      4. IP Hash:

    # 配置负载均衡方式为IP Hash方式
    upstream webservers {
    	ip_hash;
        server 127.0.0.1:2401 weight = 40;
        server 127.0.0.1:2402 weight = 20;
        server 127.0.0.1:2403 weight = 20;
        server 127.0.0.1:2404 weight = 10;
        server 127.0.0.1:2405 weight = 10;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

      5. 最少连接数:

    # 配置负载均衡方式为IP Hash方式
    upstream webservers {
    	least_conn;
        server 127.0.0.1:2401;
        server 127.0.0.1:2402;
        server 127.0.0.1:2403;
        server 127.0.0.1:2404;
        server 127.0.0.1:2405;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

      每次更新完负载均衡方式配置后,我们需要用nginx -s reload命令重启nginx服务。

    四、实验结果

      1. 轮询方式:在cmd中利用curl localhost:2400命令访问负载均衡器的对外端口2400,则负载均衡器会将若干次的访问请求按顺序轮流分发给server群中的s1,s2,s3,s4,s5。

      2. 随机方式:在cmd中利用curl localhost:2400命令访问负载均衡器的对外端口2400,则负载均衡器会将若干次的访问请求随机分发给server群中的s1,s2,s3,s4,s5。

      3. 固定权重方式:在cmd中利用curl localhost:2400命令访问负载均衡器的对外端口2400,则负载均衡器会将若干次的访问请求按照各服务器的权重分发给server群中的s1,s2,s3,s4,s5。

      连续curl 20次,并统计浏览器请求分发到各server的次数如下表所示:

    server 1server 2server 3server 4server 5
    8次4次4次2次2次

      不难看出,浏览器请求被各server接收到的次数比为4 : 2 : 2 : 1 : 1,这符合先前设定的权重之比。

      4. IP Hash方式:每个请求按访问IP的Hash散列结果分配,来自某客户端的请求固定访问一个后端服务器,可以解决session的问题。 在cmd中利用curl localhost:2400命令访问负载均衡器的对外端口2400,由于本地模拟的请求都来自同一IP,故负载均衡器会将若干次的访问请求分配给server群中固定的服务器server 1。

      4. 最少连接数方式:把请求发给当前链接数最少的后端服务器。 在cmd中利用curl localhost:2400命令访问负载均衡器的对外端口2400,由于在本次实验中各服务器只处理我们每次用curl模拟的请求,不存在哪个服务器的连接数更多或更少的问题,因此这里最少连接数方式退化为轮询方式。

      4. 补充记录:

      由于我在编写server端时加入了console.log(request.headers)等控制台回显语句,因此每curl一次,相应的server控制台就会回显一次请求头信息,如下图所示:


    五、心得体会

      1. 通过本次实验,我掌握了服务器集群以及负载均衡的概念,并通过动手实现基于NginxNode.js的负载均衡加深了对于负载均衡的具体策略包括随机、轮询、固定权重、IP Hash、最少连接数等的认识。

      2. 在本次实验的实现过程中,我也遇到了一些问题,但最终解决了它们,在这里记录一些要点:

      (1) 在upstream中定义服务器集群的IP时只能用127.0.0.1这个本地IP,否则无法访问,并且在实验过程中我发现有些端口已被占用,无法使用,需要重新选择可用的端口;

      (2) curl的端口号必须和nginx.conf中server块中的监听端口号一致,否则会请求失败;

      (3) 每次改变负载均衡策略后要记得用nginx -s reload命令重启nginx服务;

      (4) 若不小心开启了多个Nginx服务进程,可用taskkill /f /t /im nginx.exe命令终止所有正在运行的nginx进程,这样可以避免用任务管理器一个一个地kill进程。

  • 相关阅读:
    [ROS](10)ROS通信 —— 服务(Service)通信
    Fiddler基础入门教程【7】--Composer构造器
    Python面向对象(一)
    Streamsets Data Collector 3.12
    分词phrase
    2022-8-18 第七小组 学习日记 (day42)JDBC+练习题
    java毕业设计家教管理系统mybatis+源码+调试部署+系统+数据库+lw
    Mysql详细学习笔记
    秋招腾讯!配套初级程序员到Java高级架构师学习路线+配套学习资源
    关于MuLoginWebGL介绍说明:
  • 原文地址:https://blog.csdn.net/qq_45717425/article/details/126140538