从站点到平台——探讨服务端高并发分布式架构演进

从站点到平台——探讨服务端高并发分布式架构演进,第1张

三级缓存高可以提升应用的执行速度,每次打开应用都会保存一点数据在cpu中,就是这点数据,再下次读取的时候可以大幅度提升应用的响应速度,多任务切换。

三级缓存是为读取二级缓存后未命中的数据设计的—种缓存,在拥有三级缓存的CPU中,只有约5%的数据需要从内存中调用,这进一步提高了CPU的效率。其运作原理在于使用较快速的储存装置保留一份从慢速储存装置中所读取数据且进行拷贝,当有需要再从较慢的储存体中读写数据时,缓存(cache)能够使得读写的动作先在快速的装置上完成,如此会使系统的响应较为快速。

(一)三级缓存分类

Cache(三级缓存),分为两种,早期的是外置,以后的升级产品都是内置的。而它的实际作用即是,L3缓存的应用可以进一步降低内存延迟,同时提升大数据量计算时处理器的性能。降低内存延迟和提升大数据量计算能力对游戏软件都很有帮助。而在服务器领域增加L3缓存在性能方面仍然有显著的提升。

如具有较大L3缓存的配置利用物理内存会更有效,故它比较慢的磁盘I/O子系统可以处理更多的数据请求。具有较大L3缓存的处理器提供更有效的文件系统缓存行为及较短消息和处理器队列长度。

其实最早的L3缓存被应用在AMD发布的K6-III处理器上,当时的L3缓存受限于制造工艺,并没有被集成进芯片内部,而是集成在主板上。在只能够和系统总线频率同步的L3缓存同主内存其实差不了多少。后来使用L3缓存的是英特尔为服务器市场所推出的Itanium处理器。

接着就是P4EE和至强MP。Intel还打算推出一款9MB L3缓存的Itanium2处理器,和以后24MB L3缓存的双核心Itanium2处理器。但基本上L3缓存对处理器的性能提高显得不是很重要,如配备1MB L3缓存的Xeon MP处理器却仍然不是Opteron的对手,由此可见前端总线的增加,要比缓存增加带来更有效的性能提升。

(二)一级、二级和三级缓存谁更重要?

一级最重要,但是现在CPU的一级缓存几乎都一样,所以忽略。

二级缓存的话对于Intel的CPU是很重要的,Intel的CPU的二级缓存越大性能提升非常明显,而AMD的CPU虽然二级缓存也很重要,但是二级缓存大小对AMD的CPU的性能提升不是很明显。

三级缓存其实只是做了个辅助的作用,除了服务器,其实对大多数家庭机没什么用的,内存还是很重要的,但如果运行大型程序或游戏来说三级缓存就显得重要了,目前新型CPU已经有三级缓存了。

(三)主频、二级缓存和三级缓存哪个更重要?

要说主频、二级缓存和三级缓存哪个更重要,这个问题完全还要看你使用电脑追求什么了,主要执行什么任务。主频高运算速度快,二级缓存(L2)和三级缓存(L3)起到内存和CPU之间的缓冲作用,缓解内存和CPU速度不匹配问题会影响到CPU执行的效率。所以大的L2、L3在CPU长时间大量数据处理的时候效率会比较高。高主频在短时间内少量数据的处理上会比较快,其实3项这都很重要 ,哪一项达不到一定标准都会出现瓶颈效应。

IntelXeon 7100系列CPU(16MB三级缓存)

Intel正式发布了针对高端服务器的最新双核Xeon处理器,代号Tulsa的Xeon 7100系列。该处理器依然基于上一代NetBurst架构,但在性能和功耗表现方面都有不小的改进。

适合缓存的内容

1 不变的图像,如logo,图标等

2 js、css静态文件

3 可下载的内容,媒体文件

适合协商缓存

1 HTML文件

2 经常替换的

3 经常修改的js、css文件,js、css文件的加载可以加入文件的签名来拒绝缓存,如‘indexcss签名’,‘index签名js’

不建议缓存的内容

1 用户隐私等敏感数据

2 经常改变的API数据接口

NGINX配置缓存策略

本地缓存配置

1 add_header指令:添加状态码为2XX和3XX的响应头信息,设置代码add_header name value [always];,可以设置Pragma、Expires、Cache-Control,可以继承

2 expires指令:通知浏览器过期时长,设置代码expires time;

3 Etag指令:指定签名,设置代码etag on|off,默认on

前端代码和资源压缩

优势

1 让资源文件更小,加快文件在网络中的传输,让网页更快的展现,降低带宽和流量的开销

压缩方式

1 js、css、、html代码的压缩

2 gzip压缩

gzip配置

gzip on|off; #是否开启gzipgzip_buffers 32 4K|16 8K; #缓冲(在内存中缓存几块?每块多大)gzip_comp_level [1-9] #推荐6,压缩级别(级别越高,压得越小,越浪费CPU计算资源)

gzip_disable #正则匹配UA,什么样的Uri不进行gzip

gzip_min_length 200 #开始压缩的最小长度

gzip_>1-技术有什么区别
首先通信上目前的主流是>


今年年中,一位前谷歌、前亚马逊的工程师推出了他创作的开源内存数据缓存系统 Dragonfly,用 C/C++ 编写,基于 BSL 许可(Business Source License)分发。


根据过往的基准测试结果来看, Dragonfly 可能是世界上最快的内存存储系统,它提供了对 Memcached 和 Redis 协议的支持,但能够以更高的性能进行查询,运行时内存消耗也更少。与 Redis 相比,Dragonfly 在典型工作负载下实现了 25 倍的性能提升;单个 Dragonfly 服务器每秒可以处理数百万个请求;在 5GB 存储测试中,Dragonfly 所需的内存比 Redis 少 30%。


作为一个开源软件,Dragonfly 在短短两个月获得了 92K GitHub 星,177 个 fork 分支。虽然这些年,涌现了不少类似的 Redis 兼容型内存数据存储系统,例如 KeyDB、Skytable,但是都没能像这次这么“轰动”。毕竟 Redis 诞生了十多年,这时从头开始设计一个缓存系统,可以抛弃 历史 包袱,更好地利用资源。



为回击新冒头的 Dragonfly,Redis 的联合创始人兼 CTO Yiftach Shoolman 和 Redis Labs 的首席架构师 Yossi Gottlieb、Redis Labs 的性能工程师 Filipe Oliveira 联合发布了一篇名为《13 年后,Redis 是否需要新的架构》的文章。


在文章中,他们特地给出了自认更加公平的 Redis 70 vs Dragonfly 基准测试结果:Redis 的吞吐量比 Dragonfly 高 18% - 40%,以及一些有关 Redis 架构的观点和思考,以证明 “为什么 Redis 的架构仍然是内存实时数据存储(缓存、数据库,以及介于两者之间的所有内容)的最佳架构”。


虽然他们强调 Redis 架构仍然是同类最佳,但也没法忽视 Dragonfly 这些新软件提供的一些新鲜、有趣的想法和技术,Redis 表示其中的一些甚至有可能在未来进入 Redis(比如已经开始研究的 io_uring 、更现代的 dictionaries、更有策略地使用线程等)。


另外,Redis 指出 Dragonfly 基准测试的比较方法 “不能代表 Redis 在现实世界中的运行方式” 。对此,Reddit 上有网友反驳称:



还有人表示,这篇文章是 Redis 团队在有礼貌地否认“Dragonfly 是最快的缓存系统”,但更多网友表示,Redis 发文章进行“回击”,就已经代表他们的营销部门输了:




我们当然一直在寻求为 Redis 提升性能、扩充功能的创新方向,但这里我们想聊聊自己的观点和思考,阐释 Redis 时至今日为何仍是最出色的实时内存数据存储(包括缓存、数据库以及介于二者之间的一切)方案之一。


接下来,我们将重点介绍 Redis 对于速度和架构差异的观点,再以此为基础做出比较。在文章的最后,我们还会提供基准测试结果、与 Dragonfly 项目的详尽性能比较信息,欢迎大家自行对比参考。


Dragonfly 基准测试其实是将独立单进程 Redis 实例(只能使用单一核心)与多线程 Dragonfly 实例(可以使用虚拟机 / 服务器上的全部可用核心)进行比较。很明显,这样的粗暴比较并不能代表 Redis 在现实场景下的运行状态。作为技术构建者,我们希望更确切地把握自有技术同其他方案间的差异,所以这里我们做了一点公平性调整:将具有 40 个分片的 Redis 70 集群(可使用其中的大部分实例核心)与 Dragonfly 团队在基准测试中使用的最大实例类型(AWS c4gn16xlarge)进行性能比较。


在这轮测试中,我们看到 Redis 的吞吐量比 Dragonfly 要高出 18% 至 40%,而这还仅仅只用到全部 64 个 vCore 中的 40 个。






在我们看来,每一位多线程项目的开发者在立项之前,都会根据以往工作中经历过的痛点来指导架构决策。我们也承认,在多核设备上运行单一 Redis 进程(这类设备往往提供几十个核心和数百 GB 内存)确实存在资源无法充分利用的问题。但 Redis 在设计之初也确实没有考虑到这一点,而且众多 Redis 服务商已经拿出了相应的解决方案,借此在市场上占得一席之地。


Redis 通过运行多个进程(使用 Redis 集群)实现横向扩展,包括在单一云实例背景下也是如此。在 Redis 公司,我们进一步拓展这个概念并建立起 Redis Enterprise。Redis Enterprise 提供管理层,允许用户大规模运行 Redis,并默认启用高可用性、即时故障转移、数据持久与备份等功能。


下面,我们打算分享幕后使用的一些原则,向大家介绍我们如何为 Redis 的生产应用设计良好的工程实践。




通过在每个虚拟机上运行多个 Redis 实例,我们可以:


我们不允许单一 Redis 进程的大小超过 25 GB(运行 Redis on Flash 时上限为 50 GB)。如此一来,我们就能:


以横向扩展的方式灵活运行内存数据存储,是 Redis 获得成功的关键。下面来看具体原因:


我们仍然欣赏由社区提出的种种有趣思路和技术方案。其中一部分有望在未来进入 Redis(我们已经开始研究 io_uring、更现代的字典、更丰富的线程使用策略等)。但在可预见的未来,我们不会放弃 Redis 所坚守的无共享、多进程等基本架构原则。这种设计不仅具备最佳性能、可扩展性和d性,同时也能够支持内存内实时数据平台所需要的各类部署架构。


附录:Redis 70 对 Draonfly 基准测试细节


版本:

目标:

客户端配置:

资源利用与配置优化:


最后,我们还发现 Redis 和 Dragonfly 都不受网络每秒数据包或传输带宽的限制。我们已经确认在 2 个虚拟机间(分别作为客户端和服务器,且均使用 c6gn16xlarge 实例)使用 TCP 传递约 300 B 大小的数据包负载时,可以让每秒数据包传输量达到 1000 万以上、传输带宽超过 30 Gbps。





单 GET 通道延迟低于 1 毫秒:

30 条 GET 通道:

单 SET 通道延迟低于 1 毫秒:

30 条 SET 通道:

用于各变体的 memtier_benchmark 命令:

单 GET 通道延迟低于 1 毫秒

30 条 GET 通道

单 SET 通道延迟低于 1 毫秒

30 条 SET 通道


在本次比较测试中,我们在客户端(用于运行 memtier_benchmark)和服务器(用于运行 Redis 和 Dragonfly)使用了相同的虚拟机类型,具体规格为:


参考链接:

>

微服务¹架构的目标是帮助工程团队更快,更安全,更高质量地交付产品。解耦服务允许团队快速迭代,对系统的其余部分影响最小。

在Medium,我们的技术堆栈始于2012年的单片Nodejs应用程序。我们已经构建了几个卫星服务,但我们还没有制定一个系统地采用微服务架构的策略。随着系统变得越来越复杂并且团队不断发展,我们在2018年初转向了微服务架构。在这篇文章中,我们希望分享我们有效地做到这一点并避免微服务综合症的经验。

首先,让我们花一点时间来思考微服务架构是什么,不是什么。 “微服务”是那些过载和混乱的软件工程趋势之一。这就是我们在Medium认为它是什么:

该定义包括三个微服务设计原则:

Three Principles of Modeling Microservices

当我们对微服务进行建模时,我们应该遵守所有三个设计原则。这是实现微服务架构全部潜力的唯一途径。错过任何一个都会成为反模式。

没有一个目的,每个微服务最终会做太多事情,成长为多个“单片”服务。我们不会从微服务架构中获得全部好处,我们也会支付运营成本。

如果没有松散耦合,对一个服务的更改会影响其他服务,因此我们无法快速安全地发布更改,这是微服务架构的核心优势。更重要的是,紧密耦合引起的问题可能是灾难性的,例如数据不一致甚至数据丢失。

如果没有高凝聚力,我们将最终得到一个分布式单片系统 - 一组混乱的服务,必须同时进行更改和部署才能构建单一功能。由于多个服务协调的复杂性和成本(有时跨多个团队),分布式单片系统通常比集中式单片系统差得多。

与此同时,了解 微服务不是什么 很重要:

在Medium,我们总是在做出重大产品或工程决策时会问“为什么现在?”这个问题。 “为什么?”是一个显而易见的问题,但它假设我们拥有无限的人,时间和资源,这是一个危险的假设。当你想到“为什么现在?”时,你突然有了更多的限制 - 对当前工作的影响,机会成本,分心的开销等等。这个问题有助于我们更好地优先考虑。

我们现在需要采用微服务的原因是我们的Nodejs单片应用程序已经成为多个方面的瓶颈。

首先,最紧迫和最重要的瓶颈是其性能。

某些计算量很大且I / O很重的任务不适合Nodejs我们一直在逐步改进整体应用程序,但事实证明它是无效的。它的低劣性能使我们无法提供更好的产品而不会使已经非常慢的应用程序变慢。

其次,整体应用程序的一个重要且有点紧迫的瓶颈是它会减慢产品开发速度。

由于所有工程师都在单个应用程序中构建功能,因此它们通常紧密耦合。我们无法灵活地改变系统的一部分,因为它也可能影响其他部分。我们也害怕做出重大改变,因为影响太大,有时难以预测。整个应用程序作为一个整体进行部署,因此如果由于一次错误提交导致部署停滞,那么所有其他更改(即使它们完全正常工作)也无法完成。相比之下,微服务架构允许团队更快地发货,学习和迭代。他们可以专注于他们正在构建的功能,这些功能与复杂系统的其余部分分离。更改可以更快地进入生产。他们可以灵活地安全地尝试重大变革。

在我们新的微服务架构中,更改会在一小时内完成生产,工程师不必担心它会如何影响系统的其他部分。该团队还 探索 了在开发中安全使用生产数据的方法²多年来一直是白日梦。随着我们的工程团队的发展,所有这些都非常重要。

第三,单一应用程序使得难以为特定任务扩展系统或隔离不同类型任务的资源问题。

使用单一的单一应用程序,我们必须扩展和缩小整个系统,以满足更多资源需求的任务,即使这意味着系统过度配置用于其他更简单的任务。为了缓解这些问题,我们对不同类型的请求进行分片,以分离Nodejs进程。它们在一定程度上起作用,但不会扩展,因为这些微单一版本的单片服务是紧密耦合的。

最后但同样重要的是,一个重要且即将成为紧迫的瓶颈是它阻止我们尝试新技术。微服务架构的一个主要优点是每个服务都可以使用不同的技术堆栈构建,并与不同的技术集成。这使我们能够选择最适合工作的工具,更重要的是,我们可以快速安全地完成工作。

采用微服务架构并非易事。它可能会出错,实际上会损害工程生产力。在本节中,我们将分享七个在采用早期阶段帮助我们的策略:

有人可能会认为采用新的服务器架构意味着产品开发的长时间停顿以及对所有内容的大量重写。这是错误的做法。我们永远不应该为了建立新的服务而建立新的服务。每次我们建立新服务或采用新技术时,都必须具有明确的产品价值和/或工程价值。

产品价值应以我们可以为用户提供的利益为代表。与在单片Nodejs应用程序中构建值相比,需要一项新服务来提供值或使其更快地交付值。工程价值应该使工程团队更好,更快。

如果构建新服务没有产品价值或工程价值,我们将其留在单一的应用程序中。如果十年内Medium仍然有一个支持某些表面的单片Nodejs应用程序,那就完全没了问题。从单一应用程序开始实际上有助于我们战略性地对微服务进行建模。

建立具有明确价值的新服务

有人可能会认为采用新的服务器架构意味着产品开发的长时间停顿以及对所有内容的大量重写。这是错误的做法。我们永远不应该为了建立新的服务而建立新的服务。每次我们建立新服务或采用新技术时,都必须具有明确的产品价值和/或工程价值。

产品价值应以我们可以为用户提供的利益为代表。与在单片Nodejs应用程序中构建值相比,需要一项新服务来提供值或使其更快地交付值。工程价值应该使工程团队更好,更快。

如果构建新服务没有产品价值或工程价值,我们将其留在单一的应用程序中。如果十年内Medium仍然有一个支持某些表面的单片Nodejs应用程序,那就完全没了问题。从单一应用程序开始实际上有助于我们战略性地对微服务进行建模。

单片持久存储被认为是有害的

建模微服务的很大一部分是对其持久数据存储(例如,数据库)进行建模。跨服务共享持久数据存储通常似乎是将微服务集成在一起的最简单方法,然而,它实际上是有害的,我们应该不惜一切代价避免它。这就是原因。

首先,持久数据存储是关于实现细节的。 跨服务共享数据存储会将一个服务的实现细节暴露给整个系统。如果该服务更改了数据的格式,或者添加了缓存层,或者切换到不同类型的数据库,则还必须相应地更改许多其他服务。 这违反了松散耦合的原则。

其次,持久数据存储不是服务行为,即如何修改,解释和使用数据 。如果我们跨服务共享数据存储,则意味着其他服务也必须复制服务行为。 这违反了高内聚的原则 - 给定域中的行为泄露给多个服务。如果我们修改一个行为,我们将不得不一起修改所有这些服务。

在微服务架构中,只有一个服务应该负责特定类型的数据。所有其他服务应该通过负责服务的API请求数据,或者保留数据的 只读非规范(可能具体化)副本

这可能听起来很抽象,所以这是一个具体的例子。假设我们正在构建一个新的推荐服务,它需要来自规范帖子表的一些数据,目前在AWS DynamoDB中。我们可以通过两种方式之一为新推荐服务提供发布数据。

在单片存储模型中,推荐服务可以直接访问单片应用程序所执行的相同持久存储。这是一个坏主意,因为:

缓存可能很棘手。 如果推荐服务与单一应用程序共享相同的缓存,我们也必须在推荐服务中复制缓存实现细节;如果推荐服务使用自己的缓存,当单片应用更新帖子数据时,我们将不知道何时使其缓存无效。

如果单片应用程序决定更改为使用RDS而不是DynamoDB来存储帖子数据,我们将不得不重新实现推荐服务中的逻辑以及访问帖子数据的所有其他服务。

单片应用程序具有解释帖子数据的复杂逻辑 ,例如,如何确定帖子是否应该对给定用户不可见。我们必须在推荐服务中重新实现这些逻辑。一旦整体应用程序更改或添加新逻辑,我们也需要在任何地方进行相同的更改。

即使推荐服务是自己的数据访问模式的错误选项,推荐服务仍然停留在DynamoDB上。

在解耦存储模型中,推荐服务不能直接访问发布数据,也不能直接访问任何其他新服务。发布数据的实​​现细节仅保留在一个服务中。有不同的方法来实现这一目标。

Option A 理想情况下,应该有一个拥有帖子数据的Post服务,其他服务只能通过Post服务的API访问邮政数据。但是,为所有核心数据模型构建新服务可能是一项昂贵的前期投资。

当人员配置有限时,还有一些更实用的方法。根据数据访问模式,它们实际上可能是更好的方式。

选项B 中,单一应用程序可让推荐服务知道何时更新相关的帖子数据。通常,这不必立即发生,因此我们可以将其卸载到排队系统。

选项C 中,ETL管道生成推荐服务的发布数据的只读副本,以及可能对推荐有用的其他数据。在这两个选项中,推荐服务完全拥有其数据,因此它可以灵活地缓存数据或使用最适合的数据库技术。

解耦“建立服务”和“运行服务”

如果构建微服务很难,那么运行服务往往更难。 当运行服务与构建每个服务相结合时,它会减慢工程团队的速度,团队必须不断重新发明这样做。我们希望让每项服务都专注于自己的工作而不用担心如何运行服务的复杂问题,包括网络,通信协议,部署,可观察性等。服务管理应该与每个服务的实现完全分离。

由于最近在 容器化,容器编排,服务网格,应用程序性能监 控等方面的技术进步,“运行服务”的解耦变得比以往更容易实现。

网络。 网络(例如,服务发现,路由,负载平衡,流量路由等)是运行服务的关键部分。传统方法是为每种平台/语言提供库。它工作但不理想,因为应用程序仍然需要非常繁琐的工作来集成和维护库。通常,应用程序仍然需要单独实现某些逻辑。现代解决方案是在Service Mesh中运行服务。在Medium,我们使用 Istio和Envoy作为边车代理 。构建服务的应用工程师根本不需要担心网络问题。

通信协议 。无论您选择哪种技术堆栈或语言来构建微服务,从一个高效,类型化,跨平台且需要最少开发开销的成熟RPC解决方案开始是非常重要的。支持向后兼容性的RPC解决方案也使部署服务更加安全,即使它们之间存在依赖关系。在Medium,我们选择了gRPC。

一种常见的替代方案是基于>

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zz/12634757.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-27
下一篇 2023-05-27

发表评论

登录后才能评论

评论列表(0条)

保存