分布式架构下的高可用设计

写在前面:

  • 你好,欢迎你的阅读!
  • 我热爱技术,热爱分享,热爱生活, 我始终相信:技术是开源的,知识是共享的!
  • 博客里面的内容大部分均为原创,是自己日常的学习记录和总结,便于自己在后面的时间里回顾,当然也是希望可以分享自己的知识。目前的内容几乎是基础知识和技术入门,如果你觉得还可以的话不妨关注一下,我们共同进步!
  • 除了分享博客之外,也喜欢看书,写一点日常杂文和心情分享,如果你感兴趣,也可以关注关注!
  • 微信公众号:傲骄鹿先生
     

避免单点故障:

  • 负载均衡技术(failover/选址/硬件负载/ 软件负载/去中心化的软件负载(gossip(redis- cluster)))

  • 热备(Linux HA)

  • 多机房(同城灾备、异地灾备)

应用的高可用性:

  • 故障监控(系统监控(CPU、内存)/链路监控/日志监控) 自动预警

  • 应用的容错设计、(服务降级、限流)自我保护能力

  • 数据量(数据分片、读写分离)

分布式架构下的可伸缩设计:

  • 垂直伸缩

  • 提升硬件能力

  • 水平伸缩

  • 增加服务器

加速静态内容访问速度的 CDN

CDN 全称是 Content Delivery Network,中文释义是内容分发网络。

CDN 的作用是把用户需要的内容分发到离用户最近的地方进行响应,这样用户能够快速获取所需要的内容。

CDN 本质上就是一种网络缓存技术,能够把一些相对稳定的资源放到距离最终用户较近的地方,一方面可以节省整个广域网的带宽消耗,另外一方面也可以提升用户的访问速度、改善用户体验。

 

现实系统中我们一般会把静态的文件(图片、脚本、静态页面等)放到 CDN 中:

  • 当用户访问网站页面上的内容 URL,经过本地 DNS 系统解析,DNS 系统最终会将域名的解析权交给 CNAME 指向的 CDN 专用 DNS 服务器。

  • CDN 的 DNS 服务器将 CDN 的全局负载均衡设备 IP 地址返回用户。

  • 用户向 CDN 的全局负载均衡设备发起内容 URL 访问请求。

  • CDN 全局负载均衡设备根据用户 IP 地址,以及用户请求的内容 URL, 选择一台用户所属区域的区域负载均衡设备,告诉用户向这台设备发起请求。

  • 区域负载均衡设备会为用户选择一台合适的缓存服务器提供服务。选择的依据包括:根据用户 IP 地址,判断哪一台服务器距离用户最近。

根据用户所请求的 URL 中携带的内容名称,判断哪一台服务器上有用户所需内容;查询各个服务器当前的负载情况,判断哪一台服务器上有服务能力。

  • 基于以上条件的综合分析之后,区域负载均衡设备会向全局负载均衡设备返回一台缓存服务器的 IP 地址。

  • 全局负载均衡设备把服务器的 IP 地址返回给用户。用户向缓存服务器发起请求,缓存服务器响应用户请求,将用户所需内容返回到用户终端。

如果这台缓存服务器上并没有用户想要的内容,而区域均衡设备依然将它分配给了用户,那么这台服务器就要向它的上一级缓存服务器请求内容,直到追溯到包含该内容的源服务器并将内容拉到本地。

什么情况下用 CDN?

最适合的是那些不会经常变化的内容,比如图片,JS 文件,CSS 文件。图片文件包括程序模板中 CSS 文件中用到的背景图片,还有就是作为网站内容组成部分的那些图片等等。

灰度发布

我们的应用即使经过了测试部门的测试,也仍然很难全面覆盖用户的使用场景。为了保证万无一失,我们在进行发布的时候一般都会采用灰度发布,也就是会对新应用进行分批发布,逐步扩大新应用在整个及集群中的比例直到最后全部完成。灰度发布是说针对新应用在用户体验方面完全无感知。

灰度发布系统的作用在于,可以根据自己的配置,来将用户的流量导到新上线的系统上,来快速验证新的功能。

而一旦出问题,也可以马上的回滚发布,简单的说,就是一套 A/B Test 系统:

如何实现高可用?

入口层

入口层,通常指Nginx和Apache等层面的东西,负责应用(不管是Web应用还是移动应用)的服务入口。我们通常会将服务定位在一个IP,如果这个IP对应的服务器当机了,那么用户的访问肯定会中断。此时,可以用keepalived来实现入口层的高可用。例如,机器A 的IP是 1.2.3.4,机器 B 的 IP 是 1.2.3.5, 那么再申请一个 IP 1.2.3.6(称为⼼跳IP), 平时绑定在机器A上,如果A当机,IP会自动绑定在机器B上;如果B当机,IP会自动绑定在机器A上。对于这种形式,我们将DNS绑定到心跳IP上,即可实现入口层的高可用。

但这个方案有一点小问题。第一,它的切换可能会有一到两秒的中断,也就是说,如果不是要求到非常严格的毫秒级就不会有问题。第二,对入口的机器会有些浪费,因为买了两台机器的入口,可能就只有一台机器用上。对一些长连接的应用可能会导致服务中断,这时候就需要客户端做配合做一些重新创建连接的工作。简单来说,对于比较普通的业务来说,这个方案就能解决一部分问题。

  这里要注意,keepalived在使用上会有一些限制。

  • 两台机器必须在同一个网段,不是在同一个网段,没有办法实现互相抢IP。

  • 内网服务也可以做心跳,但需要注意的是,以前为了安全我们会把内网服务绑定在内网IP上,避免出现安全问题。但为了使用keepalived,必须监听在所有IP上(如果监听在心跳IP上,那么机器没有持有该IP时,服务无法启动),简单的方案是启用 iptables, 避免内网服务被外网访问。

  • 服务器利用率下降,这时可以考虑做混合部署来改善这一点。

  比较常见的一个错误是,如果有两台机器,两个公网IP,DNS上把域名同时定位到两个IP,就觉得已经做了高可用了。这完全不是高可用,因为如果一台机器当机,那么就有一半左右的用户无法访问。

  除了keepalive,lvs也能用来解决入口层的高可用问题。不过,与keepalived相比,lvs会更复杂一些,门槛也会高一些。

业务层

  业务层通常是由PHP、Java、Python、Go等写的逻辑代码构成的,需要依赖于后台数据库及一些缓存层面的东西。如何实现业务层的高可用呢?最核心的就是,业务层不要有状态,将状态分散到缓存层和数据库。目前大家通常喜欢将以下几种数据放入业务层。

  第一个是session,即用户登录相关的数据,但好的做法是将session放在数据库里,或者一个比较稳定的缓存系统中。

  第二个是缓存,在访问数据库时,如果一个查询很慢,就希望将这些结果暂时放到进程里,下次再做查询时就不用再访问数据库了。这种做法带来的问题是,当业务层服务器不只一台时,数据很难做到一致,从缓存拿到的数据就可能是错误的。。

  一个简单的原则就是业务层不要有状态。在业务层没有状态时,一台业务层服务器当掉了之后,Nginx/Apache会自动将所有的请求打到另外一台业务层的服务器上。由于没有状态,两台服务器没有任何差异,所以用户完全感受不到。如果把session放在业务层里面的话,那么面临的问题是,这个用户以前是登录在一台机器上的,这个进程死掉后,用户就会被登出了。

  友情提醒:有一段时间比较流行cookie session,就是将session中的数据加密之后放在客户的cookie里,然后下发到客户端,这样也能做到与服务端完全无状态。但这里面有很多坑,如果能绕过这些坑就可以这样使用。第一个坑是怎么保证加密的密钥不泄露,一旦泄露就意味着攻击者可以伪造任何人的身份。第二个坑是重放攻击,如何避免别人通过保存 cookie 去不停地尝试的验证码,当然也还有其他一些攻击手段。如果没有好办法解决这两方面的问题,那么cookie session尽量慎用。最好是将session放在一个性能比较好的数据库中。如果数据库性能不行,那么将session放在缓存中也比放在cookie里要好一点。

缓存层

  非常简单的架构里是没有缓存这个概念的。但在访问量上来之后,MySQL之类的数据库扛不住了,比如在SATA盘里跑MySQL,QPS到达200、300甚至500时,MySQL的性能会大幅下降,这时就可以考虑用缓存层来挡住绝大部分服务请求,提升系统整体的容量。

  缓存层做高可用一个简单的方法就是,将缓存层分得细一点儿。比如说,缓存层就一台机器的话,那么这台机器当了以后,所有应用层的压力就会往数据库里压,数据库扛不住的话,整个网站(或应用)就会随之当掉。而如果缓存层分在四台机器上的话,每台只有四分之一,这台机器当掉了以后,也只有总访问量的四分之一会压在数据库上面,数据库能扛住的话,网站就能很稳定地等到缓存层重新起来。在实践中,四分之一显然是不够的,我们会将它分得更细,以保证单台缓存当机后数据库还能撑得住即可。在中小规模下,缓存层和业务层可以混合部署,这样可以节省机器。

数据库层

  在数据库层面实现高可用,通常是在软件层面来做。例如,MySQL有主从模式(Master-Slave),还有主主模式(Master-Master)都能满足需求。MongoDB也有ReplicaSet的概念,基本都能满足大家的需求。

  总之,要想实现高可用,需要做到这几点:入口层做心跳,业务层服务器无状态,缓存层减小粒度,数据库做一个主从模式。对于这种模式来讲,我们做的高可用不需要太多服务器,这些东西都可以同时部署在两台服务器上。这时,两台服务器就能满足早期的高可用需求了。任何一台服务器当机用户完全无感知。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值