大流量时代,如何规划系统流量提升可靠性

这篇具有很好参考价值的文章主要介绍了大流量时代,如何规划系统流量提升可靠性。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

摘要:本文主要是对《凤凰架构》的解读,讲述规划系统流量的几种方式。

本文分享自华为云社区《大流量时代,如何规划系统流量提升可靠性》,作者:breakDawn 。

透明多级分流系统

对系统流量进行规划, 要注意以下2个原则

  1. 尽可能减少单点部件, 或者减少到达单点部件的流量或者作用
  2. 奥卡姆剃刀原则,确定有再有必要的时候才去使用,避免过度设计

1 客户端缓存

即对于某些资源, 在客户端就做缓存,客户端不去重复请求。

1.1 强制缓存

类似HTTP协议里在header里用到的两种标签,且都是服务端强行控制的,基于时间的

  1. Expires
    服务端直接返回数据不会变动的截止时间。
    缺点:受限于客户端本地时间、无法表示不缓存除非强制改时间戳、无法表示是否是私有资源(避免私有资源被其他节点缓存)
  2. Cache-Control
    这个请求头使用max-age、private、no-cache等标签解决了Expires里的3个缺点。

1.2 协商缓存

协商缓存需要考虑是否真的发生变化。 协商和强制可以共同存在,即强制失效的时候就可以用上协商。
协商缓存不仅存在于地址输入、跳转,也存在F5中(但如果Ctrl+F5强制刷新则会让缓存失效)

  1. Last-Modified
    告诉客户端资源的最后修改时间, 客户端再次请求时也会对这个时间做修改
    如果服务端发现在那个时间之后资源未变动,返回304 Not Modified
    如果有变动,就返回OK,并携带完整的资源
  2. ETag
    需要对资源计算哈希值,客户端发请求也会带上自己存的ETag,每次会比对资源的哈希值是否一致,不一致则返回新资源。
    Etag是一致性最强的本地缓存机制,但也是性能最差的。

2 传输通道优化

本章节大部分以熟知的HTTP协议作为主要传输通道协议,讲解如何进行优化

2.1 连接数优化

HTTP是基于TCP的,每次都是重新建立一个TCP连接。 因此前端开发人员开发了很多小优化,来减少请求次数,例如雪碧图、分段文档、合并Ajax请求之类的。

HTTP1.0里的长连接(keep-alive连接复用)为什么不能解决这个问题?
因为存在队首阻塞问题,本质上是基于FIFO复用连接, 1个请求卡住了,后面9个请求都阻塞住了,但如果同时支持返回,在顺序混乱的情况下无法正常处理

HTTP2.0的多路复用解决了这个问题:

  • 以帧作为最小粒度单位,每个帧都携带流ID识别是哪个流
  • 客户端可以很容易在不同流中重组HTTP请求和响应报文

2.2 传输压缩

HTTP很早就支持GZip压缩来减少大资源的传输量

HTTP1.0中, 持久连接和传输压缩无法一起使用, 因为压缩后无法识别资源是否传输完毕。

HTTP1.1中引入了“分块传输编码”,来进行资源结束的判断。

2.3 用UDP来加快网络传输

HTTP/3中,希望能替换掉HTTP on TCP的依赖、
谷歌推出了快速UDP网络连接, 即QUIC

  • QUIC以UDP为基础, 可靠传输能力由自己实现
  • QUIC专门面向移动设备支持, 移动设备的ip地址经常会切换,使用ip作为定位不合适, 因此提出了连接标识符来保持连接。
  • 对于不支持QUIC的情况,支持回退为TCP连接,实现兼容

3 内容分发网络CDN

CND可以解决 互联网系统跨运营商、跨地域物理距离所导致的时延问题,为网站流量带宽起到分流、减负的作用。
主要包含以下4个工作部分

3.1 路由解析

用户的静态资源请求访问CDN是通过DNS解析来完成的,甚至可能一个网站会有各种不同地域的CDN域名解析地址返回, 通过你的路由配置会自动选择符合地域的ip地址

3.2 内容分发

如何分发内容有两种方式:

  1. 主动分发, 通过CND服务商提供的接口主动推送自己的资源,这样你需要额外编写资源推动的代码。大型活动例如双11会优先考虑主动分发预先准备资源。
  2. 被动回源, 由用户访问触发,当发现没有资源时,CDN会去源站请求并返回,则用你不需要新写相关代码,只要在CDN那边支持回源你的源站即可。小型站点基本都是用这个方法。

如何更新资源有两种方式:

  1. 超时被动失效,CDN的资源都有有效期,超时了就回源获取
  2. 手工主动失效, CDN服务商提供缓存失效接口,主动触发失效并进行被动回源更新。
    现在一般是1和2结合使用,二者不冲突

4 负载均衡

负载均衡有两种大类

  • 四层负载均衡
    指的是计算机七层模型中四层及以下的均衡策略结合
    即 数据链路层 + 网络层 均可做均衡
  • 七层负载均衡
    指的是在应用层通过实际代码做均衡

4.1 数据链路层负载均衡(四层负载均衡)

  • 通过链路层上的均衡器替换MAC地址,进行链路层的均衡
  • 各负载节点的IP是一样的(相同的虚拟IP)
  • 返回时无需经过均衡器,直接返回即可(因为目标ip、源ip基本没变)

缺点:
必须是同一个子网内,无法跨VLAN,只能作为最接近数据中心的均衡器

4.2 网络层负载均衡(四层负载均衡)

有两种方式:

IP隧道模式

均衡器在IP报文外面包了一层新的header,header里指定了目标机器的实际ip或者小网ip。 接收机器要支持解header,且同样要求作为返回的虚拟ip是一致的,也是直接返回无需经过均衡器。
缺点:

  1. 用到的服务器都要支持隧道解包能力(linux系统现在都支持)
  2. 虚拟ip仍然有较大限制,需要人工介入管理众多机器

NAT模式

NAT模式中,就是进行真正的ip转换, 且返回时也要返回给NAT进行ip转换,这样只需要针对NAT进行人工管理即可。
缺点在于NAT容易成功性能瓶颈

SNAT会修改源IP改为NAT的ip, 可以做到对业务真正透明, 但是代价是如果需要对源IP做限制时容易有问题, 因为所有的来源ip都是一样的了。

4.3 应用层负载均衡(七层负载均衡)

也叫做七层代理(应用层代理),因为这个负载均衡属于反向代理(即部署在服务端的代理,对客户端不感知)

不适合做下载站、视频站等流量应用
如果瓶颈在服务计算能力,则可以考虑做应用层均衡

七层代理除负载均衡外的其他功能:

  • 支持做CDN类似的缓存能力
  • 施行智能化路由,根据URL或者特定用户做特殊服务
  • 抵御安全工具,提前过滤攻击报文
  • 链路治理

4.4 负载均衡策略

  • 轮询均衡
    轮流分配,从1到N再到1
    适用于所有服务器硬件配置完全相同,服务请求需要相对均衡
  • 权重轮询
    根据服务器权重分配周期内的轮询次数
  • 随机均衡
    适用于数据量足够大的相对均衡分布
  • 权重随机均衡
    提升权重高的随机率
  • 一致性哈希均衡
    适用于服务器经常可能掉线或者加入,可以避免哈希键全部更新的情况
  • 响应速度均衡
    定期探测各个服务器的响应速度,根据速度分配权重
  • 最少连接数均衡
    根据连接数分配权重, 适用于长时处理服务例如FTP等
  • 软件均衡器包括基于操作系统内核的LVS、 基于应用程序的Nginx、KeepAlive、HAProxy
  • 硬件均衡器包括F5、A10等公司提供的硬件负载均衡产品

5 服务端缓存

引入缓存的理由:

  • 减缓CPU计算压力
  • 缓存IO压力
    这2个缓解只是能峰值时的压力缓解,如果普通的响应都很慢,那就算用了缓存也意义不大。

5.1 缓存的几个属性

缓存需要选型,选型时需要根据实际场景选择你匹配的缓存熟悉

吞吐量

JDK8改进后的ConcurrentHashMap是并发场景下吞吐量最高的缓存容器,但除了吞吐量其他的能力就很弱了。

缓存状态更新思路:

  • GuavaCache: 同步处理机制,在访问数据时一并更新,分段加锁减少竞争
  • Caffeine:异步日志提交机制,参考数据库日志,并且还有环形缓冲区容忍有损失的状态变更,读性能非常快, 使用多读少写的情况。

命中率和淘汰策略

基础的三种淘汰方案:

  • FIFO:先进先出,简单实现,但对于高频访问的缓存命中率低,越常用到越可能先进入队列
  • LRU:优先淘汰最久未被访问,基于时间, 用HashMap+链表List实现,但每个缓存都要记录时间,且可能淘汰短期内正好没访问且价值高的数据
  • LFU:优先淘汰最不频繁使用,基于使用次数,可以解决LRU的缺点。
    自身缺点:
  1. 每个缓存专门维护要更新次数的计数器,维护开销大还有加锁问题(LRU的更新时间不需要考虑加锁,直接覆盖最新即可)
  2. 如果某个缓存某时期访问很高,比其他缓存高了一个数量级,后面不再使用,想淘汰很困难

为了解决上面2个缺点,有2个新的策略:

  • TinyLFU: 解决修改计数器的开销问题, 采用Sketch分析访问数据,用少量数据估计全体数据特征,采用滑动时间窗、热度衰减等处理
  • W-Tinfy-LFU: 结合了LRU+LFU的特点, 考虑热度和时间。

分布式能力

分布式缓存介绍了复制式缓存JbossCache以及集中式缓存Memcached。

jbosscache的缺点在于写入性能太差,容易因为网络同步速度跟不上写入速度,导致内存中积累过多待发对象引发omm

memcached是C语言实现的,好处在于读写性能高,缺点在于数据结构太过紧密,非常依赖序列化做跨语言传输,如果100个字段中的1个字段发生更新,要把100个字段都发出去更新

redis基本打败了各种分布式缓存,成为首选。

对于redis等分布式缓存, 是不会追求一致性C的
如果一定要一致性C, 那应该选用zk或者etcd等分布式协调框架(但他们一般就不会拿来做缓存,因为高并发下吞吐量太低,没有可用性)

进程内缓存和分布式缓存通常结合使用,但容易出现二者数据不一致,写维护策略导致缓存对开发者而言不透明。
一种设置原则是 变更以分布式缓存中的数据为主,访问以进程内缓存的数据优先。
大致做法是数据发生变动时, 在分布式缓存内推送通知, 让一级缓存失效。
访问缓存时,提供封装好的一二级联合查询接口, 让开发者对一二级缓存不感知。

5.2 缓存风险

缓存穿透

大量不存在的缓存打进来
要么是支持对不存在的数据缓存空值
要么是引入布隆过滤器

缓存击穿

同一时间瞬间涌现很多请求,访问数据库有但是缓存里没有的数据,此时可能直接打穿数据库(缓存生效是有延迟的)
可以是用锁、队列来完成同步
对于热点缓存,提前预处理或者配置策略

 

点击关注,第一时间了解华为云新鲜技术~文章来源地址https://www.toymoban.com/news/detail-428068.html

到了这里,关于大流量时代,如何规划系统流量提升可靠性的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • TCP如何保证可靠性,TCP如何实现可靠性传输的

    tcp 如何保证可靠性 大家都知道TCP是可靠性传输协议,既然是可靠的,就需要解决比如包丢失了、数据被破坏了、包重复了、乱序了等等这样的问题。下面将从几个方面介绍TCP的可靠性。 1. 校验和 TCP每一段报文都有校验和,这保证了报文不被破坏或篡改,如果收到的报文在校

    2024年02月10日
    浏览(50)
  • 精通中间件测试:Asp.Net Core实战指南,提升应用稳定性和可靠性

    在上一章节我们实战了在 Asp.Net Core 中的项目实战,这一章节讲解一下如何测试 Asp.Net Core 的中间件。 还记得我们在集成测试中提供的 TestServer 吗? TestServer 是由 Microsoft.AspNetCore.TestHost 包提供的。包含了用于在测试环境中模拟 ASP.NET Core 应用程序的类和方法。通过使用 TestSe

    2024年04月22日
    浏览(49)
  • [rocketmq] 如何保证消息可靠性

    1、生产者发送消息到Broker时; 2、Broker内部存储消息到磁盘以及主从复制同步时; 3、Broker把消息推送给消费者或者消费者主动拉取消息时; 1.重试策略,发送消息失败后会进行一定的重试策略 重试机制:固定重试次数,同步刷盘会切换 broker 重试,异步刷盘会在同一 broker

    2024年02月11日
    浏览(45)
  • RabbitMQ如何保证消息可靠性

    目录 1、RabbitMQ消息丢失的可能性 1.1 生产者消息丢失场景 1.2 MQ导致消息丢失 1.3 消费者丢失 2、如何保证生产者消息的可靠性 2.1 生产者重试机制 2.2 生产者确认机制 2.3 实现生产者确认 2.3.1 配置yml开启生产者确认 2.3.2 定义ReturnCallback 2.3.3 定义ConfirmCallback 3、MQ消息可靠性 3.1

    2024年02月20日
    浏览(57)
  • TCP如何保证传输可靠性?

    文章参考: 《网络是怎样连接的》:https://book.douban.com/subject/26941639/ 《图解网络》:https://www.xiaolincoding.com/network/ 在开始阅读该博客之前,先要好好了解一下 TCP报文头部 到底有那些信息,阅读后续内容时有任何模糊的地方都可以回来这里 查看梳理 ,接下来我来解释一下:

    2024年02月20日
    浏览(49)
  • 如何保证消息的可靠性(面试题)

    面试题 :Rebbitmq怎么保证消息的可靠性 消费者在接收到消息后,默认情况下RabbitMQ会自动确认消息(autoAck=true)。为保证消息可靠性,可以设置autoAck=false,使得消费者在处理完消息后手动发送确认(basicAck)。如果消费者在处理过程中发生异常或者未完成处理就终止运行,那

    2024年04月14日
    浏览(48)
  • 如何保证 RabbitMQ 的消息可靠性?

    项目开发中经常会使用消息队列来 完成异步处理、应用解耦、流量控制等功能 。虽然消息队列的出现解决了一些场景下的问题,但是同时也引出了一些问题,其中使用消息队列时如何保证消息的可靠性就是一个常见的问题。 如果在项目中遇到需要保证消息一定被消费的场景

    2024年02月07日
    浏览(49)
  • rabbitmq如何保证消息的可靠性

    RabbitMQ可以通过以下方式来保证消息的可靠性: 在发布消息时,可以设置消息的delivery mode为2,这样消息会被持久化存储在磁盘上,即使RabbitMQ服务器重启,消息也不会丢失。 可以创建持久化的队列,这样即使RabbitMQ服务器重启,队列也不会丢失。 在消费者端,可以 设置手动

    2024年01月23日
    浏览(54)
  • TCP如何保证服务的可靠性

    TCP保证可靠性一般有以下几种方法: (1) 确认应答 :ACK和序列号 (2) 超时重传 :发送数据包在一定的时间周期内没有收到相应的ACK,等待一定的时间,超时之后就认为这个数据包丢失,就会重新发送 (3) 流量控制 :控制发送方发送窗口的大小来实现流量控制 (4) 拥

    2024年02月15日
    浏览(41)
  • TCP如何保证传输的可靠性

    TCP采用哪些方式保证数据传输可靠? 答: 1、数据分块:将数据包划分为合适的大小,这样更能适应网络的限制,如果数据发生错误或丢失,只要重传有问题的部分即可,减少重传的数据量。方便进行流量和拥塞控制。 2、数据包有序号,可以根据序号对失序的数据包进行重

    2024年04月11日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包