8张图带你了解大型应用架构的演进过程下面说说应用架构的演进。如何打造高可用、高性能、易扩展的应用?首先我们了解一下大型应用的特点:高可用:系统需要不间断地提供服务,不能出现单点故障高并发:在大流量的冲击下,系统仍然稳定提供服务大数据:应用程序每天都会产生大量的数据,需要很好地存储和管理这些数据。最简单的架构,在应用初期不会有太大的流量,所以只需要一台服务器。此时的架构如下:最简单的架构。在服务器上。应用程序可以用Java开发并部署在Tomcat服务器上。使用开源的MySQL应用程序可以将数据库与数据服务分离。空间严重不足。这个时候我们考虑把服务数量增加到三个(加机器能解决的问题都不是问题);分离应用服务器、数据库服务器和文件服务器。应用服务器需要处理大量的访问,因此需要性能更好的CPU。数据库服务器需要存储大量数据和快速检索,因此磁盘的检索速度快,存储空间大。文件服务器需要存储上传的文件,需要更大的磁盘;现在通常会选择一个第三方的存储服务应用和数据访问服务进行分离,根据每个服务器对应的场景,配置好服务器后,可以大大提升应用的性能,更好的支持业务发展。但是随着业务的发展,访问量的增加,这种架构又会面临挑战,应用服务器的处理能力会下降,存储空间会不够用,但是这个时候,增加服务器和部署集群提供服务,分担各个服务器的压力。部署集群的另一个好处是可伸缩性。比如在双11流量大的情况下,可以增加服务器的数量来分担流量。双11后,减少服务器数量,节省成本。架构如下:应用服务器集群如果应用服务器是Tomcat,可以部署一个Tomcat集群,并在外部部署一个负载均衡器,可以将用户请求以随机、轮询或一致的方式分发到不同的应用服务中散列算法集群;通常选择的免费负载均衡器是nginx。在这种架构下,应用服务器的负载不会成为整个应用的瓶颈点;虽然在这种架构下应用程序的处理速度有了很大的提升,但是也会暴露出另一个问题,数据库的压力会大大增加,导致Access响应延迟,影响整个应用程序的性能。这种架构还有另一个问题。通常应用是有状态的,需要记录用户的登录信息。如果每个用户的请求都随机路由到后端应用服务器,那么用户的会话就会丢失;解决这个问题二一个解决方案:使用一致性哈希将用户请求路由到同一个Tomcat。如果服务器宕机,则该服务器上的用户信息将丢失。通过在Tomcat集群之间配置会话复制,实现共享。这个方案效率高下面两个方案都不太好,请问还有其他方案吗?请继续往下看。根据第28条原则,80%的业务集中访问20%的数据。这20%的数据通常被称为热点数据,但这20%的数据占用的内存也不会小。如果每个应用服务器都存储一个副本,很浪费存储空间,所以这时候需要考虑增加一个分布式缓存服务器(常用redis);当引入了分布式缓存服务器,再看上面解决方案的问题,是可以解决的,将用户的session存储在缓存服务器中,不仅可以防止用户数据丢失,而且效率也不低;架构图如下:分布式缓存服务器毕竟是远程存储,需要通过网络,所以取数据需要一点时间;本地缓存访问速度较快,但内存空间有限,会与应用程序竞争资源;所以这个架构结合了分布式缓存和本地缓存。本地缓存存储少量常用的热点数据。当本地缓存没有命中时,去掉集中式缓存,引入缓存后,可以在一定程度上缓解数据库访问压力。虽然数据库的读写分离加入了缓存,有些数据可以不访问数据库直接进入缓存,但是还是会有一些请求会访问数据库,比如:缓存失败,缓存未命中;流量大的时候,访问数据库的量是不小的。这时候就需要考虑搭建数据库集群,读写分离数据库读写分离。当应用服务器有写操作时,它访问主库。当应用有读操作时,访问从库;大多数应用程序都是读取操作。比写操作大很多,所以可以配置数据库一主多从,分担数据库的压力;为了让应用程序不知道主库和从库,通常需要引入一些读写分离框架来做一个统一的数据访问模块。这种架构需要防范的一个问题是主从延迟。在高并发场景下,主库刚刚写入成功,但是还没有和从库同步成功。这时另一个请求输入读取的数据,发现不存在;解放方案是在应用的高并发场景下设置强制主库查询我们的应用会在全国各地使用。由于不同地区的网络情况不同,有的人请求响应速度快,有的人请求响应速度慢,会严重影响用户体验。为了提高响应速度,需要引入反向代理和CDN;CDN和反向代理都使用缓存,目的:将数据尽快呈现给用户,减轻后端服务器的压力。架构图如下:反向代理和CDNCDN:部署在网络提供商的机房,当用户来访时,数据从距离用户最近的服务器返回,第一时间呈现给用户;通常,静态资源(html、js、css)缓存在CDN中,实现动静分离;但是有时候当一些数据访问量特别大的时候,后端会生成静态资源放在CDN里面,比如:商城的首页,每个用户都需要访问的一个页面,如果每个请求都进入到后端,服务器的压力肯定不小。这种情况下,首页生成的静态文件会缓存到CDN和反向代理服务器。反向代理:部署在应用的中心机房,通常也会缓存静态资源,当用户没有通过CDN请求需要的数据时,首先进入反向代理服务器。如果有用户访问的缓存数据,则直接返回给用户;这里也有特殊情况。请求是从分布式缓存服务器获取的,能获取到就直接返回。该架构实现了4级缓存Level1:CDN缓存静态资源Level2:反向代理缓存静态资源和部分热点数据Level3:应用服务器本地缓存Level4:分布式缓存服务器通常情况下,经过4-级缓存,能够进入数据库的请求不多,减轻了数据库的压力。随着业务的不断扩展,搜索引擎和NoSQL对数据存储和查询的要求越来越高。比较复杂的,通常我们需要引入非关系型数据库,比如搜索引擎和NoSQL数据库。搜索引擎和NoSQL有时候我们的查询场景很复杂,需要查询很多数据表,经过一系列的计算完成。这时候,我们可以考虑使用数据同步工具(如canal)拉取数据到大数据平台,使用批处理框架进行离线计算,将输出结果存储在搜索引擎或NoSQL数据库中,应用直接查询并计算结果返回给用户。也有可能我们需要将多个表的数据汇总起来做成一个宽表,方便应用查询。由于引入的数据存储方式越来越多,为了减少应用管理多个数据源的麻烦,需要封装一个统一的数据访问模块。如果使用Java,可以考虑spring-data业务的垂直拆分随着发展,应用程序越来越大,研发、维护、发布的成本也越来越大。这时候就需要考虑根据业务将单体应用拆分成多个服务。这些服务可以通过RPC进行远程调用和消息传递。一起排队完成用户请求。由于业务的拆分,通常数据库也会进行相应的拆分,以达到一个数据库对应一个服务的理想状态。还在消息队列中,数据不会丢失加快请求的响应:当用户的请求到达服务器时,将请求中可以异步处理的数据放入MQ中,让系统一个一个消费,无需用户等待,加快响应速度。填峰填谷:当大量请求同时进入系统时,会全部放入消息队列,系统会一个一个消费,不会对系统造成太大影响。还有一种情况没有提到,那就是数据库的水平拆分,这也是数据库拆分的最后手段。只有在单表数据量太大,不能满足业务需要时才使用。最常用的方法是将数据库的业务垂直拆分,将数据库中不同业务的数据放在不同的物理服务器上。当前应用选择哪种架构,必须根据实际业务需要灵活选择。推动技术架构发展的主要动力在于业务的发展,而不是为了技术而技术。写在最后首先感谢大家耐心看完到这里。当然,文章中或多或少可能存在不足和错误,有什么建议或意见欢迎评论交流。
