分布式系统的负载均衡 | 架构干货

  一、 什么是负载均衡?
  
  什么是负载均衡?
  
  记得第一次接触 Nginx 是在实验室,那时候在服务器部署网站需要用 Nginx 。Nginx 是一个服务组件,用来反向代理、负载平衡和 HTTP 缓存等。那么这里的 负载均衡 是什么?
  
  负载均衡(LB,Load Balance),是一种技术解决方案。用来在多个资源(一般是服务器)中分配负载,达到最优化资源使用,避免过载。
  
  file
  
  资源,相当于每个服务实例的执行操作单元,负载均衡就是将大量的数据处理操作分摊到多个操作单元进行执行,用来解决互联网分布式系统的大流量、高并发和高可用的问题。那什么是高可用呢?
  
  二、什么是高可用?
  
  首先了解什么是高可用?
  
  这是 CAP 定理是分布式系统的基础,也是分布式系统的 3 个指标:
  
  Consistency(一致性)
  
  Availability(可用性)
  
  Partition tolerance(分区容错性)
  
  那高可用(High Availability)是什么?高可用,简称 HA,是系统一种特征或者指标,通常是指,提供一定性能上的服务运行时间,高于平均正常时间段。反之,消除系统服务不可用的时间。
  
  衡量系统是否满足高可用,就是当一台或者多台服务器宕机的时候,系统整体和服务依然正常可用。
  
  举个例子,一些知名的网站保证 4 个 9 以上的可用性,也就是可用性超过 99.99%。那 0.01% 就是所谓故障时间的百分比。比如电商网站有赞,服务不可用会造成商家损失金钱和用户。那么在提高可用性基础上同时,对系统宕机和服务不可用会有补偿。
  
  file
  
  比如下单服务,可以使用带有负载均衡的多个下单服务实例,代替单一的下单服务实例,即使用冗余的方式来提高可靠性。
  
  总而言之,负载均衡(Load Balance)是分布式系统架构设计中必须考虑的因素之一。一般通过负载均衡,冗余同一个服务实例的方式,解决分布式系统的大流量、高并发和高可用的问题。负载均衡核心关键:在于是否分配均匀。
  
  三、常见的负载均衡案例
  
  file
  
  场景1:微服务架构中,网关路由到具体的服务实例 hello:
  
  两个相同的服务实例 hello service ,一个端口 8000 ,另一个端口 8082
  
  通过 Kong 的负载均衡 LB 功能,让请求均匀的分发到两个 hello 服务实例
  
  Kong 的负载均衡策略算法很多:默认 weighted-round-robin 算法,还有 consumer: consumer id 作为 hash 算法输入值等
  
  file
  
  场景2:微服务架构中,A 服务调用 B 服务的集群。通过了 Ribbon 客户端负载均衡组件:
  
  负载均衡策略算法并不高级,最简单的是随机选择和轮循
  
  四、互联网分布式系统解决方案
  
  file
  
  常见的互联网分布式系统架构分为几层,一般如下:
  
  客户端层:比如用户浏览器、APP 端
  
  反向代理层:技术选型 Nignx 或者 F5 等
  
  Web 层:前后端分离场景下, Web 端可以用 NodeJS 、 RN 、Vue
  
  业务服务层:用 Java 、Go,一般互联网公司,技术方案选型就是 SC 或者 Spring Boot + Dubbo 服务化
  
  数据存储层:DB 选型 MySQL ,Cache 选型 Redis ,搜索选型 ES 等
  
  一个请求从第 1 层到第 4 层,层层访问都需要负载均衡。即每个上游调用下游多个业务方的时候,需要均匀调用。这样整体系统来看,就比较负载均衡
  
  /* driver for lmdif1 example. */
  
  #include <stdio.h>
  
  #include <math.h>
  
  #include <assert.h>
  
  #include <minpack.h>
  
  #define real __minpack_real__
  
  // 用户自定义的函数f()
  
  // real -> __cminpack_real__ -> 浮点数(double)
  
  void fcn(const int *m, const int *n, const real *x, real *fvec, int *iflag);
  
  int main()
  
  {
  
  int j, m, n, info, lwa, iwa[3], one=1;
  
  real tol, fnorm, x[3], fvec[15], wa[75];
  
  // 函数个数15; 变量数3
  
  m = 15;
  
  n = 3;
  
  /* the following starting values provide a rough fit. */
  
  // 初始位置
  
  // 1.e0 = 1.0e0 = 1.0
  
  x[0] = 1.e0;
  
  x[1] = 1.e0;
  
  x[2] = 1.e0;
  
  // 为什么要设置75?
  
  lwa = 75;
  
  /* set tol to the square root of the machine precision. unless high
  
  precision solutions are required, this is the recommended
  
  setting. */
  
  // (建议打印一下看值是多少)
  
  tol = sqrt(__minpack_func_www.tdcqpt.cn_(dpmpar)(&one));
  
  // 需要注意指针
  
  __minpack_func__(lmdif1)(&fcn, &m, &n, x, fvec, &tol, &info, iwa, wa, &lwa);
  
  // 最终的2范数(即平方和开根号)
  
  fnorm = __minpack_func__(enorm)(&m, fvec);
  
  printf(" final l2 norm of the residuals%15.7g\n\n", (double)fnorm);
  
  printf(" exit parameter %10i\n\n", info);
  
  printf(" final approximate solution\n");
  
  for (j=1; j<=n; j+www.dongfangyuld.com+) {
  
  printf("%s%15.7g", j%3==1?"\n www.senta7pt.com ":"", (double)x[j-1]);
  
  }
  
  printf("\n");
  
  return 0;
  
  }
  
  // The problem is to determine the values of x(1), x(2), and x(3)
  
  // which provide the best fit (in the least squares sense) of
  
  // x(1) + u(i)/(v(i)*x(www.baikayule.cn) + w(i)*x(3)), i = 1, 15
  
  // to the data
  
  // y = (0.14,0.18,0.22,0.25,0.29,0.32,0.35,0.39,
  
  // 0.37,0.58,0.73,0.96,1.34,2.10,4.39),
  
  // where u(i) = i, v(i) = 16 - i, and w(i) = min(u(i),v(i)). The
  
  // i-th component of FVEC is thus defined by
  
  // y(i) - (x(1) + u(i)/(v(www.jmaguojiyL.com)*x(2) + w(i)*x(3))).
  
  void fcn(const int *m, const int *n, const real *x, real *fvec, int *iflag)
  
  {
  
  /* function fcn for lmdif1 example */
  
  int i;
  
  real tmp1,tmp2,tmp3;
  
  // 实际的y值
  
  real y[15]={1.4e-1,1.8e-1,2.2e-1,2.5e-1,2.9e-1,3.2e-1,3.5e-1,3.9e-1,
  
  3.7e-1,5.8e-1,7.3e-1,9.6e-1,1.34e0,2.1e0,4.39e0};
  
  assert(*m == 15 && *n == 3);
  
  if (*iflag == 0) {
  
  /* insert print statements here when nprint is positive. */
  
  /* if the nprint www.zbyL2019.com parameter to lmder is positive, the function is
  
  called every nprint iterations with iflag=www.chengsyl.cn 0, so that the
  
  function may perform special operations, such as printing
  
  residuals. */
  
  客户端层 -> 反向代理层的负载均衡如何实现呢?
  
  答案是:DNS 的轮询。 DNS 可以通过 A (Address,返回域名指向的 IP 地址)设置多个 IP 地址。比如这里访问 bysocket.com 的 DNS 配置了 ip1 和 ip2 。为了反向代理层的高可用,至少会有两条 A 记录。这样冗余的两个 ip 对应的 nginx 服务实例,防止单点故障。
  
  每次请求 bysocket.com 域名的时候,通过 DNS 轮询,返回对应的 ip 地址,每个 ip 对应的反向代理层的服务实例,也就是 nginx 的外网ip。这样可以做到每一个反向代理层实例得到的请求分配是均衡的。
  
  第 2 层:反向代理层 -> Web 层 的负载均衡
  
  反向代理层 -> Web 层 的负载均衡如何实现呢?
  
  是通过反向代理层的负载均衡模块处理。比如 nginx 有多种均衡方法:
  
  请求轮询。请求按时间顺序,逐一分配到 web 层服务,然后周而复始。如果 web 层服务 down 掉,自动剔除
  
  upstream web-server {
  
  server ip3;
  
  server ip4;
  
  }
  
  ip 哈希。按照 ip 的哈希值,确定路由到对应的 web 层。只要是用户的 ip 是均匀的,那么请求到 Web 层也是均匀的。 还有个好处就是同一个 ip 的请求会分发到相同的 web 层服务。这样每个用户固定访问一个 web 层服务,可以解决 session 的问题。
  
  upstream web-server {
  
  ip_hash;
  
  server ip3;
  
  server ip4;
  
  }
  
  weight 权重 、 fair、url_hash 等
  
  第 3 层:Web 层 -> 业务服务层 的负载均衡
  
  Web 层 -> 业务服务层 的负载均衡如何实现呢?
  
  比如 Dubbo 是一个服务治理方案,包括服务注册、服务降级、访问控制、动态配置路由规则、权重调节、负载均衡。其中一个特性就是智能负载均衡:内置多种负载均衡策略,智能感知下游节点健康状况,显著减少调用延迟,提高系统吞吐量。
  
  为了避免避免单点故障和支持服务的横向扩容,一个服务通常会部署多个实例,即 Dubbo 集群部署。会将多个服务实例成为一个服务提供方,然后根据配置的随机负载均衡策略,在20个 Provider 中随机选择了一个来调用,假设随机到了第7个 Provider。LoadBalance 组件从提供者地址列表中,使用均衡策略,选择选一个提供者进行调用,如果调用失败,再选另一台调用。
  
  Dubbo内置了4种负载均衡策略:
  
  RandomLoadBalance:随机负载均衡。随机的选择一个。是Dubbo的默认负载均衡策略。
  
  RoundRobinLoadBalance:轮询负载均衡。轮询选择一个。
  
  LeastActiveLoadBalance:最少活跃调用数,相同活跃数的随机。活跃数指调用前后计数差。使慢的 Provider 收到更少请求,因为越慢的 Provider 的调用前后计数差会越大。
  
  ConsistentHashLoadBalance:一致性哈希负载均衡。相同参数的请求总是落在同一台机器上。
  
  同样,因为业务的需要,也可以实现自己的负载均衡策略
  
  第 4 层:业务服务层 -> 数据存储层 的负载均衡
  
  数据存储层的负载均衡,一般通过 DBProxy 实现。比如 MySQL 分库分表。
  
  当单库或者单表访问太大,数据量太大的情况下,需要进行垂直拆分和水平拆分两个维度。比如水平切分规则:
  
  Range 、 时间
  
  hash 取模,订单根据店铺ID 等
  
  但伴随着这块的负载会出现下面的问题,需要解决:
  
  分布式事务
  
  跨库 join 等
  
  现状分库分表的产品方案很多:当当 sharding-jdbc、阿里的 Cobar 等
  
  五、小结
  
  对外看来,负载均衡是一个系统或软件的整体。对内看来,层层上下游调用。只要存在调用,就需要考虑负载均衡这个因素。所以负载均衡(Load Balance)是分布式系统架构设计中必须考虑的因素之一。考虑主要是如何让下游接收到的请求是均匀分布的:
  
  第 1 层:客户端层 -> 反向代理层 的负载均衡。通过 DNS 轮询
  
  第 2 层:反向代理层 -> Web 层 的负载均衡。通过 Nginx 的负载均衡模块
  
  第 3 层:Web 层 -> 业务服务层 的负载均衡。通过服务治理框架的负载均衡模块
  
  第 4 层:业务服务层 -> 数据存储层 的负载均衡。通过数据的水平分布,数据均匀了,理论上请求也会均匀。比如通过买家ID分片类似
  
  原创不易,争取多画图,图解胜千言(泥瓦匠@bysocket.com)

转载于:https://www.cnblogs.com/qwangxiao/p/11204060.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值