目录

SpringCloud_Alibaba

微服务入门—微服务架构的前世今生

此文转载自哈喽沃德先生,处于小白学习阶段,手打去感悟理解,加入自己的理解,在此感谢大佬。

互联网发展史

Web1.0

 用户只能搜索和阅读网络信息。比如中国的几大门户网站:搜狐、新浪、网易、腾讯,平台提供内容和数据,用户被动接受,和用户缺乏交互。

Web2.0

​ 用户能够创造内容,并分享在网路平台上跟大家进行互动,而不再只是单纯的访问者;这种范式的发展重新定义了市场和商业模式。比如QQ、天涯、微博、淘宝、美团、滴滴,提供一个平台,用户你们自己玩。用户需要注册,用户和平台交互变得很强,用户和用户之间可以交流,数据几乎由用户产生。

Web3.0

​  网络在接受信息的同时,通过数据分析,能够根据用户的喜好产生出新的数据和信息并推送给用户。比如网易云音乐的推荐,搜索引擎的推荐,淘宝的商品推荐,地图应用的出行规划,堵车预测等等。其特征是使用 web 2.0 时代所产生的大量数据,更加精准、实时和深入的为用户提供服务。一个简单的例子:当你在淘宝上买了某件商品后,订单下方会出现很多类似商品推送

总结

比如:你家楼下餐馆代表互联网,你饰演互联网用户。

  • WEB1.0时代:你晚上一进餐馆,老板给你上了一桌子菜,说兄弟都是你的吃吧!(不分析)你自己挨个尝试,因为你不知道哪个菜好吃。(缺乏交互)
  • WEB2.0时代:你晚上一进餐馆,你说:老板来斤饺子。老板说:没有饺子有面条。你说来碗面条,老板给你上了一碗面条。(被动分析)或者,你不知道吃什么好,但是坐在你旁边的食客会告诉你哪个好吃。(用户交互)
  • WEB3.0时代:你晚上一进餐馆,一进门老板就说:客官,来碗面条吧!你问为啥,老板说,你连续吃一礼拜面条了。(主动分析)WEB 3.0 是微服务、大数据、云计算、人工智能的时代。

技术架构演变

随着网站应用的规模扩大,系统架构随之演进:单体应用架构—>垂直应用架构—>分布式架构—>SOA架构—>微服务架构,还有悄然兴起的Service Mesh(服务网格化)

单体应用架构

通俗地讲,“单体应用(monolith application)”就是将应用程序的所有功能都打包成一个独立的单元。当网站流量很小时,只需一个应用,将所有功能都部署在一起,以减少部署节点和成本。

初期单体架构

在互联网应用初期,互联网用户数相对都较少,可以把web服务器(例如Tomcat)和数据库部署在同一台服务器上。浏览器往www.taobao.com发起请求时,首先经过DNS服务器(域名系统)把域名转换为实际IP地址10.102.4.1,浏览器转而访问该IP对应的Tomcat。

https://gitee.com/cao-lianjie/pic-go/raw/master/img/20210726162249.png

IP与端口
  • IP为网络中计算机的唯一标识,端口为计算机上某个应用的唯一标识,对应系统中的唯一进程

  • 进程间通过不同协议进行通信,浏览器与Tomocat间通讯的协议为http协议;Tomcat与数据库间通讯的协议为TCP协议; 两者都是面向连接的协议,需要先建立连接才能通讯

  • UDP协议是一种无连接协议,简单理解为只做输出,不管接收端是否输入

注意
在单体架构下,随着用户数的增长,Tomcat和数据库之间竞争资源,单机性能不足以支撑业务. 存储资源与系统可用性不足
思考
  1. 从浏览器输入一个url到数据加载完成整个过程发生了什么?

  2. 浏览器与tomcat进行通讯使用的什么协议,这个协议有什么特点?

  3. Tomcat如何并发处理多个客户端的请求?

  4. Tomcat中的应用是如何访问数据数据库的?

  5. ……..

水平应用架构发展

Web服务与数据库分离

https://gitee.com/cao-lianjie/pic-go/raw/master/img/%E5%8D%95%E4%BD%93%E5%BA%94%E7%94%A8%E6%9E%B6%E6%9E%84.png

特点
  • 所有的功能集成在一个项目工程中;
  • 所有的功能打一个 war 包部署到服务器;
  • 应用与数据库分开部署;
  • 通过部署应用集群和数据库集群来提高系统的性能。
优点
  • 开发简单:一个 IDE 就可以快速构建单体应用;
  • 便于共享:单个归档文件包含所有功能,便于在团队之间以及不同的部署阶段之间共享;
  • 易于测试:单体应用一旦部署,所有的服务或特性就都可以使用了,这简化了测试过程,因为没有额外的依赖,每项测试都可以在部署完成后立刻开始;
  • 容易部署:整个项目就一个 war 包,Tomcat 安装好之后,应用扔上去就行了。群化部署也很容易,多个 Tomcat + 一个 Nginx 分分钟搞定。
缺点
  • 妨碍持续交付:随着时间的推移,单体应用可能会变得比较大,构建和部署时间也相应地延长,不利于频繁部署,阻碍持续交付。在移动应用开发中,这个问题会显得尤为严重;
  • 不够灵活:随着项目的逐渐变大,整个开发流程的时间也会变得很长,即使在仅仅更改了一行代码的情况下,软件开发人员需要花费几十分钟甚至超过一个小时的时间对所有代码进行编译,并接下来花费大量的时间重新部署刚刚生成的产品,以验证自己的更改是否正确。如果多个开发人员共同开发一个应用程序,那么还要等待其他开发人员完成了各自的开发。这降低了团队的灵活性和功能交付频率;
  • 受技术栈限制:项目变得越来越大的同时,我们的应用所使用的技术也会变得越来越多。这些技术有些是不兼容的,就比如在一个项目中大范围地混合使用 C++ 和 Java 几乎是不可能的事情。在这种情况下,我们就需要抛弃对某些不兼容技术的使用,而选择一种不是那么适合的技术来实现特定的功能。
  • 可靠性差:某个环节出现了死循环,导致内存溢出,会影响整个项目挂掉。
  • 伸缩性差:系统的扩容只能针对应用进行扩容,不能做到对某个功能进行扩容,扩容后必然带来资源浪费的问题。
  • 技术债务:假设我的代码库中有一个混乱的模块结构。此时,我需要添加一个新功能。如果这个模块结构清晰,可能我只需要2天时间就可以添加好这个功能,但是如今这个模块的结构很混乱,所以我需要4天时间。多出来的这两天就是债务利息。随着时间推移、人员变动,技术债务必然也会随之增多。
注意
本次演进过程中,随着用户数的增长,并发读写数据库成为瓶颈

本地缓存和分布式缓存

在Tomcat同服务器上或同JVM中增加本地缓存,并在外部增加分布式缓存,缓存热门商品信息或热门商品的html页面等。通过缓存能把绝大多数请求在读写数据库前拦截掉,大大降低数据库压力。如图所示:

https://gitee.com/cao-lianjie/pic-go/raw/master/img/20210726163627.png

​ 其中涉及的技术包括:基于memcached作为本地缓存,使用Redis作为分布式缓存,还会涉及缓存一致性、缓存穿透/击穿、缓存雪崩、热点数据集中失效等问题。

注意
​ 缓存虽然抗住了大部分的访问请求,但随着用户数的增长,并发压力主要落在单机的Tomcat上,响应逐渐变慢。

反向代理与负载均衡设计

​ 在多台服务器上分别部署Tomcat,使用反向代理软件(Nginx)把请求均匀分发到每个Tomcat中。此处假设Tomcat最多支持100个并发,Nginx最多支持50000个并发,那么理论上Nginx把请求分发到500个Tomcat上,就能抗住50000个并发。其中涉及的技术包括:Nginx、HAProxy,如图所示:

https://gitee.com/cao-lianjie/pic-go/raw/master/img/20210726164708.png

注意
反向代理使应用服务器可支持的并发量大大增加,但并发量的增长也意味着更多请求穿透到数据库,单机的数据库最终成为瓶颈。

数据库读写分离设计

把数据库划分为读库和写库,读库可以有多个,通过同步机制把写库的数据同步到读库,对于需要查询最新写入数据场景,可通过在缓存中多写一份,通过缓存获得最新数据。如图所示:

https://gitee.com/cao-lianjie/pic-go/raw/master/img/20210726164913.png

其中涉及的技术包括:Mycat,它是数据库中间件,可通过它来组织数据库的分离读写和分库分表,客户端通过它来访问下层数据库,还会涉及数据同步,数据一致性的问题。

注意
业务逐渐变多,不同业务之间的访问量差距较大,不同业务直接竞争数据库,相互影响性能。

数据库按业务进行分库

把不同业务的数据保存到不同的数据库中,使业务之间的资源竞争降低,对于访问量大的业务,可以部署更多的服务器来支撑。

https://gitee.com/cao-lianjie/pic-go/raw/master/img/20210726172223.png

这样同时导致跨业务的表无法直接做关联分析,需要通过其他途径来解决,但这不是本文讨论的重点,有兴趣的可以自行搜索解决方案。

注意
对于这种方案,随着用户数的增长,单机的写库会逐渐会达到性能瓶颈。

大表拆分为小表

​ 比如针对评论数据,可按照商品ID进行hash,路由到对应的表中存储;针对支付记录,可按照小时创建表,每个小时表继续拆分为小表,使用用户ID或记录编号来路由数据。只要实时操作的表数据量足够小,请求能够足够均匀的分发到多台服务器上的小表,那数据库就能通过水平扩展的方式来提高性能。其中前面提到的Mycat也支持在大表拆分为小表情况下的访问控制。

https://gitee.com/cao-lianjie/pic-go/raw/master/img/20210726172551.png

​ 这种做法显著的增加了数据库运维的难度,对DBA的要求较高。数据库设计到这种结构时,已经可以称为分布式数据库,但是这只是一个逻辑的数据库整体,数据库里不同的组成部分是由不同的组件单独来实现的,如分库分表的管理和请求分发,由Mycat实现,SQL的解析由单机的数据库实现,读写分离可能由网关和消息队列来实现,查询结果的汇总可能由数据库接口层来实现等等,这种架构其实是MPP(大架构的一类实现规模并行处理)。

注意
数据库和Tomcat都能够水平扩展,可支撑的并发大幅提高,随着用户数的增长,最终单机的Nginx会成为瓶颈。

LVS或F5让多个Nginx负载均衡

由于瓶颈在Nginx,因此无法通过两层的Nginx来实现多个Nginx的负载均衡。此时采用LVS和F5作为网络负载均衡解决方案,如图所示:

https://gitee.com/cao-lianjie/pic-go/raw/master/img/20210726174817.png

​ 其中LVS是软件,运行在操作系统内核态,可对TCP请求或更高层级的网络协议进行转发,因此支持的协议更丰富,并且性能也远高于Nginx,可假设单机的LVS可支持几十万个并发的请求转发;F5是一种负载均衡硬件,与LVS提供的能力类似,性能比LVS更高,但价格昂贵。由于LVS是单机版的软件,若LVS所在服务器宕机则会导致整个后端系统都无法访问,因此需要有备用节点。可使用keepalived软件模拟出虚拟IP,然后把虚拟IP绑定到多台LVS服务器上,浏览器访问虚拟IP时,会被路由器重定向到真实的LVS服务器,当主LVS服务器宕机时,keepalived软件会自动更新路由器中的路由表,把虚拟IP重定向到另外一台正常的LVS服务器,从而达到LVS服务器高可用的效果。

注意
此种方案中,由于LVS也是单机的,随着并发数增长到几十万时,LVS服务器最终会达到瓶颈,此时用户数达到千万甚至上亿级别,用户分布在不同的地区,与服务器机房距离不同,导致了访问的延迟会明显不同。

DNS轮询实现机房的负载均衡

​ 在DNS服务器中可配置一个域名对应多个IP地址,每个IP地址对应到不同的机房里的虚拟IP。当用户访问www.taobao.com时,DNS服务器会使用轮询策略或其他策略,来选择某个IP供用户访问。此方式能实现机房间的负载均衡,至此,系统可做到机房级别的水平扩展,千万级到亿级的并发量都可通过增加机房来解决,系统入口处的请求并发量不再是问题。

https://gitee.com/cao-lianjie/pic-go/raw/master/img/20210726175007.png

注意
随着数据的丰富程度和业务的发展,检索、分析等需求越来越丰富,单单依靠数据库无法解决如此丰富的需求

垂直应用架构发展

https://gitee.com/cao-lianjie/pic-go/raw/master/img/20210726164410.png

当访问量逐渐增大,单一应用增加机器带来的加速度越来越小,将应用拆成互不相干的几个应用,以提升效率。

大应用拆分成小应用

​ 按照业务板块来划分应用代码,使单个应用的职责更清晰,相互之间可以做到独立升级迭代。这时候应用之间可能会涉及到一些公共配置,可以通过分布式配置中心Zookeeper来解决。

https://gitee.com/cao-lianjie/pic-go/raw/master/img/20210726175334.png