vlambda博客
学习文章列表

读书笔记《building-restful-web-services-with-spring-5-second-edition》结垢

Chapter 11. Scaling

随着世界比以往任何时候都更加关注网络,我们所有的网络应用程序都需要服务更多的请求。为了面对更多的请求,我们可能需要扩展我们的应用程序以支持它们。

本章主要关注可应用于我们常规应用程序以解决可伸缩性问题的技术、库和工具。

在本章中,我们将讨论以下主题:

  • Clustering and its benefits
  • Load balancing
  • Scaling databases
  • Distributed caching

Clustering


简单地说,集群是nothing,而是添加多个服务器来提供相同的服务。它将帮助我们避免在系统崩溃和其他不幸情况等灾难期间的中断。集群可以用作故障转移系统、负载平衡系统或并行处理单元。

故障转移集群是一组服务器,其中示例应用程序在所有服务器中复制,以向客户端提供相同的服务,以保持应用程序和服务的高可用性。如果某个服务器由于某种原因出现故障,其余的服务器将接管负载并为消费者提供不间断的服务。

  • Scaling up (vertical scaling): This is about adding more resources to our servers, for example, increasing the RAM, hard drive capacity, and processors. Though it might be a good option, it will only be applicable for certain scenarios, not all. In some cases, adding more resources might be expensive.
  • Scaling out (horizontal scaling): Unlike adding more resources inside one server, scaling out focuses on adding more servers/nodes to service requests. This grouping is called clustering, as all of the servers are doing the same types of task, but duplicated on different servers to avoid interruption.

Benefits of clustering

集群是更首选 用于扩展服务的解决方案,因为它提供了一个快速灵活的选项,可以在需要时添加更多服务器,而无需中断现有服务。在扩展过程中可以提供不间断的服务。在扩展应用程序时,消费者不需要等待任何接近停机时间。所有服务器负载均由中央负载平衡服务器正确平衡。

Load balancing


负载均衡器是集群中最有用的工具。负载均衡器使用多种算法,例如循环、最少连接等,将传入的请求转发到正确的后端服务器进行处理。

市面上有很多第三方负载均衡器,如as F5 (https://f5.com)、HAProxy (http://www.haproxy.org) 等等。尽管这些负载平衡工具的行为不同,但它们侧重于主要作用:将请求负载分配到可用的后端服务器并保持所有服务器之间的平衡。通过适当的负载平衡,我们可以防止单个后端服务器过载。此外,大多数负载均衡器都带有运行状况监控功能,例如 as 检查以验证服务服务器的可用性。

除了服务器之间的主要请求分配外,负载平衡器还保护后端服务器免受前端服务器的影响。前端服务器将不知道将请求发送到哪个后端服务器,因为负载平衡器隐藏了有关后端服务器的所有详细信息。

Scaling databases


扩展数据库 是架构设计中具有挑战性的部分之一。在这里,我们将讨论一些数据库扩展技术来扩展我们的应用程序。

Vertical scaling

正如我们之前讨论过的,在应用服务器级别,我们还可以将扩展技术用于我们的数据库 服务器。增加更多的能力,例如 CPU 和 RAM,将在查询数据库时带来更好的性能。通过使用垂直缩放技术,我们可以获得一致的性能,并且在出现问题时也很容易调试。此外,与水平缩放相比,垂直缩放提供了更高的效率。但是,垂直扩展可能需要定期停机来安装新硬件,并且受到硬件容量的限制。

Horizontal scaling

正如我们讨论过在应用程序级别的水平扩展,我们可以通过向我们的集群添加更多机器来对数据库服务器做同样的事情照顾 database 负载。与垂直扩展相比,它的成本要低得多;然而,这也伴随着集群配置、维护和管理成本的成本结构。

Read replicas

通过保留多个可用于读取目的的从站,我们可以为我们的应用程序带来显着的改进。只读副本有助于读取我们所有只读从属设备中的数据。但是,当我们需要发送写请求时,我们可以使用主数据库。主 database 可用于写入和读取目的,从属只能用于读取目的。我们安装的从站越多,可以处理的基于读取的查询就越多。这种只读副本技术在我们需要处理最少的写入查询和最多的读取查询的情况下非常有用。

Pool connections

当应用程序查询数据库时,它会创建客户端连接、发送查询并获取结果。由于客户端与数据库的连接是一项昂贵的操作,因此必须重用这些连接以进行进一步的查询。在这种情况下,连接池将有助于防止需要为每个请求建立与 database 的连接。通过保持更好的连接池,例如 HikariCP,我们可以提高应用程序的性能。

Use multiple masters

与只读副本一样,多个主机制提供了复制多个 database 服务器的选项。与只读副本复制从属不同,这里我们复制主数据库来写入和读取数据。这种模式对于特定场景非常有用,例如以 REST API 数据事务为中心的应用程序。在多主模式中,我们要求我们的应用程序生成通用唯一标识符UUIDs),以防止多主复制过程中的数据冲突

Load balancing in DB servers

由于来自应用程序服务器的客户端连接限制基于数据库供应商,因此当应用程序服务器请求更多连接时,处理这种情况可能会很棘手。通过保持负载平衡器,我们可以使用其连接池将 database 查询分发到可用的数据库服务器。在负载均衡器的帮助下,我们将确保所有数据库服务器的负载均等;但是,这取决于特定负载均衡器中使用的算法。

Database partitioning

当我们处理大型数据库数据库进行分区非常有用class="indexterm"> 需要高端服务器,查询时间长。此外,当我们的应用程序需要查询大量读写请求时,这很有用。分区可以水平和垂直进行。以下部分将介绍水平和垂直分区。

Sharding (horizontal partitioning)

可以根据任何特定属性将数据库表拆分为多个表。例如,一个用户数据库可以拆分成两个不同的数据库,如user_1user_2,其中user_1 表的用户名以 A-N 开头user_2 表的用户名以 O-Z。通过像前面那样拆分数据库,我们可以减少每个表上的行数,因此我们可以提高性能。

Vertical partitioning

在垂直分区中,可以根据业务概念将数据库表拆分为许多表。例如,一个表可能有更多列以保持其他表可以轻松访问以获得更好的性能。

通过同时进行水平和垂直分区,查询数据库将花费更少的时间并提高 性能。此外,通过将大数据库分成小块,我们可以避免需要高端计算机。这些数据分片也可以分发到低商品服务器中以节省资金。但是,在特定场景下,数据共享可能是一个复杂的过程。

Distributed caching


分布式缓存技术将有助于提高我们网络服务的可扩展性。与进程内缓存不同,分布式缓存不需要构建在同一个应用程序空间中。它们可以存储在集群的多个节点上。尽管分布式缓存部署在多个节点上,但它们提供了缓存的单一状态。

Data-tier caching

在数据库中添加缓存 layer 将提供更好的性能。它被认为 一种提高性能的常用策略,尤其是当我们的应用程序中的读取请求很繁重时。在这里,我们将讨论 Hibernate 的缓存级别。

First-level caching

一级缓存是Hibernate启用的inbuilt会话缓存,它是所有请求的强制缓存。在 Hibernate 中没有禁用一级缓存的选项。一级缓存与会话对象相关联,一旦会话过期就会丢失。当我们第一次查询 Web 服务时,从数据库中检索对象并存储在与 Hibernate 会话相关联的一级缓存中。如果我们再次请求相同的实体,它将从缓存中检索而不查询数据库。

Second-level caching

二级缓存是 Hibernate 中的可选缓存。一级 cache 将是我们的请求到达二级缓存之前的接触点。二级缓存可以按类或按集合配置,它负责跨会话缓存对象。

由于只有少数类受益于缓存,默认情况下二级缓存被禁用。它可以启用给服务设计者。

Application-tier caching

就像在数据库中缓存一样,我们也可以 cache 应用程序中的任何对象 layer 来提高应用程序的性能。在这里,我们将讨论各种对象缓存,尤其是键值缓存工具,并检查它们在市场上的独特性。

Memcached

由于大多数公司在其应用程序中使用 Memcached (https://memcached.org),我们认为 Memcached 是最强大的分布式缓存系统之一。它遵循分布式内存缓存机制,在重复场景下非常有用,例如多次请求同一个服务时.

Redis

Redis (https://redis.io) 是另一个 可用于缓存的内存键值存储。 Redis 支持哈希、列表、集合等数据结构。 Redis 被认为是 流行的键值存储之一,并支持高级键值缓存。 Redis 支持交集和并集等操作。由于其先进的功能和速度,它比 Memcached 更受欢迎。

Hazelcast

Hazelcast (https://hazelcast.com) 是一个支持的内存数据网格 分布式集合,简化分布式计算。它提供了一个简单的 API 和一个简单直接的部署策略。由于 Hazelcast 提供 Memcached 客户端库,使用 Memcached 集群的应用程序可能能够适应 Hazelcast 集群。 Hazelcast 架构支持集群平台中的数据分布和高可扩展性。它还提供智能同步和自动发现。 Hazelcast 提供分布式数据结构、分布式查询和分布式计算等功能。 Spring Boot 在其框架中具有对 Hazelcast 的显式缓存支持。

Ehcache

Ehcache(http://www.ehcache.org)主要用于small 到中等规模的部署,因为它具有简化的可扩展选项。它被认为是使用最广泛的分布式缓存之一。此外,Ehcache 提供了与其他流行的库和框架集成的选项。 Ehcache 扩展从进程内缓存开始,经过混合进程内和进程外部署。此外,Ehcache 还提出了 Terracotta 服务器来提高缓存性能。

Riak

Riak (https://github.com/basho/riak) 是一个 Erlang-基于键值对数据存储 that 具有容错性并提供高可用性。在 Riak 中,数据可以存储在内存、磁盘或两者中。 Riak 可以通过 HTTP API 或 Native Erlang 接口等协议访问。 Riak 支持 Java、C 和 Python 等主要语言。此外,它还支持 MapReduce,可以灵活地进行大数据相关的操作。

Aerospike

Aerospike (https://www.aerospike.com) 是一个开放的 span> 源、闪存优化、内存中 NoSQL 数据库和键值存储。 Aerospike 在三层上运行:闪存优化数据层、自我管理分布层和集群感知客户端层。为确保一致性,分布层在所有 data 中心进行复制。即使单个服务器节点发生故障或从集群中删除,这些副本仍将保持功能。

Infinispan

Infinispan (http://infinispan.org/) 是一个分布式内存键值< span>data 存储,可用作缓存或仅用作数据网格。它可以作为库或通过 REST 等协议访问。此外,Infinispan 可以与 JPA、JCache、Spring 和 Spark 集成。 Infinispan 支持大多数与 MapReduce 相关的操作。

Cache2k

Cache2k (https://cache2k.org/) 提供内存对象缓存选项Java 应用程序中。 Cache2k 主要关注 JVM 内部的缓存。

Other distributed caching

之前,我们讨论了主缓存工具 及其机制。在这里,我们将讨论更多有关市场上可用的其他分布式缓存的信息:

Amazon ElastiCache

ElastiCache 主要使用作为内存数据存储和缓存服务;它是由 AWS 推出的。在 Amazon ElastiCache 的支持下,我们可以快速部署我们的缓存环境,无需任何复杂的安装。它同时支持 Memcached 和 Redis 缓存。

Oracle distributed cache (Coherence)

在这个分布式缓存中,数据在集群中的所有计算机中进行分区。这些分区缓存将被配置为将每条数据保存在集群中的节点上。分布式缓存是 Coherence 中最常用的使用 缓存。

尽管我们在市场上有大量可用的缓存解决方案,但选择特定的解决方案取决于许多因素,例如业务需求、性能要求、数据完整性、容错性、成本等。将正确的分布式缓存层添加到应用程序层和数据库层将带来更好的性能。

Summary


在本章中,我们讨论了扩展 RESTful Web 服务的不同库、工具和技术。在开发应用程序时,我们必须通过使用定义良好的接口来寻找系统组件之间的松散耦合。在下一章中,我们将讨论微服务及其好处。