SRE之前端服务器的负载均衡

news2024/11/23 15:17:41

写在前面


  • 今天和小伙伴们分享一些前端服务器负载均衡技术
  • 内容为结合《 SRE Google运维解密》 整理:
    • 涉及DNS 负载均衡
    • VIP 负载均衡
    • 反向代理负载均衡
  • 理解不足小伙伴帮忙指正

傍晚时分,你坐在屋檐下,看着天慢慢地黑下去,心里寂寞而凄凉,感到自己的生命被剥夺了。当时我是个年轻人,但我害怕这样生活下去,衰老下去。在我看来,这是比死亡更可怕的事。--------王小波


运维大型系统时,将所有鸡蛋放在一个篮子里是引来灾难的最好办法。所以从容灾,负载均衡角度考虑,一般的大型系统,受众较多的,比如电信运营商的系统,都会有多个数据中心,根据流量分布,地域划分,同时考虑地理位置,电费,房价,人力等相关的经济因素,负载均衡的同时,解决了容灾问题。

在这里插入图片描述

负载的模式有很多种,主备,轮询,随机,哈希一致性负载等,比如主备区域负载,正常业务可以走省级别的数据中心,然后数据增量同步给集团数据中心,当省数据中心故障时,可以切到集团的地址,反之亦然。

有时候硬件并不能解决问题

用户流量负载均衡(traffic load balancing)系统是用来决定数据中心中的这些机器中哪一个用来处理某个请求的。

理想情况下,用户流量应该最优地分布于多条网络链路上、多个数据中心中,以及多台服务器上。但是这里的 “最优”是如何定义的呢?

并没有一个独立的答案,最优严重依赖于下列几个因素:

  • 逻辑层级(是在全局还是在局部)
  • 技术层面(硬件层面与软件层面)
  • 用户流量的天然属性

讨论以下两个常见的用户流量场景:一个搜索请求和一个视频上传请求

用户想要很快地获取搜索结果,所以对 搜索请求来说最重要的变量是延迟(latency)。对于视频上传请求来说,用户已经预期该请求将要花费一定的时间,但是同时希望该请求能够一次成功,所以这里最重要的变量是吞吐量(throughput)

两种请求用户的需求不同,是我们在 全局层面 决完“最优”分配方然的重要条件

  • 最小化请求的延迟 :搜索请求将会被发往最近的、可用的数据中心:评价条件是数据包往返时间(RTT)
  • 最大化吞吐量: 视频上传流将会采取另外一条路径——也许是一条目前带宽没有占满的链路—来最大化吞吐量,同时也许会牺牲一定程度的延迟。

局部层面: 在一个数据中心内部,我们经常假设同一个物理建筑物内的所有物理服务器都在同一个网络中,对用户来说都是等距的。因此在这个层面上的“最优”分配往往关注于优化资源的利用率,避免某个服务器负载过高

在现实中,很多其他因素也都在“最优”方案的考虑范围之内:有些请求可能会被指派到某个稍远一点的数据中心,以保障该数据中心的缓存处于有效状态。或者某些非交互式请求会被发往另外一个地理区域,以避免网络拥塞

负载均衡,尤其是大型系统的负载均衡,是非常复杂和非常动态化的。

Google在多个层面上使用负载均衡策略来解决这些问题:

DNS进行负载均衡

在某个客户端发送HTTP请求之前,会通过域名获取IP,需要先通过系统底层Socket库的解析器来向DNS服务器发起请求查询IP地址。DNS系统会通过域名和地址的映射表中查找相关的记录,然后返回ip,这就为我们第一层的负载均衡机制提供了一个良好基础:

DNS负载均衡,最简单的方案是在DNS回复中提供多个A记录或者AAAA记录(ipv4&ipv6),由客户端任意选择一个IP地址使用。这种方案虽然看起来简单并且容易实现,但是存在很多问题。

PS C:\Users\liruilong> nslookup www.baidu.com
DNS request timed out.
    timeout was 2 seconds.
服务器:  UnKnown
Address:  10.96.0.1

非权威应答:
名称:    www.a.shifen.com
Addresses:  220.181.38.150
          220.181.38.149
Aliases:  www.baidu.com

PS C:\Users\liruilong>

www.baidu.com 被解析为两个IP地址,即220.181.38.149和220.181.38.150。这意味着当你尝试连接到www.baidu.com时,你的计算机可以选择其中一个IP地址来建立连接。这样可以分散流量、提高性能和可用性,以应对高负载或服务器故障的情况。

在DNS服务器上创建多个A记录,每个记录对应一个服务器的IP地址。例如,假设有3个服务器的IP地址分别为192.168.1.1、192.168.1.2和192.168.1.3,则需要在DNS服务器上创建3个A记录,分别对应这些IP地址。

针对每个A记录,设置相同的域名和TTL值,以确保客户端每次查询时都会得到相同的结果。

在BIND DNS服务器中,可以使用round-robin关键字启用轮询功能

编辑 BIND 配置文件,并在 example.com zone 中添加以下行:

zone "example.com" {
    type master;
    file "example.com.zone";
    rrset-order { random; };
};

同时需要在 example.com.zone 文件中添加对应三个域名相同的A 记录

第一个问题 是这种机制对客户端行为的约束力很弱:记录是随机选择的,也就是每条记录都会引来有基本相同数量的请求流量。如何避免这个问题呢?

理论上我们可以使用SRV记录来指明每个IP地址的优先级和比重,但是HTTP·协议目前还没有采用SRV记录。(某些互联网协议,如 IMAP、SIP 和 XMPP`,除了与特定的服务器连接外,还需要连接到一个特定的端口。SRV 记录是在 DNS 中指定端口,优先级和权重等)

_xmpp._tcp.example.com. 86400 IN SRV 10 5 5223 server.example.com

服务 XMPP
原型协议 TCP
域名 example.com
TTL(有效期) 86400
class(网络类型) IN
在提示下键入 SRV
优先级 10
权重 5
端口 5223
目标 server.example.com

另一个问题 是客户端无法识别“最近”的地址。我们可以通过提供一个 anycast DNS服务器 地址,通过 DNS 请求一般会到达最近的地址这种方式来一定程度上缓解这个问题。内部DNS,服务器可以使用最近的数据中心地址来生成DNS回复。

更进一步的优化方式是,将所有的网络地址和它们对应的大概物理位置建立一个对照表,按照这个对照表来发送回复。但是这种解决方案使得我们需要维护一个更加复杂的DNS服务,并且需要维护一个数据更新流水线(pipeline)来保证位置信息的正确性。

当然,没有一个很简单的方案,因为这是由DNS的基本特性决定的:最终用户很少直接跟权威域名服务器(authoritive nameserver)直接联系。在用户到权威服务器中间经常有一个递归解析器(recursive nameserver)代理请求。该递归解析器代理用户请求,同时经常提供一定程度的缓存机制。

这样的DNS中间人机制在用户流量管理上有三个非常重要的影响:

  • 递归方式解析IP
  • 不确定的回复路径
  • 额外的缓存问题

负载均衡:虚拟IP

虚拟IP地址(VIP)不是绑定在某一个特定的网络接口上的,它是由很多设备共享的。所以说和代理是有本质区别的,代理往往是一个绑定到一个特定的网卡,主要用于负载均衡,这里讲的VIP是 `虚拟IP+负载均衡``的一种设计。

当然,从用户视角来看,VIP仍然是一个独立的、普通的lP地址。理论上来讲,这种实现可以让我们将底层实现细节隐藏起来(比如某一个VIP背后的机器数量),无缝进行维护工作。

比如我们可以依次升级某些机器,或者在资源池中增加更多的机器而不影响用户。

数据到达数据中心内部之后,我们可以在内部采用更大的MTU来避免碎片重组的发生,但是这种做法需要网络设备支持尽早进行负载均衡,以及分级多次进行

常见的 VIP 解决方案 一般使用 LVS+Keepalived 的方式,当然也可以考虑 NLB,HLB

LVS 是什么,即 Linux 虚拟服务器

┌──[root@vms152.liruilongs.github.io]-[~]
└─$ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  192.168.26.200:80 rr
  -> 192.168.26.153:80            Masq    2      0          0
  -> 192.168.26.154:80            Masq    2      0          0

LVS 无法对真实负载机器进行监控检测,即无法判断负载节点是否健康,能够提供能力,由此引入 Keepalived

另外使用 keepalived 可进行 HA 故障切换,也就是有一台备用的 LVS,主 LVS 宕机,LVS VIP 自动切换到从,可以基于 LVS+Keepalived 实现负载均衡及高可用功能,满足网站7x24小时稳定高效的运行。

┌──[root@vms152.liruilongs.github.io]-[~]
└─$ansible node -a 'ipvsadm -Ln'
192.168.26.153 | CHANGED | rc=0 >>
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  192.168.26.200:80 rr persistent 2
  -> 192.168.26.155:80            Route   3      0          0
  -> 192.168.26.156:80            Route   3      0          0
192.168.26.154 | CHANGED | rc=0 >>
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  192.168.26.200:80 rr persistent 2
  -> 192.168.26.155:80            Route   3      0          0
  -> 192.168.26.156:80            Route   3      0          0
┌──[root@vms152.liruilongs.github.io]-[~]
└─$

Keepalived 基于三层检测(IP层,TCP传输层,及应用层),需要注意,如果使用了 keepalived.conf 配置,就不需要再执行 ipvsadm -A 命令去添加均衡的 realserver 命令了,所有的配置都在 keepalived.conf里面设置即可。它可以自动地将真实服务器添加到 IPVS 中。当然,您需要在 keepalived.conf 文件中配置虚拟服务和真实服务器。

负载均衡:反向代理

基于反向代理的负载均衡技术, 通过使用反向代理服务器分发传入的请求后端服务器上。反向代理服务器充当了客户端和后端服务器之间的中间人,将请求转发给后端服务器,并将响应返回给客户端。

常见的反向代理负载均衡技术:Nginx,HAProxy,Apache HTTP Server` 等。负载均衡角度理解,反向代理来说更细了,ISO 参考模型角度考虑, 支持 4层和7层的代理,同时可以考虑做一些动静分离

4 层代理

┌──[root@liruilongs.github.io]-[~/load_balancing]
└─$ cat nginx.conf
user  nginx;
worker_processes  auto;
error_log  /var/log/nginx/error.log notice;
pid        /var/run/nginx.pid;
daemon off;

events {
    worker_connections  1024;
}
# 四层代理的方式
stream{
    server {
        listen     8088;
        proxy_pass backend;
        }
    upstream backend {
        server web1:80;
        server web2:80;
    }

}

7 层代理

┌──[root@liruilongs.github.io]-[~/load_balancing]
└─$ cat nginx.conf
user  nginx;
worker_processes  auto;
error_log  /var/log/nginx/error.log notice;
pid        /var/run/nginx.pid;
#daemon off;
events {
    worker_connections  1024;
}
http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$upstream_addr - $remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for" ';
    access_log  /var/log/nginx/nginx_access.log  main;
    sendfile        on;
    keepalive_timeout  65;
    include /etc/nginx/conf.d/*.conf;
    server {
        listen          8099;
        server_name     localhost;
        root            /var/www/html/;
        index           index.html index.htm;
        access_log      /var/log/nginx/default_access.log main;
        error_log       /var/log/nginx/default_error.log;
        location / {
                proxy_pass http://backend;
        }
        location ~ .* {
                        proxy_pass http://backend;
                        proxy_set_header Host $http_host;
                        proxy_set_header X-Real-IP $remote_addr;
                        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }
}
    upstream backend {
        server web2:80;
        server web1:80;
    }
}

博文部分内容参考

© 文中涉及参考链接内容版权归原作者所有,如有侵权请告知


《 SRE Google运维解密》


© 2018-2023 liruilonger@gmail.com, All rights reserved. 保持署名-非商用-相同方式共享(CC BY-NC-SA 4.0)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/866258.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

人大金仓三大兼容:Oracle迁移无忧

企业级应用早期的架构模式是C/S(Client/Server)模式,Client做人机交互逻辑的呈现,Sever做业务计算逻辑的实现。这就类似餐馆的运作模式,Client是前台的服务员提供点菜和上菜服务,而Server则是后厨完成菜品的…

Java基础篇--修饰符

Java语言提供了很多修饰符,主要分为以下两类: 访问控制修饰符 非访问修饰符 访问控制修饰符 private:私有访问权限,用于修饰类的属性和方法。被private修饰的成员只能在本类中进行访问。default(默认访问权限&…

spark 图计算 助力解决 dataframe中的链式依赖

链式依赖说明 name newName a b c d b c 我们需要的结果 即我们可以支持获取到链式转换的 起点 重点 以及链式的中间转换过程顺序数组. 特别说明: 出版只支持 单向 无分叉的图,其他复杂场景暂时未测试. 场景举例: 比如某件商品价格变化,我们需要知…

原始套接字编程(AF_PACKET+SOCK_RAW)模拟一个PING

1. 背景 最近看一个客户的代码片段,发现他在用原始套接字编程,一般学习套接字都是流式套接字和数据报套接字,本来也不是搞网络的,原始套接字了解得很少,借着这次机会,自己来学习一下原始套接字编程。 2. …

函数的模拟实现

题一&#xff1a; 模拟实现strncpy #include <stdio.h>void my_strncpy(char* arr2, char* arr1, size_t num){int i 0;for (i 0; i < num; i){*(arr2 i) *(arr1 i);}}int main(){char arr1[] "hello liangzai";char arr2[10] { 0 };//strncpy(ar…

包管理工具详解npm 、 yarn 、 cnpm 、 npx 、 pnpm(2023)

1、包管理工具npm &#xff08;1&#xff09;包管理工具npm&#xff1a; Node Package Manager&#xff0c;也就是Node包管理器&#xff1b;但是目前已经不仅仅是Node包管理器了&#xff0c;在前端项目中我们也在使用它来管理依赖的包&#xff1b;比如vue、vue-router、vuex、…

3.6 Spring MVC文件上传

1. 文件上传到本地 实现方式 Spring MVC使用commons-fileupload实现文件上传&#xff0c;注意事项如下&#xff1a; l HTTP请求方法是POST。 l HTTP请求头的Content-Type是multipart/form-data。 SpringMVC配置 配置commons-fileupload插件的文件上传解析器CommonsMultip…

搭建servlet服务

目录 servlet的生命周期 配置tomcat环境 创建web后端项目 配置web.xml http请求 get和post 其他请求 http响应 Servlet是Server Applet的简称&#xff0c;意思为用Java编写的服务器端的程序&#xff0c;它运行在web服务器中&#xff0c;web服务器负责Servlet和客户的通…

Springboot开发常用注解

文章目录 1.RestController2.Data3.RequestMapping4.Builder 1.RestController RestController注解其实就是将 return 中的内容以 JSON字符串的形式返回客户端 controller的详解 2.Data Data详解 3.RequestMapping RequestMapping 4.Builder Builder

文件系统目录结构

1. 目录结构 linux的文件系统是采用级层式的树状目录结构&#xff0c;在此结构中的最上层是根目录/ &#xff0c;然后在此目录下再创建其他的目录。 在linux中&#xff0c;一切皆文件(Linux将所有的设备、文件、进程等都当做文件来处理) 2. 目录作用具体介绍 目录名解析/b…

访企聚力促创新:长安大学来访闪马智能

7月31日&#xff0c;长安大学运输工程学院院长葛颖恩教授、学院副书记李婷以及学办主任董彬一行来访闪马智能&#xff0c;闪马智能创始人兼CEO彭垚、城市交通行业总经理兼营销副总裁詹诚以及公共交通行业总经理熊天圣等出席了本次交流会。 长安大学运输工程学院院长葛颖恩教授…

软考考点之Mccabe度量计算及路径覆盖

软考考点之Mccabe度量计算及路径覆盖 [2023年上半年] 34、35、以下流程图中&#xff0c;至少需要(34)个测试用例才能覆盖所有路径。采用McCabe方法计算程序复杂度为(35) A&#xff0e;3B&#xff0e;4C&#xff0e;5D&#xff0e;6(35)A&#xff0e;2B&#xff0e;3C&#xf…

【框架类】—Vue3的生命周期

一、生命周期的相关函数 onBeforeMount 页面渲染之前 和 onMounted渲染之后 示例 <template><div class"test"><div ref"el">组件初始化</div></div> </template> <script> //按需引入所需方法 import { ref,…

sudo root命令不在sudoers文件中。此事将被报告。全网比较详细版本,解决报错问题步骤较多

我在使用个人用户zhang&#xff08;非root用户&#xff09;时&#xff0c;在执行其他命令时&#xff0c;使用sudo命令来执行的时候&#xff0c;需要验证当前用户的密码&#xff0c; 输入了之后&#xff0c;提示“zhang‘ 不在sudoers文件中&#xff0c;此事将被报告” 分析原…

JAVA设计模式----原型设计模式

文章目录 一、简介二、实现方式三、原型模式的注意事项浅拷贝与深拷贝浅拷贝深拷贝一、简介 定义:用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。 类型:创建类模式 类图: 原型模式主要用于对象的复制,它的核心是就是类图中的原型类Prototype。Protot…

eNSP:ibgp的破水平切割练习

实验要求&#xff1a; 拓扑展示&#xff1a; 命令操作&#xff1a; R1&#xff1a; <Huawei>sys [Huawei]sys r1 [r1]int g 0/0/1 [r1-GigabitEthernet0/0/1]ip add 12.1.1.1 24 [r1-GigabitEthernet0/0/1]int lo0 [r1-LoopBack0]ip add 1.1.1.1 24 [r1-LoopBack0]osp…

dingding机器人

“自定义机器人”只支持消息发送&#xff0c;自动回复需要“企业内部机器人” 消息发送 import requests import jsonres requests.post(https://oapi.dingtalk.com/robot/send?access_token036a339axxx,data json.dumps({"text": {"content":"h…

React UI组件库

1 流行的开源React UI组件库 1 material-ui(国外) 官网: Material UI: React components based on Material Design github: GitHub - mui/material-ui: MUI Core: Ready-to-use foundational React components, free forever. It includes Material UI, which implements Go…

【Hilog】鸿蒙系统日志源码分析

【Hilog】鸿蒙系统日志源码分析 Hilog采用C/S结构&#xff0c;Hilogd作为服务端提供日志功能。Client端通过API调用&#xff08;最终通过socket通讯&#xff09;与HiLogd打交道。简易Block图如下。 这里主要分析一下。Hilog的读、写、压缩落盘&#xff0c;以及higlog与android…

PIL报错:TypeError: Cannot handle this data type: (1, 1, 3), <f4

问题&#xff1a; mi_fgsm.py:101: DeprecationWarning: Starting with ImageIO v3 the behavior of this function will switch to that of iio.v3.imread. To keep the current behavior (and make this warning disappear) use import imageio.v2 as imageio or call image…