当前位置: 首页 > 科技观察

浓缩精华的进化过程我看了六遍!

时间:2023-03-22 13:30:04 科技观察

【.com原稿】业务驱动技术的发展是永恒不变的真理。一开始业务量小,业务复杂度低,采用的技术也比较简单,基本满足了用户对功能的需求。图片来自Pexels。随着IT信息化的普及,越来越多的交易发生在互联网上。信息量的增加和访问频率的增加是需要解决的问题。因此逐渐加入了缓存、集群等技术手段。同时,对业务扩展性和扩展性的要求也越来越高。高并发、高可用、可扩展、可伸缩、安全的软件架构一直是架构设计的目标。今天我们就来看看架构设计经历了哪些阶段,每个阶段都解决了哪些问题,又提出了哪些新问题。主要是为了引起大家的思考。在不同业务发展阶段采用合适的技术手段,以变求变,是IT人追求的目标。应用与数据集成模型最早的业务应用主要是网站、OA等,访问量有限,单台服务器就可以搞定。通常,应用程序和数据库都部署在一台服务器上,如图1所示:图1:应用程序和数据集成模式在这个阶段,我们可以使用LAMP(LinuxApacheMySQLPHP)技术来快速搞定,而这些工具都是开源的。这种应用程序模式的各种开源代码已经存在很长时间了。这种模式基本没有高并发要求,可用性也很差。有些服务器采用托管模式,上面安装了不同的业务应用程序。一旦服务器出现问题,所有的应用程序都会罢工。但其开发部署成本较低,适合刚起步的应用服务。图1描述了单个应用程序和数据库在单个服务器上运行的模式。我们称这种模式为应用-数据集成模式。应用与数据分离模式随着业务的发展,用户和请求逐渐增多,服务器性能出现问题。一种更简单的解决方案是增加资源并将业务应用程序和数据存储分开。其架构图如图2所示:图2:应用与数据分离模式其中,应用服务器需要处理大量的业务请求,对CPU和内存有一定的要求;而数据库服务器需要进行存储和索引数据等IO操作,更多的会考虑磁盘速度和内存。这种分离解决了性能问题。我们需要扩展更多的硬件资源,让它们各司其职,这样系统才能处理更多的用户请求。虽然在业务上还是有耦合的,但是硬件层面的分离在易用性上要比一体化设计好很多。缓存的加入随着信息系统的发展和上网人数的增加,业务量、用户量、数据量都在不断增加。我们还发现,某些类型的数据,例如新闻、产品信息和趋势新闻,是用户特别需要的。以前这些信息都是依赖数据库获取的,所以受数据库IO性能的影响。此时数据库成为整个系统的瓶颈。如果服务器数量增加,可能很难解决,于是缓存技术登场了。服务器本地缓存和缓存服务器缓存。①客户端浏览器缓存:当用户通过浏览器请求服务器时,会发起一个HTTP请求。如果缓存每个HTTP请求,可以减轻应用服务器的压力。②应用服务器本地缓存:使用进程内缓存,也叫托管堆缓存。以Java为例,这部分缓存是放在JVM的托管堆上的,会受到托管堆回收算法的影响。因为它运行在内存中,对数据的响应速度很快,所以我们通常会把热点数据放在这里。当进程内缓存未命中时,它会去缓存服务器获取信息。如果还是没有命中,就会去数据库中获取。③缓存服务器缓存:与应用服务器本地缓存相比,是进程外缓存,可以与应用服务部署在同一台服务器上,也可以部署在不同的服务器上。一般来说,为了便于管理和合理利用资源,会部署在专用的缓存服务器上。由于缓存会占用内存空间,所以这类服务器会配置比较大的内存。图3描述了缓存请求的顺序,首先访问客户端缓存,然后是进程内本地缓存,然后是缓存服务器,最后是数据。如果缓存信息是在任何一层获取到的,那么再往下就不会再访问了,否则会按照这个顺序获取缓存信息,直到数据库。用户请求访问数据的顺序是客户端浏览器缓存→应用服务器本地缓存→缓存服务器缓存。如果没有按照上面的顺序命中数据,则访问数据库获取数据。加入了缓存的设计,提高了系统的性能。由于缓存是放在内存中的,而且内存的读取速度比磁盘快很多,所以可以快速响应用户的请求。特别是对于一些热点数据,优势尤为明显。同时,在可用性方面也有了明显的改进。即使数据库服务器出现短时间故障,缓存服务器中存储的热点或核心数据仍然可以满足用户的临时访问。当然,易用性会在后期进行优化。服务器集群的加入经历了前面三个阶段的演进,系统对用户请求有很好的支持。其实这都是为了解决高性能和可用性的问题,而这个核心问题会贯穿整个系统架构的演进过程。随着用户请求数量的增加,另一个问题出现了,那就是并发。把这两个词拆开来看:and,理解为“paralleltogether”,意思是同时;send,理解为“issueacall”,意思是请求。一起,多个用户同时请求应用服务器。如果原来的系统只面对大量的数据,那么现在就需要面对多个用户的同时请求。如果还是按照前一阶段的架构图推导的话,单台应用服务器已经不能满足高并发的需求了。至此,服务器集群加入了战场,其架构图如图4所示:图4:加入服务器集群服务器集群就是多台服务器聚在一起,更多的服务器用来分担服务器的负载压力单个服务器,以提高性能和可用性。说白了就是增加单位时间内服务处理请求的数量。以前是一台服务器处理,现在是一堆服务器处理。就像银行柜台一样,增加柜员数量,服务更多人。与以往的架构演进相比,本次架构演进增加了应用服务器的数量,形成了多台应用服务器的集群。应用服务器部署的应用服务没有变化,在用户请求和服务器之间增加了一个负载均衡器,帮助将用户请求路由到对应的服务器。增加服务器的举动表明系统的瓶颈在于处理并发用户请求。没有对数据库和缓存做任何改动,只需要增加服务器数量就可以缓解请求压力。服务器集群会使用多台服务器来分担一台服务器需要处理的请求,同时在多台服务器上运行一个系统,因此可以同时处理大量并发的用户请求。有点像三个皮匠顶诸葛亮,这样对集群中单台服务器的硬件要求也会降低。此时需要关注负载均衡算法,如roundrobin和weightedroundrobin。我们需要保证用户的请求能够平均分配到服务器上,保证同一会话的请求在同一台服务器上处理,并根据不同服务器资源的优劣动态调整流量。添加负载均衡器后,由于它位于互联网和应用服务器之间,负责用户流量的接入,因此可以监控用户流量,验证接入用户的身份和权限。数据库读写分离加缓存可以解决一些热点数据的读取问题,但是缓存数据的容量是有限的,那些非热点数据还是会从数据库中读取。数据库的写入和读取表现不同。写入数据时,会造成行锁或表锁。这时候如果并发执行其他写操作,就会出现排队现象。读操作比写操作快,可以通过索引、数据库缓存等方式实现。因此,引入了一种数据库读写分离的方案,其架构图如图5所示:图5:数据库读写分离此时建立一个主从数据库,主数据库(master))主要用于写入数据,然后通过同步binlog的方式将更新后的数据同步到从库(slave)。对于应用服务器来说,写数据的时候只需要访问主库,读数据的时候只需要访问从库。使用数据库读写分离的方式,将数据库的读写职责分离。利用读取数据的高效率,扩展更多的从库来服务用户的读取操作请求。毕竟在现实场景中,大部分操作都是读操作。另外,从数据同步技术的角度来看,可以分为同步复制技术、异步复制技术和半同步复制技术。数据库读写分离带来好处的同时,架构也需要考虑可靠性问题。比如主库挂了,从库怎么接管主库的工作。主库恢复后,是成为从库还是继续充当主库,如何同步数据。反向代理和CDN随着互联网的逐渐普及,人们对网络安全和用户体验的要求越来越高。以往,用户通过客户端直接访问应用服务器获取服务,应用服务器暴露在互联网中,容易受到攻击。如果在应用服务器和Internet之间增加一个反向代理服务器,它接收用户的请求,然后转发给内网的应用服务器,作为外网和内网之间的缓冲。反向代理服务器只是转发请求,并没有在上面运行任何应用程序,所以当有人攻击它时,不会影响到内网的应用服务器。这无形中保护了应用服务器,提高了安全性。同时,它还起到互联网与内网之间适配和网速转换的作用。比如应用服务器需要同时服务于公网和教育网,但是这两个网络的网速是不一样的。应用服务器和Internet之间可以放置两台反向代理服务器,一台接公网,一台接教育网,屏蔽网络差异,服务更多用户群体。如图6所示,公网客户端和校园网客户端分别来自两个不同的网络:公网和校园网:图6:添加反向代理服务器由于两个网络的访问速度不同,因此将分别为两个网络设置公网代理服务器和校园网代理服务器,通过这种方式,位于不同网络的用户可以请求访问系统。说完反向代理,再说说CDN。它的全称是ContentDeliveryNetwork,即内容分发网络。如果把因特网想象成一个大网络,那么每个服务器或客户端就是分布在网络中的一个节点。节点之间的距离由远到近,用户请求会从一个节点跳到另一个节点,最后跳转到应用服务器获取信息。跳转次数越少,获取信息的速度越快,所以信息可以存放在离客户端较近的节点。这样用户通过客户端只需少量的跳转就可以到达信息。由于这部分信息的更新频率不高,建议存放一些静态数据,比如JavaScript文件、静态HTML、图片文件等,这样客户端就可以从距离最近的网络节点获取资源本身,大大提高了用户体验和传输效率。加入CDN后的架构图如图7所示:图7:CDNCDN的加入显着加快了用户访问应用服务器的速度,同时减轻了应用服务器的压力。本来直接访问应用服务器的请求是不需要经过层层网络的,只需要找到最近的网络节点就可以获取资源。但是,从请求资源的角度来看,这种方式也有局限性。只能作用于静态资源,需要定时更新CDN服务器上的资源。反向代理和CDN的加入解决了安全性、可用性和高性能的问题。分布式数据库和分表分库在经历了前面几个阶段之后,软件的系统架构趋于相对稳定。随着系统运行时间的增加,数据库中积累的数据也越来越多。同时,系统还会记录一些过程数据,比如操作数据、日志数据等,也会增加数据库的负担。即使数据库设置了索引和缓存,当查询海量数据时,它仍然会被拉长。如果说读写分离是从读写层面为数据库分配资源,那么分布式数据库则需要从业务和数据层面分配资源。①对于一个数据表,当表中包含的记录过多时,会分成多个表进行存储。例如:如果有1000万条会员记录,可以将它们分成两条500万条记录,分别存储在两个表中。也可以根据业务拆分表中的列,将表中的一些列放到其他表中存储,然后通过外键与主表关联。拆分列通常是不常访问的数据。②对于数据库来说,每个数据库所能支持的最大连接数和连接池是有上限的。为了提高数据访问效率,数据库会根据业务需求进行划分,让不同的业务可以访问不同的数据库。当然,同一个业务的不同数据也可以存放在不同的库中。如果将这些数据库资源放在不同的数据库服务器上,就是分布式数据库设计。由于数据存储在不同的表/库中,甚至存储在不同的服务器上,因此在执行数据库操作时,代码的复杂度会增加。此时可以添加数据库中间件来消除这些差异。图8:分布式数据库及分表分库架构如图8所示,数据拆分后分别放在表1和表2中。两个表所在的数据库服务器也不一样。还需要考虑数据同步的问题。由于数据的分散部署,业务应用获取数据需要借助数据库中间件。数据库的分表分库和分布式设计在带来性能提升的同时,也增加了数据库管理和访问的难度。以前只能访问一表一库,现在需要跨多表多库。从软件编程的角度来看,有一些数据库中间件提供了最佳实践,例如MyCat和ShardingJDBC。此外,从数据库服务器管理的角度来看,需要监视服务器可用性。从数据治理的角度,需要考虑数据扩容和数据治理的问题。业务拆分解决了大数据量存储的问题后,系统可以存储更多的数据,也就是可以处理更多的业务。业务量的增加,访问量的增加,是任何软件系统随时都必须面对的严峻考验。通过前面几个阶段的学习,我们知道系统的改进基本上是靠空间换时间,用更多的资源和空间来处理更多的用户请求。随着业务越来越复杂,高并发的到来,一些大厂开始对业务系统进行细分,单独部署。此时的架构图如图9所示:图9:业务拆分如果说之前的服务器集群模式是将同一个应用复制到不同的服务器上,那么业务拆分就是将一个应用拆分成多个部署在不同的服务器上。此外,核心应用程序可以水平扩展并部署在多台服务器上。虽然应用已经拆分,但应用之间仍然存在关联,存在应用之间的调用、通信和协调等问题。这也会引入队列、服务注册发现、消息中心等中间件,可以辅助系统管理分布在不同服务器和网络节点上的应用。业务拆分后会形成应用服务,包括商品服务、订单服务等基于业务的服务,以及消息推送、授权验证等基础服务。这些应用服务和数据库服务器分布在不同的容器、服务器和网络节点中,它们之间的通信、协调、管理和监控都是我们需要解决的问题。分布式和微服务近年来,微服务已经成为一种比较流行的架构方式,它将业务应用程序切割成更小的业务模块。实现模块的高内聚、低耦合,每个模块可以独立存在,由独立的团队维护。每个模块内部都可以采用一种独特的技术,而不用关心其他模块的技术实现。模块贯穿容器的部署,通过接口和协议调用模块。任何模块都可以将自己暴露给其他模块调用。同时可以横向扩展热点模块,提升系统性能。当其中一个模块出现问题时,可以用其他相同的模块替换它,从而增强了可用性。概括起来,微服务具有以下特点,业务精细拆分、自治、技术异构、高性能、高可用。它与分布式架构非常相似。我们来看看它们的区别,如图10所示:图10:从概念上理解分布式和微服务的区别。都做了“拆”,但在下面这些方面存在差异:①拆分的目的不同:分布式设计是为了解决单体应用资源有限的问题,不能有更高的用户访问在一台服务器上支持,所以一个应用程序被拆解成不同的部分,然后部署到不同的服务器上来分担高并发的压力。微服务是对服务组件的细化,目的是为了更好的解耦,让服务可以组合起来,实现高性能、高可用、可扩展、可伸缩。②不同的拆分方式:分布式服务架构按照业务和技术分类对系统进行拆分,目的是让拆分后的服务能够承载原来单一服务的业务。微服务在分布式的基础上被分成更细的部分。它将服务拆分成更小的模块,这些模块更专业,分工更细,每个小模块都可以独立运行。③部署方式不同:分布式服务拆分后,通常部署在不同的服务器上。微服务也可以在不同的服务器上放置不同的服务模块。同时也可以在一台服务器上部署多个微服务,或者同一个微服务的多个备份,部署在容器中。分布式和微服务虽然有以上区别,但是从实用的角度来说,都是基于分布式架构的思想构建的。微服务是分布式的进化版本,是分布式的子集。它还会遇到服务拆分、服务通信、协作和管理调度等问题。总结本文按照技术跟随业务变化的思路,描述了从单体架构到集群,再到分布式架构和微服务的发展阶段,描述了软件架构各个阶段的变化特点,前后架构更换的原因和关系以及之后,又解释了软件架构的发展总是会随着业务发展的方向而变化。遵循高性能、高可用性、可扩展性、可伸缩性和安全性的架构目标。【原创稿件,合作网站转载请注明原作者和出处为.com】