当前位置: 首页 > news >正文

试着探索高并发下的系统架构面貌

前言

以前端入行编码,但是对后端架构也非常感兴趣。一直以来都觉得那些做到在洪水流量面前保持系统提供高可靠,高性能的服务的小哥哥们都很厉害。总想着去学习一番,因此大半年来不断学习后端相关的知识,试图去理解高并发架构的面貌。

当然,本文仅仅是试着探索而已,并没有相关实践的经历,也只能从理论的角度去推演,从现有可参考的资料中去堆砌一个在我看来合理的架构方案。限于作者水平有限,因此难免行文难免有误,亦或是对整个系统的理解上理想化了,欢迎各位指出不足。同时,本文不会详实的阐述提到的每个细节,因为本身自己对细节的把控也不到位,另外也是希望大家能够在本文的基础上自己去详细了解这些技术。

图片描述

核心技术点

在作者看来,本文偏向于考虑如何做到高并发和高可用,因此一些性能优化的点则可能不作为重点言及,一是因为性能优化点过于繁多,会造成篇幅过长,另外也是因为具体的细节作者也未经实践不敢在这里细究。因此,列出以下这些在作者看来最为重要的核心技术点。

  1. 智能DNS解析调度

  2. 负载均衡

  3. 消息服务

  4. CDN配合对象存储服务

  5. Redis缓存

  6. 分库分表

通过横向叠加机器解决并发突增问题,这是的架构设计的一项最基本要求。

技术详解

智能DNS解析调度

在所有用户的都是通过同一域名www.qq.com获取服务的情况下,想要将流量分散到多个负载均衡节点,必须要依赖DNS的解析。

DNS解析最简单的可以通过添加多条A记录将域名映射到多个IP地址来达到分流的目的。看到许多资料,往往只提到这个层面,然后抛出了问题:调度算法简单,往往是动态轮询,而部署的机器之间可能会存在性能差异或者当下健康状况不同,简单的轮询并不能满足实际需求。
因此,经过一番搜索,发现了dnspod这样的第三方DNS解析服务提供设置权重,这样一来就可以针对机器的状况不同进行不同的权重配比。通过配比权重,基本上,就可以完成DNS解析的负载均衡了。

但是作者一直好奇,这些第三方的DNS解析厂商如何工作,因此在查阅资料之后,将原理总结如下:
在DNS解析中,我们购买域名后,可以设置对应域名的权威DNS解析服务器。以访问www.qq.com.为例,DNS解析首先会递归查找对应域名的IP地址。一直查找到根域.,根域让我们去问com.的权威服务器, 之后去问qq.com.的权威服务器,再问www.qq.com.的权威服务器,这时候我们终于找到了www.qq.com.的权威服务器ns-edu1.qq.com.ns-edu2.qq.com.,权威服务器经过一系列算法最后给了我们请求域名的IP地址。

DNS解析图

购买域名后,域名往往被默认的设置为平台默认的DNS解析服务器上,我们也可以对其进行更改,比如设置到dnspod,并自己在dnspod进行配置。对于一些大厂,也可以通过自行架设DNS解析服务器并编写自定义的规则进行处理来达到高度定制化的管控。常见的管控如下:

  • 通过识别用户是电信网还是联通网,将对应的网络内部署的服务器地址返回,以避免用户请求的跨网,跨网会带来一定的网络传输性能的下降

  • 识别用户归属地,分配到最近的服务器以减少网络传输的距离

最后需要注意的是DNS解析的更改的实时性存在很大的限制,因为各地ISP服务商刷新域名DNS的时间不一致,所以导致解析在全球生效一般需要0-72小时。

负载均衡

这里的负载均衡只特指负载均衡的节点。DNS解析后的IP地址即对应负载均衡的IP地址,请求到达负载均衡节点后,将由负载均衡节点对请求进行转发到相应的http应用处理服务器。负载均衡节点可以设置相应转发的策略,例如最简单通过将用户的ip来hash到不同的http应用服务器来分散压力,这样的好处是可以保证每次请求都打到同一台机器上。另外负载均衡节点也会监听应用服务器,并且及时隔离掉异常状态的服务器,在服务器恢复健康后,再次接入。

通过负载均衡节点接入多台应用服务器,当遇到促销等场景时,动态增加应用服务器即可满足需求。

此外,我们还需要确保负载均衡节点的高可用性。通过VRRP(Virtual Router Redundancy Protocol, 虚拟路由冗余协议)保证负载均衡节点的高可用性。原理如下:
负载均衡节点往往由2台机器通过VIP(virtual IP,负载均衡向客户端提供服务的 IP 地址)技术向用户提供服务,两台机器同时只有一台机器保持在active的状态,两台机器之间通过Keepalived技术互相监听对方的状态,如果active的机器宕机,则另一台机器自动切换到active的状态,通过冗余来保证负载均衡节点的高可用性。

消息服务

项目简单的时候,我们往往会把所有的代码耦合在一起,同步执行。诸如购买一件商品,执行下单,减库存,支付等等操作同步运行完成之后再将请求返回,造成单个请求驻留时间过长,堆积大量的请求,造成应用服务器的不可用。

通过消息服务,我们可以将这些服务解耦,并且通过将同步逻辑异步化,减少请求的驻留,从而减轻并发压力。用户操作产生消息,再通过建立另外的消费者进行消费。

我们还可以根据情况,设置消费者的策略,比如,通过拉取消息而非推送消息,来保证无论前端并发多大的流量,都可以在消息服务这里熨平,消费者根据自己的能力拉取,不至于超负荷造成服务不可用。

CDN配合对象存储服务

CDN这个技术基本上写代码的人都知道,说优化的时候大家都能提到,可是过往也一直没有真正的设置过CDN的使用,这次专门去腾讯云上查看了下配置,并了解了下策略。

首先,用户准备一个域名用来作为CDN的分发域名,这里比如说qian-img.tenpay.com。设置qian-img.tenpay.com的别名CNAME为CDN厂商给我们提供的域名比如说tenpay.com.CDN.dnsv1.com,之后还需要设置源站(ip/域名)即你静态文件实际存放的机器地址。这样对qian-img.tenpay.com的请求都会打到对应的CDN域名上,CDN域名也会解析到最近的CDN节点上,并且递归查找资源,类似于DNS解析。当没有找到资源的时候,才会去用户设置的源站IP上去获取资源。这样对自己的静态资源源站的性能要求会大大减少,系统性能也会大大提高。

而源站的资源管理上也推荐使用对象存储服务,相比与使用自己搭建服务器的文件系统。对象存储服务,也可以存储任意形式的非结构化的数据,并且高可用、高稳定、强安全。

Redis缓存

Redis是基于内存的键值对数据库,IO性能远远高于基于文件系统的数据库。对一个接口的请求的多个请求过程中,往往数据并没有产生变化,如果每次都去数据库中去查询,则会造成数据库压力过大,同时接口性能下降,通过将数据缓存在Redis这样的内存键值对数据库中可以大大提高系统的性能。

分库分表

常用的数据库诸如MySQL都是基于文件系统,而文件系统是基于磁盘,整个系统中,磁盘的IO可以说是最慢的一个地方。因此数据库往往是系统的性能瓶颈,分库分表,是最常用的策略。

单个数据库存在并发连接数上线单位是百,因此面对海量的请求,是无能为力的。因此需要通过分库来将压力分担到不同的数据库机器上,以承载高并发的请求。分库的策略可以简单的根据用户UID的尾号进行水平拆分,同时分库后,单个数据库的记录数也减少了,读写性能也得到提高。

写在最后

大半年前,在公司听后端童鞋讲解后端架构的时候,很多东西都是一脸懵逼,大半年里不断认知学习,认识上终于有不少进步。学无止境,需要去学习的还有很多~
行将毕业,7月入职,希望在未来工作中能够在Web这一块有更加深入的认识。

相关文章:

  • 深入理解Java内存模型(四)——volatile
  • 亲历服务器ARP攻击处理办法
  • docker 安装 Error response from daemon: Cannot start container no such file or directory
  • Ruby on rails开发从头来系列教程(附ruby电子书下载)
  • 测试计划模板
  • [转] Session简介
  • rocketmq 学习记录-2
  • 浅谈 Java 主流开源类库解析 XML
  • ASP.NET MVC - 旧形式URL的路由
  • v4l2 spec 中文 Ch01【转】
  • 在WinForm中使用Web Services 来实现 软件 自动升级(C#)
  • CISCO路由器license激活图解教程
  • [LeetCode] Wiggle Sort
  • ASP得到当前页面完整地址
  • Photoshop脚本 关闭所有已打开的文档
  • ➹使用webpack配置多页面应用(MPA)
  • CNN 在图像分割中的简史:从 R-CNN 到 Mask R-CNN
  • DataBase in Android
  • IndexedDB
  • LeetCode29.两数相除 JavaScript
  • Linux各目录及每个目录的详细介绍
  • python 学习笔记 - Queue Pipes,进程间通讯
  • 短视频宝贝=慢?阿里巴巴工程师这样秒开短视频
  • 利用jquery编写加法运算验证码
  • 如何选择开源的机器学习框架?
  • 消息队列系列二(IOT中消息队列的应用)
  • 小程序上传图片到七牛云(支持多张上传,预览,删除)
  • 学习笔记:对象,原型和继承(1)
  • 一文看透浏览器架构
  • 一些基于React、Vue、Node.js、MongoDB技术栈的实践项目
  • 异常机制详解
  • 在electron中实现跨域请求,无需更改服务器端设置
  • 【云吞铺子】性能抖动剖析(二)
  • JavaScript 新语法详解:Class 的私有属性与私有方法 ...
  • ​html.parser --- 简单的 HTML 和 XHTML 解析器​
  • (02)Hive SQL编译成MapReduce任务的过程
  • (ZT)出版业改革:该死的死,该生的生
  • (差分)胡桃爱原石
  • (第一天)包装对象、作用域、创建对象
  • (原創) 如何動態建立二維陣列(多維陣列)? (.NET) (C#)
  • (转)母版页和相对路径
  • ./configure,make,make install的作用
  • .net core使用RPC方式进行高效的HTTP服务访问
  • .NET Core中Emit的使用
  • .NET LINQ 通常分 Syntax Query 和Syntax Method
  • .NET 中小心嵌套等待的 Task,它可能会耗尽你线程池的现有资源,出现类似死锁的情况
  • .NET/C# 项目如何优雅地设置条件编译符号?
  • .Net的DataSet直接与SQL2005交互
  • .net访问oracle数据库性能问题
  • /dev下添加设备节点的方法步骤(通过device_create)
  • /etc/motd and /etc/issue
  • ?
  • @EnableWebMvc介绍和使用详细demo
  • @NoArgsConstructor和@AllArgsConstructor,@Builder
  • []error LNK2001: unresolved external symbol _m