SegmentFault 阿里云栖号最新的文章
2024-03-18T15:23:19+08:00
https://segmentfault.com/feeds/blogs
https://creativecommons.org/licenses/by-nc-nd/4.0/
AI加速引擎PAI-TorchAcc:OLMo训练加速最佳实践
https://segmentfault.com/a/1190000044722684
2024-03-18T15:23:19+08:00
2024-03-18T15:23:19+08:00
阿里云云栖号
https://segmentfault.com/u/aliyunqi
0
<h2>1.PAI-TorchAcc 简介</h2><p>PAI-TorchAcc(Torch Accelerator)是阿里云机器学习平台开发的Pytorch上的大模型训练加速框架。</p><p>PAI-TorchAcc借助社区PyTorch/XLA,通过 GraphCapture 技术将 Pytorch 动态图转换为静态计算图,基于计算图进行分布式优化、计算优化、显存优化等,为包括大语言模型在内的Pytorch上的模型提供高效训练支持。相比于社区Pytorch/XLA,PAI-TorchAcc具有更好的易用性、更高的性能和更丰富的功能。更详细的介绍可以见文章:AI加速引擎PAI-TorchAcc:整体介绍与性能概述。</p><h2>2.完全开源的 OLMo 模型</h2><p>OLMo (Open Language Model) 是由艾伦人工智能研究所等机构发表的完全开源的大语言模型。OLMo 模型提供了完整的训练数据集、代码、checkpoint 等,几乎完全开源了一个大语言模型从零开始训练所需的代码和数据。不仅如此,OLMo 模型在多项核心指标上接近而且部分超过 LLAMA2 模型。</p><h2>3.如何使用 PAI-TorchAcc 加速 OLMo 模型训练?</h2><p>通过 PAI-TorchAcc 加速模型训练一般需要三个步骤:</p><ul><li>定义 torchacc.Config,并指定加速选项。</li><li>调用 torchacc.accelerate,并传入model和config,完成加速训练的准备。</li><li>通过 torchacc.AsyncLoader对 torch dataset_loader 进行封装,加速数据加载。</li></ul><pre><code># 定义 model 和 dataloader
model = AutoModelForCausalLM.from_pretrained("allenai/OLMo-1B", trust_remote_code=True)
tokenizer = AutoTokenizer.from_pretrained("allenai/OLMo-1B", use_fast=False, trust_remote_code=True)
train_loader = get_dataloader(tokenizer)
# 定义 TorchAcc Config
config = torchacc.Config()
config.compute.bf16 = True # 开启 bf16
config.compute.acc_scaled_dot_attn = True # 自动替换 Torch ScaledDot 为torchacc flash attn 版本
config.dist.fsdp.size = torchacc.dist.world_size() # 开启 FSDP,设置 FSDP 数目
config.dist.fsdp.wrap_layer_cls = {"OlmoSequentialBlock"} # 将OLMo模型的decoder layer进行FSDP封装
# 一行代码加速模型
model = torchacc.accelerate(model, config)
# 异步加速数据加载
train_loader = torchacc.AsyncLoader(train_loader, model.device)
# training loop
...</code></pre><p>阿里云 DSW Gallery 现在有更完整的 OLMo 模型加速示例:<a href="https://link.segmentfault.com/?enc=qzZ42QYdlQWNJyjp7A3AZA%3D%3D.95G66QVy0SV74LGHpIH%2FYwRw4cDyMFjRpFHFd%2BFPn0aWU2Gm6xhSaHN9UMXuyJqt0YledWkeLAjen8zYbFZT760lstyEEZAR5P%2FjeWTCe7cNdSrWNd7nGQJdvV%2BxVIqIwRsEWACC3RGrX9q8PqQdFQ%3D%3D" rel="nofollow">https://pai.console.aliyun.com/?regionId=cn-wulanchabu#/dsw-g...</a></p><h2>4.PAI-TorchAcc 的性能表现</h2><p>以单机 8 卡 A100 为例,在 OLMo 1B 上,PAI-TorchAcc 相比 PyTorch FSDP 加速比为 1.64X;在 OLMo 7B 上,PAI-TorchAcc 相比 PyTorch FSDP 加速比为 1.52X。</p><p><img src="/img/remote/1460000044722686" alt="图片" title="图片"></p><p>$$
图 1: PAI-TorchAcc 相比 PyTorch FSDP 在 OLMo 模型上的性能提升
$$</p><h2>5.PAI-TorchAcc 为何这么快?</h2><p>在 OLMo 模型的性能对比中,PAI-TorchAcc和 PyTorch 都采用相同的分布式策略 FSDP(ZeRO-3)。PAI-TorchAcc 通过计算优化、通信优化、显存优化等,在 OLMo 7B 上相比 PyTorch 达到了 1.52X 的加速比。下面我们以 OLMo 7B 为例分析 PAI-TorchAcc 的性能收益来源。</p><h3>计算优化&通信优化</h3><p>为了方便对比,我们将 PAI-TorchAcc和 PyTorch 的 micro batch size都设置为 2 进行对比。</p><p>从图 2 中可以看出,通过计算优化,PAI-TorchAcc 将访存密集型算子的时间优化为 PyTorch 对应算子时间的 45.56%,整体的加速比约为 1.25X。通过通信优化,PAI-TorchAcc 能够将计算和通信更好进行 overlap,将没有 overlap 的通信占整体时间的占比从 8.19%降低到 2.43%。</p><p>通过计算优化&通信优化,PAI-TorchAcc 相比PyTorch达到了 1.32X 的加速比。</p><p><img src="/img/remote/1460000044722688" alt="图片" title="图片"></p><p>$$
图 2: micro batch size=2 时,PAI-TorchAcc 相比 PyTorch FSDP 在 OLMo 7B 上的性能提升
$$</p><h3>显存优化</h3><p>在 PAI-TorchAcc 中,由于 PyTorch 模型已经转换为静态计算图,所以可以使用比较多的显存优化方法。例如,通过对算子的执行顺序进行调整,可以得到更小的显存峰值;通过更优的显存分配算法,可以让显存碎片更少,减少显存使用;通过 patten match 等方式将 attention 替换为使用显存更少的 flash attention 等等。</p><p>通过显存优化,PAI-TorchAcc 的最大 micro batch size 能够达到 4,而 PyTorch 的最大 micro batch size 只能达到 2,这使得PAI-TorchAcc 能够获得更高的性能加速比,这一部分的性能收益主要来自于计算密集型算子。</p><p>如图 3 所示,PAI-TorchAcc micro batch size=4 相比 micro batch size=2 的吞吐加速比为 1.15X,这使得PAI-TorchAcc 相比 PyTorch 最终达到了 1.52X 的加速比。</p><p><img src="/img/remote/1460000044722689" alt="图片" title="图片"></p><p>$$
图 3: 在不同 micro batch size 下,PAI-TorchAcc 相比 PyTorch FSDP 在 OLMo 7B 上的性能提升
$$</p><h2>6.总结</h2><p>本文介绍了如何使用 PAI-TorchAcc 加速 OLMo 模型训练,分析了PAI-TorchAcc 的性能收益来源。实际上,PAI-TorchAcc可以通过并行化策略、显存优化、计算优化和调度优化等方法来加速更多的大语言模型训练,目前已接入常见的开源大模型,包括LLaMA、LLaMA-2、BaiChuan、ChatGLM、QWen等。除了大语言模型之外,PAI-TorchAcc也易于接入视觉类、语音类模型,并大幅度提升训练性能。欢迎在阿里云上使用该产品。</p><p>作者:黄奕桐、沈雯婷、艾宝乐、王昂、李永</p><p><strong><a href="https://link.segmentfault.com/?enc=1Mydnugzyc08epo8pKrhuw%3D%3D.ff6dsHJWMvbssUuz5jIBdlwaKxSpqxbEP7pSrh7P%2FGjGmQVYXPksf0oYkfhkZgDXv3OYNujxc3KhGWJSm58tQ%2Fu%2FY6vxHZp%2FIycp9imV0t4%3D" rel="nofollow">原文链接</a></strong></p><p><strong>本文为阿里云原创内容,未经允许不得转载。</strong></p>
通义千问1.5(Qwen1.5)大语言模型在 PAI-QuickStart 的微调与部署实践
https://segmentfault.com/a/1190000044721845
2024-03-18T13:09:32+08:00
2024-03-18T13:09:32+08:00
阿里云云栖号
https://segmentfault.com/u/aliyunqi
0
<p>Qwen1.5(通义千问1.5)是阿里云最近推出的开源大型语言模型系列。作为“通义千问”1.0系列的进阶版,该模型推出了多个规模,从0.5B到72B,满足不同的计算需求。此外,该系列模型还包括了Base和Chat等多个版本的开源模型,为全球的开发者社区提供了空前的便捷性。阿里云的人工智能平台PAI,作为一站式的机器学习和深度学习平台,对Qwen1.5模型系列提供了全面的技术支持。无论是开发者还是企业客户,都可以通过PAI-QuickStart轻松实现Qwen1.5系列模型的微调和快速部署</p><h2>1.Qwen1.5系列模型介绍</h2><p>通义千问1.5在先前发布1.0版本模型的基础上进行了大幅更新,主要体现在如下三个方面:</p><ul><li>多语言能力提升:Qwen1.5在多语言处理能力上进行了显著优化,支持更广泛的语言类型和更复杂的语言场景。</li><li>人类偏好对齐:通过采用直接策略优化(DPO)和近端策略优化(PPO)等技术,增强了模型与人类偏好的对齐度。</li><li>长序列支持:所有规模的Qwen1.5模型均支持高达32768个tokens的上下文长度,大幅提升了处理长文本的能力。</li></ul><p>在性能评测方面,Qwen1.5在多项基准测试中均展现出优异的性能。无论是在语言理解、代码生成、推理能力,还是在多语言处理和人类偏好对齐等方面,Qwen1.5系列模型均表现出了强大的竞争力。</p><h2>2.PAI-QuickStart 介绍</h2><p>快速开始(PAI-QuickStart)是阿里云人工智能平台PAI的产品组件,它集成了国内外 AI 开源社区中优质的预训练模型,涵盖了包括大语言模型,文本生成图片、语音识别等各个领域。通过 PAI 对于这些模型的适配,用户可以通过零代码和 SDK 的方式实现从训练到部署再到推理的全过程,大大简化了模型的开发流程,为开发者和企业用户带来了更快、更高效、更便捷的 AI 开发和应用体验。</p><h2>3.运行环境要求</h2><ul><li>本示例目前支持在阿里云北京、上海、深圳、杭州地域,使用PAI-QuickStart产品运行。</li><li>资源配置要求:</li></ul><p>1.Qwen1.5-0.5B/1.4B/4B/7B量级模型:最低使用V100/P00/T4(16GB显存)及以上卡型运行训练任务(QLoRA轻量化微调);<br>2.Qwen1.5-14B量级模型:最低使用V100(32GB显存)/A10及以上卡型运行训练任务(QLoRA轻量化微调)。</p><h2>4.通过PAI-QuickStart使用模型</h2><p>开发者可以在 PAI 控制台的“快速开始”入口,找到Qwen1.5系列模型,以Qwen1.5-7B-Chat为例,模型卡片如下图所示:</p><p><img src="/img/remote/1460000044721851" alt="图片" title="图片"></p><h3>4.1 模型部署和调用</h3><p>PAI 提供的Qwen1.5-7B-Chat预置了模型的部署配置信息,用户仅需提供推理服务的名称以及部署配置使用的资源信息即可将模型部署到PAI-EAS推理服务平台。当前模型需要使用公共资源组进行部署。</p><p><img src="/img/remote/1460000044721852" alt="图片" title="图片"></p><p>部署的推理服务支持使用ChatLLM WebUI进行实时交互,示例如下:</p><p><img src="/img/remote/1460000044721854" alt="图片" title="图片"></p><h3>4.2 模型微调训练</h3><p>PAI 为Qwen1.5-7B-Chat模型配置了微调算法,支持用户以开箱即用得方式对Qwen1.5-7B-Chat进行微调。训练算法支持使用 Json 格式输入,每条数据由问题、答案组成,分用“instruction”、“output”字段表示,例如:</p><pre><code>[
{
"instruction": "写一首以“寓居夜感”为题的诗:",
"output": "独坐晚凉侵,客窗秋意深。风沙疑化雾,夜气欲成霖。家务劳人倦,浓茶代酒斟。哀鸿鸣四野,一并助长吟。"
},
{
"instruction": "写一首以“次答友人思乡诗”为题的诗:",
"output": "阅尽沧桑万事空,何如归卧夕阳中。并州最是伤心地,四十馀年噩梦同。"
}
]
</code></pre><p>当完成数据的准备,用户可以将数据上传到对象存储 OSS Bucket 中。算法需要使用V100/P00/T4(16GB显存)的GPU资源,请确保选择使用的资源配额内有充足的计算资源。</p><p><img src="/img/remote/1460000044721855" alt="图片" title="图片"></p><p>训练算法支持的超参信息如下,用户可以根据使用的数据,计算资源等调整超参,或是使用算法默认配置的超参。</p><p><img src="/img/remote/1460000044721856" alt="图片" title="图片"></p><p>点击“训练”按钮,PAI-QuickStart 开始进行训练,用户可以查看训练任务状态和训练日志。</p><p><img src="/img/remote/1460000044721857" alt="图片" title="图片"></p><p><img src="/img/remote/1460000044721858" alt="图片" title="图片"></p><p>如果需要将模型部署至PAI-EAS,可以在同一页面的模型部署卡面选择资源组,并且点击“部署”按钮实现一键部署。模型调用方式和上文直接部署模型的调用方式相同。</p><h3>通过Python SDK使用</h3><p>PAI 提供了Python SDK,支持开发者方便得使用Python在PAI完成模型的开发到上线的。通过PAI Python SDK,开发者可以轻松调用PAI-快速开始提供的模型,完成相应模型的微调训练和部署。</p><p>部署推理服务的示例代码如下:</p><pre><code>from pai.model import RegisteredModel
# 获取PAI提供的模型
model = RegisteredModel(
model_name="qwen1.5-7b-chat",
model_provider="pai"
)
# 直接部署模型
predictor = model.deploy(
service="qwen7b_chat_example"
)
# 用户可以通过推理服务的详情页,打开部署的Web应用服务
print(predictor.console_uri)</code></pre><p>微调训练的示例代码如下:</p><pre><code># 获取模型的微调训练算法
est = model.get_estimator()
# 获取PAI提供的公共读数据和预训练模型
training_inputs = model.get_estimator_inputs()
# 使用用户自定义数据
# training_inputs.update(
# {
# "train": "<训练数据集OSS或是本地路径>",
# "validation": "<验证数据集的OSS或是本地路径>"
# }
# )
# 使用默认数据提交训练任务
est.fit(
inputs=training_inputs
)
# 查看训练产出模型的OSS路径
print(est.model_data())</code></pre><p>通过快速开始的模型卡片详情页,用户可以通过“在DSW打开”入口,获取一个完整的Notebooks示例,了解如何通过PAI Python SDK使用的细节。</p><h2>5.结论</h2><p>Qwen1.5(通义千问1.5)的推出标志着阿里云在开源大语言模型领域的最新进展。这个系列推出了不同规模的开源模型,可广泛用于多样化的下游应用场景。开发者可以借助PAI-QuickStart轻松地对Qwen1.5模型进行定制和部署。此外,PAI QuickStart还汇集了一系列先进的模型,覆盖多个专业领域,欢迎广大开发者们体验和应用这些丰富的资源。</p><p>相关资源链接:</p><ul><li>Qwen1.5 介绍:<a href="https://link.segmentfault.com/?enc=%2FqYi%2B10l6bgVzHAiPs7t2w%3D%3D.MYn9Ibq8opO0q%2BLDSnYK2G01MS3sfdfWszDhRy66CKgPmpa9iq7iw%2BqIcjnl2vil" rel="nofollow">https://qwenlm.github.io/zh/blog/qwen1.5/</a></li><li>PAI 快速开始:<a href="https://link.segmentfault.com/?enc=C0Rugb4Q%2BkLcNcqXj%2BWRwQ%3D%3D.Q5yqceGCWHdkheHAkloa4C1j9jsn7urPf5YbjV2qc3aWEnrEOymP3tdrOnWZhs%2B7I6ThCAkmGmViy8Zfsf7Tqw%3D%3D" rel="nofollow">https://help.aliyun.com/zh/pai/user-guide/quick-start-overview</a></li><li>PAI Python SDK Github:<a href="https://link.segmentfault.com/?enc=Jycbr%2Fry%2FiFMH9izPhRUEw%3D%3D.H1GfQU3ssii5iWb5k1aSJz9TY3UI9ZUJfqSlv%2F4cbOOhm4Q4U2UipDpij0k9kcxk" rel="nofollow">https://github.com/aliyun/pai-python-sdk</a></li></ul><p>作者:汪诚愚(熊兮)、高一鸿(子洪)、黄俊(临在)</p><p><strong><a href="https://link.segmentfault.com/?enc=KtAI0XwUxfO9jTqRQiM5PQ%3D%3D.z4nY3xt3FVYG4pjf%2BVVxKC6QTVq3Y4se7aVXewDV%2FuaKfWWexhcPGGiA2JTLgHwh223%2BJr4ho%2BQnyY78kMMJz97oWwY5bbKb4wHTtChavQo%3D" rel="nofollow">原文链接</a></strong></p><p><strong>本文为阿里云原创内容,未经允许不得转载。</strong></p>
AI加速引擎 PAI-TorchAcc:整体介绍与性能概述
https://segmentfault.com/a/1190000044716081
2024-03-15T15:41:44+08:00
2024-03-15T15:41:44+08:00
阿里云云栖号
https://segmentfault.com/u/aliyunqi
0
<h2>1.简介</h2><p>PAI-TorchAcc(Torch Accelerator)是阿里云人工智能平台PAI开发的Pytorch上的大模型训练加速框架。</p><p>PAI-TorchAcc提供了一套基于Pytorch的简洁、易用的接口,无需进行模型转换就可以无缝地接入HuggingFace上的模型,并用多种分布式策略进行训练加速。</p><p>PAI-TorchAcc借助社区PyTorch/XLA,通过 LazyTensor 技术将Pytorch代码转换为静态执行图,基于计算图,结合阿里云上的计算资源情况,进行了大量的GPU硬件上模型训练的针对性分布式优化、计算优化。</p><p>得益于简单的模型接入方式、基于计算图的优化,PAI-TorchAcc能够灵活地支持各种大模型的多种规模,兼容不同的硬件。PAI-TorchAcc支持常见大模型1B-175B的训练,训练吞吐相对PyTorch原生、Megatron-LM均有提升,如LLaMA系列模型,相比PyTorch原生提升了140%,相比Megatron-LM提升了5%,在A100上MFU达到70%,8卡到128卡线性加速比达到15.6X。</p><h2>2.背景和需求</h2><h3>2.1 背景</h3><ul><li>大模型训练</li></ul><p>近年来,大语言模型、视频生成类模型迅速发展,它们基于庞大的文本、图片、视频等数据集进行训练,执行多种自然语言处理、图像生成、视频生成等任务,具备强大的理解和生成能力。随着计算资源和技术的不断进步,大模型的参数量已增长到数亿甚至数万亿级别,例如LLaMA、GPT-3、通义千问、Sora等,这些模型在许多基准测试上表现出了前所未有的性能。</p><p>然而,训练大模型需要极高的成本。比如使用Megatron-LM预训练一个OPT-175B模型需要上千张A100训练2个月[1],硬件利用率MFU约47%,期间因为硬件故障经历了几十次checkpoint的加载和续训练。使用PyTorch FSDP进行LLaMA-2-70B的微调也需要16张A100运行约13.5小时[2]。NVIDIA A100、H100等硬件资源价格高昂且不易获取,市面上也逐渐出现了其他性价比更高的硬件资源。</p><p>加速不同的大模型的预训练、续训练、微调,充分利用不同的硬件资源,提升资源利用率,是降低大模型训练成本的一个有效途径。</p><ul><li>Megatron-LM</li></ul><p>NVIDIA Megatron-LM[3]是一个基于 PyTorch 的分布式训练框架,用来训练基于Transformer的大模型。Megatron-LM综合应用了数据并行、模型并行、流水并行来实现GPT-3等特定模型的训练。然而,不同的大模型、训练数据集接入Megatron-LM十分不灵活,需要将checkpoint和数据格式进行转换。同时,Megatron-LM虽然对一些模型算子做了手动的优化,在面对不同模型的不同计算模式时,难以自动地应用这种手动的优化。</p><ul><li>DeepSpeed</li></ul><p>DeepSpeed[4]是微软开源的一个PyTorch上的大模型分布式训练框架,支持ZeRO和流水并行,并且可以结合Megatron-LM运行3D并行。DeepSpeed已经成为HuggingFace transformers库中一个训练组件。然而DeepSpeed性能表现较差,并且和Megatron-LM同样存在面对不同计算模式时无法灵活优化的限制。</p><ul><li>PyTorch/XLA</li></ul><p>PyTorch/XLA[5]将PyTorch和 OpenXLA相结合,使用LazyTenor技术,将PyTorch代码转换为静态执行图,在静态图上进行计算图优化和后端编译优化。Pytorch/XLA主要是针对TPU 场景进行优化,在GPU上还存在一定问题和优化空间,如不支持Transformers 模型常用的FlashAttention加速算子、不支持 torchrun 拉起、计算通信 Overlap 差、显存开销大等问题。</p><h2>2.2 需求</h2><p>基于以上背景,我们需要一个大模型分布式训练引擎,能够方便接入多变的PyTorch模型,尤其是Transformer类模型,兼容多种硬件。在不同模型变化的计算模式下,在不同硬件变化的硬件架构和计算、访存能力下,能够自动地对计算进行优化,尤其在阿里云的硬件上能够表现较高的性能。同时,大模型导致单卡内存和显存无法完全放下,不同的模型需要结合不同的分布式策略,合理通信,完成多卡训练并提升线性加速比。</p><h2>3.PAI-TorchAcc核心技术特性</h2><h3>灵活的模型接入</h3><ul><li>支持LLaMA系列、Qwen、BaiChuan、ChatGLM、OLMo、Bloom等常见的大模型1B-175B的训练;</li><li>无缝对接HuggingFace中的模型;</li><li>一键接入和加速Pytorch模型。</li></ul><h3>千亿级模型参数量</h3><ul><li>已经支持1B到175B大模型训练;</li></ul><h3>全面的训练模式</h3><ul><li>支持混合精度训练,包括Float32、Float16、BFloat16等;</li><li>支持Pytorch模型的预训练、微调和续训练。、</li></ul><h3>组合的分布式策略</h3><ul><li>支持Data Parallel、Tensor Parallel、Sequence Parallel、Fully Sharded Data Parallel、Pipeline等分布式策略及其组合。</li></ul><h3>自动计算优化和显存优化</h3><ul><li>使用手动的Gradient Checkpoint和自动的Rematerialization降低峰值显存;</li><li>自动进行显存规划和管理,降低峰值显存和减少显存碎片化;</li><li>自动对Kernel进行编译优化,提高计算效率;</li><li>自动接入SOTA的高性能Kernel。</li></ul><h3>兼容多种硬件</h3><ul><li>兼容NVIDIA A100/800, H100/800, V100等;</li><li>兼容阿里云上灵骏集群的硬件资源。</li></ul><h3>与现有框架对比</h3><p><img src="/img/remote/1460000044716083" alt="图片" title="图片"></p><h2>4.PAI-TorchAcc架构</h2><h2>4.1 总体架构</h2><p><img src="/img/remote/1460000044716084" alt="图片" title="图片"></p><p>PAI-TorchAcc的架构自顶向下分为以下几层:</p><ul><li>模型层:支持计算机视觉、自然语言处理、语音合成等深度学习模型训练的加速;</li><li>算法库:支持HuggingFace Transfomers、PAI-EasyNLP、TIMM等算法库构建的模型;</li><li>前端:支持以PyTorch为前端语言的模型训练;</li><li>Lowering:使用LazyTensor、Symbolic Trace等技术将前端代码转换为静态执行图;</li><li>IR:使用多层中间表达,包含High-Level的设备无关的IR和Low-Level的设备相关的IR,基于两层IR上分别做计算图优化和后端编译优化。</li><li>编译优化引擎:TorchAcc的编译优化引擎包括计算图优化引擎TorchAcc Compiler和多种后端编译优化引擎BladeDISC和OpenXLA。基于两层IR,进行分布式优化、显存优化、通信优化、计算优化以及算子调度和显存管理等优化,生成优化的设备码。</li><li>硬件:最终产生硬件相关的设备码在不同算力、带宽和显存的硬件设备上执行。</li></ul><h3>4.2 接口</h3><p>PAI-TorchAcc抽取了一套简洁的接口,灵活接入并加速任意的Pytorch模型,而不需要改动原有的模型代码。</p><p>通过 PAI-TorchAcc 加速模型训练一般需要三步:</p><ul><li>定义 torchacc.Config,并指定加速选项。</li><li>调用 torchacc.accelerate,并传入model和config,完成加速训练的准备。</li><li>通过 torchacc.AsyncLoader对 torch dataset_loader 进行封装,加速数据加载。</li></ul><pre><code> model = ...
dataloader = ...
+ # 一行代码加速模型,也可传入Config配置更丰富的加速功能,如分布式策略、编译优化选项等
+ model = torchacc.accelerate(model)
+ # 异步加速数据加载
+ dataloader = torchacc.AsyncLoader(dataloader, model.device)
model.train()
for source, labels in dataloader:
...</code></pre><h3>4.3 编译优化</h3><p>PAI-TorchAcc通过LazyTensor、Symbolic Trace等技术将前端Pytorch代码转换为静态执行图,并在静态图上进行自动优化,在分布式的硬件设备上高效运行。</p><h4>计算图优化</h4><p>在Tensor Graph上进行优化,这层优化基于High-Level IR——StableHLO进行。</p><ul><li>分布式: 通过分图和通信算子插入,完成流水并行、SPMD等。</li><li>显存优化:通过算子级别的显存Live range和复用分析、静态调度策略、自动重算、显存管理优化等来减少显存的峰值和碎片化。</li><li>计算优化:通过CSE等简化计算,通过算子大粒度融合来优化访存密集型算子,减少kernel launch,减少访存,提升计算效率;通过自动的计算图匹配重写的方式接入Flash Attention等高性能Kernel。</li><li>通信优化:通过通信算子的合并、拆分、异步化以及算子的调度来提升通信效率,提高计算和通信的overlap。</li></ul><h4>后端编译优化</h4><p>在Buffer Graph上进行优化,这层优化基于Low-Level的IR,包括LHLO、LLVM IR和多种MLIR的dialect。</p><ul><li>多后端:支持OpenXLA和阿里自研的BladeDISC两种编译后端;</li><li>Lowering和Codegen:将上层的StableHLO Lowering成LHLO和多种MLIR的dialect,并在各级Lowering过程中进行优化,最终表达为LLVM IR,通过LLVM生成针对硬件的优化代码;</li><li>Custom Call:High-Level IR自动Pattern rewrite的优化kernel,通过custom call调用。</li></ul><h2>5.实践案例和性能</h2><p>PAI-TorchAcc在A100上能够达到70%的MFU,并且在多卡下几乎线性扩展(8卡到128卡加速比15.6X),在灵活支持各种模型的基础上,性能能够高于Megatron-LM。我们在常见的开源大模型上做了性能测试,使用相同的硬件资源,PAI-TorchAcc的训练吞吐相对PyTorch原生、Megatron均有提升,如LLaMA系列模型相对PyTorch原生提升了140%,相对Megatron提升了5%。</p><p>我们将在后续的系列文章中提供一个具体的实践案例:PAI-TorchAcc在OLMo模型训练上的接入示例和加速效果,并且给出加速的来源分析。</p><h2>6.总结和未来展望</h2><p>PAI-TorchAcc可以灵活接入Pytorch模型,并通过并行化策略、显存优化、计算优化和调度优化等方法来加速大模型以及视觉类、语音类模型的训练。PAI-TorchAcc已经在常见大模型上如LLaMA、LLaMA-2、BaiChuan、ChatGLM、QWen、OLMo、Bloom取得了不错的效果。未来我们将从以下方向继续深入优化,以支持更多的场景,取得更好的加速效果。</p><ul><li>Graph Capture优化和子图编译:在生成计算图的过程中遇到无法识别的算子将导致编译失败,我们将进一步优化Graph Capture,并支持子图的编译优化。</li><li>自动分布式:PAI-TorchAcc提供了多种分布式策略,然而在不同的模型和硬件上,使用哪种组合的分布式策略、如何进行分图能够取得最优的性能,仍然需要根据经验手动配置。PAI-TorchAcc将借助静态计算图和模型、硬件特性,做自动的分布式。</li><li>AutoGC:借助静态计算图和模型、硬件特性,自动进行checkpoint选点。</li><li>动态Shape性能优化:动态Shape导致重编译引起的性能下降,当前我们通过分桶的方式减少了重编译的次数,仍然存在大量的padding,如何做更高性能的动态Shape支持,是一个深入优化的方向。</li><li>自研编译优化引擎BladeDISC的优化。</li></ul><h2>引用</h2><p>[1] <a href="https://link.segmentfault.com/?enc=WHNPT%2Fs2N%2FBuTxF3DS8mVA%3D%3D.hhmhxSuc9HhOwNvN3NQclGk%2Fxce7wZ2zwbH1EEmxq0j4g8yWyWnEmDBhnp39%2FD78" rel="nofollow">https://arxiv.org/pdf/2205.01068.pdf</a></p><p>[2] <a href="https://link.segmentfault.com/?enc=JA1WKiAlY9qiwGBfhSKmvA%3D%3D.Kr%2BXQrq74BfQ3IosdAFPJ3hIABTUBv%2F%2BluJ2TkgI4gZfi4XW0lv9psEjKPJ8UCHmU1yFvu2BKI%2BMSvgPAgHKmw%3D%3D" rel="nofollow">https://huggingface.co/blog/ram-efficient-pytorch-fsdp</a></p><p>[3] <a href="https://link.segmentfault.com/?enc=N%2BfDB%2BH83KeJRCOII%2Bz6cw%3D%3D.iYX9KR%2BiI6KENgVbshxOqhH2f3e40heMcQXIOIQ%2FOI4HpK19nBFwD8%2FLjdxnB6xW" rel="nofollow">https://github.com/NVIDIA/Megatron-LM</a></p><p>[4] <a href="https://link.segmentfault.com/?enc=Vj0nqOE8lMH5nz94hAtwLA%3D%3D.p9ByU4gbGc3IMp50s2iYZSKPYbDpPph2eA0tPlnFiSPh%2FSN99oSa%2F8jMkXIsPxfo" rel="nofollow">https://github.com/microsoft/DeepSpeed</a></p><p>[5] <a href="https://link.segmentfault.com/?enc=OYJu5ntxv99yalFbFctrug%3D%3D.lYw5zg9rW9RIVzXy7tHTBCSr%2FBnH9yFPzTUkp3mxpi4%3D" rel="nofollow">https://github.com/pytorch/xla</a></p><p>作者:沈雯婷、黄奕桐、艾宝乐、王昂、李永</p><p><strong><a href="https://link.segmentfault.com/?enc=NRun6e76dOw1kDaZ6rESUg%3D%3D.u7sjArsKcNucMHqNz%2FPV%2BkpYvpAa32xayN0v0CuwqyOb9vf%2BVFzQ0CMOFs4H7X6RVtHxim8WCKKSF4R4Uhu0nwj4YCEYpx%2F%2FUaYW%2BtWxEeI%3D" rel="nofollow">原文链接</a></strong></p><p><strong>本文为阿里云原创内容,未经允许不得转载。</strong></p>
PTS 3.0:开启智能化的压测瓶颈分析
https://segmentfault.com/a/1190000044709564
2024-03-13T16:51:47+08:00
2024-03-13T16:51:47+08:00
阿里云云栖号
https://segmentfault.com/u/aliyunqi
0
<h2>PTS 简介</h2><p>性能测试 PTS(Performance Testing Service)是阿里云上一款简单易用,具备强大的分布式压测能力的 SaaS 压测平台。PTS 可以模拟复杂的业务场景,并快速精准地调度不同规模的流量,同时提供压测过程中多维度的监控指标和日志记录。用户无需准备资源,即可按需发起压测任务,监控压测指标,获取压测报告,进而能够高效率、全方位地验证业务站点的性能、容量和稳定性。</p><h2>阿里云压测平台演进之路</h2><p>阿里云压测平台 PTS,由阿里云可观测团队倾心打造,应双十一稳定性和容量规划的需求背景而诞生,随高可用、中间件上云而对外输出产品能力。整体演进分以下 5 个阶段:</p><p><img src="/img/remote/1460000044709566" alt="图片" title="图片"></p><h3>2010 年:阿里巴巴容量规划平台</h3><p>在此之前,阿里巴巴大促活动的容量规划主要通过人工估算的方式来完成的。各个系统的负责同学聚在一起开个会,将信息汇总到一起,按专家经验就把容量规划的机器预算给定下来了。而且,各个系统通常都留了比较大的机器冗余,即使估算的不准也不会造成大的业务影响。</p><p>此时,容量计算的公式被第一次提了出来,通过目标容量/单机容量上限,得到各应用需要的机器资源数,再加上一定比例的冗余量,就是大促时需要的总资源数。</p><p>在阿里容量规划平台的 1.0 版本当中,通过对各业务系统线下环境单机压测,来获取各服务的单机容量上限,完成了从人工容量规划到系统化容量规划的过度。</p><h3>2013 年:阿里巴巴全链路压测-流量平台</h3><p>随着双十一业务规模快速拉升,分布式系统架构的技术组件越来越多,应用的上下游依赖关系也越来越复杂。双十一当天 0 点到来的时候,从 CDN 到接入层、前端应用、后端服务、缓存、存储、中间件整个链路上都面临着巨大流量,这个时候应用的服务状态除了受自身影响,还会受到依赖环境影响,并且影响面会继续传递到上游,哪怕一个环节出现一点误差,误差在上下游经过几层累积后会造成什么影响谁都无法确定。由于各层依赖的不确定性,无法再基于单业务容量上限规划全局容量。</p><p>所以我们建立了全链路压测机制,通过全面仿真双十一业务流量,我们的系统能够提前经历几次“双十一”,让容量的不确定性问题提前暴露并解决。</p><p>流量平台是全链路压测的 CPU,能够模拟出双十一上亿用户的仿真流量,制造每秒数十万次用户行为的超大规模流量。主要由两大部件构成:1)全链路压测操控中心,进行压测的配置和操控、数据的监控以及对压测引擎集群的管控;2)压测引擎,由控制台统一管控,部署在外网 cdn 集群,进行登陆、session 同步,发送各种协议的压测请求、状态统计。</p><p>2013 年之后,全链路压测成为双十一、双十二等大促备战最重要的稳定性验证工具,随着业务的发展不断进化,持续发挥着不可替代的作用。</p><h3>2018 年;阿里云 PTS 1.0:阿里云压测产品发布</h3><p>在云计算的浪潮下,越来越多的用户开始基于阿里云上的基础产品设计自己的架构。在 2018 年,我们正式发布了阿里云压测产品:PTS,将阿里巴巴集团压测平台的技术架构迁移至阿里云,对外部用户提供 SaaS 化的压测产品。PTS 1.0 核心能力包括:</p><ul><li>无限接近真实的流量:业务场景中无论是高并发要求还是发起端的分散度,覆盖三四线城市主要运营商的节点广度都能做到真正模拟用户行为,客户端到服务端间复杂的网络瓶颈也能暴露无遗,压测结果更加全面和真实可信。</li><li>操作简单易上手:不需要专门的性能测试团队或者测试背景的积累,完全面向开发的交互设计,开发自测试,投入产出比高。</li><li>多维度施压:支持并发和 RPS 双维度。</li><li>压力动态调整:支持压测能力动态修改。</li></ul><h3>2020 年:阿里云 PTS 2.0:施压能力、产品体验再升级</h3><p>随着 PTS 1.0 用户规模的不断扩大,越来越多的用户在不同的业务场景对 PTS 提出了支持超高并发的压测需求,甚至超过了集团双十一的并发量级,典型场景如:春晚红包压测、保险开门红压测、考试报名压测等。PTS 2.0 通过优化资源调度和施压引擎性能,提供了百万并发、千万 QPS 的压测能力,连续支撑了多次春晚红包活动等顶级流量压测。</p><p>同时,PTS 2.0 升级了流量录制和多协议场景化功能,提升了产品体验:</p><ul><li>流量录制功能:允许录制实际用户操作,以便创建真实的用户行为模拟。</li><li>多协议支持:对流媒体、MQTT、RocketMQ、Kafka、JDBC、Redis、Dubbo 等协议支持白屏化压测配置,扩宽测试场景。</li></ul><h3>2024 年:阿里云 PTS 3.0:可观测、智能化、开源加持的下一代压测平台</h3><p>在 PTS 1.0 和 2.0 的持续演进中,PTS 在产品体验、施压能力都得到了大幅提升。要做一轮完整的容量规划,用户还需要解决以下问题:</p><ul><li>评估压测的影响范围,确定压测流量会经过哪些服务端应用,如何准确地掌控压测的爆炸半径。</li><li>洞察压测和业务系统的全局监控指标,分析当前系统容量水位。</li><li>如果压测结果不满足预期,需要出分析整个系统的性能瓶颈点。</li></ul><p>这些问题是每个测试团队都需要面对的,在云原生和可观测技术的发展下,如何更好的解决这些问题?</p><p>针对以上挑战,我们提出性能压测可观测化能力,分别针对以上问题提出压测链路可观测:</p><p>首先,在实施压测前,先执行一次拨测,通过拨测发起一次请求来构建整个压测链路拓扑,通过链路拓扑全局来看整个压测的影响范围。</p><p>其次,性能指标可观测,获取压测链路所涉及的监控指标,自动生成压测及各业务各实例水位大盘,边压边观测。</p><p>再次,聚合压测请求各指标和调用链,通过 调用链分析和智能化分析,实现性能瓶颈可观测。</p><p>最后,通过前面提到的压测指标和各服务实例资源水位,进行梯度压测评估验证系统服务容量。构建性能压测可观测,实现从压测到数据分析。</p><p>在此之上,我们构建了可观测加持下的下一代阿里云压测平台 PTS 3.0 ,通过打通阿里云全栈可观测生态,并集成云原生大模型和多模型智能归因算法,给用户提供更专业、结论更清晰、更有洞察力的压测报告,辅助用户在 PTS 实现压测瓶颈定位和根因分析。</p><p>同时 PTS 3.0 全面兼容开源 JMeter 压测工具,只需 JMeter 脚本上传到 PTS,即可自动补全依赖插件,一键发起压测。</p><h2>PTS 3.0 核心功能</h2><h3>自动感知压测应用拓扑</h3><p>PTS 与阿里云可观测链路 OpenTelemetry 打通,在发起压测之前,会通过拨测能力进行压测脚本测试和链路探测,能自动准确识别请求链路所经过的组件,根据拨测请求建立链路拓扑图,不会涉及正常请求所经过的链路,这样我们就可以很直观的感知压测所经过的链路,明确压测涉及的应用范围和架构拓扑。</p><p><img src="/img/remote/1460000044709568" alt="图片" title="图片"></p><h3>应用瓶颈分析</h3><p>压测性能瓶颈往往出现在服务端应用层,最通过压测报告-全局监控-应用监控,可以观测到压测时段各服务端应用的副本数,以及 CPU、内存、磁盘等资源水位。配合错误请求数、数据库错慢调用次数、FullGC 次数等指标,可以判断出哪些应用负载较高,需要优化性能或扩容。</p><p><img src="/img/remote/1460000044709569" alt="图片" title="图片"></p><p>对 JVM 内存泄漏等场景,可以通过 JVM 监控判断出问题现象,并配合 Profiling 分析根因。</p><p><img src="/img/remote/1460000044709570" alt="图片" title="图片"></p><h3>错慢请求根因分析</h3><p>定界瓶颈点在应用层,需要进一步分析根因时,PTS 可以打通可观测链路 OpenTelemetry,获取到本次压测的错慢调用链,包含从施压端到数据库层的完整链路。通过下钻分析,可以定位到请求在调用链的哪里出现了错慢现象,并可以通过堆栈分析,判断出错慢的原因。</p><p><img src="/img/remote/1460000044709571" alt="图片" title="图片"></p><p><img src="/img/remote/1460000044709572" alt="图片" title="图片"></p><h3>云资源瓶颈分析</h3><p>在云原生的架构体系中,系统接入层、数据库、中间件、容器等基础资源都天然在云上,通过打通阿里云可观测监控 Prometheus,可以获取到负载均衡 SLB、RDS 数据库、ECS、容器等基础云资源的监控指标和大盘,辅助用户分析云资源是否存在瓶颈。</p><p><img src="/img/remote/1460000044709573" alt="图片" title="图片"></p><p><img src="/img/remote/1460000044709574" alt="图片" title="图片"></p><p><img src="/img/remote/1460000044709575" alt="图片" title="图片"></p><h3>智能洞察</h3><p>性能测试 PTS 3.0 通过异常区间检测算法,自动发现应用层监控指标的异动,并通过多模型的智能归因算法,推理出异常现象的根因。</p><p><img src="/img/remote/1460000044709576" alt="图片" title="图片"></p><p><img src="/img/remote/1460000044709577" alt="图片" title="图片"></p><h2>总结</h2><p>PTS 3.0 以瓶颈分析为核心场景,构建出可观测、智能化、开源加持的下一代压测平台。目前 PTS 3.0 已全面上线,新版控制台地址:<a href="https://link.segmentfault.com/?enc=x4b0pY0CPUq0ia2RuBcW4w%3D%3D.%2BbVyn4Qk46GI1PV2MJtv05fljJaUl6bI1coS%2FN%2FTs8qzFRj0OfXiGFumuYUug9aJ" rel="nofollow">https://ptsnext.console.aliyun.com/</a></p><p>PTS 2.0 用户可以通过概览页右上角的“体验 PTS 3.0”按钮,一键跳转新版,新版 PTS 和 JMeter 的场景与报告和 PTS 2.0 完全兼容。</p><p><img src="/img/remote/1460000044709578" alt="图片" title="图片"></p><p>为了更好的满足中小企业上云验证、容量规划等性能测试需求,目前性能测试 PTS 推出 59.9 元基础版特惠资源包。3 万 VUM 额度,最高 5 万虚拟用户规模并发量,让性能测试更具性价比。</p><p><img src="/img/remote/1460000044709579" alt="图片" title="图片"></p><p>作者:拂衣</p><p><strong><a href="https://link.segmentfault.com/?enc=th4Faz%2BevC0uHIe8H7Tm6Q%3D%3D.m%2Fy5ojrmiAW8MmlakFu9dXbapW%2B7gv6VVPZ%2BYTk27L2NdokY%2Fnvx3mOwLvK2XBoKxsgb0EV2mx050R6Eu3m%2BEUtqrLnRypGHKCTTLcyehfU%3D" rel="nofollow">原文链接</a></strong></p><p><strong>本文为阿里云原创内容,未经允许不得转载。</strong></p>
弱结构化日志 Flink SQL 怎么写?SLS SPL 来帮忙
https://segmentfault.com/a/1190000044705664
2024-03-12T16:25:18+08:00
2024-03-12T16:25:18+08:00
阿里云云栖号
https://segmentfault.com/u/aliyunqi
0
<h2>背景</h2><p>日志服务 SLS 是云原生观测与分析平台,为 Log、Metric、Trace 等数据提供大规模、低成本、实时的平台化服务,基于日志服务的便捷的数据接入能力,可以将系统日志、业务日志等接入 SLS 进行存储、分析;阿里云 Flink 是阿里云基于 Apache Flink 构建的大数据分析平台,在实时数据分析、风控检测等场景应用广泛。阿里云 Flink 原生支持阿里云日志服务 SLS 的 Connector,用户可以在阿里云 Flink 平台将 SLS 作为源表或者结果表使用。</p><p>阿里云 Flink SLS Connector 对于结构化的日志非常直接,通过配置,SLS 的日志字段可以与 Flink SQL 的 Table 字段列一一映射;然后仍有大量的业务日志并非完全的结构化,例如会将所有日志内容写入一个字段中,需要正则提前、分隔符拆分等手段才可以提取出结构化的字段,基于这个场景,本文介绍一种使用 SLS SPL 配置 SLS Connector 完成数据结构化的方案,覆盖日志清洗与格式规整场景。</p><h2>弱结构化日志处理的痛点</h2><h3>弱结构化日志现状与结构化处理需求的矛盾</h3><p>日志数据往往是多种来源,多种格式,往往没有固定的 Schema,所以在数据处理前,需要先对数据进行清洗、格式规整,然后在进行数据分析;这类数据内容格式是不固定的,可能是 JSON 字符串、CSV 格式,甚至是不规则的 Java 堆栈日志。</p><p>Flink SQL 是一种兼容 SQL 语法的实时计算模型,可以基于 SQL 对结构化数据进行分析,但同时也要求源数据模式固定:字段名称、类型、数量是固定;这也是 SQL 计算模型的基础。</p><p>日志数据的弱结构化特点与 Flink SQL 结构化分析之间有着一道鸿沟,跨越这道鸿沟需要一个中间层来进行数据清洗、规整;这个中间层的方案有多种选择可以使用,下面会对不同的方案做简单对比,并提出一种新的基于 SLS SPL 的方案来轻量化完成解决数据清洗规整的工作。</p><h3>弱结构化日志数据</h3><p>下面是一条日志示例,日志格式较为复杂,既有 JSON 字符串,又有字符串与 JSON 混合的场景。其中:</p><ul><li>Payload 为 JSON 字符串,其中 schedule 字段的内容也是一段 JSON 结构。</li><li>requestURL 为一段标准的 URL Path 路径。</li><li>error 字段是前半部分包含 CouldNotExecuteQuery:字符串,后半部分是一段 JSON 结构。</li><li><strong>tag__:__path</strong> 包含日志文件的路径,其中 service_a 可能是业务名称。</li><li>caller 中包含文件名与文件行数。</li></ul><pre><code>{
"Payload": "{\"lastNotified\": 1705030483, \"serverUri\": \"http://test.alert.com/alert-api/tasks\", \"jobID\": \"44d6ce47bb4995ef0c8052a9a30ed6d8\", \"alertName\": \"alert-12345678-123456\", \"project\": \"test-sls-project\", \"projectId\": 123, \"aliuid\": \"1234567890\", \"alertDisplayName\": \"\\u6d4b\\u8bd5\\u963f\\u91cc\\u4e91\\u544a\\u8b66\", \"checkJobUri\": \"http://test.alert.com/alert-api/task_check\", \"schedule\": {\"timeZone\": \"\", \"delay\": 0, \"runImmediately\": false, \"type\": \"FixedRate\", \"interval\": \"1m\"}, \"jobRunID\": \"bf86aa5e67a6891d-61016da98c79b-5071a6b\", \"firedNotNotified\": 25161}",
"TaskID": "bf86aa5e67a6891d-61016da98c79b-5071a6b-334f81a-5c38aaa1-9354-43ec-8369-4f41a7c23887",
"TaskType": "ALERT",
"__source__": "11.199.97.112",
"__tag__:__hostname__": "iabcde12345.cloud.abc121",
"__tag__:__path__": "/var/log/service_a.LOG",
"caller": "executor/pool.go:64",
"error": "CouldNotExecuteQuery : {\n \"httpCode\": 404,\n \"errorCode\": \"LogStoreNotExist\",\n \"errorMessage\": \"logstore k8s-event does not exist\",\n \"requestID\": \"65B7C10AB43D9895A8C3DB6A\"\n}",
"requestURL": "/apis/autoscaling/v2beta1/namespaces/python-etl/horizontalpodautoscalers/cn-shenzhen-56492-1234567890123?timeout=30s",
"ts": "2024-01-29 22:57:13"
}</code></pre><h3>结构化数据处理需求</h3><p>对于这样的日志提取出更有价值的信息需要进行数据清洗,首先需要提取重要的字段,然后对这些字段进行数据分析;本篇关注重要字段的提取,分析仍然可以在 Flink 中进行。</p><p>假设提取字段具体需求如下:</p><ul><li>提取 error 中的 httpCode、errorCode、errorMessage、requestID。</li><li>提取 <strong>tag__:__path</strong> 中的 service_a 作为 serviceName。</li><li>提取 caller 中的 pool.go 作为 fileName,64 作为 fileNo。</li><li>提取 Payload 中的 project;提取 Payload 下面的 schedule 中的 type 为 scheuleType。</li><li>重命名 <strong>source</strong> 为 serviceIP。</li><li>其余字段舍弃。</li></ul><p>最终需要的字段列表如下,基于这样一个表格模型,我们可以便捷的使用 Flink SQL 进行数据分析。</p><p><img src="/img/remote/1460000044705666" alt="图片" title="图片"></p><h2>解决方案</h2><p>实现这样的数据清洗,有很多种方法,这里列举几种基于 SLS 与 Flink 的方案,不同方案之间没有绝对的优劣,需要根据不同的场景选择不同的方案。</p><p>数据加工方案:在 SLS 控制台创建目标 Logstore,通过创建数据加工任务,完成对数据的清洗。</p><p><img src="/img/remote/1460000044705667" alt="图片" title="图片"></p><p>Flink 方案:将 error 和 payload 指定为源表字段,通过 SQL 正则函数、JSON 函数对字段进行解析,解析后的字段写入临时表,然后对临时表进行分析。</p><p><img src="/img/remote/1460000044705669" alt="图片" title="图片"></p><p>SPL 方案:在 Flink SLS Connector 中配置 SPL 语句,对数据进行清洗,Flink 中源表字段定义为清洗后的数据结构。</p><p><img src="/img/remote/1460000044705670" alt="图片" title="图片"></p><p>从上述三种方案的原理不难看出,在需要数据清洗的场景中,在 SLS Connector 中配置 SPL 是一种更轻量化的方案,具有轻量化、易维护、易扩展的特点。</p><p>在日志数据弱结构化的场景中,SPL 方案既避免了方案一中创建临时中间 Logstore,也避免了方案二中在 Flink 中创建临时表,在离数据源更近的位置进行数据清洗,在计算平台关注业务逻辑,职责分离更加清晰。</p><h2>如何在 Flink 中使用 SPL</h2><p>接下来以一段弱结构化日志为例,来介绍基于 SLS SPL 的能力来使用 Flink。为了便于演示,这里在 Flink 控制台配置 SLS 的源表,然后开启一个连续查询以观察效果。在实际使用过程中,仅需修改 SLS 源表配置,即可完成数据清洗与字段规整。</p><h3>SLS 准备数据</h3><ul><li>开通 SLS,在 SLS 创建 Project,Logstore,并创建具有消费 Logstore 的权限的账号 AK/SK。</li><li>当前 Logstore 数据使用 SLS SDK 写入模拟数据,格式使用上述日志片段,其中包含 JSON、复杂字符串等弱结构化字段。</li></ul><p><img src="/img/remote/1460000044705671" alt="图片" title="图片"></p><h3>预览 SPL 效果</h3><p>在 Logstore 可以可以开启扫描模式,SLS SPL 管道式语法使用丨分隔符分割不同的指令,每次输入一个指令可以即时查看结果,然后增加管道数,渐进式、探索式获取最终结果。</p><p><img src="/img/remote/1460000044705672" alt="图片" title="图片"></p><p>对上图中的 SPL 进行简单描述:</p><pre><code>* | project Payload, error, "__tag__:__path__", "__tag__:__hostname__", caller
| parse-json Payload
| project-away Payload
| parse-regexp error, 'CouldNotExecuteQuery : ({[\w":\s,\-}]+)' as errorJson
| parse-json errorJson
| parse-regexp "__tag__:__path__", '\/var\/log\/([\w\_]+).LOG' as serviceName
| parse-regexp caller, '\w+/([\w\.]+):(\d+)' as fileName, fileNo
| project-rename serviceHost="__tag__:__hostname__"
| extend scheduleType = json_extract_scalar(schedule, '$.type')
| project httpCode, errorCode,errorMessage,requestID,fileName, fileNo, serviceHost,scheduleType, project</code></pre><ul><li>1 行:project 指令:从原始结果中保留 Payload、error、__tag__:__path__、caller 字段,舍弃其他字段,这些字段用于后续解析。</li><li>2 行:parse-json 指令:将 Payload 字符串展开为 JSON,第一层字段出现在结果中,包括 lastNotified、serviceUri、jobID 等。</li><li>3 行:project-away 指令:去除原始 Payload 字段。</li><li>4 行:parse-regexp 指令:按照 error 字段中的内容,解析其中的部分 JSON 内容,置于 errorJson 字段。</li><li>5 行:parse-json 指令:展开 errorJson 字段,得到 httpCode、errorCode、errorMessage 等字段。</li><li>6 行:parse-regexp 指令:通过正则表达式解析出 <strong>tag__:__path</strong> 种的文件名,并命名为 serviceName。</li><li>7 行:parse-regexp 指令:通过正则表达式捕获组解析出 caller 种的文件名与行数,并置于 fileName、fileNo 字段。</li><li>8 行:project-rename 指令:将 <strong>tag__:__hostname</strong> 字段重命名为serviceHost。</li><li>9 行:extend 指令:使用 json_extract_scalar 函数,提取 schedule 中的 type 字段,并命名为 scheduleType。</li><li>10 行:project 指令:保留需要的字段列表,其中 project 字段来自于 Payload。</li></ul><h3>创建 SQL 作业</h3><p>在阿里云 Flink 控制台创建一个空白的 SQL 的流作业草稿,点击下一步,进入作业编写。</p><p><img src="/img/remote/1460000044705673" alt="图片" title="图片"></p><p>在作业草稿中输入如下创建临时表的语句:</p><pre><code>CREATE TEMPORARY TABLE sls_input_complex (
errorCode STRING,
errorMessage STRING,
fileName STRING,
fileNo STRING,
httpCode STRING,
requestID STRING,
scheduleType STRING,
serviceHost STRING,
project STRING,
proctime as PROCTIME()
) WITH (
'connector' = 'sls',
'endpoint' ='cn-beijing-intranet.log.aliyuncs.com',
'accessId' = '${ak}',
'accessKey' = '${sk}',
'starttime' = '2024-02-01 10:30:00',
'project' ='${project}',
'logstore' ='${logtore}',
'query' = '* | project Payload, error, "__tag__:__path__", "__tag__:__hostname__", caller | parse-json Payload | project-away Payload | parse-regexp error, ''CouldNotExecuteQuery : ({[\w":\s,\-}]+)'' as errorJson | parse-json errorJson | parse-regexp "__tag__:__path__", ''\/var\/log\/([\w\_]+).LOG'' as serviceName | parse-regexp caller, ''\w+/([\w\.]+):(\d+)'' as fileName, fileNo | project-rename serviceHost="__tag__:__hostname__" | extend scheduleType = json_extract_scalar(schedule, ''$.type'') | project httpCode, errorCode,errorMessage,requestID,fileName, fileNo, serviceHost,scheduleType,project'
);</code></pre><ul><li>其中 ${ak},${sk},${project},${logstore} 需要替换为有消费权限的 AK 账号。</li><li>query 字段,替换为上述 SPL,注意在阿里云 Flink 控制台需要对单引号使用单引号转义,并且消除换行符。</li><li>SPL 最终得到的字段列表与 TABLE 中字段对应。</li></ul><h3>连续查询及效果</h3><p>在作业中输入分析语句,查看结果数据:</p><pre><code>SELECT * FROM sls_input_complex</code></pre><p>点击右上角调试按钮,进行调试,可以看到 TABLE 中每一列的值,对应 SPL 处理后的结果。</p><p><img src="/img/remote/1460000044705674" alt="图片" title="图片"></p><h2>总结</h2><p>为了适应弱结构化日志数据的需求,Flink SLS Connector 进行了升级,支持直接通过 Connector配置 SPL 的方式实现 SLS 数据源的清洗下推,特别是需要正则字段提取、JSON 字段提取、CSV 字段提取场景下,相较原数据加工方案和原 Flink SLS Connector 方案更轻量级,让数据清洗的职责更加清晰,在数据源端完成数据清洗工作,也可以减少数据的网络传输流量,使得到达 Flink 的数据已经是规整好的数据,可以更加专注在 Flink 中进行业务数据分析。</p><p>同时为了便于 SPL 验证测试,SLS 扫描查询也已支持使用 SPL 进行查询,可以实时看到 SPL 管道式语法执行结果。</p><p><strong>参考链接:</strong></p><p>[1] 日志服务概述</p><p><a href="https://link.segmentfault.com/?enc=DP0WJBmEFpPhmQHqseTehA%3D%3D.DYvEJa5elVQFvepJae%2F6rSVrrZdi49EalULetmZi1dSAoGzvPLyZjhrbJrTTjIB4ov7BItenvIjAGbIrvpHnwBxzMR%2FBfUm%2FvxMt7cczZoQ%3D" rel="nofollow">https://help.aliyun.com/zh/sls/product-overview/what-is-log-s...</a></p><p>[2] SPL 概述</p><p><a href="https://link.segmentfault.com/?enc=EAS1qXwgVNMF5MP%2F14d5Ww%3D%3D.Y703SNIL8ZdmbKkXvk9PVs2yhYNJNHolr7t9yQR68BRoc%2FQl%2FFW8F%2BGj%2BWdxLSA5h1iq53gtHFqpfmfmvQpqmQ%3D%3D" rel="nofollow">https://help.aliyun.com/zh/sls/user-guide/spl-overview</a></p><p>[3] 阿里云 Flink Connector SLS</p><p><a href="https://link.segmentfault.com/?enc=Pmx9JV%2FR00DPVubk%2FUrVDg%3D%3D.y4NC7mOMR5W%2BSaaiBagQ2y8LaxcOmw3gCJtZTIqRcNsG6V9aMfCkNucAJlZ%2FjqjOZH5piTp5JlUuWTGDMMhh3wKtN%2F0A7bKG7aIY2wjH6AA%3D" rel="nofollow">https://help.aliyun.com/zh/flink/developer-reference/log-serv...</a></p><p>[4] SLS 扫描查询</p><p><a href="https://link.segmentfault.com/?enc=s8QDiGRbFhYZARwk0c%2Byxw%3D%3D.EnG7DMiQLz1NTqZQ1sQDaSEibzGSuPqLO7kuqBUSMSaYikpdQBQqBfyfowNwqupMaWn9TWaQWBNUNkQFcTC%2BNuQ%2FVIDpT8XZdDSwBo7WXbg%3D" rel="nofollow">https://help.aliyun.com/zh/sls/user-guide/scan-based-query-ov...</a></p><p>作者:潘伟龙(豁朗)</p><p><strong><a href="https://link.segmentfault.com/?enc=J7Pi%2B3oJ%2BcnJFczTFTQtcQ%3D%3D.NNAMQQt8ThUMUTxAO%2BQUWibLv0n4PdWpfLb7WVoSsKwc1qECNzocO6VchkU9SEuFoaKWN1fZsQEBqmOilr2ZFHYEOkzAmZs%2FB3hb2vYeV6s%3D" rel="nofollow">原文链接</a></strong></p><p><strong>本文为阿里云原创内容,未经允许不得转载。</strong></p>
青团社:亿级灵活用工平台的云原生架构实践
https://segmentfault.com/a/1190000044704682
2024-03-12T14:04:04+08:00
2024-03-12T14:04:04+08:00
阿里云云栖号
https://segmentfault.com/u/aliyunqi
0
<p>青团社是国内领先的一站式灵活用工招聘服务企业,灵活用工行业的 Top1。青团社于 2013 年在杭州成立,业务已经覆盖全国,在行业深耕 10 年。我的分享将分为以下三部分:</p><ul><li>青团社架构演进的历程</li><li>青团社如何实现云原生</li><li>总结与展望</li></ul><h2>01 云原生架构的演进历程</h2><p>2020 年,我们的技术架构比较薄弱,存在较多问题。面对这些问题,团队开始了架构演进,存在的问题主要是以下多个方面。</p><p><img src="/img/remote/1460000044704684" alt="图片" title="图片"></p><p>第一,运维能力和可观测性比较差,因为公司大部分都是业务研发人员,专业的 DBA 和运维都没有。</p><p>第二,在业务刚刚开始起步时,业务迭代速度非常快,每天都会有很频繁的发布,线上经常因为发布导致一些稳定性的问题,作为平台型公司连接 B 端和 C 端两端,对线上可用性要求非常高,但早期的架构设计也不太合理,所以很多时候应用是无法支持高可用的。</p><p>第三,因为线上的资源部署不太合理,比较浪费资源,资源成本较高。</p><p>第四,部署模式比较粗放,日志、告警都没有,所以出了问题之后排查非常困难,研发人员通常需要很长时间才能把这些问题弄清楚,响应时间比较长,相信大部分初创型公司在业务早期发展的阶段都存在这种问题。</p><p>那我们如何去应对这些挑战呢?答案就是使用云原生架构来重塑架构体系,不断地对架构进行演进,选择合适的技术栈,配合使用云的基础设施,来构建业务平台,让系统达到好的水准。</p><p>从下图中可以看到,青团社的业务架构演变遵循从单体架构到 SOA 架构再到微服务。基础架构物理机是没有的,团队从 2014 年开始就直接使用阿里云 ECS,在 2021 年开始容器化,最终到达期望的云原生架构形态。</p><p><img src="/img/remote/1460000044704685" alt="图片" title="图片"></p><p>云原生基金会官方对云原生的定义是 5 部分,第一是容器化,第二是不可变基础设施,第三个是声明式 API,然后是服务网格和微服务,其中微服务作为承载业务应用的核心,围绕这个,会有像调度编排、流量管理、可观测、DevOps 这些领域的一些能力,这是技术架构要做的事情。</p><p>从技术角度看,云原生架构是基于云原生技术的一组架构原则和一些设计模式的组合,将应用中的非核心的业务逻辑剥离出去,然后下沉到云原生基础设施这一层来统一处理,这样业务开发人员只需要关心自己的业务开发,让我们的业务应用变得更加轻量,高效。</p><p><img src="/img/remote/1460000044704686" alt="图片" title="图片"></p><p>因为公司是 2013 年成立的,早期的业务非常简单,运维能力也比较差,所以单体架构是优选。经过四五年的发展,业务有了长足的进步,平台的功能和模块都已经比较多了,因此,就升级到 Spring Cloud 微服务架构。当时用的是一套标准的用法,比如服务注册中心、配置中心用的是 Eureka,网关用的是 Spring Cloud Gateway。</p><p><img src="/img/remote/1460000044704687" alt="图片" title="图片"></p><p>此时,虽然实现了微服务架构,但也存在诸多问题,例如服务不稳定、排查效率低下、资源利用率低等。基于这些问题,开始做业务容器化改造。</p><p>首先,选用成熟的 K8s 平台去做业务容器平台,先解决部署与排查问题。 一开始我们选型的是阿里云容器服务 ACK Serverless 版,主要是看中了它开箱即用,不需要额外去维护,比较简单的优点。在使用的过程中,主要是先在开发侧去验证它,用了一段时间到 2021 年的时候,就完成了线上的迁移</p><p>之后选用阿里云 ACK 的技术底座去完成线上容器化改造的原因是,当时在用 Serverless 过程中出现一些问题,比如调度比较慢等,在当时我们是没有这些能力去解决的。改造之后,大概是 300 多个微服务。此外,还涉及到一些基础架构的改造,比如服务注册中心,我们原先用的是 Eureka,后来迁移到 MSE 的 Nacos 里,配置中心使用了 MSE Nacos,来提升性能和稳定性。</p><p>在可观测性和应用性的架构上,开始用阿里云应用实时监控服务 ARMS 的应用监控能力和 MSE 产品来对应用服务进行性能观测与流量治理,这些都是在 2021 年这一年去完成的。</p><p>2021 年 8 月,我们将 Spring Cloud Gateway 进行了迁移,因为当时 Spring Cloud Gateway 的问题比较多,性能也比较差,所以就基于开源做了自己的 API 网关,再结合 MSE 的微服务套件,实现了流量管理。2022 年之后,开始做业务指标监控和稳定性建设这方面的工作。</p><h2>02 青团社云原生架构实践</h2><p>接下来是实践的部分,这张图是线上的部署图。</p><p><img src="/img/remote/1460000044704688" alt="图片" title="图片"></p><p>前面这 4 个部分都是技术接入层,如 BGP 高防、WAF、BFF 等,主要提供基础的安全防护和路由转发功能。到了虚线这一部分是 K8s 集群,是基于 ACK 构建的容器运行平台,我们所有的业务容器都运行在 ACK 里面。</p><p>大家可以看到,我们运用了很多阿里云的中间件服务,比如 Kafka、RocketMQ。这些都是在使用 MSE 微服务引擎之后最新的一版架构,由于我们人手有限,所以为了线上的服务稳定性和降低运维成本,会直接用阿里云的这些云产品。网关方面,微服务内部的东西向流量主要由微服务引擎 MSE 来做流量管理,它给我们提供了一些能力,比如服务优雅上线下线,流量灰度,还有同可用区域这些部署能力。</p><p>接下来,我们将从调度编排、流量管理、可观测 3 个维度展开我们的实践。</p><h3>1.云原生架构实践调度编排</h3><p><img src="/img/remote/1460000044704689" alt="图片" title="图片"></p><p>第一部分是调度编排方面,我们有三个手段。首先是使用阿里云 ACK 作为技术底座来构建容器平台,再配合资源隔离的部署模式,保证多条业务线互不影响,因为我们有两条不同的业务线,所以无论是在成本核算还是服务稳定性,都会做到资源隔离。弹性伸缩方面是通过一些弹性伸缩策略取得成本和稳定性之间的平衡,降成本的同时不能损失稳定性。</p><p>接下来,通过两个案例阐述一下,第一是我们怎么样用 ACK 来实现高效弹性部署。</p><p><img src="/img/remote/1460000044704690" alt="图片" title="图片"></p><p>首先,在部署的时候是多可用区的,有杭州 H 区和 K 区,这是两个主可用区,所有的服务在部署的时候,在 K8s 的节点分隔上和调度策略上加一些标记,让它能够把业务负载给打散,这样一个服务有两个实例的话就是 K 区和 H 区各一个,一个挂了另一个还是好的。</p><p>在发布阶段,因为滚动更新是 K8s 内置的机制,可以通过简单的配一些健康检查的机制来得到好的发布体验,保证服务在发布的过程中不会出现业务受损。通过资源监控和业务容器监控,可以灵活伸缩业务容器的规模。节点池设计是 ACK 独有的,它相当于能为不同的业务线配专属节点,这样就可以达到物理隔离,有了节点池,要去做集群的弹性伸缩容的时候就非常方便,集群资源不够时可以通过简单的通过节点池的扩容操作,瞬间把节点池资源能力提升上去。</p><p>CSI 插件主要是用在开发测试环境。我们为了节省成本,很多开发测试环境,像中间件都是用容器自建的,容器自建属于有状态应用,有状态应用需要存储来支持它。CSI 插件,阿里云提供了很多对应的对接,比如阿里云的云盘 OSS、NAS 等。我们主要是用云盘插件来对接,把云盘挂到容器里,这样像数据库、Redis 等就可以得到稳定高效的存储。</p><p>VPC 方面,因为 ACK 里 VPC 网络是直通的,我们用的是阿里云的 Terway 插件,这个插件可以把容器内部的网络和我们的 VPC 互相打通,这个能力我们觉得比较重要,是因为没有上容器平台之前,我们的服务都是部署在 ECS 机器上的,现在如果要迁进去,我们的服务发现组件它在集群之外,就必然要让网络能够互通,否则它发现不了也就无法迁移了,所以 VPC 直通功能对我们是非常有用的。</p><p>另外还有集群监控,主要是体现在 ACK 提供了开箱即用的集群,借助与 ACK 深度集成的可观测监控 Prometheus 版,对 K8s 集群和业务容器轻松构建资源监控体系。一方面,可以及时了解容器运行情况和集群运行情况,另一方面,这些集群监控的技术指标可以作为我们判断系统是否需要扩容缩容的数据依据。通过部署基于指标或者是事件的弹性深度机制,能够快速对容器进行扩容。</p><p>以上这些使用场景,大部分公司应该都是类似的,可以总结一点:通过容器化来部署,充分运用云的能力,降低应用成本,保障应用高可用。这是第一个案例。</p><p>第二个案例是如何利用云来实现业务弹性。</p><p><img src="/img/remote/1460000044704691" alt="图片" title="图片"></p><p>这里有三个小的业务场景,第一是埋点,第二个是广告投放,第三个是热点活动。</p><p>埋点大家应该都不陌生,每个互联网公司都会需要埋点,通过埋点数据来了解用户,分析用户。埋点数据作为分析用户行为的数据资源,在整个产品的生命周期里面都非常重要。但是埋点数据的量通常都是非常巨大的,用户每一次点击,页面的曝光,还有用户的交互都会产生很多埋点数据。这些数据可以上传到后台去分析产品的使用情况,分析用户的行为和使用习惯,还可以延伸出做用户画像,用户偏好及用户转化路径这一系列数据产品。</p><p>我们的埋点有很明显的潮汐特征,流量通常是早上七八点钟开始逐渐上升,到了中午十一点、下午两点到达一天的顶峰,然后再开始逐渐下降,到夜晚四五点钟的时候就达到一天中最低,埋点数据量的规模也遵循这样的规律。</p><p>埋点数据,我们通常是先把数据发到后台,后台有埋点接收数据的处理程序,先简单的把它处理一下,然后给它丢到 Kafka 里,再由大数据的一个平台的组件去消费,消费完之后存储进去。</p><p>我们的大数据团队会通过埋点数据来构建不同的数据层,供不同的业务场景使用,在部署埋点接收程序的时候,就会充分考虑埋点流量的潮汐特征,去把它做一些定时扩容缩容的机制,比如可以加一些定时任务,早上九点、十点开始扩容扩一倍,就可以应对一天的流量高峰,到晚上再把它缩回去。</p><p>广告投放方面也很重要。我们平台也和很多互联网平台有广告投放的合作。在他们平台里面去投放广告吸引新用户。作为一项日常的运营工作,投放的时间点可能不太固定,它的效果也不一定能按照预期来,有时候出现爆点,流量就可能会被打爆。同时,伴随流量而来的一些点击数据或埋点数据都会剧增。</p><p>为了做好日常广告投放的工作,我们做了基于指标和事件的动态扩缩容机制。如果是因为应用容器资源,比如 CPU 内存爆了或者是达到了警戒线,又或者是处理数据的程序,有 MQ 消息积压的事件出现了之后,就去对事件进行监控,然后动态的去扩容。</p><p>我们用开源的 KEDA 工具配置业务指标进行监听,KEDA 工具通过监听 Prometheus 里面的指标(我们所有的指标都存在 Prometheus 里面),如果触发条件了之后会向 K8s 的 API server 发起一个 Pod 的扩容请求,这样就完成了扩容操作,整个过程都是自动化的。</p><p>最后的热点活动,类似于电商里面的促销活动,这个场景的特点是它的开始时间和结束时间都是已经提前知道的,这样只需要配备提前扩容的程序就可以了,比如到体验活动开始前的半小时先把容器给扩上去,结束之后就缩回去,我们主要是基于指标和事件这两点来做弹性扩容。</p><h3>2.流量管理</h3><p>这部分主要分享一下怎么去对流量进行管理。我们主要分三个部分:网关、流量服务治理引擎 MSE、消息队列。</p><p>这里有两个案例,因为作为头部的灵活用工企业,我们有很多端,比如有 C 端,B端,有安卓平台,有 iOS 平台。各大互联网平台,像支付宝、抖音、快手、百度、QQ 等都有对应的投放、产品和小程序在上面。</p><p><img src="/img/remote/1460000044704692" alt="图片" title="图片"></p><p>行业上也主要聚焦于 8 大行业,像餐饮、物流、商超这些。在这种在多端口,多行业的场景下,我们的报名岗位在类目上,或者是端口上都有很多差异,无论展示逻辑还是流量分发的规则都是有差异的。我们通过 API 网关和 BFF 来实现流量编排和不同端口的差异化处理。</p><p>网关这块主要是把流量引进来,BFF 主要是适配各端,它自己可能需要独有的一些数据格式,然后再调用后端的数据返回去。在网关里, BFF 本身是作为后端服务存在的,流量先经过网关,再经过 BFF 后通过后端把数据返回去。BFF 具体的实践架构不再赘述,但在青团社是用这个模式来做多端口的适配。</p><p><img src="/img/remote/1460000044704693" alt="图片" title="图片"></p><p>第二个案例是基于事件驱动构建灵活响应系统,案例是我们灵工管家这个产品,该产品主要是提供一系列的管理服务,比如考勤、发薪,还有排班等服务,这些服务是企业用到的一些企业级服务。平台用户可以做到薪资日结,像很多兼职岗位,商家都是提供兼职日,你早上去上班打卡,然后下班打完卡,还没到你回家,工资就到账了,这个就职体验是非常好的。</p><p>这就是基于事件来驱动,下班打卡之后会触发下班打卡的事件,触发算工时、算薪资的逻辑,再到提前到账,整个流程是全部事件驱动的,快的话可能几秒钟你的薪资就能到账,这也是灵工管家的比较好的一个产品卖点。当然消息 MQ 的场景是很常见的消息解耦,但我们还有别的场景,我们把 MQ 用在数据同步和消息分发上。数据同步用了一些插件和组件做一些数据同步的工作, MQ可以给它做一个缓冲,避免数据很多,一下子把对端给打爆了。消息分发的话,我们消息平台会有一些定时需要触发的定时消息,比如给用户发推送短信,我们会利用 MQ 的延迟消息能力去做,相当于到点之后,你就去触发这一消息,然后给用户发短信,发 push,这是一个具体的案例。</p><p><img src="/img/remote/1460000044704694" alt="图片" title="图片"></p><p>下面的案例介绍一下怎么实现灰度。早期我们没有灰度,所有的服务只要一上线,就相当于是全量状态,没法去验证服务到底对用户有多大影响。在 2021 年完成业务容器化改造之后,我们就引入了 MSE 微服务引擎来帮助我们实现全链路的灰度。</p><p>所谓全链路,指的是在流量链路这一层,网关进来之后到服务再到数据库,或者到经过消息中间件的这个链路。还有一个就是消息方面,要对流量的特征进行打标,然后链路的下一跳可能也需要打标,标识一下它要去到哪里。网关要负责南北流量的分发,在外部,我们通过开源的 APISIX 网关,它是有流量分拆插件的,可以在发布的时候,通过部署多个版本,在发布的时候,部署两个版本或者或多个版本,叫 deployment。部署完了之后,再给它打标,然后网关上面会有个流量分拆插件,你可以配一些特征,然后让流量进到指定的版本。</p><p>进来之后,这里面东西向的流量就属于 MSE 微服务引擎来做的事情。它通过 agent 插装的方式,把整个链路给串起来,实现了整个链路的灰度。</p><p>比如说像 HTTP 请求,它可以在请求头上加 gray 标识,然后依次透传到底层去。到消息中间件这一块,它对 MQ 这块做一些增强,相当于是埋点一样,把这些流量的灰度标记埋进去。然后在消费端做一下控制,这样就可以保证你的流量能按照你预定的规则顺利的进来。</p><p>重要的线上服务要发布的时候,先走一下灰度,可以明显的增强我们的信心。原先没有灰度的情况下,发布的时候都是很忐忑的,一般白天不敢发,都是夜晚才发,就是为了防止故障,因为你如果有问题的话,可能会影响很多用户。现在我们已经有 7300 万用户了,虽然说日活不是很高,但月活也有 1000 多万,所以说白天的流量还是非常大的。通过灰度发布,有问题的话在灰度阶段就能发现把它解决掉。</p><p><img src="/img/remote/1460000044704695" alt="图片" title="图片"></p><p>下面的案例是使用微服务引擎实现优雅上下线,这个能力也比较重要。因为早期很多线上故障都是因为发布导致的,经常在发布中发现很多服务调不通了,是因为它在下线过程中,但调用方这边不知道还去请求,就会报错。因此,在 2021 年,我们用微服务引擎 MSE 把服务期间不平滑的问题解决了。</p><p>优雅下线的原理其实非常简单,比如说服务提供者,我们称为 provider,他如果发了新的实例,当然流程还跟以前 K8s 滚动更新机制是一样的。他先滚动更新一个新版本的过程中,会触发老版本的下线动作,老版本下线动作就会执行 pre stop 钩子函数,这个函数是 K8s 提供了内置的机制,这个函数里 MSE 会提供一个接口,通过调用这个接口,让 MSE 的 agent 感知到服务要下线了,赶紧触发下线的事件。</p><p>事件触发之后,它的调用方可以感受到事件,然后在自己本地的 ribbon 服务列表缓存里面把 IP 给摘掉,摘掉之后,后面的请求就不再调用了,相当于我知道你要下线就把你提前摘掉,不调用就不会报错了。</p><p>服务上线的原理也差不多,上线之前先延迟一会儿,先不那么快到注册中心,而是放一点点流量进来,这个节奏是通过 K8s 健康检查机制来实现的。MSE 提供健康检查的接口,它会通过接口去向 K8s 暴露服务到底有没有准备就绪。现在没有准备就绪,流量就不能全部放进,可以放一点点,比如百分之零点几的流量进来,我先把服务预热一下,该建立的链接先建立起来,等到服务完全就绪之后,再把流量放进来,这样无论是下线还是上线,服务都是处于相对平稳的状态,下线调用端提前知道的话就不会再调用了。上线是先给你一段时间,让你先准备好,准备好之后,我再把流量放进来,这是优雅上线的原理。</p><h3>3.可观测和监控</h3><p>接下来我讲一下可观测的实践,可观测主要用到阿里云 ARMS 应用监控 + Prometheus + Grafana 以及云监控这个组合。</p><p><img src="/img/remote/1460000044704696" alt="图片" title="图片"></p><p>这个图就是用阿里云的云监控进行基础资源监控,如 ECS、云数据库 PolarDB、云消息队列,这些基础监控都有些对应的指标。</p><p>那如果要进行更精细、全面的指标监控,阿里云也提供 Prometheus 指标监控能力,它会把你的指标放到 Prometheus 里面,利用预置模板快速构建告警体系的同时,也可以通过自己的业务需求去配置相应的自定义告警规则。</p><p>第二个是应用实时监控服务 ARMS,作为一个具备诸多监控模块的云原生可观测平台,我们用其中的应用监控来解决 Java 应用性能的监控问题,我们的应用在线上跑的时候可能会突然发现有几个请求报错,或者是响应极慢,那研发人员要要怎么去排查呢?</p><p>通过 ARMS 应用监控去观测整个调用链路,及时发现整个链路到底哪一环节执行的比较慢。通过耗时数看得到,看得到之后定位一下的问题,比如说像这个实例里面,这是高德的三方接口比较慢,因为三方接口耗时确实是不可控的,这种问题我们可以提前知道,还有一些超时、异常问题,这些都可以通过 ARMS 应用监控发现,当然也可以配相应的一些告警规则。</p><p><img src="/img/remote/1460000044704697" alt="图片" title="图片"></p><p>除了云基础设施以及应用性能,我们希望进一步对业务指标进行监控,实现全栈可观测。针对业务指标监控,我们主要是用 Prometheus 和 Grafana 来进行加工与呈现。这里有两个案例,一个案例是基于业务指标,也就是消息中心的监控大盘,这里面的所有的数据都是通过 Java 端用 Prometheus 的客户端把指标数据暴露出来,然后 Prometheus 服务端把这些数据采集上来,再给它配成这种图表。</p><p><img src="/img/remote/1460000044704698" alt="图片" title="图片"></p><p>配成图表之后就可以可视化了,能看到现在的业务运行状况,这个曲线和两个图例应该都是实际的业务运营状况,有了这些数据,就有了监控告警的条件,没有这些东西就不知道业务到底运行怎么样。</p><p><img src="/img/remote/1460000044704699" alt="图片" title="图片"></p><p>然后日志告警中心这部分,像一些严重的日志报错,Error 日志这些比较重要的日志报错,我们会配对应的一些告警规则,在出现问题的时候进行及时告警。</p><p>经过这么多年业务发展,我们的业务一直是在云上不断的发展和壮大,充分用了云的各项能力来构建平台。我们主要考虑的是成本,稳定性和研发效率这三块,希望能达到平衡。因为我们团队本身也比较小,所以用云的优势是非常明显的,可以利用云的弹性有效应对日益剧增的业务增长规模。云原生之路我们还将继续,在此先汇报我们的成果。</p><p><img src="/img/remote/1460000044704700" alt="图片" title="图片"></p><p>通过容器化部署,提高部署密度的方式,把原先的 ECS 成本降低了 50%,因为原先 ECS 部署的比较粗放,可能一台机器上只部署一两个或者两三个服务。通过容器化的部署,可以提高部署密度。</p><p>第二个是应用实现了高可用和弹性调度,使我们可以从容的应对未来的业务增长。</p><p>第三个是通过全面实施基础资源、应用服务及业务监控,快速了解系统运行状态。过去,系统运行状况对我们来说是一个黑盒。即使有一部分数据,也无法有效的对不同类型数据进行加工与利用,一切都是未知。通过这些能力,从无到有的建设,我们现在可以非常快速的去了解、观测系统的状态。</p><p>第四个成果是运维成本大幅降低,把机器给省下去了,像一些人工需要做的事情,现在通过高度的自动化可以实现大规模的集群管理。</p><h2>03 总结与展望</h2><p>展望未来,可能会更多的考虑这以下三个方向,这些也是我们未来要做的事情。</p><ul><li>我们现在比较关心的服务网格,因为以后也会有更多语言,像一些应用比如说 Java、Python、Go 这些,MSE 目前可能对 Java 的支持非常好,后面我们也会探索基于服务网格的通用的流量治理能力。</li><li>因为 Java 占我们整个应用的体量大概是 80%,后续会考虑用一些新的技术,比如用 GraaLVM native 来实现原生镜像部署,这样可以进一步降低应用的资源占用情况,提高应用的响应峰值性能。</li><li>通过混沌工程的实施,进一步提高线上的稳定性。目前我们的稳定性可能还没有达到理想的目标,这是后面的努力方向。</li></ul><p>作者:杨磊</p><p><strong><a href="https://link.segmentfault.com/?enc=WCDUcuka3y4NKQPj%2F318FA%3D%3D.ub%2FRwInRxukiuPOOF4cC2v%2B9BcBf%2B6weJlakIKCNmtioYLXGEdc2eFEEv0l7cTItB3fa68Tt183GCKa5Ro4UTfoClkV1s7htuKUbvjlX0wE%3D" rel="nofollow">原文链接</a></strong></p><p><strong>本文为阿里云原创内容,未经允许不得转载。</strong></p>
你好,iLogtail 2.0!
https://segmentfault.com/a/1190000044701558
2024-03-11T16:32:26+08:00
2024-03-11T16:32:26+08:00
阿里云云栖号
https://segmentfault.com/u/aliyunqi
0
<h2>01 概述</h2><p>随着可观测数据采集需求的不断推陈出新,多样化的数据输入输出选项、个性化的数据处理能力组合、以及高性能的数据处理吞吐能力已经成为顶流可观测数据采集器的必备条件。然而,由于历史原因,现有的 iLogtail 架构和采集配置结构已经无法继续满足上述需求,逐渐成为制约 iLogtail 继续向前快速演进的瓶颈:</p><p>▶︎ iLogtail 设计之初完全面向文件日志采集至日志服务的场景:</p><p>1)简单地将日志分为多种格式,每种格式的日志仅支持一种处理方式(如正则解析、Json 解析等);</p><p>2)功能实现与日志服务相关概念(如 Logstore 等)强绑定;基于此设计思想,现有的 iLogtail 架构偏向于单体架构,导致模块间耦合严重,可扩展性和普适性较差,难以提供多个处理流程级联的能力。</p><p>▶︎ Golang 插件系统的引入极大地扩展了 iLogtail 的输入输出通道,且一定程度提升了 iLogtail 的处理能力。然而,囿于 C++ 部分的实现,输入输出与处理模块间的组合能力仍然严重受限:</p><p>1)C++ 部分原生的高性能处理能力仍然仅限于采集日志文件并投递至日志服务的场景使用;</p><p>2)C++ 部分的处理能力无法与插件系统的处理能力相结合,二者只能选其一,从而降低了复杂日志处理场景的性能。</p><p>▶︎ 与 iLogtail 整体架构类似,现有的 iLogtail 采集配置结构也采用平铺结构,缺乏处理流水线的概念,无法表达处理流程级联的语义。</p><p>基于上述原因,在 iLogtail 诞生 10 周年之际,日志服务启动对 iLogtail 的升级改造,寄希望于让 iLogtail 的易用性更佳,性能更优,可扩展性更强,从而更好地服务广大用户。</p><p>目前,经过半年多的重构与优化,iLogtail 2.0 已经呼之欲出。接下来,就让我们来抢先了解一下 iLogtail 2.0 的新特性吧!</p><h2>02 新特性</h2><h3>(一)【商业版】采集配置全面升级流水线结构</h3><p>为了解决旧版采集配置平铺结构无法表达复杂采集行为的问题,iLogtail 2.0 全面拥抱新版流水线配置,即每一个配置对应一条处理流水线,包括输入模块、处理模块和输出模块,每个模块由若干个插件组成,各模块的插件功能如下:</p><ul><li>输入插件:用于从指定输入源获取数据(各插件具体功能详见输入插件[1])</li><li>处理插件:用于对日志进行解析和处理(各插件具体功能详见处理插件[2]),可进一步分为原生处理插件和扩展处理插件</li><li>原生处理插件:性能较优,适用于大部分业务场景,推荐优先使用</li><li>扩展处理插件:功能覆盖更广,但性能劣于原生处理插件,建议仅在原生处理插件无法完成全部处理需求时使用</li><li>输出插件:用于将处理后的数据发送至指定的存储</li></ul><p>我们可以用一个 JSON 对象来表示一个流水线配置:</p><p><img src="/img/remote/1460000044701560" alt="图片" title="图片"></p><p>其中,inputs、processors 和 flushers 即代表输入、处理和输出模块,列表中的每一个元素 {...} 即代表一个插件;global 代表流水线的一些配置。有关流水线配置结构的具体信息,可参见 iLogtail 流水线配置结构[3]。</p><blockquote>示例:采集 /var/log 目录下的 test.log,对日志进行 json 解析后发送到日志服务。以下是实现该采集需求对应的旧版和新版配置,可以看到新版配置十分精炼,执行的操作一目了然。<br>旧版配置:</blockquote><pre><code>{
"configName": "test-config",
"inputType": "file",
"inputDetail": {
"topicFormat": "none",
"priority": 0,
"logPath": "/var/log",
"filePattern": "test.log",
"maxDepth": 0,
"tailExisted": false,
"fileEncoding": "utf8",
"logBeginRegex": ".*",
"dockerFile": false,
"dockerIncludeLabel": {},
"dockerExcludeLabel": {},
"dockerIncludeEnv": {},
"dockerExcludeEnv": {},
"preserve": true,
"preserveDepth": 1,
"delaySkipBytes": 0,
"delayAlarmBytes": 0,
"logType": "json_log",
"timeKey": "",
"timeFormat": "",
"adjustTimezone": false,
"logTimezone": "",
"filterRegex": [],
"filterKey": [],
"discardNonUtf8": false,
"sensitive_keys": [],
"mergeType": "topic",
"sendRateExpire": 0,
"maxSendRate": -1,
"localStorage": true
},
"outputType": "LogService",
"outputDetail": {
"logstoreName": "test_logstore"
}
}</code></pre><blockquote>新版流水线配置:</blockquote><pre><code>{
"configName": "test-config",
"inputs": [
{
"Type": "file_log",
"FilePaths": "/var/log/test.log"
}
],
"processors": [
{
"Type": "processor_parse_json_native"
"SourceKey": "content"
}
],
"flushers": [
{
"Type": "flusher_sls",
"Logstore": "test_logstore"
}
]
}</code></pre><blockquote>如果在执行 json 解析后需要进一步处理,在流水线配置中只需额外增加一个处理插件即可,但是在旧版配置中已经无法表达上述需求。</blockquote><p>有关新版流水线配置和旧版配置的兼容性问题,请参见文末兼容性说明板块。</p><h4>全新 API</h4><p>为了支持流水线配置,同时区分旧版配置结构,我们提供了全新的用于管理流水线配置的 API 接口,包括:</p><ul><li>CreateLogtailPipelineConfig</li><li>UpdateCreateLogtailPipelineConfig</li><li>GetLogtailPipelineConfig</li><li>DeleteLogtailPipelineConfig</li><li>ListLogtailPipelineConfig</li></ul><p>有关这些接口的详细信息,请参见 OpenAPI 文档[4]。</p><h4>全新控制台界面</h4><p>与流水线采集配置结构相对应,前端控制台界面也进行了全新升级,分为了全局配置、输入配置、处理配置和输出配置。</p><p><img src="/img/remote/1460000044701561" alt="图片" title="图片"></p><p>与旧版控制台界面相比,新版控制台具有如下特点:参数内聚:某一功能相关的参数集中展示,避免了旧版控制台参数散落各处出现漏配置。</p><blockquote>示例:最大目录监控深度与日志路径中的**密切相关,旧版界面中,二者分隔较远,容易遗忘;在新版界面中,二者在一起,便于理解。<br>旧版控制台:</blockquote><p><img src="/img/remote/1460000044701562" alt="图片" title="图片"></p><blockquote>新版控制台:</blockquote><p><img src="/img/remote/1460000044701563" alt="图片" title="图片"></p><p>所有参数均为有效参数:在旧版控制台中,启用插件处理后,部分控制台参数会失效,从而引起不必要的误解。新版控制台所有参数均为有效参数。</p><h4>全新 CRD</h4><p>同样,与新版采集配置对应,K8s 场景中与采集配置对应的 CRD 资源也全新升级。与旧版 CRD 相比,新版 CRD 具有如下特点:</p><ul><li>支持新版流水线采集配置</li><li>CRD 类型调整为 Cluster 级别,且将 CRD 名称直接作为采集配置名称,避免同一集群多个不同的 CRD 资源指向同一个采集配置引起冲突</li><li>对所有操作的结果进行定义,避免出现多次操作旧版 CRD 后出现的行为未定义情况</li></ul><pre><code>apiVersion: log.alibabacloud.com/v1alpha1
kind: ClusterAliyunLogConfig
metadata:
name: test-config
spec:
project:
name: test-project
logstore:
name: test-logstore
machineGroup:
name: test-machine_group
config:
inputs:
- Type: input_file
FilePaths:
- /var/log/test.log
processors:
- Type: processor_parse_json_native
SourceKey: content</code></pre><h3>(二)处理插件组合更加灵活</h3><p>对于文本日志采集场景,当您的日志较为复杂需要多次解析时,您是否在为只能使用扩展处理插件而困惑?是否为因此带来的性能损失和各种不一致问题而烦恼?</p><p>升级 iLogtail 2.0,以上问题都将成为过去!</p><p>iLogtail 2.0 的处理流水线支持全新级联模式,和 1.x 系列相比,有以下能力升级:</p><ul><li>原生处理插件可任意组合:原有原生处理插件间的依赖限制不复存在,您可以随意组合原生处理插件以满足您的处理需求。</li><li>原生处理插件和扩展处理插件可同时使用:对于复杂日志解析场景,如果仅用原生处理插件无法满足处理需求,您可进一步添加扩展处理插件进行处理。</li></ul><p>注意:扩展处理插件只能出现在所有的原生处理插件之后,不能出现在任何原生处理插件之前。</p><blockquote>示例:假如您的文本日志为如下内容:<br>{"time": "2024-01-22T14:00:00.745074", "level": "warning", "module": "box", "detail": "127.0.0.1 GET 200"}<br>您需要将 time、level 和 module 字段解析出来,同时还需要将 detail 字段做进一步正则解析,拆分出 ip、method 和 status 字段,最后丢弃 drop 字段,则您可以按顺序使用“Json 解析原生处理插件”、“正则解析原生处理插件”和“丢弃字段扩展处理插件”完成相关需求:<br>【商业版】</blockquote><p><img src="/img/remote/1460000044701564" alt="图片" title="图片"></p><p><img src="/img/remote/1460000044701565" alt="图片" title="图片"></p><p>【开源版】</p><pre><code>{
"configName": "test-config"
"inputs": [...],
"processors": [
{
"Type": "processor_parse_json_native",
"SourceKey": "content"
},
{
"Type": "processor_parse_regex_native",
"SourceKey": "detail",
"Regex": "(\\S)+\\s(\\S)+\\s(.*)",
"Keys": [
"ip",
"method",
"status"
]
}
{
"Type": "processor_drop",
"DropKeys": [
"module"
]
}
],
"flushers": [...]
}</code></pre><p>采集结果如下:</p><p><img src="/img/remote/1460000044701566" alt="图片" title="图片"></p><h3>(三)新增 SPL 处理模式</h3><p>除了使用处理插件组合来处理日志,iLogtail 2.0 还新增了 SPL(SLS Processing Language)处理模式,即使用日志服务提供的用于统一查询、端上处理、数据加工等的语法,来实现端上的数据处理。使用 SPL 处理模式的优势在于:</p><ul><li>拥有丰富的工具和函数:支持多级管道操作,内置功能丰富的算子和函数</li><li>上手难度低:低代码,简单易学</li><li>【商业版】统一语法:一个语言玩转日志采集、查询、加工和消费</li></ul><p><img src="/img/remote/1460000044701567" alt="图片" title="图片"></p><h4>SPL 语法</h4><p>整体结构:</p><ul><li>指令式语句,支持结构化数据和非结构化数据统一处理</li><li>管道符(|)引导的探索式语法,复杂逻辑编排简便</li></ul><pre><code>{
"configName": "test-config"
"inputs": [...],
"processors": [
{
"Type": "processor_parse_json_native",
"SourceKey": "content"
},
{
"Type": "processor_parse_regex_native",
"SourceKey": "detail",
"Regex": "(\\S)+\\s(\\S)+\\s(.*)",
"Keys": [
"ip",
"method",
"status"
]
}
{
"Type": "processor_drop",
"DropKeys": [
"module"
]
}
],
"flushers": [...]
}</code></pre><p>结构化数据 SQL 计算指令:</p><ul><li>where 通过 SQL 表达式计算结果产生新字段</li><li>extend 根据 SQL 表达式计算结果过滤数据条目</li></ul><pre><code>*
| extend latency=cast(latency as BIGINT)
| where status='200' AND latency>100</code></pre><p>非结构化数据提取指令:</p><ul><li>parse-regexp 提取指定字段中的正则表达式分组匹配信息</li><li>parse-json 提取指定字段中的第一层 JSON 信息</li><li>parse-csv 提取指定字段中的 CSV 格式信息</li></ul><pre><code>*
| project-csv -delim='^_^' content as time, body
| project-regexp body, '(\S+)\s+(\w+)' as msg, user</code></pre><h3>(四)日志解析控制更加精细</h3><p>对于原生解析类插件,iLogtail 2.0 提供了更精细的解析控制,包括如下参数:</p><ul><li>KeepingSourceWhenParseFail:解析失败时,是否保留原始字段。若不配置,默认不保留。</li><li>KeepingSourceWhenParseSucceed:解析成功时,是否保留原始字段。若不配置,默认不保留。</li><li>RenameSourceKey:当原始字段被保留时,用于存储原始字段的字段名。若不配置,默认不改名。</li></ul><p>示例:假设需要在日志字段内容解析失败时在日志中保留该字段,并重命名为 raw,则可配置如下参数:</p><ul><li>KeepingSourceWhenParseFail:true</li><li>RenameSourceKey:raw</li></ul><h3>(五)【商业版】日志时间解析支持纳秒级精度</h3><p>在 iLogtail 1.x 版本中,如果您需要提取日志时间字段到纳秒精度,日志服务只能在您的日志中额外添加“纳秒时间戳”字段。在 iLogtail 2.0 版本中,纳秒信息将直接附加至日志采集时间(__time__)而无需额外添加字段,不仅减少了不必要的日志存储空间,也为您在 SLS 控制台根据纳秒时间精度对日志进行排序提供方便。</p><p>如果需要在 iLogtail 2.0 中提取日志时间字段到纳秒精度,您需要首先配置时间解析原生处理插件,并在“源时间格式(SourceFormat)”的末尾添加“.%f”,然后在全局参数中增加"EnableTimestampNanosecond": true。</p><p>示例:假设日志中存在字段 time,其值为 2024-01-23T14:00:00.745074,时区为东 8 区,现在需要解析该时间至纳秒精度并将 <strong>time</strong> 置为该值。</p><p><img src="/img/remote/1460000044701568" alt="图片" title="图片"></p><p><img src="/img/remote/1460000044701569" alt="图片" title="图片"></p><p>采集结果如下:</p><p><img src="/img/remote/1460000044701570" alt="图片" title="图片"></p><p>注意:iLogtail 2.0 不再支持 1.x 版本中提取纳秒时间戳的方式,如果您在 1.x 版本中已经使用了提取纳秒时间戳功能,在升级 iLogtail 2.0 后,需要按照上述示例手动开启新版纳秒精度提取功能,详细信息参见文末兼容性说明。</p><h3>(六)【商业版】状态观测更加清晰</h3><p>相比于 iLogtail 1.x 暴露的简单指标,iLogtail 2.0 极大地完善了自身可观测性的建设:</p><ul><li>所有采集配置都有完整指标,可以在 Project/Logstore 等维度上进行不同采集配置的统计与比较</li><li>所有插件都有自己的指标,可以构建完整流水线的拓扑图,每个插件的状态可以进行清楚的观测</li><li>C++ 原生插件提供更加详细的指标,可以用来监控与优化插件的配置参数</li></ul><p><img src="/img/remote/1460000044701571" alt="图片" title="图片"></p><h3>(七)运行更快更安全</h3><p>iLogtail 2.0 支持 C++ 17 语法,C++ 编译器升级至 gcc 9,同时更新了 C++ 依赖库的版本,使得 iLogtail 的运行更快更安全。</p><p>表:iLogtail 2.0 单线程处理日志的性能(以单条日志长度 1KB 为例)</p><p><img width="692" height="95" src="/img/bVdbI4C" alt="image.png" title="image.png"></p><h2>03 兼容性说明</h2><h3>(一)采集配置</h3><h4>商业版</h4><ul><li>新版流水线采集配置是完全向前兼容旧版采集配置的,因此:</li><li>在您升级 iLogtail 至 2.0 版本的过程中,日志服务会在下发配置时自动将您的旧版配置转换为新版流水线配置,您无需执行任何额外操作。您可以通过 GetLogtailPipelineConfig 接口直接获取旧版配置对应的新版流水线配置</li><li>旧版采集配置并不完全向后兼容新配流水线配置</li><li>如果流水线配置描述的采集处理能力可用旧版配置表达,则该流水线配置依然可以被 iLogtail 0.x 和 1.x 版本使用,日志服务会在向 iLogtail 下发配置时自动将新版流水线配置转换为旧版配置</li><li>反之,该流水线配置会被 iLogtail 0.x 和 1.x 版本忽略</li></ul><h4>开源版</h4><p>新版采集配置与旧版采集配置存在少量不兼容情况,详见 iLogtail 2.0 版本采集配置不兼容变更说明[5]。</p><h3>(二)iLogtail 客户端</h3><ol><li>使用扩展处理插件时的 Tag 存储位置</li></ol><p>当您使用扩展插件处理日志时,iLogtail 1.x 版本由于实现原因会将部分 tag 存放在日志的普通字段中,从而为您后续在 SLS 控制台使用查询、搜索和消费等功能时带来诸多不便。为了解决这一问题,iLogtail 2.0 将默认将所有 tag 归位,如果您仍希望保持 1.x 版本行为,您可以在配置的全局参数中增加"UsingOldContentTag": true。</p><ul><li>对于通过旧版控制台界面和旧版 API 创建的采集配置,在您升级 iLogtail 2.0 后,tag 的存储位置仍然与 1.x 版本一致;</li><li>对于通过新版控制台界面和新版 API 创建的采集配置,在您升级 iLogtail 2.0 后,tag 的存储位置将默认归位。</li></ul><ol start="2"><li>高精度日志时间提取</li></ol><p>2.0 版本不再支持 1.x 版本的 PreciseTimestampKey 和 PreciseTimestampUnit 参数,当您升级 iLogtail 2.0 版本后,原有纳秒时间戳提取功能将失效,如果您仍需解析纳秒精度时间戳,您需要参照日志时间解析支持纳秒精度板块对配置进行手动更新。</p><ol start="3"><li>飞天格式日志微秒时间戳时区调整</li></ol><p>2.0 版本的飞天解析原生处理插件将不再支持 1.x 版本的 AdjustingMicroTimezone 参数,默认微秒时间戳也会根据配置的时区进行正确的时区调整。</p><ol start="4"><li>日志解析控制</li></ol><p>对于原生解析类插件,除了日志解析控制更加精细板块中提到的 3 个参数,还存在 CopyingRawLog 参数,该参数仅在 KeepingSourceWhenParseFail 和 KeepingSourceWhenParseSucceed 都为 true 时有效,它将在日志解析失败时,在日志中额外增加 <strong>raw_log</strong> 字段,字段内容为解析失败的内容。</p><p>该参数的存在是为了兼容旧版配置,当您升级 iLogtail 2.0 版本后,建议您及时删去该参数以减少不必要的重复日志上传。</p><h2>总结</h2><p>为用户提供更舒适便捷的用户体验一直是日志服务的宗旨。相比于 iLogtail 1.x 时代,iLogtail 2.0 的变化是比较明显的,但这些转变只是 iLogtail 迈向现代可观测数据采集器的序曲。我们强烈建议您在条件允许的情况下尝试 iLogtail 2.0,也许您在转换之初会有些许的不适应,但我们相信,您很快会被 iLogtail 2.0 更强大的功能和更出色的性能所吸引。</p><h3>相关链接:</h3><p>[1] 输入插件</p><p><a href="https://link.segmentfault.com/?enc=6txHyZd%2FwtMDH4KeqXI3hw%3D%3D.ye6SkKvhCUIOvbK5anVMSFVW81wk1leAcy5XVZuO2ls%2BoqM8nFKXDBRxL0T0WM9LObB5tERKGXBwgOzpQSiHf%2BsUMiPeoJT0HpU1Hhk%2FZUw6paOFy67ZFOisK9SEHc7Z" rel="nofollow">https://help.aliyun.com/zh/sls/user-guide/overview-19?spm=a2c...</a></p><p>[2] 处理插件</p><p><a href="https://link.segmentfault.com/?enc=85gAaNtRJarZK1pVp598kg%3D%3D.DyAza3OW0cVMmFWbYXzpAs7vBR601FYKdtujPaho%2BOy6eFCWkKZU2P%2BhsWIgHR%2B1f9gP3norSwLHGQitSWOo6kO3re3DC49jNr6QPRvXm1qwVygm8YV3t10tGJgfLuMu" rel="nofollow">https://help.aliyun.com/zh/sls/user-guide/overview-22?spm=a2c...</a></p><p>[3] iLogtail 流水线配置结构</p><p><a href="https://link.segmentfault.com/?enc=xFXBaQYFBsrjmM4moxDmFA%3D%3D.sE4DRhJcZ4074SZnf%2F6BI5e9dvBlNMaUjUpAG9gjXFLgcDcnypAaTfgAfndSWe28E79OEjH3I9CLq9bHPY7UYpMXW9YpfmblUw1BF2Dc8KkJMyDsqG23gsHIb1M3es6Ojcb%2BeETOnxZG36C%2BzNsod28YlDvZRnzBkxOXKToyLDs%3D" rel="nofollow">https://next.api.aliyun.com/struct/Sls/2020-12-30/LogtailPipe...</a></p><p>[4] OpenAPI 文档</p><p><a href="https://link.segmentfault.com/?enc=Zu19NHcPFQbtgrC%2FuLJ0HA%3D%3D.Y%2FbyP%2FONEfp2Z7HcDKyAzfP%2B1UWLA%2FdyRxrZ8eVPXNntgTtCZ%2Fqv%2Fh%2FuMaMCJB%2BzfiInewTc%2Bhqj1TItjBNeSgAJab3xpv1dXB%2BrC2qU7nxIhAB4GwNJyaw%2BlVQ3IaiSnOqSx9otP5y7PJBFgpycZg0cThtqMX46a8cHm0OyoWBCOVSQcZ1xCoaQnhB%2BSXrr" rel="nofollow">https://next.api.aliyun.com/document/Sls/2020-12-30/CreateLog...</a></p><p>[5] iLogtail 2.0 版本采集配置不兼容变更说明</p><p><a href="https://link.segmentfault.com/?enc=o%2BDBs5cTowq9EaQfONlRcQ%3D%3D.7XJ8Vd32QMdAeIx6EEIPZZqUtUlZA8YhybC7VE%2FB7dOK2wpw4L303DIzBSL7iBrdGYVzoBDiexNDMW060q3BvQ%3D%3D" rel="nofollow">https://github.com/alibaba/ilogtail/discussions/1294</a></p><p>作者:张浩翔(笃敏)</p><p><strong><a href="https://link.segmentfault.com/?enc=BKIa4KTSnvSZHHTp1GPbIQ%3D%3D.KtGKqhLKSM%2BOiMFePkmRUx52KbHJu9c%2BqDJufPJ0oIJjOQNG5dTyUAKOfKctGJJjgWoc6yiNxgoeYALPMKJ309tFak23HxLrjR8gqPhD%2BmI%3D" rel="nofollow">原文链接</a></strong></p><p><strong>本文为阿里云原创内容,未经允许不得转载。</strong></p>
需求并行开发场景,如何高效发布
https://segmentfault.com/a/1190000044694638
2024-03-08T15:36:32+08:00
2024-03-08T15:36:32+08:00
阿里云云栖号
https://segmentfault.com/u/aliyunqi
0
<h2>1.适用场景</h2><p>微服务架构下,每个应用服务独立开发、独立发布,小步快跑,持续快速交付业务需求。多人协同开发同一个应用时,分支开发模式是一个适合的协同方案。该模式下一个需求或任务通常对应一个 feature 分支,多个需求一起合并到 release 分支进行集成测试验证并发布。</p><p>该场景下,你是否有这样的苦恼?</p><ul><li>一个需求没有经过集成测试验证,却被发布上线了,最终因为“漏测”导致生产故障!</li><li>一个需求经过了集成测试验证,但是临发布前发现有严重问题,但需求无法灵活“下车”,最终导致本次发布的所有需求都被延期了!</li></ul><h2>2.云效解决方案</h2><p><img src="/img/remote/1460000044694640" alt="图片" title="图片"></p><p>云效应用交付平台 AppStack 提供变更持续交付解决方案,涉及核心概念如下:</p><ul><li>应用:一个软件的最小发布单元,聚合代码、环境、版本等软件资产,以及研发流程定义。最小发布单元意味着无法解耦的一个或者多个服务的组合,这个服务组合会通过一个流程进行统一交付。</li><li>变更:变更是对应用的一次特性改变(引入新的特性或改变已有特性),源于需求,终于交付。通常一个需求或任务对应一个变更,对应一个 feature 分支。</li><li>研发流程:应用完成一次变更的过程和约束,包括开发、测试、发布上线的完整流程,由多个阶段的多条流水线承载,依次在不同环境进行测试、构建、部署,最终审批通过后发布生产环境。</li></ul><p><img src="/img/remote/1460000044694641" alt="图片" title="图片"></p><p>云效通过应用定义、变更承载需求、研发流程约束发布规范,来解决以下两个问题:</p><ul><li>问题1:当其中一个 feature 分支没有经过测试验证时,怎么“阻止”它发布到生产环境避免漏测引起故障?</li><li>问题2:当其中一个 feature 分支做了测试验证,但是发现有严重问题,怎样可以“退出”本次发布而不影响其他需求正常发布?</li></ul><h2>3.云效操作实践</h2><p>以下实践,以一个spring-boot应用的“图书馆管理系统”为例,开发“图书借阅功能”、“图书归还功能”、“图书到期续借功能”三个需求,一起发布上线。</p><h3>3.1 前提条件</h3><p>已有一个应用 spring-boot,配置好应用代码、研发流程(CI/CD流水线)、环境等。通常一个应用的研发流程可以分为测试阶段、预发阶段、生产阶段:</p><ul><li>测试阶段:由Java单元测试、Java代码扫描、构建、部署测试环境等步骤组成。用于日常测试验证。</li><li>预发阶段:由构建、部署预发环境等步骤组成。用于预发布验证。</li><li>生产阶段:由构建、生产发布审批(人工卡点)、部署生产环境、合并主干、关闭变更等步骤组成。</li></ul><p>1.配置准入规则为:「测试阶段-执行结果」等于「成功」,「预发阶段-执行结果」等于「成功」,避免没有经过预发验证的分支直接进入生产阶段。<br>2.生产发布审批通过后,部署生产环境。<br>3.生产环境部署验证通过后,表明本次发布成功,可以将发布release 分支合并回主干 master,并自动关闭相关变更。</p><p><img src="/img/remote/1460000044694642" alt="图片" title="图片"></p><h3>3.2 需求开发测试</h3><p>“需求1:图书借阅功能”、“需求2:图书归还功能”、“需求3:图书到期续借功能”三个需求分别分配给开发小张、小明、小强开发。</p><h4>第1步,为一个需求新建一个变更拉一个 feature 分支</h4><p>小张创建一个变更「变更1-实现图书借阅功能」,选择新建分支输入 feature001,则可自动为该需求拉取一个分支。依次类推,小明创建一个变更「变更2-实现图书归还功能」,自动新建分支feature002。小强创建一个变更「变更3-实现到期续借功能」,自动新建分支feature003。</p><p><img src="/img/remote/1460000044694643" alt="图片" title="图片"></p><h4>第2步,开发代码提交到 feature 分支</h4><p>小张开发好图书借阅相关代码后,提交代码到feature001上,小明开发图书归还相关代码后,提交代码到feature002分支上。</p><h4>第3步,选择变更集成,部署测试环境验证</h4><p>小张和小明,一借一还,需要一起部署到测试环境进行联调验证。进入应用研发流程页,选择变更1和变更2一起集成测试,云效会自动将 feature001 和 feature002 合并到自动生成的 release/xxx_n 分支,使用该 release 分支做构建,并部署环境。环境部署成功即可进行测试验证。</p><p><img src="/img/remote/1460000044694644" alt="图片" title="图片"></p><p><img src="/img/remote/1460000044694645" alt="图片" title="图片"></p><h4>第4步,提交变更进行预发布</h4><p>测试环境验证通过,进入「预发阶段」,选择变更1和变更2进行集成,勾选自动合并上一阶段集成的分支,会自动生成新的 release/xxx_m 集成分支,自动合并上一阶段 feature001、feature002、release/xxx_n 分支,使用新的 release/xxx_m 分支构建并部署预发环境。预发部署成功后即可进行预发验证。</p><p><img src="/img/remote/1460000044694646" alt="图片" title="图片"></p><p><img src="/img/remote/1460000044694647" alt="图片" title="图片"></p><h3>3.3 需求发布上线</h3><p>提交变更,需求自动化发布到生产环境</p><p>预发验证通过后,即可进入生成发布阶段。选择待发布的变更1和变更2,运行生产流水线,发布审批通过后,即可部署生产环境。生产环境部署完成,可配置自动关闭变更,并将发布 release/xxx_k 分支合并入主干 master,至此即完成了一次完整的需求发布上线。</p><p>未经过预发验证的需求禁止发布,避免“漏测”</p><p>此时若在生产阶段选择变更1、变更2、变更3一起发布,则经过变更准入卡点时会校验失败,因为变更3没有在测试环境部署验证过,即保证了没有经过测试验证的需求不可发布。</p><p><img src="/img/remote/1460000044694648" alt="图片" title="图片"></p><p>需求临时“下车”,退出发布窗口,不影响其他需求发布</p><p>临发布前,变更3因没有测试验证通过,不满足发布条件,团队本次决定图书续借功能不上线,只上线变更1和变更2,则可再次运行预发阶段流水线,将变更3踢出集成区,退出本次发布。</p><p><img src="/img/remote/1460000044694649" alt="图片" title="图片"></p><h2>4.总结语</h2><p>至此,本方案完成了从应用配置、到需求开发、多变更(需求)集成测试、发布上线的完整流程,满足了变更分支自动创建、变更分支自动合并集成测试、发布准入卡点控制等诉求,避免因为“漏测”带来的生产故障,也避免因为其中一个需求未达到发布条件延期所有需求。</p><p><strong><a href="https://link.segmentfault.com/?enc=wabkj%2B3cly%2BIP%2B4NDZOWgQ%3D%3D.%2BZV66iJta79zxRXhpWb9dwWeVkP0aVpdOZioSaRMfCMxCAUnrlKe1E2OLlgo0SjIHCPAigu5%2B9rEBz5aEfc6OFeqnUNzqea6yIwLzND0rVs%3D" rel="nofollow">原文链接</a></strong></p><p><strong>本文为阿里云原创内容,未经允许不得转载。</strong></p>
阿里云连续两年斩获全球存储顶会FAST最佳论文
https://segmentfault.com/a/1190000044694309
2024-03-08T14:34:53+08:00
2024-03-08T14:34:53+08:00
阿里云云栖号
https://segmentfault.com/u/aliyunqi
0
<p><img src="/img/remote/1460000044694311" alt="图片" title="图片"></p><p>$$
(阿里云块存储团队论文获 FAST 2024最佳论文)
$$</p><p>FAST全称为Conference on File and Storage Technologies,创办于2002年,是由美国高等计算系统协会(USENIX)和美国计算机学会操作系统专业组织(ACM SIGOPS)联合组织的聚焦存储领域的顶级国际会议,代表了计算机存储领域的国际最高水平。创办二十多年来,FAST 推动了如软硬件结合、RAID、闪存文件系统、非易失内存技术和分布式存储等多项存储相关技术的发展。</p><p>本次的最佳论文来自阿里云存储团队,详细阐述了过去十余年阿里云弹性块存储(EBS)的架构演变。为应对用户需求和硬件发展,块存储三代系统架构设计焦点从最初的简单可用性,转变到第二代架构的高性能和低成本,演进到第三代架构的对 IO执行效能极致优化,实现了阿里云企业级块存储ESSD百微秒级平均延迟和毫秒级长尾延迟,单块云盘达到百万IOPS和4GiB/s 吞吐,有力支撑数据库、搜索和推荐等众多性能敏感型业务。基于高速非易失性内存,阿里云块存储进一步推出ESSD PL-X产品,单块云盘可提供30 微秒平均延迟,高达三百万IOPS和12GiB/s吞吐,为用户提供更极致的存储性能。</p><p><img src="/img/remote/1460000044694312" alt="图片" title="图片"></p><p>$$
(阿里云技术专家张伟东在FAST 2024上介绍阿里云存储技术)
$$</p><blockquote>作为阿里云存储的关键技术成果之一,本文将对这篇论文进行深度解读。<br>论文全称:《What’s the Story in EBS Glory: Evolutions and Lessons in Building Cloud Block Store》</blockquote><h2>01 十二年磨一剑:三代架构演进,打造高性能、低成本的块存储!</h2><p>过去的 12 年间,阿里云块存储一共演进了三代架构,每一代架构升级都给用户提供了更高的性能和更低的成本,同时我们通过不断优化高可用的架构设计,为块存储的稳定性保驾护航。</p><ul><li>简单易部署的初代架构</li></ul><p><img src="/img/remote/1460000044694313" alt="图片" title="图片"></p><p>初代架构采用计算存储分离的架构。以简单易部署为目标。</p><p>计算节点中我们部署了客户端(BlockClient),用户虚拟机(VM)中的盘(VD)通过 BlockClient 向后端存储集群发送读写请求。计算节点中的单用户云盘在后端集群中被分配给一个独立的块存储服务器(BlockServer),负责进一步以多副本形式转发到不同 Chunk 存储服务器(ChunkServer)中以实现数据的容灾。</p><p>初代架构在 IO 路径上采用了 多对一映射(云盘到存储服务器)和 原地更新(In-place Update)的设计。一个用户的云盘同一时间只会被一个 BlockServer 服务,每个 BlockServer 同时服务多个云盘。同时,BlockServer 通过将用户云盘的地址空间线性划分为相同大小的 Chunk(通常为 64 MiB 大小),通过 ChunkServer 以 Ext4 文件的形式存储在 HDD 中。对云盘地址空间中每个数据块的更改,BlockServer 直接将请求转发到对应 3 副本的 ChunkServer,由 ChunkServer 直接修改文件。</p><p>初代架构设计的选择促进了业务的快速上线,然而在性能和成本方面有所局限。多对一映射意味着盘的热点可能集中在存储集群的单节点中,性能也受到单节点的制约。原地更新方式使得数据压缩和纠删编码的部署难度变大,因为它们会改变数据块的大小,数据在压缩和纠删过后,无法以原地更新的方式再次写入。</p><ul><li>高性能、低成本的第二代架构!</li></ul><p><img src="/img/remote/1460000044694314" alt="图片" title="图片"></p><p>第二代系统架构基于初代架构进行了大幅度创新,通过地址空间分段、采用日志结构以及部署压缩和纠删编码技术,极大提高了盘的性能并降低了存储成本。</p><p>从二代开始,块存储的业务逻辑与文件管理逻辑分开,文件管理逻辑由 盘古分布式文件系统 进行管理,并成为阿里云多项存储业务(EBS,OSS,OTS 等)的底座。在块存储业务中,我们采用了全闪存(SSD)集群,并设计了闪存友好的系统架构。</p><p>第二代架构首先采用了地址分段设计(Disk Segmentation Design),每个用户的盘逻辑地址空间被线性划分为多个连续的SegmentGroup(通常为数百 GiB),包含多个Segment(代表数十 GiB 的地址空间)。SegmentGroup的地址空间到Segment的地址空间映射类似于RAID0,以提高读写并行度。采用地址分段后,BlockServer以Segment为粒度管理用户的盘。至此实现了用户盘更高的性能可扩展性,提高更高的性能。</p><p>进一步,第二代架构采用了日志结构设计(Log-Structured Design),盘古文件系统提供了可供追加写的文件类型,BlockServer 得以不以就地更新的方式去写数据,而是采用追加写的方式。用户的写首先经由地址分段设计机制映射到唯一的Segment上,由BlockClient发送到对应的 BlockServer。BlockServer将由BlockClient来的请求转换为追加写的请求,并维护类似 LSM-tree 结构作为索引。</p><p>为提供更便宜的块存储服务给用户,基于日志结构设计,第二代架构部署了压缩(Compression)和纠删编码(Erasure Coding)。通过后台转储服务,第二代架构得以将数据利用后端计算资源从三副本转换为压缩和纠删编码格式。同时,BlockServer 在数据写入时无需感知存量数据的位置,用户的服务完全不受影响。</p><p>第二代架构大幅提升了单盘性能并实现了成本的降低。基于第二代架构,阿里云块存储推出ESSD云盘,实现1百万 IOPS, 4GiB/s 吞吐,100us平均延迟的高性能企业级产品。然而,随着硬件架构的不断发展,SSD每 GB 价格的不断下降,块存储的成本逐渐从空间敏感型转向了流量敏感型。因此,第二代架构带来的流量放大已不可忽视。对于每个写请求,BlockServer由于不采用数据压缩/纠删编码技术,仍然以三副本形式写入到盘古中。在后台进行转储时,数据需要再次从盘古读取并以压缩和纠删编码形式重新写入。部署数据表明,该架构的流量放大高达 4.69 倍,这成为了限制成本继续降低的又一瓶颈。</p><ul><li>极致 IO 效能的第三代架构</li></ul><p><img src="/img/remote/1460000044694315" alt="图片" title="图片"></p><p>第三代系统架构基于第二代架构继续创新,通过引入融合写入引擎,进一步降低了流量的放大系数。同时,第三代架构卸载数据压缩到 FPGA 中,进一步降低 CPU 开销,实现极致的 IO 效能。</p><p>第三代架构引入了名为融合写入引擎的设计,并在用户的写路径上实现了在线的数据压缩和纠删编码。在融合写入引擎的设计下,不同用户的写请求数据,先由BlockServer先聚合到名为 JournalFile 的文件,然后持久化到盘古中。</p><p>这一设计的核心巧妙之处在于,将不同的低流量用户的写入在时间上聚合,从而使得在短时间内可以聚集得到压缩和纠删编码所需要的数据量(压缩单元和纠删编码单元通常需要数十KiB,而单个Segment的流量较小,通常不能在低延迟的场景下积累起足够多的数据量)。通过在用户的写路径上在线使用压缩和纠删编码技术,流量放大得到显著下降。</p><p>更进一步,BlockServer会在内存中以Segment为粒度积累每个用户的写请求数据,然后当数据量达到一定量时(通常为数MiB),BlockServer通过后台的Dump操作将数据以压缩纠删编码格式的 DataFile 持久化到盘古中。通过在聚合和Dump操作中都使用数据压缩和纠删编码,第三代架构的流量放大得以大幅下降。部署数据显示,流量放大相较第二代架构下降了66%。</p><p>JournalFile和DataFile虽然形式上都经过压缩和纠删编码,但其数据本身和用途却有很大差别。一方面,JournalFile中混合了来自不同用户和不同 Segment 的数据,因此JournalFile在大部分时间内是不会被读取的,除非BlockServer发生故障。另一方面,DataFile主要用来服务用户的读请求。因为DataFile是以Segment为粒度存储数据,因此在处理用户读请求时,从DataFile中读取数据的开销远小于从 JournalFile 读取。</p><p>通过融合写入引擎,BlockServer在用户写路径上实现了在线的数据压缩和纠删编码,但这些计算操作带来了额外开销。例如,使用CPU压缩一个 16 KiB的数据块,延迟将增加25us。 这一开销在平均延迟为100us的ESSD云盘中是不可接受的。</p><p>基于此,为避免在线数据压缩带来的额外延迟,我们将数据压缩卸载到定制的FPGA中。我们在FPGA中实现了一个调度器来将数据块拆分为固定大小的(例如,4 KiB)片段,并且利用多个执行单元并行地执行这些片段的 压缩/解压缩 任务。为确保数据完整性,我们在数据压缩链路中实现了端到端的CRC检查。在FPGA返回压缩数据后,BlockServer会立即解压数据,并通过 CRC 检查来验证数据完整性。</p><h2>02 高可用架构助力块存储平稳运行</h2><p>伴随着十二年高速发展,阿里云块存储不仅给用户带来高性能和低成本的块存储服务,也在生产过程中沉淀了丰富的高可用的架构设计。我们关注服务故障时的爆炸半径(即单一角色故障时影响的客户数目),并设计低爆炸半径的架构,来增强系统的稳定性。</p><ul><li>控制面:分组 BlockManager</li></ul><p>在第二代架构的最初设计中,控制面由三个部署在不同机器上的进程(BlockManager)组成。其中一个机器上的BlockManager作为主要角色服务单存储集群内所有的控制面请求。随着集群规模的扩大,单一节点需要管理的用户数目急剧增加,当该节点出现故障时,受到影响的用户数会增加。</p><p><img src="/img/remote/1460000044694316" alt="图片" title="图片"></p><p>$$
(分组 BlockManager 的架构图)
$$</p><p>在这样的背景下,我们设计了分组架构的控制面(Federated BlockManager)。分组架构中,服务控制面请求的角色被分拆到多个机器上,每个机器管理一组分区(Partition),其中每个分区管理一小组用户的盘。</p><p>同时,我们引入了轻量级的中心管理角色(CentralManager)。CentralManager 负责管理BlockManager的状态,以及对Partition在BlockManager之间进行均衡调度,不参与用户关键路径。</p><p>在分组架构的设计下,单一机器宕机对用户的影响急剧减少。举例而言,对于在百台数量规模的集群,在最初设计中,一个控制面机器的宕机会影响 10 万级的用户。在分组架构下,通过在每一台机器上部署一个BlockManager,单机宕机影响的用户范围下降到数千级别。更进一步,通过创建更小粒度的Partition(通常为百盘级)来维护盘的元数据,宕机时元数据的恢复速度也得以提升。单一机器宕机,CentralManager可以在多个BlockManager上并行加载盘的元数据,显著提高控制面的可用性。</p><ul><li>数据面:逻辑故障域(Logical Failure Domain)</li></ul><p>数据平面由一个存储集群内的多个 BlockServer 组成,每个BlockServer同时服务数千个 Segment 并处理这些Segment的I/O请求。当一个BlockServer崩溃时,控制平面会将其服务的所有Segment迁移到集群中的其他BlockServer上,以便 I/O可以快速在其他BlockServer上恢复。</p><p>然而,这种机制可能导致故障在BlockServer间迅速传播并造成级联故障。具体来说,如果崩溃是由异常的Segment(例如,错误的代码实现)引起的,迁移后,BlockServer会再次崩溃。在这种情况下优化Segment调度以加快恢复速度可能会导致更多的BlockServer在短时间内崩溃,甚至导致整个集群的服务异常。</p><p>根据生产经验,我们得到了 3 个重要观察:</p><ul><li>故障通常源于单个云盘或Segment的请求,因此我们需要监Segment的状态而不是BlockServer。</li><li>故障的根本原因大多是软件错误(例如,代码Bug或错误的配置),因为硬件或机械故障不太可能使得故障随着Segment的迁移而扩散。由软件引起的故障可能需要大量的时间才能最终确定问题的罪魁祸首,更不用说构建自动恢复工具了。因此,更实际的方法是主动减少影响。</li><li>如果不加干预,级联故障可能会迅速传播到整个集群。作为一个分布式服务,我们可以容忍一些BlockServer服务异常,但是不能发生整个集群的宕机。</li></ul><p>基于这些观察,我们设计了逻辑故障域。其核心思想是通过将可疑Segment分配到一组特定的BlockServer中来隔离它们,以避免其他BlockServer甚至整个集群受到影响。我们首先将每个Segment与一个最大容量为 3 的唯一令牌桶关联起来。每次Segment被迁移到新的 BlockServer 都会消耗一个令牌,并且令牌每 30 分钟重新填充一次。当令牌桶为空时,Segment的任何迁移只能从 3 个预先指定的BlockServer中选择一个,称其为逻辑故障域。</p><p>Segment-level故障域可以有效地隔离异常的Segment。然而,如果存在多个异常的Segment(例如,来自一VD)甚至是异常的云盘,Segment-level故障域不足以防止多个级联故障同时发生。</p><p>我们的解决方案是将故障域合并为一个。具体来说,当存在多个Segment形成一个故障域时,我们选择第一个故障域作为全局故障域,以确保最多只有 3 个BlockServer被隔离用于级联故障,而不会降低集群容量。任何后续的具有空令牌桶的Segment都将共享同一个全局故障域。在部署逻辑故障域后,我们成功地防御了由Segment迁移引起的多次潜在的级联故障。</p><h2>03 结语</h2><p>目前,阿里云在分布式存储领域已积累了一系列创新实践,并发表于计算机系统领域顶级会议上,包括自研分布式存储系统底座盘古(FAST 2023),面向云原生的大规模文件系统(FAST 2023),基于叠瓦式磁盘高性能存储引擎(FAST 2023),高性能分布式键值存储系统(SIGMOD 2021)。</p><p><img src="/img/remote/1460000044694317" alt="图片" title="图片"></p><p>$$
(阿里云存储资深专家储道介绍阿里云盘古分布式存储系统论文)
$$</p><p>以外,在高性能存储网络方面,自研的高性能用户态协议栈(ATC 2023),自研的高性能 RDMA 存储网络(SIGCOMM 2022),HPCC 流控算法(SIGCOMM 2019),RDMA 网络的大规模实践和优化(NSDI 2021),引领了云存储进入微秒延迟时代。前不久,阿里云分布式存储技术还获了中国发明专利金奖。</p><p><img src="/img/remote/1460000044694318" alt="图片" title="图片"></p><p>$$
(阿里云分布式存储技术专利获中国专利金奖)
$$</p><p>目前,相关技术已广泛应用到阿里云统一存储平台盘古分布式存储中,并成为阿里云提供存储服务的基础升级方案。所支撑的存储服务已广泛应用于铁路12306、云上奥运会、电子社保卡、医保平台、数字政府、城市大脑、杭州亚运等重要工程,为全球数百万客户提供服务,累计服务超9亿人次。</p><p><strong><a href="https://link.segmentfault.com/?enc=GSwYY7QsYcjn7B8dGVtUbg%3D%3D.RPqY0sjOwA3QYGjrW9kIhhVsc3t0P4j%2FuT8W2LwZgSdfMj%2BthivwBGhbjFA53vHm2m8Nnl6RhfdND17ckfx9ezQ%2FtR7W%2BiLK0l3khjE9btg%3D" rel="nofollow">原文链接</a></strong></p><p><strong>本文为阿里云原创内容,未经允许不得转载。</strong></p>
AI 绘画平台难开发,难变现?试试 Stable Diffusion API Serverless 版解决方案
https://segmentfault.com/a/1190000044691549
2024-03-07T15:57:30+08:00
2024-03-07T15:57:30+08:00
阿里云云栖号
https://segmentfault.com/u/aliyunqi
0
<p>Stable Diffusion 模型,已经成为 AI 行业从传统深度学习时代走向 AIGC 时代的标志性里程碑。越来越多的开发者借助 stable-diffusion-webui(以下简称 SDWebUI)能力进行 AI 绘画领域创业或者业务上新,获得高流量及商业价值,但是面对多客户、高并发的复杂场景,使用原生 Stable Diffusion API 会面临以下挑战:</p><ol><li>显卡资源昂贵且难以购买,GPU 卡池管理技术门槛高:高性能的 GPU 资源不仅价格昂贵,而且往往难以大规模采购。此外,GPU 卡池的有效管理和维护需要复杂的技术支持,也带来了额外的挑战。</li><li>难以应对高并发:原生的 Stable Diffusion API 采用单实例推理模式,其并发处理能力有限。在面对高并发场景时,尤其是并发请求具有大的波动性时,资源配置难以精确预测,从而可能导致系统错误和业务中断。</li><li>多模型切换难度大:当不同模型的请求在高并发条件下同时发送到同一实例时,频繁的模型切换成为一个显著的瓶颈。这种切换不仅消耗巨大,而且影响了推理效率,使得多模型部署在实际应用中变得复杂和低效。</li></ol><p>为了帮助用户高效率、低成本应对企业级复杂场景,函数计算团队正式推出 Stable Diffusion API Serverless 版解决方案,通过使用该方案,用户可以充分利用 Stable Diffusion +Serverless 技术优势快速开发上线 AI 绘画应用,期待为广大开发者 AI 绘画创业及变现提供思路。</p><p>基于 Stable Diffusion API Serverless 版解决方案搭建的,部署 AI 艺术字应用活动火热进行中!生成姓氏头像赢新春好礼,欢迎点击“阅读原文”体验。</p><p>活动链接:<a href="https://link.segmentfault.com/?enc=Bzrs%2BujKANth5Fx3lnPAuQ%3D%3D.qjCzWN%2FWLKXYfzRz76UaYY9yhIEWZ5GI28VUlLgNT9EcQXxVcG7LWrYIrc0Fwy5T" rel="nofollow">https://developer.aliyun.com/topic/fcnewyear</a></p><h2>01 应用场景</h2><p>Stable Diffusion API Serverless 版本提供了多种可能性,以适应不同的应用场景和业务需求。</p><ol><li>个性化内容创作:利用 Stable Diffusion API,内容创作者和数字艺术家可以快速生成个性化的艺术作品和图像。例如,艺术家可以根据用户的描述或关键词,即时创作出独特的艺术风格图像,实现个性化的艺术创作和用户互动。</li><li>广告和市场营销:在广告和市场营销领域,Stable Diffusion API 可以用来生成吸引人的视觉内容,从而增强广告效果。例如,企业可以根据产品特性和目标受众的偏好,快速创建多样化的广告图像,以提升品牌形象和市场吸引力。</li><li>游戏和娱乐产业:在游戏和娱乐产业中,Stable Diffusion API 可以被用来增强用户体验,通过生成独特的游戏背景、角色和元素来丰富游戏世界。例如,游戏开发者可以使用 API 来设计独特的游戏环境和角色,为玩家提供更丰富和个性化的游戏体验。</li></ol><h2>02 方案优势</h2><p>Stable Diffusion API Serverless 版本在多方面提供了显著的优势,特别是在简化部署、成本效率、推理效率、资源管理、并发处理和用户体验上。以下是这些优势的具体体现:</p><ol><li>上手简单,快速部署:借助阿里云 Serverless 应用中心,用户可以实现快速部署,大幅简化传统 Stable Diffusion API 的复杂部署流程。这使得开发者能够快速上手并专注于应用的开发和创新。</li><li>计费灵活,成本效益显著:Serverless 版本提供按需计费模式,用户仅需为实际使用的资源付费,无需预先投资昂贵的硬件。这种灵活的计费方式大幅降低了总体成本,尤其适合资源需求波动的场景。</li><li>优化的模型管理,提升推理效率:通过优化多模型的管理和部署,Serverless 版本有效提高了推理效率。减少模型切换和加载的频率,确保了快速、稳定的推理性能。</li><li>自动扩缩容,高效资源管理:利用自动扩缩容机制,Serverless 版本根据实时需求灵活调整资源使用,避免了资源浪费并保障了服务的连续性。</li><li>异步处理和排队机制,优化并发处理:Serverless 版本通过引入异步处理和高效排队机制,克服了高并发场景下的挑战,保证了服务的高可用性和响应速度。</li></ol><p>总之,Stable Diffusion API Serverless 版本集成了阿里云 Serverless 技术的核心优势,提供了一种高效、成本有效且用户友好的解决方案,为开发者在 AI 绘画和其他 AI 应用领域的创新和商业化提供支持。</p><h3>方案架构图</h3><p><img src="/img/remote/1460000044691551" alt="图片" title="图片"></p><p>名词解释:</p><ul><li>admin,提供模型管理,包括模型上传+删除等</li><li>webui,提供界面化的调试功能,主要是模型和参数调整、插件安装等,达到更好出图效果</li><li>proxy,API 的前端服务,提供非推理之外的功能,主要包括结果、进度查询等</li><li>control,控制推理实例最大并发实例数。通过控制 control 的并发度,控制下游多函数推理服务的实例数</li><li>agent+sd-api,推理服务</li></ul><p>1.一个模型(checkpoints)创建一个函数,每个函数支持弹多个实例,总的实例数通过 control 并发度进行控制。<br>2.之所以一个模型(checkpoints)创建一个函数,是为了避免多模型并发推理使用场景下的模型间的频繁切换带来的开销,提升推理效率,进而达到给用户降本的效果<br>3.sd_ 开头的都是动态创建函数</p><p>注意事项:</p><ul><li>使用过程中会动态创建 sdapi 函数,每个 checkpoint 对应一个函数,并且会在 ots 中 function 表中记录对应的函数详情。如果想删除动态创建的函数,请清理对应 ots 中 function 表的函数记录,避免后续调用出问题</li><li>异步推理结果会默认存放到 oss 中,存放到 image/default 路径下</li></ul><h2>03 部署 Stable Diffusion API Serverless 版</h2><h3>准备工作</h3><p>开通云产品:</p><ul><li>函数计算 FC:用于提供 CPU+GPU 算力</li><li>对象存储 OSS:用于保存输出图片结果;同时存储请求中的中转图片,便面直接传递 base64 导致超出请求的 body 限制</li><li>表格存储 Tablestore:用于存储推理结果、函数信息等</li><li>文件存储 NAS:用于多节点共享存储空间</li></ul><h3>部署 Stable Diffusion Serverless API</h3><ol><li>进入函数计算 FC 3.0 控制台,点击左侧“应用”进行应用中心。如果老用户曾经创建过应用,点击“创建应用”也可直达应用中心</li></ol><p><img src="/img/remote/1460000044691553" alt="图片" title="图片"></p><ol start="2"><li>点击“人工智能”分类,选择“fc-stable-diffusion-v3”模版,点击“立即创建”</li></ol><p><img src="/img/remote/1460000044691554" alt="图片" title="图片"></p><ol start="3"><li>确定详细参数进行应用创建,您可以重点注意三个信息的填写,其他使用默认值即可。</li></ol><ul><li>地域:选择距离您较近的地区,如果后续有更多出图需要,可以考虑选择海外地区,以方便 hugging face 等网站的连接</li><li>命名空间:如果您已经部署多个 SD,请在这里进行区分,新用户可使用默认值</li><li>绘图类型:选择艺术字</li></ul><p><img src="/img/remote/1460000044691555" alt="图片" title="图片"></p><ol start="4"><li>首次使用需要额外的权限,可以根据提示“前往授权”</li></ol><p><img src="/img/remote/1460000044691556" alt="图片" title="图片"></p><p><img src="/img/remote/1460000044691557" alt="图片" title="图片"></p><ol start="5"><li>点击“创建应用”,勾选了解内容,点击“同意并继续部署”,等待大约 1 分钟</li></ol><p><img src="/img/remote/1460000044691558" alt="图片" title="图片"></p><p><img src="/img/remote/1460000044691559" alt="图片" title="图片"></p><ol start="6"><li>生成 WebUI 域名(注意保护此链接不外传以免耗费您账户的费用),不要点击链接,直接切换到右侧“Serverless API”</li></ol><p><img src="/img/remote/1460000044691560" alt="图片" title="图片"></p><ol start="7"><li>点击“Serverless API”点击“初始化 Serverless API”,再次确认已经开通“FC、OSS、OTS”三款产品,勾选“已阅读”点击“下一步”</li></ol><p><img src="/img/remote/1460000044691561" alt="图片" title="图片"></p><p><img src="/img/remote/1460000044691562" alt="图片" title="图片"></p><ol start="8"><li>进行“角色名”的授权,勾选“启用 Serverless API”,OTS 实例创建方式可以默认“自动创建”,确认后等待大约 30 秒</li></ol><p><img src="/img/remote/1460000044691563" alt="图片" title="图片"></p><ol start="9"><li>创建好 Serverless API,就可以参考下面 API 定义开始进行测试生产使用</li></ol><p><img src="/img/remote/1460000044691564" alt="图片" title="图片"></p><h2>04 Stable Diffusion API Serverless 版支持的 API 详情</h2><p>API 接口主要分两类:</p><ul><li>非推理类接口,用于结果和进度查询、模型管理、应用重启等</li><li>推理类接口,文生图、图生图、图片放大等</li></ul><p>具体可以参考: <a href="https://link.segmentfault.com/?enc=M5K16GJ%2B4LzmqkozMp5rnA%3D%3D.M3tYY4nC272BUy5%2Fr0GvIw65KXs2Kbw66k%2FHM%2F2BtFvVuGibMCQcT8oD%2Fk56T7OXzdPAbxfCmT6aOvQjejZTCznZygTGm3CBzWGalKJYU6Sgbm6lmiLKhSaLnf%2FOXMa7" rel="nofollow">https://github.com/devsapp/serverless-stable-diffusion-api/blob/main/api/api.yaml</a></p><h3>1.模型相关 API</h3><p>模型的注册、更新和删除都通过 admin 界面化操作即可</p><p><img src="/img/remote/1460000044691565" alt="图片" title="图片"></p><h4>1.1 获取模型列表 API</h4><p>GET /modelsresponse:</p><pre><code>[
{
"type": "stableDiffusion",
"name": "model_v1",
"ossPath": "/path/to/oss/model_v1",
"etag": "3f786850e387550fdab836ed7e6dc881de23001b",
"status": "loaded", // registering|loading|loaded|unloaded|deleted
"registeredTime": "2023-01-01T12:00:00Z",
"lastModificationTime": "2023-01-10T12:00:00Z"
}
]</code></pre><h3>2.推理相关 API</h3><p>支持文生图和图生图</p><p>支持同步模式和异步模式两种,默认同步模式</p><ul><li>同步模式:header 中添加 {"Request-Type":"sync"},不添加默认为同步模式</li><li>异步模式:header 中添加 {"Request-Type":"async"}</li></ul><p>推理结果会同步存储到 oss 和 ots 中,可以通过 /tasks/{taskId}/result 接口获取推理结果(oss 图片地址、推理参数等)</p><h4>2.1 txt2img</h4><p>POST /txt2img</p><p>request:其中 stable_diffusion_model, sd_vae 新加字段,其他保持跟原生 webui:txt2img 保持一致</p><p>其中 controlnet 中图片支持两种格式:</p><ul><li>图片的 base64 编码:备注:base64 请求存在超过 FC 异步请求 body 上限可能,如果超过上限请使用 oss 方式</li><li>oss 上图片路径,支持 png/jpg/jpeg</li></ul><pre><code>{
"stable_diffusion_model": "diffusion_v1", // sd主模型
"sd_vae": "vae_v1", // vae模型
"enable_hr": true,
"denoising_strength": 0.5,
"firstphase_width": 640,
"firstphase_height": 480,
"hr_scale": 2,
"hr_upscaler": "upscale_method_v1",
"hr_second_pass_steps": 10,
"hr_resize_x": 1280,
"hr_resize_y": 960,
"hr_sampler_name": "sampler_v1",
"hr_prompt": "High resolution prompt",
"hr_negative_prompt": "Negative high resolution prompt",
"prompt": "Mountain landscape during sunset",
"styles": [
"style1",
"style2"
],
"seed": 123456,
"subseed": 789,
"subseed_strength": 5,
"seed_resize_from_h": 480,
"seed_resize_from_w": 640,
"sampler_name": "sampler_v2",
"batch_size": 32,
"n_iter": 1000,
"steps": 100,
"cfg_scale": 1,
"width": 640,
"height": 480,
"restore_faces": true,
"tiling": false,
"do_not_save_samples": false,
"do_not_save_grid": false,
"negative_prompt": "Avoid mountains",
"eta": 5,
"s_min_uncond": 1,
"s_churn": 3,
"s_tmax": 10,
"s_tmin": 1,
"s_noise": 2,
"override_settings": {
"settingKey": "settingValue"
},
"override_settings_restore_afterwards": true,
"script_args": [
{
"argKey": "argValue"
}
],
"sampler_index": "index_v1",
"script_name": "script_v1",
"send_images": true,
"save_images": true,
"alwayson_scripts": {
"controlnet": {
"args": [
{
"image":"base64srcimg|image/default/xxxx.png", //支持传输base64和oss对应图片path(png/jpg/jpeg)
"enabled":True,
"module":"canny",
"model":"control_v11p_sd15_scribble",
"weight":1,
"resize_mode":"Crop and Resize",
"low_vram":False,
"processor_res":512,
"threshold_a":100,
"threshold_b":200,
"guidance_start":0,
"guidance_end":1,
"pixel_perfect":True,
"control_mode":"Balanced",
"input_mode":"simple",
"batch_images":"",
"output_dir":"",
"loopback":False
}
]
}
}
}</code></pre><p>response:</p><pre><code>{
"status":"succeeded", // 推理任务状态
"taskId":"1HmyrbhBJD", // 推理任务id, 后续结果获取,进度查询,取消推理都依赖于该id
"ossUrl" :["xxxxx"] // 同步模式下返回的oss上图片临时地址(有一定时效性)
}</code></pre><h4>2.2 img2img</h4><p>POST /img2img</p><p>request:其中 stable_diffusion_model,sd_vae 新加字段,其他保持跟原生 webui:img2img 保持一致</p><p>其中 controlnet 和 init_images 中图片支持两种格式:</p><ul><li>图片的 base64 编码:备注:base64 请求存在超过 FC 异步请求 body 上限可能,如果超过上限请使用 oss 方式</li><li>oss 上图片路径,支持 png/jpg/jpeg</li></ul><pre><code>{
"stable_diffusion_model": "diffusion_v2", // sd主模型
"sd_vae": "vae_v2", // vae模型
"init_images": [ //支持base64、oss图片地址两种格式
"Base64SrcImg|ossPath",
"Base64SrcImg|ossPath"
],
"resize_mode": 1,
"denoising_strength": 0.8,
"image_cfg_scale": 2,
"mask": "mask_path",
"mask_blur": 3,
"mask_blur_x": 2,
"mask_blur_y": 2,
"inpainting_fill": 4,
"inpaint_full_res": true,
"inpaint_full_res_padding": 2,
"inpainting_mask_invert": 0,
"initial_noise_multiplier": 5,
"prompt": "Forest landscape",
"styles": [
"styleA",
"styleB"
],
"seed": 654321,
"subseed": 987,
"subseed_strength": 6,
"seed_resize_from_h": 480,
"seed_resize_from_w": 640,
"sampler_name": "sampler_v3",
"batch_size": 64,
"n_iter": 500,
"steps": 50,
"cfg_scale": 2,
"width": 1280,
"height": 960,
"restore_faces": false,
"tiling": true,
"do_not_save_samples": false,
"do_not_save_grid": true,
"negative_prompt": "Avoid forests",
"eta": 6,
"s_min_uncond": 2,
"s_churn": 4,
"s_tmax": 11,
"s_tmin": 2,
"s_noise": 3,
"override_settings": {
"settingKeyV2": "settingValueV2"
},
"override_settings_restore_afterwards": false,
"script_args": [
"arg1",
"arg2"
],
"sampler_index": "index_v2",
"include_init_images": false,
"script_name": "script_v2",
"send_images": false,
"save_images": true,
"alwayson_scripts": {
"controlnet": {
"args": [
{
"image":"base64srcimg|ossPath", //支持base64、oss图片地址两种格式
"enabled":True,
"module":"canny",
"model":"control_v11p_sd15_scribble",
"weight":1,
"resize_mode":"Crop and Resize",
"low_vram":False,
"processor_res":512,
"threshold_a":100,
"threshold_b":200,
"guidance_start":0,
"guidance_end":1,
"pixel_perfect":True,
"control_mode":"Balanced",
"input_mode":"simple",
"batch_images":"",
"output_dir":"",
"loopback":False
}
]
}
}
}</code></pre><p>response:</p><pre><code>{
"status":"succeeded", // 推理任务状态
"taskId":"1HmyrbhBJD", // 推理任务id, 后续结果获取,进度查询,取消推理都依赖于该id
"ossUrl" :["xxxxx"] // 同步模式下返回的oss上图片临时地址(有一定时效性)
}</code></pre><h3>3.图片处理 API</h3><h4>3.1 图片放大</h4><p>图片放大,支持单张图片处理,暂不支持批量处理。respone 返回 taskId,调用获取结果接口获取图片地址即可</p><p>其中 image 支持两种格式:</p><ul><li>图片的 base64</li><li>oss 上图片路径,支持 png/jpg/jpeg</li></ul><p>POST /extra_images</p><p>request:</p><pre><code>{
"resize_mode": 0,
"show_extras_results": True,
"gfpgan_visibility": 0,
"codeformer_visibility": 0,
"codeformer_weight": 0,
"upscaling_resize": 4,
"upscaling_crop": True,
"upscaler_1": "Lanczos",
"upscaler_2": "None",
"extras_upscaler_2_visibility": 0,
"upscale_first": False,
"image":self.file_to_base64(),
"image" : "base64|ossPath" //支持传输base64和oss对应图片path(png/jpg/jpeg)
}</code></pre><p>response:</p><pre><code>{
"status":"succeeded",
"taskId":"TovRrc0Jnr",
"ossUrl" :["xxxxx"] // 同步模式下返回的oss上图片临时地址(有一定时效性)
}</code></pre><h3>4.结果相关 API</h3><h4>4.1 获取结果</h4><p>通过 taskid 获取推理结果</p><p>GET /tasks/{taskId}/result</p><p>response:</p><pre><code>{
"images":[
"images/admin/Xldf9m80im_1.png" // images 推理结果, oss图片path
],
"ossUrl" :["xxxxx"], oss上图片临时地址(有一定时效性)
"info":{ // info 推理过程中产生信息
"all_negative_prompts":[
""
],
"all_prompts":[
"cute beautiful blonde, very detailed, 21 years old, inoccent face, natural wave hair, blue eyes, high-res, masterpiece, best quality,intricate details, highly detailed,sharp focus, detailed skin,realistic skin texture,texture, detailed eyes lora:shuimobysimV3:1\u003e"
],
"all_seeds":[
3896184641
],
"all_subseeds":[
6579621
],
"alwayson_scripts":"",
"batch_size":1,
"cfg_scale":7,
"clip_skip":1,
"denoising_strength":0,
"do_not_save_grid":false,
"do_not_save_samples":false,
"enable_hr":false,
"eta":null,
"extra_generation_params":{
},
"face_restoration_model":null,
"firstphase_height":0,
"firstphase_width":0,
"height":512,
"hr_negative_prompt":"",
"hr_prompt":"",
"hr_resize_x":0,
"hr_resize_y":0,
"hr_sampler_name":null,
"hr_scale":2,
"hr_second_pass_steps":0,
"hr_upscaler":null,
"index_of_first_image":0,
"infotexts":[
"cute beautiful blonde, very detailed, 21 years old, inoccent face, natural wave hair, blue eyes, high-res, masterpiece, best quality,intricate details, highly detailed,sharp focus, detailed skin,realistic skin texture,texture, detailed eyes lora:shuimobysimV3:1\u003e\nSteps: 50, Sampler: Euler, CFG scale: 7.0, Seed: 3896184641, Size: 512x512, Model hash: 18ed2b6c48, Model: xxmix9realistic_v40, Denoising strength: 0, Version: v1.5.1"
],
"is_using_inpainting_conditioning":false,
"job_timestamp":"20230828073155",
"n_iter":1,
"negative_prompt":"",
"override_settings":{
},
"override_settings_restore_afterwards":true,
"prompt":"cute beautiful blonde, very detailed, 21 years old, inoccent face, natural wave hair, blue eyes, high-res, masterpiece, best quality,intricate details, highly detailed,sharp focus, detailed skin,realistic skin texture,texture, detailed eyes lora:shuimobysimV3:1\u003e",
"restore_faces":false,
"s_churn":0,
"s_min_uncond":0,
"s_noise":1,
"s_tmax":null,
"s_tmin":0,
"sampler_index":"Euler",
"sampler_name":"Euler",
"save_images":false,
"script_args":[
],
"script_name":null,
"sd_model_hash":"18ed2b6c48",
"seed":3896184641,
"seed_resize_from_h":-1,
"seed_resize_from_w":-1,
"send_images":true,
"steps":50,
"styles":[
],
"subseed":6579621,
"subseed_strength":0,
"tiling":false,
"width":512
},
"parameters":{ // parameters实际推理过程中的参数
"all_negative_prompts":[
""
],
"all_prompts":[
"cute beautiful blonde, very detailed, 21 years old, inoccent face, natural wave hair, blue eyes, high-res, masterpiece, best quality,intricate details, highly detailed,sharp focus, detailed skin,realistic skin texture,texture, detailed eyes lora:shuimobysimV3:1\u003e"
],
"all_seeds":[
3896184641
],
"all_subseeds":[
6579621
],
"alwayson_scripts":"",
"batch_size":1,
"cfg_scale":7,
"clip_skip":1,
"denoising_strength":0,
"do_not_save_grid":false,
"do_not_save_samples":false,
"enable_hr":false,
"eta":null,
"extra_generation_params":{
},
"face_restoration_model":null,
"firstphase_height":0,
"firstphase_width":0,
"height":512,
"hr_negative_prompt":"",
"hr_prompt":"",
"hr_resize_x":0,
"hr_resize_y":0,
"hr_sampler_name":null,
"hr_scale":2,
"hr_second_pass_steps":0,
"hr_upscaler":null,
"index_of_first_image":0,
"infotexts":[
"cute beautiful blonde, very detailed, 21 years old, inoccent face, natural wave hair, blue eyes, high-res, masterpiece, best quality,intricate details, highly detailed,sharp focus, detailed skin,realistic skin texture,texture, detailed eyes lora:shuimobysimV3:1\u003e\nSteps: 50, Sampler: Euler, CFG scale: 7.0, Seed: 3896184641, Size: 512x512, Model hash: 18ed2b6c48, Model: xxmix9realistic_v40, Denoising strength: 0, Version: v1.5.1"
],
"is_using_inpainting_conditioning":false,
"job_timestamp":"20230828073155",
"n_iter":1,
"negative_prompt":"",
"override_settings":{
},
"override_settings_restore_afterwards":true,
"prompt":"cute beautiful blonde, very detailed, 21 years old, inoccent face, natural wave hair, blue eyes, high-res, masterpiece, best quality,intricate details, highly detailed,sharp focus, detailed skin,realistic skin texture,texture, detailed eyes lora:shuimobysimV3:1\u003e",
"restore_faces":false,
"s_churn":0,
"s_min_uncond":0,
"s_noise":1,
"s_tmax":null,
"s_tmin":0,
"sampler_index":"Euler",
"sampler_name":"Euler",
"save_images":false,
"script_args":[
],
"script_name":null,
"sd_model_hash":"18ed2b6c48",
"seed":3896184641,
"seed_resize_from_h":-1,
"seed_resize_from_w":-1,
"send_images":true,
"steps":50,
"styles":[
],
"subseed":6579621,
"subseed_strength":0,
"tiling":false,
"width":512
},
"taskId":"Xldf9m80im"
}</code></pre><h4>4.2 查询进度</h4><p>推理进度查询</p><p>GET /tasks/{taskId}/progress,同 webui 中的 progress</p><p>response:</p><pre><code>{
"currentImage":"",
"etaRelative":0.10594336,
"progress":0.99,
"state":{
"interrupted":false,
"job":"scripts_txt2img",
"job_count":1,
"job_no":0,
"job_timestamp":"20230828073155",
"sampling_step":49,
"sampling_steps":50,
"skipped":false
},
"taskId":"Xldf9m80im"
}</code></pre><h4>4.3 取消推理</h4><p>取消对应任务</p><p>POST /tasks/{taskId}/cancellation</p><h3>5.动态资源相关 API</h3><h4>5.1 获取动态创建 sd 函数</h4><p>获取动态创建的 sdapi 函数</p><p>GET /list/sdapi/fucntions</p><p>response:</p><pre><code>{
"functions":[
{
"functionName":"sd_739f6de96fdbb66704296cd11ab3f96c182fde7f2cbbb127185b184a43414dea",
"model":"chilloutmix_NiPrunedFp16Fix.safetensors"
}
],
"status":"success"
}</code></pre><h4>5.2 更新动态创建 sd 资源</h4><p>批量更新动态创建 sd 函数资源,比如镜像、环境变量、cpu、显存等。其中 models 不指定代表更新所有动态创建 sd 函数资源</p><p>POST /batch_update_sd_resource</p><p>request:</p><pre><code>{
"models": ["chilloutmix_NiPrunedFp16Fix.safetensors"],
"cpu": 4,
"memorySize": 16384, // MB
"image": "xxx",
"extraArgs": "--api --nowebui --no-hashing",
"instanceType": "fc.gpu.ampere.1",
"gpuMemorySize": 16384, // MB
"timeout": 60, //s
"env": {},
"vpcConfig":{
"securityGroupId":"xxx",
"vSwitchIds":[
"xxx"
],
"vpcId":"xxx"
},
"nasConfig": {
"groupId" : 123,
"mountPoints": [
{
"enableTLS": true|false,
"mountDir": "xxx",
"serverAddr": "dddd"
}
],
"userId": 123
},
"mountPoints":[
{
"bucketName": "xxx",
"bucketPath": "xxx",
"endpoint": "xxx",
"mountDir": "ddd",
"readOnly": true|false
}
]
}</code></pre><p>response:</p><pre><code>{
"status": "success|fail",
"failFuncList": ["xxx"], // 失败的函数列表
"errMsg": ["xxxx"] //错误信息
}</code></pre><h4>5.3 批量删除动态创建函数接口</h4><p>批量删除动态创建的函数,入参函数列表</p><p>POST /del/sd/functions</p><p>request:</p><pre><code>{
"functions":["xxxxx"]
}
responese
// status_code=200
{
"status":"success"
}
// status_code=500
{
"fails":[
{
"err":"xxxx",
"functionName":"xxxx"
}
],
"status":"fail"
}</code></pre><h3>6.其他接口</h3><ul><li>原生 webui-api 接口,除了上面支持的功能接口,剩下的 api 接口</li><li>插件自定义的 api 接口</li></ul><p>其中支持同步、异步模式+任务模式:</p><ul><li>同步/异步,header 中设置 Request-Type,其中值 sync 为同步模式,async 为异步模式,不设置该值默认为同步模式,异步获取结果需要从上面的获取结果接口(tasks/{taskId}/result)获取最终的结果</li><li>任务模式,header 中设置 Task-Flag,会将结果保存到 ots 进行持久化,同样支持同步+异步</li></ul><h2>05 最佳实践</h2><p>为了方便大家直观体验一下该解决方案成效,基于函数计算团队开发者的基于 Stable Diffusion Serverless API 解决方案搭建的 AI 文字生成应用,作为一个实验 demo 开放体验,期待为广大开发者 AI 绘画创业及变现提供一些有益思考。直接参加体验活动,送好礼!</p><blockquote>活动链接:<a href="https://link.segmentfault.com/?enc=tMnWuqk4tIDDYful%2BQmD1g%3D%3D.IJNNGSIog%2B36nVttg151H0f39%2FJd9dh5iQB49uJC%2FBken5WgZC3f%2BZqQj8EzKqNs" rel="nofollow">https://developer.aliyun.com/topic/fcnewyear</a></blockquote><p><img src="/img/remote/1460000044691566" alt="图片" title="图片"></p><p>部署成功的 AI 绘画应用:</p><p><img src="/img/remote/1460000044691567" alt="图片" title="图片"></p><p>眯着眼睛看看是什么字?</p><blockquote>开源代码 github: <a href="https://link.segmentfault.com/?enc=PgQ7kkB1LC3gbu7K2TwddA%3D%3D.YUeestqaT81G3z6cTXW7Hzn3itSLE%2FdVA42VflQno%2BfJQO3TZTz0CvY3H7%2Bs3CiI6t1iZZiRtWMp2F2TXHaVcg%3D%3D" rel="nofollow">https://github.com/devsapp/serverless-stable-diffusion-api</a></blockquote><p>可以自己基于开源代码加工开发</p><p>作者:王佳、江昱、筱姜</p><p><strong><a href="https://link.segmentfault.com/?enc=Ops56eJPYO2I0Xyh2wr04g%3D%3D.8I6ZdX1rujVUA7zO0kgpLYJ5VOn1KhJFWDa72OduuqUxa%2Bh9FYTxJjPPitTrjQexlCaXvGSe8rg7jBbPZJtI88VIUGY8gkSwtwWh7B%2BcAWw%3D" rel="nofollow">原文链接</a></strong></p><p><strong>本文为阿里云原创内容,未经允许不得转载。</strong></p>
解密 ARMS 持续剖析:如何用一个全新视角洞察应用的性能瓶颈?
https://segmentfault.com/a/1190000044683714
2024-03-05T16:44:14+08:00
2024-03-05T16:44:14+08:00
阿里云云栖号
https://segmentfault.com/u/aliyunqi
0
<h2>01 应用复杂度提升,根因定位困难重重</h2><p>随着软件技术发展迭代,很多企业软件系统也逐步从单体应用向云原生微服务架构演进,一方面让应用实现高并发、易扩展、开发敏捷度高等效果,但另外一方面也让软件应用链路变得越来越长,依赖的各种外部技术越来越多,一些线上问题排查起来变得困难重重。</p><p>尽管经过过去十几年的发展,分布式系统与之对应的可观测技术快速演进,在一定程度上解决了很多问题,但有一些问题定位起来仍然很吃力,如下图是几个非常有代表性的线上常见问题:</p><p><img src="/img/remote/1460000044683716" alt="图片" title="图片"></p><p>$$
图 1 CPU 持续性出现波峰
$$</p><p><img src="/img/remote/1460000044683718" alt="图片" title="图片"></p><p>$$
图 2 堆内存空间用在了哪里
$$</p><p><img src="/img/remote/1460000044683719" alt="图片" title="图片"></p><p>$$
图 3 Trace调用链无法定位到耗时根因
$$</p><p>针对上述问题,该如何进行根因定位?</p><p>对于一些问题排查经验比较资深,各种排查工具接触比较多的朋友可能会分别针对上述问题想到如下排查定位方法:</p><ol><li>针对 CPU 波峰诊断,使用 CPU 热点火焰图工具进行问题排查;</li><li>针对内存问题可通过内存快照来进行内存使用诊断;</li><li>针对慢调用链诊断过程中出现耗时缺失问题,可以使用 Arthas 提供的 trace 命令进行方法耗时诊断。</li></ol><p>上述方案确实有时候可以解决一部分问题,但有过相关问题排查经验的朋友一定也清楚,其分别有各自的使用门槛和局限性,比如:</p><ol><li>针对测试环境难以复现的线上问题,CPU 热点火焰图工具也无能为力;</li><li>内存快照不仅对线上应用运行稳定可能有影响,而且需要有比较强的相关工具使用分析经验才可能诊断得出问题来;</li><li>Arthas 的 trace 命令在慢调用链不是稳定复现难以跟踪情况下问题排查就变得很困难,另外,针对跨多应用,多台机器的调用请求定位过程也非常困难等。</li></ol><h2>02 持续剖析,一个全新应用洞察视角</h2><p>那有没有一种比较简单又高效的强大诊断技术能帮助我们解决上述问题呢?答案就是本文接下来要介绍的持续剖析技术。</p><h3>持续剖析是什么?</h3><p>持续剖析(Continuous Profiling)是通过动态实时采集应用程序 CPU/内存等资源申请的堆栈信息,来帮助监测和定位应用程序的性能瓶颈。通过上述介绍,大家对持续剖析的概念是不是还是比较模糊?如果说之前很多朋友没听说过持续剖析,那 JDK 提供的 jstack 打印线程方法栈,定位现程状态这个工具可能有很多朋友在过往排查应用问题的时候或多或少都可能接触过:</p><p><img src="/img/remote/1460000044683720" alt="图片" title="图片"></p><p>$$
图 4 jstack 工具
$$</p><p>持续剖析其实思想跟 jstack 类似,它也是以一定频率或者阈值抓取应用线程执行的 CPU、内存等资源申请使用方法栈信息,然后通过一些可视化技术将相关信息呈现出来,让我们能比较直观地洞察到应用相关资源使用情况。说到这里,可能性能分析工具使用比较多的朋友会联想到火焰图:</p><p><img src="/img/remote/1460000044683721" alt="图片" title="图片"></p><p>$$
图 5 火焰图工具
$$</p><p>平时在压测过程中,通过手动开启或关闭使用的一次性性能诊断工具如 Arthas CPU 热点火焰图生成工具其实是一类即时剖析技术,它无论从采集数据的方法与数据呈现形式,跟将介绍的持续剖析技术基本无二。相比于持续剖析,最核心的区别在于它是即时而非“持续”的。</p><p>有过火焰图使用经验的朋友,大家回忆一下,日常我们使用 CPU 热点火焰图工具一般都是在压测场景,通过一些工具在压测过程中抓取应用一段时间的火焰图做压测性能分析。而持续剖析不仅仅是解决压测场景的性能观测,更重要的是它通过一些技术优化能以低开销的方式,伴随着应用整个运行生命周期,持续地剖析应用的各种资源使用情况,然后通过火焰图或者其他可视化方式为我们呈现出相比可观测技术,更底层更深入的可观测效果。</p><h3>持续剖析实现原理</h3><p>说完持续剖析基本概念,大家一定对持续剖析的实现原理有所好奇,接下来简单介绍一些相关实现原理。我们知道 Tracing 通过对关键执行路径上方法埋点采集调用中的信息,来还原调用中参数/返回值/异常/耗时等信息,但业务应用难以穷举所有埋点,另外埋点太多开销也会很大,因此难以完全覆盖全面才会出现上文介绍的图 3 Tracing 监控盲区问题。而持续剖析的实现其实是在更底层对一些资源申请相关 JDK 库关键位置进行埋点或者依赖于操作系统特定事件来实现信息采集,不仅可以实现低开销而且所采集的信息具有更强的洞察力效果。</p><p>比如 CPU 热点剖析,其大致思路,通过操作系统底层的系统调用获得 CPU 上执行线程的信息,然后以一定频率(比如 10ms)采集一个线程对应的方法栈信息,1s 中就可以采集 100 个线程方法栈信息,类似下图 6一样,最后将这些方法栈做一些处理,最后再利用一些可视化技术比如火焰图展示出来,就是 CPU 热点剖析结果了。当然上述只是简单说了一些实现原理,不同的剖析引擎以及所需要剖析的对象在技术实现上一般也有些许差异。</p><p><img src="/img/remote/1460000044683722" alt="图片" title="图片"></p><p>$$
图 6 持续剖析数据采集原理
$$</p><p>除了常见的 CPU 热点火焰图剖析,其实对计算机中的各种系统资源的使用和申请,都可通过持续剖析技术提供对应的剖析结果来帮助分析相关资源的申请和实现原理简介(注意,不同的剖析实现技术可能会有差异):</p><p><img width="603" height="533" src="/img/bVdbEq3" alt="image.png" title="image.png"></p><h3>持续剖析可视化技术</h3><p>之前说了很多关于持续剖析的内容,也提到了火焰图,在持续剖析采集后的数据可视化方面,应用最为广泛的技术之一便是火焰图(Flame Graph)那火焰图又有哪些奥妙之处呢?</p><h4>什么是火焰图?</h4><p>火焰图是一种可视化程序性能分析工具,它可以帮助开发人员追踪程序的函数调用以及调用所占用的时间,并且展示出这些信息。其核心思想是将程序的函数调用方法栈转化为一个矩形的 “火焰” 形图像,每个矩形的宽度表示该函数对应资源使用占比,高度表示函数整体的调用深度。通过比较不同时间点的火焰图,可以快速诊断程序的性能瓶颈所在,从而针对性地进行优化。</p><p>广义上的火焰图画法分为 2 种,分别是函数方法栈栈底元素在底部,栈顶元素在顶部的狭义火焰图,如下左图所示,以及方法栈栈底元素在顶部,栈顶元素在底部的冰柱状火焰图,如下右图所示。</p><p><img src="/img/remote/1460000044683723" alt="图片" title="图片"></p><p>$$
图 7 各种类型火焰图
$$</p><p><img src="/img/remote/1460000044683724" alt="图片" title="图片"></p><p>$$
图 7 各种类型火焰图
$$</p><h4>如何使用火焰图?</h4><p>火焰图作为性能分析的可视化技术,只有理解它该如何读才能基于其做性能分析。比如对于一张 CPU 热点火焰图,对于这个问题经常听到的一个说法就是看看火焰图中是否有较宽的栈顶,这个说法背后的原因是什么呢?</p><p>其实是因为,火焰图所绘制的内容就是计算机中方法执行的方法栈。而计算机中函数的调用上下文是基于一个叫做栈[1]的数据结构去存储,栈数据结构的特点是元素先进后出,因此栈底就是初始调用函数,依次向上就是一层层的被调用子函数。当最后一个子函数也就是栈顶执行结束以后才会依次从上往下出栈,因此栈顶较宽,就表示该子函数执行时间长,其下方的父函数也会因为其一直执行无法即时出栈而导致最终整体耗时很长。</p><p><img src="/img/remote/1460000044683725" alt="图片" title="图片"></p><p>$$
图 8 栈数据结构
$$</p><p>因此分析火焰图的方法步骤如下:</p><ol><li>判断火焰图对应的类型,找到其中的栈顶方向;</li><li>如果火焰图总资源占用高,就继续检查火焰图的栈顶是否有较宽的部分;</li><li>如果存在较宽的栈顶,沿着栈顶依次往栈底方向搜索,找到第一个包名为所分析应用自身所定义的方法行,然后重点排查该方法是否存在优化空间。</li></ol><p>以下为一张资源占用高的火焰图,具体分析火焰图中的性能瓶颈步骤如下:</p><ol><li>由下图形状可发现为一张栈底在上,栈顶在下的冰柱状火焰图,因此需要从下往上分析。</li><li>分析下方的栈顶,可以发现右侧较宽的栈顶为右侧的方法:java.util.LinkedList.node(int)。</li><li>由于该较宽栈顶是 JDK 中的库函数,并非为业务方法,因此,沿着栈顶方法:java.util.LinkedList.node(int),从下往上搜索,依次经过:java.util.LinkedList.get(int)->com.alibaba.cloud.pressure.memory.HotSpotAction.readFile(),而com.alibaba.cloud.pressure.memory.HotSpotAction.readFile() 是一个属于所分析应用的业务方法,即为第一个所分析应用自身所定义的方法行,其耗时为 3.89s,占到整张火焰图的 76.06%,因此其是该火焰图所采集时段内资源占用较高的最大瓶颈所在,因此可以根据相关方法名,对业务中相关方法的逻辑进行梳理,看是否存在优化空间。另外也可根据上述分析方法对图的左下角 java.net.SocketInputStream 相关方法一样进行分析,发现其属所分析应用第一个自身所定义的父方法全限定名为:com.alibaba.cloud.pressure.memory.HotSpotAction.invokeAPI,总占比位约为 23%。</li></ol><p><img src="/img/remote/1460000044683726" alt="图片" title="图片"></p><p>$$
图 9 火焰图分析过程
$$</p><h2>03 开箱即用的 ARMS 持续剖析能力</h2><p>经过上面的介绍,这个时候大家无论是对持续剖析概念、数据采集原理以及可视化技术应该都有了一定了解。然后,再介绍一下 ARMS 提供的开销即用持续剖析能力,如何帮助排查定位各类线上问题。</p><p>ARMS 提供一站式持续剖析产品能力,已经有接近 1w 应用实例在线上开启该功能进行持续数据采集与监控。</p><p><img src="/img/remote/1460000044683727" alt="图片" title="图片"></p><p>$$
图 10 ARMS 持续剖析产品能力
$$</p><p>左测图是当前 ARMS 持续剖析能力的概览,从上往下依次是数据采集、数据处理以及数据可视化。具体功能层面,目前针对用户需求最为急迫的几个场景分别提供了对应解决方案,比如 CPU、堆内存分析,提供了 CPU、内存热点功能。针对慢调用链诊断问题,ARMS 提供了代码热点功能。ARMS 上的持续剖析是 ARMS 团队联合阿里云 Dragonwell 团队一起研发的持续剖析产品能力,相比于一般的剖析方案,它具有开销低、粒度细和方法栈完备等特点。</p><h3>使用介绍</h3><p>除了视频演示 demo,在 ARMS 产品文档已经提供对应子功能的最佳实践内容:</p><ul><li>针对 CPU 利用率高问题诊断,可以参考《使用 CPU 热点诊断 CPU 消耗高问题[2]》进行问题诊断。</li><li>针对堆内存利用率高问题诊断,可以参考《使用内存热点诊断堆内存使用高的问题[3]》进行问题诊断。</li><li>针对调用链耗时根因诊断,可以参考《使用代码热点诊断慢调用链的问题[4]》进行问题诊断。</li></ul><h3>客户案例</h3><p>相关功能自发布以后,较好地协助用户对一些线上困扰已久的疑难杂症进行诊断,获得很多用户的好评,例如:</p><p>1.用户 A,发现某个应用服务刚启动的时候,前几个请求会很慢,使用 Tracing 出现了监控盲区无法诊断耗时分布。最后,使用 ARMS 代码热点,帮助其诊断出相关慢调用链的耗时根源是 Sharding-JDBC 框架初始化耗时所致,帮助其终于搞清楚了一直困扰的现象根因。</p><p><img src="/img/remote/1460000044683728" alt="图片" title="图片"></p><p>$$
图 11 用户问题诊断案例 1
$$</p><p>2.用户 B,压测过程中,应用的所有实例中总会出现有部分节点响应时长比其它节点慢很多,使用 Tracing 也看不出根因。最后,通过代码热点发现相关应用实例一压到某个压力情况下就会出现大量的时间消耗在写日志上,然后,根据相关信息,排查应用环境日志采集组件的资源使用率,发现其压测过程中占用了大量 CPU,导致应用实例写日志争抢不到资源而导致请求处理慢。</p><p><img src="/img/remote/1460000044683729" alt="图片" title="图片"></p><p>$$
图 12 用户问题诊断案例 2
$$</p><p>3.用户 C,线上应用运行过程中,发现堆内存使用量总是很大,通过内存热点,很快发现是应用使用的该版本微服务框架运行过程中将订阅的上游服务信息进行持久化处理导致大量堆内存占用,然后咨询相关框架服务提供方,最后,了解到可通过升级框架版本解决该问题。</p><p><img src="/img/remote/1460000044683730" alt="图片" title="图片"></p><p>$$
图 13 用户问题诊断案例 3
$$</p><h3>开销情况</h3><p>最后,大家可能会 ARMS 持续剖析开销非常关心,我们设计了如下压测场景对该功能开销进行测算,其模拟了一个从压测中心发起请求打入到业务入口应用,该应用会查询查询数据库并返回结果。</p><p><img src="/img/remote/1460000044683731" alt="图片" title="图片"></p><p>$$
图 14 压测示意图
$$</p><p>测试环境开启所有的持续剖析功能,采用的 K8s 容器运行环境来模拟一般企业应用运行环境。Pod limit 值为 4c8g,4g 堆内存年轻代占比设置为 1/2,压力极限为 6000 TPS。分别测试 500TPS 和极限压力的 80% 4800TPS 情况下的开销如下表所示。从表中可以看到,全部功能开启后 CPU 开销在 5% 左右,堆内内存开销不明显,堆外内存占用为 50MB 左右,流量小,或者仅开启部分持续剖析功能的情况下会更低。</p><p><img src="/img/remote/1460000044683732" alt="图片" title="图片"></p><p>$$
图 15 压测结果
$$</p><p>据了解,很多企业应用运行过程中的 CPU/内存等资源利用率都是比较低,通过少量资源消耗,为应用提供一个全新的观测视角,让应用在运行异常时有详细的根因定位数据还是非常有价值的!</p><p>直播推荐:</p><p>掌握 ARMS 持续剖析-轻松洞察应用性能瓶颈:<a href="https://link.segmentfault.com/?enc=uTT2ssoAg10sZoWxdAXtdQ%3D%3D.WEaYv6NXGli3paiBoPUbRYVg93eHLBNltRoIt6y8u3v4GAoGjbhJRicbFOT7vOk5" rel="nofollow">https://developer.aliyun.com/live/253768</a></p><p>相关链接:</p><p>[1] 栈</p><p><a href="https://link.segmentfault.com/?enc=41%2BkQyFj3EyFtBEkBGEtYg%3D%3D.7UGN3GDJ7iH05WUKAQd%2BkgVFPcPquoz1jjb393lh7MG9YX0z4udANpxIE%2FaCUbZY" rel="nofollow">https://baike.baidu.com/item/%E6%A0%88/12808149</a></p><p>[2] 使用 CPU 热点诊断 CPU 消耗高问题</p><p><a href="https://link.segmentfault.com/?enc=sHzP8e%2Fjl4A3B1xJnNwt%2Fw%3D%3D.yz93njSu2qSx1Ydoa5Foz8d5ILvR0ot1PZUZj6%2Fb%2FWHzwWo%2BFWcKrKiCd0PgINX%2B3A0AYGG3ztRopveF73SEtNXvH6ftG8n%2Fpm51gzRtsb9%2BRP3%2B1ZAfyJZmLItZ6CG8ZEksMDteSWSeQ3sDnDW6Q%2BioN7lzYMeZUqrL9zMbimo%3D" rel="nofollow">https://help.aliyun.com/zh/arms/application-monitoring/user-g...</a></p><p>[3] 使用内存热点诊断堆内存使用高的问题</p><p><a href="https://link.segmentfault.com/?enc=VKGY4ZsrHge9iGrCOq%2BgxA%3D%3D.xFW%2BP6hUNtFhHGI6Sxq%2B%2FCMmWxbsDZfIh5Khw5lGUx9Zx4Z0oIbINqJNZ11I3jFdrqmZuyCErKzL7jkSlLH0dd4TqW6da%2FdMVkRikrsPDhiwy4K4xH2pURAxsMDn%2Fx783IudtS6vaKzZxWgor4p8mHREniL08bJfXhiNsSmqZzU%3D" rel="nofollow">https://help.aliyun.com/zh/arms/application-monitoring/user-g...</a></p><p>[4] 使用代码热点诊断慢调用链的问题</p><p><a href="https://link.segmentfault.com/?enc=%2FyO4Dq2L9drqB%2FEAUFG5KQ%3D%3D.MOEnzsegL9KNEo8zgFmWFPxvVnTUUTccPFTERF0bCz6KY6eouexTmI7UymcQ4OSQgAeabb3L16GKwPB5YVwUOq8QmmlXfHDy%2BFci6aW82Uv23Ot%2FocdBArafhcsZHnbDWCw7V712bUIEzKCax6NmDC69kUR%2BrWOYClubC2Ur3Qw%3D" rel="nofollow">https://help.aliyun.com/zh/arms/application-monitoring/user-g...</a></p><p>作者:饶子昊、杨龙</p><p>原文链接</p><p>本文为阿里云原创内容,未经允许不得转载。</p>
面向智算服务,构建可观测体系最佳实践
https://segmentfault.com/a/1190000044680270
2024-03-04T15:52:34+08:00
2024-03-04T15:52:34+08:00
阿里云云栖号
https://segmentfault.com/u/aliyunqi
0
<h2>01 构建面向 AI、大数据、容器的可观测体系</h2><h3>(一)智算服务可观测概况</h3><p>对于越来越火爆的人工智能领域来说,MLOps 是解决这一领域的系统工程,它结合了所有与机器学习相关的任务和流程,从数据管理、建模、持续部署的到运行时计算和资源管理。下图是开源 ML-Ops 平台 MLReef 在 2021 年发布的 ML 市场相关工具和平台玩家。时至今日,相关工具与平台玩家数量保持着持续高速增长。当前,随着大语言模型(LLM)从新兴技术发展为主流技术,以大模型为核心技术的产品将迎来全新迭代。</p><p><img src="/img/remote/1460000044680272" alt="图片" title="图片"></p><p>近期,阿里云战略进行了一定调整,确立“AI 驱动,公有云优先”核心战略。在 AI 领域有哪些产品布局呢?</p><ul><li>基础设施及服务 IaaS 层</li></ul><p>在计算、存储、网络、安全产品中提供以“灵骏”智算服务为特色的软硬件一体化的算力集群服务;</p><ul><li>容器即服务 CaaS 层</li></ul><p>laaS 层之上以 Kubernetes 为代表的容器技术,已成为云计算的新界面,“ACK 灵骏托管集群”+“云原生 AI 套件”产品组合可以高效管理异构资源,提供 AI、HPC 等高性能计算场景下的云原生增强能力;</p><ul><li>平台即服务 PaaS 层</li></ul><p>CaaS 之上的平台即服务 PaaS 层构建了以“人工智能平台 PAI”为核心,提供一站式机器学习解决方案;</p><ul><li>模型即服务 MaaS 层</li></ul><p>提供“灵机模型服务 DashScope”、通义大模型和各行业生态大模型、企业专属定制大模型及 ModelScope 魔搭社区供业内交流,围绕 AI 各领域模型,通过标准化 API 提供模型推理、模型微调训练在内的多种服务。</p><p><img src="/img/remote/1460000044680274" alt="图片" title="图片"></p><p>AI 时代下有新技术栈,包括新技术、新数据类型及新工作流。目前可观测领域产品更多服务于应用开发者,针对 ML 开发者也需要配套的工具来更好地进行调试、运维及发布模型服务。为了更好的帮助大家理解,我们先讲讲可观测行业头部企业 DataDog 如何做 AI 可观测。所谓的 AI 端到端可观测即从 Infrastructure,Vector Database 再到 Model 和 orchestration framework。DataDog 早已推出了 OpenAI 即 model 这一层的可观测能力,包括 api 费用、接口响应及 prompt,收获了非常多小客户。</p><p>本次 2023 Dash 大会将模型从 OpenAI GPT 模型延伸到了更多模型,基本上实现上面所有模型的可观测能力。随着各种大模型不断丰富,每一次请求涉及到的链路会非常复杂,对于使用方来说都是黑盒。因此 DataDog 推出 LLM Model Catalog,方便开发者去观测链路上各个节点的异常,界面非常类似 APM 服务列表和链路查询功能。基于 Catalog,不仅可以按照模型提供方维度,服务维度,环境维度等进行浏览,清晰看到不同模型性能、请求延迟、请求量以及费用。还可以针对 prompt 进行监控,增加了统一的反馈功能,来对 prompt 结果统一分析。接下来,我们看看国内厂商针对 AI 场景在做进行哪些探索。</p><p><img src="/img/remote/1460000044680275" alt="图片" title="图片"></p><h3>(二)Prometheus 云产品可观测监控生态</h3><p>既然围绕 AI 的可观测要有一套标准体系,谁来做 AI 可观测更为合适呢?我们的回答是 Prometheus,因为他天生契合了云原生架构,在开源领域 Prometheus 处于 Metrics 事实规范的市场地位。</p><p>当今多种行业都在做云原生化改造背景下,Prometheus 在架构、功能维度与 Kubernetes 天然集成。它具有自动服务发现、多层次采集能力、生态强大、通用多模指标模型及强大的 PromQL 查询语法等特点。下图是阿里云所提供的全栈可观测能力,里面囊括了上百款阿里云产品的监控,覆盖基础设施、容器、中间件、应用等各个层面,而这些产品监控都由 Prometheus 支撑。</p><p><img src="/img/remote/1460000044680276" alt="图片" title="图片"></p><p>阿里云 Prometheus 集成的众多云产品业务指标,针对云产品多租需求提供了一整套完整的解决方案。每个阿里云云产品除对产品自身指标监控外,同时需要对产品售卖租户指标进行监控。云产品针对租户资源划分主要分为租户独占资源、租户共享资源两种模式,可以给资源打租户标签或云产品自行添加租户信息方式来区分租户。</p><p>阿里云Prometheus 监控相对开源 Prometheus 采用采集、存储查询分离架构,采集端具备多租识别和分发能力,存储端内置多租能力,租户之间资源是完全隔离的。阿里云 Prometheus 会每个阿里云用户创建一个 Prometheus 云服务实例来存储用户对应的阿里云产品指标,真正解决了以往监控系统数据分散形成数据孤岛的问题,同时为每个云产品提供了深度定制、开箱即用的大盘和告警能力。</p><p><img src="/img/remote/1460000044680277" alt="图片" title="图片"></p><p>下图是阿里云 Prometheus 接入云产品监控的完整架构,包含以 Pull 模式为主、Push 模式为辅的全场景覆盖。Pull 模式支持云产品以 Kubernetes 或 ECS 部署模式,通过指标暴露、日志或云监控方式来对接;Push 模式支持以 Prometheus 标准的 Pushgateway、Remote Write 协议将指标推送过来,所有接入模式均支持云产品面向自身和租户的两层监控能力。我后面讲到的阿里云 AI 产品可观测就是综合运用了多种接入模式完成相关产品可观测监控接入的。</p><p><img src="/img/remote/1460000044680278" alt="图片" title="图片"></p><h3>(三)阿里云 AI 可观测最佳实践</h3><p>下面我详细讲下阿里云 AI 产品体系如何做端到端可观测体系建设。</p><p>最底层 IaaS 层,阿里云以“灵骏”智算服务为特色的软硬件一体化设计的算力集群服务,灵骏底层硬件核心由磐久服务器以及高性能 RDMA 网络两部分组成,这里面就包括提供 NAVIDIA A100 高性能 GPU 服务器。灵骏本身是以节点交付的,灵骏集群内可以划分多个分组,分组内包含计算节点。</p><p>节点上的计算资源 GPU、RDMA、Nimitz 等组件监控数据自身以 Pushgateway 协议上报的 Prometheus,指标中携带租户标来实现多个租户的隔离。内置的监控大盘支持集群级、节点级 GPU、RDMA 等资源的监控能力,涵盖 IaaS 层常规 CPU、Mem、Disk、Net 以及算力方面的一千余个指标。</p><p><img src="/img/remote/1460000044680279" alt="图片" title="图片"></p><p>高性能算力之上 CaaS 层,ACK 灵骏托管集群提供全托管和高可用的控制面的标准 Kubernetes 集群服务,它作为支持机器学习平台 PAI 的云原生底座。ACK 灵骏集群会默认启用云原生 AI 套件,向下封装对各类异构资源的统一管理,向上提供标准 K8s 集群环境,提供高效、灵活的一站式 AI 平台。</p><p>ACK 灵骏托管集群支持对灵骏节点管理,纳入到灵骏节点池。AI 套件增强对异构资源调度,通过 GPU 共享调度和 GPU 拓扑感知调度可以高效地管理 GPU 程序以及 GPU 隔离。GPU 监控 2.0 基于 NVIDIA DCGM 来构建。ACK 灵骏集群内置 Prometheus 监控集成,可以一键获取整个 K8s 集群全部资源、组件的监控采集。节点上安装了 ACK 团队增强的 gpu-exporter 将 DCGM 服务以指标暴露出来,并内置了集群、节点、Pod 维度 GPU 大盘。</p><p>这里有一点需要说明,常规 GPU 利用率指标采用 nvidia-smi 查询到整张卡的 GPU 利用率。但 GPU 利用率目前存在一些局限性,如不能告知用户有多少 SM 在使用,用户写的代码到底是真忙还是假忙,代码到底在做单双精度浮点运算(FP32/64)还是在拷贝数据?此时就需要做一些 Profiling 指标,去查看更细粒度的指标信息。</p><p><img src="/img/remote/1460000044680280" alt="图片" title="图片"></p><p>在 PaaS 层,阿里云人工智能平台 PAI,提供了一站式机器学习解决方案。他包含基础设施,计算引擎和容器,计算框架,ML 从数据准备、模型开发与训练及模型部署阶段的全流程产品,应用于金融、医疗、教育等各领域。</p><p>PAI 的可观测也是最复杂的,我们需要囊括 PAI 各自产品、容器、节点等相应层面的监控覆盖,每一层的架构、部署方式都有极大差异,接入方式也各不相同。但 Prometheus 存储、查询侧我们做到了一致的解决方案,以各子产品为隔离粒度的面向租户的存储,垂直形成一个租户逻辑实例,单实例支持 100w/s 写入,每个产品可以根据业务情况切分实例单独扩容,逻辑实例可以付费升级成租户独享实例支持用户定义更长存储周期和更高的隔离粒度确保稳定性。如果用户想要所有 PAI 产品的监控数据还可以定义全局聚合实例会返回所有产品监控信息而不占用存储空间。</p><p><img src="/img/remote/1460000044680281" alt="图片" title="图片"></p><p>我们实现了 PAI 产品的全栈可观测能力,支持 EAS 在线推理指标,DLC 训练作业级、节点级、LRN 级资源指标的透出,以及容器组件、节点、Pod 等集群所有资源指标,还有底层基础设施算力节点的全部监控数据采集、存储、展示等全方位能力。</p><p><img src="/img/remote/1460000044680282" alt="图片" title="图片"></p><p>最上层 MaaS 层,模型服务灵机 DashScope 围绕 AI 各领域模型,通过标准化 API 提供模型推理、模型微调训练在内的多种模型服务。内置包括通义千问、白川开源大语言模型在内的 20+ LLM,支持模型推理、定制,并结合 ModelScope 魔搭社区打造下一代模型及服务共享平台。</p><p>灵积的监控是通过日志中转方式实现的,灵机将各种 LLM 大模型以及业务网关监控数据写到日志系统,Prometheus 通过内部的流式 ETL 工具实时将日志转成指标数据分发到各租户名下,形成了灵机模型 API 层面的监控覆盖。</p><p><img src="/img/remote/1460000044680283" alt="图片" title="图片"></p><p>正如前面讲到的 AI 时代下有新技术栈,目前的可观测领域产品更多服务于应用开发。当前的 AI 可观测虽然做到了 IaaS、CaaS、PaaS、MaaS 不同层面核心产品覆盖,但整套 AI 体系还有更多可观测需要挖掘和覆盖的场景,真正做到 AI 端到端全栈可观测任重而道远。</p><h2>02 实现自身数据的深入洞察</h2><h3>(一)Smart Metrics</h3><p>可观测离不开告警,告警里有两个核心痛点。一是无效告警太多,AIOps 对告警数据做了统计之后发现真实意图的告警比例仅为 3.05%,典型无效告警配置包括用固定阈值遍历所有应用/接口,敞口告警可能最初配置没问题,运行一段时候后业务变化了告警就失效了。二是告警难配,典型的告警页面仅支持配静态阈值,而真实的指标(比如 QPS)往往是随着业务周期变化的,基于静态阈值的告警配置难、维护难。</p><p><img src="/img/remote/1460000044680284" alt="图片" title="图片"></p><p>Smart Metrics 为了解决上述告警痛点而生,基于历史数据中学习 Metrics 特征,并对未来一段时间内 Metrics 正常变化范围做出预测,生成上下基线。他具有开箱即用免运维、效果可视、准确率高,支持 Grafana 原生告警能力等特征。</p><p>事实上用单一模型是难以满足多种曲线类型的,我们采用自研分类算法 + 多模型融合方式,用户可以自定义灵敏度事件等,多模型可以为每种曲线寻找最合适的算法,让我们的产品足够“Smart”。</p><p><img src="/img/remote/1460000044680285" alt="图片" title="图片"></p><p>这里简单介绍两个使用场景。</p><p>场景 1:针对 QPS 波动性明显指标,静态阈值是没法配置的,智能算法可以一键产生上下边界,超出边界的值我们才认为是可以报警的,这样就帮用户解决了如 QPS 等起伏不定指标的告警难配问题。</p><p><img src="/img/remote/1460000044680286" alt="图片" title="图片"></p><p>场景 2:CPU 使用率等一般平稳型指标,会随着新应用上线发生较大变化。传统做法需要对发布后更新阈值,Smart Metrics 可以每天自动更新模型,自动学习新环境,自动生成上下边界,有效减少“敞口告警”问题产生。</p><p><img src="/img/remote/1460000044680287" alt="图片" title="图片"></p><h3>(二)Text2PromQL 问答机器人</h3><p>如果说用算法预测监控曲线基本上成为每款监控产品的必备能力,那 Text2PromQL 则是使用 LLM 解决可观测提效问题的利器。</p><p>为什么我们需要自然语言转 PromQL 的智能机器人?PromQL 是 Prometheus 专属查询语言,和传统 SQL 有本质的不同。PromQL 是几乎所有 K8s 应用的运维工程师最经常使用的查询语句,没有之一。写 PromQL 不是一件简单的事,用三个 C 来形容它的复杂性。第一个"C"是"Complex",PromQL 语法其实是比较复杂的;第二个"C"是"Confusing", PromQL 是由指标名、算子和 label 组成,指标名有时候会非常难懂。</p><p>每个公司都有自己的命名方式,甚至有一些指标是用户自定义的。监控领域关注的指标又多又杂,有时候看文档都看不明白那些指标到底什么意思;第三个"C"是"Commenly",PromQL 是一个非常常用的查询语言。它不仅能提供运维相关的指标,也可以统计点击率、转换率、SLA 等业务指标,运维、开发、产品、运营都可以用它。综上,PromQL 语法不好学、指标名又复杂,日常工作中用得又多,为了减轻 SRE 工作、降低服务工单,也为了 Promethues、K8s 的推广,我们需要一款自然语言转 PromQL 的机器人。</p><p><img src="/img/remote/1460000044680288" alt="图片" title="图片"></p><p>我们第一步要做的事情是,先看看 ChatGPT 是不是就可以完成自然语言到 PromQL 的翻译了。如果大模型本身就可以很好地完成这个任务,那我们不用开发了。就等着通义千问做大做强,我们直接调用他们的 API 就行。我们做了一些实验,发现 ChatGPT 和通义千问,都不能很好地完成这个工作。以 ChatGPT 为例,我问他“给我写个 PromQL,帮我查一下过去 5min,平均响应时间最长的 10 个应用是啥”。</p><p>它给我的回答是:topk(10,avg_over_time(application_response_time_seconds[5m]))</p><p><img src="/img/remote/1460000044680289" alt="图片" title="图片"></p><p>我们看下它哪里错了,首先是指标名的事情,在我们的系统中,根本没有一个叫"application_response_time_seconds"的指标。其次,对平均响应时间的理解也是不对的,正确的例子:</p><p>topk(10,sum by (service)(sum_over_time(arms_http_requests_seconds{}[5m]))/sum by (service)(sum_over_time(arms_http_requests_count{}[5m])))</p><p>总的来说,通用的 LLM:</p><ol><li>它给的 PromQL 语法上是正确的。</li><li>它对我们的系统一无所知,不知道我们的指标名,当然它对别的公司提供的监控系统也不知道。3. 它其实不大了解用户问这个问题真正的意图,因为它在这里的背景知识太少了。</li></ol><p>也就是说,看起来 LLM 需要更多的知识......</p><p><img src="/img/remote/1460000044680290" alt="图片" title="图片"></p><p>为了给 LLM 灌知识,我们也做了一些调研。总的来说,有 2 种方案:</p><p>第一种是 Fine-tuning:就是你用足够的语料,对大模型进行微调,这里的微调指的是,你已经改了模型本身的一些参数,或者你在大模型外接了一个小模型,总之除了 LLM 本身自带的参数之外,已经有了你自己任务相关的神经网络和参数了。</p><p>第二种方案是 Prompt Engineering,提示词工程:就是我们不会增加或修改大模型本身任意一个参数,我们做的只是在用户问问题的时候,给它带一点上下文,作为额外的知识,来提升回答的准确性。</p><p>这两种方案本身没有优劣之分,我们画了一颗决策树,希望能给想要做 LLM-based 应用的同行们一些我们的经验。</p><p>既然选择了 Prompt Engineering 提示词工程,下一个问题就是,什么样的提示词是有用的。</p><p>我们花了好几个月的时间,尝试了 5 种的提示词,终于,把 Text2PromQL 准确率从 5% 以下,提升到了百分之 70-80%。我们的探索过程使用过 PromQL 官方文档、Stack Overflow 社区问答、阿里云 ARMS 内部客户 QA 问答(这里包含了我们自己系统的指标名信息)、ARMS 内部 PromQL 问答示例 + ChatGPT 生成的 PromQL 解释等手段准确率可以到 20% 左右。</p><p>直到引入 Chain-of-Thought 格式 PromQL 问答示例,准确率一下子提升到 60-70%,终于迎来了第一个拐点。最后我们基于 Chain-of-Thought 格式 PromQL 问答+通义千问,准确率原地涨了 10%,达到 80% 左右。即使不完全对的场景,也给了指标名、该用的算子等非常有用的信息,而且语法基本不会错了。通义千问确实很厉害!</p><p><img src="/img/remote/1460000044680291" alt="图片" title="图片"></p><p>Chain-of-Thought 是 Google Brain 实验室提出来算法,本来用来增强 LLM 推理能力的,它的提示词是带有推理步骤的知识。推理过程很像解小学数学题。</p><p><img src="/img/remote/1460000044680292" alt="图片" title="图片"></p><p>普通提示词:</p><p>Q:Roger 有 5 个羽毛球,他又买了 2 桶,每桶有 3 个,那他现在有几个。</p><p>A:答案是 11。</p><p>理论上,LLM 应该能照葫芦画瓢回答出来,但是他的答案是错误的。</p><p>Google 给的 Chain-of-Thought 提示词:</p><p>Q:Roger 有 5 个羽毛球,他又买了 2 桶,每桶有 3 个,那他现在有几个。</p><p>A:Roger 本来有 5 个球,买了 2 桶,每桶 3 个的球,也就是 6 个球。5+6=11。所以答案是 11。</p><p>这里就是给了例子中的推导过程。</p><p>然后,奇迹发生了,GPT 居然就会了,给了正确的答案。</p><p><img src="/img/remote/1460000044680293" alt="图片" title="图片"></p><p>下面我们来介绍 CoT 算法,在 Text2PromQL 场景下是怎么使用的。</p><p>这是我们的架构图,我们拥有一个离线系统和一个在线系统。在离线系统中,我们将 ARMS 多年沉淀的,大量用户关于 Text2PromQL 的问答示例,通过 Chain-of-Chain Prompting 算法,转换成 Chain-of-thought 格式 Q&A 示例,然后进行文本切割,得到 Q&A 示例。然后通过 embedding,将文字转换为数字组成的向量。再把这些向量存到数据库中;在线系统中,当一个用户提问,比如写一个 PromQL,查平均响应时间最长的 10 个应用,我们会把这些文字通过 embedding 转换成数字组成的向量。</p><p>现在我们拥有了用户问题转换出来的向量以及离线系统中数据库中一系列向量。那么,我们就可以在数据库中检索和当前用户问题最相似的 topk 个向量,把这个 k+1个数字组成的向量还原为文字,然后把用户的问题以及 k 个最相似的历史 Q&A 作为提示词输入到大模型中,从而可以得到最终 PromQL。可以看到,我们这个系统初始的输入是用户的 PromQL 问答示例,所以当用户问得越多,我们能覆盖的场景也越多,准确率也会越高,总的来说,我们的机器人会越问越聪明。</p><p><img src="/img/remote/1460000044680294" alt="图片" title="图片"></p><p>我们当前覆盖了 20+ 场景,准确率 76.9%。即使在没有覆盖的场景下,也能给出非常多有用的信息。更重要的是,因为我们是 Prompt Engineering,通过给提示词增加模型的准确率,所以覆盖新场景非常快,只要给它生成 CoT 格式的提示词就好。目前 Smart Metrics 和 Text2PromQL 已经在阿里云可观测可视化 Grafana 版上线,欢迎开发者体验。</p><p><img src="/img/remote/1460000044680295" alt="图片" title="图片"></p><h2>03 每月 50GB 免费额度让 Prometheus 成本更低、更可控</h2><p><img src="/img/remote/1460000044680296" alt="图片" title="图片"></p><p>近期,可观测监控 Prometheus 版发布新计费模式,屏蔽原有上报指标采样点数量、存储时长等计费项,以实际写入数据量(GB)进行计费。</p><p><img width="723" height="111" src="/img/bVdbDxx" alt="image.png" title="image.png"></p><p>新计费模式单价 & 免费额度:</p><p><img width="723" height="69" src="/img/bVdbDxy" alt="image.png" title="image.png"></p><p>Prometheus 包含基础指标、自定义指标。其中,基础指标以容器服务产生的基础指标举例,默认存储 7 天且免费,不占用 50GB 免费额度。自定义指标以云服务器 ECS 实例举例,每日上报指标量 24.5 万/实例,每日数据写入量约 0.093GB/实例。</p><blockquote>计算器:<a href="https://link.segmentfault.com/?enc=%2Be1fob6bTnY88bxA9hfGsQ%3D%3D.nnV0B4Puzmaj6gycR8M9cQwmo6KZ1S0YPMm%2BXO0L2pf%2BgIQq1aLxIZtq5iEN%2BQ0wW5qh2o5puk2EjKBmNtluUw%3D%3D" rel="nofollow">https://armsnext.console.aliyun.com/price-gb#/overview</a></blockquote><p>老用户如何基于新计费模式进行成本预估</p><p>1)基本条件</p><p>1 条上报指标约 0.5KB;</p><p>注:不同使用模式下存在一定数据量差异,实际使用时请关注。</p><p>2)新老对比</p><p>以中小企业通常每日上报自定义指标 15000 万条 ,数据保存 30 天举例。</p><ul><li>新计费(按量付费)每月成本:150000000(条) <em> 0.00000048 (GB/条) </em> 0.4(元/GB)* 30(天)= 864 元</li><li>旧计费(按量付费)</li></ul><p>1.阶梯一部分:50000000 条 <em> 0.0000008(元/条)</em> 30(天)= 1200元<br>2.阶梯二部分:100000000 条 <em> 0.00000065(元/条)</em> 30(天)= 1950元<br>3.总计成本:1200 + 1950 = 3150元</p><p>对比两种计费方式,新计费节省 70% 以上。</p><p>作者:蓟北</p><p><strong><a href="https://link.segmentfault.com/?enc=3UBttatG5dzhf8dFhE13Og%3D%3D.TCd3Zo%2BDHsO%2BIEYhDtXx67hJVJYQwZxGVDn5iDM2tbX66ugqgMsG5BwW2YnxejJ9sHsD8dJRteE0vTukmbzSFif2TUKuS%2FE27YxDY7lATmc%3D" rel="nofollow">原文链接</a></strong></p><p><strong>本文为阿里云原创内容,未经允许不得转载。</strong></p>
MSE Nacos 配置变更审计平台使用指南
https://segmentfault.com/a/1190000044668980
2024-02-29T15:44:25+08:00
2024-02-29T15:44:25+08:00
阿里云云栖号
https://segmentfault.com/u/aliyunqi
0
<h2>配置审计平台简介</h2><p>Nacos[1]作为一款业界主流的微服务注册中心和配置中心,管理着企业核心的配置资产,由于配置变更的安全和稳定诉求越来越高,因此我们提供了安全和可追溯性保障机制。</p><p>配置变更的途径主要包括控制台手动发布和使用 Nacos SDK 客户端等方式,为了配置变更的安全性,我们需要对这两种变更进行变更操作的通知和追溯;其中既包括这些变更操作的变更责任人、责任机器的追踪,也包括变更操作对于相关方的通知和告警。</p><h2>配置变更审计平台核心目标</h2><p>从变更内容方面,配置变更动作可分为配置的发布、删除、导入、修改等;从变更渠道划分,Nacos 配置变更可分为 在控制台进行的手动操作、使用 Nacos SDK 进行的操作。配置变更发生之后,我们需要进行变更的详细审计,其中主要包括呈现配置的变更细节、变更之后的消息通知。</p><p>由此可见,配置变更的目标主要是在配置变更后进行相应的附加处理,来提升配置的可靠性、精准性,从而提升系统整体的安全性、可用性。</p><p>为了提供给用户一个完善的配置变更审计平台,我们在审计平台中提出了以下几个配置变更的审计点:</p><ul><li>配置变更操作责任人审计:在 MSE 中添加配置变更的操作责任人的信息,方便客户追溯配置变更的具体执行者;而对于未开启鉴权,未留下用户信息的用户,MSE Nacos 会将配置变更的来源 IP 记录下来,并且将其暴露给用户,从而保证整个审计链路的完整性和可追溯性;</li><li>配置变更影响面审计:当有多个微服务应用监听该配置时,我们需要记录下有哪些应用和机器监听了该配置,当配置内容发生变化,我们需要将其推送行为、推送成功与否、是否影响业务等信息在变更审计平台上呈现给用户;</li><li>配置变更内容审计:对所发布配置的内容进行记录,便于用户追溯配置历史的版本,以及每个历史版本的更新日期、所属应用、变更内容;</li><li>配置变更通知和告警:在配置变更(含发布、修改、导入、删除操作)之后,配置使用水位的实时监控以及配置使用水位超过阈值之后的告警,能够保证用户的及时感知配置的变化情况。</li></ul><h2>配置变更审计平台原理</h2><p>如下图所示,配置变更审计平台会将用户的变更操作完整记录,并且通过配置操作人追溯、推送轨迹、配置历史版本审查、变更通知及告警等功能向用户透出。</p><p>例如,当用户组织内,某变更操作执行人 A 发起“配置变更 1”操作时,MSE 会将其操作内容和影响面做完整的记录,如“A 执行了配置变更1操作,变更内容为 XXX,该配置监听者及可能的受影响者为 C”。这些信息会通过配置操作人追溯大盘、配置操作影响面追溯大盘等,统一汇总到变更的审计人 E;同时,审计人 E 也可以通过配置使用水位监控观测到配置中心当前的整体使用情况,当配置的使用量超出既定阈值时,MSE 会通过告警信息等方式将风险透出给配置变更审计者。</p><p><img src="/img/remote/1460000044668982" alt="图片" title="图片"></p><p>由此,当用户组织内部的变更审计人需要对该变更进行审计和追溯时,便可以通过 MSE 配置变更审计平台,完整地看到该变更发行时间点、操作人、操作内容、影响面等各种信息,便于其进行团队和研发进度管理,界定风险责任。</p><h3>配置操作人追溯</h3><p>MSE Nacos 配置变更操作人追溯作为配置变更平台最主要的功能,用户可以在该追溯界面查看看到历次配置变更的详情和变更操作的责任人信息。</p><p><img src="/img/remote/1460000044668983" alt="图片" title="图片"></p><p>如下图所示,该功能在记录和呈现配置的操作细节时,对于展示内容设置了多个优先级:</p><p>1.当变更的操作来源为用户手动在 MSE 控制台进行发布变更时,配置变更责任人的内容为用户的账号信息,其中:</p><ul><li>若用户使用阿里云主账号登录,则记录并呈现主账号的 UID;</li><li>若用户使用其所属的子账号登录,则记录并呈现登录使用的子账号的 UID。</li></ul><p>2.当变更的操作来源为用户使用 Nacos 的 Client 来进行配置的增删改查等操作时,MSE 会判断操作源是否携带身份信息:</p><ul><li>如果该操作源携带了身份信息,则将其识别并展示出来;</li><li>否则,MSE 会自动识别该操作源的来源 IP 并展示在配置操作人追溯列表中,便于配置审计人更加准确和全面地履行审计职责。</li></ul><p><img src="/img/remote/1460000044668984" alt="图片" title="图片"></p><h3>配置变更推送轨迹</h3><p>同时,MSE Nacos 配置变更审计平台也呈现了配置中心的推送轨迹。如下图所示,在推送轨迹页面,用户可以通过推送轨迹查询某配置相关的变更事件,也可以根据 IP 查询所有和该 IP 地址相关的推送轨迹。其中配置中心配置变更和发布的各种详细问题都在推送轨迹界面有所展示,例如:</p><ul><li>配置发布异常;</li><li>配置修改完发现某台机器不生效;</li><li>需要查看配置中心变更及推送事件。</li></ul><p><img src="/img/remote/1460000044668986" alt="图片" title="图片"></p><p>其中,变更事件、DataId、Group 分别表示分别表示本次配置变更事件类型、该配置变更事件的配置、该配置变更事件的配置所属分组。在“详情”列可以看到详情图标可以看到本次变更事件详细信息,点击详情列跳转按钮可以切换到配置维度查询的入口查询当前配置在该时间点的推送事件。</p><h3>配置监控大盘及告警</h3><p>同时,MSE Nacos 也提供了变更之后的配置监控页面,主要监测指标包括:</p><ul><li>配置中心主要业务指标:配置数、配置监听者数;</li><li>配置中心访问量指标:配置中心 TPS、QPS、写 RT、读 RT;</li><li>MSE 引擎整体的节点数、配置数、每秒查询数、每秒操作数和连接数等信息。</li></ul><p>在这个监控大盘下,用户可以在配置变更之后,进行各项配置管理核心指标的校验,例如当配置管理业务上出现推送配置不及时时,可以通过读写 RT 指标快速定位当前配置中心的相应时间;</p><p>另外,在压测场景下,用户也可以通过该大盘进行配置数、配置监听者数、TPS 等指标的实时观测;</p><p>当配置数或配置使用水位超过既设阈值时,也会给配置变更的审计者发送报警信息。</p><p><img src="/img/remote/1460000044668987" alt="图片" title="图片"></p><p><img src="/img/remote/1460000044668988" alt="图片" title="图片"></p><h2>配置变更审计最佳实践</h2><p>下面介绍如何使用 MSE Nacos 提供的配置变更审计能力,并使用该能力增强配置变更的安全性和可追溯性。</p><p>整个最佳实践可以归纳为如下几个步骤:</p><blockquote>1.开通微服务引擎 MSE<br>2.登录 MSE 控制台,并创建 Nacos 引擎实例<br>3.在 MSE Nacos 创建相关配置、修改相关配置并删除<br>4.在配置中心控制台查看配置操作人及配置变更历史<br>5.使用 Nacos Client SDK 进行配置创建和删除<br>6.在配置中心控制台查看配置操作人及配置变更来源 IP<br>7.对配置中心使用情况配置告警,当配置使用水位超过某一阈值的时候,对用户发送通知</blockquote><ol><li>开通微服务引擎 MSE</li></ol><p>您可登录微服务引擎 MSE[1],查看并开通 MSE。</p><ol start="2"><li>登录 MSE 控制台,并创建 Nacos 引擎实例</li></ol><p><img src="/img/remote/1460000044668989" alt="图片" title="图片"></p><p>登录微服务引擎 MSE 产品控制台,在左侧选项框中选择“注册配置中心”,点击“实例列表”,确定 region 后,选择“创建实例”。</p><ol start="3"><li>在 MSE Nacos 创建相关配置、修改相关配置并删除重建</li></ol><p>您可在 MSE Nacos 控制台界面手动创建配置,并做多次修改、删除及重新创建等操作。</p><p><img src="/img/remote/1460000044668990" alt="图片" title="图片"></p><ol start="4"><li>在配置中心控制台查看配置操作人及配置变更历史</li></ol><p>由下图可见,配置变更的操作人已经呈现,点击“查看”也可以看到历次配置变更的详情和变更之前的历史版本内容。</p><p><img src="/img/remote/1460000044668991" alt="图片" title="图片"></p><ol start="5"><li>使用 Nacos Client SDK 进行配置创建和删除</li></ol><p>可参考 Nacos Client SDK 使用指南[2]进行 Nacos Client SDK 的依赖安装,并进行配置创建、修改、删除等操作。</p><ol start="6"><li>在配置中心控制台查看配置操作人及配置变更来源 IP</li></ol><p>可以看到,使用 Nacos Client SDK 进行操作,即使在未开启鉴权的情况下,也留下了发布来源 IP。MSE Nacos 用户可以通过该 IP 追溯到配置变更的来源信息。</p><p><img src="/img/remote/1460000044668992" alt="图片" title="图片"></p><ol start="7"><li>添加配置用量告警</li></ol><p>此处我们添加配置水位大于 90% 时的告警,当配置使用水位超过该阈值时,会通过短信、电话等方式通知到配置变更的审计人。</p><p><img src="/img/remote/1460000044668993" alt="图片" title="图片"></p><p>注意:</p><ol><li>对于 Nacos Client SDK1.X(HTTP 版本),由于其IP信息并未携带在 HTTP 报文中,MSE Nacos 并未对其进行存储;若使用该 SDK 进行配置发布,本着配置操作人来源信息的准确性原则,并未透出该信息;</li><li>使用 Nacos Client SDK 发布,控制台可查看 IP 的功能支持需升级至 Nacos2.2.3.2 版本。但目前该版本尚在全网灰度发布中,预计 2 月中旬将全部灰度完毕,如果发现该版本尚未灰度至您所在地域,可以通过 MSE 工单解决。</li></ol><h2>MSE Nacos 配置变更审计平台未来展望</h2><p>对于配置变更的发生位置主要分为变更前和后,上述功能主要发生在变更后。而在未来,我们将一方面对于配置变更发生之前的问题进行拦截和处理,协助 MSE 用户进行配置变更的防错性措施,主要包括文件检查、参数校验等,即防御式开发;另一方面继续保障配置变更发生之后的确认和验收性工作,保证变更的正确发生。</p><p>MSE Nacos 配置变更审计平台将致力于在配置变更的整个生命周期进行相应的附加处理,来提升配置的可靠性、精准性、安全性。我们主要提出三种未来将添加进入配置变更审计平台的功能:</p><h3>文件内容校验和审批</h3><p>此功能为事前校验、预防性的配置变更审计功能,在配置变更发生之前,MSE Nacos 将发起一个审批流程,交由用户组织内部的研发管理者或运维管理者判断文件上传的内容是否符合要求;</p><p>具体的落地方案是通过 MSE 控制台进行校验、预防;另外,为了防止存在偶发的漏放情况,MSE 将允许用户设计多层次的审批结构加强校验防护。</p><h3>变更内容白名单与黑名单</h3><p>此类需求也为事前拦截、预防性的需求,在配置变更发生之前,判断本次变更的具体内容是否在白名单或者黑名单(比如是否在 yaml 文件的指定 Key 范围)之内,来保证更加精细粒度的权限管理。</p><p>例如,当运维 A 只被授权修改某配置文件 yaml 中的“useLocalCache”字段时,如果该配置变更审批修改了其他的字段,则会被黑名单拦截;而如果该变更只局限于该字段,则会被放行。即,权限受限的操作人只允许规定的配置内容的修改和变更。</p><h3>基于 WebHook 的配置变更通知</h3><p>此类需求为事后感知类的需求,当配置变更发生之后,将配置变更的情况通过多渠道及时推送至客户,让用户明确所操作带来的后果是否符合预期。</p><p>现有的实现方案则是通过 listener 进行监听。但该方案缺点则是不便于清晰感知、同时需要用户进行二次开发,而采用 Webhook 方式,结合常用的办公应用,如钉钉,企业微信,则可将变更情况推送至群\个人,更加清晰地感知,便捷地接受。</p><p><strong>相关链接:</strong></p><p>[1] Nacos/微服务引擎 MSE</p><p><a href="https://link.segmentfault.com/?enc=ALVKKhTYZ1eN0RWTWAWRWA%3D%3D.rZaY67IUAmxME094MCLEh2Jn6G6rsuqtYFV9y7Sb1fKTRKotJ3FPQrIzkqWViAExPXEwDOodhFMdgQhTQP4Iq6Emv4VZkh1mqvPLq9L6juqbJftOvp2qhv2J5BpJp%2Bhc4lqAHy%2F4Z66WWFu4KtQZnMaSWK9H8YCroJ1su8v48PKZFxTyDvxKTFUkToQISJpP51XYnuIUFHYHDtL8sFmpckgt0GBcJ%2BNHpU1Cd5ZnIk6MZYhNmUqpVz2x1OHBHTFE0fCPZkoLppK64c3lYmbifh6hSi4HgEJlkH9W3INW40HHpi5B8cr9Ja35lkJ%2BOuU5AKgMtZhu57aQd1WBc1c6M5Rqee1CTX9JOq2YwVmDfG0%3D" rel="nofollow">https://www.aliyun.com/product/aliware/mse?spm=5176.28508143....</a></p><p>[2] Nacos Client SDK 使用指南</p><p><a href="https://link.segmentfault.com/?enc=ZeX%2BZcSMqbXiKxoW%2FmJHXA%3D%3D.gCaga60QO2aoJcBb9mKv7FTYuDXzK%2Bs7lPZMDMvuioNwbwvYIOBzaoDm62ecwM9P" rel="nofollow">https://nacos.io/docs/v2/guide/user/sdk/</a></p><p>作者:孙立(涌月)、邢学超(于怀)、李艳林(彦林)</p><p><strong><a href="https://link.segmentfault.com/?enc=DqQzPQ4zS6QwJNc8HS9ZXw%3D%3D.4rgpHhJZlZXAHjRu122Ago1NwQ7F65wTjveV%2FTx%2Fo3DEy1p9Lv%2B4Ww82pmKGN%2Bbq4BPFK6fjzpGgojSftvILhsfrZpH2lUFc%2ByY901F7QsE%3D" rel="nofollow">原文链接</a></strong></p><p><strong>本文为阿里云原创内容,未经允许不得转载。</strong></p>
Higress × OpenKruiseGame 游戏网关最佳实践
https://segmentfault.com/a/1190000044668377
2024-02-29T14:02:10+08:00
2024-02-29T14:02:10+08:00
阿里云云栖号
https://segmentfault.com/u/aliyunqi
0
<p>OpenKruiseGame(下文简称:OKG)是一个面向多云的开源游戏服 Kubernetes 工作负载,是 CNCF 工作负载开源项目 OpenKruise 在游戏领域的子项目,其提供了热更新、原地升级、定向管理等常用的游戏服管理功能。而游戏作为典型的流量密集型场景,在吞吐量、延迟性能、弹性与安全性等方面对入口网关提出了很高的要求。</p><p>Higress 是基于阿里内部两年多的 Envoy 网关实践沉淀,以开源 Istio 与 Envoy 为核心构建的下一代云原生网关。Higress 实现了安全防护网关、流量网关、微服务网关三层网关合一,可以显著降低网关的部署和运维成本。Higress 可以作为 K8s 集群的 Ingress 入口网关,并且兼容了大量 K8s Nginx Ingress 的注解,可以从 K8s Nginx Ingress 快速平滑迁移到 Higress。同时也支持 K8s Gateway API 标准,支持用户从 Ingress API 平滑迁移到 Gateway API。</p><p>本文将演示 Higress 如何无缝对接 OKG 游戏服,并为其带来的优秀特性。</p><h2>Higress 无缝接入 OKG</h2><p>前置步骤:</p><ol><li>安装 OpenKruiseGame[1]。</li><li>安装 Higress[2]。</li></ol><p>OKG 提供诸多游戏服热更新和游戏服伸缩的优秀特性,便于游戏运维人员管理游戏服的全生命周期。游戏不同于无状态类型的服务,玩家战斗的网络流量是不允许被负载均衡的,因此每一个游戏服需要独立的访问地址。</p><p>使用原生工作负载(如 Deployment 或 StatefulSet)时,运维工程师需要为众多游戏服一一配置接入层网络,这无疑阻碍了开服效率,同时手动配置也无形中增加了故障的概率。OKG 提供的 GameServerSet 工作负载可以自动化地管理游戏服的接入网络,大幅度降低运维工程师的负担。</p><p>对于 TCP/UDP 网络游戏,OKG 提供了诸如 HostPort、SLB、NATGW 等网络模型;而对于 H5/WebSocket 类型的网络游戏,OKG 也相应提供了 Ingress 网络模型,如 Higress、Nginx、ALB 等。</p><p><img src="/img/remote/1460000044668379" alt="图片" title="图片"></p><p>本文采用了一款开源游戏 Posio 来构建 demo 游戏服。下述配置中,IngressClassName="higress" 指定了 Higress 作为游戏服的网络层,Higress 通过下面配置可以无缝接入 Posio 游戏服,并且可以基于 Annotation 实现 Higress 定义的高阶流量治理等功能。示例 Yaml 如下所示,GameServerSet 生成的游戏服对应的访问域名与游戏服 ID 相关。</p><p>在此例中,游戏服 0 的访问域名为 <a href="https://link.segmentfault.com/?enc=bKEDachjtv4%2B7%2F%2Byeu3L1g%3D%3D.zDV1VO4dBF4HNVlQEG7VloASF3jjUPkikd%2BWjpk6OiM%3D" rel="nofollow">http://game0.postio.example.com</a>,游戏服 1 的访问域名为 game1.postio.example.com. 客户端以此来访问不同的游戏服。</p><pre><code>piVersion: game.kruise.io/v1alpha1
kind: GameServerSet
metadata:
name: postio
namespace: default
spec:
replicas: 1
updateStrategy:
rollingUpdate:
podUpdatePolicy: InPlaceIfPossible
network:
networkType: Kubernetes-Ingress
networkConf:
- name: IngressClassName
value: "higress"
- name: Port
value: "5000"
- name: Path
value: /
- name: PathType
value: Prefix
- name: Host
value: game<id>.postio.example.com
gameServerTemplate:
spec:
containers:
- image: registry.cn-beijing.aliyuncs.com/chrisliu95/posio:8-24
name: postio</code></pre><p>OKG 水平伸缩[3]提供自动扩容、根据游戏服的 OpsState 缩容、根据 DeletionPriority 缩容、根据游戏服序号缩容等功能来支持游戏运维的业务需求。水平伸缩的特性在给游戏开发者带来便利的同时,也对入口网关提出了更高的要求:入口网关必须具备配置热更新的能力,完成路由配置的平滑下发。</p><p>原因在于:在进行游戏服的扩容时,OKG 会同步创建 Ingress 等相关网络相关资源,以此来保障游戏服的自动上线。如果入口网关不具备配置热更新的能力,在扩容时就,线上玩家就会遇到连接断开等问题,影响游玩体验。</p><h2>Nginx reload 无法优雅热更新</h2><p>在游戏服出现扩容,或者定义的路由策略发生变更时,Nginx 的配置变更会触发 reload,导致上下游的连接都断开并触发重连。</p><p>我们以 Posio 游戏服为例,模拟 Nginx+OKG 在游戏服扩容时出现的问题。Posio 服务端依赖于 Socket 连接与客户端通信。游戏服扩容时,触发对应的 Ingress 资源创建,此时 Nginx-ingress-controller 监听到 Ingress 资源变更,触发自身 reload 机制,此时原来与游戏服建立的连接(如本例中的 Socket 连接会被断开)。在正在游戏的玩家侧的体感便是出现了异常卡顿。</p><p>为了直观的展示 Nginx Ingress reload 带来的影响,我们对 Nginx 默认配置参数进行一些更改:</p><pre><code>kubectl edit configmap nginx-configuration -n kube-system
data:
...
worker-shutdown-timeout: 30s # 一个很难做权衡的配置</code></pre><p>Nginx 配置参数中 worker-shutdown-timeout 是 Nginx 的 worker 进程优雅下线的超时配置,worker 进程会先停止接收新的连接,并等待老的连接逐渐关闭,达到超时时间后,才会去强制关闭当前的所有连接,完成进程退出。</p><p>此参数配置过小,会导致大量活跃连接瞬间断开;而此参数配置过大时,又会导致 websocket 长连接始终维持住 Nginx 进程,当发生频繁 reload 时会产生大量 shutting down 状态的 worker 进程,老 worker 占有的内存迟迟得不到释放,可能会导致 OOM 引发线上故障:</p><p><img src="/img/remote/1460000044668380" alt="图片" title="图片"></p><p>实际游玩的测试过程如下:客户端访问游戏服,进行正常游玩。在此过程中通过 OKG 能力触发游戏服扩容,查看此时客户端的响应。通过网页开发者工具可以看到,出现了两条 Socket 连接,一条是原先浏览器访问游戏服建立,另一条是由于 Nginx 断连后重连产生的 Socket 连接。</p><p><img src="/img/remote/1460000044668381" alt="图片" title="图片"></p><p>原有连接收到的最后一个包时间戳是 15:10:26。</p><p><img src="/img/remote/1460000044668382" alt="图片" title="图片"></p><p>而新建连接到获取第一个正常游戏包的时间是 15:10:37,网页与游戏服的断连大概持续 5s 左右。</p><p><img src="/img/remote/1460000044668383" alt="图片" title="图片"></p><p>除了玩家的游玩体验受影响,这个机制也会给业务整体稳定性埋雷。在高并发场景下,因为连接瞬断,导致大批量客户端的并发重连,会导致 Nginx 的 CPU 瞬间飙升;而后端游戏服务器需要处理更多业务逻辑,一般比网关的资源需求更高,因此 Nginx 透传过来的大量并发重连,也更容易打垮后端,造成业务雪崩。</p><h2>Higress 如何实现优雅热更新</h2><p>Higress 支持采用 K8s Ingress 暴露游戏服外部 IP 端口,供玩家连接访问。当游戏服伸缩或者定义的路由配置发生变化时,Higress 支持路由配置的热更新,以此保障玩家连接的稳定性。</p><p><img src="/img/remote/1460000044668384" alt="图片" title="图片"></p><p>Higress 基于 Envoy 的精确配置变更管理,做到了真正的配置动态热更新。在 Envoy 中 downstream 对应 listener 配置,交由 LDS 实现配置发现;upstream 对应 cluster 配置,交由 CDS 实现配置发现。listener 配置更新重建,只会导致 downstream 连接断开,不会影响 upstream 的连接;downstream 和 upstream 的配置可以独立变更,互不影响。再进一步,listener 下的证书(cert),过滤器插件(filter),路由(router)均可以实现配置独立变更,这样不论是证书/插件/路由配置变更都不再会引起 downstream 连接断开</p><p>精确的配置变更机制,除了让 Envoy 可以实现真正的热更新,也让 Envoy 的架构变的更可靠,Envoy 配置管理从设计之初就是为数据面(DP)和控制面(CP)分离而设计的,因此使用 gRPC 实现远程配置动态拉取,并借助 proto 来规范配置字段,并保持版本兼容。这个设计实现了数据面和控制面的安全域隔离,增强了架构的安全性。</p><p>使用 OKG 接入 Higress 后,下面依然模拟客户端访问游戏服,进行正常游玩。在此过程中通过 OKG 能力触发游戏服扩容,查看此时客户端的响应。通过网页开发者工具可以看到,在此过程中客户端与游戏服建立的连接稳定不受影响。</p><p><img src="/img/remote/1460000044668385" alt="图片" title="图片"></p><p>此外,在大规模游戏服场景下,每个游戏服对应一个独立的 Ingress,会产生大量的 Ingress 资源,我们测试在达到 1k 级别规模时,Nginx Ingress 要新扩一个游戏服需要分钟级生效,而 Higress 可以在秒级生效。Nginx Ingress 的这一问题也被 Sealos 踩坑,并最终通过切换到 Higress 解决,有兴趣可以阅读这篇文章了解:《云原生网关哪家强:Sealos 网关血泪史》</p><p><strong>相关链接:</strong></p><p>[1] OpenKruiseGame</p><p><a href="https://link.segmentfault.com/?enc=%2Fni%2B3PGdCSg9H3cdSawWRQ%3D%3D.F%2Bc4XlcwJJSXd9CmB6%2B8J7rtGWQoZA5zIgohxKNYQ3B5ClPsR%2BPFgWMxlC%2F1fJi5YonX4dG%2FUkmlHy2p6SEpHQ%3D%3D" rel="nofollow">https://openkruise.io/zh/kruisegame/installation/</a></p><p>[2] Higress</p><p><a href="https://link.segmentfault.com/?enc=Zfripn6KRVTP4eHTS1yE%2FA%3D%3D.QoQ%2BteR1ntgVZebAoFim1mamnDKrr5K8JumpXCT32sShzs28qARmH9YX2xWkHh4E" rel="nofollow">https://higress.io/zh-cn/docs/user/quickstart/</a></p><p>[3] OKG 水平伸缩</p><p><a href="https://link.segmentfault.com/?enc=E%2FAGAXJeceDvjSSXgjEqrw%3D%3D.PdJb%2BHUitcSoDLQZh7mAi7T8qeLng8x79LRTYiimINeY4qRf4rhSi3KuiJ1UGE99ddyZST0YDbwLLMtguaPW5F2RQ7V3UnQz1LqjM0j9USU%3D" rel="nofollow">https://openkruise.io/zh/kruisegame/user-manuals/gameservers-...</a></p><p>作者:赵伟基、力铭、澄潭</p><p><strong><a href="https://link.segmentfault.com/?enc=wv36dKgGhIk5r9t6IR6%2FDg%3D%3D.sOK%2FsVurNYCcQrNg9qw6J%2FN38t%2BWPhUJXLv4QVy%2F5ILbnnIF%2BvLnDyKG9lOP3kpsl%2BLCPewahxikwm9fCY3InujgwIf6nF38X6rzvgoO99I%3D" rel="nofollow">原链接</a></strong></p><p><strong>本文为阿里云原创内容,未经允许不得转载。</strong></p>
应用监控 eBPF 版:实现高效协议解析的技术探索
https://segmentfault.com/a/1190000044665142
2024-02-28T14:46:03+08:00
2024-02-28T14:46:03+08:00
阿里云云栖号
https://segmentfault.com/u/aliyunqi
0
<h2>01 引言</h2><p>随着 Kuberentes 等云原生技术的飞速发展,带来了研发与运维模式的变革。企业软件架构由单体服务向分布式、微服务演进。随着业务发展,多语言、多框架、多协议的微服务在企业中越来越多,软件架构复杂度越来越高,如何快速通过可观测工具快速定位出问题对研发人员至关重要。为满足全场景、端到端的应用监控需求,应用实时监控服务 ARMS 推出应用监控 eBPF 版,通过 eBPF 技术完善整个应用监控体系。应用监控 eBPF 版提供无侵入、语言无关的可观测能力。</p><p>详细产品介绍:多语言应用监控最优选,ARMS 应用监控 eBPF 版正式发布</p><p>使用 eBPF 来进行可观测性需要进行应用层协议解析,但云上微服务软件架构中的应用层协议往往比较复杂,这也给协议解析带来了不小的挑战。传统的协议解析方式存在 CPU、内存占用高,错误率高等问题,在应用监控 eBPF 版中,我们提出一种高效的协议解析方案,实现对应用层协议的高效解析。</p><h2>02 eBPF 技术简介</h2><p>eBPF(扩展的 Berkeley 包过滤器)是一种强大的技术,允许开发人员在 Linux 内核中安全地运行预编译的程序,而不改变内核源码或加载外部模块[1]。这一独特的能力使得 eBPF 成为构建现代、灵活且高效的应用监控工具的理想选择。</p><p><img src="/img/remote/1460000044665144" alt="图片" title="图片"></p><p>$$
图 2.1 eBPF 示意图
$$</p><p>在可观测性方面,eBPF 优势尤为突出:</p><ul><li>实时性:eBPF 能够实时捕获和分析数据,为开发者提供即时的性能反馈。</li><li>精确性:通过精细的 hook 函数(hook points),eBPF 可以在系统的具体点进行监控,从而准确地收集所需数据。</li><li>灵活性:开发者可以编写定制的 eBPF 程序来监控特定事件,使其能够适应各种复杂的监控需求。</li><li>低开销:eBPF 程序直接在内核空间运行,避免了传统监控工具中频繁的用户空间和内核空间之间的上下文切换。</li><li>安全性:eBPF 程序在执行前必须通过内核的严格检查,确保不会危及系统安全。</li></ul><h2>03 传统的协议解析方案</h2><p><img src="/img/remote/1460000044665145" alt="图片" title="图片"></p><p>$$
图 3.1 传统协议解析方案架构图
$$</p><h3>3.1 传统方案的解析流程</h3><p>基于 eBPF 来做数据抓取和协议解析的传统方案主要分为:</p><ul><li>数据采集</li><li>数据传递</li><li>协议解析</li></ul><p>其中数据采集主要在内核态,数据传递介于内核态和用户态,协议解析在用户态进行。具体的,数据采集的流程为 eBPF 使用 kprobe 或 tracepoint 方式,从内核中抓取到流量事件即 event,这些事件中有控制层面的事件如从 connect、close 等系统调用处采集到的事件。也有数据层面的事件,如从 read、write 等系统调用处采集到的事件。待数据采集到内核事件后,我们需要将数据从内核态传递至用户态去做进一步的处理。在 eBPF 中,我们采用 perf buffer(一种特殊 eBPF Map)来做数据传递。数据存放到整个 perf buffer 后,在用户态进行协议解析。</p><h3>3.2 传统方案中存在的问题</h3><p>传统的解析方案中 CPU、内存占用过高,在高流量场景下错误率较高,主要体现在以下三个方面:</p><ul><li>高内存占用:数据采集中无法筛选协议,导致大量无关数据占满 perf buffer,引发内存过高。</li><li>事件丢失风险:高 QPS 导致 perf buffer 迅速填满,处理不及时会丢失事件,特别是控制层事件可能因数据层事件过多而丢失。</li><li>解析效率低:需要遍历尝试所有支持协议才能找到正确的协议,导致大量无效解析,增加 CPU 负担。</li></ul><h2>04 实现高效协议解析的技术探索</h2><h3>4.1 高效的协议解析方案流程</h3><p>鉴于上文所述传统方案中存在的问题,本文提出一种高效的协议解析方案,本文所述方案主要分为四部分:</p><ul><li>数据采集</li><li>协议推断</li><li>事件分流</li><li>协议解析</li></ul><p>其中协议解析由分为:</p><ul><li>连接维护</li><li>数据分帧</li><li>协议解析</li><li>请求-响应匹配</li></ul><p><img src="/img/remote/1460000044665146" alt="图片" title="图片"></p><p>$$
图 4.2 本文所述协议解析框架图
$$</p><p>如图 4.2 所示,eBPF 首先在内核态中采集到数据,根据协议帧头进行协议推断。根据协议推断的结果,可以初步判断改数据帧是否是所支持的协议。如果判断为“是”,才传递至用户态进行进一步解析,否则不进行处理。进行简单的事件过滤后,本文根据事件的类型进行事件分流。</p><p>如控制事件放到 control events perf buffer 中,数据事件放到 data event perf buffer。事件传递至用户态后控制事件将用于连接维护,数据事件根据其数据流向,分别放入发送队列和接收队列中。然后周期性的从对队列中的数据进行分帧处理,这样可以很好的解决单发多收、多发单收、多发多收等场景。从接受队列或发送队列(也可以理解为数据流)中拆解出单独的帧数据后将会通过按照内核态中推断的协议类型去匹配对应的协议解析器进行进一步解析。分别解析出请求与响应后,需要去匹配请求和响应,完成一个完成的可观测记录,即 record,后续也将通过 record 来生成可观测中的 Span。</p><p>本章后续小节将会重点讲解图 4.2 中的关键流程,即协议推断器(protocol infer)、协议解析进行详解。</p><h3>4.2 协议推断(protocol infer)</h3><p>顾名思义,协议推断主要用于在采集到数据包时,通过协议的协议帧头来推测是否是支持的协议类型。如果是支持的类型则将数据传递至用户态进行进一步处理。</p><p>以 MySQL5.7 协议为例:在 MySQL5.7 协议中,如果第一帧数据为 MySQL 的命令帧,如图 4.3 所示,命令帧有以下几种类型,具体见 MySQL 官方文档协议[2]。</p><p><img src="/img/remote/1460000044665148" alt="图片" title="图片"></p><p>$$
图 4.3 MySQL 命令帧
$$</p><p>但在这里,具体是不是真的是 MySQL 协议还到用户态解析时进一步确认。基于此,我们在内核中先通过简单的判读进行推断,简易的推断代码如下:</p><pre><code>static __inline enum protocol_type_t infer_mysql(const char* buf, size_t count) {
static const uint8_t query = 0x03;
static const uint8_t connect = 0x0b;
static const uint8_t stmtPrepare = 0x16;
static const uint8_t stmtExecute = 0x17;
static const uint8_t stmtClose = 0x19;
if (buf[0] == connect || buf[0] == query || buf[0] == stmtPrepare || buf[0] == stmtExecute ||
buf[0] == stmtClose) {
return request;
}
return unknown;
}</code></pre><h3>4.3 协议解析(conn tracker)</h3><p>整个协议解析流程主要是在 conn tracker 组件中进行,其主要的能力有:</p><ul><li>连接维护</li><li>数据分帧</li><li>协议解析</li><li>请求-响应匹配</li></ul><p>具体的,在长连接场景下每次数据传输的基本元数据信息,如 source ip、 source port、dest ip、dest port 等信息总是相同的。如图 4.4 所示,如果我们能够在用户态维护其连接信息,那这部分连接相关的元数据信息就不必每次都放入 perf buffer 中,只用传递连接 ID 即可,进一步降低网络带宽。</p><p><img src="/img/remote/1460000044665149" alt="图片" title="图片"></p><p>$$
图 4.4 conn tracker 连接维护图
$$</p><p>其次有部分协议,如 MySQL 协议,有部分 MySQL 相关信息,如版本号,编码等信息只在初次建立连接时候会发送包信息,如果用户态没有维护连接信息,则这部分元数据信息将无法解析。</p><p>上文提到的内核中采集到的数据会放置接收队列、发送队列两个队列中,也可以理解为数据流。从整个数据流中分解出每一帧的数据是进行协议解析的前提。基本思路是根据每种协议的结束帧标识来做判断,如 MySQL 响应的 EOF 帧信息。图 4.5 所示为 MySQL 协议分帧示意图。</p><p><img src="/img/remote/1460000044665150" alt="图片" title="图片"></p><p>$$
图 4.5 MySQL 协议分帧示意图
$$</p><p>分解出每一帧的数据后,就按照各个协议进行协议解析即可。</p><p><img src="/img/remote/1460000044665151" alt="图片" title="图片"></p><p>$$
图 4.6 MySQL 协议解析示意图
$$</p><p>在可观测中,我们需要有一个完整的请求-响应记录。以 MySQL 协议为例,由于 MySQL 协议是按照时间序有序的,请求的时间序和响应的时间序能进行对应,响应总是以 EOF 结束,EOF 帧为以下形式。</p><p><img src="/img/remote/1460000044665152" alt="图片" title="图片"></p><p>$$
图 4.7 MySQL Response 结束帧(EOF)
$$</p><p>参考 MySQL 官方文档[2]。</p><p><img src="/img/remote/1460000044665153" alt="图片" title="图片"></p><p>$$
图 4.8 MySQL 请求-响应匹配示意图
$$</p><h2>05 总结</h2><p>基于 eBPF 因其高性能,低开销,无侵入等特点近年来成为可观测性的研究热点。基于 eBPF 来进行应用监控必须进行协议解析。当前传统的协议解析方案存在 CPU、内存开销大,错误率高等问题。基于此本文提出一种高效的协议解析框架,并在阿里云应用实时监控服务 ARMS “应用监控 eBPF 版”[1]中正式发布。成功接入后将会出现如下的应用监控展示大盘,以下是展示示意图。</p><p>使用的测试项目 github 地址:alibabacloud-microservice-demo[3]</p><p><img src="/img/remote/1460000044665154" alt="图片" title="图片"></p><p>$$
图 5.1 应用监控 eBPF 版-概览
$$</p><p><img src="/img/remote/1460000044665155" alt="图片" title="图片"></p><p>$$
图 5.2 应用监控 eBPF 版-数据库分析
$$</p><p><img src="/img/remote/1460000044665156" alt="图片" title="图片"></p><p>$$
图 5.2 应用监控 eBPF 版-应用拓扑
$$</p><p>具体接入流程见下方链接,仅需一分钟即可无死角监控您的应用。</p><p><strong>参考链接:</strong></p><p>[1] 多语言应用监控最优选,ARMS 应用监控 eBPF 版正式发布</p><p>[2] <a href="https://link.segmentfault.com/?enc=wAJ8LDc7SfJsTHVFJZldTw%3D%3D.b6NVn5Hb8lva9JscUflf3S2bj1Ua9MSCxMJPa%2FmVFGe1%2BBIr3i2p5ukXIGOsGk0VJ7vx0Mcm2BONZ9kNRdeZ2Rw6oi%2BOLxDDOoj2S9%2FIyiYA5mLKIddDLnuB76Xch3pC" rel="nofollow">https://dev.mysql.com/doc/dev/mysql-server/latest/page_protoc...</a></p><p>[3] <a href="https://link.segmentfault.com/?enc=DC7bQowgKSFHlXtzrqq42Q%3D%3D.Cyu1SsHJL%2FbET5dOB8n8FMlLiDhFnnKipmqCg0YX01faRCrqRsRpWXg3A0mNuxTb2cEnHYpPE7Tf386HmcTosA%3D%3D" rel="nofollow">https://github.com/aliyun/alibabacloud-microservice-demo</a></p><p>作者:彦鸿</p><p><strong><a href="https://link.segmentfault.com/?enc=Kyg7L9lg%2FtcTgyGF6nbfhQ%3D%3D.VKWzkabZhiAZWKSCrqygCXbLC1vraj2hIQFbWVfQbq5L0RW0eaynFCvCo0%2BNXgWWWjolA3XkjvczIV4OFj5zAJ1d6Kdm2ekL%2FvzyMG%2FKack%3D" rel="nofollow">原文链接</a></strong></p><p><strong>本文为阿里云原创内容,未经允许不得转载。</strong></p>
阿里云推出 3.x Java 探针,解锁应用观测与治理的全新姿势
https://segmentfault.com/a/1190000044662540
2024-02-27T16:31:48+08:00
2024-02-27T16:31:48+08:00
阿里云云栖号
https://segmentfault.com/u/aliyunqi
0
<h2>前言</h2><p>随着春节大促即将到来,为了确保线上业务高效稳定地运行,电商企业大多会对旗下关键业务应用进行多轮测试。通过模拟线上较高流量的请求,来观察服务性能的实际表现。以某企业的业务测试报告举例:</p><p><img src="/img/remote/1460000044662542" alt="图片" title="图片"></p><p><img src="/img/remote/1460000044662543" alt="图片" title="图片"></p><p>$$
图 1 压测报告显示,成功率非常低,且全局接口成功率都很低
$$</p><p>通过报告可以看到:当应用所承受的流量增加至特定临界点时,请求成功率大幅下降,导致整个测试周期内平均成功率相当惨淡,仅有 9.89%,并伴随着较高的响应时间(RT)。经过深入分析,发现这种高失败率现象普遍存在于所有接口上,并且在整个压测过程中未显示出任何回归稳定状态的迹象。</p><p>面对这类压测结果的直观推断是应用可能已达到其性能瓶颈。Prometheus 监控所采集的 CPU 使用情况进一步印证了这一假设:应用实例的 CPU 使用率几乎达到饱和状态,应用在当前情景下无法处理如此高 TPS(每秒事务数)。该企业采用的优化手段为:一方面,通过链路追踪(Tracing)数据和 CPU 火焰图,逐步定位到代码层面性能瓶颈,并开展针对性优化;另一方面,为应用集成开源的流量控制防护和熔断降级组件来应对线上流量的不确定性,并对关键业务应用进行扩容处理,进一步增强应用可用性。</p><p><img src="/img/remote/1460000044662544" alt="图片" title="图片"></p><p>$$
图 2 压测过程中应用实例 pod 的 CPU 指标
$$</p><p>在实际业务场景中类似问题并不少见,并可以总结为以下两个挑战:</p><ul><li>如何定位复杂业务系统中的性能瓶颈?</li><li>如何应对流量的不确定性,保护好我们的服务?</li></ul><p>示例中的公司对于以上问题给出了自己的解答:模拟线上流量开展性能测试,以 Tracing 数据 + CPU 火焰图作为问题定位依据,通过流控和熔断降级来保护服务。上述方案在开源领域拥有比较成熟的落地实践:</p><ul><li>使用 OpenTelemetry 的 SDK/Agent 采集 Tracing 数据[1]</li><li>使用 Async Profiler 工具生成 CPU 火焰图[2]</li><li>使用 Sentinel 实现流量治理[3]</li></ul><p>但实际上,无论是对业务代码进行改造,还是搭建 OpenTelemetry 服务端用于数据接收,都会带来一定的成本投入,研发不再能专注于业务代码开发和维护。那么,是否有无侵入、自动化方式来解决问题呢?阿里云推出的全新 3.x 版本 Java 探针为这些问题带来了全新回答。</p><p>Java 探针(也称为 JavaAgent)可以在应用运行态增强应用本身的字节码,业务应用本身不需要做任何代码改动即可实现额外能力的扩展[4]。部署在 kubernetes 中的应用,还可以基于 init-container 实现探针自动注入,进一步降低接入成本。</p><h2>如何定位业务系统性能瓶颈?</h2><p>正如前文所说,在定位和优化慢调用问题时,除了观测应用的各个关键指标外,还有“两大法宝”:调用链数据(Tracing)和 CPU 火焰图,可以帮助定位业务调用中耗时较长、CPU 较高的代码片段然后做对应修复。然而,这“两大法宝”却各有自己的“硬伤”:</p><h3>Tracing 数据常常存在观测盲区</h3><p>对 Tracing 而言,其数据一般依赖 Agent/SDK 提供的自动或手动的埋点实现数据采集,然后上报到 Tracing 数据收集端(Collector)存储,再由展示端的 Dashboard 关联并展示出来。显然,一条链路的精细程度取决于埋点的颗粒度。但实际上,Tracing 数据的采集也会带来一定的开销,并不会无限制地细分粒度,只会对通用框架中的关键方法进行埋点。那么对于某些业务中的高开销逻辑,往往就可能缺失埋点,从而无法对业务逻辑的耗时进行准确判断,类似下图中的埋点缺失问题在调用链中经常存在。</p><p><img src="/img/remote/1460000044662545" alt="图片" title="图片"></p><p>$$
图 3 常见的 Tracing 数据中容易存在未覆盖埋点导致的观测盲区
$$</p><h3>CPU 火焰图难以帮助定位线上问题</h3><p>对 CPU 火焰图而言,可以直观展现业务应用执行过程中 CPU 密集点。火焰图中方法栈宽度代表方法执行时长,通过对“宽底座”、“大平头”的方法开展优化,缩减其调用耗时以达到性能提升效果。然而,许多隐藏的性能问题在测试阶段往往不容易暴露出来,但在线上环境却能显露无余。而火焰图的生成需要花一些时间来采集,当集中于对线上业务进行止血的时候,现场的保存往往有所缺失,毕竟不可能在线上问题发生后先跑个 5 分钟的火焰图。这可能会让整个问题的定位复盘过程变得更加复杂。</p><p><img src="/img/remote/1460000044662546" alt="图片" title="图片"></p><p>$$
图 4 常见 CPU 火焰图中的“大平头”与“宽底座”
$$</p><p>那么,有没有一种不需要手动建立密集埋点就能观测到 Tracing 数据盲区,又可以自动识别慢 trace,并将相关方法栈的 CPU 火焰图过滤和关联到对应 Trace 的方法呢?应用实时监控服务(ARMS)在 3.x 版本 Java 探针中通过“代码热点”功能给出了答案。</p><p>接下来,以解析并遍历 JSON 数据及调用下游 HTTP 接口场景举例:</p><pre><code>public class HotSpotAction extends AbsAction {
private RestTemplate restTemplate = new RestTemplate();
//请求入口方法
@Override
public void runBusiness() {
readFile();
invokeAPI();
}
//执行HTTP调用
private void invokeAPI() {
String url = "https://httpbin.org/get";
String response = restTemplate.getForObject(url, String.class);
}
//读取文件数据并解析
private double readFile() {
InputStreamReader reader = new InputStreamReader(
ClassLoader.getSystemResourceAsStream("data/xxx.json"));
LinkedList<Movie> movieList = GSON.fromJson(reader, new TypeToken<LinkedList<Movie>>() {
}.getType());
double totalCount = 0;
for (int i = 0; i < movieList.size(); i++) {
totalCount += movieList.get(i).rating();
}
return totalCount;
}
}</code></pre><p>结合下图,对于上述接口,在 Tracing 系统中找到一条慢调用链。可以看到本条调用链共计耗时达到了 2649ms,但后两个 Span 跟第一个 Span 之间存在 2s 多的耗时盲区(这段逻辑对应上述执行 JSON 数据解析),单纯依赖于 Tracing 系统,并没有办法定位到缺失的 2s 耗时具体发生在哪段代码中。</p><p><img src="/img/remote/1460000044662547" alt="图片" title="图片"></p><p>$$
图 5 业务系统的 Tracing 数据,可以看到第二条 span 之前存在一块观测盲区
$$</p><p>针对上述问题,接入 ARMS 最新版本探针并开启代码热点后,该问题根因定位就变更非常简单了。仅需单击调用链详情中的代码热点页签,可以在右侧的火焰图中看到相比 Tracing 除了左侧的 HTTP 相关方法栈(对应 Tracing 中的 HTTP 调用),还包含 com.alibaba.cloud.pressure.memory.HotSpotAction.readFile() 导致的 1.91s 执行耗时:</p><p><img src="/img/remote/1460000044662548" alt="图片" title="图片"></p><p>$$
图 6 代码热点页签中的实际展示,可以直观看到耗时较高的方法栈
$$</p><p>图中左侧为本次调用中所涉及的所有方法所耗时情况列表,右侧为对应方法所有方法栈信息所绘制的火焰图,其中:</p><p>1)"Self" 列显示方法自身消耗的时间或资源。</p><ul><li>这个指标表示方法在自身的调用栈中所消耗时间或资源,不包括其子方法调用所消耗时间或资源。</li><li>帮助识别哪些方法在自身内部花费了大量时间或资源。</li></ul><p>2)"Total" 列显示方法及其所有子方法调用所消耗的总时间或资源。</p><ul><li>这个指标包括方法自身消耗时间或资源,以及其所有子方法调用所消耗的时间或资源。</li><li>帮助了解整个方法调用栈中哪些方法所贡献了最多的时间或资源。</li></ul><p>对于如何使用代码热点功能生成的火焰图定位慢调用根因,可以通过重点关注 Self 这一列或者直接看右侧火焰图中底部的较宽火苗从中定位到高耗时的业务方法,较宽火苗其是引发上层耗时高的根源,一般是系统性能的瓶颈所在。</p><p>从上图中不难看到,本文中的慢调用核心原因就是因为 LinkedList 不具备随机访问的能力,在频繁查的场景下开销较高,通过将其重构为 ArrayList 等有索引的 List 实现就可以解决这一问题。其他更多有关代码热点的使用细节可以参考该功能相关用户文档[5]</p><h2>如何应对流量的不确定性?</h2><p>其实在压测过程中,如果已配置依靠 CPU 指标/流量指标的弹性,为什么请求成功率还是会持续劣化?经过分析,从指标到达阈值到新的服务实例就绪过程中其实存在一定的时间间隔(可能是因为 Java 应用启动较慢的原因,达到了秒级别的启动时长),在突增流量场景下出现新服务实例还未就绪,老服务实例就已经过载情况。此时业务成功率大幅下跌原因,一部分是因为老服务实例过载;另一个原因是,由于原有实例过载,请求处理能力下降,导致大量流量涌入新启动的服务实例,从而导致新服务实例也因为过大流量而引起过载,陷入不断重启不断扩容的“最坏情况”。当系统面对突增流量,是否有手段可以有效地保护系统始终处于稳态情况?</p><p>那就是微服务引擎(MSE)的最新特性,自适应过载保护。</p><p><img src="/img/remote/1460000044662549" alt="图片" title="图片"></p><p>$$
图 7 MSE 自适应过载保护页面
$$</p><p>正常情况下,面对突然到来的流量洪峰(弹性来不及扩容),会导致 CPU 飙升(即系统负载上升),全局接口出现明显的性能劣化,比如 RT 持续增加、成功率大幅度下跌。</p><p><img src="/img/remote/1460000044662550" alt="图片" title="图片"></p><p>$$
图 8 开启过载保护后的大流量压测情况
$$</p><p>Aliyun JavaAgent 3.x 版本提供了自适应过载保护能力,可以有效地保护我们系统。自适应过载保护会在 CPU 使用率到达阈值时调整限流策略,以一定比例进行限流,保障系统负载处于稳定水平,使得全局接口保持较高 RT 及成功率。</p><p><img src="/img/remote/1460000044662551" alt="图片" title="图片"></p><p>$$
图 9 开启过载保护后的大流量下接口表现
$$</p><p>总成功率 50.99%,在 /xx 接口流量突增后,全局所有接口成功率开始下降,RT 也快速飙升,自适应过载保护生效,成功率逐步上升,RT 也快速回落到正常水平。需要注意的是,压测中限流也被当成普通异常处理,因此在成功率上仅 50.99%(实际在去除了限流的异常后请求成功率在 80% 左右,从后半段 RT 表现中也可以看到。)</p><h2>3.x Java 探针,全新的能力矩阵</h2><p>前文中提到的“代码热点”与“自适应过载保护”特性,都是以阿里云推出的全新 3.x Java 探针作为底座实现的功能,该组件为您的 Java 应用提供了一整套无侵入的接入方案,深度集成了 OpenTelemetry、Arthas、Sentinel 等多种可观测与微服务治理组件与方案。帮您快速、无感地接入应用实时监控服务(ARMS)、微服务引擎(MSE)、企业级分布式应用服务(EDAS)、Serverless 应用引擎(SAE)等云产品的重要功能。</p><h3>如何接入 3.x Java 探针</h3><p>阿里云 Java 探针提供了多种便捷的接入方式,且可以依据您的需求定制可观测和服务治理能力的接入与否。您可以参考 ARMS 应用监控接入概述[9]与 MSE 服务治理应用接入[10]进行接入。</p><p>对于运行在阿里云容器服务 ACK[11]中的应用,您可以采用最简单的接入方式:基于 Pilot 模式实现探针的自动注入以及配置,无需修改镜像,只需要在应用 Yaml 中加入几个 label 就可以为 Java 应用接入可观测或服务治理能力。</p><p>首先为 ACK 集群安装 ack-onepilot,如图所示:</p><p><img src="/img/remote/1460000044662552" alt="图片" title="图片"></p><p>$$
图 10 安装 ack-onepilot
$$</p><p>安装完成之后,在 ACK 集群内创建Java应用,并在 pod 的 spec.template.metadata 字段中添加几个 label,您也可以直接编辑 Deployment 的 yaml 文件,在 spec.template.metadata.labels 下为 pod 添加 label:</p><p>如果您需要接入 ARMS 应用实时监控服务,请添加以下两个 label:</p><pre><code>armsPilotAutoEnable: "on"
armsPilotCreateAppName: "${接入到ARMS的应用名}"</code></pre><p>如果您需要接入 MSE 微服务治理服务,请添加以下三个 label:</p><pre><code>msePilotAutoEnable: "on"
msePilotCreateAppName: "${接入到MSE的应用名}"
mseNamespace: "${接入到MSE的命名空间}"</code></pre><p>应用成功部署后,您可以在 ACK 控制台上看到对应的 Deployment,点击“ARMS 控制台”即可跳转到 ARMS 控制台查看应用的监控信息。</p><p><img src="/img/remote/1460000044662553" alt="图片" title="图片"></p><p>$$
图 11 从 ACK 控制台跳转到 ARMS 控制台
$$</p><p>如果您的应用接入了 MSE 微服务治理,可以在 ACK 控制台上点击更多 > 微服务治理按钮直接跳转至 MSE 服务治理控制台。</p><p><img src="/img/remote/1460000044662554" alt="图片" title="图片"></p><p>$$
图 12 从 ACK 控制台跳转到 MSE 控制台
$$</p><h3>版本改动一览</h3><p>除“代码热点”、“自适应过载保护”功能外,本次 Java 探针中还带来了其他全新特性:</p><ul><li>支持 Java 21 应用的字节码增强,一个探针可同时支持 Java 8-21 应用的无侵入式可观测数据采集和微服务治理解决方案。</li><li>ARMS 数据上报架构全面升级,基于短连接和上报压缩,进一步浓缩上报数据,数据上报成功率从原有的 99% 提升到 99.99%,提供更加稳定可用的数据采集服务。</li><li>ARMS 重磅推出慢调用诊断利器——基于调用链的代码热点功能,提供接口慢调用过程的自动观测能力,帮助分析代码执行中的性能瓶颈,详情请参考使用代码热点诊断慢调用链的问题[5]。</li><li>ARMS 开展性能优化,应用接入更加轻量化,更加无感;2c4g 双副本规格的容器场景下,挂载探针带来的额外 CPU 开销相较过往版本降低 50%,接近极限 TPS 场景下 CPU 仅增加 10%,使用异步框架的场景 CPU 开销优化幅度达到 65%,性能表现更加良好;启动时间大幅度优化,探针挂载启动耗时降低到 5 秒内,通过容器方式接入,init-container 启动耗时降低到 6 秒内,探针整体启动耗时缩减 10s+。详情请参考ARMS Java探针性能压测报告[6]。</li><li>ARMS 支持 Vert.x、Reactor-Netty 等异步框架的完整耗时统计,补充了 OceanBase、xxl-job 等组件的自动化埋点,同时对已有的组件如 PostgreSQL、Kafka 等埋点进行优化,提供了更加精准、更加丰富的指标和 Span 数据,详情请参考 ARMS 支持的 Java 组件和框架[7]。</li><li>MSE 流量防护实现对 RPC 调用行为的自定义支持,详情参考配置 MSE 流量防护行为[8]。</li><li>MSE 流量防护支持自适应过载保护,基于 CPU 指标以及自适应算法自动保护系统不被过大的流量打垮[12]。</li></ul><h2>结语</h2><p>JavaAgent 技术通过其字节码增强的特点,可以无侵入地增强Java微服务的功能,为用户带来了全新的产品能力体验。通过本文的说明,我们可以发现阿里云 3.x 版本探针不仅引入了激动人心的新特性,而且在使用体验上也实现了质的飞跃。</p><ul><li>在性能方面:探针挂载启动耗时降低到 5 秒内,探针整体启动耗时缩减 10s+;挂载探针带来的额外 CPU 开销相较过往版本降低 50%;接近极限 TPS 场景下 CPU 仅增加 10%;</li><li>在特性方面:带来了诊断、治理领域新特性,自适应负载保护、慢调用诊断、Java 21 的支持等。</li></ul><p>当然 3.x 系列 Java 探针并不是终点,为了达成阿里云上的微服务永远在线的目标,我们才刚刚起航。最新的 4.x 版本已经在邀约灰度中,该版本探针完全兼容开源 OpenTracing 协议,新增了自定义线程池的监控,同时提供了更广的自动埋点支持范围与更可靠的异步 tracing 能力,欢迎对新版探针感兴趣的客户联系进行灰度升级,第一时间使用新探针的特性。</p><p><strong>相关链接:</strong></p><p>[1] OpenTelemetry 官方网站</p><p><a href="https://link.segmentfault.com/?enc=QOisjOudwTQxJNzk6Vytgg%3D%3D.fk66SOX9ztePgaILgGKt%2FZlKCicHBkLXLVuLqarYoN0%3D" rel="nofollow">https://opentelemetry.io/</a></p><p>[2] Async Profiler 工具</p><p><a href="https://link.segmentfault.com/?enc=Us2Em%2FzjMLfiuLqAhj4W%2Fw%3D%3D.w4tSghE7nkr4fF67lIr2qTHdKdOB5fRHw12XcIbpJwUj75DexrAtUlruDeLHTbmUNHTghrxZ67HXGGnaSB02Zg%3D%3D" rel="nofollow">https://github.com/async-profiler/async-profiler</a></p><p>[3] 使用 Sentinel 进行流量治理</p><p><a href="https://link.segmentfault.com/?enc=OrsrhzoxXnRlZn61N3C%2BgA%3D%3D.XUm6xvkWNGt%2FyVe7H%2BcJ4fi3m2wosTZ6VjBeDvDWJsbIMEwOGEwQvJA7zGNfGi%2BU%2F0ddVRb5waQWYEYZKInhlQ%3D%3D" rel="nofollow">http://sentinelguard.io/zh-cn/docs/introduction.html</a></p><p>[4] 什么是 Java agent</p><p><a href="https://link.segmentfault.com/?enc=5kTql2b5XCQk%2FQp37Btatw%3D%3D.jvPn2LfYuTut%2BzcrRX4QCd%2BOy%2FmE4q1U0bIkuOGpYpGnBsRyzpbR%2BsUgXbctAgcKWfFfw7vUzss%2Bl%2FAEmXnumQ%3D%3D" rel="nofollow">https://www.developer.com/design/what-is-java-agent/</a></p><p>[5] 使用代码热点诊断慢调用链的问题</p><p><a href="https://link.segmentfault.com/?enc=J8HpfZrvASSSl27aRDEu3w%3D%3D.2ZPyztjsWDbxplmLn5TmjpbwedJ2VX6LrZ3VwM5l4Otr26%2BS7nlv5H%2BEqkvb%2BF9B7wPtHliVAzRUvMuL7UA2kUth4RmoqfG1jBcD18nes%2B1qLR9h1fQsJDg0RMalqhYmwlLXDjEXQrMUUv4bZcg5pwtSwFwEvDQKEtROBXcyu4s%3D" rel="nofollow">https://help.aliyun.com/zh/arms/application-monitoring/user-g...</a></p><p>[6] Aliyun JavaAgent 性能压测报告</p><p><a href="https://link.segmentfault.com/?enc=Pol2mTXlOo9WZ5IOKHlXtQ%3D%3D.9iQz07U2RxgIQuHTwQwJDeFhNmlF9SyXJg3PeL3fxjgm4Gz4voxdiKPUMHZ8YePAxUN7%2B0N7ywdMHSVjdx9ew7%2BuntboydIPK9akblhOvK2fPrEmHQ7n1zDFNjli%2FfkJ8f5mg2Cnz%2BlmHpAX3d68bZYUuOMW477OZ%2FpyflY8S7JLk6vZ0z6z9NdM7dtzuc2eRlHiEb7tOzlPgtdqxqJPrQ%3D%3D" rel="nofollow">https://help.aliyun.com/zh/arms/application-monitoring/develo...</a></p><p>[7] ARMS 应用监控支持的 Java 组件和框架</p><p><a href="https://link.segmentfault.com/?enc=YGctV0P1vnlEETS7iEPKSg%3D%3D.QGbfuCyZc2fpZdgvL%2Bo1oZDDsddqCVrzvdT%2Fs%2B8Z5UzXOUK0t2VG5M49FGKe0b1TpwGy7foXx0ll21R0LDAxEpizinXTQAE8uDeOor%2Bh1pFa%2FV3FeqO3vaxxwFG707nIYelvb7jVXgpJOI2swVZm40rUggQiEHUFZebk%2FI3SRvE%3D" rel="nofollow">https://help.aliyun.com/zh/arms/application-monitoring/develo...</a></p><p>[8] 配置 MSE 流量防护行为</p><p><a href="https://link.segmentfault.com/?enc=AYxyZHGxq6AKb2l1U7um%2Fw%3D%3D.UfxkOeTcDOOiQlmY%2FOkVxhlZyEEV8prVTWG9m972IXNKeRXM9SPH3yOKWZviktii1eULmh92T5ASoPh%2F2Gh4kd27a72EOOLzJnqePXBggO4BF87xc4o0EepCNHJpEt%2FIysk05PfdWWZdoztWYexw4R87AQ6aEq%2Fw%2FoKiK9D%2FqzE%3D" rel="nofollow">https://help.aliyun.com/zh/mse/user-guide/configure-web-behav...</a></p><p>[9] ARMS 应用监控接入概述</p><p><a href="https://link.segmentfault.com/?enc=rS3gXuiRHlxvrSjcFxvupQ%3D%3D.COomLZxLvlAu4PCbZr315hWmILn1xl8d6EHxMnQicFVTbkPfHll4Md7zLXndMrexc0csQzEc4InRneK3c9PtznL%2BQypXzb5H29iMjVKIrjA%3D" rel="nofollow">https://help.aliyun.com/zh/arms/application-monitoring/gettin...</a></p><p>[10] MSE 服务治理应用接入</p><p><a href="https://link.segmentfault.com/?enc=%2BbfwxK2i9m4F5%2Fo3po13GA%3D%3D.4pUtuBVIFqzXEErEUdLCpzIutb8LJb320cpf%2B9iQTx5MKWddwzR9p38%2FvlbBAjogsybY9mOchKcncdKNPd3WcmM4bQAcT58I9fFhWePYopMNXsLEH5rrpQjqfytqqNwptzY8Lprss3gd%2BPc4b72vPg%3D%3D" rel="nofollow">https://help.aliyun.com/zh/mse/user-guide/application-access-...</a></p><p>[11] 容器服务 Kubernetes 版 ACK</p><p><a href="https://link.segmentfault.com/?enc=q6%2F53mB7dXm5tD4vCfiYCQ%3D%3D.rhcE9cZpCif%2B6WWFNmyVNXc988P7RiW1wYpM0VXJ3bgeTrODI939IN%2BwFiUi3FSW" rel="nofollow">https://www.aliyun.com/product/kubernetes</a></p><p>[12] 配置系统防护</p><p><a href="https://link.segmentfault.com/?enc=SWOIFcRvtzwPu%2BMeI0k9Ow%3D%3D.VYUsmckYcIbClOzNcPeWclQKjFsx9LRHQa6nQqBAIAd%2BxKefRDAVLCNYVPnYALDScl9m6Xmn9jkjIAOauHeZM2Uq%2BvFOTC7NJYj1SMw7POEomauWd9CTbGGPkV7Z%2FhBa" rel="nofollow">https://help.aliyun.com/zh/mse/user-guide/configure-system-pr...</a></p><p>作者:张铭辉、泮圣伟</p><p><strong><a href="https://link.segmentfault.com/?enc=k1vmlJOB6mg%2Fu4fw%2B7x2Cw%3D%3D.l5qb%2BngEUA5%2Bjt7mbRKRsdL2TwMI9s6iXCUSHJhU9CL279XTh9YpGs9uAZ1yxhoqcSoDUdT7o%2BMLDb11qitXu%2FIaEMMdswI1gYBjWbxMNCE%3D" rel="nofollow">原文链接</a></strong></p><p><strong>本文为阿里云原创内容,未经允许不得转载。</strong></p>
Kube Queue:Kubernetes 任务排队的利器
https://segmentfault.com/a/1190000044662298
2024-02-27T15:34:51+08:00
2024-02-27T15:34:51+08:00
阿里云云栖号
https://segmentfault.com/u/aliyunqi
0
<p>批处理作业(Batch Job)常应用于数据处理、仿真计算、科学计算和人工智能等领域,主要用于执行一次数据处理或模型训练任务。由于这类任务往往需要消耗大量计算资源,因此必须根据任务的优先级和提交者的可用资源情况进行合理排队,才能最大化集群资源的利用效率。</p><h2>Scheduler 在任务调度领域水土不服</h2><p>当前 Kubernetes 的调度器提供了完善的 Pod 通用调度功能,但是在面对大量任务排队时,依然暴露出了局限性:</p><ul><li>缺少自动化的排队机制</li></ul><p>默认情况下,批处理任务会直接创建作业 Pod,当集群可用资源不足时,大量 Pending Pod 会严重拖慢 Kubernetes 调度器的处理速度,影响在线业务扩容和调度。因此,迫切需要能够自动根据集群资源控制作业启停的自动化排队机制。</p><ul><li>缺少多样化的排队策略</li></ul><p>为提升任务排队效率,需要根据集群资源和任务规模,采取阻塞队列、优先级队列、回填调度等不同的排队策略。然而,Kubernetes 调度器的默认调度策略主要根据优先级和 Pod 创建顺序进行排队,难以应对多样化的任务排队需求。</p><ul><li>缺少多队列能力</li></ul><p>为隔离不同用户或租户的任务,避免资源被单一用户的大量任务占满,导致其它用户“饿死”,任务排队系统需要支持多队列管理,将不同用户提交的任务分配到不同队列中排队。目前,Kubernetes 调度器仅支持单一队列,无法有效避免此类问题。</p><ul><li>大量任务类型难以统一</li></ul><p>在机器学习、高性能计算、大数据计算和离线工作流等不同应用场景下,用户会提交不同类型的任务,每类任务对资源和优先级的计算方法都有所不同,将这些计算逻辑都集成到调度器中,必然大幅增加维护复杂性和运维成本。</p><p>因此,在处理复杂的任务调度场景时,云服务提供商通常不将原生 Kubernetes 调度器作为首选方案。</p><h2>Queue 在 Kubernetes 中的定位与职责</h2><p>在 Kubernetes 集群中,Queue 与 Scheduler 共同协作以确保任务的高效调度。为了避免“脑裂”等典型的分布式系统问题,必须清晰划分它们的职责。目前,Kubernetes 中的 Queue 可以分为两类:</p><p>第一类 Queue 与 Kubernetes 的 Scheduler 属于不同分层。Queue 负责任务的排序和按顺序出队,专注于任务的生命周期管理和实现更公平的用户间出队策略;Scheduler 负责任务 Pod 的合理编排,找到最优的放置策略,专注于节点亲和性、拓扑感知等方面。这类 Queue 不直接感知底层的物理信息,任务出队后可能会因为节点亲和性、资源碎片化等因素无法调度,导致队头阻塞。因此,这类队列通常需要引入“任务在无法调度时重新入队”的机制。本文将介绍的 Kube Queue 和开源社区中的 Kueue 都是这类 Queue 的代表。</p><p>第二类 Queue 与 Scheduler 相互耦合,任务只有在确保能够调度的情况下才会出队。这种设计避免了第一类 Queue 的队头阻塞问题,但是依然存在难以完全兼容调度器全部调度语法的问题。而且,使用这类 Queue 意味着需要替换默认调度器,对集群而言是较大的变更。这类 Queue 的典型代表有 Volcano 和 YuniKorn。</p><p><img src="/img/remote/1460000044662300" alt="图片" title="图片"></p><h2>Kube Queue 概述</h2><p>Kube Queue 是阿里云容器服务 ACK 的云原生 AI 套件中的一个关键组件,旨在解决以上 Kubernetes 调度器在任务调度场景中存在的问题。Kube Queue 通过与云原生 AI 套件的 Arena 组件以及 ACK 集群的弹性 Quota 特性相结合,能够高效支持多种 AI 任务自动排队和多租户 Quota 管理。</p><p>Kube Queue 的架构如下图所示,由以下主要部分构成:</p><ol><li>Kube Queue Controller:负责任务排队的核心控制器,如下图左侧所示。</li><li>Operator Extension:为不同任务类型提供定制化支持的扩展组件,如下图右侧所示。</li></ol><p><img src="/img/remote/1460000044662301" alt="图片" title="图片"></p><h2>Kube Queue 的工作机制</h2><p>任务排队系统围绕两个核心抽象——Queue 和 QueueUnit:</p><p>Queue:代表一个队列实体,是队列进行排队的容器,它包含队列的策略、Quota、排队参数等信息。目前 Kube Queue 能够自动感知不同种类的资源配额,如 Resource Quota、Elastic Quota 和 ElasticQuotaTree。Kube Queue Controller 会根据这些 Quota 的配置自动创建对应的 Queue 对象。用户仅需要配置上层的 Quota,无需额外配置底层队列。</p><p>QueueUnit:代表一个任务实体,它会忽略原任务中与排队策略无关的参数信息,从而减少 Kube Queue Controller 需要监听的对象类型以及与 Api Server 建立的连接数。并且,由于 QueueUnit 屏蔽了实际 Job 的类型,任何需要接入排队系统的任务,仅需实现 Extension 的排队接口即可,有效实现了任务类型的可扩展。</p><p>工作流程如下:</p><p>任务提交和入队:当一个可被 Kube Queue 识别的任务被提交到 Api Server,对应的 Job Operator 和 Operator Extension 会收到任务创建事件。它们会根据任务提交时是否为挂起状态,决定是否接管任务排队。若任务提交时处于挂起状态,Extension 会评估任务所需资源和确定优先级等关键排队参数,并创建 QueueUnit(这是在 Kube Queue 排队的统一对象,其初始状态为 Enqueued)。</p><p>任务排队和等待调度:Kube Queue Controller 接收到 QueueUnit 的创建后,会根据内部队列归属策略确定 QueueUnit 所属队列,并在队列内根据优先级与创建时间进行排序。Kube Queue Controller 通过一个调度循环处理所有队列,每轮循环会从每个队列中抽取出队头的任务尝试调度,以此确保不同队列中的任务数量和优先级不会互相干扰。</p><p>任务出队和执行调度:任务出队后,QueueUnit 状态更新为 Dequeued,Extension 接收到此状态后会移除该任务的挂起状态。Operator 监听到任务解除挂起后,会开始创建任务 Pod,此后任务进入正常的调度流程。若任务在一个可配置的超时时段内未完成调度,Extension 会将对应的 QueueUnit 重置为 Enqueued 状态,代表任务启动超时,需要重新排队,这样做是为了防止队列出现队头阻塞。若任务成功执行,QueueUnit 的状态则会被更新为 Running。</p><p><img src="/img/remote/1460000044662302" alt="图片" title="图片"></p><h2>Kube Queue 的排队策略</h2><p>排队策略是排队系统不可缺少的部分。目前,Kube Queue 提供了三种灵活的排队策略以满足企业客户的多样化需求,且每个队列都可配置独立的排队策略。</p><h3>轮转策略(默认策略)</h3><p>ack-kube-queue 默认采用与 kube-scheduler 相同的任务轮转机制处理任务,即所有任务在队列中依次请求资源,请求失败则进入 Unschedulable 队列退避,等待下次调度。该策略确保每个任务均有机会调度,最大效率利用 Quota,但对于出队的任务可能无法严格保证优先级。推荐在希望保证集群资源利用率的情况下使用该策略。</p><h3>阻塞策略</h3><p>当集群中存在大量资源需求量小的任务时,由于小任务会占用大量队列轮转时间,资源需求量大的任务将难以获得资源执行,存在长时间 Pending 的风险。为了避免此类情况,ack-kube-queue 提供阻塞队列功能,开启后,队列将只调度队列最前端的任务,使得大任务能够有机会执行。推荐在希望保证任务优先级的情况下使用该策略。</p><h3>严格优先级策略</h3><p>为了保证高优先级任务能够在集群获得空闲资源时被优先尝试调度,即便它们仍处于退避阶段,ack-kube-queue 提供严格优先级调度功能。开启后,队列将在运行中的任务结束后,从最早提交的高优先级任务开始尝试执行,使其优先获得集群空闲资源,避免资源被低优先级任务占用。该策略是轮转策略和阻塞策略的折中策略。</p><h3>快速上手 Kube Queue</h3><p>在本节中,我们将通过一个实际案例演示如何使用 Kube Queue 执行一个基本的任务排队操作。</p><p>首先,需要安装 kube-queue 组件,在阿里云容器服务 ACK 产品的云原生 AI 套件页面中即可一键安装。可参考:如何安装及使用任务队列 ack-kube-queue[1]</p><p>安装了 Kube Queue 之后,在集群的 kube-queue 命名空间下会存在 Kube Queue Controller 和多个针对不同 Job 类型提供扩展支持的 Controller。每个 Controller 会负责 Kube Queue 与一种类型任务的对接。</p><p>默认情况下,kube-queue-controller 中会通过 oversellrate 参数设置超卖比为 2,此时队列会能够出队配置资源两倍资源量的任务,可以在 Deployment 的编辑页面中将超卖比设置为 1。</p><p><img src="/img/remote/1460000044662303" alt="图片" title="图片"></p><p>若需实现两个 Job 之间的排队,首先需要提交一个申明队列的 ElasticQuotaTree。该 ElasticQuotaTree 申明了一个最多可以使用 1 核 CPU 和 1Gi 内存资源的队列,并将 default 命名空间挂载在该队列下。</p><pre><code>apiVersion: scheduling.sigs.k8s.io/v1beta1
kind: ElasticQuotaTree
metadata:
name: elasticquotatree
namespace: kube-system # 只有kube-system下才会生效
spec:
root:
name: root # Root节点的Max等于Min
max:
cpu: 1
memory: 1Gi
min:
cpu: 1
memory: 1Gi
children:
- name: child-1
max:
cpu: 1
memory: 1Gi
namespaces: # 配置对应的Namespace
- default</code></pre><p>之后,我们提交两个 Kubernetes Job,提交时需要将 Job 设置为 Suspend 状态,即将 Job 的 .spec.suspend 字段设置为 true。</p><pre><code>apiVersion: batch/v1
kind: Job
metadata:
generateName: pi-
spec:
suspend: true
completions: 1
parallelism: 1
template:
spec:
containers:
- name: pi
image: perl:5.34.0
command: ["sleep", "1m"]
resources:
requests:
cpu: 1
limits:
cpu: 1
restartPolicy: Never</code></pre><p>提交之后,查看任务状态,可以看到两个任务中仅有一个任务开始执行,另一个任务进入等待状态。</p><p><img src="/img/remote/1460000044662304" alt="图片" title="图片"></p><p>在前一个任务执行完成后,后续任务自动开始执行,完成任务执行的自动控制。</p><p><img src="/img/remote/1460000044662305" alt="图片" title="图片"></p><h2>What's Next</h2><p>在本篇文章中,我们探讨了云原生时代下,任务队列系统的重要性以及必要性,并详细介绍了阿里云容器服务 ACK 的 Kube Queue 如何在当前的 Kubernetes 生态中,明确自身的角色定位与价值贡献。在后续的文章中,我们将进一步讨论,如何利用容器服务 ACK 的 Kube Queue 以及高效的调度机制,快速构建一个能够满足企业需求、基于 ElasticQuotaTree 的任务管理系统。</p><p><strong>相关链接:</strong></p><p>[1] 如何安装及使用任务队列 ack-kube-queue</p><p><a href="https://link.segmentfault.com/?enc=Kmj56LeyI9M4ufzzvEXDCA%3D%3D.ChPHaN%2FoDRXUO%2FJXUz3LVzqVkLj8xi7FDNTOA%2Bw30Ysh7rbtch4nafLzaXfwg6rJmQRsinlr22CEhVBYHmi5RRTT%2Fowvr4XQZ6WTcK980o5GXFhOoo5gqhKUXXcfsaJPX2FNLqMwIePGJT3B4F4H3lEj9%2F5XkL9gOP8GKjIAJqAb5Eh6RHjIRfFBPlr5OpPkFcWSWBW58LcvQf7YtfrSzA%3D%3D" rel="nofollow">https://help.aliyun.com/zh/ack/ack-managed-and-ack-dedicated/...</a></p><p>作者:吴昆</p><p><strong><a href="https://link.segmentfault.com/?enc=e%2B%2B7js429Q9LqWhSsvboAw%3D%3D.Ud8k4uUWYCFQlxkFp4xFuXGWMUxZD66dboqNhtJV47AEoQ7Ba0jekRZyORai1I0jH%2BcDRmyG%2Fx4GPJABR7qI8Xqm%2FpikelDk4yTUYahCs7s%3D" rel="nofollow">原文链接</a></strong></p><p><strong>本文为阿里云原创内容,未经允许不得转载。</strong></p>
云原生网关哪家强:Sealos 网关血泪史
https://segmentfault.com/a/1190000044661186
2024-02-27T11:11:38+08:00
2024-02-27T11:11:38+08:00
阿里云云栖号
https://segmentfault.com/u/aliyunqi
0
<p>Sealos 公有云(<a href="https://link.segmentfault.com/?enc=JUFVC%2F5jyUFTeBmxifaGFg%3D%3D.RmDjfQB%2F%2FLYZ3z8fvUL9pYp6UwUZyfDvnznVj7fCfhU%3D" rel="nofollow">https://cloud.sealos.io</a>)几乎打爆了市面上所有主流的开源网关,本文可以给大家很好的避坑,在网关选型方面做一些参考。</p><h2>Sealos Cloud 的复杂场景</h2><p>Sealos 公有云上线以来,用户呈爆发式增长,目前总共注册用户 8.7w,每个用户都去创建应用,每个应用都需要有自己的访问入口,就导致整个集群路由条目非常巨大,需要有支撑数十万条 Ingress 的能力。</p><p>另外,在公网提供共享集群的服务,对多租户要求极为苛刻,用户之间的路由必须不能相互影响,需要非常好的隔离性,以及流量控制能力。</p><p>公有云的受攻击面是很大的,黑客会攻击云上跑的用户应用,也会直接攻击平台的出口网络,安全性上也有非常大的挑战。</p><p>对控制器的性能和稳定要求都比较高,很多控制器路由条目一多时消耗资源会非常大,甚至 OOM 导致网关奔溃。</p><h2>排除 Nginx Ingress</h2><p>我们最早用的就是 Nginx Ingress,最后发现有几个核心问题无法解决:</p><ul><li>reload 问题,每次有 ingress 变更会导致断连一小会,而一个集群用户一多的时候,ingress 的创建变更会是个频繁事件,就会导致网络经常不稳定。</li><li>长链接不稳定,也是因为变更,在用的长链接会经常断。</li><li>性能不行,生效时间慢,消耗资源多。</li></ul><p>所以几乎排除掉了很多底层用 Nginx 实现的网关。我们实测下来基于 Envoy 实现的网关性能彪悍太多,几乎控制面和数据面都不怎么消耗性能。</p><p>这是 Envoy 的:</p><p><img src="/img/remote/1460000044661188" alt="图片" title="图片"></p><p>这是 Nginx 的:</p><p><img src="/img/remote/1460000044661190" alt="图片" title="图片"></p><p>差距非常之大,所以我们就可以排除掉 Nginx 系列选项了,彻底拥抱 Envoy。</p><h2>关于 APISIX</h2><p>APISIX 本身是个优秀项目,解决了 Nginx reload 的一些问题,所以我们 Laf 早期也用了 APISIX,但是很不幸 APISIX 的 Ingress Controller 并不是很稳定,控制面崩溃给造成了我们好几次大的故障,还出现过控制器 OOM 等问题,我们本来真的很想用,但是最终还是因为故障问题被强制劝退,当然 APISIX 社区也在一直跟进这些问题,希望能越做越好。</p><p>总结一下就是:APISIX 本身稳定性很好,但是控制器需要优化的东西还很多,稳定性也有待提高。社区支持力度也很大,无奈我们线上问题火烧眉毛没法按照社区的节奏慢慢迭代,只能先切成别的网关了。</p><h2>Cilium Gateway</h2><p>Sealos 的 CNI 很早就切换成 Cilium 了,确实很强,所以我们想着网关也统一用 Cilium 得了,但是现实很骨感。</p><p>Cilium Gateway 只支持 LB 模式,这样就强依赖云厂商的 LB,而我们也有一些私有化的场景,所以不希望耦合,稳定性方面也遇到了路由非常多的时候,Ingress 生效特别慢的问题,需要分钟级生效,这样用户的体验就很差了,我们能接受的是 5s 内路由生效。所以结论就是只能再等等。</p><h2>Envoy Gateway</h2><p>从 K8s 标准的发展来看,会逐渐从 Ingress 迁移到 Gateway 的标准,而我们底层又更倾向使用 Envoy,那 Envoy Gateway 的实现似乎是一个很好的选择,所以我们调研了 Envoy Gateway,但是这个项目还是太过于早期,遇到了一些不稳定的 bug,比如会 OOM,pathpolicy 不生效,有些特性在 merge gateway 模式下不生效等问题,在持续解决中,我们也在不断帮助上游社区提改进意见和贡献,希望未来可以能达到生产可用的状态。</p><h2>逼格很高但不那么实用的 Gateway 标准</h2><p>Gateway 的处境很尬感,我的感觉是设计者并没有真的实践过多租户场景,当多租户共享一个集群时,就要明确区分管理者和使用者的权限问题,Gateway 设计之初就没完全考虑清楚,举个例子:</p><pre><code>apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: eg
spec:
gatewayClassName: eg
listeners:
- name: http
port: 80
protocol: HTTP
# hostname: "*.example.com"
- name: https
port: 443
protocol: HTTPS
# hostname: "*.example.com"
tls:
mode: Terminate
certificateRefs:
- kind: Secret
name: example-com</code></pre><p>这里监听端口这类的配置应该是给集群管理员而不是普通用户,而 TLS 证书的配置属于某个应用,管理员可以有权限配置,主要还是每个用户去配置自己的,所以这里面权限就没有分开。那就只能让用户也有权限配置 Gateway,所以这里就又需要在控制器里实现很多的权限控制的细节问题,如端口号白名单,冲突检测等。</p><p>个人觉得更优雅的设计是把其中租户级别的字段下沉到 HTTPRoute 中实现,或者一个单独的 CRD,这样用户态和超级管理员就可以分开的更清楚。现有的方式也能做,就是有点混杂。</p><h2>最终 Higress 胜出</h2><p>除了以上重点的项目,我们还测试了很多其他项目,我这里就不一一列举了。Sealos 最终选了 Higress。</p><p>我们目前选择网关的逻辑很简单,主要就是在满足功能的前提下足够稳定,最终选择 Higress 几乎是排除法得出来的。</p><p>稳定性是排在第一位的,在我们的场景里面能够达到生产可用的目前只有 Higress。不过实践过程中也出现过一些问题,好在 Higress 社区的支持力度很大,很快速的解决了,主要有几个:</p><ol><li>Ingress 生效速度慢,路由条目多时, 2min 多新建路由才能生效,社区最后优化到了 3s 左右,这已经到极致了,也没有再优化的必要了,因为已经比容器 Ready 时间还短了,Higress 使用了一种增量加载配置的机制,让海量路由条目时也能有夸张的性能。</li><li>控制器 OOM,在无动态加载时资源消耗比较大,出现过 OOM 的情况,目前三高问题都解决掉了。</li><li>超时问题,有一个进一步优化加载延时的参数配置 onDemandRDS 在我们一个主集群会偶发请求超时,目前是把该配置关闭了,还在进一步查看原因,而在其它集群中未发现这个问题。</li></ol><p>安全性方面,我们很多时候的故障问题都是性能问题造成的,流量过大,打爆网关比较常见,所以网关的性能变得至关重要,实测下来 Envoy 要彪悍很多,控制器写的好不好也生死攸关,这个方面 Higress 表现出众:</p><p><img src="/img/remote/1460000044661191" alt="图片" title="图片"></p><p><img src="/img/remote/1460000044661192" alt="图片" title="图片"></p><p>在我们已经海量路由,超高并发的情况下,需要的资源少的可怜。</p><p>Higress 还兼容 Nginx Ingress 语法,主要是一些 annotations,我们之前的代码都是用的 Ingress,所以几乎没有任何迁移成本,直接几分钟的升级就可以搞定。</p><p>同样为了促进社区更好的发展我们也给 Higress 一些意见:</p><p>1.能对 Gateway 的标准有更好的支持,目前虽然已经支持了 v1 版本,但还没有完全兼容 Ingress 上的能力。<br>2.能开放出一些大杀器的功能,比如安全和熔断方面的能力。让开源和商业结合的更紧密一些,我们倒是不排斥付费,但是随着平台发展,需要更强的一些功能。<br>3.周边功能建议更多通过插件机制扩展,让核心功能更内聚一些,简单可依赖。</p><h2>总结</h2><p>网关对于云和应用而言是个非常非常核心的组件,随着 Sealos 规模的不断扩大,也会出现很多新的挑战,我们希望能和上下游社区建立紧密的合作,让开源网关能得到更好的发展,让更多开发者受益。</p><p>以上列举的很多网关都很优秀,Sealos 没用不代表项目不厉害,只是我们的场景苛刻且奇葩,真的在公网环境能支持多租户的网关并不多,所以各位看官还是要从自己的场景出发。我们的选型仅作参考,同样 Sealos 本身也会以一个开放心态来继续跟进其他网关的发展。</p><p>最后非常感谢 Higress 开源社区的大力支持,感谢阿里云云原生团队开源了这么优秀的项目,造福广大社区用户。</p><p>作者:Sealos 创始人,环界云计算 CEO 方海涛</p><p><strong><a href="https://link.segmentfault.com/?enc=38EXnd0MRtv0D60anZCPXQ%3D%3D.OoOG9ANRfakC5bdYVdvpHEDLVYhx%2Bfyqg%2Fk7d8w3DY8Zn7uwhEZCxj38jCw3aJS1CotjwUM%2BBanF%2BKu6cS1qLY0lgk0GInK9ICbo3Aa4KwE%3D" rel="nofollow">原文链接</a></strong></p><p><strong>本文为阿里云原创内容,未经允许不得转载。</strong></p>
基于 Megatron-Core 的稀疏大模型训练工具:阿里云MoE 大模型最佳实践
https://segmentfault.com/a/1190000044659416
2024-02-26T17:06:47+08:00
2024-02-26T17:06:47+08:00
阿里云云栖号
https://segmentfault.com/u/aliyunqi
0
<h2>概述</h2><p>随着大模型技术的不断发展,模型结构和参数量级快速演化。大模型技术的应用层出不穷。大模型展现惊人效果,但训练和推理成本高,一直是巨大挑战。模型稀疏化能降低计算和存储消耗。近期以Mixtral为代表的MoE(多专家混合)大模型证明了稀疏MoE技术能大幅降低计算量、提升推理速度,模型效果甚至超过同规模稠密模型。阿里云PAI和NVIDIA团队深入合作,基于Megatron-Core MoE框架,解决了MoE大模型训练落地时会遇到的可拓展性、易用性、功能性以及收敛精度等核心问题,在下游任务上取得了很好的模型效果。PAI团队将上述MoE训练框架和技术与阿里云AI平台产品深度整合,使云上大模型用户能方便地进行MoE大模型的训练和部署。</p><h2>基于 Megatron-Core 的 MoE 训练工具链</h2><p>这一章节中,我们从MoE算法介绍,Megatron-Core MoE训练框架、以及云平台工具三个方面了解支撑MoE落地背后的基础能力。</p><h3>MoE 算法介绍</h3><p>MoE的全称是Mixture of Experts,其中的Expert对应的是Transfomrer模型的MLP层,在训练的时候从多个MLP中选取一个MLP进行激活 [1](如下图所示)。这意味着模型可以在不增加FLOPs的情况下,通过增加MLP模块的数量来增加模型参数量级,进而提升模型在下游任务上的效果。采用MoE后的稀疏Transformer模型和同等质量(验证集loss以及Zero-shot NLU下游任务性能)的稠密模型相比有较大幅度的训练和推理吞吐性能提升。MoE主要由以下两个关键部分组成:</p><ul><li>稀疏MoE层: 这些层代替了传统 Transformer模型中的前馈网络 (FFN) 层。MoE层包含若干experts组成,每个experts本身是一个独立的神经网络。在实际应用中这些专家通常是前馈网络 (FFN)。</li><li>Router路由: 这个部分用于决定哪些tokens被发送到哪个专家。例如在下图中,“More”这个tokens可能被发送到第二个专家,而“Parameters”这个tokens被发送到第一个专家。</li></ul><p><img src="/img/remote/1460000044659418" alt="图片" title="图片"></p><p>接着我们讨论下MoE中的token负载均衡问题。如上图所示的Top-1 Routing算法,每个输入hidden_states被router分配了4个experts中的1个用于前向推理计算,然后其输出被加权求和汇总后送入Transformer的下一个处理单元。这种路由方式会出现少数受欢迎的experts需要处理很多token,而其他experts仅需处理极少数量的token的情况,这导致处理极少token的那些experts无法获得足够多的信息,从而导致训练效率大幅降低。</p><p>为了缓解这种token到expert负载不均衡(Load Imbalancing)的问题,可以引入了一个辅助损失函数,旨在鼓励给予所有专家相同的重要性。这个损失函数确保所有专家接收到大致相等数量的训练样本,从而平衡了专家之间的选择。另外也可以通过drop tokens的方式得到缓解。首先定义一个expert capacity,即为一个expert被分配到的token的容量。如果分配到一个expert的token数超出了一个固定容量,则多余的tokens会被丢掉。这些被丢掉的tokens不参与和experts的矩阵乘运算,直接通过一个残差连接进入到下一个处理单元。如果一个expert没有被分配到其容量上限内的足够多的tokens,则需要采用padding的方式填充到容量上限。</p><p>Mixtral-8x7b模型提供了另外一种思路来缓解负载不均衡的问题,其采用的Megablocks [2]论文中提出的dropless moe算法。如下图所示,首先tokens通过router被分配到具体的experts,token到expert的分配关系被存储到expert indices中,分配置信度被存储到Probabilities中。其次根据预先设置好的expert的容量将tokens分组放置,超出容量的tokens被丢掉。接着将分组中的tokens和experts进行批量矩阵乘运算。最后输出结果按照分配置信度进行加权求和(如下左边公式),其分配置信度的计算采用的是normalized softmax(如下右边公式)。</p><p><img src="/img/remote/1460000044659420" alt="图片" title="图片"></p><p><img src="/img/remote/1460000044659421" alt="图片" title="图片"></p><p><img src="/img/remote/1460000044659422" alt="图片" title="图片"></p><p>Megablock论文认为这个drop token方案会导致效果下降,于是在此基础上引入块稀疏算子来实现dropless功能。如下图所示,dropable的moe算法在experts之间并行批量矩阵乘(如下图A所示)可以用一种块对角矩阵乘来等价表达(如下图B所示)。Megablock设计了一个新的算子允许变长的输入(如下图C所示),然后输出到一个稀疏对角矩阵上。引入了这个变长输入就意味着不需要drop的方式就能处理超出容量的tokens。类似的,Megatron-Core MoE使用GroupedGEMM解决了多 expert变长输入的问题。</p><p><img src="/img/remote/1460000044659423" alt="图片" title="图片"></p><h3>Megatron-Core MoE 训练框架</h3><p>Megatron-Core是NVIDIA推出的一个成熟且轻量级的大规模LLM训练框架,它包含了训练大规模LLM模型所需的所有关键技术,例如各类模型并行的支持、算子优化、通信优化、显存优化以及FP8低精度训练等。Megatron-Core不仅继承了前代Megatron-LM的优秀特性,还在代码质量、稳定性、功能丰富性和测试覆盖率上进行了全面提升。更重要的是,Megatron-Core在设计上更加解耦和模块化,不仅提高了LLM训练的效率和稳定性,也为二次开发和探索新的LLM架构提供了更大的灵活性。</p><p>基于Megatron-Core,研究人员可以在大规模集群上高效地训练各种大型LLM模型,其中也包括对 MoE 模型的探索。MoE的建模方式也带来了参数量的急剧上升、MoE层复杂的通信逻辑、Routing等额外的开销,都给训练框架带来了不小的挑战。其中首当其冲的就是如何在多个GPU间高效的拓展MoE 训练。</p><p>在最新发布的Megatron-Core v0.5中,Megatron-Core正式推出了对大规模MoE模型训练的支持,也就是Megatron-Core MoE,涵盖了并行性、路由和负载均衡、性能优化、Token分发机制等多个feature。以下是一些值得关注的特性:</p><h4>并行性(Parallelism)</h4><p>Megatron-Core MoE支持专家并行(Expert Parallel),这是一种专门为MoE模型设计的并行方法。在这种并行化策略中,不同的 Rank 负责处理其中一个或多个专家的计算。</p><p>此外,Megatron-Core MoE还支持3D并行(Data Parallel, Tensor Parallel, Pipeline Parallel, Sequence Parallel)。对于更大的MoE模型, Megatron-Core MoE也支持将专家并行(EP)与其它的并行DP/TP/PP/SP/Distributed Optimizer结合使用。</p><p>未来,Megatron-Core MoE还将支持Context Parallel,以支持更长序列的训练。</p><h4>Token 分发机制(Token Dispatch Mechanism)</h4><p>Megatron-Core MoE目前提供了对Dropless MoE的支持(不进行Token丢弃)。即将加入对Token drop MoE的支持。</p><h4>路由和负载均衡(Router and Load Balancing)</h4><p>Megatron-Core MoE提供了多种路由类型,包括通用的Top-K router和即将推出的Expert Choice router。</p><p>在负载均衡算法方面,支持Sinkhorn(S-BASE)、Z-Loss,以及Load balancing Loss。</p><h4>Grouped GEMM</h4><p>Megatron-Core MoE开发了GroupedGEMM来解决多Experts变长输入这一问题。当每个Rank有多个专家时,Megatron-Core MoE利用自CUTLASS 2.8引入的Grouped GEMM特性,将多个局部(可能是较小的)GEMM操作合并为单个GroupedGEMM kernel,能够大幅度提高SM利用率和性能。</p><p>同时,Megatron-Core MoE还将部分效率较低的操作替换为优化后的CUDA Kernel,如Sinkhorn、local token permutation/unpermutation等。</p><p>即将推出的功能与优化</p><p>近期将发布的部分新特性包括:</p><ul><li>上下文并行(Context Parallel)</li><li>FP8低精度训练</li><li>FP8 Grouped GEMM</li><li>Token-Drop MoE</li></ul><p>通过这些特性,Megatron-Core MoE为用户提供了一个强大的MoE训练框架,以在大规模集群上高效地训练和探索大型MoE模型。随着更多功能的推出,我们期待Megatron-Core MoE将在未来的LLM研究和应用中发挥更大的作用。</p><h3>MoE平台工具</h3><p>在阿里云PAI灵骏分布式集群上运行的基于Megatron的MoE训练工具由三部分组成(如下图所示)。从上到下依次是PAI平台,PAI-Megatron-Patch (<a href="https://link.segmentfault.com/?enc=2eeVCU61VF1CLFOc4VshMQ%3D%3D.tKQBGqxH5RNZEsQ4Y50A6VNS1cHU6Za%2B%2Bkmqoysl2Mco9Lsfz1bu6y%2BUn9XIHfmU" rel="nofollow">https://github.com/alibaba/Pai-Megatron-Patch</a>)以及NVIDIA Megatron-Core(<a href="https://link.segmentfault.com/?enc=FgsHobhxOovRLAy4I1Rbpw%3D%3D.AGWZ%2FiKQeJV%2BvvQTGmRcRSnl9U3ghf%2FJ3eDGAHL2WFeHVBjS80h004PvHEK%2BfCIe" rel="nofollow">https://github.com/NVIDIA/Megatron-LM</a>)。PAI平台的DSW产品是为AI开发者量身定制的云端机器学习交互式开发IDE,随时随地开启Notebook快速读取数据、开发算法、训练及部署模型。DLC产品则为您提供灵活、稳定、易用和极致性能的多机多卡深度学习训练环境。Pai-Megatron-Patch是各类开源大模型和Megatron训练加速引擎之间的“桥梁”,为用户提供用Megatron训练开源大模型的易用性以及LLM算法场景定制化的灵活性。NVIDIA开发的Megatron以其良好的业界口碑赢得了众多大模型用户的青睐,其算子拆分和流水并行等模型并行技术已经成为行业标准。基于DeepSpeed Zero-1改进的Distributed Optimizer在大规模分布式训练过程中的降显存方面发挥巨大作用。集成最新的算子融合,Transformer Engine以及Flash Attention等训练加速技术更是将大模型的吞吐性能&显卡利用率提升到了极致[3].。</p><p>以代码生成这个LLM应用场景为例,研发团队首先在DSW中开发&调试用于该场景的定制化数据处理流程,使用定制化的分词器对原始代码数据进行ID化,同时调试模型库中对应的代码生成模型比如deepseek。接着在DSW中跑通适用于多机多卡训练的HuggingFace到Megatron的权重转换流程并生成Megatron可加载的权重。然后在DLC中配置Patch提供的训练启动脚本,将训练所需的超参数比如学习率以及训练加速开关比如Flash Attention等通过脚本传入Megatron训练引擎。</p><p><img src="/img/remote/1460000044659424" alt="图片" title="图片"></p><h2>MoE 训练效果展示</h2><p>我们以最近社区热门的Mixtral-8x7B稀疏MoE大模型为例,从HuggingFace到 Megatron的零样本loss对齐,训练loss收敛曲线,代码生成下游任务评测,训练吞吐性能这四个方面向用户展示训练工具的预期效果,以此来验证工具的可靠性和稳定性。为方便用户测试,我们提供了已经处理好的idxmap格式的Wudao数据集,转换前的HuggingFace模型以及转换后的Megatron-Core格式的模型供下载使用,具体文件大小和下载链接如下所示。</p><p><img src="/img/remote/1460000044659425" alt="图片" title="图片"></p><p><img src="/img/remote/1460000044659426" alt="图片" title="图片"></p><pre><code>https://atp-modelzoo-wlcb-pai.oss-cn-wulanchabu.aliyuncs.com/release/models/pai-megatron-patch/mistral-ckpts/Mixtral-8x7B-v0.1-to-mcore-tp4-ep4.tar.zsthttps://atp-modelzoo-wlcb-pai.oss-cn-wulanchabu.aliyuncs.com/release/models/pai-megatron-patch/mistral-ckpts/Mixtral-8x7B-v0.1.tar.zsthttps://atp-modelzoo-wlcb-pai.oss-cn-wulanchabu.aliyuncs.com/release/models/pai-megatron-patch/mistral-datasets/wudao_mistralbpe_content_document.binhttps://atp-modelzoo-wlcb-pai.oss-cn-wulanchabu.aliyuncs.com/release/models/pai-megatron-patch/mistral-datasets/wudao_mistralbpe_content_document.idxhttps://atp-modelzoo-wlcb-pai.oss-cn-wulanchabu.aliyuncs.com/release/models/pai-megatron-patch/mistral-ckpts/Mixtral-8x7B-v0.1-to-mcore-tp4-ep4.tar.zsthttps://atp-modelzoo-wlcb-pai.oss-cn-wulanchabu.aliyuncs.com/release/models/pai-megatron-patch/mistral-ckpts/Mixtral-8x7B-v0.1.tar.zsthttps://atp-modelzoo-wlcb-pai.oss-cn-wulanchabu.aliyuncs.com/release/models/pai-megatron-patch/mistral-datasets/wudao_mistralbpe_content_document.binhttps://atp-modelzoo-wlcb-pai.oss-cn-wulanchabu.aliyuncs.com/release/models/pai-megatron-patch/mistral-datasets/wudao_mistralbpe_content_document.idx</code></pre><p>测试镜像地址请采用:<a href="https://link.segmentfault.com/?enc=nz%2FVwlsDYk%2B%2BJFgtYndgow%3D%3D.qKQFjDRsaul5ehXsXhkQpiY3i5B7jm85p5vb3YPLvXymtNnMy8vubMz%2BGdLcV1uki4o1lqE3%2BTmxADYlzaZQDv3fMlot7AuDCieeGSPP5eOf88T0CY9GsXTEEND8xniGOxAeOAbIcFGUhp370xy3ZXLKDBeRohm0snhzyKj59cE%3D" rel="nofollow">http://dsw-registry.cn-wulanchabu.cr.aliyuncs.com/pai/pytorch...</a></p><h3>HF 到 Megatron 模型权重转换</h3><p>由于从头预训练大模型所消耗的算力成本较高,因此用户普遍采用加载 HuggingFace 提供已经训练好的模型权重继续预训练或者微调。这就需要先把 HuggingFace的Transformer结构的权重转换到Megatron的Transformer可识别并加载的格式。下图显示的两边的算子之间的对照关系。</p><p><img src="/img/remote/1460000044659427" alt="图片" title="图片"></p><p>这里需要注意的是当TP>1的时候,对权重矩阵的切分与合并操作应符合Megatron的建模方式。以mlp层的gate_proj和up_proj为例,按TP=2切分后两个算子的左半部分先组合到一起,然后右半部分再组合到一起,然后拼接形成Megatron可识别的dense_h_to_4h操作,如下图所示。这种拆分&合并的顺序一旦出现错误,会导致两边的前向推理无法对齐。</p><p><img src="/img/remote/1460000044659428" alt="图片" title="图片"></p><p>另外涉及到experts的分配的时候也需要格外小心。我们对比dense的转换在moe模型的convert脚本中新增了两个参数(expert_model_parallel_size和world_size(总卡数))来对experts的分布进行精细化处理。比如mixtral的experts的总数是8,那么在16张卡有三种转换情况, tp4ep4, tp8ep2, tp2ep8,按照每种情况来分配moe层的权重。以tp4ep4为例,权重转换后的文件夹命名如下表所示:</p><p><img src="/img/remote/1460000044659429" alt="图片" title="图片"></p><p>在每个文件里存储两个experts的FFN权重,每个tp_rank有8个experts来做路由,如下图所示:</p><p><img src="/img/remote/1460000044659430" alt="图片" title="图片"></p><p>最后我们通过zeroshot loss来衡量转换后的模型是否正确,从下表中可以看到,转换前后的误差基本可以控制在非常小的范围内。下表中箭头精度转换(fp16->bf16)的含义是checkpoint格式是fp16, 运行的时候加载成bf16。</p><p><img src="/img/remote/1460000044659431" alt="图片" title="图片"></p><h3>基于 MoE 模型继续预训练 & 微调收敛</h3><p>我们探索了三个使用场景的收敛情况分别是:从头预训练,加载Mixtral-8x7B-v0.1继续预训练以及加载Mixtral-8x7B-Instruct-v0.1微调。具体操作方法可参考我们提供的Mixtral-8x7B稀疏大模型最佳实践,里面详细介绍了如何启动训练的细节。在从头预训练的实验中,我们采用的训练配置是:A800机型80G显存,两机16卡,global_size=256,lr=1e-4, seq_len=2048, TP=4。训练24个小时到2.4k个step后的loss可以到收敛到1.9的曲线如下所示:</p><p><img src="/img/remote/1460000044659432" alt="图片" title="图片"></p><p>*仅做技术参考和探讨</p><p>在加载Mixtral-8x7B-v0.1继续预训练的实验中,我们采用的训练配置是:A800机型80G显存,两机16卡,global_size=256,lr=5e-5, seq_len=2048, TP=4。训练18个小时到2k个step后的loss收敛曲线如下所示:</p><p><img src="/img/remote/1460000044659433" alt="图片" title="图片"></p><p>*仅做技术参考和探讨</p><p>在加载Mixtral-8x7B-Instruct-v0.1微调的实验中,我们在代码生成这个下游任务中设计了三种微调场景分别是:base模型纯自回归训练(橙色曲线,计算全部loss),instruct模型纯自回归训练(蓝色曲线,计算全部loss) 和instruct模型纯自回归训练(红色曲线,计算answer loss)。从三种情况的收敛loss曲线对比可以看出基本都收敛到0.5上下。其中采用base模型来微调的loss下载不如其他两个,这是符合预期的。</p><p><img src="/img/remote/1460000044659434" alt="图片" title="图片"></p><h3>代码生成任务评测</h3><p>代码生成是指通过自然语言描述生成相应的可执行代码,从而提升开发人员的工作效率。随着LLM模型的不断发展,在代码生成任务上也取得了突破性的进展,如github copilot能够提升55%的开发效率。我们针对代码生成这个下游领域任务,基于Evol-Instruct-Code-80K数据对Mixtral-8x7B-Instruct-v0.1模型进行微调,并测试了在微调前后模型Human-eval上的通过率,和LLaMA2等开源通用模型对比可以看到微调后的模型在代码生成的能力上有明显的优势,如下表所示。</p><p><img src="/img/remote/1460000044659435" alt="图片" title="图片"></p><p>我们在A800机型80G显存,两机16卡下采用的微调参数如下,具体操作方法可参考我们提供的Mixtral-8x7B稀疏大模型最佳实践。</p><pre><code>micro batch size: 1
global batch size: 128
lr: 1e-5
min_lr: 1e-6
seqlen:2048
padlen:2048
tp:4
pp:1
ep:4
train_iter:2500</code></pre><p>*仅做技术参考和探讨</p><p>在评测时,我们使用如下的prompt来生成代码:</p><pre><code>f"[INST] Create a Python script for this problem:{question} [/INST]"</code></pre><h3>训练吞吐性能</h3><p>笔者注:Megatron-Core MoE在短期内还会加入对于通信、计算以及Token dispatch的多项性能优化,当前的测试数据不代表最终的性能数据。</p><p>在吞吐速度评测环节,阿里PAI团队调研了Megablocks(<a href="https://link.segmentfault.com/?enc=shNuL2h62lkvd07H6iGlhA%3D%3D.d34ERDqFvQ2FzwDYKcc1kINUsU%2FWqSsllMnxZAG5ENwwiN4I2%2F20fw%2Bo3Ll7Y0q6At%2B%2BhEChoZ4qlQtxKu1HOw%3D%3D" rel="nofollow">https://github.com/stanford-futuredata/Megablocks</a>)中的dmoe实现,一方面是因为Mixtral-8x7b论文中说采用的是Megablocks的框架训练的MoE模型,另一方面我们也想探索下在相同Megatron平台底座上,哪个MoE实现方式对训练吞吐加速效果更好。Megablocks论文中提供了同Dense模型的收敛速度的比较,如下图所示的具有2.4x的收敛加速能力,我们期望基于Megatron-Core的实现方案也具有同样甚至更好的加速效果。</p><p><img src="/img/remote/1460000044659436" alt="图片" title="图片"></p><p>吞吐性能对比实验采用的是阿里云PAI灵骏平台上A800机型80G显存,两机16卡运行环境。我们发现采用Mixtral-8x7B模型配置时,Megablocks的seqlen如果等于1024/2048会出现OOM。因此我们将Megablocks和Megatron-Core的seqlen都设置为512。同时我们打开 --moe-grouped-gemm 开启GroupedGEMM提升多 Experts 时的 GPU 利用率,从下表的吞吐数据可以看出,当前Megatron-Core的吞吐速度比 Megablock 快 10%左右。此外,由于我们得知Megatron-Core当前正在推进MoE的性能优化,因此当前的数据仅供参考。</p><p><img src="/img/remote/1460000044659437" alt="图片" title="图片"></p><h2>总结</h2><p>在基于Megatron-Core的稀疏大模型训练工具:阿里云MoE大模型最佳实践开发过程中,我们围绕稀疏大模型训练测试了以下核心技术的性能:</p><ul><li>MoE基础技术平台:基于Megatron-Core MoE的多重训练加速技术的可靠性。</li><li>MoE落地Pipeline:HF到Megatron的模型权重转换在继续预训练&微调以及代码生成下游任务中的效果。</li></ul><p>后续在Pai-Megatron-Patch中还会陆续放出更多高质量的大模型最佳实践,敬请期待。</p><h2>参考文献</h2><p>[1]. Switch Transformers: Scaling to Trillion Parameter Models with Simple and Efficient Sparsity</p><p>[2]. Megablocks: Efficient Sparse Training with Mixture-of-Experts</p><p>[3]. Reducing Activation Recomputation in Large Transformer Models</p><p>作者:李鹏,颜子杰,王明,颜海强,刘振寰,黄俊</p><p>单位:阿里云人工智能平台PAI,NVIDIA DevTech Team</p><p><strong><a href="https://link.segmentfault.com/?enc=QWvraxh1fSSl3nMiJXtstQ%3D%3D.XGDF%2FbvLhJm2jy8vCc%2Ble%2FCiXOUz1toDffAwunDfoMkbiyk4koQDSvDNggjOmA%2FPQGREVzXHYjtlUjmHpUgSwhROqjApohYVHx%2Bx1MZdY3I%3D" rel="nofollow">原文链接</a></strong></p><p><strong>本文为阿里云原创内容,未经允许不得转载。</strong></p>
Koordinator v1.4 正式发布!为用户带来更多的计算负载类型和更灵活的资源管理机制
https://segmentfault.com/a/1190000044652069
2024-02-23T14:00:00+08:00
2024-02-23T14:00:00+08:00
阿里云云栖号
https://segmentfault.com/u/aliyunqi
0
<h2>背景</h2><p>Koordinator 作为一个积极发展的开源项目,自 2022 年 4 月发布 v0.1.0 版本以来,经历了多次迭代,持续为 Kubernetes 生态系统带来创新和增强。项目的核心是提供混部工作负载编排、混部资源调度、混部资源隔离和混部性能调优的综合解决方案,帮助用户优化容器性能,并提升集群资源使用效率。</p><p>在过去的版本迭代中,Koordinator 社区不断壮大,已经得到了包括阿里巴巴、蚂蚁科技、Intel、小米、小红书、爱奇艺、360、有赞、趣玩、美亚柏科、PITS 等知名企业工程师的积极参与和贡献。每一个版本都是在社区共同努力下推进的,反映了项目在实际生产环境中解决问题的能力。</p><p>今天我们很高兴的向大家宣布,Koordinator v1.4.0 版本正式发布。在本次发布中,Koordinator 引入了 Kubernetes 与 YARN 负载混部、NUMA 拓扑对齐策略、CPU 归一化和冷内存上报等新特性,同时重点增强了弹性配额管理、宿主机非容器化应用的 QoS 管理、重调度防护策略等领域的功能。这些新增和改进点旨在更好地支持企业级 Kubernetes 集群环境,特别是对于复杂和多样化的应用场景。</p><p>v1.4.0 版本的发布,将为用户带来更多的计算负载类型支持和更灵活的资源管理机制,我们期待这些改进能够帮助用户应对更多企业资源管理挑战。在 v1.4.0 版本中,共有 11 位新加入的开发者参与到了 Koordinator 社区的建设,他们是 @shaloulcy,@baowj-678,@zqzten,@tan90github,@pheianox,@zxh326,@qinfustu,@ikaven1024,@peiqiaoWang,@bogo-y,@xujihui1985,感谢期间各位社区同学的积极参与和贡献,也感谢所有同学在社区的持续投入。</p><h2>版本功能特性解读</h2><h3>1.支持 K8s 与 YARN 混部</h3><p>Koordinator 已经支持了 K8s 生态内的在离线混部,然而在 K8s 生态外,仍有相当数量的大数据任务运行在传统的 Hadoop YARN 之上。YARN 作为发展多年的大数据生态下的资源管理系统,承载了包括 MapReduce、Spark、Flink 以及 Presto 等在内的多种计算引擎。</p><p>Koordinator 社区会同来自阿里云、小红书、蚂蚁金服的开发者们共同启动了 Hadoop YARN 与 K8s 混部项目 Koordinator YARN Copilot,支持将 Hadoop NodeManager 运行在 kubernetes 集群中,充分发挥不同类型负载错峰复用的技术价值。Koordinator YARN Copilot 具备以下特点:</p><ul><li>面向开源生态</li></ul><p>基于 Hadoop YARN 开源版本,不涉及对 YARN 的侵入式改造;</p><ul><li>统一资源优先级和 QoS 策略</li></ul><p>YARN NM 使用 Koordinator 的 Batch 优先级资源,遵循 Koordinator QoS 管理策略;</p><ul><li>节点级别的资源共享</li></ul><p>Koordinator 提供的混部资源,既可被 K8s Pod 使用,也可被 YARN task 使用,不同类型的离线应用可运行在同一节点。</p><p><img src="/img/remote/1460000044652071" alt="图片" title="图片"></p><p>关于 Koordinator YARN Copilot 的详细设计,以及在小红书生产环境的使用情况,请参考往期文章:《Koordinator 助力云原生应用性能提升:小红书混部技术实践》以及社区官方文档[1]。</p><h3>2.引入 NUMA 拓扑对齐策略</h3><p>运行在 Kubernetes 集群中的工作负载日益多样化。尤其是在机器学习等领域,对于高性能计算资源的需求持续上升。在这些领域中,不仅需要大量 CPU 资源,还经常需要 GPU 和 RDMA 等其他高速计算资源配合使用;并且,为了获得最佳的性能,这些资源往往需要在同一个 NUMA 节点,甚至同一个 PCIE 中。</p><p>Kubernetes 的 Kubelet 提供了 Topology Manager 来管理资源分配的 NUMA 拓扑,试图在 Kubelet 的 Admission 阶段从节点层面对齐多种资源的拓扑。然而,节点组件没有调度器的全局视角以及为 Pod 选择节点的时机,可能导致 Pod 被调度到无法满足拓扑对齐策略的节点上,从而导致 Pod 由于 Topology Affinity 错误无法启动。</p><p>为了解决这一问题,Koordinator 将 NUMA 拓扑选择和对齐的时机放在中心调度器中,从集群级别优化资源之间的 NUMA 拓扑。在本次发布的版本中,Koordinator 将 CPU 资源(包含 Batch 资源)的 NUMA 感知调度和 GPU 设备的 NUMA 感知调度作为 alpha 功能支持,整套 NUMA 感知调度快速演进中。</p><p>Koordinator 支持用户通过节点的 Label 配置节点上多种资源的 NUMA 拓扑对齐策略,可配置策略如下:</p><ul><li>None 是默认策略,不执行任何拓扑对齐。</li><li>BestEffort 表示节点不严格按照 NUMA 拓扑对齐来分配资源。只要节点的剩余总量满足 Pods 的需求,调度器总是可以将这样的节点分配给 Pods。</li><li>Restricted 表示节点严格按照 NUMA 拓扑对齐来分配资源,即调度器在分配多个资源时必须只选择相同的一个或多个 NUMA 节点,否则不应使用该节点;可以使用多个 NUMA 节点。例如,如果一个Pod请求 33C,并且每个 NUMA 节点有 32C,那么它可以被分配使用两个 NUMA 节点。如果这个 Pod 还需要请求 GPU/RDMA,那么它需要位于与 CPU 相同的 NUMA 节点上。</li><li>SingleNUMANode 与 Restricted 类似,也是严格按照 NUMA 拓扑对齐,但与 Restricted 不同的是,Restricted 允许使用多个NUMA节点,而 SingleNUMANode 只允许使用一个NUMA 节点。</li></ul><p>举例,我们可以为 node-0 设置策略 SingleNUMANode:</p><pre><code>apiVersion: v1
kind: Node
metadata:
labels:
node.koordinator.sh/numa-topology-policy: "SingleNUMANode"
name: node-0
spec:
...</code></pre><p>在生产环境中,用户可能已经开启了 Kubelet 的拓扑对齐策略,这个策略会由 koordlet 更新到 NodeResourceTopologyCRD 对象中的 TopologyPolicies字段。当 Kubelet 的策略和用户在 Node 上设置的策略相冲突时,以 Kubelet 策略为准。Koordinator 调度器基本采用与 Kubelet Topology Manager 相同的 NUMA 对齐策略语义,Kubelet 策略 SingleNUMANodePodLevel 和SingleNUMANodeContainerLevel 被映射为 SingleNUMANode。</p><p>在为节点配置好 NUMA 对齐策略的前提下,调度器可以为每个 Pod 选出许多个符合条件的 NUMA Node 分配结果。Koordinator 当前支持 NodeNUMAResource 插件配置 CPU 和内存资源的 NUMA Node 分配结果打分策略,包括 LeastAllocated 和 MostAllocated,默认为 LeastAllocated 策略,资源支持配置权重。调度器最终将选择得分最高的 NUMA Node 分配结果。如下例,我们配置 NUMA Node 分配结果打分策略为 MostAllocated:</p><pre><code>apiVersion: kubescheduler.config.k8s.io/v1beta2
kind: KubeSchedulerConfiguration
profiles:
- pluginConfig:
- name: NodeNUMAResource
args:
apiVersion: kubescheduler.config.k8s.io/v1beta2
kind: NodeNUMAResourceArgs
scoringStrategy: # Here configure Node level scoring strategy
type: MostAllocated
resources:
- name: cpu
weight: 1
- name: memory
weight: 1
- name: "kubernetes.io/batch-cpu"
weight: 1
- name: "kubernetes.io/batch-memory"
weight: 1
numaScoringStrategy: # Here configure NUMA-Node level scoring strategy
type: MostAllocated
resources:
- name: cpu
weight: 1
- name: memory
weight: 1
- name: "kubernetes.io/batch-cpu"
weight: 1
- name: "kubernetes.io/batch-memory"
weight: 1</code></pre><h3>3.ElasticQuota 再进化</h3><p>为了充分地利用集群资源、降低管控系统成本,用户常常将多个租户的负载部署在一个集群中。在集群资源有限的情况下,不同租户之间必然会发生资源争抢。有的租户的负载可能一直被满足,而有的租户的负载一直无法得到执行。这就产生对公平性的诉求。配额机制是非常自然地保障租户间公平性的方式,给每个租户一个配额,租户可以使用配额内的资源,超过配额的任务将不被调度和执行。然而,简单的配额管理无法满足租户对云的弹性期待。用户希望除了配额之内的资源请求可以被满足外,配额之外的资源请求也可以按需地被满足。</p><p>在之前的版本中,Koordinator 复用了上游 ElasticQuota 的协议,允许租户设置 Min 表达其一定要满足的资源诉求,允许设置 Max 限制其最大可以使用的资源和表达在集群资源不足的情况下对集群剩余资源的使用权重。另外,Koordinator 观察到,一些租户可能通过 Min 申请了配额,但是实际的任务申请可能并没有充分利用该配额。由此,为了更近一步地提高资源利用率,Koordinator 允许租户间借用/归还资源。</p><p>除了提供弹性的配额机制满足租户按需诉求外,Koordinator 在 ElasticQuota 上增加注解将其组织成树的结构,方便用户表达树形的组织架构。</p><p><img src="/img/remote/1460000044652072" alt="图片" title="图片"></p><p>上图是使用了 Koordinator 弹性配额的集群中常见的 Quota 结构树。Root Quota 是连接配额与集群中实际资源之间的桥梁。在之前的设计中,Root Quota 只在调度器逻辑中存在,在本次发布中,我们将 Root Quota 也通过 CRD 的形式暴露给用户,用户可以通过 koordinator-root-quota 这个ElasticQuota CRD 查看 Root Quota 信息。</p><h4>3.1 引入 Multi QuotaTree</h4><p>大型集群中的节点的形态是多样的,例如云厂商提供的 ECS VM 会有不同的架构,常见的是 amd64 和 arm64,相同架构又会有不同种类的机型,而且一般会把节点按可用区划分。不同类型的节点放到同一个 Quota Tree 中管理时,其特有的属性将丢失,当用户希望精细化管理机器的特有属性时,当前的 ElasticQuota 显得不够精确。为了满足用户灵活的资源管理或资源隔离诉求,Koordinator 支持用户将集群中的资源划分为多份,每一份由一个 Quota Tree 来管理,如下图所示:</p><p><img src="/img/remote/1460000044652074" alt="图片" title="图片"></p><p>同时,为了帮助用户简化管理复杂性,Koordinator 在 v1.4.0 中 引入了 ElasticQuotaProfile 机制,用户可以通过 nodeSelector 快速的将节点关联到不同的 QuotaTree 中,如下实例所示:</p><pre><code>apiVersion: quota.koordinator.sh/v1alpha1
kind: ElasticQuotaProfile
metadata:
labels:
kubernetes.io/arch: amd64
name: amd64-profile
namespace: kube-system
spec:
nodeSelector:
matchLabels:
kubernetes.io/arch: amd64 // 挑选 amd64 节点
quotaName: amd64-root-quota // 匹配的 root quota 名称
---
apiVersion: quota.koordinator.sh/v1alpha1
kind: ElasticQuotaProfile
metadata:
labels:
kubernetes.io/arch: arm64
name: arm64-profile
namespace: kube-system
spec:
nodeSelector:
matchLabels:
kubernetes.io/arch: arm64 // 挑选 arm64 节点
quotaName: arm64-root-quota // 匹配的 root quota 名称</code></pre><p>关联好 QuotaTree 之后,用户在每一个 QuotaTree 中与之前的 ElasticQuota 用法一致。当用户提交 Pod 到对应的 Quota 时,当前仍然需要用户完成 Pod NodeAffinity 的管理,以确保 Pod 运行在正确的节点上。未来,我们会增加一个特性帮助用户自动管理 Quota 到 Node 的映射关系。</p><h4>3.2 支持 non-preemptible</h4><p>Koordinator ElasticQuota 支持把 ElasticQuota 中 min 未使用的部分共享给其他 ElasticQuota 使用从而提高资源利用效率,但当资源紧张时,会通过抢占机制把借用配额的 Pod 抢占驱逐走拿回资源。</p><p>在实际生产环境中,有一些在线服务如果从其他 ElasticQuota 中借用了这部分额度,后续又发生了抢占,是可能影响服务质量的。这类工作负载实质上是不能被抢占的。</p><p>为了实现这个机制,Koordinator v1.4.0 引入了新的 API,用户只需要在 Pod 上声明 quota.scheduling.koordinator.sh/preemptible: false 表示这个 Pod 不可以被抢占。</p><p>调度器调度时发现 Pod 声明了不可抢占,那么此类 Pod 的可用配额的上限不能超过 min,所以这里也需要注意的是,启用该能力时,一个 ElasticQuota 的 min 需要设置的合理,并且集群内有相应的资源保障。</p><p>这个特性不会破坏原有的行为。</p><pre><code>apiVersion: v1
kind: Pod
metadata:
name: pod-example
namespace: default
labels:
quota.scheduling.koordinator.sh/name: "quota-example"
quota.scheduling.koordinator.sh/preemptible: false
spec:
...</code></pre><h4>3.3 其它改进</h4><ol><li>Koordinator Scheduler 过去支持跨 Namespace 使用同一个 ElasticQuota 对象,但有一些场景下,希望只被一个或者多个有限的 Namespace 可以共享同一个对象,为了支持这个场景,用户可以在 ElasticQuota 上增加 annotation quota.scheduling.koordinator.sh/namespaces,对应的值为一个 JSON 字符串数组。</li><li>性能优化:过去的实现中,当 ElasticQuota 发生变化时,ElasticQuota 插件会重建整棵 Quota 树,在 v1.4.0 版本中做了优化。</li><li>支持忽略 Overhead:当 Pod 使用一些安全容器时,一般是在 Pod 中声明 Overhead 表示安全容器自身的资源开销,但这部分资源成本最终是否归于终端用户承担取决于资源售卖策略。当期望不用用户承担这部分成本时,那么就要求 ElaticQuota 忽略 overhead。在 v1.4.0 版本中,可以开启 featureGate ElasticQuotaIgnorePodOverhead 启用该功能。</li></ol><h3>4.CPU 归一化</h3><p>随着 Kubernetes 集群中节点硬件的多样化,不同架构和代数的 CPU 之间性能差异显著。因此,即使 Pod 的 CPU 请求相同,实际获得的计算能力也可能大不相同,这可能导致资源浪费或应用性能下降。CPU 归一化的目标是通过标准化节点上可分配 CPU 的性能,来保证每个 CPU 单元在 Kubernetes 中提供的计算能力在异构节点间保持一致。</p><p>为了解决该问题,Koordinator 在 v1.4.0 版本中实现了一套支持 CPU 归一化机制,根据节点的资源放大策略,调整节点上可分配的 CPU 资源数量,使得集群中每个可分配的 CPU 通过缩放实现算力的基本一致。整体的架构如下图所示:</p><p><img src="/img/remote/1460000044652075" alt="图片" title="图片"></p><p>CPU 归一化分为两个步骤:</p><ol><li>CPU 性能评估,计算不同 CPU 的性能基准,可以参考工业级性能评测标准 SPEC CPU[2],这部分 Koordinator 项目未提供;</li><li>配置 CPU 归一化系数到 Koordinator,调度系统基于归一化系数来调度资源,这部分 Koordinator 提供。</li></ol><p>将 CPU 归一化比例信息配置到 koord-manager 的 slo-controller-config 中,配置示例如下:</p><pre><code>apiVersion: v1
kind: ConfigMap
metadata:
name: slo-controller-config
namespace: koordinator-system
data:
cpu-normalization-config: |
{
"enable": true,
"ratioModel": {
"Intel(R) Xeon(R) Platinum 8269CY CPU @ 2.50GHz": {
"baseRatio": 1.29,
"hyperThreadEnabledRatio": 0.82,
"turboEnabledRatio": 1.52,
"hyperThreadTurboEnabledRatio": 1.0
},
"Intel Xeon Platinum 8369B CPU @ 2.90GHz": {
"baseRatio": 1.69,
"hyperThreadEnabledRatio": 1.06,
"turboEnabledRatio": 1.91,
"hyperThreadTurboEnabledRatio": 1.20
}
}
}
# ...</code></pre><p>对于配置了 CPU 归一化的节点,Koordinator 通过 Webhook 拦截 Kubelet 对 Node.Status.Allocatable 的更新以实现 CPU 资源的缩放,最终在节点上呈现出归一后的 CPU 资源可分配量。</p><h3>5.改进的重调度防护策略</h3><p>Pod 迁移是一个复杂的过程,涉及审计、资源分配、应用启动等步骤,并且与应用升级、扩展场景以及集群管理员的资源操作和维护操作混合在一起。因此,如果同时有大量 Pods 正在进行迁移,可能会对系统的稳定性产生影响。此外,如果同一工作负载的许多 Pods 同时被迁移,也会影响应用的稳定性。此外,如果同时迁移多个作业中的 Pods,可能会造成惊群效应。因此,我们希望顺序处理每个作业中的 Pods。</p><p>Koordinator 在之前提供的 PodMigrationJob 功能中已经提供了一些防护策略来解决上述问题。在 v1.4.0 版本中,Koordinator 将之前的防护策略增强为仲裁机制。当有大量的 PodMigrationJob 可以被执行时,由仲裁器通过排序和筛选,来决定哪些 PodMigrationJob 可以得到执行。</p><p>排序过程如下:</p><ul><li>根据迁移开始时间与当前时间的间隔进行排序,间隔越小,排名越高。</li><li>根据 PodMigrationJob 的 Pod 优先级进行排序,优先级越低,排名越高。</li><li>按照工作负载分散 Jobs,使得同一作业中的 PodMigrationJobs 靠近。</li><li>如果作业中已有 Pods 正在迁移,则该 PodMigrationJob 的排名更高。</li></ul><p>筛选过程如下:</p><ul><li>根据工作负载、节点、命名空间等对 PodMigrationJob 进行分组和筛选。</li><li>检查每个工作负载中正在运行状态的 PodMigrationJob 数量,达到一定阈值的将被排除。</li><li>检查每个工作负载中不可用副本的数量是否超出了最大不可用副本数,超出的将被排除。</li><li>检查目标 Pod 所在节点上正在迁移的 Pod 数量是否超过单个节点的最大迁移量,超出的将被排除。</li></ul><h3>6.冷内存上报</h3><p>为提升系统性能,内核一般尽可能不让应用程序请求的页面缓存空闲,而是尽可能将其分配给应用程序。虽然内核分配了这些内存,但是应用可能不再访问,这些内存被称为冷内存。</p><p>Koordinator 在 1.4 版本中引入冷内存上报功能,主要为未来冷内存回收功能打下基础。冷内存回收主要用于应对两个场景:</p><ul><li>对于标准的 Kubernetes 集群,当节点内存水位过高时,突发的内存请求容器导致系统直接内存回收,操作系统的直接内存回收触发时会影响已经运行容器的性能,如果回收不及时极端场景可能触发整机 oom。保持节点内存资源的相对空闲,对提升运行时稳定性至关重要。</li><li>在混部场景中,高优先级应用程序请求但未使用的资源可以被低优先级应用程序回收利用。对内存而言,操作系统未回收的内存,是不能被 Koordinator 调度系统看到的。为了提高混部资源效率,回收容器未使用的内存页面可以提高整机的资源利用效率。</li></ul><p>Koordlet 在 Collector Plugins 中添加了一个冷页面回收器,用于读取由 kidled(Anolis 内核)、kstaled(Google)或 DAMON(Amazon)导出的 cgroup 文件 memory.idle_stat。该文件包含页面缓存中的冷页面信息,并存在于 memory 的每个层次结构中。目前 koordlet 已经对接了 kidled 冷页面收集器并提供了其他冷页面收集器接口。</p><p>在收集冷页面信息后,冷页面回收器将把收集到的指标(例如节点、Pod 和容器的热页面使用量和冷页面大小)存到 metriccache 中,最后该数据会被上报到 NodeMetric CRD 中。</p><p>用户可以通过 NodeMetric 启用冷内存回收和配置冷内存收集策略,当前提供了 usageWithHotPageCache、usageWithoutPageCache 和 usageWithPageCache 三种策略,更多的细节详见社区设计文档[3]。</p><h3>7.非容器化应用的 QoS 管理</h3><p>在企业容器化过程中,除了已经运行在 K8s 上的应用,可能还会存在一些非容器化的应用运行在主机上。为了更好兼容企业在容器化过程这一过渡态,Koordinator 开发了节点资源预留机制,可以在尚未容器化的应用预留资源并赋予特定的 QoS 特性。与 Kubelet 提供的资源预留配置不同,Koordinator 主要目标是解决这些非容器化应用与容器化应用运行时的 QoS 问题,整体的方案如下图所示:</p><p><img src="/img/remote/1460000044652076" alt="图片" title="图片"></p><p>目前,应用程序需要按照规范将进程启动到对应的 cgroup 中,Koordinator 未实现自动的 cgroup 搬迁工具。针对宿主机非容器化应用,支持 QoS 如下:</p><ul><li>LS (Latency Sensitive)</li></ul><p>1.CPU QoS(Group Identity):应用按照规范将进程运行在 cgroup 的 cpu 子系统中,koordlet 根据 CPU QoS 的配置 resource-qos-config 为其设置 Group Identity 参数;<br>2.CPUSet Allocation:应用按照规范将进程运行在 cgroup 的 cpu 子系统中,koordlet 将为其设置 cpu share pool 中的所有 CPU 核心。</p><ul><li>BE (Best-effort)</li></ul><p>1.CPU QoS(Group Identity):应用按照规范将进程运行在 cgroup 的 cpu 子系统中,koordlet 根据 CPU QoS 的配置为其设置 Group Identity 参数。</p><p>关于宿主机应用 QoS 管理的详细设计,可以参考社区文档[4],后续我们将陆续增加其他 QoS 策略对宿主机应用的支持。</p><h3>8.其它特性</h3><p>除了上述新特性和功能增强外,Koordinator 在 v1.4.0 版本还做了一些如下的 bugfix 和优化:</p><ul><li>RequiredCPUBindPolicy</li></ul><p>精细化 CPU 编排支持 Required 的 CPU 绑定策略配置,表示严格按照指定的 CPU 绑定策略分配 CPU,否则调度失败。</p><ul><li>CICD</li></ul><p>Koordinator 社区在 v1.4.0 提供了一套 e2e 测试的 Pipeline;提供了 ARM64 镜像。</p><ul><li>Batch 资源计算策略优化</li></ul><p>支持了 maxUsageRequest 的计算策略,用于更保守地超卖高优资源;优化了节点上短时间大量 Pod 启停时,Batch allocatable 被低估的问题;完善了对 hostApplication、thirdparty allocatable、dangling pod used 等特殊情况的考虑。</p><ul><li>其它</li></ul><p>利用 libpfm4&perf group 优化 CPI 采集、SystemResourceCollector 支持自定义的过期时间配置、BE Pod 支持根据 evictByAllocatable 策略计算CPU 满足度、Koordlet CPUSetAllocator 修复了对于 LS 和 None Qos 的 Pod 的过滤逻辑、RDT 资源控制支持获得 sandbox 容器的 task IDs 等。</p><p>通过 v1.4.0 Release[5]页面,可以看到更多包含在 v1.4.0 版本的新增功能。</p><h2>未来计划</h2><p>在接下来的版本中,Koordinator 目前规划了以下功能:</p><ul><li>Core Scheduling</li></ul><p>在运行时侧,Koordinator 开始探索下一代 CPU QoS 能力,通过利用 Linux Core Scheduling 等内核机制,增强的物理核维度的资源隔离,降低混部的安全性风险,相关工作详见 Issue #1728[6]。</p><ul><li>设备联合分配</li></ul><p>在 AI 大模型分布式训练场景中,不同机器 GPU 之间通常需要通过高性能网卡相互通信,且 GPU 和高性能网卡就近分配的时候性能更好。Koordinator 正在推进支持多种异构资源的联合分配,目前已经在协议上和调度器分配逻辑上支持联合分配;单机侧关于网卡资源的上报逻辑正在探索中。</p><p>更多信息,敬请关注 Milestone v1.5.0[7]。</p><h2>结语</h2><p>最后,我们十分感谢 Koordinator 社区的所有贡献者和用户,是您们的积极参与和宝贵意见让 Koordinator 不断进步。我们期待您继续提供反馈,并欢迎新的贡献者加入我们的行列。</p><h3>相关链接:</h3><p>[1] 社区官方文档</p><p><a href="https://link.segmentfault.com/?enc=xHdbgL8fbh9DBHSTOFKeRw%3D%3D.TrBYWapzeojVWOIyyRTyavyu84luUiwEeYk2H7D829WtheKq1DJKz6M2dDbWmgqPYX4Y65%2BofDaRq6sr9qKDzZIJ3fgvwsf5izCsEwC4PUU%3D" rel="nofollow">https://koordinator.sh/zh-Hans/docs/next/designs/koordinator-...</a></p><p>[2] SPEC CPU</p><p><a href="https://link.segmentfault.com/?enc=QnLnshfm01%2F4sQ9MygTwwg%3D%3D.EbKyKwGIZ6%2FC9S8jESlOCqZ0fhe%2BmHA1RgVLW1vfVas%3D" rel="nofollow">https://www.spec.org/cpu2017/</a></p><p>[3] 设计文档</p><p><a href="https://link.segmentfault.com/?enc=%2F0%2FgzWpjnb6vJfsU8d04yg%3D%3D.E9TbZwXjEBD0UcVLjNRV7NmY8HZuTmGUpttqTXxU5So4dZnUjkJ%2BFqnEwr8tr4bqfdWGbCIOPM2V36xHRotVTlaTIteMFNCxRJoq4YhPwyn9%2BRGz5%2BS3rREr5ZzpDmJ1seek3UKaYCA4fzcfNK2kVucerG43pQX%2BRaP0X79HSjk%3D" rel="nofollow">https://github.com/koordinator-sh/koordinator/blob/main/docs/proposals/koordlet/20230728-support-cold-memory-compute.md</a></p><p>[4] 社区文档</p><p><a href="https://link.segmentfault.com/?enc=1fG%2B5ZXQxxj%2BGqRimcoKUw%3D%3D.QB4yggFUuK5eHYZFihaCQ7E%2FVb4kY76%2BsmRLrc%2B9GrpkU5l86hiMNX8RjlMCM5A%2B6mGEoJgz8ECNNI5Zn%2FUP7P%2F5BsS9mxjxyB3l4j7AtFs%3D" rel="nofollow">https://koordinator.sh/zh-Hans/docs/next/user-manuals/host-ap...</a></p><p>[5] v1.4.0 Release</p><p><a href="https://link.segmentfault.com/?enc=9HMiY1CKm2nAtnA9eyZDJA%3D%3D.RGLlR%2Bc33A%2FEud%2BNYwp9NzgICpnNy372M12uA%2BwZT7O8VFnPwaiTbSw9s3JWkrlDsG966gyA52jXZFndC1t6yj3gQdXUFXCc0UagDIrpEvM%3D" rel="nofollow">https://github.com/koordinator-sh/koordinator/releases/tag/v1.4.0</a></p><p>[6] Issue #1728</p><p><a href="https://link.segmentfault.com/?enc=HovDUHj3AVgdmv6NUHF9rw%3D%3D.X0M2aIx%2FYyt7FWr95KgRL9Uk4hY%2B0DU5oWGHN6%2FE4sfFRa%2FZW2VcnmxlrmSCWFRYLpjyV8I%2Bm1IB2kL0sR%2F%2BCA%3D%3D" rel="nofollow">https://github.com/koordinator-sh/koordinator/issues/1728</a></p><p>[7] Milestone v1.5.0</p><p><a href="https://link.segmentfault.com/?enc=tsB8o2GTaE0UZAj%2F6vfzEg%3D%3D.lbCCxUt6Tlbbtkji1TrOvaILX4HJbZJRb%2BK3el96zLxRJcm6oGo9Q8OaG3jRWh94reSuVNor96psKk50rXGI5w%3D%3D" rel="nofollow">https://github.com/koordinator-sh/koordinator/milestone/14</a></p><p>作者:乔普</p><p><strong><a href="https://link.segmentfault.com/?enc=Skepfp7CRMWGhthKCqy5gg%3D%3D.ccse39zE7YoNGiW5%2FNON2iBUKF2xCFv4SQK%2B3aRAXommEzrzVMcCsHaFMztUgyEZ0j%2FZkyh%2BTz749pSkYH8b7q0v5RXgupIX%2BqECHjkVVho%3D" rel="nofollow">原文链接</a></strong></p><p><strong>本文为阿里云原创内容,未经允许不得转载。</strong></p>
百万并发,API 网关抗住了亚运会流量高峰
https://segmentfault.com/a/1190000044648140
2024-02-22T11:27:26+08:00
2024-02-22T11:27:26+08:00
阿里云云栖号
https://segmentfault.com/u/aliyunqi
0
<h2>1.背景</h2><p>2023 年杭州亚运会给大家留下了美好的回忆,当时各种线上线下的活动和赛事也将如火如荼地展开,与亚运会相关的应用和服务迎来流量高峰。作为亚运会所有核心流量的入口,阿里云 API 网关的重要性不言而喻。为了确保 API 网关能够稳定、高效地处理大量的并发请求,阿里云推出了一款百万并发规格的 API 网关,为亚运会提供强大的技术支持。</p><p>百万并发规格的 API 网关,是我们专门针对高并发场景进行优化和升级的产品。它采用了先进的技术架构和算法,能够有效地处理大量的并发请求,保证 API 网关的稳定性和可靠性。同时,它还支持 API 级别的流控、热点数据缓存、多种安全机制,包括 API 授权与鉴权、流量控制等,能够有效地保护亚运相关业务系统的平稳运行。</p><p>API 网关将所有经过 API 网关的调用日志同步到用户自己的 SLS 日志服务中去,通过 SLS 日志服务可以进行实时日志查询、下载、多维度统计分析等,并且可以配置基于日志的报警策略;API 会自动将调用日志同步给阿里云云监控产品,用户可以在云监控产品上直接配置报警规则,监控报警的指标包括:Http 应答码,API 响应时间,请求次数,流入流量,流出流量。用户可以配置将调用日志上传到阿里云链路追踪平台,分析全链路调用情况。链路追踪 Tracing Analysis 提供了完整的调用链路还原、调用请求量统计、链路拓扑、应用依赖分析等工具,可以帮助用户提高开发诊断效率。</p><p><img src="/img/remote/1460000044648142" alt="图片" title="图片"></p><h2>2.突破 100 万 RPS 具备弹性能力的实例集群</h2><p>API 网关现在支持使用专享实例组建专享实例集群,突破最大规格专享实例的并发限制。API 网关当前可以提供的专享实例能够支持的最大能力有限,当最大规格的专享实例为 6 万 RPS 的实例,在一些大型场景下还无法满足用户的使用需要,API 网关在近期为用户提供了专享实例集群产品能力,专享实例集群能够根据用户对服务性能的需求进行缩容和扩容,突破网关可以支持的最大规格上限,在亚运会项目中为客户提供了突破了 100 万 RPS 的服务能力,满足用户更高并发的业务场景。API 网关提供的实例集群,具有灵活伸缩的能力,可以实时扩容和缩容,理论上只要底层资源足够,API 网关的实例集群具备无限扩容的能力。</p><h2>3.性能优秀</h2><p><img src="/img/remote/1460000044648143" alt="图片" title="图片"></p><p>阿里云的 API 网关除了可以为用户提供无限扩容的专享实例外,本身性能优秀,耗时极低,在性能上和容量上彻底打消后顾之忧。</p><p>性能是所有 API 网关的一个非常核心的一个指标,所有业务请求都需要过 API 网关,API 网关的性能会是整个系统性能指标的的非常关键的一环。阿里云 API 网关商业化后在公有云对公众用户提供服务七年有余,在性能上做个多次大幅度的优化,可以给大家分享一个 2023 年统计的一个专享实例的关键性能指标:98.17% 的请求在 API 网关耗时在 1 毫秒以内,API 网关平均耗时在 1ms 以内。</p><h2>4.流量控制</h2><p><img src="/img/remote/1460000044648145" alt="图片" title="图片"></p><p>流控是 API 网关最基础的能力,无论用户的业务 API 还是 AI 的 API 都需要有流控的保护。阿里云 API 网关允许用户根据后端系统最大承受能力设置流量阈值,当客户端请求总量超过阈值时,网关把多出的请求直接驳回,保证后端服务不会遇到过载请求的情况。API 网关允许用户通过多个维度对请求进行流控,可以对 API,App(访问凭证),用户(访问方的 App 归属用户)三个维度进行秒、分钟、小时、天等时间维度进行流控,API 网关同时提供针对请求中自定义参数这个维度的限流,请求的任意一个参数都可以成为流控的锚定值,比如用户可以指定请求中的 IP 头作为流控锚定值,那么可以通过 API 网关的流控能力轻松控制每个 IP 的请求 RPS。</p><h2>5.授权与鉴权</h2><p><img src="/img/remote/1460000044648146" alt="图片" title="图片"></p><p>不同的 AI 能力提供者对用户派发了不同的访问凭证,调用不同的 AI 提供者的 API 的鉴权方式各有不同。用户可以将这些复杂度统统在阿里云的 API 网关配置上,对其调用者提供统一的鉴权方式。用户可以通过 API 网关为不同的用户生成不同的访问凭证,并且为这些访问凭证设置有效期,也可以在 API 网关控制台随时删除指定的访问凭证。</p><p>阿里云 API 网关除了为用户提供访问凭证类型的鉴权方式,还提供了标准的 JWT 的鉴权方式,用户可以通过颁发 Token 的方式对调用者进行动态鉴权,并且可以通过管理 API 网关的插件数据集方式来 Block 已经颁发的 Token。</p><p>阿里云 API 网关还提供了灵活的第三方鉴权的能力,用户配置自己的鉴权服务为 API 的访问进行鉴权,API 网关在调用 API 后端服务之前先调用用户的鉴权服务,收到鉴权服务的鉴权成功应答后才会继续调用后端服务,否则给客户端返回鉴权失败的应答。</p><h2>6.日志监控与报警</h2><p><img src="/img/remote/1460000044648147" alt="图片" title="图片"></p><h3>6.1 SLS 日志同步与监控报警</h3><p>用户可以通过配置,将所有经过 API 网关的调用日志同步到用户自己的 SLS 日志服务中去,通过 SLS 日志服务您可以进行实时日志查询、下载、多维度统计分析等,您也可以将日志投递到 OSS 或者 MaxCompute 进行远期备份或深度分析。用户还可以使用这些日志作为日志审计的数据源,日志审计是法律刚性需求,是客户安全合规依赖的基础,是一些项目的必选项,可以轻松通过配置实现。用户除了可以在日志中看到调用的基本信息,包括域名、调用者身份、调用耗时,应答状态码等基本信息外,还可以配置记录整个请求和应答,便于排查问题。</p><h3>6.2 集成云监控</h3><p>API 会自动将调用日志同步给阿里云云监控产品,用户可以在云监控产品上直接配置报警规则,监控报警的指标包括:Http 应答码,API 响应时间,请求次数,流入流量,流出流量。如果需要对该 API 分组下的所有 API 应用相同的报警规则,进入 API 分组详情页,点击详情页右上角的开启云监控。云监控报警可设置多级报警,阈值处于不同区间时,对应 Critical 、Warning、Info 三个不同级别,不同级别通过不同渠道发送报警通知。</p><p><img src="/img/remote/1460000044648148" alt="图片" title="图片"></p><h3>6.3 全链路追踪平台</h3><p>用户可以配置将调用日志上传到阿里云链路追踪平台,分析全链路调用情况。链路追踪 Tracing Analysis 提供了完整的调用链路还原、调用请求量统计、链路拓扑、应用依赖分析等工具,可以帮助用户提高开发诊断效率。</p><p><img src="/img/remote/1460000044648149" alt="图片" title="图片"></p><p>配置好之后,就可以在全链路追踪平台上看到整个调用链每个节点的耗时情况了:</p><p><img src="/img/remote/1460000044648150" alt="图片" title="图片"></p><h2>7.对接微服务体系</h2><p><img src="/img/remote/1460000044648151" alt="图片" title="图片"></p><p>API 网关除了通过用户配置的后端业务系统的地址和后端业务系统进行通信外,同时支持从用户的微服务注册中心实时动态感知后端业务系统的服务地址,并进行点对点通信。</p><p>API 网关能够集成多种微服务注册中心,从而与微服务架构深入融合,降低系统的耦合度并提高程序的可管理性。网关可作为微服务系统的请求入口,负责所有客户端的接入、请求的路由和转发、以及保证微服务应用的安全和稳定。</p><p>微服务的注册中心,可以接收微服务业务系统的注册请求,并将业务系统的服务地址保存在注册表中。API 网关集成微服务的注册中心,如下图所示,网关作为服务的订阅者,可以从微服务的注册中心获取业务系统的服务地址、端口等信息,并根据地址和端口将请求分发到后端的多个业务系统的服务节点中,从而实现动态路由和负载均衡。</p><p>API 网关目前已经能够支持三种主流的微服务注册中心:</p><ul><li>Nacos</li><li>Zookeeper</li><li>Eureka</li></ul><h2>8.总结</h2><p>API 网关是阿里云的一款在线上平稳运行六年多的成熟云产品,为广大用户提供标准的高性能网关服务,它为用户提供 API 托管服务,覆盖设计、开发、测试、发布、售卖、运维监测、安全管控、下线等 API 各个生命周期阶段。阿里云 API 网关为用户提供了标准化的百万级 RPS 规格的专享实例,能够服务更多规模的业务系统,特别在本次亚运会中抗住了流量高峰,稳定、高效地处理大量的并发请求。</p><p>API 网关处理在容量上可以提供超大规格的实例外,在性能上也表现优异,耗时极低,自身平均耗时在 1ms 以内。API 网关除了能够提供主流的流控、鉴权等基础能力外,还集成了微服务网关的注册中心,能够与各种微服务架构实现融合,能为更多业务场景提供服务。</p><p><strong><a href="https://link.segmentfault.com/?enc=8svgz6MDOBxytOh6ionE6w%3D%3D.MF3ngpB8N%2Bo%2B6PLhVPGFN2CX0ZepcO8Gwq0ZWJEMdPHSYAWfZZOnOpdmhcXR%2BzUx%2BrQfh2L6FrYwv0qX8VC4lkmcMbpXeh5mUSkeFvInIpQ%3D" rel="nofollow">原文链接</a></strong></p><p><strong>本文为阿里云原创内容,未经允许不得转载。</strong></p>
大语言模型推理提速,TensorRT-LLM 高性能推理实践
https://segmentfault.com/a/1190000044645709
2024-02-21T15:44:26+08:00
2024-02-21T15:44:26+08:00
阿里云云栖号
https://segmentfault.com/u/aliyunqi
0
<h2>1.TensorRT-LLM 如何提升 LLM 模型推理效率</h2><p>大型语言模型(Large language models,LLM)是基于大量数据进行预训练的超大型深度学习模型。底层转换器是一组神经网络,这些神经网络由具有 self-attention 的编码器和解码器组成。编码器和解码器从一系列文本中提取含义,并理解其中的单词和短语之间的关系。</p><p>当前 LLM 模型推理的主要瓶颈是 GPU 显存资源不足。因此,各类加速框架主要集中于降低 GPU 显存峰值和提高 GPU 使用率两大目标。</p><p>TensorRT-LLM[1]是 NVIDIA 推出的大语言模型(LLM)推理优化框架。它提供了一组 Python API 用于定义 LLMs,并且使用最新的优化技术将 LLM 模型转换为 TensorRT Engines,推理时直接使用优化后的 TensorRT Engines。</p><p>TensorRT-LLM 主要利用以下四项优化技术提升 LLM 模型推理效率。</p><h3>1.1 量化</h3><p>模型量化技术是通过降低原始模型的精度来减少模型推理时的 GPU 显存使用。</p><p>TensorRT 支持多种模型的多种精度,以下列举了部分主流模型支持的量化精度。</p><p><img src="/img/remote/1460000044645711" alt="图片" title="图片"></p><p>W8A8 SQ 使用了 SmoothQuant 技术[2],在不降低模型推理准确率的前提下,将模型权重和激活层都降低为 INT8 精度,显著减少了 GPU 显存消耗。</p><p>W4A16/W8A16 是指模型权重为 INT4 或者 INT8,激活层为 FP16 精度。</p><p>W4A16 AWQ 以及 W4A16 GPTQ 分别实现了 AWQ[3]和 GPTQ[4]两篇论文中提到的量化方法。模型权重为 INT4,激活层为 FP16 精度。</p><h3>1.2 In-Flight Batching</h3><p>传统的 Batching 技术为 Static Batching 的,需要等 Batching 中所有序列推理完成后才能进行下一次批次。下图为一个输出最大 Token 为 8,Batch size 为 4 的推理过程,使用 Static Batching 技术。S3 序列在 T5 时刻就已经完成推理,但是需要等到 S2 序列在 T8 时刻推理完成后才会处理下一个 sequence,存在明显的资源浪费。</p><p><img src="/img/remote/1460000044645712" alt="图片" title="图片"></p><p>In-Flight Batching 又名 Continuous Batching 或 iteration-level batching,该技术可以提升推理吞吐率,降低推理时延。Continuous Batching 处理过程如下,当 S3 序列处理完成后插入一个新序列 S5 进行处理,提升资源利用率。详情可参考论文 Orca: A Distributed Serving System for Transformer-Based Generative Models[5]。</p><p><img src="/img/remote/1460000044645714" alt="图片" title="图片"></p><h3>1.3 Attention</h3><p>Attention 机制用于从序列中提取关键/重要信息,在情感识别、翻译、问答等任务中起着至关重要的作用。Attention 机制按照演进顺序可以分为 MHA(Multi-head Attention)、MQA(Multi-query Attention)[6]以及 GQA(Group-query Attention)[7]机制。MQA 和 GQA 都是 MHA 的变种。</p><p><img src="/img/remote/1460000044645715" alt="图片" title="图片"></p><p>MHA 是标准的多头注意力机制,每个 query 存储一份 KV,因此需要使用较多的显存。MQA 所有 query 共享一份 KV,推理时容易丢失一些细节信息。GQA 将 query 进行分组,组内共享一份 KV,可以有效避免 MHA 和 MQA 的问题。</p><p>TensorRT-LLM 支持 MHA、MQA 及 GQA 方式,可以在 tensorrt_llm.functional.gpt_attention 查看具体实现。</p><h3>1.4 Graph Rewriting</h3><p>TensorRT-LLM 在将 LLM 模型编译为 TensorRT Engines 时会对神经网络进行优化,提升执行效率。</p><h2>2.基于阿里云容器服务 ACK 的实战体验</h2><h3>2.1 云原生 AI 套件</h3><p>云原生 AI 套件是阿里云容器服务 ACK 提供的云原生 AI 技术和产品方案,帮助企业更快、更高效地落地云原生 AI 系统。</p><p>本文将介绍如何基于阿里云容器服务 ACK 云原生 AI 套件,利用 TensorRT-LLM 优化 LLM 模型推理。</p><h3>2.2 环境配置</h3><ol><li>参考文档安装云原生 AI 套件[8]。</li><li>登陆容器服务管理控制台[9],在左侧导航栏选择集群 > 应用 > 云原生 AI 套件。等待开发控制台准备就绪后,单击开发控制台。</li><li>在开发控制台左侧,选择 Notebook,在 Notebook 页面右上角,单击创建 Notebook 创建新的 Notebook 环境。Notebook 资源需要 CPU:12C,内存:40G,GPU 显存:24GB。(节点对应规格为 ecs.gn7i-c16g1.4xlarge[10])</li></ol><p><img src="/img/remote/1460000044645716" alt="图片" title="图片"></p><h3>2.3 准备 TensorRT-LLM 环境</h3><ol><li>构建 Notebook 所需镜像。</li></ol><pre><code>FROM docker.io/nvidia/cuda:12.2.2-cudnn8-runtime-ubuntu22.04
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get upgrade -y && \
apt-get install -y --no-install-recommends \
libgl1 libglib2.0-0 wget git curl vim \
python3.10 python3-pip python3-dev build-essential \
openmpi-bin libopenmpi-dev jupyter-notebook jupyter
RUN pip3 install tensorrt_llm -U --extra-index-url https://pypi.nvidia.com
RUN pip3 install --upgrade jinja2==3.0.3 pynvml>=11.5.0
RUN rm -rf /var/cache/apt/ && apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* && \
rm -rf /root/.cache/pip/ && rm -rf /*.whl
WORKDIR /root
RUN git clone https://github.com/NVIDIA/TensorRT-LLM.git --branch v0.7.1
ENTRYPOINT ["sh","-c","jupyter notebook --allow-root --notebook-dir=/root --port=8888 --ip=0.0.0.0 --ServerApp.token=''"]</code></pre><p><img src="" alt="图片" title="图片"></p><ol start="2"><li>下载模型,本文以 Baichuan2-7B-Base 为例。</li></ol><p>a.确认 tensorrt_llm 安装成功</p><pre><code>! python3 -c "import tensorrt_llm; print(tensorrt_llm.__version__)"
# 0.7.1</code></pre><p>b.安装 baichuan 依赖</p><pre><code>! cd /root/TensorRT-LLM/examples/baichuan
!pip3 install -r requirements.txt</code></pre><p>c.下载 Baichuan2-7B-Chat 模型</p><pre><code>!yum install git-lfs
!GIT_LFS_SKIP_SMUDGE=1 git clone https://www.modelscope.cn/baichuan-inc/Baichuan2-7B-Chat.git
!cd Baichuan2-7B-Chat/
!git lfs pull</code></pre><p>d.将模型编译为 TensorRT Engines,权重指定为 INT8。模型转换约 5 分钟。</p><pre><code>! cd /root/TensorRT-LLM/examples/baichuan
# Build the Baichuan V2 7B model using a single GPU and apply INT8 weight-only quantization.
! python3 build.py --model_version v2_7b \
--model_dir ./Baichuan2-7B-Chat \
--dtype float16 \
--use_gemm_plugin float16 \
--use_gpt_attention_plugin float16 \
--use_weight_only \
--output_dir ./tmp/baichuan_v2_7b/trt_engines/int8_weight_only/1-gpu/</code></pre><p>e.使用构建好的 tensort engines 进行推理</p><pre><code># With INT8 weight-only quantization inference
! python3 ../run.py --input_text "世界上第二高的山峰是哪座?" \
--max_output_len=50 \
--tokenizer_dir=./Baichuan2-7B-Chat \
--engine_dir=./tmp/baichuan_v2_7b/trt_engines/int8_weight_only/1-gpu/</code></pre><p>预期输出:</p><pre><code>Input [Text 0]: "世界上第二高的山峰是哪座?"
Output [Text 0 Beam 0]: "世界上第二高的山峰是喀喇昆仑山脉的乔戈里峰(K2),海拔高度为8611米。"</code></pre><h3>2.4 性能测试</h3><ol><li>使用 TensorRT-LLM 自带的 benchmark。</li></ol><p>向 _allowed_configs dict 中添加 baichuan2_7b_chat 配置,代码可参考链接[11]。</p><p>注:0.7.1 版本 benchmark 还未支持 baichuan2 模型,因此需要手动修改下 allowed_configs 配置。</p><pre><code>! cd /root/TensorRT-LLM/benchmarks/python
! vim allowed_configs.py
# "baichuan2_7b_chat":
ModelConfig(name="baichuan2_7b_chat",
family="baichuan_7b",
benchmark_type="gpt",
build_config=BuildConfig(
num_layers=32,
num_heads=32,
hidden_size=4096,
vocab_size=125696,
hidden_act='silu',
n_positions=4096,
inter_size=11008,
max_batch_size=128,
max_input_len=512,
max_output_len=200,
builder_opt=None,
)),</code></pre><p>运行 benchmark:</p><pre><code>! python3 benchmark.py \
-m baichuan2_7b_chat \
--mode plugin \
--engine_dir /root/TensorRT-LLM/examples/baichuan/tmp/baichuan_v2_7b/trt_engines/int8_weight_only/1-gpu \
--batch_size 1 \
--input_output_len "32,50;128,50"
# batch_size 并发度
# input_output_len 输入输出的长度,多个测试用例用分号分隔</code></pre><p>Expected outputs:</p><pre><code>[BENCHMARK] model_name baichuan2_7b_chat world_size 1 num_heads 32 num_kv_heads 32 num_layers 32 hidden_size 4096 vocab_size 125696 precision float16 batch_size 1 input_length 32 output_length 50 gpu_peak_mem(gb) 8.682 build_time(s) 0 tokens_per_sec 60.95 percentile95(ms) 821.977 percentile99(ms) 822.093 latency(ms) 820.348 compute_cap sm86 generation_time(ms) 798.45 total_generated_tokens 49.0 generation_tokens_per_second 61.369
[BENCHMARK] model_name baichuan2_7b_chat world_size 1 num_heads 32 num_kv_heads 32 num_layers 32 hidden_size 4096 vocab_size 125696 precision float16 batch_size 1 input_length 128 output_length 50 gpu_peak_mem(gb) 8.721 build_time(s) 0 tokens_per_sec 59.53 percentile95(ms) 841.708 percentile99(ms) 842.755 latency(ms) 839.852 compute_cap sm86 generation_time(ms) 806.571 total_generated_tokens 49.0 generation_tokens_per_second 60.751</code></pre><ol start="2"><li>对比 INT8 量化模型与原始模型性能。</li></ol><p>原始模型执行命令:</p><pre><code>def normal_inference():
from transformers import AutoModelForCausalLM, AutoTokenizer
from transformers.generation.utils import GenerationConfig
tokenizer = AutoTokenizer.from_pretrained(model_path, use_fast=False, trust_remote_code=True)
model = AutoModelForCausalLM.from_pretrained(model_path, device_map="auto", torch_dtype=torch.bfloat16, trust_remote_code=True)
model.generation_config = GenerationConfig.from_pretrained(model_path)
messages = []
messages.append({"role": "user", "content": prompt})
response = model.chat(tokenizer, messages)
print(response)</code></pre><p>INT8 量化模型命令:</p><pre><code>def tensorrt_llm_inference():
from subprocess import Popen, PIPE
script = f'''python3 /root/TensorRT-LLM/examples/run.py --input_text \"{prompt}\" \
--max_output_len=50 \
--tokenizer_dir=/root/TensorRT-LLM/examples/baichuan/Baichuan2-7B-Chat \
--engine_dir=/root/TensorRT-LLM/examples/baichuan/tmp/baichuan_v2_7b/trt_engines/int8_weight_only/1-gpu/'''
p = Popen(['sh', '-c', script], stdout=PIPE,
stderr=PIPE)
output, err = p.communicate()
if p.returncode != 0:
print(f"tensorrt_llm_inference() error:{err}")
return
print(output)</code></pre><p><img src="/img/remote/1460000044645717" alt="图片" title="图片"></p><p>TensorRT-LLM 加速方案在采用 INT8 模型量化的情况下,相比于默认的 Baichuan2-7B-Chat 模型,显存峰值降低了 43.8%,时延降低了 61.1%。</p><h2>3.相关资料</h2><p>[1] 参考文献</p><p>[2] SmoothQuant技术</p><p>[3] AWQ</p><p>[4] GPTQ</p><p>[5] Orca: A Distributed Serving System for Transformer-Based Generative Models</p><p>[6] MQA(Multi-query Attention)</p><p>[7] GQA(Group-query Attention)</p><p>[8] 安装云原生AI套件</p><p>[9] 容器服务管理控制台</p><p>[10] ecs.gn7i-c16g1.4xlarge</p><p>[11]<a href="https://link.segmentfault.com/?enc=4tFTQmDJCIMVD1NbZiXenQ%3D%3D.XG9ffanU%2F7z%2FNtuuTCl%2FkNQz%2BhuWeNSzhiS5oPWHld9u23zVUW9BI2ma1nk9nDE6t8la62%2B7w%2BkmwOPMPEiMk9qXIsnjVqFOVVoX1ruLGTiX%2FVqOTcJyaQvcccfFSi80dXwMNhQbqOt9nIcMBWuBhbJjf1GEuCP4MSEz1Z1xX%2B8UUGBEY7S4UphL92eA1Rjm" rel="nofollow">https://github.com/NVIDIA/TensorRT-LLM/blob/12e82e30b0e64b0f7ada0dc5993edd3b05385964/benchmarks/python/allowed_configs.py#L940TensorRT-LLM</a></p><p>[12]参考资料</p><p><strong><a href="https://link.segmentfault.com/?enc=TYprIfCW%2FycGdI5U6KxUIg%3D%3D.456yIKbCuarB1%2F3iISLEBDPXbkE0mZsYb6HIjygy%2F1VPElZ22TaS6D92ewcHqywI5mMULw79fnaT5iq7LqEHVZ%2FGh%2BcFgpxJZSTrnhSzLt8%3D" rel="nofollow">原文链接</a></strong></p><p><strong>本文为阿里云原创内容,未经允许不得转载。</strong></p>
秒级弹性!探索弹性调度与虚拟节点如何迅速响应瞬时算力需求?
https://segmentfault.com/a/1190000044642885
2024-02-20T16:46:01+08:00
2024-02-20T16:46:01+08:00
阿里云云栖号
https://segmentfault.com/u/aliyunqi
0
<h2>前言</h2><p>在前面的文章《弹性调度助力企业灵活应对业务变化,高效管理云上资源》中,我们介绍了阿里云容器服务 ACK 弹性调度为了帮助客户解决在使用云上弹性资源时,面对的“难以差异化控制业务资源使用量,缩容时部分业务 Pod 未释放”等挑战,提供了按照多级资源的优先顺序进行调度,以及按照定义的优先顺序进行缩容的能力。</p><p>本文将介绍弹性调度如何使用虚拟节点来满足您的业务弹性需求。</p><p>企业在实施应用弹性过程中,弹性速度和弹性位置是重点关注的两个核心指标。</p><p>对于追求高可用以及稳定性的企业来说,敏捷的弹性能够在业务流量突增时,保证系统的连续性与稳定性。同时,通过跨多地域部署应用,可以在地域性故障发生时,有效地维持服务的持续可用性。</p><p>对于大数据处理任务的企业来说,快速的弹性能够缩短任务执行时间,加快应用的迭代速度。同时,集中部署在单个地域,则可以减少应用之间的网络通信时延,从而进一步提升数据处理效率。</p><p>显然,这两个指标对于确保企业业务的稳定高效运行至关重要。</p><p>然而,许多企业在面对快速到来的业务流量高峰和日益增长的大数据算力需求时,现行的分钟级自动伸缩节点池的弹性响应已经无法满足需求。并且,通过合理的部署策略,实现预期的弹性位置,也颇具挑战。</p><p>为此,阿里云推出弹性容器实例(Elastic Container Instance,ECI),以十秒级的弹性速度,有效应对突发流量的弹性需求。同时,阿里云容器服务 Kubernetes 版(ACK)利用虚拟节点技术实现与 ECI 弹性资源的无缝集成,使得业务能够在集群内灵活动态地调用 ECI 资源,迅速应对弹性挑战。此外,容器服务 ACK 的弹性调度功能在将业务调度到 ECI 上时,还能维持业务的亲和性配置不变,确保应用运行的稳定和高效。</p><h2>使用虚拟节点实现秒级弹性</h2><p>为了在 ACK 中使用 ECI,需要在 ACK 集群中安装虚拟节点组件。</p><blockquote><p>在 ACK Pro 版集群中,可以通过组件管理页面部署 ack-virtual-node 组件,该组件默认被托管,不占用 Worker 节点资源。</p><p>在 ACK 专有版集群中,可以通过应用市场页面部署 ack-virtual-node 组件,安装成功后会在 kube-system 命名空间下创建一个名为 ack-virtual-node-controller 的 deployment,该 deployment 会运行在您的 Worker 节点上。</p></blockquote><p>安装成功后用户可以通过 kubectl get no 命令在集群中查看到若干虚拟节点,代表虚拟节点安装成功。</p><p>虚拟节点安装成功之后,可以使用弹性调度功能配置 ECI 的使用策略,以下是“优先调度 ECS,当 ECS 资源使用完后使用 ECI 资源”的示例。</p><pre><code>apiVersion: scheduling.alibabacloud.com/v1alpha1
kind: ResourcePolicy
metadata:
name: test
spec:
strategy: prefer
units:
- resource: ecs
- resource: eci</code></pre><p>配置了以上 ResourcePolicy 之后,在 default 命名空间下的所有 Pod 都将遵循以下的调度规则:优先使用 ECS,ECS 资源用完后使用 ECI。</p><p>需要注意的是:以上配置会使得 ECS 节点上的抢占功能失效,如果需要同时保持在 ECS 上的抢占能力,请配置 preemptPolicy=BeforeNextUnit,如果需要限定生效的业务范围,请按需配置 selector。</p><p>以下是实际使用效果:</p><p>首先,提交一个 Deployment,8 个业务 Pod 中仅有 7 个业务 Pod 能够被成功调度。</p><p><img src="/img/remote/1460000044642887" alt="图片" title="图片"></p><p>此时,提交 ResourcePolicy,并将 Deployment 的副本数增加到 10,新的副本将全部运行在 ECI 上。</p><p><img src="/img/remote/1460000044642889" alt="图片" title="图片"></p><p>通过统计业务 Pod 的创建时间以及 startTime,可以看到这里新 Pod 的创建时间在 13 秒,远远低于自动伸缩节点所需的弹性时间。</p><p><img src="/img/remote/1460000044642890" alt="图片" title="图片"></p><h2>降低大数据任务通信时延</h2><p>若您的集群配置了多个可用区的虚拟节点,在默认情况下,ECI Pod 可能会被调度在多个可用区上。如下图,在默认情况下,nginx 被调度到了 C 和 D 两个可用区的 virtual node 上。</p><p><img src="/img/remote/1460000044642891" alt="图片" title="图片"></p><p><img src="/img/remote/1460000044642892" alt="图片" title="图片"></p><p>对于大数据型应用,配置可用区亲和往往意味着计算 Pod 之间的网络通信代价更小,进而带来更高的吞吐量。通过阿里云弹性调度,您可以通过 Pod 上的节点亲和以及 Pod 亲和限制业务调度的可用区,从而实现 ECS 上的 Pod 与 ECI 上的 Pod 调度在相同的可用区上。</p><p>以下是两种在 ECI 上配置相同可用区调度的示例,分别使用了指定可用区调度以及不指定可用区调度两种方式,在以下的两个例子中,已提前提交了 ResourcePolicy:</p><h3>手动指定可用区</h3><p>原生 Kubernetes 提供了节点亲和调度语义来控制 Pod 的调度位置,以下的例子中我们指定 nginx 服务仅在可用区 C 上进行调度。您唯一需要进行的修改是在工作负载的 PodTemplate 或 PodSpec 中添加节点亲和约束。</p><pre><code>apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx
name: nginx-deployment-basic
spec:
replicas: 9
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: topology.kubernetes.io/zone
operator: In
values:
- cn-hongkong-c
containers:
- image: 'nginx:1.7.9'
imagePullPolicy: IfNotPresent
name: nginx
resources:
limits:
cpu: 1500m
requests:
cpu: 1500m
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File</code></pre><p>同样将业务 Pod 扩容到 9,此时能够观察到业务 Pod 全部运行在可用区 C 上,由于集群中 ECS 节点均为可用区 D 上的机器,因此所有业务 Pod 全部运行在 ECI 上。</p><p><img src="/img/remote/1460000044642893" alt="图片" title="图片"></p><h3>最优可用区感知调度</h3><p>为应对大数据计算需求,通常需要部署大量的 Pod,这时候确保 ECI 提供充足的算力资源成为关键。为确保选择到具有充足剩余算力的可用区,可以在指定可用区亲和时使用 Pod 亲和。在 ECI 调度过程中,调度器会参考 ECI 提供的可用区建议,选择一个可用算力更多的可用区,从而实现自动选择更优位置的效果。以下例子中我们将限制 Pod 仅在 ECI 上调度,并通过 Pod 亲和限制 Pod 必须被调度到同一个可用区。</p><p>注:Pod 亲和会使得后续 Pod 与第一个被调度的 Pod 亲和在相同可用区,当采用 ECS+ECI 弹性调度时,由于第一个被调度的 Pod 通常为 ECS Pod,会使得后续 ECI Pod 亲和在 ECS 相同的可用区,此时建议您使用 preferredDuringSchedulingIgnoredDuringExecution。</p><p>提交的 ResourcePolicy 为:</p><pre><code>apiVersion: scheduling.alibabacloud.com/v1alpha1
kind: ResourcePolicy
metadata:
name: test
spec:
strategy: prefer
units:
- resource: eci</code></pre><p>提交的工作负载为:</p><pre><code>apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx
name: nginx-deployment-basic
spec:
replicas: 9
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- nginx
topologyKey: topology.kubernetes.io/zone
containers:
- image: 'nginx:1.7.9'
imagePullPolicy: IfNotPresent
name: nginx
resources:
limits:
cpu: 1500m
requests:
cpu: 1500m
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File</code></pre><p>提交后可用发现,此时 Pod 依然均调度在相同的可用区,此时调度到的可用区将会是 ECI 推荐的更优可用区。</p><p><img src="/img/remote/1460000044642894" alt="图片" title="图片"></p><h2>保证在线业务高可用</h2><p>对于在线业务而言,配置业务多可用区部署是保证业务高可用的一种有效手段。通过阿里云弹性调度,您可以通过 Pod 上的拓扑分布约束来实现 ECS 上的 Pod 与 ECI 上的 Pod 遵循相同的拓扑分布约束,从而实现业务的高可用。</p><p>以下是一个在 ECI 上配置业务高可用的示例,指定了业务 Pod 在多个可用区上均匀分布,并且在 ECS 资源不足时使用 ECI。</p><pre><code>apiVersion: scheduling.alibabacloud.com/v1alpha1
kind: ResourcePolicy
metadata:
name: test
spec:
strategy: prefer
units:
- resource: ecs
- resource: eci
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx
name: nginx-deployment-basic
spec:
replicas: 9
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
topologySpreadConstraints:
- labelSelector:
matchLabels:
app: nginx
maxSkew: 1
topologyKey: topology.kubernetes.io/zone
whenUnsatisfiable: DoNotSchedule
containers:
- image: 'nginx:1.7.9'
imagePullPolicy: IfNotPresent
name: nginx
resources:
limits:
cpu: 1500m
requests:
cpu: 1500m
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File</code></pre><p>提交上述资源清单后,Pod 最终的可用区和节点分布如下,由于可用区 D 上存在三个 ECS 节点,因此最终 Pod 在可用区 D 上存在 5 个 Pod,在可用区 C 上存在 4 个 Pod。能够满足约束中最大倾斜度为 1 的要求。</p><p><img src="/img/remote/1460000044642895" alt="图片" title="图片"></p><h2>What's Next</h2><p>阿里云容器服务 Kubernetes 版(ACK)在标准 K8s 调度框架的基础上扩展了弹性调度功能,致力于提高应用性能和集群整体资源的利用率,保障企业业务的稳定高效运行。</p><p>在前期文章《弹性调度助力企业灵活应对业务变化,高效管理云上资源》中,我们已经探讨了如何通过阿里云容器服务 ACK 的弹性调度有效管理各类弹性资源,以帮助企业优化资源配置,实现降本增效。</p><p>在本文中,我们又深入解析了 ACK 弹性调度如何与弹性容器实例(ECI)这一关键弹性资源结合,凭借 ECI 快速弹性、秒级计费和即时释放的优势,显著提升企业业务的稳定性和效率。</p><p>在即将推出的调度系列文章中,我们将详细介绍如何在 ACK 上管理和调度 AI 任务,助力企业 AI 业务在云端快速落地。</p><p>作者:吴昆</p><p><strong><a href="https://link.segmentfault.com/?enc=NEB5eexpbQ3DGyAvo6%2FnRA%3D%3D.sEB6spvDlkttCT4OTHSiVenj5MgR5WuJu%2FwuFdyHm4CoWJh4T%2BHvhkWjsyJe1o%2FKMCUI7RZiElxldzSBZxK8V9p3RxyvQLaAgewtMKtEnsQ%3D" rel="nofollow">原文链接</a></strong></p><p><strong>本文为阿里云原创内容,未经允许不得转载。</strong></p>
解读 EventBridge Transform,数据转换和处理的灵活能力
https://segmentfault.com/a/1190000044639645
2024-02-19T16:48:46+08:00
2024-02-19T16:48:46+08:00
阿里云云栖号
https://segmentfault.com/u/aliyunqi
0
<p>阿里云 EventBridge 提供了强大而灵活的事件总线服务,它可以连接应用程序、阿里云云服务和阿里云 Serverless 服务来快速构建 EDA(Event-driven Architectures)事件驱动架构,驱动应用与应用,应用与云的连接。除此之外,它还可以作为流式的数据管道,在不同的数据仓库和数据处理或分析程序之间快速构建 ETL 系统。</p><p>本文将从以下几个方面展开对阿里云 EventBridge Transform 能力的介绍:</p><p>1)首先介绍 ETL 基本概念;</p><p>2)接着介绍 T(Transform)的能力;</p><p>3)最后探讨 EventBridge Transform 能力及落地场景。</p><h2>1.什么是 ETL?</h2><p>ETL 表示的是数据提取(Extract)、转换(Transform)和加载(Load)的过程,是数据集成的核心任务。三个步骤的主要作用如下:</p><h3>1.1 提取</h3><p>从数据源中提取数据,数据源可以是各种数据存储系统,比如消息队列、数据库等。</p><h3>1.2 转换</h3><p>对提取的数据进行转换操作,比如数据富化、数据清洗、数据聚合、数据拆分、格式转换等。</p><h3>1.3 加载</h3><p>将经过转换后的数据加载到目标服务中,比如数据仓库、数据湖、BI 系统等。ETL 应用广泛,它可以帮助企业管理和利用数据,实现数据驱动的决策和业务转型。</p><p><img src="/img/remote/1460000044639647" alt="图片" title="图片"></p><h2>2.T(Transform)的能力</h2><h3>2.1 Transform 应用场景</h3><p>ETL 中的 T(Transform)可以对提取的数据进行转换操作,它具体的使用场景如下:</p><h4>2.1.1 数据富化</h4><p>调用外部服务获取额外信息丰富原始数据,提高数据的完整度和可应用性。</p><h4>2.1.2 数据清洗</h4><p>对原始数据进行清洗或验证,去除重复、缺失或者不准确的数据,确保数据的质量和准确性,或者对数据中的信息进行脱敏,确保 数据的安全性。</p><h4>2.1.3 数据聚合</h4><p>将多条原始数据进行合并,形成一个统一的数据视图,便于后续的快速分析和查询。</p><h4>2.1.4 数据拆分</h4><p>将单条原始数据根据业务需求拆分为多条数据。</p><h4>2.1.5 数据格式转换</h4><p>将上游数据转换为目标服务可接受的格式,比如将 Base64、Avro、PB 等格式的原始数据统一转换为 json 格式。</p><p>通过 Transform,可以将原始数据转化为一致性、准确性和安全性兼具的高质量数据,为后续的数据分析等操作提供可靠的基础。</p><h3>2.2 业界 Transform 架构概述</h3><p>目前业界的 Transform 能力,常见的做法有以下几类:</p><h4>2.2.1 内置开箱即用的简单且轻量的 Transform 能力</h4><p>数据清洗:去除数据中的敏感字段、处理噪音数据等。</p><p>数据格式转换:将数据中的指定字段转换为特定格式。</p><h4>2.2.2 内置 Custom Transform 能力</h4><p>用户可自定义 Transform 的逻辑。这种常见的做法是:用户根据 Custom Transform 的接口规范,实现接口并将实现的代码打成 jar 包,之后在系统导入该 jar 包即可使用自己编写的 Transform 逻辑。</p><h4>2.2.3 Remote Custom Transform 能力</h4><p>通过 Remote 调用的方式调用外部系统对数据进行 Transform。</p><p>上述 1、2 两种做法,由于其 Transform 与系统逻辑高度耦合,共享计算资源,并不太适合在 Transform 中进行重量级计算,仅适合应用在一些轻量、简单的业务场景。更优的做法是 Remote Custom Transform,它解耦了 Transform 业务逻辑与数据通路,更具灵活性。</p><h3>2.3 阿里云 EventBridge Transform 设计</h3><p>阿里云 EventBridge 通过集成阿里云函数计算实现了 Custom Transform 能力,通过 Remote 调用的方式将 Transform 业务逻辑与数据通路解耦。提高了 Transform 的灵活性,降低计算资源的挤兑风险。</p><h4>2.3.1 链路架构</h4><p>使用阿里云的函数计算进行 Transform 时,EventBridge 的整体链路如图所示。</p><ul><li>EventBridge 从 Source 侧提取数据。</li><li>提取的数据,先经过攒批(window)逻辑的处理,达到攒批条件后,数据将以批的方式交由下一步处理。过滤(Filter)会遍历每一条数据,判断是否要丢弃该条数据。过滤完成后,数据将仍以批的方式交由下一步处理。转换(Transform)阶段会调用函数计算,将数据交由用户编写的函数代码进行处理,Transform 阶段会等待函数执行完成并接收其返回的处理结果。</li><li>EventBridge 将 Transform 处理后的数据加载到 Sink 侧。</li></ul><p><img src="/img/remote/1460000044639648" alt="图片" title="图片"></p><p>下文在此基础之上继续探讨链路中涉及的几个关键问题:</p><h4>2.3.2 攒批问题</h4><p>攒批可以批量聚合多条数据,在达到攒批条件后再将数据批量推送给下一步进行处理。EventBridge 将攒批能力置于 Transform 之前,通过攒批能力提升了数据的处理效率和吞吐量,并且显著降低 Transform 调用函数计算的次数。</p><p>EventBridge 从数量和时间两个条件来控制攒批的行为,只要达到其中一个条件时就会触发批量推送。</p><p>批量推送条数:单次可聚合的最大数据条数。</p><p>批零推送间隔:聚合的间隔时间,系统每到间隔时间会将已聚合的数据批量推送给下一步。</p><h4>2.3.3 高可用问题</h4><p>Transform 处理数据时可能出现异常,为避免异常导致数据丢失或影响链路的稳定性和可用性等。Transform 复用了 EventBridge 的重试、死信、容错等机制。</p><ul><li>重试机制由于网络异常、系统 crash 等原因导致 Transform 处理异常时,EventBridge 会按照用户选择的重试策略进行重试,目前支持退避重试、指数衰减重试两种方式。</li><li>死信队列当数据超过重试次数后仍未 Transform 成功时,会变成死信数据。如果不希望死信数据被丢弃,用户可以配置死信队列,所有的死信数据会被 EventBridge 投递到死信队列中,目前 EventBridge 支持 Kafka、RocketMQ、MNS 作为死信队列的目标端。</li><li>容错策略当 Transform 发生错误时,EventBridge 提供了以下两种处理方式:</li></ul><p>1.允许异常容错:当 Transform 异常发生时不会阻塞执行,会继续处理后续的数据。但是,EventBridge 会重试发生异常的数据,在超出重试策略后根据配置将数据投递至死信队列或直接丢弃。<br>2.禁止容错:不允许错误,当 Transform 异常发生且超过重试策略配置时会阻塞执行。</p><h4>2.3.4 费用问题</h4><p>函数计算的调用和函数的执行会产生一定费用,包含函数调用、资源使用(CPU、Mem 等)和公网出流量三部分的费用。为减少函数计算产生的费用,函数计算定向减免了来自 EventBridge 的函数调用次数费用,即 EventBridge 触发函数计算产生的函数调用次数不再计入费用账单[3,4]。</p><h3>2.4 产品交互</h3><p>目前可在 EventBridge 的事件流中体验 Transform 能力,如图所示。</p><p><img src="/img/remote/1460000044639649" alt="图片" title="图片"></p><p>对于阿里云函数计算来说,我们提供了两种方式:</p><h4>2.4.1 新建函数模板</h4><p>可在提供的模板之上,直接创建函数。产品层面提供了简易的 IDE,便于用户编写和调试代码。</p><p><img src="/img/remote/1460000044639650" alt="图片" title="图片"></p><h4>2.4.2 绑定现有函数</h4><p>支持绑定用户已有的函数。更详细的使用可参考 Transform 帮助文档,见附录[4]。</p><p><img src="/img/remote/1460000044639652" alt="图片" title="图片"></p><h3>2.5 Transform 优势</h3><h4>2.5.1 Serverless Transform 特性</h4><p>EventBridge Transform 基于 Serverless 函数计算构建,可享受 Serverless 服务免运维、资源弹性伸缩、按量付费等特性,具体如下:</p><ul><li>弹性:百毫秒内级别的伸缩,可满足波峰波谷、Burst、持续稳定等多样化的负载场景。</li><li>免运维:用户无需关心和运维 Transform 运行环境及资源。</li><li>按量付费:用户只需支付函数运行所产生的费用,更重要的是 EventBridge 调用函数所产生的调用次数费用将不计费。</li><li>灵活性:UDF 的方式可满足实际业务中复杂、个性化的需求。</li><li>多语言支持支持:go、python、java、nodejs 等主流语言,可选择熟悉或适合的语言实现 Custom Transform 逻辑。</li><li>架构解耦:Remote Transform 的架构将 Transform 业务逻辑和系统逻辑结解耦,资源隔离,避免产生资源争抢等问题。</li><li>模版支持:产品层面提供了多种 Transform 函数模板,避免用户从零开始。</li><li>攒批提效:通过攒批,函数的入参为批量的消息,大幅提升了消息的处理效率和吞吐。</li></ul><h2>3.客户场景案例介绍</h2><h3>3.1 数据格式转换+架构升级</h3><p>消息(MNS)->Transform->消息(RocketMQ)</p><p>客户面临架构升级问题,希望将系统依赖的 MNS 升级为 RocketMQ,但系统架构复杂,依赖 MNS 逻辑较多,且牵涉研发人员较多,预计全部升级架构需持续几个月时间。为保证架构升级过程中产生的数据一致性问题,客户使用 EventBridge 将旧架构的 MNS 消息实时同步到新架构的 RocketMQ 实例中,来保证数据在一致性。同时为了适配新架构中的消息设计,客户使用 FC Transform 先将旧消息转换为目标格式,再投递至 RocketMQ 中。</p><h3>3.2 数据清洗+数据转储</h3><p>消息(RocketMQ)->Transform->OSS</p><p>客户会将用户产生的视频数据投递到 RocketMQ 中,这些数据用户是可以查看的。为此客户选择 OSS 来进行文件存储,满足这种写多读少、低成本存储数据的场景。但是,视频数据中包含了若干敏感信息,为此客户使用 FC Transform 对视频中的敏感数据做清除后,再将视频投递到 OSS 中。</p><h2>4.总结与展望</h2><p>EventBridge Transform 通过集成函数计算,满足了实际业务中复杂、个性化的需求。其弹性伸缩、免运维、按量付费的特性深受客户青睐。未来 Transform 会通过集成更多的服务(阿里云工作流、HTTP Destination 等)解锁更多的业务场景,满足多样化需求。</p><p><strong>相关链接:</strong></p><p>[1] EventBridge-事件流-事件内容转换</p><p>[2] EventBridge-事件流产品首页</p><p>[3] 定向减免消息类产品和云工作流的函数调用次数费用</p><p>[4] 函数计算计费项降价通知</p><p><strong><a href="https://link.segmentfault.com/?enc=s7AuPCQzDQ9OFXow9GGt7w%3D%3D.ks0qnEbzSOOqs4vIrGJEXhET3vllsEJmX7w2EN%2BV9Gc8ODk0QchNZlvP%2By0gfcgaInbZX5XtbdJ1OgmyqVVq7EoknO8LH1Ckaw5zHhIInSY%3D" rel="nofollow">原文链接</a></strong></p><p><strong>本文为阿里云原创内容,未经允许不得转载。</strong></p>
从 13 个企业关心的问题看懂用云范式的改变
https://segmentfault.com/a/1190000044638778
2024-02-19T14:30:14+08:00
2024-02-19T14:30:14+08:00
阿里云云栖号
https://segmentfault.com/u/aliyunqi
0
<p>今天,容器和 K8s 已经成为应用研发运维的新标准,行业调研数据显示,2022 年有 64% 的最终用户在生产环境中使用了 K8s;2022 年托管在云上的 K8s 集群增速达到了 127%。我们也看到云托管的 K8s 将在 2023 年超过本地部署。这意味着容器化上云成为了新常态。</p><p>同时,随着互联网分布式技术的普及,微服务架构被广泛使用,围绕着一整套的技术体系,运维复杂度陡然上升。在这两个趋势之下,我们看到企业和开发者面临新的挑战:比如 K8s 的入门门槛高、维护比较复杂,而微服务的运维体系很复杂,企业的业务流量波动很大,需要更好的按需弹性、同时实现更低成本;云产品组合选择比较多,对于企业来讲需要更好的性价比。</p><p>为了解决企业在当下背景下面临的挑战,阿里云带来一款全新的产品:容器计算服务 ACS,将容器和资源一体化,打造全新的用云范式。</p><p>ACS 简化了产品的实例类型,它只有 3 种实例:通用型、任务型、独享型。以一个典型的互联网网站服务为例,一个典型企业的应用工作负载,一般包括 Web 应用程序、CICD 流水线、大数据计算、数据库中间件等。对于这样经典的场景,我们推荐在 Web 应用程序里使用通用型实例,CI/CD 流水线使用通用型实例,大数据计算框架使用任务型实例,数据库、缓存就使用独享型实例。通过这样的实例组合,能够实现企业最大化的资源利用和成本降低。</p><p>目前,容器计算服务 ACS 已开启体验。我们也期待有更多的用户通过 ACS,能够去享受容器化用云的红利。点击阅读原文,即可体验容器计算服务 ACS。</p><blockquote><strong>体验链接:<a href="https://link.segmentfault.com/?enc=YtYyP03oeoRjfpO4Cu4rQA%3D%3D.VnuYYbUjJERd%2BdQyn7n2s05OQMAic%2FPY7%2Fn6WMRmHKD02E6tpvUh97ryavwty1Pd" rel="nofollow">https://www.aliyun.com/product/acs</a></strong></blockquote><p>我们特别邀请阿里云云原生应用平台负责人丁宇,针对 ACS 相关话题,期待通过他的回答给予企业和开发者更多的思考。</p><h4>问题 1:阿里云目前有四十余款核心 Serverless 产品的发布,这背后反映出了云上开发需求的巨大转变。您如何看待这一变化?</h4><p>丁宇:出现这一变化的原因与越来越多的客户开始上云有关。千行百业的客户都在上云,并且他们寻求的是更高效、便捷、经济及易用的服务。这标志着客户进入到了一个用好云的阶段,他们对云产品提出了更高的要求,期望免运维、全托管、按需弹性、按量付费。因此,云平台也在升级云产品,朝着 Serverless 方向投入产品建设,以满足客户增长对于云的多快好省的需求。</p><p>云具备资源池化、弹性能力、存储计算分离、分布式存储和网络等技术优势,正是这些技术的底座和基础,让我们能够更迅速地推进 Serverless 化产品建设。</p><h4>问题 2:那您如何看待当前企业应用云的现状?ACS 又是如何解决这些问题的?</h4><p>丁宇:据调研报告显示,2022 年,64% 的最终用户在生产环境中使用了 K8s,并且托管在云上的 K8s 集群年增速达到 127%,所以说上云用容器已经成为一个巨大的趋势。预计到 2023 年,云托管的 K8s 将超过本地部署,这意味着容器化用云将成为一个新常态。</p><p>此外,随着越来越多的应用架构微服务化,服务治理的复杂度在不断上升,当微服务遇到 K8s,带来了更多的复杂度。例如,K8s 配置复杂,计算资源机型多、代际多,集群和节点组件管理复杂,业务高峰实现按需弹性难度大等。</p><p>因此,为了降低 K8s 使用和运维复杂度,解决资源和容器割裂的问题,我们设计了容器计算服务 ACS。它能大幅简化云的使用界面,让云的使用界面上移,实现容器、资源一体化。同时 K8s 集群不需要维护,节点不需要运维,ACS 的功能与资源类型也极为简洁,可以让我们实现灵活的资源调配,支持多种应用场景。</p><p>总体来看,ACS 可以让企业实现高性价比的运营,解决企业在新时期用云的一些需求、痛点和挑战。</p><h4>问题 3:ACS 是全球首个容器计算服务,它实现了容器与资源的一体化,这实际上是一种新的范式,这一点具体是如何实现的?</h4><p>丁宇:在用云的过程中,我们的客户,尤其是那些头部企业,他们会先购买 ECS,然后配置网络和存储。他们对资源有很强的把控需求,一些头部企业已经开始拥抱容器技术,他们会结合 ACK 和 ECS 来管理资源,并对 ACK 进行扩展和定制。这种组合使用的方式要求企业对资源、K8s、ACK 有很强的把控能力,因此门槛相对较高。</p><p>但今天我们看到了一个趋势,那就是 K8s 已经成为了行业标准。每个企业和开发者都希望使用容器。众所周知,K8s 能够降低成本,提高研发效率。然而,许多企业无法把控现有的技术栈来接纳、控制 K8s 的复杂度,无法应对随之而来的复杂性。</p><p>ACS 做的事情就是把这些概念都精简了。对于开发者而言,只需一个配置脚本或一个命令行,就可以将应用发布到云上。对新手用户来说,通过简单配置页面上的三、五个参数,即可轻松发布镜像到云上。我们为企业提供了一套 OpenAPI,使他们能够与自己的 PaaS 平台轻松对接。</p><p>ACS 从概念上进行了大量抽象,简化了过去需要深入学习的几十个概念。因此,ACS 不仅具备良好的生态标准和基础,还降低了运维成本,解决了过去使用云服务时的各种问题。总的来说,ACS 大幅降低了用云的门槛,并实现了客户用云界面的上移。</p><h4>问题 4:云计算的整个发展过程一直在不断地对后台资源进行抽象化。这次的 ACS 是对容器和资源又做了一次抽象。在这个过程中,阿里云面临的最大研发挑战是什么?为什么阿里云是第一个实现这一创新的公司呢?</h4><p>丁宇:阿里云在这方面拥有许多优势。首先,在同等体量企业中,阿里云是第一个能够把阿里巴巴这样的企业搬到云上,这意味着我们是一个云原生上云。阿里云经历过双十一、阿里巴巴整体上云这样的场景,在这些场景里我们积累了大量的云原生技术,包括海量的规模调度、安全隔离以及资源混部等多方面的能力。</p><p>同时,我们服务了中国最大的客户群体,在云计算领域,阿里云处于领先地位;此外,阿里云还拥有深厚的开源背景,影响了非常多的开发者。</p><p>我们看到,K8s 已经得到越来越广泛的应用,用户对云计算的期望也越来越高,他们希望云服务能够更加高效、快速、经济、简单。</p><p>我们坚信这个趋势,并相信这个趋势一定会成为既定事实。因此,阿里云在提前布局,将我们多年的技术积累和实际场景的磨练转化为产品,以更早地服务于更广大的客户群体。</p><h4>问题 5:您认为 ACS 在面世后会遇到哪些市场挑战?比如用户在使用过程中可能会遇到哪些问题?</h4><p>丁宇:基于我们的前提假设,即 K8s 的普及趋势,我们相信,K8s 将从头部客户到中小企业客户全面普及。对于中小企业客户和开发者来说,ACS 是一个易于使用、门槛低的产品。这些用户刚好又渴望使用企业级的 K8s 服务,但又受限于其技术门槛。</p><p>对于头部客户如何更好地使用 ACS,我认为需要一点时间去适应,因为这些客户已经习惯了在 VM 和 ACK 上组建一个庞大的团队来维护技术体系。他们拥有很强的资源控制力、资源确定性和技术定制化,并且已经习惯了这样的模式。</p><p>所以我认为,ACS 要慢慢演进,先服务好中小企业客户,再慢慢了解头部客户的需求。长远来看,我相信客户对云的需求一定会趋同,即更简单、更经济,我们也将朝这个方向努力。</p><h4>问题 6:现在 ACS 已经进入邀请测试阶段,您能分享一下行业客户的试用情况和反馈吗?</h4><p>丁宇:客户的反馈非常积极。我们有许多客户正在参与邀测,诸如斯凯奇、安利、安踏、心动公司等,他们正在使用 ACS 进行一些线上测试和应用运行。以心动公司为例,他们的技术负责人告诉我们:ACS 是一款代表云计算未来的产品。它极大地简化了整个操作流程,诸如配置、弹性等方面,真正让企业能专注于业务创新,这对我们来说是巨大的肯定。我们希望更多的客户能尽快试用这个产品。</p><h4>问题 7:ACS 的确是在用户端上进行了巨大简化,这种变化是否会要求用户将来在系统架构上进行思路上的改变?</h4><p>丁宇:我们的一个核心出发点是要兼容社区标准。ACS 这个产品,它不是定制的,它是兼容 K8s 的,只要用户熟悉 K8s,就可以使用 ACS。它完全符合 K8s 的 API 和容器化的社区标准。所以从这个角度来讲,我们希望客户在理解云计算时可以从 K8s 出发,这是他们需要改变的地方。不需要改变的是他们使用容器和 K8s 的方式。</p><p>我们对客户的应用架构是无感的,是无侵入的,不会有厂商绑定和定制化问题,所以我觉得这是一个很好的解耦点。</p><h4>问题 8:混合云也是目前的一个趋势,那么 ACS 的出现对未来部署混合云也是一个利好吗?</h4><p>丁宇:是的。今天我们在混合云、专有云以及公共云的联通上取得了巨大进步,K8s 是最好的联通方式。今天 ACK 已经与这几个场景结合起来,我们相信未来 ACS 也可以与这些场景相结合,让企业应用无缝从 IDC 到专有云、混合云,再到公共云迁移,全部使用一套 K8s 标准,实现应用层的无感迁移。</p><h4>问题 9:刚才谈了 ACS 对云计算的影响,那您认为 ACS 将来会对整个行业带来哪些改变?</h4><p>丁宇:无论是哪家云服务提供商,面临的客户需求都是相同的——大家都追求更便捷、更经济、全托管、免运维以及高性价比的服务。考虑到容器和 K8s 流行的趋势,所有供应商面临的挑战也是一致的。阿里云率先推出了 ACS 这样的产品,实现了容器与资源的一体化,这意味着容器成为了云计算的一等公民。我相信这将带来巨大的行业变化,因为需求和趋势明确地摆在那里,我也相信许多同行将提供类似的产品。</p><h4>问题 10:您认为容器与资源一体化将成为一个趋势,也将成为未来云计算厂商的一个标配吗?</h4><p>丁宇:是的,我相信这将成为趋势,并最终成为云计算服务提供商的一个标准配置。随着云服务越来越向简化和标准化发展,这样的产品将更能满足市场需求,并为用户提供更加便捷和高效的解决方案。</p><h4>问题 11:Serverless 等概念逐渐成为业界共识,您认为未来的技术趋势将会如何发展?</h4><p>丁宇:我们服务了众多客户,并且做了大量的开源工作,与开发者和客户的紧密合作让我们洞察到一些趋势。从云计算、云原生、Serverless 这几个方向来看看,未来有几件事情是可以预见的。首先,客户的用云界面将持续上移,因为所有客户对技术红利的追求是不变的。这个过程中可以采用多种方式,例如,应用、大数据、人工智能运行在云上,甚至开发过程和开发方式也将转移到云端,这也是一大趋势。</p><p>对于云计算,我们一直在推进 Serverless 的加速和演进。我们相信,云产品的最终形态是 Serverless 化,使用云的终极方式也是 Serverless 化,云原生的未来同样也在 Serverless 化上。</p><h4>问题 12:如果说 Serverless 化是未来的趋势,那阿里云对基于 Serverless 的生态有哪些扶持计划吗?</h4><p>丁宇:首先,阿里云产品正在向 Serverless 化演进,并已提供相应的版本。另外,容器是一个极佳的切入点,它是承载生态产品进入阿里云的良好载体。</p><p>如果部署和构建方式、云交互方式千差万别,建设一个可扩展的生态体系将非常困难。因此,除了云市场,我们还将在容器市场上努力构建与整个生态软件的集成对接。</p><p>我们欣喜地看到,今天很多的 ISV、很多的 toB 技术创业公司,他们都是从 K8s 开始构建其技术栈。所以从这个角度来看,这与 ACS、容器的市场将有很好的结合点。我们将从云市场、生态体系以及容器应用市场这几个方向加强生态体系的构建。</p><h4>问题 13:您经常跟客户打交道,能否分享一下他们当前对 Serverless 技术的看法和态度?</h4><p>丁宇:事实上,大部分客户对 Serverless 的方向和技术演进趋势持肯定态度,并认可它带来的价值。我们注意到,客户们面临的挑战主要是让他们的团队为重大的架构升级做好准备,以及他们的IT系统架构是否能够支撑这样深刻的变革。</p><p>因为 Serverless 属于下一代企业架构,而目前有些企业还停留在传统架构中。当然有些企业已经迁移到互联网分布式微服务架构,有些创新型企业已经采用了 Serverless 架构。总的来说,尽管企业处于不同的发展阶段,但对 Serverless 趋势和价值的认可是一个普遍现象。</p><p>但是有些企业面临改革的难题,例如迁移成本过高。为了解决这一问题,我们提供了像 SAE (Serverless 应用引擎)这样的产品,它可以让企业应用无需改造即可迁移到云上,只需将其打包成容器镜像即可。这样,企业就无需更改现有的技术栈和开发语言,从而消除了他们的顾虑。</p><p>此外,企业通常担心 PaaS 层会导致厂商绑定问题。K8s是开源的,因此我们将 Serverless 应用托管平台进行开源以解决这一问题。总体来看,Serverless 的趋势非常乐观,受到行业客户的广泛认可。</p><blockquote><strong>点击链接,即可体验容器计算服务 ACS:<a href="https://link.segmentfault.com/?enc=4S665xoRlFOq6x5czc5erA%3D%3D.R%2BnhPEgd%2FXdfvaTflcY71wKkRDrSe4feghld348cO1u5rB3d%2FCKB2BSxAORpry4K" rel="nofollow">https://www.aliyun.com/product/acs</a></strong></blockquote><p><strong><a href="https://link.segmentfault.com/?enc=jQwl70vli9MR4PKVleynxw%3D%3D.3UsfPwSKyI9b%2FtxsUTbasvmbl8moHJeBFxnuyKGn31zidbl3xx5sRFJwLap4%2BvYrlNjCBSRN7U5M%2BSTarCbEZX%2B%2FaGVT1YwOBXCrDjcR8%2BQ%3D" rel="nofollow">原文链接</a></strong></p><p><strong>本文为阿里云原创内容,未经允许不得转载。</strong></p>
Sentinel 新版本发布,提升配置灵活性以及可观测配套
https://segmentfault.com/a/1190000044620347
2024-02-05T10:26:50+08:00
2024-02-05T10:26:50+08:00
阿里云云栖号
https://segmentfault.com/u/aliyunqi
0
<h2>基本介绍</h2><p>Sentinel 是阿里巴巴集团开源的,面向分布式、多语言异构化服务架构的流量治理组件,承接了阿里巴巴近 15 年的双十一大促流量的核心场景,例如秒杀、冷启动、消息削峰填谷、集群流量控制、实时熔断下游不可用服务等,是保障微服务高可用的利器。开源以来也被众多企业广泛应用于生产实践。</p><p><img src="/img/remote/1460000044620349" alt="图片" title="图片"></p><p>在功能上主要以流量为切入点,从流量路由、流量控制、流量整形、熔断降级、系统自适应过载保护、热点流量防护等多个维度来帮助开发者保障微服务的稳定性。同时 Sentinel 将会在未来的 2.0 系列版本中,进一步支持流量路由、流量染色与标透传、异常流量调度、预热调权等能力。在生态对接以及使用方式上也会更加贴近云原生。由流量防护升级为流量治理与自愈,扩大场景边界,从原来的只覆盖运行时稳定性,增加了变更态稳定性治理,覆盖服务全生命周期的稳定性,为业界提供统一的流量治理能力与标准化的治理方式。</p><h2>版本预览</h2><p>近期 Sentinel 1.8.7 正式发布,该版本基于 1.8.6 新增了多项特性和改进。主要新特性及改进如下:</p><ul><li>支持按照正则匹配资源名称,便于批量配置规则</li><li>流量指标支持对接 Prometheus</li><li>支持默认熔断规则</li><li>重构 RateLimitController:提高准确性并支持 maxQps 阈值大于 1000</li></ul><p>详情请参考 Release Notes[1]。感谢为该版本付出的所有贡献者:@sczyh30, @wuwen5, @xiaozzzi, @EzrealOf, @wilsonwu, @kirklin, @garroshh, @JosephZhang3, @LiYangSir, @Yan1025, @wenshao, @pandaapo, @frank-zsy, @z521598, @LearningGp, @robberphex, @clara0, @karl-sy, @SaaiVenkat。</p><h2>新特性介绍</h2><h3>资源名称支持正则匹配</h3><p>Sentinel 一直以来支持资源名称的规则配置,但在实际的生产时间中,会存在对某一组的接口进行批量配置的需求,因此在 1.8.7 版本中,我们引入了资源名称支持正则匹配的新特性来支持更加灵活的资源匹配,提高配置效率。</p><p>下面是一个简单的示例(代码详见 sentinel-demo-basic 的 FlowQpsRegexDemo 类),首先我们构建正则匹配的流控规则。</p><pre><code>//匹配以 /A/ 为前缀的资源名
private static final String KEY = "/A/.*";
private static void initFlowQpsRule() {
List<FlowRule> rules = new ArrayList<FlowRule>();
FlowRule rule1 = new FlowRule();
rule1.setResource(KEY);
// set limit qps to 20
rule1.setCount(20);
rule1.setGrade(RuleConstant.FLOW_GRADE_QPS);
rule1.setRegex(true);
rule1.setLimitApp("default");
rules.add(rule1);
FlowRuleManager.loadRules(rules);
}</code></pre><p>然后我们对 /A/a , /A/c,/B/a 三种资源分别发起请求,从输出中随机截取一部分可以看到 /A/a 资源以及 /A/c 资源匹配正则表达式,因此限流规则生效 pass qps 为 20,而 /B/a 资源由于不匹配正则表达式 pass qps 等于 total qps,符合预期,功能生效。</p><pre><code>90 /A/a send qps is: 375
1703753361846, total:375, pass:20, block:355
90 /A/c send qps is: 370
1703753361846, total:370, pass:20, block:350
90 /B/a send qps is: 383
1703753361846, total:383, pass:383, block:0
89 /A/a send qps is: 366
1703753362850, total:366, pass:20, block:346
89 /A/c send qps is: 392
1703753362850, total:392, pass:20, block:372
89 /B/a send qps is: 357
1703753362850, total:357, pass:357, block:0</code></pre><h3>流量指标对接 Prometheus</h3><p>在之前的版本中,Sentinel 的指标只能够通过日志或是控制台查看,但是存在诸多弊端,因此在 1.8.7 版本中我们对接了 Prometheus 这一云原生时代下流行的可观测组件,通过扩展的方式将指标暴露给 Prometheus。</p><p>下面是一个简单的示例(详见 sentinel-prometheus-metric-exporter 的 README.md 文件 )。</p><ol><li>引入 Sentinel 插件</li></ol><pre><code><dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-prometheus-metric-exporter</artifactId>
<version>1.8.7</version>
</dependency></code></pre><ol start="2"><li>引入 Prometheus 依赖</li></ol><pre><code><dependency>
<groupId>io.prometheus</groupId>
<artifactId>simpleclient</artifactId>
<version>0.3.0</version>
</dependency>
<dependency>
<groupId>io.prometheus</groupId>
<artifactId>simpleclient_httpserver</artifactId>
<version>0.3.0</version>
</dependency></code></pre><ol start="3"><li>在 Prometheus 端 prometheus.yml 中增加采集配置</li></ol><pre><code>scrape_configs:
- job_name: 'sentinelMetrics'
static_configs:
- targets: ['localhost:9092']
# Note: the port needs to be the same as the value in the configuration (csp.sentinel.prometheus.fetch.port)
</code></pre><p>最终的效果如下:</p><p><img src="/img/remote/1460000044620350" alt="图片" title="图片"></p><h2>社区未来规划</h2><p>在将来的一段时间内,1.8.x 系列和 2.0 系列将保持并行演进,欢迎社区积极参与到新版本的建设中。</p><h3>1.8.x 后续计划</h3><p>1.8.x 版本自发布以来,持续深耕流量防护领域,后续还会在流量防护领域保持持续演进,并对一些基础结构、机制以及模型进行优化和重构,在提供更加完善的流量防护能力的同时,向 Sentinel 2.0 版本平稳过渡。</p><h3>2.0 计划</h3><p>Sentinel 2.0 品牌由流量防护升级为流量治理与自愈,扩大场景边界,为业界提供统一的流量治理能力与标准化的治理方式,同时更加贴近云原生。Sentinel 2.0 新的能力包括但不限于:流量路由、流量染色与标透传、异常流量调度、预热调权等,从原来的只覆盖运行时稳定性,增加了变更态稳定性治理,覆盖服务全生命周期的稳定性,为业界提供统一的流量治理能力与标准化的治理方式。</p><p><strong>相关链接:</strong></p><p>[1] Release Notes</p><p><a href="https://link.segmentfault.com/?enc=78DiCIcFGmM6kX81LzhrpQ%3D%3D.qbWYam%2Bk91tXHyCex9xbP2KW2dILXIV8RXTRYZHzh6gMHbzl%2BuDMV2rtUJoEL5lpuqwBzxSoQudAGumy5YHYOg%3D%3D" rel="nofollow">https://github.com/alibaba/Sentinel/releases/tag/1.8.7</a></p><p>作者:屿山</p><p><strong><a href="https://link.segmentfault.com/?enc=%2BIvW%2BPfccNXlEZ5hwEZI%2FQ%3D%3D.bFPpo9UL%2FxJY8DxiDYo8rWLB%2F9J5RarZQUPodBXFl2wxeEGfd%2BRsbs%2Fb%2BHeycZ0f10Z31btTUHNNB2BOhFdwsngWE%2BtF07Iuj0mMvC9NnPQ%3D" rel="nofollow">原文链接</a></strong></p><p><strong>本文为阿里云原创内容,未经允许不得转载。</strong></p>
成本更低、更可控,云原生可观测新计费模式正式上线
https://segmentfault.com/a/1190000044617822
2024-02-04T16:02:47+08:00
2024-02-04T16:02:47+08:00
阿里云云栖号
https://segmentfault.com/u/aliyunqi
0
<p>在上云开始使用云产品过程中,企业一定遇见过两件“讨厌”事:</p><ul><li>难以理解的复杂计费逻辑,时常冒出“这也能收费”的感叹;</li><li>某个配置参数调节之后,云产品使用成本不可预估的暴涨。</li></ul><p>可观测作为企业 IT 运维必须品,在应对不同可观测场景时提供了非常多产品,以及与之对应的计费模式,供企业灵活选择。但如果产品价格说明不完整且不能有效评估现有业务规模及增长趋势,就会给企业带来非常高的成本规划与选型评估门槛。为解决上述问题,云原生可观测推出「按写入数据量」计费模式,降低不同可观测产品间的计费认知差距,以便更好的理解与管理可观测成本。并提供每月累计 150GB 免费额度(多产品独立额度叠加),进一步压降建设可观测成本。</p><h2>01 什么是按写入数据量计费</h2><p>写入数据量是指通过 ARMS 自研探针、开源探针/SDK、云服务、开源 Exporter 上报到 ARMS 云原生可观测平台,经过清洗、聚合、转化、分析等计算处理后存储的数据量,并具备以下优势:</p><ul><li>更低可观测成本<br>同样数据规模下,单位价格下调 70%,部分规格存储时长延长 50%,整体成本更低;</li><li>成本支出更可控仅需考虑业务及对应的数据规模,无需担忧增值服务带来的额外成本;</li><li>评估模型更简单相较旧计费模式下诸多计费项,新计费模型更简单易懂,无需理解特定语境下计算单位定义及计费项间关联关系。</li></ul><h2>02 按写入数据量计费的适用场景</h2><h3>(1)针对 Java 应用的性能监控及链路追踪</h3><p>ARMS 应用监控:针对分布式、微服务化 Java 应用,提供代码级实时性能监测与全链路分析能力。覆盖云服务器 ECS、Serverless 应用引擎 SAE、容器服务 ACK 等不同应用部署环境,配合丰富的场景分析与全链路明细数据分析功能,随时掌握应用运行状态,梳理服务依赖关系,及时解决性能瓶颈与故障,提高产品可用性。</p><p><img src="/img/remote/1460000044617824" alt="图片" title="图片"></p><h3>(2)针对 PHP、Node.js、.NET 等多语言应用的性能监控及链路追踪</h3><p>可观测链路 OpenTelemetry 版:针对 PHP、C++、Go、Node.js 等多语言应用,提供端到端全链路追踪、应用监控与告警、链路拓扑、日志关联分析能力。并基于 OpenTelemetry 开源标准,兼容 Jaeger、Zipkin、SkyWalking 等开源项目数据上报。快速发现性能瓶颈,缩短错/慢调用根因定位耗时,提高全栈开发与诊断效率。</p><p><img src="/img/remote/1460000044617825" alt="图片" title="图片"></p><h3>(3)针对云服务、应用组件、容器、基础设施的指标监控</h3><p>可观测监控 Prometheus 版:针对业务自定义监控 / 应用组件监控 / 云服务监控 / 容器监控 / 系统监控等场景,提供指标监控与告警能力。并兼容 Prometheus 开源生态,提供一站式指标观测与告警平台,免去日常运维成本。</p><p><img src="/img/remote/1460000044617826" alt="图片" title="图片"></p><h2>03 按写入数据量计费详解</h2><h3>(1)ARMS 应用监控</h3><p>应用监控新计费模式屏蔽原有基础版、专家版的 Agent * Hour、链路数据存储、指标数据存储等计费项,不再以功能区分计费,以实际写入数据量(GB)进行计费。除了常见的链路、指标数据之外,增加剖析数据。剖析数据指使用 CPU & 内存诊断、应用诊断功能时产生的文件数据,包含内存快照、性能分析火焰图、线程分析的线程状态和调用栈信息数据。</p><p><img src="/img/remote/1460000044617827" alt="图片" title="图片"></p><p>新计费模式单价 & 免费额度:</p><p><img src="/img/remote/1460000044617828" alt="图片" title="图片"></p><p>计算器:<a href="https://link.segmentfault.com/?enc=4otOB%2Bw6r2X3Vr1ll1DLYg%3D%3D.191iUZDL4TVf5QKj%2Bhh4Ior60LkzUStxZAaTHelXoVqrM4ONcowwHKbYZGX88TmbvtBwBlxgz%2B452Mn%2BvROSAQ%3D%3D" rel="nofollow">https://armsnext.console.aliyun.com/price-gb#/overview</a></p><h4>老用户如何基于新计费模式进行成本预估</h4><p><strong>1)基本条件</strong></p><p>1 个 ARMS Java 探针可监测 1 个应用实例(如 1 个 Tomcat 实例,1 个 Java 进程),在标准使用模式下(采样率 10%,接口级别指标开启收敛,不开启在线剖析,24 小时全时使用),每天产生数据约 2GB。</p><p>注:不同使用模式下存在一定数据量差异,实际使用时请关注。</p><p><strong>2)新老对比</strong></p><p>以中小企业通常规模 50 个节点举例。</p><ul><li>新计费(按量付费)每月成本:50 <em> 2GB </em> 0.4(元/GB)* 30(天)= 1200元</li><li>旧计费(按量付费)每月成本:50 <em> 0.28(元/Agent</em>Hour) <em> 30(天) </em> 24(Hour)= 10080元</li></ul><p>对比两种计费方式,新计费节省 88% 以上。</p><h3>(2)可观测链路 OpenTelemetry 版</h3><p>可观测链路 OpenTelemetry 版新计费模式屏蔽原有上报、链路数据存储、指标数据存储等计费项,以实际写入数据量(GB)进行计费。除了常见的链路、指标数据之外,增加剖析数据。剖析数据指使用 CPU & 内存诊断、应用诊断功能时产生的文件数据,包含内存快照、性能分析火焰图、线程分析的线程状态和调用栈信息数据。</p><p>同时,可观测链路 OpenTelemetry 版针对默认生成的性能统计指标免费,而用户自定义生成的指标则根据写入数据量收取费用,共享可观测链路 OpenTelemetry 版每月 50GB 免费额度。</p><p><img src="/img/remote/1460000044617829" alt="图片" title="图片"></p><p>新计费模式单价 & 免费额度:</p><p><img src="/img/remote/1460000044617830" alt="图片" title="图片"></p><p>计算器:<a href="https://link.segmentfault.com/?enc=75vf9UMzWPoige5l6v0QHA%3D%3D.y9%2F4qPkwvq66bOkPZwX4gmSz732f63CgwJWVGhVmcXihuD3bw%2FSdEIAj9a0OO6wlWdFhrooWyI2jCGwQam50Xg%3D%3D" rel="nofollow">https://armsnext.console.aliyun.com/price-gb#/overview</a></p><h4>老用户如何基于新计费模式进行成本预估</h4><p><strong>1)基本条件</strong></p><p>1 个 Span 约 1.27KB;</p><p>注:不同使用模式下存在一定数据量差异,实际使用时请关注。</p><p><strong>2)新老对比</strong></p><p>以中小企业通常规模 1000 万请求(请求复杂度:平均 10 个 Span),链路数据保存 30 天、指标保存 90 天举例。</p><ul><li>新计费(按量付费)每月成本:100000000 <em> 0.00000121 GB </em> 0.4(元/GB)* 30(天)= 1453 元</li><li>旧计费(按量付费)每月上报成本:100(100 个百万 Span)<em> 0.09(百万 Span 上报单价)</em> 30(天)= 270元</li><li>每月链路存储成本:100(100 个百万 Span)<em> 0.02(每天百万 Span 存储单价)</em> 30(存 30天)* 30(天) = 1800元</li><li>每月指标存储成本:10(10 个百万指标)<em> 0.01(每天百万指标单价)</em> 90(存 90 天)* 30(天)= 270元</li><li>总计成本:270 + 1800 + 270 = 2340元</li></ul><p>对比两种计费方式,新计费节省 33% 以上。</p><h3>(3)可观测监控 Prometheus 版</h3><p>可观测监控 Prometheus 版新计费模式屏蔽原有上报指标采样点数量、存储时长等计费项,以实际写入数据量(GB)进行计费。</p><p><img src="/img/remote/1460000044617831" alt="图片" title="图片"></p><p>新计费模式单价 & 免费额度:</p><p><img width="677" height="71" src="/img/bVdbnip" alt="image.png" title="image.png"></p><p>Prometheus 包含基础指标、自定义指标。其中,基础指标以容器服务产生的基础指标举例,默认存储 7 天且免费,不占用 50GB 免费额度。自定义指标以云服务器 ECS 实例举例,每日上报指标量 24.5 万/实例,每日数据写入量约 0.093GB/实例。</p><p>计算器:<a href="https://link.segmentfault.com/?enc=bU%2BrhWvqJ1FZjdkvEDEtYA%3D%3D.VcJhhVwsh0gIpaH0xUkGoJOb3cCAodfpn3uYuUT0jzh%2FTAjZZVIIdehBTsxI5mm5RBt9MMwVsP2QYdsJ3%2FP%2BFg%3D%3D" rel="nofollow">https://armsnext.console.aliyun.com/price-gb#/overview</a></p><h4>老用户如何基于新计费模式进行成本预估</h4><p><strong>1)基本条件</strong></p><p>1 条上报指标约 0.5KB;</p><p>注:不同使用模式下存在一定数据量差异,实际使用时请关注。</p><p><strong>2)新老对比</strong></p><p>以中小企业通常每日上报自定义指标 15000 万条 ,数据保存 30 天举例。</p><ul><li>新计费(按量付费)每月成本:150000000(条) <em> 0.00000048 (GB/条) </em> 0.4(元/GB)* 30(天)= 864 元</li><li>旧计费(按量付费)阶梯一部分:50000000 条 <em> 0.0000008(元/条)</em> 30(天)= 1200元</li><li>阶梯二部分:100000000 条 <em> 0.00000065(元/条)</em> 30(天)= 1950元</li><li>总计成本:1200 + 1950 = 3150元</li></ul><p>对比两种计费方式,新计费节省 70% 以上。</p><h2>04 如何开通写入数据量计费</h2><h3>新用户</h3><p>新用户仅需根据自己的业务需求,在应用实时监控服务 ARMS、可观测监控 Prometheus 版、可观测链路 OpenTelemetry 版产品详情页,分别选择「立即开通(每月 50GB 免费额度)」进行开通即可,如下图:</p><p><img src="/img/remote/1460000044617832" alt="图片" title="图片"></p><ul><li>应用实时监控服务 ARMS:<a href="https://link.segmentfault.com/?enc=c1OS45%2B3uqFXxkaTYG2KFg%3D%3D.7xR6A42RkrEH6pp%2BFnQJnVwWMkaXBj9XMc%2FHosAW%2BEuXg%2FcexGFj8I%2Fe262NAu0o" rel="nofollow">https://www.aliyun.com/product/arms</a></li><li>可观测监控 OpenTelemetry 版:<a href="https://link.segmentfault.com/?enc=UQnTLsIC%2BY%2BX3mbXkKnFSw%3D%3D.c28Apu%2FmXw86Dkiyi3evGtO8z1j4YcYsNNWA%2BvZGYb6KAeF0QRjiq1l1q3LzGpAZ" rel="nofollow">https://www.aliyun.com/product/xtrace</a></li><li>可观测监控 Prometheus 版:<a href="https://link.segmentfault.com/?enc=THNTNe1UR2k1LpmAcOW8sQ%3D%3D.mAzbP2vs3T1IGoW28uaBwujdzqAPp5VZymeMzW7133zO7PsJIy8LUVkv%2BgRGhAaE%2BZibY41nUPY3MM%2FXSCJOsQ%3D%3D" rel="nofollow">https://www.aliyun.com/product/developerservices/prometheus</a></li></ul><h3>老用户</h3><p>老用户仅需登陆应用实时监控服务 ARMS 或相应产品产品控制台,在概览页右侧「产品计费状态」模块选择需要转变为新计费的产品即可。(近期上线,敬请期待)</p><h2>05 按写入数据量计费的小 Tips</h2><ul><li>如何获得免费额度:开通新计费即可获得并在每日计费时自动进行抵扣。</li><li>免费额度的使用:免费额度是按照阿里云账号级别计算,即该账号下子产品的不同应用/实例共享免费额度。</li><li>存储时长:写入数据后各种数据类型享受不同天数免费存储权益,存储天数暂不支持修改。</li><li>最小写入数据量:针对 ARMS 应用监控/可观测链路 OpenTelemetry 版,每个应用每个计费数据类型最小计量单位为 0.1GB/天,未使用则不产生计量。例如某应用一天的指标用量 20MB、链路用量 10MB、剖析用量 0MB,计费按照该应用指标用量 0.1GB、链路用量 0.1GB、剖析用量 0GB 出账。</li></ul><p>阿里云可观测全新推出的按写入数据量计费模式,彻底解决过往极易超出成本的计费项开通、难以理解的不同计费项定义与关系等问题。让众多可观测产品更具性价比,帮助企业成本更可控、场景更轻松的进行拓展。</p><p><strong><a href="https://link.segmentfault.com/?enc=O68vF6xEYC7YpckFpn8m7g%3D%3D.CfNnwwmCC9V7IHTTBhDhfj9IaG3EKJN7V7TXNDNItmilckSpgfDzVeLi1UpBzPU2rVmOMypTBGKkhZweVN9nsVRFMTHhjlU%2F%2F3F27Jf%2Bi3A%3D" rel="nofollow">原文链接</a></strong></p><p><strong>本文为阿里云原创内容,未经允许不得转载。</strong></p>
进击的 Serverless:Java 应用如何从容地面对突增流量
https://segmentfault.com/a/1190000044611290
2024-02-02T09:55:11+08:00
2024-02-02T09:55:11+08:00
阿里云云栖号
https://segmentfault.com/u/aliyunqi
0
<p>让我们从一个十分常见的业务场景说起。</p><p>移动互联网时代,许许多多的业务都有着流量的周期性变化,无论是直播、游戏、点单系统、电商平台等等,都会存在着流量的高峰与波谷。如果采用固定的计算资源部署服务,使用的多了,大量资源在流量波谷闲置浪费,使用的少了,服务难以抗住高峰期的大规模流量,易带来业务损耗。</p><p>尤其在大促或节日期间,难以预估具体需要的计算资源数量,同时不论水平还是垂直扩容,人工操作成本都十分高昂。容器技术在某种程度上解决了这类问题,K8s 原生的 HPA 可以根据应用的 CPU、Mem 等指标进行灵活弹性,无需手动扩容,但是使用 K8s 容器化需要付出大量的学习和维护成本,这会极大地侵占运维团队的精力。</p><p><img src="/img/remote/1460000044611299" alt="图片" title="图片"></p><p>许多企业都面临着这样的问题。Serverless 产品因此而走进大众的视野。提到简单,低负担,大家都会想到 Serverless,它的本质就是希望开发者不再需要去处理 Server 运维的复杂性。它能够让用户无需使用和运维 K8s 等容器技术,同时又能享受到容器技术带来的技术红利,解放人力。</p><h2>非弹性场景</h2><p>下图是我使用镜像部署的 demo web 应用,想动手实践体验下的同学可以参考本文后边附加的实践教程。这里我使用阿里云的压测工具 PTS 模拟流量波峰的场景,在不使用弹性能力的场景下,可以看到,随着流量的递增,服务器难以顶住流量的压力,调用的成功率大幅降低,RT 在 5000ms(timeout 阈值)左右徘徊,线上业务产生了很大的损失。</p><p><img src="/img/remote/1460000044611300" alt="图片" title="图片"></p><h2>加一点弹性?</h2><p>在 SAE 控制台可以一键开启弹性能力,无需任何修改和 K8s 运维,同时,除了 K8s 原生支持的 CPU、Mem 指标外,SAE 支持还多种指标弹性,包括 QPS、RT、TCP 连接数等,还支持定时弹性策略和混合弹性策略,下图是开启指标弹性策略后的压测结果,可以看到,在同样的,短暂的延迟之后,请求的成功率接近百分百,延迟也降至几十毫秒,业务几乎没有收到影响,相比于未开启弹性能力时,有极大的改善。</p><p><img src="/img/remote/1460000044611302" alt="图片" title="图片"></p><p>对于非 Java 应用而言,这里已经足够应对绝大多数的场景了,然而针对 Java 应用,又有特殊的地方。众所周知,Java 应用启动相对较慢,从开始创建容器,到服务完全 ready,这需要消耗大量的时间,在流量短时间内大幅度上升的情况下,这段真空时间可能也会导致线上业务的损失,那么如何解决这个问题呢?</p><h2>流量防护解决突发流量风险</h2><p>每个系统和服务都有其能够容纳的上限,但是流量的变化是不确定的。有时候前一秒还很平稳,但后一秒可能会出现大量的流量,就像双十一零点的场景一样。如果突然来的流量超过了系统的承受能力,即使我们配置了弹性能力,由于 Java 应用冷启动过程时间过长的问题,即使我们立即扩容,请求仍然处理不过来。因为扩容来不及,新的 Pod 无法启动并分配新的流量,而堆积的请求会持续增加且处理速度缓慢,老的 Pod 由于请求过多导致 CPU/Load 飙升,最终导致整个系统崩溃。因此,在这个过程中,我们需要针对这种突发的流量来进行限制,在尽可能处理请求的同时来保障服务不被打垮,这就是流量防护。</p><p><img src="/img/remote/1460000044611303" alt="图片" title="图片"></p><p>为了应对多余的请求,我们需要使用流量防护能力来限制这些请求,以避免系统被压垮。经过我们的调研,我们发现 MSE 流量防护可以满足我们的需求。MSE 流量防护基于毫秒级滑动窗口精确统计以及令牌桶、漏桶等流量控制算法,可以提供多种维度的流量控制场景,包括秒级精准流控和匀速排队等。这样,我们就可以通过 MSE 流量防护来限制多余的请求,确保系统的正常运行。</p><p><img src="/img/remote/1460000044611304" alt="图片" title="图片"></p><p>我们集成了 MSE 的流量防护能力,对于 SAE 的用户来说,通常在 Web 入口或服务提供方(Service Provider)的场景下,我们需要根据服务提供方的服务能力进行流量控制。我们可以结合前期压测评估核心接口的承受能力,配置流控规则,当每秒的请求量超过设定的阈值时,会自动拒绝多余的请求。从而保护服务提供方自身不被突然出现的过多的流量给打垮。</p><h2>无损上线确保应用完全预热</h2><p>在压力测试过程中,我们还发现了 Java 应用普遍存在的一个问题,即冷启动过程中容量过小的问题。当微服务应用刚启动后,由于 JIT 预热和框架资源的懒加载等情况,应用的容量会比正常情况下小得多。特别是对于 Java 应用来说,这个问题会更加明显。如果我们在这个时候不进行任何预处理,应用直接接收线上均分下来的大量流量,很容易导致大量请求响应缓慢、资源阻塞甚至应用实例宕机的问题。</p><p>在大流量下,服务竟然扩容不出来,新启动的 Pod 很快就被大流量打垮,导致 Liveness 检查失败引起 Pod 重启。在这个阶段我们需要一种手段保证新启动的 Pod 可以平稳地度过冷启动阶段。</p><p>此时,预热一词蹦入我们脑海;在这阶段我们需要通过小流量预热的方式让系统充分进行预热,合理分配少量的流量启到充分预热我们系统的作用,确保新的 Pod 完全启动后再接受生产中均分下来的大流量。</p><p><img src="/img/remote/1460000044611305" alt="图片" title="图片"></p><p>SAE 默认集成了 MSE 无损上下线,我们需要在无损上线页面开启无损上线开关,并配置预热时长;然后我们重启应用后,我们就可以看到上线 Pod 的流量曲线如上图所示,缓慢增长,符合小流量预热曲线。</p><h2>Java 应用难道启动就要很长时间?</h2><p>我们通过实验发现,Java 应用在扩容的过程中需要预热、启动过慢,因此很大程度上限制了 Serverless 的能力,难道 Java 应用启动就应该很慢吗?最近在社区中出现了另外的一些声音。</p><p><img src="/img/remote/1460000044611306" alt="图片" title="图片"></p><p>$$
图片来自:https://shipilev.net/talks/j1-Oct2011-21682-benchmarking.pdf
$$</p><p>一个 Java 程序的执行生命周期如下图所示,分为 JVM 初始化、应用程序初始化、应用预热、应用稳定执行和关闭 5 个部分:在这个过程中我们可以看到 Java 应用的局限性,Java 在运行基于 JVM 之上,因此Java程序启动过程中需要进行 JVM 的初始化与启动。</p><p>Java 静态编译在这个过程中相比于传统基于 JVM 的 Java 应用程序运行方式,采用静态编译技术能给 Java 应用程序带来如下优势:</p><ul><li>消除冷启动:没有了程序解释执行、虚拟机初始化等步骤,冷启动问题得到大幅度改善。</li><li>内存占用率大幅降低:静态编译做了大量优化,并且没有了虚拟机运行时内存占用,内存占用得到大幅降低。</li></ul><p><img src="/img/remote/1460000044611307" alt="图片" title="图片"></p><p>$$
右图来自:https://learn.lianglianglee.com/
$$</p><p>GraalVM 为 Java 应用提供 AOT 编译和二进制打包能力,基于 GraalVM 打出的二进制包可以实现快速启动、具有超高性能、无需预热时间、同时需要非常少的资源消耗。可以很好地解决 Java 应用启动慢的问题。</p><p>Spring Cloud Alibaba 社区基于 GraalVM 技术的最新版本 Spring Cloud Alibaba 应用使用 Nacos 进行服务注册与消费/配置订阅的启动速度提升了近 10 倍、内存占用率降低为原来 1/3。同时,我们也在 SAE 上验证基于 GraalVM 技术对 Java 应用启动的效果,Java 应用启动时长从 3s 优化至 300ms,极大满足了 Serverless 极致弹性的诉求。可以说 GraalVM 技术为 Java 在 Serverless 场景下带来了新的变革与机遇。</p><h2>无损下线确保流量低峰缩容过程平滑</h2><p>当流量高峰过去后,我们弹性扩容出来的服务也会随着流量的下降而缩容,从而确保最高的资源利用率,这也是Serverless 弹性所带来的红利。但是我们在实践的过程中发现,开源微服务在缩容的过程中流量并不能做到平滑,在Pod销毁的过程中依旧有流量在持续访问下线中的服务,从而引起业务问题。</p><p><img src="/img/remote/1460000044611308" alt="图片" title="图片"></p><p>如上图左侧所示,只有到客户端感知到服务端下线并且使用最新的地址列表进行路由与负载均衡时,请求才不会被负载均衡至下线的节点上。那么在节点开始下线的开始到请求不再被打到下线的节点上的这段时间内,业务请求都有可能出现问题,这段时间我们可以称之为服务调用报错期。</p><p>想象一下,在大流量的场景下,如果服务调用报错期持续数秒至数十秒,我们的业务会有多少请求出现错误?也正因为这个原因,我们碰到许多客户,扩容出来后就不敢缩容。MSE 无损下线可以有效解决微服务下线过程中的流量损失问题,MSE 通过提前注销、主动通知等策略,保证每一次微服务下线过程中,尽可能缩短服务调用报错期,同时确保待下线节点处理完任何发往该节点的请求之后再下线。对于 SAE 的应用来说,我们只需要开启微服务治理的无损下线能力,无需额外操作即可实现平滑缩容的效果。</p><h2>进击的 Serverless</h2><p>提到简单,低负担,相信大家都会想到 Serverless,它的本质就是希望开发者不再需要去处理 Server 运维的复杂性,当然 Server 并没有消失,而是交给了云平台,这也就是 Less 的部分。</p><p>经过这么多年的发展,Serverless 也在不断地演进,"Less"的范围在不断扩大,不仅仅包含 Server 部分,还有 0 改造、可观测、弹性、应用托管、微服务、CI/CD 等等各个方面。结合我们前面的微服务架构下复杂性讨论,Serverless 其实是微服务架构下降低复杂度,减少维护成本的最好的一个解决方案之一。</p><h2>完整的 Serverless 微服务解决方案:SAE</h2><p>在阿里云最新的 Serverless 体系中,已经不局限仅仅关注“Server”部分,而是围绕应用整体需要,开发或者融合各种 PaaS 能力,真正对开发者做到“将复杂留给平台,简单留给客户”。以下为阿里云 SAE 产品作为例:</p><p><img src="/img/remote/1460000044611309" alt="图片" title="图片"></p><p>首先是第一部分,SAE 给用户提供了一个白屏化的界面,极大的降低用户的使用门槛,甚至可以说 0 门槛,它的交互符合大多数开发者心中 PaaS 的心智,同时,它提供了大量的开发者工具和 SaaS 服务的集成,如 Cloudtoolkit 插件、云效流水线、镜像仓库、jar/war 代码包部署、OpenAPI 等等。同时也有很多企业级特性,比如命名空间隔离,细粒度的权限控制、事件告警中心等等,这些能帮助企业解决许多需要面对的实实在在的问题,实现微服务无缝迁移,0 代码改造,开箱即用。</p><p>第二部分,在微服务能力上,SAE 通过集成 MSE,在平台侧注入 MSE 探针,整体上实现了一个无侵入,业务无感的解决方案,提供了丰富的微服务治理能力,包括无损上下线,灰度发布、流量防护等等。</p><p><img src="/img/remote/1460000044611310" alt="图片" title="图片"></p><p>第三部分,在微服务架构下,应用数量较多,定位问题困难,可观测就需要具备非常高的要求,SAE 结合阿里云的 ARMS、云监控、SLS、Prometheus 等产品,在 Metrices、Tracing、Logging 等方面都提供了相对完整的解决方案,切实解决开发者在可观测方面的痛点,包括基础监控、调用链、实时日志、事件等等。</p><p>第四部分,SAE 让开发者不仅不需要运维 IaaS,也不需要运维 K8s,免去了 K8s 高昂的学习、试错、运维成本,同时又可以利用 K8s 的各种能力,包括健康检查、弹性。在此基础上,SAE 又实现了比原生 K8s 更强劲的能力。以弹性为例,除了 K8s 原生支持的 CPU、Mem 指标外,SAE 支持还多种指标弹性,如 QPS、RT、TCP 连接数等,还支持定时弹性策略和混合弹性策略,满足应用在不同环境下按需启停,实现 15s 的端到端快速扩容,应对突发流量。</p><p>提到云原生,大家都会想到容器、微服务、不可变基础设施等等技术,但是我们回到为什么会出现云原生,本质也是希望能借助云原生相关的技术构建出“容错性好、易于管理和便于观察的松耦合系统”,所以它也是为了降低复杂性和门槛。相信微服务和 Serverless PaaS 结合的解决方案是实现这个目标的最佳手段之一。</p><p>Serverless 的概念已经出现很久,并且持续走热,在 Serverless 场景下,我们的 Java 应用如何更优雅地处理突增的流量呢?通过本文的实践,我们可以看到 Java 应用在流量洪峰到来之前,如何安全平滑地进行防护、扩容和预热,以及在流量峰值过去后如何无损地缩容。这样我们可以充分享受 Serverless 架构带来的成本、稳定等方面的红利,Serverless 让业务更关注于业务本身。</p><h2>如何一键使用无损上下线/流量防护能力</h2><p>前文已经介绍了无损上下线与流量治理,相信许多技术从业者已经迫不及待想体验对应的能力了。那么是否有方法可以为应用一键开启这两种微服务治理能力?实际上,之前 SAE 通过集成 MSE,已经提供了公测版本的无损上下线功能。最近,随着 SAE 2.0 商业化版本的发布,SAE 更为深入地集成了 MSE,提供了更完整的治理能力,更简洁的配置方式,和更清晰的交互逻辑,下面来为大家介绍一下,如何在 SAE 控制台为部署好的应用开启无损上下线和微服务治理。</p><p>前提条件:已创建微服务应用,可参考链接文档[1]</p><p>创建完成后,在应用详情页可以统一在微服务治理菜单下管理相关功能,开启无损上下线需要用户开通 MSE 专业版或企业版,开启限流降级需要开通 MSE 企业版。点击开通链接完成开通操作后,可以点击开启按钮,期间会自动触发一次应用重启,完成后,可跳转至对应功能页,微服务治理能力即接入应用中。</p><p><img src="/img/remote/1460000044611312" alt="图片" title="图片"></p><p>针对无损上线功能,有两个重要参数需要进行配置,一个是预热时长,用来设置应用实例下一次启动的预热时间。避免前文提到的,在较大流量下,刚启动的冷系统因应用内部资源初始化不彻底,在直接处理大量请求时出现请求阻塞、报错等问题。取值范围为[0,86400],即最大取值为 24 小时,默认为 120 秒。</p><p>另一个是延迟注册时间,用来设置服务注册的延迟时间,从而避免应用还未完全初始化就已经被注册到注册中心供外部消费者调用,导致请求报错。取值范围为[0,3600],即最大取值为 1 小时,默认为 0 秒。</p><p>在高级设置中,可以设置在就绪检查前完成服务注册或服务预热,系统会默认为应用业务就绪检查(Readiness 配置)路径为 /health,端口为 54199,原有就绪检查可能会被覆盖。详细功能介绍可以参考无损上下线文档[2]。针对无损下线,点击开启主动通知功能后,应用在收到下线请求时,会主动通知消费方,避免下线过程中消费方继续访问即将下线的应用实例。</p><p><img src="/img/remote/1460000044611313" alt="图片" title="图片"></p><p><strong>相关链接:</strong></p><p>[1] 链接文档</p><p><a href="https://link.segmentfault.com/?enc=5ECGFgWEKWBRY8oERYqcmQ%3D%3D.%2FOxQaJmSo8mht0fC%2BKtSBI7KRarIc9HgY1Xd9UEMUurxNhrSVAwdoPROgsX%2Bhq3ycUu4%2Bv2lZT2iP%2B0rAiFiDZ%2FZidi5QYEFZf0rVI43p4jPtNB6TvFAoQJq45%2F2aK8LAArcBwbQoau%2FvaiAPVmyVw%3D%3D" rel="nofollow">https://help.aliyun.com/zh/sae/user-guide/application-managem...</a></p><p>[2] 无损上下线文档</p><p><a href="https://link.segmentfault.com/?enc=WCG42D5SfAEv9PFIH6OMSQ%3D%3D.EjajkqCa6Dy1CDzUlGAr8MyVzJZLqTQnIUErS%2Fiw3%2BqGbAGx0G0TN%2BcyYezZVX%2BbqM1jvKg%2FB4p1BiYpCEfeGCJEys1x84lXhNHMJmLkWJI5XPAEqjLvwLD5Aunvm%2F4pPF1leu1AAS3Dnuk%2Fvd8SqQ%3D%3D" rel="nofollow">https://help.aliyun.com/zh/sae/user-guide/configure-graceful-...</a></p><p>作者: 袭周、十眠</p><p><strong><a href="https://link.segmentfault.com/?enc=%2FCXYLP5Ax42JjY4IXy9kbA%3D%3D.Nfa%2F%2F2D4lMlRSloICPprIGxfEFZUPA%2F8O6cMHf0caP8NhE7w4rOEmbzWAp%2BxsHlN5Q4XUc%2BuwmmPt5unyYCNmiOhII4fsih0wVHSmjYvJLc%3D" rel="nofollow">原文链接</a></strong></p><p><strong>本文为阿里云原创内容,未经允许不得转载。</strong></p>
走出大模型部署新手村!小明这样用魔搭×函数计算
https://segmentfault.com/a/1190000044609736
2024-02-01T17:08:50+08:00
2024-02-01T17:08:50+08:00
阿里云云栖号
https://segmentfault.com/u/aliyunqi
0
<p>前文介绍了魔搭 ModelScope 社区模型服务 SwingDeploy 服务。开发者可以将模型从魔搭社区的模型库一键部署至阿里云函数计算,当选择模型并部署时,系统会选择对应的机器配置。按需使用可以在根据工作负载动态的减少资源,节约机器使用成本。5 分钟完成从开源模型至模型推理 API 服务的生产转换……好,优势前文已经介绍过了。</p><p>那么,到底怎么应该怎么开始使用,本文将带小明(纯纯的小白)走出新手村,体验魔搭社区的一键部署服务(SwingDeploy[1]),对小明的种种疑惑进行解答。开始!</p><p><img src="/img/remote/1460000044609738" alt="图片" title="图片"></p><h2>小明如何在魔搭社区一键部署开源模型?</h2><p>魔搭开源社区当前只有热门开源模型支持一键部署(可支持部署的模型列表紧密扩充中),小明可以在模型库列表页面,过滤支持快速部署的 SwingDeploy 的模型列表,然后点击进模型详情页,其中模型详情页的右上角包含有部署按钮,可以进行快速部署(SwingDeploy)。</p><p><img src="/img/remote/1460000044609739" alt="图片" title="图片"></p><p>模型列表页:过滤支持模型部署的模型列表。</p><p><img src="/img/remote/1460000044609740" alt="图片" title="图片"></p><p>模型详情页:右上快速部署。</p><p>另外,小明可以切换至首页,通过左侧【模型服务】进入模型部署服务(SwingDeploy)页面。</p><p><img src="/img/remote/1460000044609742" alt="图片" title="图片"></p><p>在新建快速部署(SwingDeploy)后,小明可以针对模型部署信息进行配置,包括必要的部署模型版本、部署地域、部署卡型、部署显存等。</p><p><img src="/img/remote/1460000044609743" alt="图片" title="图片"></p><p>当小明点击确认快速配置无误后,通过点击【一键部署】按钮,从而进入部署过程;整个过程一般持续 1-5 分钟,当部署完成后,可以看到服务状态切换为【部署成功】。</p><p><img src="/img/remote/1460000044609744" alt="图片" title="图片"></p><h2>小明在魔搭一键部署模型到 FC 后,实际在 FC 部署了什么?</h2><p>当小明将魔搭开源模型一键部署(SwingDeploy)到阿里云函数计算 FC 后,实际上是在阿里云函数计算 FC 平台创建了对应的服务与函数;服务和函数是阿里云函数计算资源模型中的一级概念:</p><p>1.服务:</p><ul><li>一个服务中可以包含多个函数。</li><li>在服务级别上可以配置日志采集、网络通道、存储扩展等,服务中的所有函数继承服务中的这些配置。</li></ul><p>2.函数:</p><ul><li>函数是调度与运行的基本单位,是平台用户业务逻辑的所在,其中指明了代码/容器镜像,配置了 CPU/内存/显存/GPU 的运行规格等。</li></ul><p>函数计算平台在收到该函数的推理请求调用后,会根据服务和函数的配置来创建对应的 CPU/GPU 容器实例。函数实例处理完请求后,再由平台将响应返回给用户。对应的 CPU/GPU 容器实例空闲一段时间没有处理调用请求后,函数计算平台会将其释放。所以默认情况下,空闲未使用的服务/函数没有资源消耗,函数计算仅对请求处理部分计费。</p><p>使用魔搭的“模型服务” SwingDeploy 一键部署模型到函数计算后,可以在部署列表中看到“服务名称”,使用服务名称可以到函数计算控制台[2]相应地域的服务列表找到部署好的服务和函数。</p><p><img src="/img/remote/1460000044609745" alt="图片" title="图片"></p><p>在函数计算控制台的服务与函数页面,搜索指定的服务。</p><p><img src="/img/remote/1460000044609746" alt="图片" title="图片"></p><p>用户通过魔搭一键部署模型后,在函数计算会对应生成的一个服务与其下的两个函数:</p><ul><li>model_download_func 作用:用于部署阶段将魔搭模型下载至用户 NAS 内。</li><li>model_app_func作用:基于 Flask + 魔搭模型的推理 API,具体源码可见链接[3]。</li></ul><p><img src="/img/remote/1460000044609747" alt="图片" title="图片"></p><h2>小明如何调用部署在 FC 的模型?</h2><p>函数的调用是事件驱动的,我们定义一组规则,事件源产生的事件若匹配这些规则,就会触发函数的调用执行。这些规则的定义在函数计算中由“触发器”[4]承载。具体到魔搭一键部署的函数,我们默认为其配置了一个 HTTP 触发器,若有相应的 HTTP 请求发生,即会触发函数的调用,详见函数计算平台 HTTP 触发器的使用文档[5]。</p><p>小明可以通过魔搭平台提供的示例代码调用已部署好的模型。</p><p><img src="/img/remote/1460000044609748" alt="图片" title="图片"></p><p>魔搭示例代码中 API_URL 中的 HTTP URL,就是函数计算为每个魔搭模型函数配置的 HTTP 触发器。可以通过 FC 控制台,找到对应的魔搭服务下的 model_app_func 函数,通过查看函数详情页的“触发器管理”选项卡,查看更为详细的触发器信息。</p><p><img src="/img/remote/1460000044609749" alt="图片" title="图片"></p><h2>小明发现部署在 FC 的模型首次调用耗时长,后续调用耗时短,如何调优</h2><p>如上所说,函数如果长时间空闲(没有调用发生),平台会通过回收函数实例来释放资源。函数计算平台在收到一个调用请求后,会判断当前是否有空闲的函数实例可供使用,如果没有,则需要新创建一个函数实例来服务该请求,这个过程称之为冷启动。</p><p>如果函数实例初始化时间耗时较长,那么服务该实例上发生的初次调用的时延也会增加,例如,初始化较大的模型文件(ChatGLM-6B 模型文件 15GB)。</p><p>为了应对上述场景,函数实例按照弹性规则,可以分为按量和预留两种模式。上述根据请求量弹出的实例我们称为按量实例。与之对应的,可以为函数配置弹性规则,增加预留模式[6]的实例。预留实例由函数计算平台预先创建,属于常驻资源,可用于平缓突发请求产生的时延毛刺。</p><p>FC 按量模式与预留模式的差异:</p><blockquote>FC 按量模式为通过请求自动触发实例的创建,首次发起调用时,需要等待实例冷启动。如果您希望消除冷启动延时的影响,可以通过配置 FC 预留模式来解决。<br>FC 预留模式是将函数实例的分配和释放交由您管理,当配置预留函数实例后,预留的函数实例将会常驻,直到您主动将其释放。</blockquote><p>在控制台中,可以在函数详情的“弹性管理”选项卡配置弹性规则。如下图示例,最小实例数即预留实例数,最大实例数与最小实例数之差即按量实例数的上限(避免弹出资源太多,控制成本上限)。弹性管理的配置方法详见文档[7]</p><p>例如:可以通过如下操作指导,预留指定数量的 GPU 实例(测试目的:一般建议预留 1 个 GPU 实例)。</p><p><img src="/img/remote/1460000044609750" alt="图片" title="图片"></p><ul><li>切换至函数的弹性管理 Tab 页</li></ul><p><img src="/img/remote/1460000044609751" alt="图片" title="图片"></p><ul><li>设置函数的 LATEST 版本,至少预留 1 个 GPU 实例</li></ul><p><img src="/img/remote/1460000044609752" alt="图片" title="图片"></p><ul><li>查看当前预留实例数量,是否满足目标预留实例数量。(上图表明完成指定数量的 GPU 实例预留)</li><li>当预留实例就绪后,推理请求调用会被优先分配至该预留实例上执行,从而规避按量场景下的冷启动。</li><li>小明可以通过请求级别的日志观测,来查看请求是由按量实例服务、还是预留实例服务。</li></ul><p><img src="/img/remote/1460000044609753" alt="图片" title="图片"></p><p><img src="/img/remote/1460000044609754" alt="图片" title="图片"></p><p><img src="/img/remote/1460000044609755" alt="图片" title="图片"></p><ul><li>通过删除弹性规则,可以删除对应预留实例。</li><li>注意:预留实例的生命周期,完全由小明全权负责。</li></ul><h2>小明想实现类似 MidJourney 异步调用效果,应该如何做呢?</h2><p>类似于 StableDiffusion 的 AIGC 生图场景,Midjourney 提供了非常好的异步队列效果,基于函数计算如何实现呢?函数计算同时提供同步调用、异步调用、异步任务三种处理能力。</p><p>1.同步调用:</p><ul><li>当您同步调用一个函数时,事件将直接触发函数,函数计算会运行该函数并等待响应。当函数调用完成后,函数计算会将执行结果直接返回给您,例如返回结果、执行摘要和日志输出。</li><li>详细文档:链接[8]。</li></ul><p>2.异步调用:</p><ul><li>函数计算系统接收异步调用请求后,将请求持久化后会立即返回响应,而不是等待请求执行完成后再返回。函数计算保证请求至少执行一次。</li><li>详细文档:链接[9]。</li></ul><p>3.异步任务:</p><ul><li>当您对函数发起异步调用时,相关请求会被持久化保存到函数计算内部队列中,然后被可靠地处理。如果您想追踪并保存异步调用各个阶段的状态,实现更丰富的任务控制和可观测能力,可以选择开启任务模式处理异步请求。</li><li>详细文档:链接[10]。</li></ul><p><img src="/img/remote/1460000044609756" alt="图片" title="图片"></p><p>当函数计算的异步调用能力与 GPU 相较合时(详细文档:链接[11]),小明可以很轻松的实现 AIGC 异步排队处理的良好用户体验。</p><h2>小明发现模型/应用有问题,如何定位?</h2><h3>a. 可观测:配置 SLS 日志</h3><p>SLS 是阿里云提供的日志类数据一站式服务。我们可以通过在函数对应的服务中配置 SLS 日志项目和日志库,函数实例执行过程中的输出就可以记录到配置的日志库中。之后可以通过函数计算控制台、 SLS 的控制台都可以对这些内容进行查看。</p><p>函数计算服务配置日志的详细内容,请见文档[12]。以下给出简要步骤。</p><ol><li>在服务配置中确认日志功能已启用。</li></ol><p><img src="/img/remote/1460000044609757" alt="图片" title="图片"></p><ol start="2"><li>在函数详情中,“调用日志”选项卡查看函数维度的日志、请求维度的日志、容器实例维度的日志。</li></ol><p><img src="/img/remote/1460000044609758" alt="图片" title="图片"></p><p><img src="/img/remote/1460000044609759" alt="图片" title="图片"></p><h3>b. 可观测:如何查看监控</h3><p>函数计算平台记录了多个层次的监控指标,我们可以通过控制台进行查询。</p><p>一方面,我们可以通过控制台左侧“高级功能”、“监控大盘”进入,在大盘页面下方依次选择服务名称、函数名称,查看不同层次的监控汇总信息。有关监控指标详细信息请见文档[13]。</p><p><img src="/img/remote/1460000044609760" alt="图片" title="图片"></p><p>另一方面,我们可以在函数详情“监控指标”选项卡中,直接对函数自身相关的指标进行查看。</p><p><img src="/img/remote/1460000044609761" alt="图片" title="图片"></p><p>最后,我们可以在函数详情“调用日志”选项卡中,查看函数运行的相关日志。</p><p><img src="/img/remote/1460000044609762" alt="图片" title="图片"></p><h3>c. 可观测:如何命令行调试</h3><p>我们也可以通过函数计算控制台函数详情的“实例列表”选项卡,使用“登录实例”功能进入到函数实例里面,通过直接的交互对执行环境、函数行为进行调试。</p><p><img src="/img/remote/1460000044609763" alt="图片" title="图片"></p><p>如果当前“实例列表”为空,可以通过测试调用触发函数计算平台新弹出一个实例。</p><p><img src="/img/remote/1460000044609764" alt="图片" title="图片"></p><p>登陆 GPU 实例后,小明就可以执行相关的 shell 命令了#</p><p>Tips:需要注意的是,登录实例的过程中,函数实例处于活跃状态,和调用函数采用相同的计量规则。为避免忘记关闭会话而意外产生费用,通过控制台进行命令行操作时,会话默认会在空闲 10 分钟之后断开连接。如有需要,可以通过执行例如 top 来进行保活。</p><h2>小明想让模型跑在不同的 CPU/GPU 上,在 FC 上应如何设置呢?</h2><p>如果我们通过监控指标发现函数实例的资源使用较为饱和或者空闲,可以在“函数配置”选项卡上,对函数的资源规格进行配置,包括 CPU/磁盘/内存/显存等。</p><p>特别地,对于 GPU 函数,我们可以通过切换 GPU 卡型,还提升单个函数实例最大可配置的显存大小(T4 最大 16GB,A10 最大 24GB)。关于 GPU 函数的更多信息,可见文档[14]。</p><ol><li>查看函数当前配置</li></ol><p><img src="/img/remote/1460000044609765" alt="图片" title="图片"></p><ol start="2"><li>编辑函数基础信息</li></ol><p><img src="/img/remote/1460000044609766" alt="图片" title="图片"></p><h2>小明调优后的模型可以批量推理,在 FC 上应该如何设置呢?</h2><p>函数计算平台在收到一个推理调用请求后,会判断现有函数容器实例的并发度是否够用,决定是否将该推理调用请求转发给现有函数容器实例来处理,还是新弹出一个函数容器实例处理该请求。</p><p>单个函数容器实例同时能处理的调用请求数为函数实例的并发度[15]。如果应用本身能够同时处理多个请求,相比默认的 1 并发度,可以减少函数的冷启动次数。建议根据不同应用场景的需要,选择不同的并发度配置。</p><ul><li>计算密集型的推理应用:建议 GPU 函数实例的并发度保持默认值 1。</li><li>支持请求批量聚合的推理应用:建议 GPU 函数实例的并发度根据能同时聚合的推理请求数量进行设置,以便批量推理。</li></ul><p>我们可以在编辑函数的“基础信息”过程中,调整函数实例的并发度。</p><p><img src="/img/remote/1460000044609767" alt="图片" title="图片"></p><p>特别地,对于 GPU 函数,默认情况下,无论 Tesla 系列 T4 卡型、还是 Ampere 系列 A10 卡型的 GPU 实例,单个阿里云账号地域级别的 GPU 物理卡上限为 10 卡(示例请见文档[16])。</p><p>函数计算 FC小明完成了函数计算新手村课程,对小明还有其他嘱咐嘛?</p><ul><li>GPU 实例 FAQ[17]</li><li>GPU 函数镜像使用说明[18]</li><li>GPU 应用场景使用说明[19]</li></ul><p><strong>相关链接:</strong></p><p>[1] SwingDeploy</p><p><a href="https://link.segmentfault.com/?enc=bDCjrNd4%2FZo6%2B92yxUN7EA%3D%3D.TViPB%2FopRxrrAnTvH1m4jFszTwCSZYz8mB78lmP4owPjBrACNHZo1Iy88p3dOQLgrslCk%2FwhG21a00LRuDEYRlQDOmYUJtenk901aC76w2gMPu2K1P%2BHXvdMdhQAdgiOQ4CC%2BbbtOmvXSXs1MaJPoQ%3D%3D" rel="nofollow">https://www.modelscope.cn/docs/%E9%83%A8%E7%BD%B2FC?spm=a2c6h...</a></p><p>[2] 函数计算控制台</p><p><a href="https://link.segmentfault.com/?enc=b%2FOtLChaB%2FK5EGaZbtuUnQ%3D%3D.z6KQ6cw4OV4zrc3kM7LiV%2Fb0XG2ecAQzh21wftTFCn6RVJIZtbiKTujt8xbxPKmxRM%2BBMjr59WV6BBsbGNoX5Mt9jv8DEX%2F5y6ph%2B6RGTAqF26BmnHuiH1oUmoudeC2udHdmGyCK6MuCSbmBMIe9AiFSLyohezs%2FiWKtUgV%2FOuLSyRVI%2F0FNPThM35LqcjDLZ39FxztMJxBG9QR%2BACc4p4wSAZbezdSfdC6Xn%2FK2fB8%3D" rel="nofollow">https://account.aliyun.com/login/login.htm?oauth_callback=htt...</a></p><p>[3] 链接</p><p><a href="https://link.segmentfault.com/?enc=0DT7%2FXjDj4Dr%2BGo6Vf7jSw%3D%3D.RaXHJ5wfs8ZAk5et54wV8mdLzvsjnl1KgDC1C6R8M3NrsqjeG%2F8jP%2BfAYHMV2DtZp4qjGMfqQHlqzGonb1KOHg%3D%3D" rel="nofollow">https://www.devsapp.cn/details.html?name=start-modelscope</a></p><p>[4] 触发器</p><p><a href="https://link.segmentfault.com/?enc=Sl4A4MV2TMPRgYZ0z3IPUw%3D%3D.yM%2BTK89MZNgOXnliQIkevYFli3ushuKVkuAhXNM9YnPAbvJVmRa98KuxwuK7l%2BoX" rel="nofollow">https://help.aliyun.com/zh/fc/trigger-overview</a></p><p>[5] 使用文档</p><p><a href="https://link.segmentfault.com/?enc=WDJN2Wep2t%2BY4oyjaTskVQ%3D%3D.aBdRSTwJ4JoBiaEqzxCeHLPSFIpabJ2SgePPaag5Iw0Ax9tAYKYVUDa4WVwjWp1NnUiGqQmFLUL1%2B4U7IZRHx%2F4QeKiTj2ynyEb9ZsNJi9eR6dyhfQhhDWtOia9pOnvtrIFceTA5rx4M41MQVK3LvA%3D%3D" rel="nofollow">https://help.aliyun.com/zh/fc/configure-an-http-trigger-that-...</a></p><p>[6] 预留模式</p><p><a href="https://link.segmentfault.com/?enc=VLew4k5vid9g%2FK3SHZGOZw%3D%3D.x0u7gMxGWp3CEh2HPwc18NNzDQUVWcCFUb3%2FR%2FMxaKlaXjmjqreXakakLL9Gt7LxBK7iQKrFS%2BOD8NPCdkoSzmXf8RigxKw5qE3hYXQlDn4rR3E9OQBAkuGdfmp5eCGH7Yrld%2BUGlra57cISmS9gHg%3D%3D" rel="nofollow">https://help.aliyun.com/zh/fc/configure-provisioned-instances...</a></p><p>[7] 文档</p><p><a href="https://link.segmentfault.com/?enc=kLNVEC7QrozCO3COPZLAAw%3D%3D.fmYCp9rvzyKP9aEZZn41zMIfXGeKudt5TsnQwv1kJ8kridfZ8e11BZuEanW8N61B%2FI78YC3uRVLJrGEfaYaqSr14RKuTjSwA1hfI59BwAeIiJO%2FyP6XHNFgbnCfwtM%2FRj%2FCT34Z3IkvXq5w5dhQQOw%3D%3D" rel="nofollow">https://help.aliyun.com/zh/fc/configure-provisioned-instances...</a></p><p>[8] 链接</p><p><a href="https://link.segmentfault.com/?enc=rQA83tSY2CnpFWKDvwJD2A%3D%3D.3ToUi%2FbLxJAbBazaaVqS6rvlDy4jv7H4BJJuKXqvTf2mJtRLPlpMMwgP%2BPkqE%2FqpxEwaquyHNgTTAp0SLe3vxKeYxITk1cJ3rAtLsBFnDzw%3D" rel="nofollow">https://help.aliyun.com/zh/fc/user-guide/synchronous-invocations</a></p><p>[9] 链接</p><p><a href="https://link.segmentfault.com/?enc=lB1acROmO77IolFgLpkemw%3D%3D.rFsCrJhH4Xm0iY1afe%2F6SjDdhxVhbzuLpX%2FJPFJ6lUl6jLgKXCnzPcloXzBiTLcDld6s7lrQQjLP45kI4%2FPTTQ%3D%3D" rel="nofollow">https://help.aliyun.com/zh/fc/user-guide/overview-34</a></p><p>[10] 链接</p><p><a href="https://link.segmentfault.com/?enc=OoLe2CGEU%2Fz2nJTFOUB6%2Bg%3D%3D.BDvnQFHqjA5pXbXqFGncqNDP6qUTrMJYQql2daixrHsC2m6rt5FmOjP0zht7SDGY" rel="nofollow">https://help.aliyun.com/zh/fc/overview-25</a></p><p>[11] 链接</p><p><a href="https://link.segmentfault.com/?enc=BtNGmrjG9VgN%2B3eBGbMBJg%3D%3D.iBnHkCen58T6qLFN6Bi9FfSvivffxYjMxrVFOh8r64Nrd%2B%2FdxlkBEC2JLnyXqmkmZYJfMHf4Y9VcuLjcL14iVOpdpBHi%2FZvGitMlgymoqCM%3D" rel="nofollow">https://help.aliyun.com/zh/fc/use-cases/offline-asynchronous-...</a></p><p>[12] 文档</p><p><a href="https://link.segmentfault.com/?enc=v9PybAGQsSZivNld1Oh1UQ%3D%3D.ODXwcdnpJPF27v33C8USWAR3lXcmX6K0B58lDtP8yv9RVzoN2ne8kopddrc%2BBpPD89Rfy%2B1pB6DvMySHSb%2BLWaLuUw96Rt%2FL6rXiMn%2BcUC0%3D" rel="nofollow">https://help.aliyun.com/zh/fc/user-guide/configure-the-loggin...</a></p><p>[13] 文档</p><p><a href="https://link.segmentfault.com/?enc=3yUUHLqJAeHXjfs4fPE8MQ%3D%3D.%2FseMPIasCMMj7cjPniyhHqWEPSWjR4YUl%2FG7vtEW00Zvw9QoU2twhUIej2afIay80FwkW2hDuHzj0YdgAKctd1auH8e370dVdvlPHYgRYtE%3D" rel="nofollow">https://help.aliyun.com/zh/fc/user-guide/configure-the-loggin...</a></p><p>[14] 文档</p><p><a href="https://link.segmentfault.com/?enc=vogQZjV8qovQRPjYfCBTug%3D%3D.sS2o61wExkGHs2Q14G6hYBbUPvBtapYVs39mvvysyBu4samOqXZqHASkLEIAUB0Qh6qMoSkdT99%2BoBzFkXnZ1ZSri2%2F7h3b6oIC%2BNAQGVk8%3D" rel="nofollow">https://help.aliyun.com/zh/fc/use-cases/introduction-to-serve...</a></p><p>[15] 函数实例的并发度</p><p><a href="https://link.segmentfault.com/?enc=K2GnpGadzrRTIHFmIGW8QA%3D%3D.pk8OwFU6FqD3Qi006Gz9RPhEX%2FY1W1WlSM9X6Qs9piOJ3HwgjIaWaPe84Bryjef34C5ixc%2BLydqo7VNmoutcoA%3D%3D" rel="nofollow">https://help.aliyun.com/zh/fc/configure-instance-concurrency</a></p><p>[16] 文档</p><p><a href="https://link.segmentfault.com/?enc=s6Dmp6SbkRKXBjKVd9TCMg%3D%3D.TiwrHWmdqo5yYtfMhUJXB%2BNodVgvv1LWMlBEt6DaC7xuBHpZT5vI1YhZi%2FRRxSDAikqIHx9Hdx2eWzjvvNBaSd5Ghdg%2FcpKQE4HGMHGh%2FQh98k28UQruYN1AKh7lFcWY" rel="nofollow">https://help.aliyun.com/zh/fc/use-cases/quasi-real-time-infer...</a></p><p>[17] GPU 实例 FAQ</p><p><a href="https://link.segmentfault.com/?enc=VOxZ7eeRbHPy%2BkkJjSOVOQ%3D%3D.waSt6DQSrVNb7MrIoYwqAaColRySwEw0VKxaFgZsKWaZfXz5wQgLqcdkiSPxRdBtgZxs%2FN4i%2Fw0LuKHFgfTd4X8c2nVysPosl1SP5zTlOdg%3D" rel="nofollow">https://help.aliyun.com/zh/fc/support/faq-about-gpu-accelerat...</a></p><p>[18] GPU 函数镜像使用说明</p><p><a href="https://link.segmentfault.com/?enc=HFFUqwWM5RbNlRLEmQGj0Q%3D%3D.JP6h3M3lZxmIeHwbrNWzwREFSnOnDV0rjcHRHdBlCPnlA%2BP72%2Bf5yLJ7k8GgPF3Rn%2FYxyddUCB5ivDG0sCeiHQ%3D%3D" rel="nofollow">https://help.aliyun.com/zh/fc/use-cases/image-usage-notes</a></p><p>[19] GPU 应用场景使用说明</p><p><a href="https://link.segmentfault.com/?enc=aR5dyUvyKBgeBvPOmB7Lfg%3D%3D.rk5fJ7g9sXaqqcKBZnuAsX%2BQL6QUCk8K6C0HtD%2FYT%2Bn9u8y48eMwuhojhnf2ugegPVhLauwZ6vETdWXRmtGAvA%3D%3D" rel="nofollow">https://help.aliyun.com/zh/fc/use-cases/scenarios/</a></p><p>作者:拓山</p><p><strong><a href="https://link.segmentfault.com/?enc=OuZQ4RNOZS9kFO7zwRpgvw%3D%3D.D02nBe3nhFt875HGXALozyYyjzhtWXQXhzu1UJM11XP6piAOKOLrYNM7zsx4Dc2BJuTsNprDuPdGSkWYWzRmoh%2FfYtOiKmcQOLzQYu5HEYM%3D" rel="nofollow">原文链接</a></strong></p><p><strong>本文为阿里云原创内容,未经允许不得转载。</strong></p>
基于 Megatron-Core 的稀疏大模型训练工具:阿里云MoE 大模型最佳实践
https://segmentfault.com/a/1190000044606335
2024-01-31T16:28:53+08:00
2024-01-31T16:28:53+08:00
阿里云云栖号
https://segmentfault.com/u/aliyunqi
0
<h2>概述</h2><p>随着大模型技术的不断发展,模型结构和参数量级快速演化。大模型技术的应用层出不穷。大模型展现惊人效果,但训练和推理成本高,一直是巨大挑战。模型稀疏化能降低计算和存储消耗。近期以Mixtral为代表的MoE(多专家混合)大模型证明了稀疏MoE技术能大幅降低计算量、提升推理速度,模型效果甚至超过同规模稠密模型。阿里云PAI和NVIDIA团队深入合作,基于Megatron-Core MoE框架,解决了MoE大模型训练落地时会遇到的可拓展性、易用性、功能性以及收敛精度等核心问题,在下游任务上取得了很好的模型效果。PAI团队将上述MoE训练框架和技术与阿里云AI平台产品深度整合,使云上大模型用户能方便地进行MoE大模型的训练和部署。</p><h2>基于 Megatron-Core 的 MoE 训练工具链</h2><p>这一章节中,我们从MoE算法介绍,Megatron-Core MoE训练框架、以及云平台工具三个方面了解支撑MoE落地背后的基础能力。</p><h3>MoE 算法介绍</h3><p>MoE的全称是Mixture of Experts,其中的Expert对应的是Transfomrer模型的MLP层,在训练的时候从多个MLP中选取一个MLP进行激活 [1](如下图所示)。这意味着模型可以在不增加FLOPs的情况下,通过增加MLP模块的数量来增加模型参数量级,进而提升模型在下游任务上的效果。采用MoE后的稀疏Transformer模型和同等质量(验证集loss以及Zero-shot NLU下游任务性能)的稠密模型相比有较大幅度的训练和推理吞吐性能提升。MoE主要由以下两个关键部分组成:</p><ul><li>稀疏MoE层: 这些层代替了传统 Transformer模型中的前馈网络 (FFN) 层。MoE层包含若干experts组成,每个experts本身是一个独立的神经网络。在实际应用中这些专家通常是前馈网络 (FFN)。</li><li>Router路由: 这个部分用于决定哪些tokens被发送到哪个专家。例如在下图中,“More”这个tokens可能被发送到第二个专家,而“Parameters”这个tokens被发送到第一个专家。</li></ul><p><img src="/img/remote/1460000044606337" alt="图片" title="图片"></p><p>接着我们讨论下MoE中的token负载均衡问题。如上图所示的Top-1 Routing算法,每个输入hidden_states被router分配了4个experts中的1个用于前向推理计算,然后其输出被加权求和汇总后送入Transformer的下一个处理单元。这种路由方式会出现少数受欢迎的experts需要处理很多token,而其他experts仅需处理极少数量的token的情况,这导致处理极少token的那些experts无法获得足够多的信息,从而导致训练效率大幅降低。</p><p>为了缓解这种token到expert负载不均衡(Load Imbalancing)的问题,可以引入了一个辅助损失函数,旨在鼓励给予所有专家相同的重要性。这个损失函数确保所有专家接收到大致相等数量的训练样本,从而平衡了专家之间的选择。另外也可以通过drop tokens的方式得到缓解。首先定义一个expert capacity,即为一个expert被分配到的token的容量。如果分配到一个expert的token数超出了一个固定容量,则多余的tokens会被丢掉。这些被丢掉的tokens不参与和experts的矩阵乘运算,直接通过一个残差连接进入到下一个处理单元。如果一个expert没有被分配到其容量上限内的足够多的tokens,则需要采用padding的方式填充到容量上限。</p><p>Mixtral-8x7b模型提供了另外一种思路来缓解负载不均衡的问题,其采用的Megablocks [2]论文中提出的dropless moe算法。如下图所示,首先tokens通过router被分配到具体的experts,token到expert的分配关系被存储到expert indices中,分配置信度被存储到Probabilities中。其次根据预先设置好的expert的容量将tokens分组放置,超出容量的tokens被丢掉。接着将分组中的tokens和experts进行批量矩阵乘运算。最后输出结果按照分配置信度进行加权求和(如下左边公式),其分配置信度的计算采用的是normalized softmax(如下右边公式)。</p><p><img src="/img/remote/1460000044606339" alt="图片" title="图片"></p><p><img src="/img/remote/1460000044606340" alt="图片" title="图片"></p><p><img src="/img/remote/1460000044606341" alt="图片" title="图片"></p><p>Megablock论文认为这个drop token方案会导致效果下降,于是在此基础上引入块稀疏算子来实现dropless功能。如下图所示,dropable的moe算法在experts之间并行批量矩阵乘(如下图A所示)可以用一种块对角矩阵乘来等价表达(如下图B所示)。Megablock设计了一个新的算子允许变长的输入(如下图C所示),然后输出到一个稀疏对角矩阵上。引入了这个变长输入就意味着不需要drop的方式就能处理超出容量的tokens。类似的,Megatron-Core MoE使用GroupedGEMM解决了多 expert变长输入的问题。</p><p><img src="/img/remote/1460000044606342" alt="图片" title="图片"></p><h3>Megatron-Core MoE 训练框架</h3><p>Megatron-Core是NVIDIA推出的一个成熟且轻量级的大规模LLM训练框架,它包含了训练大规模LLM模型所需的所有关键技术,例如各类模型并行的支持、算子优化、通信优化、显存优化以及FP8低精度训练等。Megatron-Core不仅继承了前代Megatron-LM的优秀特性,还在代码质量、稳定性、功能丰富性和测试覆盖率上进行了全面提升。更重要的是,Megatron-Core在设计上更加解耦和模块化,不仅提高了LLM训练的效率和稳定性,也为二次开发和探索新的LLM架构提供了更大的灵活性。</p><p>基于Megatron-Core,研究人员可以在大规模集群上高效地训练各种大型LLM模型,其中也包括对 MoE 模型的探索。MoE的建模方式也带来了参数量的急剧上升、MoE层复杂的通信逻辑、Routing等额外的开销,都给训练框架带来了不小的挑战。其中首当其冲的就是如何在多个GPU间高效的拓展MoE 训练。</p><p>在最新发布的Megatron-Core v0.5中,Megatron-Core正式推出了对大规模MoE模型训练的支持,也就是Megatron-Core MoE,涵盖了并行性、路由和负载均衡、性能优化、Token分发机制等多个feature。以下是一些值得关注的特性:</p><h4>并行性(Parallelism)</h4><p>Megatron-Core MoE支持专家并行(Expert Parallel),这是一种专门为MoE模型设计的并行方法。在这种并行化策略中,不同的 Rank 负责处理其中一个或多个专家的计算。</p><p>此外,Megatron-Core MoE还支持3D并行(Data Parallel, Tensor Parallel, Pipeline Parallel, Sequence Parallel)。对于更大的MoE模型, Megatron-Core MoE也支持将专家并行(EP)与其它的并行DP/TP/PP/SP/Distributed Optimizer结合使用。</p><p>未来,Megatron-Core MoE还将支持Context Parallel,以支持更长序列的训练。</p><h4>Token 分发机制(Token Dispatch Mechanism)</h4><p>Megatron-Core MoE目前提供了对Dropless MoE的支持(不进行Token丢弃)。即将加入对Token drop MoE的支持。</p><h4>路由和负载均衡(Router and Load Balancing)</h4><p>Megatron-Core MoE提供了多种路由类型,包括通用的Top-K router和即将推出的Expert Choice router。</p><p>在负载均衡算法方面,支持Sinkhorn(S-BASE)、Z-Loss,以及Load balancing Loss。</p><h4>Grouped GEMM</h4><p>Megatron-Core MoE开发了GroupedGEMM来解决多Experts变长输入这一问题。当每个Rank有多个专家时,Megatron-Core MoE利用自CUTLASS 2.8引入的Grouped GEMM特性,将多个局部(可能是较小的)GEMM操作合并为单个GroupedGEMM kernel,能够大幅度提高SM利用率和性能。</p><p>同时,Megatron-Core MoE还将部分效率较低的操作替换为优化后的CUDA Kernel,如Sinkhorn、local token permutation/unpermutation等。</p><h4>即将推出的功能与优化</h4><p>近期将发布的部分新特性包括:</p><ul><li>上下文并行(Context Parallel)</li><li>FP8低精度训练</li><li>FP8 Grouped GEMM</li><li>Token-Drop MoE</li></ul><p>通过这些特性,Megatron-Core MoE为用户提供了一个强大的MoE训练框架,以在大规模集群上高效地训练和探索大型MoE模型。随着更多功能的推出,我们期待Megatron-Core MoE将在未来的LLM研究和应用中发挥更大的作用。</p><h3>MoE平台工具</h3><p>在阿里云PAI灵骏分布式集群上运行的基于Megatron的MoE训练工具由三部分组成(如下图所示)。从上到下依次是PAI平台,PAI-Megatron-Patch (<a href="https://link.segmentfault.com/?enc=Kt5vvih9DEOoAfBKGrdOlg%3D%3D.eLZk4gWvOKALhKIQ8nntAkhVY6P6kp2s6toHJrJQWt%2BBOvTpoQKSwUTYb2I%2BsVVN" rel="nofollow">https://github.com/alibaba/Pai-Megatron-Patch</a>)以及NVIDIA Megatron-Core(<a href="https://link.segmentfault.com/?enc=Z%2BmFUHvGNgIu4HgljzJkQQ%3D%3D.GFWN%2FxUWmz7gT8Gvy9AWc8V1YPWSlYT5ghAZ%2BmqVDjY7kw0HRLymhQXd9jrHiYDD" rel="nofollow">https://github.com/NVIDIA/Megatron-LM</a>)。PAI平台的DSW产品是为AI开发者量身定制的云端机器学习交互式开发IDE,随时随地开启Notebook快速读取数据、开发算法、训练及部署模型。DLC产品则为您提供灵活、稳定、易用和极致性能的多机多卡深度学习训练环境。Pai-Megatron-Patch是各类开源大模型和Megatron训练加速引擎之间的“桥梁”,为用户提供用Megatron训练开源大模型的易用性以及LLM算法场景定制化的灵活性。NVIDIA开发的Megatron以其良好的业界口碑赢得了众多大模型用户的青睐,其算子拆分和流水并行等模型并行技术已经成为行业标准。基于DeepSpeed Zero-1改进的Distributed Optimizer在大规模分布式训练过程中的降显存方面发挥巨大作用。集成最新的算子融合,Transformer Engine以及Flash Attention等训练加速技术更是将大模型的吞吐性能&显卡利用率提升到了极致[3].。</p><p>以代码生成这个LLM应用场景为例,研发团队首先在DSW中开发&调试用于该场景的定制化数据处理流程,使用定制化的分词器对原始代码数据进行ID化,同时调试模型库中对应的代码生成模型比如deepseek。接着在DSW中跑通适用于多机多卡训练的HuggingFace到Megatron的权重转换流程并生成Megatron可加载的权重。然后在DLC中配置Patch提供的训练启动脚本,将训练所需的超参数比如学习率以及训练加速开关比如Flash Attention等通过脚本传入Megatron训练引擎。</p><p><img src="/img/remote/1460000044606343" alt="图片" title="图片"></p><h2>MoE 训练效果展示</h2><p>我们以最近社区热门的Mixtral-8x7B稀疏MoE大模型为例,从HuggingFace到 Megatron的零样本loss对齐,训练loss收敛曲线,代码生成下游任务评测,训练吞吐性能这四个方面向用户展示训练工具的预期效果,以此来验证工具的可靠性和稳定性。为方便用户测试,我们提供了已经处理好的idxmap格式的Wudao数据集,转换前的HuggingFace模型以及转换后的Megatron-Core格式的模型供下载使用,具体文件大小和下载链接如下所示。</p><p><img src="/img/remote/1460000044606344" alt="图片" title="图片"></p><p><img src="/img/remote/1460000044606345" alt="图片" title="图片"></p><pre><code>https://atp-modelzoo-wlcb-pai.oss-cn-wulanchabu.aliyuncs.com/release/models/pai-megatron-patch/mistral-ckpts/Mixtral-8x7B-v0.1-to-mcore-tp4-ep4.tar.zsthttps://atp-modelzoo-wlcb-pai.oss-cn-wulanchabu.aliyuncs.com/release/models/pai-megatron-patch/mistral-ckpts/Mixtral-8x7B-v0.1.tar.zsthttps://atp-modelzoo-wlcb-pai.oss-cn-wulanchabu.aliyuncs.com/release/models/pai-megatron-patch/mistral-datasets/wudao_mistralbpe_content_document.binhttps://atp-modelzoo-wlcb-pai.oss-cn-wulanchabu.aliyuncs.com/release/models/pai-megatron-patch/mistral-datasets/wudao_mistralbpe_content_document.idx</code></pre><p>测试镜像地址请采用:<a href="https://link.segmentfault.com/?enc=%2FwsQo54JFfg4%2F0IYKnXHjw%3D%3D.tDGiWBteyEotXISXdIxm6KfjnQV6jhXWSFdL3Qzhzrc2AL%2BVRbXJBPPFwHMDi31VeEKqedleMm84ZMgjJSXO6OGWdsl%2FJtf9YbseMctAku%2BvH0tU0bMOaeW%2FHvdMTGUh3vT6sTlVf592s%2Fq5EHwumLOYkNGmpau0SLGyRaTH0PM%3D" rel="nofollow">http://dsw-registry.cn-wulanchabu.cr.aliyuncs.com/pai/pytorch...</a></p><h3>HF 到 Megatron 模型权重转换</h3><p>由于从头预训练大模型所消耗的算力成本较高,因此用户普遍采用加载 HuggingFace 提供已经训练好的模型权重继续预训练或者微调。这就需要先把 HuggingFace的Transformer结构的权重转换到Megatron的Transformer可识别并加载的格式。下图显示的两边的算子之间的对照关系。</p><p><img src="/img/remote/1460000044606346" alt="图片" title="图片"></p><p>这里需要注意的是当TP>1的时候,对权重矩阵的切分与合并操作应符合Megatron的建模方式。以mlp层的gate_proj和up_proj为例,按TP=2切分后两个算子的左半部分先组合到一起,然后右半部分再组合到一起,然后拼接形成Megatron可识别的dense_h_to_4h操作,如下图所示。这种拆分&合并的顺序一旦出现错误,会导致两边的前向推理无法对齐。</p><p><img src="/img/remote/1460000044606347" alt="图片" title="图片"></p><p>另外涉及到experts的分配的时候也需要格外小心。我们对比dense的转换在moe模型的convert脚本中新增了两个参数(expert_model_parallel_size和world_size(总卡数))来对experts的分布进行精细化处理。比如mixtral的experts的总数是8,那么在16张卡有三种转换情况, tp4ep4, tp8ep2, tp2ep8,按照每种情况来分配moe层的权重。以tp4ep4为例,权重转换后的文件夹命名如下表所示:</p><p><img src="/img/remote/1460000044606348" alt="图片" title="图片"></p><p>在每个文件里存储两个experts的FFN权重,每个tp_rank有8个experts来做路由,如下图所示:</p><p><img src="/img/remote/1460000044606349" alt="图片" title="图片"></p><p>最后我们通过zeroshot loss来衡量转换后的模型是否正确,从下表中可以看到,转换前后的误差基本可以控制在非常小的范围内。下表中箭头精度转换(fp16->bf16)的含义是checkpoint格式是fp16, 运行的时候加载成bf16。</p><p><img src="/img/remote/1460000044606350" alt="图片" title="图片"></p><h3>基于 MoE 模型继续预训练 & 微调收敛</h3><p>我们探索了三个使用场景的收敛情况分别是:从头预训练,加载Mixtral-8x7B-v0.1继续预训练以及加载Mixtral-8x7B-Instruct-v0.1微调。具体操作方法可参考我们提供的Mixtral-8x7B稀疏大模型最佳实践,里面详细介绍了如何启动训练的细节。在从头预训练的实验中,我们采用的训练配置是:A800机型80G显存,两机16卡,global_size=256,lr=1e-4, seq_len=2048, TP=4。训练24个小时到2.4k个step后的loss可以到收敛到1.9的曲线如下所示:</p><p><img src="/img/remote/1460000044606351" alt="图片" title="图片"></p><p>$$
*仅做技术参考和探讨
$$</p><p>在加载Mixtral-8x7B-v0.1继续预训练的实验中,我们采用的训练配置是:A800机型80G显存,两机16卡,global_size=256,lr=5e-5, seq_len=2048, TP=4。训练18个小时到2k个step后的loss收敛曲线如下所示:</p><p><img src="/img/remote/1460000044606352" alt="图片" title="图片"></p><p>$$
*仅做技术参考和探讨
$$</p><p>在加载Mixtral-8x7B-Instruct-v0.1微调的实验中,我们在代码生成这个下游任务中设计了三种微调场景分别是:base模型纯自回归训练(橙色曲线,计算全部loss),instruct模型纯自回归训练(蓝色曲线,计算全部loss) 和instruct模型纯自回归训练(红色曲线,计算answer loss)。从三种情况的收敛loss曲线对比可以看出基本都收敛到0.5上下。其中采用base模型来微调的loss下载不如其他两个,这是符合预期的。</p><p><img src="/img/remote/1460000044606353" alt="图片" title="图片"></p><h3>代码生成任务评测</h3><p>代码生成是指通过自然语言描述生成相应的可执行代码,从而提升开发人员的工作效率。随着LLM模型的不断发展,在代码生成任务上也取得了突破性的进展,如github copilot能够提升55%的开发效率。我们针对代码生成这个下游领域任务,基于Evol-Instruct-Code-80K数据对Mixtral-8x7B-Instruct-v0.1模型进行微调,并测试了在微调前后模型Human-eval上的通过率,和LLaMA2等开源通用模型对比可以看到微调后的模型在代码生成的能力上有明显的优势,如下表所示。</p><p><img src="/img/remote/1460000044606354" alt="图片" title="图片"><br>我们在A800机型80G显存,两机16卡下采用的微调参数如下,具体操作方法可参考我们提供的Mixtral-8x7B稀疏大模型最佳实践。</p><pre><code>micro batch size: 1
global batch size: 128
lr: 1e-5
min_lr: 1e-6
seqlen:2048
padlen:2048
tp:4
pp:1
ep:4
train_iter:2500</code></pre><p>$$
*仅做技术参考和探讨
$$</p><p>在评测时,我们使用如下的prompt来生成代码:</p><pre><code>f"[INST] Create a Python script for this problem:{question} [/INST]"</code></pre><h3>训练吞吐性能</h3><p>笔者注:Megatron-Core MoE在短期内还会加入对于通信、计算以及Token dispatch的多项性能优化,当前的测试数据不代表最终的性能数据。</p><p>在吞吐速度评测环节,阿里PAI团队调研了Megablocks(<a href="https://link.segmentfault.com/?enc=nVHSxwg2515220NChk8gQA%3D%3D.26ivHlMLvgmBJL4e8xPuF7GBfvS1H5CA82gRdiSQTdoKnkLJZbROdmkPV4cZYP%2BFCVWg%2Be6xohOmutih%2F2l8Dw%3D%3D" rel="nofollow">https://github.com/stanford-futuredata/Megablocks</a>)中的dmoe实现,一方面是因为Mixtral-8x7b论文中说采用的是Megablocks的框架训练的MoE模型,另一方面我们也想探索下在相同Megatron平台底座上,哪个MoE实现方式对训练吞吐加速效果更好。Megablocks论文中提供了同Dense模型的收敛速度的比较,如下图所示的具有2.4x的收敛加速能力,我们期望基于Megatron-Core的实现方案也具有同样甚至更好的加速效果。</p><p><img src="/img/remote/1460000044606355" alt="图片" title="图片"></p><p>吞吐性能对比实验采用的是阿里云PAI灵骏平台上A800机型80G显存,两机16卡运行环境。我们发现采用Mixtral-8x7B模型配置时,Megablocks的seqlen如果等于1024/2048会出现OOM。因此我们将Megablocks和Megatron-Core的seqlen都设置为512。同时我们打开 --moe-grouped-gemm 开启GroupedGEMM提升多 Experts 时的 GPU 利用率,从下表的吞吐数据可以看出,当前Megatron-Core的吞吐速度比 Megablock 快 10%左右。此外,由于我们得知Megatron-Core当前正在推进MoE的性能优化,因此当前的数据仅供参考。</p><p><img src="/img/remote/1460000044606356" alt="图片" title="图片"></p><h2>总结</h2><p>在基于Megatron-Core的稀疏大模型训练工具:阿里云MoE大模型最佳实践开发过程中,我们围绕稀疏大模型训练测试了以下核心技术的性能:</p><ul><li>MoE基础技术平台:基于Megatron-Core MoE的多重训练加速技术的可靠性。</li><li>MoE落地Pipeline:HF到Megatron的模型权重转换在继续预训练&微调以及代码生成下游任务中的效果。</li></ul><p>后续在Pai-Megatron-Patch中还会陆续放出更多高质量的大模型最佳实践,敬请期待。</p><p><strong>参考文献</strong></p><p>[1]. Switch Transformers: Scaling to Trillion Parameter Models with Simple and Efficient Sparsity</p><p>[2]. Megablocks: Efficient Sparse Training with Mixture-of-Experts</p><p>[3]. Reducing Activation Recomputation in Large Transformer Models</p><p>作者:李鹏,颜子杰,王明,颜海强,刘振寰,黄俊</p><p>单位:阿里云人工智能平台PAI,NVIDIA DevTech Team</p><p><strong><a href="https://link.segmentfault.com/?enc=5suUfG%2FvOa6hqwAVyGWH4w%3D%3D.RMyfHin%2FNf0PVGCjGWn8Ow2%2B0a7fJex%2B3HoWTIdlbEby0tFB3rHVIMSZxeTqY0dX1pFXrXWCLSlclrjr5VSyLId7yh8HKaif4FkHzKWBZjQ%3D" rel="nofollow">原文链接</a></strong></p><p><strong>本文为阿里云原创内容,未经允许不得转载。</strong></p>
十年后数据库还是不敢拥抱 NUMA - 续篇
https://segmentfault.com/a/1190000044605742
2024-01-31T14:29:54+08:00
2024-01-31T14:29:54+08:00
阿里云云栖号
https://segmentfault.com/u/aliyunqi
0
<h2>背景</h2><p>十年后数据库还是不敢拥抱NUMA, 这篇经典的纠正大家对NUMA 认知的文章一晃发布快3年了,这篇文章的核心结论是:</p><ul><li>之所以有不同的NUMA Node 是不同的CPU Core 到不同的内存距离远近不一样所决定的,这是个物理距离</li><li>程序跑在不同的核上要去读写内存可以让性能差异巨大,所以我们要尽量让一个程序稳定跑在一个Node 内</li><li>默认打开NUMA Node 其实挺好的</li></ul><p>写这个续篇是我收到很多解释,因为跨Node 导致性能抖动,所以集团在物理机OS 的启动参数里设置了 numa=off ,也就是不管BIOS 中如何设置,我们只要在OS 层面设置一下 numa=off 就能让程序稳定下来不再抖了! 我这几年也认为这是对的,只是让我有点不理解,既然不区分远近了,那物理上存在的远近距离(既抖动)如何能被消除掉的呢? 所以这个续篇打算通过测试来验证下这个问题</p><h2>设置</h2><p>BIOS 中有 numa node 设置的开关(注意这里是内存交错/交织),不同的主板这个BIOS设置可能不一样,但是大同小异,基本都有这个参数</p><p><img src="/img/remote/1460000044605744" alt="图片" title="图片"></p><p>Linux 启动引导参数里也可以设置numa=on(默认值)/off ,linux 引导参数设置案例:</p><pre><code>#cat /proc/cmdline
BOOT_IMAGE=/vmlinuz-3.10.0-327.x86_64 ro crashkernel=auto vconsole.font=latarcyrheb-sun16 vconsole.keymap=us BIOSdevname=0 console=tty0 console=ttyS0,115200 scsi_mod.scan=sync intel_idle.max_cstate=0 pci=pcie_bus_perf ipv6.disable=1 rd.driver.pre=ahci numa=on nosmt=force</code></pre><p>注意如上的 numa=on 也可以改为 numa=off 看完全置篇要记住一条铁律:CPU到内存的距离是物理远近决定的,你软件层面做些设置是没法优化这个距离,也就是没法优化这个时延 (这是个核心知识点,你要死死记住和理解,后面的一切实验数据都回过头来看这个核心知识点并揣摩)</p><h2>实验</h2><p>测试机器CPU,如下是BIOS numa=on、cmdline numa=off所看到的,一个node</p><pre><code>#lscpu
Architecture: x86_64
CPU op-mode(s): 32-bit, 64-bit
Byte Order: Little Endian
CPU(s): 96
On-line CPU(s) list: 0-95
Thread(s) per core: 2
Core(s) per socket: 24
Socket(s): 2
NUMA node(s): 1
Vendor ID: GenuineIntel
CPU family: 6
Model: 85
Model name: Intel(R) Xeon(R) Platinum 8163 CPU @ 2.50GHz
Stepping: 4
CPU MHz: 2500.000
CPU max MHz: 3100.0000
CPU min MHz: 1000.0000
BogoMIPS: 4998.89
Virtualization: VT-x
L1d cache: 32K
L1i cache: 32K
L2 cache: 1024K
L3 cache: 33792K
NUMA node0 CPU(s): 0-95</code></pre><p>测试工具是lmbench,测试命令:</p><pre><code>for i in $(seq 0 6 95); do echo core:$i; numactl -C $i -m 0 ./bin/lat_mem_rd -W 5 -N 5 -t 64M; done >lat.log 2>&1</code></pre><p>上述测试命令始终将内存绑定在 node0 上,然后用不同的物理core来读写这块内存,按照前一篇 这个时延肯定有快慢之分 BIOS和引导参数各有两种设置方式,组合起来就是四种,我们分别设置并跑一下内存时延,测试结果:</p><p><img src="/img/remote/1460000044605745" alt="图片" title="图片"></p><p>测试原始数据如下(测试结果文件名 lat.log.BIOSON.cmdlineOff 表示BIOS ON,cmdline OFF ):</p><pre><code>//从下面两组测试来看,BIOS层面 on后,不管OS 层面是否on,都不会跨node 做交织,抖动存在
//BIOS on 即使在OS层面关闭numa也不跨node做内存交织,抖动存在
//默认从内存高地址开始分配空间,所以0核要慢
#grep -E "core|64.00000" lat.log.BIOSON.cmdlineOff
core:0 //第0号核
64.00000 100.717 //64.0000为64MB, 100.717 是平均时延100.717ns 即0号核访问node0 下的内存64MB的平均延时是100纳秒
core:24
64.00000 68.484
core:48
64.00000 101.070
core:72
64.00000 68.483
#grep -E "core|64.00000" lat.log.BIOSON.cmdlineON
core:0
64.00000 67.094
core:24
64.00000 100.237
core:48
64.00000 67.614
core:72
64.00000 101.096
//从下面两组测试来看只要BIOS off了内存就会跨 node 交织,大规模测试下内存 latency 是个平均值
#grep -E "core|64.00000" lat.log.BIOSOff.cmdlineOff //BIOS off 做内存交织,latency就是平均值
core:0
64.00000 85.657 //85 恰好是最大100,最小68的平均值
core:24
64.00000 85.741
core:48
64.00000 85.977
core:72
64.00000 86.671
//BIOS 关闭后numa后,OS层面完全不知道下层的结构,默认一定是做交织
#grep -E "core|64.00000" lat.log.BIOSOff.cmdlineON
core:0
64.00000 89.123
core:24
64.00000 87.137
core:48
64.00000 87.239
core:72
64.00000 87.323</code></pre><p>从数据可以看到在BIOS 设置ON后,无论 OS cmdline 启动参数里是否设置了 ON 还是 OFF,内存延时都是抖动且一致的(这个有点诧异,说好的消除抖动的呢?)。如果BIOS 设置OFF后内存延时是个稳定的平均值(这个比较好理解)</p><h2>疑问</h2><ul><li>内存交错时为什么 lmbench 测试得到的时延是平均值,而不是短板效应的最慢值? 测试软件只能通过大规模数据的读写来测试获取一个平均值,所以当一大块内存读取时,虽然通过交织大块内存被切分到了快慢物理内存上,但是因为规模大慢的被平均掉了。(欢迎内核大佬指正)</li><li>什么是内存交织? 我的理解:假如你有8块物理内存条,如果你有一个int 那么只能在其中一块上,如果你有1MB的数据那么会按cacheline 拆成多个块然后分别放到8块物理内存条上(有快有慢)这样带宽更大,最后测试得到一个平均值 如果你开启numa那么只会就近交织,比如0-3号内存条在0号core所在的node,OS 做内存交织的时候只会拆分到这0-3号内存条上,那么时延总是最小的那个,如上测试中的60多纳秒。</li></ul><p>这个问题一直困扰了我几年,所以我最近再次测试验证了一下,主要是对 BIOS=on 且 cmdline=off 时有点困扰</p><h2>Intel 的 mlc 验证</h2><p>测试参数: BIOS=on 同时 cmdline off 用Intel 的 mlc 验证下,这个结果有点意思,latency稳定在 145 而不是81 和 145两个值随机出现,应该是mlc默认选到了0核,对应lmbench的这组测试数据(为什么不是100.717, 因为测试方法不一样):</p><pre><code>//如下是前面 lmbench 测试结果,抄下来和 mlc 做个对比
//从下面两种测试来看,BIOS层面 on后,不管OS 层面是否on,都不会跨node 做交织,抖动存在
//BIOS on 即使在OS层面关闭numa也不跨node做内存交织,抖动存在
#grep -E "core|64.00000" lat.log.BIOSON.cmdlineOff
core:0
64.00000 100.717
core:24
64.00000 68.484
core:48
64.00000 101.070
core:72
64.00000 68.483</code></pre><p>对应的mlc</p><pre><code>#./mlc
Intel(R) Memory Latency Checker - v3.9
Measuring idle latencies (in ns)...
Numa node
Numa node 0
0 145.8 //多次测试稳定都是145纳秒
Measuring Peak Injection Memory Bandwidths for the system
Bandwidths are in MB/sec (1 MB/sec = 1,000,000 Bytes/sec)
Using all the threads from each core if Hyper-threading is enabled
Using traffic with the following read-write ratios
ALL Reads : 110598.7
3:1 Reads-Writes : 93408.5
2:1 Reads-Writes : 89249.5
1:1 Reads-Writes : 64137.3
Stream-triad like: 77310.4
Measuring Memory Bandwidths between nodes within system
Bandwidths are in MB/sec (1 MB/sec = 1,000,000 Bytes/sec)
Using all the threads from each core if Hyper-threading is enabled
Using Read-only traffic type
Numa node
Numa node 0
0 110598.4
Measuring Loaded Latencies for the system
Using all the threads from each core if Hyper-threading is enabled
Using Read-only traffic type
Inject Latency Bandwidth
Delay (ns) MB/sec
==========================
00000 506.00 111483.5
00002 505.74 112576.9
00008 505.87 112644.3
00015 508.96 112643.6
00050 574.36 112701.5</code></pre><p>当两个参数都为 on 时的mlc 测试结果:</p><pre><code>#./mlc
Intel(R) Memory Latency Checker - v3.9
Measuring idle latencies (in ns)...
Numa node
Numa node 0 1
0 81.6 145.9
1 144.9 81.2
Measuring Peak Injection Memory Bandwidths for the system
Bandwidths are in MB/sec (1 MB/sec = 1,000,000 Bytes/sec)
Using all the threads from each core if Hyper-threading is enabled
Using traffic with the following read-write ratios
ALL Reads : 227204.2
3:1 Reads-Writes : 212432.5
2:1 Reads-Writes : 210423.3
1:1 Reads-Writes : 196677.2
Stream-triad like: 189691.4</code></pre><p>说明:mlc和 lmbench 测试结果不一样,mlc 时81和145,lmbench测试是68和100,这是两种测试方法的差异而已,但是快慢差距基本是一致的</p><h2>结论</h2><p>在OS 启动引导参数里设置 numa=off 完全没有必要、也不能解决抖动的问题,反而设置了 numa=off 只能是掩耳盗铃,让用户看不到 NUMA 结构</p><p><strong><a href="https://link.segmentfault.com/?enc=B3qTjEBHY0AwMbh71V7ClA%3D%3D.Trl2QCA4akIhinQxZaENPUTVaYIfdYouFCVj6TSg9aLpYGfbWomyWaw1vq0t%2BsuGU162w075f2u2JZCygOw%2Fpmh4vTSNnSkAbLXky1384vU%3D" rel="nofollow">原文链接</a></strong></p><p><strong>本文为阿里云原创内容,未经允许不得转载。</strong></p>
PolarDB-X 最佳实践系列(四):如何设计一张订单表
https://segmentfault.com/a/1190000044604864
2024-01-31T10:29:09+08:00
2024-01-31T10:29:09+08:00
阿里云云栖号
https://segmentfault.com/u/aliyunqi
0
<p>本文主要内容是如何使用全局索引与CO_HASH分区算法(CO_HASH),实现高效的多维度查询。</p><h2>淘宝订单号中的秘密</h2><p>有一个很有趣的事情。</p><p>打开你的淘宝客户端或者PC端的淘宝,点开订单列表,打开几个订单,查看他们的订单号,你会发现什么?</p><p><img src="/img/remote/1460000044604866" alt="图片" title="图片"></p><p><img src="/img/remote/1460000044604868" alt="图片" title="图片"></p><p>比如这是我最近的3个订单,和10年前的3个订单。其订单号分别是:</p><p>1249511065364414810<br>1238822988656414810<br>1236446127134414810<br>103698817404810<br>107655289504810<br>103719620094810</p><p>也许你会惊奇的发现,订单号的后几位好像是一样的。比如我的账号,从10年前到今天,订单号的后四位一直是4810,那么为什么?这个其实和使用分布式数据库的一个最佳实践相关。</p><h2>经典的买卖家例子</h2><p>好多年前就流传着淘宝买卖家的案例...</p><p>淘宝中有一个非常重要的表,订单表,他里面存着订单的一些关键信息,例如订单号(order_id)、卖家id(seller_id)、买家id(buyer_id)、商品id等等。有两类查询是这个表上的高频查询:</p><pre><code>select * from orders where buyer_id = ?
select * from orders where seller_id = ?</code></pre><p>这两个SQL的业务含义一目了然,分别是买家查询自己的订单列表和卖家查询自己的订单列表。</p><p>如果我们在单机数据库中做这两条SQL,都知道怎么做。嗯,在buyer_id和seller_id上分别建个建索引就可以了:</p><pre><code>create index idx_buyer_id on orders (buyer_id);
create index idx_seller_id on orders (seller_id);</code></pre><p>在数据库中,空间换时间是一个非常基本的思路,例如加索引。</p><p>如果你是用一些分库分表中间件,例如MyCAT之类的产品,对这个表做了分库分表,就需要面临一个跟单机数据库完全不一样的一个问题,该如何选择分库分表键?</p><p>一般此类中间件都会告诉你,你哪个列查的最多,就选哪个列做拆分键。</p><p>但问题来了,这两类SQL都很高频,选了buyer_id做分库分表键,那按seller_id查就会全库全表扫描;如果按seller_id做分库分表键,那按buyer_id查就会全库全表扫描。</p><p>难道鱼和熊掌不可兼得?</p><p>一般解决这类的问题的方案是,使用两套订单表,其中一套使用buyer_id做分库分表建,另一套使用seller_id做分库分表键,中间使用binlog来做同步,类似下面的样子:</p><p><img src="/img/remote/1460000044604869" alt="图片" title="图片"></p><p>这个方案是OK的,能够落地的,只不过做的过程会有些小痛苦要解决,例如:</p><p>1、这个同步怎么搞啊...,用开源的binlog订阅组件比如canal吗?那这个canal怎么运维啊...好烦<br>2、这个同步是有延迟的,延迟代表了数据死不一致的,应用需要有一些容错机制来避免不一致带来的影响,好烦+1<br>3、需要在业务里自己控制应该访问哪个表,好烦+2<br>4、分库分表下面有很多的mysql,要同时同步这么多的mysql...,好烦+3<br>5、做DDL要有些技巧,比如加列先加目标端,减列先减源端...,很多的潜规则,好烦+4<br>6、这才是一张表呢!我有一堆类似的场景怎么办!!好烦+10086</p><p>我们先不管这些缺点,假设我们已经这样做到了,我们成功的解决了买卖家订单问题。</p><h2>买卖家问题进阶</h2><p>我们现在又有了一个新的要考虑的SQL:</p><pre><code>select * from orders where order_id = ?</code></pre><p>这个SQL作用太简单了,根据订单id查订单详情嘛!</p><p>为了做这个SQL,单机里给order_id建索引即可,分库分表应该怎么做?</p><p>抢答一个!把订单表再复制一份,使用order_id做分库分表键。</p><p>听起来可以,应该能解决问题。但是,这个表多复制一份,就是多一份的代价,比如空间,比如同步链路的维护。所以,有没有更好的方法?</p><p>我们能关注到一个事情,订单id,是由我们程序控制生成的。在生成订单的时候,我们一定知道它的买家id,假如我们将买家id隐藏在订单id里,有了订单id就能算出买家id,有了买家id就可以去查买家维度的订单表了。</p><p>这样,我们还是只需要存两份数据(买家维度和卖家维度),就能同时解决三个维度的查询(买家维度、卖家维度、订单维度)。</p><p>所以现在应该明白了,为什么同一个人的淘宝订单后4位是相同的了吧。</p><p>小花絮:</p><p><img src="/img/remote/1460000044604870" alt="图片" title="图片"></p><p>我发现我11年7月10的订单号还是4810结尾,但11年6月28号及之前的订单并没有遵循这个规律。呃...这说明,淘宝应该是在11年的6.28-7.10之间做了这个优化。</p><h2>PolarDB-X中如何实现</h2><p>OK,回到我们的云原生分布式数据库PolarDB-X。</p><p>如果我们在PolarDB-X中要解决上述买卖家问题,应该怎么做?</p><p>答案是,我们只需执行以下几条SQL即可:</p><pre><code>jcreate database ms1 mode=auto;
use ms1;
create table orders(
order_id varchar(128) primary key,
buyer_id varchar(128),
seller_id varchar(128),
index idx_buyer_id(buyer_id),
index idx_seller_id(seller_id)
)partition by hash(order_id);
create clustered index gsi_buyer_id on orders (buyer_id) partition by hash(buyer_id);
create clustered index gsi_seller_id on orders (seller_id) partition by hash(seller_id);</code></pre><p>然后?没有然后了啊,这就可以了。</p><p>真的可以了,你不用改SQL,不用研究Canal(其实canal作者就坐我旁边,要考虑下来玩玩吗),不用维护同步链路,不用担心数据不一致,就O!K!了!</p><p>至于按订单id查?订单id本来就是orders的主键,默认就是orders表的分区键,所以没问题的。</p><p>这么简单就OK了?为什么?</p><h2>PolarDB-X中的全局索引</h2><p>这两条语句发生了什么?实际上,他们在orders表上,创建了两条全局索引。全局索引和单机索引的原理差不多,也是空间换时间的思想,只不过它的数据以索引的key分布在整个集群中。</p><p>全局索引的创建、维护,都在PolarDB-X内核中完成的,完全不需要用户去操心。</p><p>有一个小问题,建索引的语句里面,有个clustered关键字,这是什么意思?</p><p>我们先看,如果不加clustered,会发生什么,例如:</p><pre><code>jcreate global index gsi_buyer_id on orders (buyer_id) partition by hash(buyer_id);</code></pre><p>主表:</p><p><img src="/img/remote/1460000044604871" alt="图片" title="图片"></p><p>PolarDB-X会定义这样的一个索引结构:</p><p><img src="/img/remote/1460000044604872" alt="图片" title="图片"><br>这个索引中,会包含索引的key以及主键两个列,也即order_id与buyer_id。</p><p>PolarDB-X在执行select * from orders where buyer_id = ? 的时候,会先根据buyer_id在索引idx_buyer_id上扫描出order_id,再使用order_id到主表上进行回表操作。</p><p>听起来好像没有什么问题。</p><p>但是,有一点需要考虑。请打开你的订单列表,看一下,你有多少订单:</p><p><img src="/img/remote/1460000044604873" alt="图片" title="图片"></p><p>呃...,我有126页订单,数了下,每页15个,也就是大约1800个订单。</p><p>淘宝的订单表的分区数大约是数千这个量级,你会发现,这1800个订单的回表,要覆盖相当比例的分区,似乎跟全表扫描的代价没有什么太大的差异了。</p><p>怎么办?</p><p>我们为什么要回表?其是是因为,我们的查询是SELECT *,需要这个表所有的列,而我们的索引里只包含了索引key和主键,因此需要到主表中找到剩下的列。</p><p>所以为了不回表,我们想到的一个办法,是在索引表中冗余主表的所有列,用更多的时间来换取空间。</p><p>所以,一个合格的分布式数据库,不仅需要有全局索引,还需要有聚簇的(clustered)全局索引。</p><p>Clustered index就是PolarDB-X中的概念,它相对于普通的全局索引的区别就是,它包含了表的所有列,可以避免回表的代价。</p><p>PolarDB-X中的CO_HASH</p><p>如果如上文所说,订单ID的后四位与买家ID的后四位相同,如何使用PolarDB-X实现此类路由逻辑呢。</p><p>PolarDB-X提供了名为CO_HASH的分区算法,可以完成这个功能:</p><pre><code>jcreate database ms1 mode=auto;
use ms1;
create table orders(
order_id varchar(128) primary key,
buyer_id varchar(128),
seller_id varchar(128),
index idx_buyer_id(buyer_id),
index idx_seller_id(seller_id)
)partition by co_hash(right(order_id,4), right(buyer_id,4));
create clustered index gsi_seller_id on orders (seller_id) partition by hash(seller_id);
select * from orders where buyer_id=? //主表
select * from orders where order_id=? //主表
select * from orders where seller_id=? //gsi_seller_id</code></pre><p>通过使用CO_HASH,可以省略掉buyer_id上的全局索引。</p><p>CO_HASH的更多用法参考:如何使用DDL语句创建分区表</p><p>CO_HASH的核心理念是:</p><ul><li>有些信息来源用户的输入,例如用户系统的手机号、邮箱,订单系统中的buyer_id、seller_id;</li><li>有些信息是由“业务系统”生成的,例如用户系统中的user_id,订单系统中的order_id。</li></ul><p>我们有时可以通过控制“业务系统”的生成逻辑,将其生成的内容与用户的输入关联起来,来达到降维的目的。</p><p>例如:</p><ul><li>user_id中可以携带手机号的某几位,或者携带邮箱的hash值的某几位;</li><li>order_id可以携带seller_id,或者buyer_id的某几位。</li></ul><p>CO_HASH是一种非常有用的小技巧,合理使用可以有效的减少GSI的数目。</p><p>但CO_HASH也不是万能的,它只能减少两种存在关联的维度中的一维,如果完全不存在关联,就必须使用GSI了。</p><h2>小结</h2><p>OK,总结几条这个例子告诉我们的PolarDB-X的最佳实践:</p><p>1、使用全局索引来解决类似买卖家问题的多维度查询的问题<br>2、当索引与主表是一对多的关系的时候,考虑使用clustered index来消灭回表的代价<br>3、对订单ID等做巧妙的设计,结合CO_HASH,可以省略部分全局索引。</p><p>怎么样,PolarDB-X用起来是不是非常简单,欢迎持续关注我们。</p><p><strong><a href="https://link.segmentfault.com/?enc=6EoW04x7axWxxv5sJdeIRA%3D%3D.1FUX%2FHp7dx%2FMGKRnx81oTugzuVEsXFeg6K18QEwOU5OZ448R%2FxPWJbike0LWTxyy5gfx8hYLlKdcDCNneN%2F0gLQ2ynZEu%2B1V%2BQIL0wn4Qig%3D" rel="nofollow">原文链接</a></strong></p><p><strong>本文为阿里云原创内容,未经允许不得转载。</strong></p>
云原生离线工作流编排利器 - 分布式工作流 Argo 集群
https://segmentfault.com/a/1190000044603043
2024-01-30T16:48:16+08:00
2024-01-30T16:48:16+08:00
阿里云云栖号
https://segmentfault.com/u/aliyunqi
0
<p>在现代的软件开发和数据处理领域,批处理作业(Batch)扮演着重要的角色。它们通常用于数据处理,仿真计算,科学计算等领域,往往需要大规模的计算资源。随着云计算的兴起,阿里云批量计算和 AWS Batch 等云服务提供了管理和运行这些批处理作业的平台。</p><p>随着云原生和 Kubernetes 生态的发展,越来越多的应用运行在 Kubernetes 之上,例如在线应用,中间件,数据库。那对离线任务和批量计算是否可以在 Kubernetes 这个统一平台之上运行,答案是肯定的,分布式工作流 Argo 集群[1],基于开源 Argo Workflows[2]项目,完全符合开源工作流标准,可以编排和运行离线任务和批量计算,并使用 Serverless 方式运行,降低运维复杂度,节省运行成本。</p><p>通过分布式工作流 Argo 集群,您可以轻松编排工作流,每个工作流步骤使用容器运行,可以在短时间内轻松运行大规模机器学习、仿真计算和数据处理等计算密集型作业,也可以快速运行 CI/CD 流水线。</p><p><img src="/img/remote/1460000044603045" alt="图片" title="图片"></p><p>本文介绍主流 Batch 批量计算系统和分布式工作流 Argo 集群的区别,并讨论如何将离线任务和批量计算迁移到分布式工作流 Argo 集群。</p><h2>Batch 批量计算的相关概念</h2><p><img src="/img/remote/1460000044603047" alt="图片" title="图片"></p><h3>作业(Jobs)</h3><p>一个任务单元(例如 shell 脚本、Linux 可执行文件或 Docker 容器镜像),可以提交给 Batch 批量计算系统,批量计算系统会在计算环境中分配计算资源并运行作业。</p><h4>Array Jobs</h4><p>Array Job 是指一系列相似或相同的作业(Jobs),这些作业作为一个数组批量提交并运行。每一个作业都有相同的作业定义,但可以通过索引来区分,每个作业实例处理不同的数据集或执行稍有差异的任务。</p><h3>作业定义(Job Definitions)</h3><p>作业定义指定了作业的运行方式。运行作业前需要先创建作业定义。作业定义一般包含:作业运行所使用的镜像,具体命令与参数,需要的 CPU/Memory 资源,环境变量,磁盘存储等。</p><h3>作业队列(Job Queues)</h3><p>向 Batch 批量计算系统提交作业时,会提交到指定的作业队列中排队,直到被调度运行。作业队列可以设置优先级,并指定关联的计算环境。</p><p>计算环境(Compute Environment)</p><p>计算环境是一组计算资源,可以运行作业。对计算环境需要指定虚拟机的机型,环境的最小、最大 vCPU 数量,以及 Spot 竞价实例的价格。</p><h3>总结</h3><ol><li>用户需要学习 Batch 批量计算作业定义规范与用法,有厂商绑定风险;</li><li>还需要管理计算环境,设置机型和规模等,非 Serverless 方式,运维高;</li><li>由于计算环境规模的限制,需要管理作业队列以设置作业的优先级,复杂度高。</li></ol><h2>分布式工作流 Argo 集群的相关概念</h2><p><img src="/img/remote/1460000044603048" alt="图片" title="图片"></p><h3>模版(Templates)</h3><p>模版定义了一个任务(作业),是工作流的组成部分,一个工作流至少要包含一个模版。模版中包含要运行的 Kubernetes 容器和相应的输入输出参数。</p><h3>工作流(Workflows)</h3><p>工作流包含一个或者多个任务(模版),并可以编排多个任务,支持定义复杂的任务流程,如序列化、并行化任务,以及在条件满足时执行特定的任务。创建工作流后,工作流中的任务,会在 Kubernetes 集群中以 Pod 形式运行。</p><h3>工作流模版(Workflow Templates)</h3><p>工作流模版是可复用的工作流的静态定义,类似于函数,可以在多个工作流中被引用并运行。在定义复杂工作流时可以复用已有的工作流模版,减少重复性定义。</p><h3>无服务器 Kubernetes 集群</h3><p>分布式工作流 Argo 集群自带计算环境,不需要手工创建和管理。提交工作流后,使用阿里云弹性容器 ECI,以 Serverless 方式运行工作流中的任务,不需要维护 Kubernetes 节点。利用阿里云的弹性能力,可以运行大规模工作流(数万任务 Pod),同时使用数十万核 CPU 的算力资源,在工作流运行完成后自动释放资源。加快工作流运行速度,并节省计算成本。</p><h3>总结</h3><ol><li>基于 Kubernetes 集群和开源 Argo Workflows 构建,以云原生的方式编排运行工作流,无厂商绑定风险;</li><li>复杂工作流任务的编排,可以应对数据处理、仿真计算,科学计算的复杂业务场景;</li><li>计算环境采用阿里云弹性容器 ECI,不需要维护节点;</li><li>大规模算力的按需使用,按量计费,避免工作流排队等待,提高效率,节省计算成本。</li></ol><h2>Batch 批量计算和 Argo 工作流功能映射</h2><p><img src="/img/remote/1460000044603049" alt="图片" title="图片"></p><h2>Argo 工作流示例</h2><h3>简单工作流</h3><pre><code>cat > helloworld.yaml << EOF
apiVersion: argoproj.io/v1alpha1
kind: Workflow # new type of k8s spec
metadata:
generateName: hello-world- # name of the workflow spec
spec:
entrypoint: main # invoke the main template
templates:
- name: main # name of the template
container:
image: registry.cn-hangzhou.aliyuncs.com/acs/alpine:3.18-update
command: [ "sh", "-c" ]
args: [ "echo helloworld" ]
EOF
argo submit helloworld.yaml</code></pre><p>在这个实例中,我们启动了一个任务 Pod,使用 alpine 镜像,运行 shell 命令 echo helloworld。在这个工作流基础上,可以在 args 中,指定多个 shell 命令并执行,也可以使用自定义镜像运行镜像中的命令。</p><h3>Loops 工作流</h3><pre><code>apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
generateName: loops-
spec:
entrypoint: loop-example
templates:
- name: loop-example
steps:
- - name: print-pet
template: print-pet
arguments:
parameters:
- name: job-index
value: "{{item}}"
withSequence: # loop to run print-pet template with parameter job-index 1 ~ 5 respectively.
start: "1"
end: "5"
- name: print-pet
inputs:
parameters:
- name: job-index
container:
image: acr-multiple-clusters-registry.cn-hangzhou.cr.aliyuncs.com/ack-multiple-clusters/print-pet
command: [/tmp/print-pet.sh]
args: ["{{inputs.parameters.job-index}}"] # input parameter job-index as args of container</code></pre><p>在示例中,镜像 print-pet 中打包了 pets.input 文本文件和 print-pet.sh 脚本文件,print-pet.sh 以 job-index 为输入参数,打印 pets.input 文件行号为 job-index 的 pet。具体文件内容请访问 GitHub 仓库[3]。</p><p>在工作流中,会同时启动 5 个 Pod,并分别传入参数 job-index 1~5,每个 pod 根据输入的 job-index 的值,打印相应行的 pet。通过 Loops 工作流可以实现数据分片和并行处理,加快海量数据的处理速度。更多 Loops 示例可以参考工作流(Workflows)Loops[4]。</p><h3>DAG 工作流(MapReduce)</h3><p>真实的批处理场景中,往往需要多个 Job 配合完成,所以需要指定 Job 间的依赖关系,DAG 是指定依赖关系的最佳方式。但主流的 Batch 批处理系统,需要通过 Job ID 指定 Job 依赖,由于 Job ID 需要在 Job 提交后才能获取,因此需要编写脚本实现 Job 间依赖(伪代码如下),Job 较多时依赖关系不直观维护代价高。</p><pre><code>//Batch批处理系统Job间依赖,JobB 依赖 JobA,在JobA完成后运行。
batch submit JobA | get job-id
batch submit JobB --dependency job-id (JobA)</code></pre><p>Argo 工作流可以通过 DAG 定义子任务间的依赖关系,示例如下:</p><p><img src="/img/remote/1460000044603050" alt="图片" title="图片"></p><pre><code># The following workflow executes a diamond workflow
apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
generateName: dag-diamond-
spec:
entrypoint: diamond
templates:
- name: diamond
dag:
tasks:
- name: A
template: echo
arguments:
parameters: [{name: message, value: A}]
- name: B
depends: "A"
template: echo
arguments:
parameters: [{name: message, value: B}]
- name: C
depends: "A"
template: echo
arguments:
parameters: [{name: message, value: C}]
- name: D
depends: "B && C"
template: echo
arguments:
parameters: [{name: message, value: D}]
- name: echo
inputs:
parameters:
- name: message
container:
image: alpine:3.7
command: [echo, "{{inputs.parameters.message}}"]</code></pre><p>在 Git 仓库[5]中,提供了一个 MapReduce 工作流示例,分片处理数据,并聚合计算结果。</p><h2>如何迁移 Batch 批处理系统到 Argo 工作流</h2><ol><li>评估与规划</li></ol><p>评估现有 Batch 批处理作业,包括依赖关系,资源需求,参数配置等。了解 Argo Workflows 的特性和最佳实践,并根据本文选择 Argo workflows 的功能以替代 Batch 批处理作业。另外,由于分布式工作流 Argo 集群的 Serverless ECI 能力,您可以跳过规划 Compute Environment 和管理优先级队列。</p><ol start="2"><li>创建分布式工作流 Argo 集群</li></ol><p>参考文档:工作流集群快速入门[6]</p><ol start="3"><li>转换作业定义</li></ol><p>根据 Batch 批量计算到 Argo 工作流的功能映射,重写 Batch 批量计算作业为 Argo 工作流,也可以通过调用 Argo 工作流 SDK[7],以自动化方式创建工作流,并接入业务系统。</p><ol start="4"><li>数据存储</li></ol><p>确保分布式工作流 Argo 集群可以访问工作流运行所需要的数据,工作流集群可以挂在访问阿里云 OSS,NAS,CPNS,云盘等存储资源。参考使用存储卷[8]。</p><ol start="5"><li>测试验证</li></ol><p>验证工作流运行正常,数据访问,结果输出正常,资源用量符合预期。</p><ol start="6"><li>运维:监控和日志</li></ol><p>开启分布式工作流 Argo 集群可观察能力[9],查看工作流运行状态和日志。</p><h3>总结</h3><ol><li>在用户体验、核心能力、计算环境和生态集成方面,Argo 工作流可以覆盖主流 Batch 批处理系统的功能,同时在复杂工作流编排和计算环境管理方面强于 Batch 批处理系统。</li><li>分布式工作流 Argo 集群基于 Kubernetes 构建,工作流定义符合 Kubernetes Yaml 规范,子任务定义符合 Kubernetes Container 规范。如果您已经在使用 Kubernetes 运行在线应用,可以快速上手编排工作流集群,统一使用 Kubernetes 作为在线应用和离线应用的技术底座。</li><li>计算环境采用阿里云弹性容器 ECI,不需要维护节点,同时提供大规模算力的按需使用,按量计费,避免工作流排队等待,提高运行效率,节省计算成本。</li><li>结合使用阿里云 Spot 示例,可以大幅降低计算成本。</li><li>分布式工作流适合 CICD,数据处理、仿真计算,科学计算等业务场景。</li></ol><p><strong>相关链接:</strong></p><p>[1] 分布式工作流 Argo 集群</p><p><a href="https://link.segmentfault.com/?enc=v7jPTaR79f0iNNbMEq21cQ%3D%3D.P7J%2BrFKXsmnmPbbmQ1JnOc9vpvBAjvA035YmPOuPetvnMWBTlKlGb8dnAPjvjjTaPn%2FyWrA9wyaHETykfA1jwWuDstTZKiEO1X6kDvnxyMJPmn1PQBKCnJCKBo4ysCxeiqbaOkfY%2F2YL0Whrl%2B3R4981%2FLGCnAh6fpB62%2Bp0Q60hAYo6TsoUW0qGLsx3NjYB" rel="nofollow">https://help.aliyun.com/zh/ack/distributed-cloud-container-pl...</a></p><p>[2] Argo Workflows</p><p><a href="https://link.segmentfault.com/?enc=fgUL%2FQUWK3t2YrJg8%2FSb6g%3D%3D.NB8Hyi9Nb%2BhkeNIxiP%2FMgQh9OX2QBDrE8AdTELjA%2FrCeBd74TVDvA51Gnh6t%2BrfJ" rel="nofollow">https://argoproj.github.io/argo-workflows/</a></p><p>[3] GitHub 仓库</p><p><a href="https://link.segmentfault.com/?enc=%2Fdlj76sTJUVSTBHUOSDrrQ%3D%3D.fmEN42f114Al9DBq517ezmnVByKEqvk6uujNmCxIzyyYVPATRuHAY0B5NxBmsrSjpTdB32qXVUE295VJTVhxA9qh0W7OsuqGG0wlrQxl2SrkJc0cYMuRSvnhxDJk7I%2B6" rel="nofollow">https://github.com/AliyunContainerService/argo-workflow-examples/tree/main/loops</a></p><p>[4] 工作流(Workflows)Loops</p><p><a href="https://link.segmentfault.com/?enc=1PTYIDeG5XbByFv%2BlICQIQ%3D%3D.z4l%2BG1%2F9fqWt6%2Bd0eyAKFCLyV2fZoPxETyD7nfOA6hCpI0KonkXodPWYIVvBusOMhld9yqVDbTQmLONm5%2B2w%2BQUXArhvhENy3skKdl6m%2BCc%3D" rel="nofollow">https://argo-workflows.readthedocs.io/en/latest/walk-through/...</a></p><p>[5] Git 仓库</p><p><a href="https://link.segmentfault.com/?enc=m6z6%2FSx3TFxKjk8ph1N%2B1A%3D%3D.poL35Y0bVstKpJgF6FYoUI9uCzB2N4RH%2BkLMfZ3%2FJVcEJPvL%2FDaGqm05SBPRbDqdB%2BJt37eo0kpejweAs8MJ3wnmQWlEDuSsEDoiSyBmZEa%2FAEC5RdaI2vBP5jcR8a7%2F" rel="nofollow">https://github.com/AliyunContainerService/argo-workflow-examples/tree/main/map-reduce</a></p><p>[6] 工作流集群快速入门</p><p><a href="https://link.segmentfault.com/?enc=TvQariiMZh8v0hmQEG7aRQ%3D%3D.4vDS6L%2BffHoIwPda0K93zOICUALeweueZQBU36zYXJyMXmXokcznXJdtLB%2FUtaiq5HBKMbAV%2FdfXzs95H5BkUqnF8N%2BkJzmAAvKxh3kHKAUJRqhOBUzQtN1iSLMEurwNWQNFDEoAVuOaLcV6cvitW3ttdcuoT4huYNiM0d3pyGl91E4YMZk8zjuNd9fxO%2BO9VgWW%2BS%2FABfAnMwjg63hmXQ%3D%3D" rel="nofollow">https://help.aliyun.com/zh/ack/distributed-cloud-container-pl...</a></p><p>[7] SDK</p><p><a href="https://link.segmentfault.com/?enc=sFjmpWRRflBVxm2l9zWhzw%3D%3D.ErlumV20hiCkOw87zYhy9%2BwSv1ffnQhB78kWyH%2F%2BmVMJfhGlhgVrCdWeBtBiZ7mIOtD38FoJjtmQwkDSlzsdlQ%3D%3D" rel="nofollow">https://argoproj.github.io/argo-workflows/client-libraries/</a></p><p>[8] 使用存储卷</p><p><a href="https://link.segmentfault.com/?enc=0vftHfpLYNqWb7w3VKZ0hQ%3D%3D.AcaiPMndgV9Fr5OynRlGWFLPIfnFM7HnqYeLyOhGOrK9dpnU%2BiX2FUf%2FGoefhANjbnAmn2lXqn%2FQ3qNIxRzZlTPMarb93sYJagw6vLrnL2mkYGdP%2B8v9GgqIG9AU%2BsETPoD60w2A3BjhSh6DjUNChj8QjRI34TxX4W1%2FoxdsE%2Fz41TDgfA3lmusgqfjSN4x9" rel="nofollow">https://help.aliyun.com/zh/ack/distributed-cloud-container-pl...</a></p><p>[9] 可观察能力</p><p><a href="https://link.segmentfault.com/?enc=u2HlBkAqPg42CTZaZVcNRA%3D%3D.QTtSETGyD94%2FO6m0rJm9B6eYOqhnvHjZ6x1CbVjlvun7fGigS6%2FHctuV402r49AieF4eyVTIcal0UUdCxnJbtQv5WTWPb%2FcDbKtP9DjwwqrJauZ1wTsDkpr%2FXzLkhMb4AZZrAU%2FXEo1fPrlFECYZPQ%3D%3D" rel="nofollow">https://help.aliyun.com/zh/ack/distributed-cloud-container-pl...</a></p><p>作者:庄宇</p><p><strong><a href="https://link.segmentfault.com/?enc=KWVSYxZ07RSLIQVoxPNgPQ%3D%3D.VicnHLMk3P%2FfVKkeOn9Bhzotk17rNcmAjWnvMdx76gaJZdelikVnrLZnzb2BdAFZkkBrxNIo01OX%2BbXhrc%2FdVQRHysSt8L8VNCfeYEqoSXY%3D" rel="nofollow">原文链接</a></strong></p><p><strong>本文为阿里云原创内容,未经允许不得转载。</strong></p>
Consul 留给你的时间不多了
https://segmentfault.com/a/1190000044602721
2024-01-30T16:02:05+08:00
2024-01-30T16:02:05+08:00
阿里云云栖号
https://segmentfault.com/u/aliyunqi
0
<h2>HashiCorp BSL license 变更</h2><p>在今年的 8 月份 HashiCorp 宣布所有产品和多个库的未来版本将从 Mozilla 公共许可证 v2.0 (MPL 2.0) 过渡到 Business Source License(BSL 或 BUSL)v1.1[1]。</p><p>近期,公司联合创始人 Mitchell Hashimoto 面向全体职员及社区发送了一封告别信,宣布他将从 HashiCorp 离职,我们无法印证这是否与近段时间变更许可协议引起的诸多纷争有关。HashiCorp 是一家专注于 DevOps 工具链的公司,其旗下明星级产品包括 Vagrant、Packer、Terraform、Consul、Nomad、Vault 等,这些产品贯穿了持续交付的整个流程。</p><p>根据 HashiCorp Licensing FAQ[2]显示,本次更改 Business Source 许可证的开源产品包括:HashiCorp Terraform、Packer、Vault、Boundary、Consul、Nomad、Waypoint 和 Vagrant。更改 BSL 许可证之前 Consul 的开源产品主要使用了 MPL 2.0 和 MIT 许可证。在 MPL 许可证下最新版本是 Terraform 1.5.5、Packer 1.9.2、Vault 1.14.1、Boundary 0.13.1、Consul 1.16.1、Nomad 1.6.1、Waypoint 0.11.4。MIT 许可证最新版本是 Vagrant 2.3.7。</p><p>HashiCorp BSL license 变更引发了社区的激烈讨论和反抗。知名 Terraform 增强型工具 Terragrunt 的作者 Yevgeniy Brikman 写了一篇博文《The future of Terraform must be open》[3],他历数了 BSL 协议的三大问题。目前 Terragrunt 威胁发起 OpenTF(而后因为商标问题更名为 OpenTofu)项目[4],创建一个仍旧遵循 MPL 2.0 协议的 Terraform 分叉。</p><p>BSL 许可证的变更不具有追溯性,也就意味着更改之前的所有源代码和版本仍处于 MPL 2.0 许可证之下。我们可以根据原始许可无限期地继续使用这些版本。虽然我们可以一直使用这些变更之前的版本,但是因为老版本无法持续迭代,所以会存在较多的问题影响到业务的稳定性。这些问题主要包括:无法使用较新版本特性和优化,无法修复老版本的 bug,无法及时处置安全漏洞问题。根据其声明,在原 MPL 许可下安全问题修复截止到 2023.12.31。</p><p>我们是否可以继续使用最新的 BSL 许可证的版本呢,下面我们一起了解下 BSL 许可证。</p><h3>使用 BSL 许可证是否有风险?</h3><p>BSL(Business Software License)是一种商业软件许可证,旨在平衡开源和商业利益之间的需求。BSL 许可证最新的版本是 1.1 版本,它是一种混合型许可证,结合了开源软件和闭源软件的特点,它并不属于开源协议,因为并不能满足开源定义[5]中关于“No Discrimination Against Fields of Endeavor”的定义。BSL 许可证规定了一段时间,在此期间内,软件被认为是商业源代码。</p><p>BSL 允许开发者在商业源代码期间提供付费支持和服务,以便在开源之前获得一些商业回报,从而鼓励开发者投入更多的精力和资源进行产品开发。期限届满后,软件许可会转变为一种新的许可证,新许可证需要跟 GPL 兼容的协议,可以是 Permissive 和 Copyleft 开源协议中的任意一个,软件的使用、修改和分发将受到更宽松的限制,更符合传统开源许可证的要求。BSL 许可证允许许可方自定义条款明确约定变更协议的期限和是否可以在附加使用条款中允许客户在其他特定生产环境下使用。</p><p>HashiCorp 并不是第一家使用 BSL 许可证的公司,在此之前 MariaDB,Couchbase,Lightbend,Cockroach Labs 和 Sentry 也采取了相同的做法。因为允许在 BSL 模板中自定义条款,每家公司对于生产环境可使用的限定条款和协议变更的期限也不尽相同,下面针对以上几家公司的 BSL 使用限制做简要的说明。</p><h4>MariaDB</h4><p>MariaDB 下的 MaxScale 产品使用限制[6]:在生产环境中应用节点数不能超过 3 个。限制的是大规模的使用,允许个人和小规模企业用户在有限规模下免费使用,超出 3 个节点需要付费来获得商业许可。</p><blockquote>You may use the Licensed Work when your application uses the Licensed Work with a total of less than three server instances in production.</blockquote><h4>Couchbase</h4><p>Couchbase 下的 Couchbase Lite、KV engine 产品使用限制[7]:简单的说不允许任何方式以有偿或盈利提供服务。限制的是商业使用,使用限制在使用 BSL 许可证产品中是比较友好的。</p><blockquote>(i) You may not prepare a derivative work based upon the Licensed Work and distribute or otherwise offer such derivative work, whether on a standalone basis or in combination with other products, applications, or services (including in any "as-a-service" offering, such as, by way of example, a software-as-a-service, database-as-a-service, or infrastructure-as-a-service offering, or any other offering based on a cloud computing or other type of hosted distribution model (collectively, "Hosted Offerings")), for a fee or otherwise on a commercial or other for-profit basis.<br>(ii) You may not link the Licensed Work to, or otherwise include the Licensed Work in or with, any product, application, or service (including in any Hosted Offering) that is distributed or otherwise offered, whether on a standalone basis or in combination with other products, applications, or services for a fee or otherwise on a commercial or other for-profit basis. Condition (ii) shall not limit the generality of condition (i) above.</blockquote><h4>Lightbend</h4><p>Lightbend 旗下 Akka 是业内久负盛名用于构建高度并发、分布式和具有弹性的面向消息驱动的 Java 和 Scala 应用程序的工具包。BSL 许可证的信息被放置在官网的首屏,非常的显眼。</p><p><img src="/img/remote/1460000044602723" alt="图片" title="图片"></p><p>$$
图 1.1 Akka 官网 BSL 说明
$$</p><p>Lightbend 下的 Akka 产品使用限制[8]: 开发和测试不需要许可,收入小于 2500 万美元的公司可以申请免费许可在生产环境使用,其他情况需要收费许可。限制的是具有一定收入水平的中小公司使用。</p><h4>HashiCorp</h4><p>如文章开头提到的 HashiCorp 在 8 月 10 日宣布,旗下多款产品变更为 BSL 许可证。让我们看下具体的协议内容[9]。</p><blockquote>You may make production use of the Licensed Work, provided Your use does not include offering the Licensed Work to third parties on a hosted or embedded basis in order to compete with HashiCorp's paid version(s) of the Licensed Work.</blockquote><p>HashiCorp 下的 BSL 许可证产品使用限制是:不能以托管或嵌入的方式向第三方提供竞争力的产品,以与 HashiCorp 的付费版本竞争。这个描述不像前面其他几个 case 中提到的规模还是收入限制,表达得那么清晰。如果不清楚是否存在潜在的产品竞争关系,需要发邮件向 HashiCorp 咨询。我们粗略的理解是不能以任何商业的方式提供给第三方,否则就存在法务的风险,具体解释权归 HashiCorp 所有。这对于企业用户在生产环境中使用 HashiCorp 的产品带来了很大的不确定性法务风险。</p><h3>HashiCorp BSL 许可证变更对企业选型带来的思考</h3><p>开源=免费?无论从早期的 Copyleft 类许可证还是近些年流行起来的 BSL 许可证应用案例来看,都充分说明开源并不等于免费,使用开源软件需要遵守许可证中定义的义务。在这些许可证中有的对于分发,商业和生产使用相对宽松,有的则比较苛刻。使用开源软件需要充分理解许可证中定义的限制条款,否则冒然使用将对组织带来法务合规风险。</p><p>对于已经使用了 HashiCorp 非商业版的产品,规避以上产品最好的做法是更换产品的选型。对于目标选型的产品我们需要充分考虑两点:</p><ol><li>功能需求。目标产品能否满足业务的需求,能否完全替代之前产品。</li><li>迁移成本。目标产品的迁移成本有多高,是否可以实现原产品到目标产品的平滑迁移。</li></ol><p>下面我们将针对使用较多 HashiCorp Consul 产品提出一种可行的平滑替代方案,将分别从功能和迁移成本方面描述。</p><h2>Consul 的替代品 Nacos</h2><h3>主流的注册中心的对比</h3><p>Consul 具有注册中心,配置中心和流量管理等功能[10],注册中心功能是国内用户使用最多的功能。寻找其替代品,首先要对市面上主流的注册中心做一个选型的调研对比。以下选取了用户使用较多的注册中心包括:Nacos、Consul、Eureka 和 Zookkeeper。</p><p>选取的指标主要涵盖以下几个方面:</p><ul><li>license 许可</li></ul><p>是否存在商用或生产限制,上文我们已经讲到 HashiCorp BSL 许可证变更给用户生产使用带来了比较大的限制。</p><ul><li>CAP 支持</li></ul><p>CAP 是分布式系统中重要的理论依据,在设计系统时,需要根据业务需求和特定的场景来权衡一致性、可用性和分区容错性的关系,组件要根据业务的属性要求来满足 AP 或 CP 能力。比如金融系统要求更高的一致性保证数据的安全,社交系统可能牺牲一致性来更好的满足用户交互的可用性要求。对注册中心的 AP 或 CP 模型深入理解,大家可以参考文章《阿里巴巴为什么不用 ZooKeeper 做服务发现?》[11]。</p><ul><li>高可靠</li></ul><p>是否具备基本的服务实例健康检查能力,对非健康实例是否能及时注销通知客户端并收敛时间可控,对并发大流量是否具备过载保护能力,是否满足企业的多数据中心容灾的要求,是否支持多个注册中心之间跨区域和同区域同步。</p><ul><li>生态支持</li></ul><p>服务调用框架和注册中心共同构成微服务架构的最小内核,注册中心需要对主流的服务调用框架生态有完善的支持。另外,微服务是云原生架构的基石,而 Kubernetes 已成为云原生架构的标准操作界面,能否与 Kubernetes 生态集成进一步释放技术的红利对于整个 DevOPS 链路至关重要。</p><p><img src="/img/remote/1460000044602724" alt="图片" title="图片"></p><p>$$
图 2.1 注册中心选型对比
$$</p><p>通过上述表格对比来看,Nacos 相对于 Consul、Eureka 和 Zookkeeper 在license、CAP 支持、高可靠和生态上都要胜一筹。下面通过 Nacos 的简要介绍,来揭开 Nacos 的神秘面纱。</p><h3>Nacos 简介</h3><p>Nacos 是一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台,通过提供简单易用的动态服务发现、服务配置、服务共享与管理等服务基础设施,帮助用户在云原生时代,在私有云、混合云或者公有云等所有云环境中,更好的构建、交付、管理自己的微服务平台,更快的复用和组合业务服务,更快的交付商业创新的价值[12]。</p><p>Nacos 架构如下图所示,其架构在客户端接入、通讯层、连接层、功能层、一致性协议和存储层做了抽象,同时通过插件化设计满足不同用户对各类场景的扩展需求。</p><p><img src="/img/remote/1460000044602725" alt="图片" title="图片"></p><p>$$
图 2.2 Nacos 架构
$$</p><p>根据微服务领域问卷调研,国内使用 Nacos 的占有率达到 50% 以上,目前在国内服务注册中心及配置管理领域中市场占有率排名第一,并且各大云厂商纷纷开始提供 Nacos 云服务,侧面印证着 Nacos 用户基础以及快速增长。</p><p>Nacos 社区保持着高速的迭代,Nacos 多次获得 Github 中国区活跃度前十项目,目前已累计发行超过 60 个版本,社区斩获了多项开源大奖。包括 Nacos 被评为云原生领域人气指数 Top5 的项目、InfoQ 2022 年度十大开源新锐项目,近期 Nacos 也荣获由开放原子基金会主办的 “2023 年度生态开源项目”奖项,以及由中国科协科学技术传播中心、中国计算机学会、中国通信学会、中国科学院软件研究所共同主办 “2023 开源创新榜的优秀开源项目” 奖项。并且 Nacos 社区发布电子书《Nacos 架构与原理》收获 19w+ 阅读,5w+ 下载量,现已被大量各行各业的公司选型作为其注册配置中心。</p><p><img src="/img/remote/1460000044602726" alt="图片" title="图片"></p><p>$$
图 2.3 Nacos 开源获奖图
$$</p><h2>如何将 Consul 平滑迁移至 Nacos</h2><p>如何将 Consul 平滑迁移至 Nacos,Nacos Sync 为迁移提供了工具支持。</p><h3>为什么需要 Nacos Sync?</h3><p>对于服务来说分为服务 Provider 和服务 Consumer 两种角色,这两种角色如下图都对注册中心产生了依赖,对于微服务的 Provider 和 Consumer 往往由两个团队来维护,无法做到同步迭代做改造。另外,服务的发布也往往无法做到同时发布,如果任意一方直接迁移到 Nacos,另外一方未及时完成改造和发布,将会对业务的连续性造成影响。Nacos Sync 可以将服务的注册和发现两个过程实现对同一注册中心的解耦。</p><p><img src="/img/remote/1460000044602727" alt="图片" title="图片"></p><p>$$
图 3.1 服务注册和发现模型图
$$</p><p>整体迁移过程如下:</p><ol><li>安装 Nacos Sync 完成 Consul 至 Nacos 的服务同步。</li><li>服务 Consumer 改造配置,服务发现指向 Nacos。若出现问题,回滚服务 Consumer 的发布。</li><li>服务 Provider 改造配置,服务注册指向 Nacos。若出现问题,回滚服务 Provider 的发布。</li><li>确认无问题后,下线 Nacos Sync 和 Consul。</li></ol><h3>Nacos Sync 简介</h3><p>Nacos Sync 是一个支持多种注册中心的同步组件,基于 Spring boot 开发框架,数据层采用 Spring Data JPA,遵循了标准的 JPA 访问规范,支持多种数据源存储[13]。</p><p>Nacos Sync 使用了高效的事件异步驱动模型,支持多种自定义事件,使得同步任务处理的延时控制在 3s,8C16G 的单机能够支持 6K 的同步任务。目前已支持以下注册中心源端到目标端的同步:</p><ul><li>Nacos 数据同步到 Nacos</li><li>Zookeeper 数据同步到 Nacos</li><li>Nacos 数据同步到 Zookeeper</li><li>Eureka 数据同步到 Nacos</li><li>Consul 数据同步到 Nacos</li></ul><p><img src="/img/remote/1460000044602728" alt="图片" title="图片"></p><p>$$
图 3.2 Consul 同步 Nacos 架构图
$$</p><h3>如何使用 Nacos Sync 平滑迁移</h3><p>MSE 注册配置中心提供了 Nacos 的全托管集群,您无需关注引擎的资源购买、监控、运维和容灾问题,只需专注于业务开发,无需部署运维[14]。MSE 控制台提供了 Consul 至 Nacos 迁移的白屏化支持,使用户简单的两步操作即可完成服务的同步。</p><p>从 Consul 至 MSE Nacos,主要分为两个步骤:</p><ol><li>评估规格。确定 MSE Nacos 的容量规则满足业务的使用需要。</li><li>迁移上云。安装 Nacos Sync 工具,白屏化配置源端 Consul 到 MSE Nacos 的配置,完成服务的平滑同步。</li></ol><h4>步骤一:评估规格</h4><ol><li>登录 MSE 注册配置中心管理控制台,并在顶部菜单栏选择地域。</li><li>在左侧导航栏,选择注册配置中心 > 迁移上云。</li><li>在迁移上云页面,单击规格评估,在规格评估面板,配置相关参数,然后单击评估规格。</li></ol><p><img src="/img/remote/1460000044602729" alt="图片" title="图片"></p><p>$$
图 3.3 MSE 注册中心评估图
$$</p><p>在当前的规格评估页面顶部,系统将根据评估结果,生成购买链接和推荐购买的实例规格。</p><ol start="4"><li>单击购买 MSE 实例链接,在购买页面配置 VPC 和网络等信息,在仔细确认信息无误后,单击立即购买。</li></ol><h4>步骤二:迁移上云</h4><ol><li>登录 MSE 注册配置中心管理控制台,并在顶部菜单栏选择地域。</li><li>在左侧导航栏,选择注册配置中心 > 迁移上云。</li><li>在迁移上云页面,单击迁移配置,在迁移配置面板,根据页面向导配置参数。</li></ol><p>a. 在部署工具阶段,根据控制台操作步骤部署迁移工具。完成迁移工具部署后,单击下一步。<br>迁移工具可通过容器或 Tar 包两种方式部署。具体部署详情,请参见 MSE Sync 迁移方案。<br>b. 在创建配置阶段,配置相关参数,然后单击下一步。</p><p><img src="/img/remote/1460000044602730" alt="图片" title="图片"></p><p>$$
图 3.4 Nacos Sync 配置参数图
$$</p><p>通过以上白屏化参数的配置,将为 Nacos Sync 自动生成 Consul 到 MSE Nacos 的同步配置,也可以自行通过 Nacos Sync 控制台手动导入同步配置。配置格式如下:</p><pre><code>clusters:
- clusterName: dst
connectKeyList:
- {nacos.endpoint}:8848
clusterType: NACOS
- clusterName: src
connectKeyList:
- {consul.endpoint}:8500
clusterType: CONSUL
namespace: ''
tasks:
- source: src
destination: dst</code></pre><p>c. 在实施迁移阶段,执行控制台的操作步骤。</p><p>通过以上简单两步就完成了 Consul 至 Nacos 的服务同步。服务 Consumer 和 Provider 择期完成直接使用 Nacos 注册中心的代码配置改造。</p><h2>结语</h2><p>本文主要介绍了 HashiCorp BSL license 变更对于用户商业或生产使用带来的潜在风险,注册中心的选型对比,如何使用 MSE Nacos 替换 Consul 消除潜在的风险。</p><p>最后,提醒正在使用 HashiCorp 旗下开源产品如 Consul(原遵循 MPL 许可证)的用户,这些产品将不再继续维护,留给你的时间已经不多了。</p><p><strong>相关链接:</strong></p><p>[1] Business Source License(BSL 或 BUSL)v1.1</p><p><a href="https://link.segmentfault.com/?enc=c68gA7oiChogxFhpAm028A%3D%3D.wHIDcIIgYBH%2F12Q88%2F0uDNb%2BsfJuIGvbj3teHtEQwx3F5B0FECagxe3CxHSxvUDuelcHrXm%2BK4K3MK7hgHe4%2BfIz3ieTtU77jO4LUPGSl1A%3D" rel="nofollow">https://www.hashicorp.com/blog/hashicorp-adopts-business-sour...</a></p><p>[2] HashiCorp Licensing FAQ</p><p><a href="https://link.segmentfault.com/?enc=zTU8IeqbmWC6j3XsJQ0LOg%3D%3D.QtI3R80x38fslPPCJPUHcwmlIlnsnYLRAbPLLIB0L9lOwPe3oCYQFBhYUUmVb3sl" rel="nofollow">https://www.hashicorp.com/license-faq</a></p><p>[3] 《The future of Terraform must be open》</p><p><a href="https://link.segmentfault.com/?enc=cl7DPrSBf725a8c9MSmpgg%3D%3D.IBwu3RWNYjI3RQqYv%2FlQaSz7mfnEmQunkNCp2oWcW2KEC83oQG2qAefXXlLi7rigtWk9jhJAR4IHHwRABorACvTfpD2HYzgMMF%2FdloqclH4%3D" rel="nofollow">https://blog.gruntwork.io/the-future-of-terraform-must-be-ope...</a></p><p>[4] OpenTofu 项目</p><p><a href="https://link.segmentfault.com/?enc=%2FE%2BYx4bHHtYSoMR%2BSD%2BUBg%3D%3D.BBTGGiAT7P7UIuOi9whdtc%2B7lmfE6iSoweD9jsF8y%2Bc%3D" rel="nofollow">https://opentofu.org/</a></p><p>[5] 开源定义</p><p><a href="https://link.segmentfault.com/?enc=iJtFmItK4nYrWJWpvGjqYA%3D%3D.aUjRzjK7Y7Qehn7AQAiitsQJxVsI5uodbl2w6j5CJqgRl%2FgEQ9WflNEI6RdoCkGO" rel="nofollow">https://opensource.org/definition-annotated/</a></p><p>[6] MaxScale 产品使用限制</p><p><a href="https://link.segmentfault.com/?enc=CyruPpLDcOjfazx2cZlveA%3D%3D.SfV3Nwr1BLqkyYOt33lZH0A7S35WxNF0wBz72XJZT%2FPSEP25yMP6DJ31gBDeUieW" rel="nofollow">https://mariadb.com/projects-using-bsl-11/</a></p><p>[7] Couchbase Lite、KV engine 产品使用限制</p><p><a href="https://link.segmentfault.com/?enc=lhS8PRV6ySZcD%2BIqtihIOQ%3D%3D.XFMgPAhelTDFl5TJMXETOD5eB7NXExePaN6Dgn%2B0NC3l4jli%2FBkqcKOTEOwZJRuXS7%2Fnoj0s5jg7nCOBeIp9r4Z1affOZWXaoihoFufYVV%2BSePQrU97aKH9UWisy88hp" rel="nofollow">https://github.com/couchbase/couchbase-lite-core/blob/master/licenses/BSL-Couchbase.txt</a></p><p>[8] Akka 产品使用限制</p><p><a href="https://link.segmentfault.com/?enc=Aqzc2c1S%2BhoGif11jcmdzQ%3D%3D.g7dOc7WuGkISil%2FUXxzmaw6LfEyV%2FYU%2BrSQsL986FTI%3D" rel="nofollow">https://akka.io/</a></p><p>[9] 协议内容</p><p><a href="https://link.segmentfault.com/?enc=EYjWGAt9cZHVFbs4apJ9Cg%3D%3D.bYG0hSJJZkhYbFAhNTFEpKRoq9FQdU6VOvQEqAt61sQTO2ZuBxV1YS%2F2N9H1styg06Nk7we7MpItu3e5okZxUw%3D%3D" rel="nofollow">https://github.com/hashicorp/consul/blob/main/LICENSE</a></p><p>[10] Consul 具有注册中心,配置中心和流量管理等功能</p><p><a href="https://link.segmentfault.com/?enc=WlNAnBKaHffCreRb1Hux9w%3D%3D.uuT3LxZnmevAxzGy0YlNHnIckws0iX%2FJOwrFLaAVFxdFXMnjYnWAhHbxGiR%2BzmY5w5qF%2FQCGQtHqQ%2F7GyAJb9Q%3D%3D" rel="nofollow">https://developer.hashicorp.com/consul/docs/intro</a></p><p>[11] 《阿里巴巴为什么不用 ZooKeeper 做服务发现?》</p><p><a href="https://link.segmentfault.com/?enc=aB2omX3slj2fBgzEIg53YA%3D%3D.HQDC7lKzLgeL1hE5YRqeEPlcVMpLoaAQyWOSguf14zJLjBeFW6ZiLd9alDCRqJeC" rel="nofollow">https://developer.aliyun.com/article/601745</a></p><p>[12] Nacos</p><p><a href="https://link.segmentfault.com/?enc=WFlxsE2ac2jkWXQn9d1Gng%3D%3D.oZnZFGBVZoRffv70O1lcD2WArZm3XvVYU0pj83KhY%2Bo%3D" rel="nofollow">https://nacos.io/zh-cn/</a></p><p>[13] Nacos Sync</p><p><a href="https://link.segmentfault.com/?enc=5lApKj36wV2wPju8c43T0g%3D%3D.E68YairJzH9PMmaE6gF25dtnUNjweTA1KC1P8rR0%2Fr7s1l3vbbktolFrwOZsooPfG2YrBAk%2Bc79rPqSWsWNgIw%3D%3D" rel="nofollow">https://nacos.io/zh-cn/docs/v2/ecology/use-nacos-sync.html</a></p><p>[14] 微服务引擎 MSE</p><p><a href="https://link.segmentfault.com/?enc=7hkiv6o0drSsc%2B8sMWnhcA%3D%3D.RlImPAMH%2FMese5s2e9PGRhwnP9bxhfvTX92xzFp6fkK7iMoseK154oHm0QCEg3Z6" rel="nofollow">https://www.aliyun.com/product/aliware/mse</a></p><p>作者:季敏</p><p><strong><a href="https://link.segmentfault.com/?enc=Brk61QEX21fm2AHP8pjY6A%3D%3D.lmHYE%2Fzz1qcD6qYod11%2BU2eGUSSD7%2Fv1Mp3%2Fg460G1NNy3TjzE5T9asVsEBfNhCsY6kOh%2BfZsLpbJnnVNb2NASd96U%2Bmv%2F8ruM7p8E%2BJleU%3D" rel="nofollow">原文链接</a></strong></p><p><strong>本文为阿里云原创内容,未经允许不得转载。</strong></p>
定向减免!函数计算让轻量 ETL 数据加工更简单,更省钱
https://segmentfault.com/a/1190000044598423
2024-01-29T16:06:36+08:00
2024-01-29T16:06:36+08:00
阿里云云栖号
https://segmentfault.com/u/aliyunqi
0
<p>业内较为常见的高频短时 ETL 数据加工场景,即频率高时延短,一般均可归类为调用密集型场景。此场景有着高并发、海量调用的特性,往往会产生高额的计算费用,而业内推荐方案一般为攒批处理,业务实时性会有一定的影响。基于此痛点,函数计算 FC 推出定向减免方案,让 ETL 数据加工更简单、更自动化、容错能力更强,且业务实时性更高、计算费用更低。</p><p>自 2024 年 01 月 01 日 0 时起,函数计算定向减免来自阿里云消息类产品和云工作流(CloudFlow)的函数调用次数费用,即通过以上产品事件触发函数计算所产生的函数调用次数不再计入费用账单。定向减免函数调用次数费用的产品包括:</p><ul><li>阿里云消息类产品:</li><li>消息服务 MNS</li><li>云消息队列 RocketMQ 版</li><li>消息队列 RabbitMQ 版</li><li>云消息队列 Kafka 版</li><li>云消息队列 MQTT 版</li><li>事件总线 EventBridge</li><li>云工作流(CloudFlow)</li></ul><h2>这样用 FC,ETL 场景可立省 87% 计算费用</h2><p>某出行领域客户基于函数计算 FC 构建免运维、自动化的 ETL 数据加工场景如下:</p><p>每天处理 10 亿条 Kafka 消息数据,每次处理平均耗时 10 毫秒,算力规格 0.1c0.5g,其费用组成为:</p><ol><li>vCPU 使用量:0.1 <em> 1000000000 </em> 0.01 * 0.00009 = 90 元</li><li>内存使用量:0.5 <em> 1000000000 </em> 0.01 * 0.000009 = 45 元</li><li>函数调用次数费用:1000000000 / 10000 * 0.009 = 900 元</li></ol><p>注意:以上均按照函数计算阶梯计费的阶梯0单价进行计价,忽略免费额度,定价参考:</p><p><img src="/img/remote/1460000044598425" alt="图片" title="图片"></p><p><img src="/img/remote/1460000044598426" alt="图片" title="图片"></p><p><img src="/img/remote/1460000044598427" alt="图片" title="图片"></p><p>若定向减免该 ETL 场景下的函数调用次数费用,则该 ETL 场景可立省 87% 计算费用!(不同场景的降本数字需结合实际业务需求进行测算。)</p><h2>基于函数计算 FC 的热门 ETL 场景</h2><h3>数据投递分析</h3><p>在数据投递分析场景中,函数计算可以为用户的投递以及数据分析提供高自由度的模板能力和自定义能力,提供海量下游投递能力。</p><p><img src="/img/remote/1460000044598428" alt="图片" title="图片"></p><h3>数据加工清洗转存</h3><p>数据清洗加工和转存场景,函数计算可以提供数据 Transform 处理能力,供数据加工。</p><p><img src="/img/remote/1460000044598429" alt="图片" title="图片"></p><h3>业务消息处理</h3><p>函数计算 FC 有丰富的事件响应场景,消息作为事件驱动的重要数据源,可以驱动函数计算执行一系列业务逻辑,构建完整的事件驱动架构。</p><p><img src="/img/remote/1460000044598430" alt="图片" title="图片"></p><h2>立即开始</h2><h3>阿里云消息类产品</h3><p>函数计算 FC 和阿里云消息产品家族通过产品集成,只需要简单“点点点”即可实现自动化、高可用的弹性消息 ETL 方案,大幅简化了 ETL 任务的难开发、难运维的痛点。</p><h4>Connector 生态集成</h4><p>在 Kafka、RocketMQ、RabbitMQ 控制台配置 Connector 实现消息 ETL 任务,选择函数计算 FC 模板即可实现预置过滤、转换、投递等基础需求。如若需要实现更自定义的转换需求,也可以在函数计算 FC 控制台创建事件函数进行定制开发,然后在 Connector 界面选择指定的函数即可运行特定 ETL 任务。</p><p>同时,也可以通过此类 ETL 任务实现消息数据快速投递至存储、大数据等,实现数据转储需求。</p><p><img src="/img/remote/1460000044598431" alt="图片" title="图片"></p><p><img src="/img/remote/1460000044598432" alt="图片" title="图片"></p><p><img src="/img/remote/1460000044598433" alt="图片" title="图片"></p><h4>EventBridge 事件流</h4><p>在 EventBridge 控制台配置事件流,快速创建消息队列、数据库等数据 ETL 任务,选择函数计算 FC 模板即可实现预置过滤、转换、投递等基础需求。如若需要实现更自定义的转换需求,也可以在函数计算 FC 控制台创建事件函数进行定制开发,然后在 Connector 界面选择指定的函数即可运行特定 ETL 任务。</p><p>同时,也可以通过此类 ETL 任务实现消息数据快速投递至存储、大数据等,实现数据转储需求。</p><p><img src="/img/remote/1460000044598434" alt="图片" title="图片"></p><h3>云工作流 CloudFlow</h3><p>云工作流(CloudFlow)是用来协调多个分布式任务执行的全托管 Serverless 云服务,简化开发、运行业务流程需要的任务协调、状态管理和错误处理等繁琐工作。云工作流配合函数计算 FC 支持简单拖放即可实现复杂业务流程,无需编写代码,即可编排 300+ 云服务实现工作流程自动化,实现流程式编程新范式。</p><p>下面是云工作流,函数计算 FC 搭建一个高可用的数据处理流水线的最佳实践:</p><p>来自不同数据源的计量数据被收集到日志服务,函数计算 FC 的定时器每小时触发工作流,云工作流利用函数计算 FC 对多个 Shard 的计量数据做并行处理,并将结果分别写回日志服务服务;然后可以将所有 Shard 产生文件进行聚合,写入表格存储 OTS,最后为每个用户生成账单。工作流支持对流程中的单个步骤失败进行重试,降低流程失败概率。工作流支持动态并行任务执行,实现数据处理能力的高可扩展性。</p><p><img src="/img/remote/1460000044598435" alt="图片" title="图片"></p><h2>铭师堂峰值流量破万后的实时 ETL 任务解决方案</h2><h3>业务背景</h3><p>杭州铭师堂,一家在线教育高科技企业,成立十余年来一直致力于用“互联网+教育”的科技手段让更多的学生能享有优质的教育。学生做完作业后,会将作业拍照,然后上传到作业批阅系统,后端系统此时会有多个动作:</p><ol><li>将作业照片上传到 OSS;</li><li>将用户作业信息落到数据库;</li><li>发送消息到 Kafka,通过 Kafka Connector 驱动实时 ETL 任务。</li></ol><p>该 ETL 任务承载了所有的处理逻辑,通过图像识别和数据分类算法,自动识别作业的完成情况。在一年的大多数时间里,业务流量都比较平稳,但在寒暑假时,一般会迎来一年中的高峰,在 2022 年暑假期间,平均每天需要处理 100 多万条作业图片处理,峰值流量更是达到了万级别。</p><h3>业务痛点</h3><p>铭师堂的 ETL 任务原先部署在 Kubernetes (简称 K8s),通过订阅 Kafka 的 topic,获取数据路径,从 OSS 获取数据进行处理,涉及到数据并发度的处理,主要存在两方面问题:</p><ol><li>Kafka 消费端并发度受限于 topic partition,消费端数最多只能跟 partition 数齐平,超过时会导致部分消费端无法订阅数据;</li><li>消费端将消费到的数据进行 ETL,K8s 方案铭师堂在实现时将消费端数和 partition 保持一致,但因为 K8s 的弹性策略相对滞后,平峰时问题不大,但高峰期因弹性不足会经常导致任务堆积,实时性无法保证。</li></ol><p>为了保证 ETL 任务的实时性,铭师堂架构组一直在寻求一种弹性能力更强的新架构。经过实测对比,基于阿里云函数计算 FC 构建的实时 ETL 任务解决方案是最适配铭师堂业务需求,且弹性能力最强、成本最优的选择。</p><h3>解决方案</h3><p><img src="/img/remote/1460000044598436" alt="图片" title="图片"></p><p>铭师堂基于函数计算构建的实时 ETL 任务解决方案步骤如下:</p><ol><li>用户提交作业出发提交流程,将请求打到后端服务;</li><li>后端服务将用户提交的作业图片上传到 OSS,并将 OSS 地址作为一条消息发送到 Kafka;</li><li>函数计算的 Kafka 触发器实时的感知 Kafka topic,当有新数据到达,实时触发函数处理;</li><li>函数计算获取到事件数据,从 OSS 获取数据,并对数据进行处理,将处理结果发回到 Kafka topic;</li><li>后端程序订阅 Kafka topic,对处理结果进行存储和下一步的展示。</li></ol><h3>业务收益</h3><p>以上解决方案整体开发流程顺利,项目上线后有超出预期的收益:</p><ul><li>执行时间快</li></ul><p>业务高峰期,对比 K8s 方案,单请求响应时延 100~200ms,函数计算 FC 方案则维持在 50ms 左右,大大超出预期。经过分析,主要原因在于函数计算 FC 资源隔离,每个任务实例均独占计算资源,高峰期突发流量来临时也不会出现资源争抢,ETL 任务的执行性能得到保障;</p><ul><li>弹性效率高</li></ul><p>K8s 方案依赖 metrics 数据“滞后”地执行 HPA 策略调度资源,而 FC 方案则依赖任务并发“提前”实时调度资源。业务高峰期,正在执行的 ETL 任务独占实例,而新任务则通过 FC 的“百毫秒弹性能力”实时拉起新实例,FC 会最大化地复用实例,减少因为“冷启动”而带来的实时性、利用率损耗;</p><ul><li>提效还降本</li></ul><p>对比 K8s 方案需要预留和管控资源水位,基于 FC 的实时 ETL 任务解决方案实现了按需调度、按量付费,没有任务时资源缩 0,高峰期按业务需求实时调度资源,利用率大大提升。且函数计算 FC 定向减免来自阿里云消息队列 Kafka 的函数调用次数费用,业务成本得到进一步优化。</p><p>铭师堂将业务上线到函数计算 FC 后,很好地解决了 K8s 方案高峰期的任务堆积问题,且通过函数计算 FC 内置的监控和日志服务,问题排查效率也得到提升。当然最重要的一点,铭师堂通过函数计算 FC 的实时弹性,不再需要提前规划资源、预留水位、冗余备份,资源成本大幅降低。</p><p><img src="/img/remote/1460000044598437" alt="图片" title="图片"></p><p><strong>链接汇总:</strong></p><p>计费详情</p><p><a href="https://link.segmentfault.com/?enc=KR7ykymbO6VwJF80oQvopg%3D%3D.iEUWx30Dl%2FQONBmorNZAwBmWk%2B3lpSVi%2BUgJ6GGLbIl9SkCVP0aZ544aJbQqviIhk61DovBzfK%2BFwZ8VWFva6A%3D%3D" rel="nofollow">https://help.aliyun.com/zh/fc/product-overview/billing-overview</a></p><p>函数计算官网</p><p><a href="https://link.segmentfault.com/?enc=3vdPqdWekiN0QfsYP5HhUw%3D%3D.sniTs%2BqLu18OWzhXBER8f2RWLgU%2BBBGLgeQhBfrvQ1c9P9A8M8k5c3dXorE%2Bg435" rel="nofollow">https://www.aliyun.com/product/fc</a></p><p>作者:澈尔、墨飏</p><p><strong><a href="https://link.segmentfault.com/?enc=pNUOwYeVjvFztJ6hIhTYpw%3D%3D.vJJ5RQLsSxOgd1s%2FlOUiESJRIwp%2BfQsqfbm%2BRLYdZkmI0Zqyp0e2I1gD%2BJAA6aY6v5Hv%2FnVKTGpAOuASSu%2FVdhR%2FoZDAeTZ4kGajC3RtYNg%3D" rel="nofollow">原文链接</a></strong></p><p><strong>本文为阿里云原创内容,未经允许不得转载。</strong></p>
秒速出图!体验 TensorRT 加速 Stable Diffusion 图像创作
https://segmentfault.com/a/1190000044598007
2024-01-29T14:32:24+08:00
2024-01-29T14:32:24+08:00
阿里云云栖号
https://segmentfault.com/u/aliyunqi
0
<h2>TensorRT 如何加速 Stable Diffusion?</h2><p>生成式 AI 图像内容生成技术近年来发展迅速,可以根据人类语言描述生成图片,在时尚、建筑、动漫、广告、游戏等领域有着广泛应用。</p><p>Stable Diffusion WebUI 是 Github 上最为热门的利用生成式 AI 进行图像生成的项目。它采用 ClipText 对文字进行编码,然后采用 UNet+Scheduler 在潜在表示空间(latent space)上进行 Diffusion,最后采用 Autoencoder Decoder 将第二步生成的扩散信息再转为图像。</p><p><img src="/img/remote/1460000044598009" alt="图片" title="图片"></p><p>$$
Stable Diffusion Pipeline
$$</p><p>Diffusion 模型最大的痛点是生成图片的速度过慢。Stable Diffusion 采用了多种方式加速图片生成,令实时图像生成成为可能。Stable Diffusion 使用编码器将图片从 3<em>512</em>512 转为 4<em>64</em>64,极大地降低了计算量。它在潜在表示空间(latent space)上进行 Diffusion 过程,大大减少计算复杂度,同时也能保证不错的图片生成效果。在 GPU 上大约 4s 可以生成一张描述复杂的图片。</p><p>对于很多 ToC 应用来说,一张图片生成需要 4s 耗时仍然过长。TensorRT 是由 NVIDIA 提供的高性能深度学习推理框架,通过优化编译器和 runtime 来提升延迟敏感应用的并发度。TensorRT 可以优化几乎所有的深度神经网络,包括 CNN、RNN 和 Transformer。具体优化措施包括以下 6 点。</p><ul><li>减少混合精度,支持 FP32、TF32、FP16 和 INT8</li><li>优化 GPU 内存带宽</li><li>自动调整核函数,为目标 GPU 选择最佳的算法</li><li>动态 Tensor 内存分配,提升内存使用效率</li><li>可扩展设计以处理多个计算流</li><li>时间融合:随着时间步长优化 RNN</li></ul><p>TensorRT 的基本流程如下图所示,可以分为构建期和运行期。</p><p><img src="/img/remote/1460000044598010" alt="图片" title="图片"></p><p>$$
TensorRT Pipeline
$$</p><h2>基于阿里云容器服务 ACK 的实战体验</h2><h3>云原生 AI 套件</h3><p>云原生 AI 套件是阿里云容器服务 ACK 提供的云原生 AI 技术和产品方案,帮助企业更快、更高效地落地云原生 AI 系统。</p><p>本文将介绍如何基于阿里云容器服务 ACK 云原生 AI 套件,利用 TensorRT 加速 Stable Diffusion 图像生成。</p><h3>环境配置</h3><ol><li>参考文档安装云原生 AI 套件[1]。</li><li>登陆容器服务管理控制台[2],在左侧导航栏选择集群 > 应用 > 云原生 AI 套件。等待开发控制台准备就绪后,单击开发控制台。</li><li>在开发控制台左侧,选择 Notebook,在 Notebook 页面右上角,单击创建 Notebook 创建新的 Notebook 环境。Notebook 资源需要 CPU:16C,内存:32G,GPU 显存:16GB。</li></ol><p><img src="/img/remote/1460000044598011" alt="图片" title="图片"></p><h3>准备 Stable Diffusion + TensorRT 环境</h3><ol><li>在新建的 Notebook 中输入以下命令安装所需依赖。</li></ol><pre><code>! pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple
! pip install --upgrade "torch <2.0.0"
! pip install --upgrade "tensorrt>=8.6"
! pip install --upgrade "accelerate" "diffusers==0.21.4" "transformers"
! pip install --extra-index-url https://pypi.ngc.nvidia.com --upgrade "onnx-graphsurgeon" "onnxruntime" "polygraphy"
! pip install polygraphy==0.47.1 -i https://pypi.ngc.nvidia.com</code></pre><ol start="2"><li>下载数据集</li></ol><pre><code>import diffusers
import torch
import tensorrt
from diffusers.pipelines.stable_diffusion import StableDiffusionPipeline
from diffusers import DDIMScheduler
# 默认从huggingface下载,如果机器无法访问huggingface,也可以使用本地模型。
# 如使用本地模型,替换runwayml/stable-diffusion-v1-5为本地模型地址即可
model_path = "runwayml/stable-diffusion-v1-5"
scheduler = DDIMScheduler.from_pretrained(model_path, subfolder="scheduler")</code></pre><ol start="3"><li>使用 TensorRT 生成序列化网络 (计算图 TRT 的内部表示)</li></ol><pre><code># 使用自定义的pipeline
pipe_trt = StableDiffusionPipeline.from_pretrained(
model_path,
custom_pipeline="stable_diffusion_tensorrt_txt2img",
revision='fp16',
torch_dtype=torch.float16,
scheduler=scheduler,
)
# 设置缓存地址
# 会在缓存地址下生成engine文件夹,包含clip.plan、unet.plan、vae.plan文件。A10上首次生成plan文件需要约35分钟
pipe_trt.set_cached_folder(model_path, revision='fp16')
pipe_trt = pipe_trt.to("cuda")</code></pre><ol start="4"><li>使用编译后的模型进行推理</li></ol><pre><code># 生成图片
prompt = "A beautiful ship is floating in the clouds, unreal engine, cozy indoor lighting, artstation, detailed, digital painting, cinematic"
neg_prompt = "ugly"
import time
start_time = time.time()
image = pipe_trt(prompt, negative_prompt=neg_prompt).images[0]
end_time = time.time()
print("time: "+str(round(end_time-start_time, 2))+"s")
display(image)</code></pre><p>生成单张图片耗时为 2.31s。</p><h3>性能测试</h3><p>性能测试基于 Github 上的 lambda-diffusers[3]项目,prompt 数量为 1,batch_size 为 50,重复 100 次。GPU 型号为 A10,对应的 ECS 规格为 ecs.gn7i-c8g1.2xlarge。</p><p><img src="/img/remote/1460000044598012" alt="图片" title="图片"></p><p><img src="/img/remote/1460000044598013" alt="图片" title="图片"></p><p>从实验结果看,开启 xformers 和 TensorRT 优化后,Stable Diffusion 图片生成时间平均减少 44.7%,显存减少 37.6%。</p><p><strong>参考文献:</strong></p><p>TensorRT</p><p><a href="https://link.segmentfault.com/?enc=c5tiPH%2BLcGzXS45u8rbDhQ%3D%3D.45jiP8%2BZ006Zkm6adohD5APJ5fKRcsHh1OZSzH0L%2Bh6PFl6ZcaFd9OpbKLHCexkH" rel="nofollow">https://github.com/NVIDIA/TensorRT</a></p><p>Stable Diffusion WebUI</p><p><a href="https://link.segmentfault.com/?enc=Av%2BI8OTsCvnpy2WMdkwRAw%3D%3D.BFwFFaFqrGmdJu%2FLikl3O51biiCuO5bKmRkkRK4v3vr5TxW%2F%2Fl%2F7ChU9QYvuPDomJxyQ5p0zWIGjseTIyNogJQ%3D%3D" rel="nofollow">https://github.com/AUTOMATIC1111/stable-diffusion-webui</a></p><p>利用 GPU 加速生成式 AI 图像内容生成</p><p><a href="https://link.segmentfault.com/?enc=B9cm3sclarT9AyanjnzIlw%3D%3D.JCGJEPqUEQyUO6mCyN1wm0BayDWNX9dbz4zLo%2B63fJ4HMSVeRL8%2BQc5y4beMSWdBHciL95xj6oahs7R2exdWdIlAJAQUBO1z9QFCan8MmVQ%3D" rel="nofollow">https://www.nvidia.cn/webinars/sessions/?session_id=230919-29256</a></p><p><strong>相关链接:</strong></p><p>[1] 安装云原生 AI 套件</p><p><a href="https://link.segmentfault.com/?enc=rBULLbyx%2FcpcUl%2BeTFVASw%3D%3D.8q2m596BbrkTHwqstrlhDPPgiNS%2BjoU0iOk210bF01RyrfHctuYivr%2B0F%2BWTkfKEDdkESaGt6kTgS1NMdtwX%2F4WHv8lo0bBcxXCwWCXspirdwV6l2ISPWQY61q2o26XA00nLbEoRj6JpBPlYKobD30ia1AO7TO8jE9Z0o4O%2B0n0CkJ%2BBsWro6wg1SKxCo3Jr" rel="nofollow">https://help.aliyun.com/zh/ack/cloud-native-ai-suite/user-gui...</a></p><p>[2] 容器服务管理控制台</p><p><a href="https://link.segmentfault.com/?enc=fgZILNaLcUX7Xo3fwTUJ2w%3D%3D.iSsns4jiDTOhyxzzzBpprIrT8fxq2E6W1YVHW6Sg4%2FNNdgxyPOGua5jy70RfXN%2BDEUuk%2FLJdwSeN2d562iQjgl9FiCOB4s2ZTtYpDboMfeX6KBxCbZHB3B4Tc0tHUK%2Fh8%2BMFv5mKCN7SFk%2Bygc5phQ%3D%3D" rel="nofollow">https://account.aliyun.com/login/login.htm?oauth_callback=htt...</a></p><p>[3] lambda-diffusers</p><p><a href="https://link.segmentfault.com/?enc=nXgHoCH0X5KRUzAIDHHA%2Fw%3D%3D.UB8Hm6SYt2gwAYw8SastwlkntfzrZY3vEJ51Dw002v7yVcCPcrSxLKgj67ZaFDRQKlA56117jtKm6ngvDC1E9A%3D%3D" rel="nofollow">https://github.com/LambdaLabsML/lambda-diffusers</a></p><p>作者:顾静</p><p><strong><a href="https://link.segmentfault.com/?enc=pRQL1guyRkv%2B4H7NuLsVjw%3D%3D.ynQp3vZ5R5VURyBNBZhOsDg83%2Fm93V3UD%2FvkNcU7%2F%2FTnMiBb9duecad2SwYe0DFGGOymdTlIcUfDReSxUFYdxWQb25BVLbJ06NJkUPLAmTQ%3D" rel="nofollow">原文链接</a></strong></p><p><strong>本文为阿里云原创内容,未经允许不得转载。</strong></p>
阿里云 SAE 2.0 正式商用:极简易用、百毫秒弹性效率,降本 40%
https://segmentfault.com/a/1190000044597136
2024-01-29T10:56:29+08:00
2024-01-29T10:56:29+08:00
阿里云云栖号
https://segmentfault.com/u/aliyunqi
0
<p>本文主要介绍阿里云 Serverless 应用引擎(以下简称 SAE )如何帮助企业跨越技术鸿沟,从传统应用架构无感升级到 Serverless 架构,以更高效、更经济的方式进行转型,快速进入云原生快车道,让 2 人的研发团队享受 2000 人技术团队的红利。</p><h2>打破 Serverless 落地边界,SAE 1.0 让大规模微服务 on Serverless 触手可及</h2><p>早在 2018 年的 11 月,阿里云 SAE 作为业界首款面向应用的 Serverless PaaS 产品孵化诞生,产品初衷是帮助 PaaS 层用户屏蔽 K8s 复杂度、降低成本提升弹性效率。SAE 以应用为中心,提供了面向应用的 UI 和 API,不改变应用编程模型和部署方式,保持了客户在传统服务器上一致的开发部署体验,还能方便的进行本地开发调试/监控,极大地降低了客户使用 Serverless 的门槛,能做到零改造平滑迁移企业在线应用,零门槛容器化。</p><p>SAE 的出现帮助 Serverless 从专用到通用,让 All on Serverless 成为可能。它打破了 Serverless 的落地实施边界,使得 Serverless 不再是前端全栈、小程序的专宠,后台微服务、SaaS 服务、物联网应用等一样也可以构建在 Serverless 之上,天然适合企业核心业务的大规模落地。凭借 Serverless PaaS 的先发优势,阿里中间件十几年来在微服务领域的沉淀和 MSE 合作加持,SAE 1.0 深受微服务客户青睐,广受好评。</p><h2>SAE 2.0 全新升级,更快更省更易用,进一步普惠企业和开发者</h2><p>随着 Serverles 的逐渐普及,更多的企业和开发者跃跃欲试 Serverless,他们对成本越来越敏感、对体验要求更简单、对效率要求更高。五年后 SAE 重磅推出了 2.0 全新版本,重点特性包括:更丰富的适用场景、更极致的弹性效率,更低价的成本、更友好的开发者体验。</p><p><img src="/img/remote/1460000044597138" alt="图片" title="图片"></p><p>更丰富的适用场景:除支持开源微服务/XXL -job、ElasticJob、Spring Task 等无缝迁移外,SAE 2.0 新增支持 Web 应用类型,从实例托管到流量托管。</p><p>更极致的弹性效率:SAE 2.0 中的 Web 应用实现了百毫秒级弹性伸缩,根据流量自适应调整资源使用。</p><p>更低价的成本:SAE 2.0 中的 Web 应用提供闲置计费能力,无请求时 CPU 不计费,部分场景下还支持缩容到 0,降本可达 40% 以上,这对于新兴的业务以及一些创新创业的公司更加友好。</p><p>更友好的开发者体验:产品使用简单,零改造迁移,秒级创建应用,一键灰度。提供S2A、CLI 等丰富的平台工程能力,助力研发运维提效 50%。</p><h3>弹性效率升级:百毫秒弹性能力,完胜开源 K8s HPA/Knative</h3><p>Serverless 架构的一个巨大技术红利就是弹性能力。弹性从广义上讲,让 IT 能力轻松跟上用户的业务发展;从狭义上讲,则带给用户无与伦比的灵活性。天下武功,唯快不破。SAE 1.0 基于 K8s HPA 做到了 5s+ 左右的弹性效率,满足了绝大多数业务场景的需求。但仍然存在一些延时极其敏感场景:如秒杀、微博热点事件、视频直播等,客户还是存在资源浪费或者稳定性风险。</p><p><img src="/img/remote/1460000044597140" alt="图片" title="图片"></p><p>SAE 2.0 在 1.0 标准 K8s 交付链路的基础上,全新自研了一套极速交付系统,目前先在 Web 应用场景落地。自从上线以来,受到了广大客户的一致好评,都纷纷表示 2.0 创建应用/弹性扩容简直太丝滑了。</p><p>弹性响应更极速:原生 K8s HPA 和 Knative KPA 受限于监控指标采集间隔定期上报的机制,都存在弹性决策动作滞后的问题,SAE 2.0 中通过自研的实时调度模块,实时感知 HTTP 请求数的变化,及时决策扩缩容行为和扩缩容目标。</p><p>资源生产更极速:为了实现百毫秒级交付,SAE 2.0 在 K8s 的基础上专门设计一套全新的资源极速交付系统,相比 K8s 单实例的交付时延降低 95% 以上、集群交付吞吐提升了 20 倍以上。为此 SAE 重点优化了两方面能力:</p><ol><li>针对安全沙箱容器,2.0 抛弃传统的 Pod 冷启动模式,对沙箱提前池化,在交付时,复用池化沙箱并采用原地规格变配、网络动态绑定等技术快速交付,同时通过沙箱模板,优化了沙箱池化的并发和速度。</li><li>针对交付链路,相比 K8s 异步资源交付,2.0 的资源极速交付系统在设计采用了同步交付模式,链路更简洁高效,极大提升了资源交付的确定性。</li></ol><p>流量接入更极速:以往在 ECS 模式或者 K8s 架构下,新扩容的实例都会通过 SLB 的 OpenAPI 被自动加到后端虚拟服务器组,整个过程是异步实现,新实例在秒级后才能承接业务流量。SAE 2.0 通过实时的调度系统+流量网关,可以让新实例承载业务流量更及时。</p><h3>降本策略升级:提供闲置计费和缩容到 0,单实例的生产应用也能降本</h3><p>降本是企业和开发者越来越关注的话题,没有最便宜只有更便宜。业界通用的弹性能力粒度都是到主机/实例级别,对一些访问量低但又需要生产保活的业务不太友好,通过技术释放的成本红利非常有限。</p><p><img src="/img/remote/1460000044597141" alt="图片" title="图片"></p><p>SAE 2.0 在 Web 应用场景率先提供了闲置计费和缩容到 0 的能力,让单实例的生产应用也能降本 40%。SAE 2.0 采用实例并发度指标作为默认的扩缩容策略,更好的匹配实际请求和提升资源利用率。基于 HTTP 请求纵向伸缩 VCPU 的实现,在应用有请求时分配 CPU ,无请求时 CPU Freeze 到 0(CPU 不计费),能让一些访问量极少的生产应用节省大量的闲置成本。如果Web应用自身的业务延时非常不敏感或者能接受小概率的流量有损(SAE 本身也会通过延迟销毁实例一定程度上缓解流量风险),还可以直接将应用缩容到 0,将降本进行到底。</p><h3>开发者体验升级:基于 BuildPacks 自动检测构建,提供一站式 Source to Application 能力</h3><p>容器改变了传统的应用开发交付模式,如今开发人员不仅要构建应用,还要负责 CD 部署。Dockerfile 的编写和持续维护对一些中小型客户来说上手难度很大,再加上集成对接 Jenkins 时一系列的脚本编写、手动配置和运维工作,非常繁琐,占用了开发人员大量的精力。</p><p><img src="/img/remote/1460000044597142" alt="图片" title="图片"></p><p>SAE 2.0 内置了一站式 Source to Application 能力,构建类型支持 Dockefile 和 BuildPacks 自动检测构建两种,后者也是 SAE 相对其他 CD 平台最大的优势。基于 BuildPacks 技术,绝大多数应用只用配置源码仓库+构建触发规则即可,对应的 Buildpack 能自动检测应用实际的 Runtime 类型(Java/PHP/Python/NodeJS/Go等)+第三方包管理工具(Maven、NPM 等),然后自动初始化初始化依赖,编译代码和构建镜像,导出生成应用的新版本。BuildPacks 模式无需客户编写 Dockerfile,极大的降低了使用门槛,减少了一系列集成配置和运维工作,简化了镜像构建的过程,让开发人员可以更专注于业务开发。</p><h3>微服务治理能力升级:启动更快,运行更稳,SAE+ MSE 是 Serverless 微服务架构最佳实践</h3><p>区别开源自建微服务,SAE +MSE 提供了开箱即用的历经双 11 考验的全套微服务治理能力,客户无需考虑框架选型、更无需考虑数据隔离、分布式事务、熔断设计、限流降级等,也无需担心社区维护力度有限二次定制开发的问题。能做到 Spring Cloud/Dubbo 零改造无缝迁移。开源之上,我们还增强了无损上下线、服务鉴权、全链路灰度等高级特性。</p><p>SAE 2.0 继续深耕微服务,通过集成 MSE,专项治理了微服务 Agent 启动时长,目前微服务应用启动耗时减少了 50%,效果显著。同时完善了微服务无损上线的小流量预热和延迟注册等一系列能力,让运行时更稳定。通过集成 MSE Serverless 网关+注册中心,主打一个完整的 Serverless 微服务架构最佳实践(从网关-注册中心-应用托管),开箱即用,已成为诸多微服务应用上云的首选。</p><h2>千行百业选择 SAE,跨越技术鸿沟,深度用云像用水电煤一样简单</h2><p>“我们希望让用户做的更少而收获更多,通过 Serverless 化,深度用云就像用水电煤一样简单” ,这也是 SAE 产品五年以来一直坚持的产品理念:让客户不用修改任何代码,不改变原有应用部署方式,零改造平滑迁移企业在线应用,零门槛容器化和 Serverless化,免运维,开箱即用。五年来,SAE 成就了阿里云各行各业成千上万家客户的应用架构无感升级,也沉淀了产品侧宝贵的最佳实践:</p><ul><li>互娱、电商、新零售行业基于 SAE 的极致弹性抗住突发洪峰流量,典型案例如南瓜电影7天内全面 Serverless 化实践。</li><li>在线教育、地产、互联网行业基于 SAE 实现低门槛微服务架构转型,零门槛容器化,典型案例如广州小迈 Game on Serverless 落地实践 。</li><li>餐饮出行行业潮汐特性明显,借助 SAE+ECS/SAE+容器混合部署,实现弹性降本。</li><li>金融科技,传统行业借助 SAE+Jenkins 从 0 到 1 打造云原生 DevOps,典型案例如视野数科等。</li></ul><h2>未来展望</h2><p>当然,不少客户也对 SAE 的未来充满了期待:比如平台侧已经自动帮客户把 1.0 微服务应用平滑迁移到了 2.0,客户希望后续两者的成本和使用体验上也能拉齐。再比如继续优化 Java 冷启动时长,SAE 联合上下游数据库、存储、网络等产品提供一套完整的 Serverless 弹性应用架构,更多的释放 Serverless 技术红利。我们正在探索和测试验证中,会继续砥砺前行,让更多的客户上云和深度用云时都践行 SAE First!</p><p>作者:黛忻</p><p><strong><a href="https://link.segmentfault.com/?enc=mlZsmrqqTuq1Hcj0C0oRvA%3D%3D.hyNP6E3EnACUyUBGhYqF8oMC4bIBF33JGX8fCK7LXY3iopN7L%2FoZ%2BLUo7hAYb7zUBIrOC0CktVczJVFYkGASFlH5wO4crINouhsPQBVWGaM%3D" rel="nofollow">原文链接</a></strong></p><p><strong>本文为阿里云原创内容,未经允许不得转载。</strong></p>
3分钟畅玩!一键部署幻兽帕鲁联机服务器
https://segmentfault.com/a/1190000044591887
2024-01-26T15:16:26+08:00
2024-01-26T15:16:26+08:00
阿里云云栖号
https://segmentfault.com/u/aliyunqi
0
<p>《幻兽帕鲁》火爆,如何快速拥有一个可以跟小伙伴们愉快玩耍的服务器呢?本教程将指引您在阿里云上快速完成幻兽帕鲁专用服务器部署,仅需点几下鼠标,2~3分钟左右就能可完成搭建,全程无需手动配置参数。</p><h3><a href="https://link.segmentfault.com/?enc=4LSpMnBvZ3fXNhJBaW4Z0w%3D%3D.srtZFagG8YJugwYBSo6L3U4QsBc2SH%2B8oKTJlxCJft2zUtuT9VizN6fpdxRTpApEBbtq%2BNV0mcFgRY1yh4Hnk786PD9Xl5Fj9Ekz%2B2KZvpI%3D" rel="nofollow">3分钟畅玩!点击一键部署幻兽帕鲁服务器</a></h3><h2>【新手推荐】阿里云上一键部署幻兽帕鲁服务器</h2><h3>① 登录服务器创建页</h3><p>点击本页面右侧的“一键部署”即可开始创建实例。</p><p>阿里云弹性计算预置了大部分游戏所需配置,包括网络端口设置、游戏环境等。</p><p>(游戏服务端已经预置在镜像里了,无需单独安装)</p><h3>② 选择配置并完成购买</h3><p>在服务配置页面,完成相关配置。除部署地域、付费时长、设置密码外无需手动配置。</p><p>不同游玩人数需要的配置不同,阿里云推荐两种规格,满足不同玩家的需要</p><p>入门尝鲜(4-8人):e系列 4vCPU 16G内存,3M固定带宽</p><p>沉浸畅玩(10-16人):u1系列 4vCPU 32G内存,10M固定带宽</p><p><img src="/img/remote/1460000044591889" alt="图片" title="图片"></p><blockquote>*新用户可享受1/3个月新人低价折扣。</blockquote><h3>③ 生成环境,开始游戏</h3><p>当服务状态变成“已部署”,点击服务实例ID进入服务详情。</p><p>找到“幻兽帕鲁服务器地址端口”,复制端口地址。</p><p>进入Palword,选择加入多人游戏(专用服务器),在最下方IP地址处粘贴端口地址,就可以跟小伙伴们愉快地联机游戏了。</p><p><img src="/img/remote/1460000044591890" alt="图片" title="图片"></p><h2>【进阶教程】基于阿里云ECS快速部署幻兽帕鲁服务器</h2><p>如果您已经买好了阿里云ECS云服务器!本教程将指引您基于云服务器快速部署幻兽帕鲁游戏。按图索骥,畅快开玩!</p><h3>① 检查4大前提条件</h3><ul><li>您的云服务器ECS满足官方推荐的4核16G及以上配置</li><li>您的云服务器ECS操作系统在下述范围内:Alibaba Cloud Linux、Ubuntu、CentOS、Windows Server(推荐您使用最新操作系统版本)</li><li>您的云服务器ECS已开通公网IP</li><li>您的云服务器ECS已开通游戏端口8211</li></ul><h3>② 安装游戏服务端</h3><p>在控制台中打开系统运维管理OOS,选择左侧扩展程序—公共扩展程序</p><p>点击“幻兽帕鲁”扩展程序,选择你需要部署的实例进行安装</p><p><img src="/img/remote/1460000044591891" alt="图片" title="图片"></p><h3>③ 生成环境,开始游戏</h3><p>安装完成后,找到ECS的公网IP。</p><p>进入Palword,选择加入多人游戏(专用服务器),在最下方窗口输入“公网IP:8211”,就可以跟小伙伴们愉快地联机游戏了。</p><p><img src="/img/remote/1460000044591890" alt="图片" title="图片"></p>
魔搭×函数计算:一键部署,缩短大模型选型到生产的距离
https://segmentfault.com/a/1190000044589626
2024-01-25T17:35:26+08:00
2024-01-25T17:35:26+08:00
阿里云云栖号
https://segmentfault.com/u/aliyunqi
0
<p><img src="/img/remote/1460000044589628" alt="图片" title="图片"></p><h2>引言</h2><p>面对魔搭 ModelScope[1]社区提供的海量模型,用户希望快速进行选型并生产使用起来,但在此之前,却一定会面临算力管理难、模型部署难等一系列问题,那么能否实现快速把选定的模型部署在云端功能强大的 GPU 上,由云端负责服务,扩展,保护和监控模型服务,同时免于运维和管理云上算力等基础设施呢?魔搭 ModelScope × 函数计算 FC[2]给了这样一种方案。</p><h2>魔搭x函数计算,一键部署模型上云</h2><p>魔搭 ModelScope 社区模型服务 SwingDeploy 支持将模型从魔搭社区的模型库一键部署[3]至用户阿里云账号的云资源上,并根据模型资源要求为用户自动推荐最佳部署配置。让开发者可以将魔搭开源模型一键部署至阿里云函数计算,当选择模型并部署时,系统会选择对应的机器配置。按需使用可以根据工作负载动态的调剂资源,节约机器使用成本。5 分钟完成从开源模型至模型推理 API 服务的生产转换。</p><p>得益于阿里云函数计算的产品能力,魔搭 SwingDeploy 后的模型推理 API 服务默认具备极致弹性伸缩(缩零能力)、GPU 虚拟化(最小 1GB 显存粒度)、异步调用能力、按用付费、闲置计费等能力,这些能力帮助算法工程师大大加快了魔搭开源模型投入生产的生命周期。</p><h2>以百川智能的大型语言模型为例</h2><p>接下来,我们将演示如何利用魔搭 ModelScope 社区的一键部署技术(SwingDeploy),选取百川智能的大语言模型(LLM)为案例,将其部署至函数计算平台并启用闲置计费。我们将提供一系列详尽的步骤指南:</p><h3>准备工作</h3><ol><li>打开 ModelScope 官网,登录/注册账号</li></ol><p><img src="/img/remote/1460000044589629" alt="图片" title="图片"></p><ol start="2"><li>绑定阿里云账号后,可使用在线调试、训练及部署等能力</li></ol><p><img src="/img/remote/1460000044589630" alt="图片" title="图片"></p><h3>模型部署</h3><ol><li>导航至模型卡片:请在魔搭 ModelScope 社区的模型库页面进行搜索,定位到"baichuan2-7b-chat-4bits",并点击进入该模型的详细页面。您还可以通过 URL 直接访问该模型卡片。</li></ol><p><img src="/img/remote/1460000044589631" alt="图片" title="图片"></p><ol start="2"><li>执行快速部署操作:请在模型卡片的右上角找到并点击“部署”按钮,并从下拉菜单中选择“快速部署(SwingDeploy)”,随后选择“函数计算(FC)”作为目标部署平台。</li></ol><p><img src="/img/remote/1460000044589632" alt="图片" title="图片"></p><p>在随后出现的弹窗中,您可以对模型的部署参数进行详细配置,这包括选择适当的模型版本、部署的地理区域、显卡型号以及需要的显存容量等。完成这些必要设置后,请点击“一键部署”以初始化部署过程。</p><p>注意:目前函数计算 GPU 的闲置计费模式只适用于杭州和上海地区,并且仅限于整卡使用。因此,在配置部署选项时,请确保地域设置为杭州或上海,并选择相应的显存容量,即 16GB 对应于 T4 显卡型号,或 24GB 对应于 A10 显卡型号。</p><p><img src="/img/remote/1460000044589633" alt="图片" title="图片"></p><ol start="3"><li>确认部署成功:成功执行“一键部署”后,ModelScope 将开始将模型部署到函数计算云服务,此过程通常需要 1 至 5 分钟完成。部署完毕时,您可返回 ModelScope 主页,导航至“模型服务”下的“部署服务(SwingDeploy)”板块,以确认部署状态显示为“部署成功”。</li></ol><p><img src="/img/remote/1460000044589634" alt="图片" title="图片"></p><h3>启用预留闲置模式</h3><ol><li>将模型服务配置为预留模式:ModelScope 会默认使用按量模式进行部署,为了优化成本和性能,您需要将模型服务配置为预留模式。这可以通过点击“服务模式切换”至“预留模式”来实现。</li></ol><p><img src="/img/remote/1460000044589635" alt="图片" title="图片"></p><ol start="2"><li>激活预留模式的闲置计费功能:完成服务模式的切换至“预留模式”之后,您需要再次点击服务模式的切换按钮。随后,在弹出的窗口中选择“更改配置”,这将引导您跳转至函数计算控制台。在控制台的“函数弹性管理”页面,激活“闲置计费”选项并保存设置,以启用函数计算 GPU 函数的闲置计费模式。这将有助于您在保留资源的同时优化成本效益。</li></ol><p><img src="/img/remote/1460000044589636" alt="图片" title="图片"></p><p>在成功激活闲置计费模式后,在函数的弹性管理界面中,您将看到“闲置计费模式已开启”。此时,当“当前实例数”与“目标预留实例数”一致时,表明所有的闲置实例均已成功启动并处于待命状态。</p><p><img src="/img/remote/1460000044589637" alt="图片" title="图片"></p><h3>开始使用</h3><p>根据魔搭 ModelScope 模型服务里的“立即使用”说明,我们可以顺利调用到该次部署的 LLM 模型。</p><p><img src="/img/remote/1460000044589638" alt="图片" title="图片"></p><p><strong>LLM 一览表:</strong></p><p>由于当前社区以及多种层出不穷的大语言模型(LLM),本表格仅列举了当前热度较高的常用 LLM 基础模型,在其之上的微调模型同样是可以部署至函数计算平台,并开启闲置预留模式。</p><p><img src="/img/remote/1460000044589639" alt="图片" title="图片"></p><h2>函数计算大幅降低用户 GPU 成本</h2><p>随着 AGI 技术的迅速发展,各类型企业越来越多地依赖于 GPU 计算资源来推动他们的业务增长。对于正在使用或计划部署大型语言模型(LLM)等先进技术的客户来说,成本效率是一个重要的考虑因素。函数计算推出 GPU 闲置计费功能,在保障性能的前提下,可以帮助您大幅降低 GPU 的成本开销。</p><h3>GPU 闲置计费 - 实时/准实时推理服务部署方式的革新</h3><p>函数计算 GPU 闲置计费功能是一个行业领先的创新,它允许用户在不牺牲性能的前提下,以更低的成本使用 GPU 资源。这个新功能旨在解决传统 GPU 计费模式中的一个常见问题:即便 GPU 实例在没有服务请求时,用户仍然需要支付全部的资源消耗费用。现在,通过函数计算后台的显存管理,函数计算实例的 GPU 资源只有当请求到来时,才会被激活;当请求完成后,GPU 资源自动被函数计算平台冻结,用户无需为高昂的 GPU 使用费用买单。</p><h3>部署 LLM 的成本效益分析</h3><p>以往部署大型语言模型(LLM)可能需要昂贵的 GPU 支持,尤其在需要大量计算资源时。但请求处理并不是每时每刻都处于活跃状态,势必存在流量的潮汐现象,后端的计算资源会出现空载导致成本的浪费。借助函数计算 GPU 闲置计费功能,用户的开销将会根据实际计算负载动态调整。</p><p>在函数计算的 GPU 闲置模式下,当实例活跃时 GPU 单价为 0.00011 元/GB <em> 秒;当实例进入闲置模式后,闲置 GPU 单价为 0.000009/GB </em> 秒。闲置下的使用成本仅为活跃状态的 1/10。</p><p>让我们以一个实际的例子来说明这种计费方式的成本效果:</p><p>某 AI 初创公司使用 LLM 微调模型提供客服机器人业务,客户需要确保客服机器人业务能够快速响应用户的请求,因此对于冷启动时间有较高的要求,所以无法选择按量付费模式,他们选择了预留实例模式来避免冷启动问题;但同时也发现,平均到每小时,GPU 资源并不是满载的,真正发生在 GPU 实例上的请求时长总计只有 20 分钟,进而他们选择了函数计算业内首创的闲置预留模式。</p><p>基于这样典型的场景,根据函数计算 GPU 的计费模式我们来算这样一笔账:</p><p>1.仅使用 GPU 实例预留模式:</p><ul><li>该客户会选择在业务高峰时期,预留 10 个 16GB 显存的实例为业务提供推理请求,GPU 实例使用单价,GPU 部分的资源开销约为 6.34 元/时/实例</li></ul><p>2.使用 GPU 实例预留模式 + 闲置计费后:</p><ul><li>同样预留 10 个 16GB 显存的实例为业务提供推理请求,我们以 40 分钟闲置,20 分钟活跃来进行计算,总 GPU 部分资源成本约为 2.46 元/时/实例</li></ul><p>以上面的例子进行成本的推演,我们可以看到闲置计费模式可以为用户节省 60% 的 GPU 资源成本。</p><p><strong>开通函数计算获试用额度</strong></p><p>函数计算为首次开通服务的用户提供免费试用额度,试用额度的有效期为 3 个月,自购买之日起,超出试用额度的部分均会计入按量付费。试用额度的详细信息如下。</p><ol><li>GPU 试用额度:前 100 万 GB*秒 GPU 资源使用免费。</li><li>vCPU 试用额度:前 50 万 vCPU*秒 vCPU 资源使用免费。</li><li>内存试用额度:前 200 万 GB*秒内存资源使用免费。</li><li>函数调用试用额度:前 800 万次函数调用免费。</li></ol><p>除以上试用额度,2023 年 12 月 19 日 0 时之后,函数计算还为首次开通服务的用户发放有效期 3 个月、每个月 100 GB 的 CDT 公网流量试用额度。</p><p>您仅需登录至函数计算服务控制台,访问对应函数的弹性管理界面,并激活闲置计费功能。</p><p><strong>相关链接:</strong></p><p>[1] 魔搭 ModelScope 社区官网</p><p><a href="https://link.segmentfault.com/?enc=gspHIwukEsCAM3tKlTwJaQ%3D%3D.bckMJ0XOeVsCvwme%2BML9FLkkS8p%2Bi4XotmLFC1oLpII%3D" rel="nofollow">https://modelscope.cn/home</a></p><p>[2] 函数计算产品官网</p><p><a href="https://link.segmentfault.com/?enc=am%2F9rAqSZe0EhO98LJdKvg%3D%3D.hWycZXWTLNXdup9%2F5ckzhK3I%2B5wwF6o5XWHt17LJCJXZc0ULnx2afAGHKPR52Lpc" rel="nofollow">https://www.aliyun.com/product/fc</a></p><p>[3] 一键部署新手操作指南</p><p><a href="https://link.segmentfault.com/?enc=X%2FXI2d4%2FRX3mk2SEWjUAig%3D%3D.dpjlYW9zST%2FByzKIfSpoXXTtkWNe0S0w6ATFiNJ4W8DlhGLqAXoD1TlZRTLwyknY" rel="nofollow">https://developer.aliyun.com/article/1307460</a></p><p>[4] 通义千问模型系列</p><p><a href="https://link.segmentfault.com/?enc=GYL63lDqZ1OBZ37N6vKiww%3D%3D.AnY07ZI6uR%2FC3pfbWoGf3H%2B3uVwri0IahKVWu3Qp0Qcy%2FB0SMgF26ceWVZ%2FiORaB" rel="nofollow">https://modelscope.cn/organization/qwen</a></p><p>[5] 智谱 .AI 系列</p><p><a href="https://link.segmentfault.com/?enc=5kkeJXdX782tyH83WXdD6w%3D%3D.fyNVa0ipGgTrM3KdUGrfk0%2FDV0aUHW3Ao2VySXr4ro6LgAaDHgYRROHndWAs%2FMYq" rel="nofollow">https://modelscope.cn/organization/ZhipuAI</a></p><p>[6] 百川模型</p><p><a href="https://link.segmentfault.com/?enc=5T5YhHIb2q8eYplPSb2Dfg%3D%3D.nGmMPS7efmwZjDcDfM5CrRzuhXJZPwp00V%2BKiIb5cjFQDDvFPUmywG6C5YN9VOy4" rel="nofollow">https://modelscope.cn/organization/baichuan-inc</a></p><p>[7] 函数计算闲置 GPU 实例公测申请</p><p><a href="https://link.segmentfault.com/?enc=VjnKz%2Bfs8v8sWrNrLdKPsA%3D%3D.xpySvcjpupZ6q1HqAvifTufpzVqsncEvoGO3Vr2QiculfUg%2BdQQPqjsk8cgVymo5Qj2zYHQzQcjerM60y5lJgw%3D%3D" rel="nofollow">https://survey.aliyun.com/apps/zhiliao/dXfRVPEm-</a></p><p>作者:深蓝、筱姜、橙语</p><p><strong><a href="https://link.segmentfault.com/?enc=AIXXJyLv5wMmbPmxnZdeDw%3D%3D.rVLgSX9wUN7M%2F8j%2F2Ml88L1lb1IjsSGrHSZPEH0w5MSfQn8SOFWFoqeypruX1HYaXy95o1LlcB75KpRlclutltf0wvgQxoBKVmMjjQdcBpE%3D" rel="nofollow">原文链接</a></strong></p><p><strong>本文为阿里云原创内容,未经允许不得转载。</strong></p>
弹性调度助力企业灵活应对业务变化,高效管理云上资源
https://segmentfault.com/a/1190000044588685
2024-01-25T15:11:51+08:00
2024-01-25T15:11:51+08:00
阿里云云栖号
https://segmentfault.com/u/aliyunqi
0
<h2>01 什么是弹性调度</h2><p>云计算时代,企业可以通过云平台获得大量计算资源,并根据业务发展和流量需求的实时变化,灵活调整使用的资源类型与资源量。阿里云提供了多种弹性资源,如云服务器 ECS 和弹性容器实例 ECI,并且提供不同的付费方式,如包年包月、按量付费和抢占实例等。不同类型和付费方式的实例,在给客户带来更高的灵活性的同时,也对客户的资源管理能力提出了更高的要求。</p><p>阿里云容器服务 ACK 通过节点池功能,简化了集群节点的管理与运维,支持自动弹性伸缩,根据业务负载和预设策略自动调整节点数量,可以弹出不同可用区、实例规格和付费方式的 ECS 实例,虚拟节点也可以按需创建 ECI 实例,以此满足多样化的需求场景并优化成本。然而,客户仍需面对如何高效利用和管理这些计算资源的挑战。</p><p>面临的挑战主要有以下几点:</p><ol><li>差异化控制业务资源使用量</li></ol><p>在集群中,配置了包年包月实例和抢占实例,并在资源不足时将业务 Pod 运行在 ECI 实例上。为了确保高优先级的业务能够在稳定的包年包月实例上运行,我们需要限制不同业务在不同类型实例上的资源使用量。</p><ol start="2"><li>缩容时部分业务 Pod 未释放</li></ol><p>默认的缩容策略难以保证优先缩容高峰期扩容出的业务 Pod,导致业务流量高峰过后,在自动伸缩节点池或 ECI 实例上,仍然存在部分业务 Pod 未释放,导致机器无法缩容并持续计费,需要人工进行业务 Pod 迁移。</p><p>弹性调度的目标,就是帮助客户解决在使用云上弹性资源时面对的挑战。包括按照多级资源的优先顺序进行调度,以及按照定义的优先顺序进行缩容的能力。</p><h2>02 自定义弹性资源优先级调度</h2><p>为了解决客户在多级资源管理中面临的难题,阿里云容器服务 ACK 在标准 K8s 调度框架的基础上扩展了弹性调度功能,推出了“自定义弹性资源优先级调度”功能。</p><p>该功能提供了差异化调度 ECS 和 ECI 资源的能力,包括:</p><ul><li>自定义弹性资源优先级调度策略:在应用发布或扩容过程中,客户可以按照自定义资源策略,设置应用实例 Pod 被调度到不同类型节点资源的顺序。</li><li>逆序缩容:当客户通过 HPA 缩容业务 Pod 时,可以按照策略中资源优先级的逆序缩容业务,确保弹性资源优先缩容,减少计费。</li><li>灵活修改策略:当策略发生变化时,同步调整已调度的业务 Pod 的优先级。而且,该功能通过自定义资源定义策略实现,无需改动业务 Deployment。</li><li>控制业务资源使用量:通过限制不同业务在不同类型实例的资源使用量,确保高优资源优先供给高优业务使用。</li><li>多种资源使用量统计策略:限制业务资源使用量时,支持多种不同的资源使用量统计策略,如忽略 Terminating 过程中的 Pod 或忽略提交 ResourcePolicy 策略前已调度的 Pod 等。</li><li>优化 Deployment 滚动更新:能够自动将滚动更新过程中新创建的 Pod 视为新的分组,无需在每次更新 Deployment 时同步手动更新 ResourcePolicy。</li></ul><p>下面我们将通过两个场景示例介绍弹性调度功能是如何帮助企业优化资源配置,实现降本增效的。</p><h2>03 场景一:常驻 ECS 实例+自动伸缩抢占式实例实现逆序缩容</h2><p>抢占式实例(旧称竞价实例)是一种按需实例,性能与常规 ECS 实例无异,价格根据市场供需关系实时变化,相对于按量付费实例最高能节约 90% 的实例成本。通过合理使用抢占式实例,用户能够极大降低云资源成本。</p><p>抢占式实例具有可能被其他出价更高的用户抢占导致实例被回收的特点,不能保证业务的最低运行实例要求,所以用户通常会将抢占式实例和长期包年包月实例配合使用。</p><p>在业务流量的高峰期,由 Pod 水平扩缩(HPA)自动扩容出业务 Pod,再由自动伸缩节点池根据处于 Pending 状态的 Pod 实例数扩容出抢占式实例。</p><p><img src="/img/remote/1460000044588687" alt="图片" title="图片"></p><p>在业务流量减少后,抢占式实例中的 Pod 应当被优先回收,使得抢占式实例能够被自动伸缩节点池回收以减少资源开销。目前默认的缩容策略可能会将运行在常驻 ECS 上的 Pod 回收,导致额外开销。</p><p>如下图所示,其中 cn-hongkong.192.168.7.147 和 cn-hongkong.192.168.7.148 分别带有 unit=first 和 unit=second 标签,代表优先希望调度到 cn-hongkong.192.168.7.147 上:</p><p><img src="/img/remote/1460000044588689" alt="图片" title="图片"></p><p><img src="/img/remote/1460000044588690" alt="图片" title="图片"></p><p>缩容到三个 Pod 后:</p><p><img src="/img/remote/1460000044588691" alt="图片" title="图片"></p><p>可以看到 Pod 依然保留在 cn-hongkong.192.168.7.148 上。</p><p>为了实现优先回收抢占式实例的效果,可以向集群中提交以下的 ResourcePolicy,以下实例的含义是在调度业务 Pod 时仅在靠前的带有 <a href="https://link.segmentfault.com/?enc=Itk05VCAw5DjItMYeYAfaA%3D%3D.HQbUHWE%2BOnfSbiV3i78MPShgSMLk9MoxJ8cf9jmcfVIY0W%2Bnki1%2BDxkuvSaWZHVw" rel="nofollow">http://alibabacloud.com/nodepool-id:</a> example-ecs-nodepool-id 的节点均无法调度 Pod 时,才将 Pod 调度到带有 <a href="https://link.segmentfault.com/?enc=6FyUJ7dNRVsFUPcsNRHsMw%3D%3D.gvzhuH83kLJHVqicAiKAUejaRVgYRVWMeKM4K1jxGPFNjCp4pz9xeOcRi2TV1X%2Fs" rel="nofollow">http://alibabacloud.com/nodepool-id:</a> example-spot-instance-nodepool-id 的节点上。</p><p>策略中假设 ECS 实例和抢占式实例是通过节点池 ID 进行区分的,您也可以通过机型或其他自定义标签进行区分,实际使用时请将变量按需替换:</p><pre><code>apiVersion: scheduling.alibabacloud.com/v1alpha1
kind: ResourcePolicy
metadata:
name: $example-name
namespace: $example-namespace
spec:
selector:
$example-label-key: $example-label-value
strategy: prefer
units:
- nodeSelector:
alibabacloud.com/nodepool-id: $example-ecs-nodepool-id
resource: ecs
- nodeSelector:
alibabacloud.com/nodepool-id: $example-spot-instance-nodepool-id
resource: ecs</code></pre><p>配置后的效果如下:</p><p><img src="/img/remote/1460000044588692" alt="图片" title="图片"></p><p><img src="/img/remote/1460000044588693" alt="图片" title="图片"></p><p>这个示例中我们提交了一个优先调度到带有 unit=first 标签的节点,之后调度到带有 unit=second 标签的节点的策略。</p><p><img src="/img/remote/1460000044588694" alt="图片" title="图片"></p><p>在扩容时,Pod 在完全使用节点 cn-hongkong.192.168.7.147 上的资源后,将后续业务 Pod 调度到节点 cn-hongkong.192.168.7.148 上。</p><p><img src="/img/remote/1460000044588695" alt="图片" title="图片"></p><p>最后我们将业务 Deployment 缩容为三副本,此时节点 cn-hongkong.192.168.7.148 上的业务 Pod 被优先移除,达到了逆序缩容的效果。在实际使用场景中,在 cn-hongkong.192.168.7.148 上的业务 Pod 被移除后,自动伸缩节点池会自动进行相应节点的回收,从而达到节约成本的效果。</p><h2>04 场景二:通过 Max 选项控制业务资源使用量</h2><p>滚动更新是业务上线过程中一项非常重要的流程,为了保障业务在滚动更新过程中不受影响,业务通常会采用“创建后删除”的策略,即等到业务的新副本正常运行了再逐渐清理旧副本,这就使得滚动更新中业务实际消耗的资源量高于运行过程中的资源量,超出使用的资源量可能会影响到集群中其他业务的运行或扩容。</p><p>为了限制业务在部分类型资源上的资源使用量,您可以使用 Max 选项,该选项允许限制业务 Pod 在每种资源类型上的数量,从而限制资源使用。启用该功能只需要在 ResourcePolicy 的 Unit 中新增一个 Max 字段:</p><pre><code>apiVersion: scheduling.alibabacloud.com/v1alpha1
kind: ResourcePolicy
metadata:
name: $example-name
namespace: $example-namespace
spec:
selector:
$example-label-key: $example-label-value
strategy: prefer
units:
- nodeSelector:
alibabacloud.com/nodepool-id: $example-ecs-nodepool-id
resource: ecs
max: $example-max
- nodeSelector:
alibabacloud.com/nodepool-id: $example-spot-instance-nodepool-id
resource: ecs</code></pre><p>当设置了 Max 之后,如果业务 Pod 在该 Unit 上运行的 Pod 数量已经达到了 Max,则下一个 Pod 将会被调度到后续的 Unit 上,若已经是最后一个 Unit,则 Pod 会调度失败。</p><p>以下是一个使用 Max 限制资源使用的例子,依然给 cn-hongkong.192.168.7.147 和 cn-hongkong.192.168.7.148 分别设置 unit=first 和 unit=second 标签。</p><p><img src="/img/remote/1460000044588696" alt="图片" title="图片"></p><p><img src="/img/remote/1460000044588697" alt="图片" title="图片"></p><p>不加资源限制时,业务会将高优资源用完再使用下一级,若此时有其他高优应用则无法使用该高优资源。</p><p><img src="/img/remote/1460000044588698" alt="图片" title="图片"></p><p><img src="/img/remote/1460000044588699" alt="图片" title="图片"></p><p>在该例子中我们提交了一个优先调度到带有 unit=first 标签的节点,之后调度到带有 unit=second 标签的节点的策略,并在一级策略上添加了最多调度一个业务 Pod 的限制,这会将 app=nginx 业务在一级资源上的业务使用限制在 1 个 Pod 的级别。</p><p><img src="/img/remote/1460000044588700" alt="图片" title="图片"></p><p>配置了 ResourcePolicy 之后,可以发现业务在 unit=first 的机器上的资源使用被限制,超出限制的部分被调度在了 unit=second 的机器上,从而实现了业务的资源合理分配。</p><h2>05 What’s Next</h2><p>弹性调度功能通过多级优先级调度、多级资源限制、逆序缩容等能力,帮助企业高效利用云上资源。除了本文介绍的两种基本用法外,阿里云容器服务 ACK 自定义弹性资源优先级调度还支持多种资源统计策略、根据 Label 智能分组等高级特性。通过灵活设置弹性调度,企业可以实现高效的资源配置与成本管理,更好的应对业务增长带来的资源管理挑战。</p><p>作者:吴昆</p><p><strong><a href="https://link.segmentfault.com/?enc=gqCPO83c7vjZZ55jnDr8aw%3D%3D.0qh5GYXsxDULOoK00U92av1vkO4lHNiHacYme5jJYCXLped0S5gQbXhy66ZTlQEFzTIjoI9TngTGs3B20arkyTPBKLcG19QYrBjVc4HLDc0%3D" rel="nofollow">原文链接</a></strong></p><p><strong>本文为阿里云原创内容,未经允许不得转载。</strong></p>
可观测实践丨如何利用 AI 算法解决告警配置三大难题?
https://segmentfault.com/a/1190000044587922
2024-01-25T11:03:09+08:00
2024-01-25T11:03:09+08:00
阿里云云栖号
https://segmentfault.com/u/aliyunqi
0
<h2>每个运维工程师都躲不开的噩梦</h2><p>为了更代入感地解读业务场景,这里我们以运维工程师小 A 的视角来开始今天的解读。</p><p>年轻有为的运维工程师 小 A 刚接手公司最核心业务系统的稳定性保障工作。但他发现这个任务非常具有挑战性,可以说是噩梦。</p><h4>1)有没有合适工具,告诉小 A 应该对哪些指标配告警?</h4><p>这个系统非常复杂,既有像 CPU 使用率、内存使用率等基础指标,又有像响应时间、调用量等业务指标,又因为包含着很多 Java 应用,还需要关注一下 JVM 指标,林林总总几百个指标。小 A 不知道哪些指标是最重要的,也不知道应该对哪些指标配告警。</p><h4>2)有没有合适工具,给小 A 自动推荐合适的告警阈值?</h4><p>小 A 请教资深运维工程师“稳哥”,“稳哥”根据他 10 年运维经验,给小 A 划了需要重点监控的十几个指标。小 A 非常开心的开始配告警。但小 A 填告警阈值时,发现“阈值设置得太松,有可能漏掉问题;阈值设置的太严,一天下来告警 999+”。小A又回去请教“稳哥”,“稳哥”表示阈值这种东西,必须参考每个指标历史表现来设置。而且现在公司的业务不断发展壮大,需要不断地调整阈值,他也没有办法给小 A 一组长期有效的阈值。</p><h4>3)有没有合适工具,帮小 A 给起伏不定的指标配告警?</h4><p>小 A 经过不断地调整阈值和试错,终于慢慢得到了一组还算有效的阈值。但小 A 发现有的指标天然起伏不定,无论用什么阈值都不大合适。比如打车业务每天上下班的时段,下单接口每分钟有 1000+ 调用量,如果低于这个阈值就可能是系统出现了故障引发资损,需要及时告警。但在非高峰期时段,每分钟调用量为 0 也非常正常,这种场景不需要告警。但现有可观测产品好像并不支持给不同时间段设置不同告警阈值。</p><p>针对小 A 的这三个问题,阿里云应用实时监控服务(ARMS)给的答案是“有”、“有”以及“有”。</p><p>围绕小 A 遇到的这三个问题,接下来给大家介绍更简单、精准的智能告警能力,手把手教小 A 配出“系统无异常时不误告,有异常时及时告”的高质量告警规则,完成公司最核心业务系统的稳定性保障任务。</p><h2>“不知道该监控哪些指标?”——监控指标推荐表</h2><p>先来看看应该对什么指标配告警。其实对于已经接入 ARMS 应用监控的用户来说,常见的、重要的监控指标 ARMS 探针都是会自动采集。这里 ARMS 对比较重要的指标分了类,可以结合自身业务特征来决定对哪些指标配告警.</p><p><img src="/img/remote/1460000044587924" alt="图片" title="图片"></p><p>对于应用监控的用户来说,建议先对黄金三指标:调用次数、响应时间、错误率和错误次数配上告警。这是因为如果出了突增或突降,很有可能会直接影响业务。值得关注的还有一些 Http 状态码的里面 4xx、5xx 指标、Full GC 次数、数据库调用响应时间这类指标。如果负责的功能使用 Java 开发的,就配上 JVM 监控相关指标,如果强依赖于某个数据库,就把数据库指标也配上告警。</p><p>在帮助文档里有对这些指标更详细的说明,可以查看下方的链接:</p><p><a href="https://link.segmentfault.com/?enc=bSNqpmIL8uiLaNCljejFcA%3D%3D.1cLhaqQ7uIy4MB9ANmqj7ArETDOxd9tzI5xdKr9Wlb7bmRjDnCNYkRtfftTNcsxzeVwLXIgkrKuE4uHofHo1UI4o%2Bdc2A84ky8sgfE1S5RFRe0ms5LUD1aT3Pr44zwDQGRx9%2BwG409zAB%2F77PXfrYob535R8XCGZjk5ySoXZIq7upebX1OomPnF5cjkMzI1d" rel="nofollow">https://help.aliyun.com/zh/arms/application-monitoring/develo...</a></p><p>另外,这些指标其实在 ARMS 告警配置页面可以直接选,ARMS 用户配告警时可以直接看到所有指标。</p><h2>”不知道该设置什么阈值?”——智能阈值推荐及告警预览功能</h2><p>当选好了需要监控指标和应用,马上会遇到下一个问题 -- 不知道该如何设置告警阈值。或者说,不知道当系统的响应时间、错误率、机器的 CPU 使用率大于多少时,表示这个系统目前处于异常状态。</p><p><img src="/img/remote/1460000044587925" alt="图片" title="图片"></p><p>这其实可以算是一个异常检测的问题,业界比较常见的思路是推出“无阈值告警”服务。一般会给出一个下拉框,里面有十几种异常检测算法,告诉运维工程师说“选一个适合你的”。但一般也不知道哪个适合对应的业务系统。而且异常检测算法少说有几百种,并没有绝对“最优”的算法,一个一个试也不大现实。</p><p>但 ARMS 应用监控配告警时,就像把大象塞入冰箱一样,选合适的阈值只需要三步:</p><p>1.选好需要监控的应用和指标</p><p>2.点击“填入 P4 建议阈值”</p><p>3.根据 24h 指标真实历史数据,帮助用户做校验和修改</p><p><img src="/img/remote/1460000044587926" alt="图片" title="图片"></p><p>这个时候,可能会有人问:我怎么知道你给我推荐的阈值合不合适呢?这是一个非常关键的问题。所以,ARMS 不仅自动根据指标生成一个阈值,并把过去 24h 指标及阈值的水位线画出来,方便进行比较和验证阈值设置的合理性。展示的都是用户自身数据,可以一眼看出来推荐的阈值是否合理,也非常方便后面进行调节。</p><p>也会有人觉得 ARMS 这种产品设计不够“智能”。但再高端的算法,被验证了 99.9% 的准确性,也没人能保证用户不是那额外的 0.1%。如果那次漏掉的告警刚好背后是一个大故障,是会对业务造成很大损失的。在告警配置环节,ARMS 希望给到一种“最让人放心”的方案。可以清晰看到阈值和实际数据的对比,给出足够信息帮助调节阈值。这也是目前能找到的最直观能验证告警规则合理性的方式。</p><p><img src="/img/remote/1460000044587927" alt="图片" title="图片"></p><p>这里解释一下“填入 P4 建议阈值”的“P4”是什么意思。ARMS 告警支持同一指标配置不同阈值来显示告警不同严重程度,从 P1 到 P4 ,严重程度依次递减。比如同个应用,响应时间大于 1s 只是有点卡顿,大于 5s 也还行,但 1min 都还没有返回结果,可能就是系统出故障了,需要排查。这里默认给出了稍微异常的建议阈值,可根据P4给的阈值来填 P1、2、3。当然也支持只填一个 P4 阈值。ARMS 对每个填写的阈值都会画出水位线,协助进行调整。</p><p><img src="/img/remote/1460000044587928" alt="图片" title="图片"></p><p>配置完成之后,就可以点击“告警数预测按钮”,可以看到在当前配置下,过去24小时内实际值超出每个阈值多少次。如果它显示 3、4 次,也可以知道过去 1 天确定发生过一些异常,需要通知到运维工程师,也可以理解为当前阈值设置是合理的。但如果过去 1 天发生了 1000 多次告警,建议还是把阈值调高一些。</p><p>此外,ARMS 也支持多种指标结合方式来配置告警。比如运维工程师用的比较多的是“每分钟调用量”超过 200 次,且错误率大于 5% 就发出告警,这样可以有效地过滤掉一下,比如一共就 2 次调用,出错了一次,导致错误率上涨到 50% 的误告警。</p><p><img src="/img/remote/1460000044587929" alt="图片" title="图片"></p><p>除了以上的常规用法之外,ARMS 发现有些聪明的运维工程师研究出了“告警数预测”按钮,更高级的“明天再说”用法。就是有的告警他收到了,发现是个不大重要的 P4 告警,而且他已经下班了,就先不处理,第二天回来看,点一下告警数预测这个按钮,查一下异常发生时刻,开始定位问题。他会开始找异常发生时段对应 CPU 使用率、内存使用率等指标,定位根因,并想办法对系统进行进一步的优化。</p><h2>“指标正常情况就起伏不定,怎么配告警?”——阈值检测和区间检测搭配</h2><p>最后解决前文提到的最后一个问题:“对于起伏不定的指标,怎么配告警”。这种“起伏不定的指标,一般是业务指标”。比如上文提到的打车业务早晚高峰与非高峰时段的起伏问题。有的运维工程师会表示,那晚上自动把告警关掉就好了,但现实生活中,这种起伏不定的指标,很难有像“1000”这么规整的阈值,现实生活中的调用量指标是下面的样子,就是会有一些令人意想不到的“大毛刺”。</p><p><img src="/img/remote/1460000044587930" alt="图片" title="图片"></p><p>针对这个场景,ARMS 做了区间检测功能。进入区间检测功能之后,选好要监控的应用和指标。ARMS 就会自动根据指标历史数据,对正常情况下变化范围进行学习,得到上下边界。ARMS 提供上下边界预览功能,可以对算法计算出来的上下边界进行预览。下图中,蓝线是指标的实际值,绿色的阴影是上下边界。也可以根据实际需要调节灵敏度,也就是这个绿色阴影的宽度。</p><p>这篇文章主要是一个最佳实践,对算法感兴趣的同学可以看我们另一篇文章:《只需半分钟,ARMS 帮你配置出“高质量”告警》[1]</p><p>与静态阈值推荐功能不同的地方在于当业务变化导致指标正常水位发生变化,运维工程师不需通过手动编辑告警规则的方式来更新阈值。这是因为 ARMS 以每天一次的频率持续学习指标特征,并只预测未来一天的上下边界。运维工程师无需再一遍遍来回地调整阈值。ARMS 区间检测告警,仅需一次配置,自适应学习指标特征,持久有效。</p><h2>总结</h2><p>在这篇文章中,我们通过运维工程师小 A 的故事,为大家介绍了在配置告警时过程中比较常见的三个问题,以及如何使用 ARMS 智能告警解决它们:</p><h4>Q 1 :“不知道该监控哪些指标”?</h4><p>A 1:ARMS 应用监控告警中,覆盖了几乎所有重要的告警指标,也给大家提供了指标的说明文档和实践指南,可以参考[2]。</p><h4>Q 2:“不知道该设置什么阈值”?</h4><p>A 2:使用 ARMS 最近推出的【告警阈值推荐】功能得到一个建议阈值,以及与真实指标的对比图。结合图标以及【告警数】预测功能进行调整。</p><h4>Q 3:“指标正常情况下就起伏不定,怎么配告警”?</h4><p>A 3:使用【区间检测】功能,可以直接使用 ARMS 生产的上下边界,也可以通过和实际指标的对比调节灵敏度。目前,应用监控与智能告警都提供免费额度,使大家更好的构建应用监控与智能告警体系。</p><ol><li>应用监控每月提供 50GB 免费额度</li><li>智能告警每天提供 15 次短信免费额度,每天提供 3 次电话免费额度</li></ol><p><img src="/img/remote/1460000044587931" alt="图片" title="图片"></p><p><strong>相关链接:</strong></p><p>[1] 只需半分钟,ARMS 帮你配置出“高质量”告警</p><p>[2] 监控指标推荐文档</p><p><a href="https://link.segmentfault.com/?enc=GvS8DVhp5p%2BtZlkwVEGPoA%3D%3D.1uZ79AAR19wE8PKSJaUSO%2BqDrsaEKn9eXtIHJX1LFJxV%2BDFGQJ56CK%2FJSmRSZjDio9Cbn%2Fn9IEO4mpJ%2Fjqsw7hsS2h%2Frt2cJ23fb241Efl4uc3v1tKYejlcnJVYcfGJFqrhNG%2Fj0nVLmag6Vst6yNVvPuCzRQTVPF0%2BQe6pSaqSRK0VX07Sk%2Fzj%2BH6Ft2a6b" rel="nofollow">https://help.aliyun.com/zh/arms/application-monitoring/develo...</a></p><p>作者: 陈昆仪(图杨)</p><p><strong><a href="https://link.segmentfault.com/?enc=vXx9IanqbvTvrSztk%2FRzSA%3D%3D.0ZZrKx%2BPSHKH6tpUNCBqslFBn0Aaj21uBtI7lWq412f%2BTwOVWTovqrM%2BJCH4Tl56%2BRuEC4OzUx8qkaHqMeYQhOH619w28h0TYkX3moR7%2Bw0%3D" rel="nofollow">原文链接</a></strong></p><p><strong>本文为阿里云原创内容,未经允许不得转载。</strong></p>
从内核的视角观测容器 — SysOM 容器监控
https://segmentfault.com/a/1190000044585614
2024-01-24T15:21:56+08:00
2024-01-24T15:21:56+08:00
阿里云云栖号
https://segmentfault.com/u/aliyunqi
0
<h2>01 背景</h2><p>容器化现阶段已经是构建企业 IT 架构的最佳实践。云原生容器化的部署架构,相较于传统 IDC 部署架构的 IT 架构方案,已经成为兼具高效运维及成本控制的业界事实标准。</p><p>但容器化带来的都是好处么?容器化屏蔽了 IDC 基础设施和云资源的同时,也带来了容器引擎层的不透明,现有的云原生可观测体系还无法覆盖。</p><p>据我们统计,大量超过千节点规模的生产级 JAVA on K8s 的用户都遇到过内存“黑洞”导致的 OOM 问题,以及大规模集群使用上的容器引擎层 CGroup 问题也会使得用户对容器化望而却步。</p><p>阿里云容器服务 ACK 团队与阿里云操作系统团队进行合作,通过对多个头部行业客户的千万核规模的 Kubernetes 集群沉淀了丰富的容器化迁移专业经验,以及结合 Alinux 对操作系统 kernel 层的专业增强,通过与云原生容器服务结合,使容器引擎层不再“黑盒”,让用户放心容器化。</p><h2>02 常见容器化内存“黑洞问题”</h2><h3>容器内存组成剖析</h3><p>Kubernetes 采用内存工作集(workingset)来监控和管理容器的内存使用,当容器内存使用量超过了设置的内存限制或者节点出现内存压力时,Kubernetes 会根据 workingset 来决定是否驱逐或者杀死容器。</p><p><strong>内存工作集计算公式:</strong></p><p>Workingset = inactive_anon + active_anon + active_file。其中 inactive_anon 和 active_anon 是程序匿名内存总大小。active_file 是活跃文件缓存大小。</p><p><strong>匿名内存</strong></p><p>匿名内存是指没有关联到文件的内存,例如进程的堆、栈、数据段等,有以下几种部分组成:</p><p>匿名映射:程序通过 mmap 系统调用创建的没有关联文件的内存映射。</p><p>堆:程序通过 malloc/new 或 brk 系统调用分配的动态内存。</p><p>栈:用于存储函数参数和局部变量的内存。</p><p>数据段:用于存储已初始化和未初始化的全局变量和静态变量的内存。</p><p><strong>活跃文件缓存</strong></p><p>程序读写文件会产生文件缓存(file cache),其中最近多次使用的缓存称为 active file cache,通常不 容易被系统回收。</p><p><img src="/img/remote/1460000044585616" alt="图片" title="图片"></p><p>$$
(图/Kernel Level Memory Distribution)
$$</p><p>下面介绍通过 SysOM 监控来排查 Pod workingset 高的问题。</p><h3>定位步骤一:定位哪些内存导致 workingSet 高</h3><p>根据 workingset 计算公式:workingset = inactive_anon + active_anon + active_file 查看 PodMonitor 监控大盘中的 woringkset 监控,找到内存最大的类型,这里发现是 active file cache 占比较大。</p><p><img src="/img/remote/1460000044585617" alt="图片" title="图片"></p><p>$$
(图/SysOM 监控提供 Pod 维度的操作系统内核层内存各组成成分监控)
$$</p><p>发现问题步骤中,SysOM 提供通过 Top 分析快速定位集群中 active file cache 内存消耗最大的 Pod。</p><p>通过 Pod Cache (缓存内存)、InactiveFile(非活跃文件内存占用)、InactiveAnon(非活跃匿名内存占用)、Dirty Memory(系统脏内存占用)等不同内存成分的问题的监控展示,发现常见的 Pod 内存黑洞问题。</p><p><img src="/img/remote/1460000044585619" alt="图片" title="图片"></p><p>$$
(图/通过 Top 分析找出集群中 active file cache 内存消耗最大的 Pod)
$$</p><p><img src="/img/remote/1460000044585620" alt="图片" title="图片"></p><p>$$
(图/SysOM 提供 Pod 维度的详细内存各组成成分监控统计)
$$</p><h3>定位步骤二:定位具体哪些文件导致 active file cache 高</h3><p>查看 PodMonitor 监控大盘中的 file cache 监控,发现主要是 ack-ai-dashboard-admin-ui-77564df84c-z6bs2 容器在对 /workspace/ai-dashboard.jar 文件进行 IO 读写时,产生了较大的内存 Cache 缓存。</p><p><img src="/img/remote/1460000044585621" alt="图片" title="图片"></p><p>若 Pod 内存缓存较大,严重会导致 Pod 工作内存占用升高,这部分 Cache 内存会成为 Pod 工作内存的“黑洞”部分难以定为,产生线上常见的 Pod 内存黑洞导致的 OOM 驱逐问题,最终影响 Pod 所在的业务体验。</p><h2>03 ACK 提供容器化内核层问题的完整解决方案</h2><h3>发现问题 - SysOM 系统容器监控</h3><p>基于阿里云 SysOM,阿里云容器服务 ACK 拥有独有的操作系统 kernel 层的容器监控可观测能力。在客户容器化迁移中,社区、其他云厂商的容器服务没有很好地解决的内存黑洞、存储黑洞等问题,基于阿里云 SysOM 可以很好的观测、预警、诊断出问题。</p><p>SysOM 提供操作系统内核层 Pod、Node 维度监控大盘,实时监控内存、网络、存储的系统层指标。</p><p><img src="/img/remote/1460000044585622" alt="图片" title="图片"></p><p><img src="/img/remote/1460000044585623" alt="图片" title="图片"></p><p>$$
(图/SysOM Pod 维度监控大盘)
$$</p><p><img src="/img/remote/1460000044585624" alt="图片" title="图片"></p><p>$$
(图/SysOM Node 维度监控大盘)
$$</p><blockquote>SysOM 功能、指标详细请参考文档:<a href="https://link.segmentfault.com/?enc=ad%2FtIz24jHxW4DvoCWL3Sw%3D%3D.JE8yRIMHr8Q7TGmRtWKgymojLr%2B%2FFhBth9EWnFE%2BHjgiHAKfra3pViBhbAkcx0n0WZ97rG8fq1R4nc7lFQZiOA%3D%3D" rel="nofollow">https://help.aliyun.com/document_detail/2560259.html</a></blockquote><h3>解决问题 - Koordinator QoS精细化调度功能</h3><p>内存黑洞问题如何修复,阿里云容器服务通过精细化调度功能,依托 Koordinator 阿里云开源项目,ack-koordinator 为容器提供内存服务质量 QoS(Quality of Service)保障能力,在确保内存资源公平性的前提下,改善应用在运行时的内存性能。本文简介容器内存 QoS 功能,具体说明请参见容器内存 QoS[1]。</p><p>容器在使用内存时主要有以下两个方面的约束:</p><ul><li>自身内存限制:当容器自身的内存(含Page Cache)接近容器上限时,会触发容器维度的内存回收,这个过程会影响容器内应用的内存申请和释放的性能。若内存申请得不到满足则会触发容器 OOM。</li><li>节点内存限制:当容器内存超卖(Memory Limit>Request)导致整机内存不足,会触发节点维度的全局内存回收,这个过程对性能影响较大,极端情况甚至导致整机异常。若回收不足则会挑选容器 OOM Kill。</li></ul><p>针对上述典型的容器内存问题,ack-koordinator 提供了以下增强特性:</p><ul><li>容器内存后台回收水位:当 Pod 内存使用接近 Limit 限制时,优先在后台异步回收一部分内存,缓解直接内存回收带来的性能影响。</li><li>容器内存锁定回收/限流水位:Pod 之间实施更公平的内存回收,整机内存资源不足时,优先从内存超用(Memory Usage>Request)的 Pod 中回收内存,避免个别Pod造成整机内存资源质量下降。</li><li>整体内存回收的差异化保障:在 BestEffort 内存超卖场景下,优先保障 Guaranteed/Burstable Pod 的内存运行质量。</li></ul><p>关于 ACK 容器内存 QoS 启用的内核能力,详见 Alibaba Cloud Linux 的内核功能与接口概述[2]。</p><p><img src="/img/remote/1460000044585625" alt="图片" title="图片"></p><p>$$
(图/ack-koordinator 为容器提供内存服务质量 QoS(Quality of Service)保障能力)
$$</p><p>在通过第一步观测发现容器内存黑洞问题之后,可以结合通过 ACK 精细化调度功能针对性挑选内存敏感的 Pod 启用容器内存 QoS 功能,完成闭环修复。</p><p><strong>相关链接:</strong></p><p>[1] 容器内存链接</p><p><a href="https://link.segmentfault.com/?enc=kMM7QYt1YdLoiXFqoVtQDg%3D%3D.SxzZpuqaHPX72CZYK5fRcQFO47MW5to9YPKFt1FXe4ZLmwU82Q2oKnDQf5Ffdv0NO5inhJZxeHRpod3psGTLPrqjXW%2B9ABeNUnKpgyzxuv0UD%2FPhdeoQ41Fkgy2s1rAtrT3xEt%2FpiGzWs5dqyE8ZNw%3D%3D" rel="nofollow">https://help.aliyun.com/zh/ack/ack-managed-and-ack-dedicated/...</a></p><p>[2] Alibaba Cloud Linux的内核功能与接口概述</p><p><a href="https://link.segmentfault.com/?enc=xJO9McxnrrKvMUYpihXxsA%3D%3D.BfW5dQD12WfN877Tf8D5Vp80fGh0VlPkb5jq7bMg3%2Bf3NU9kfu3zxOLsQDyO0z%2BFhUb6SfixIkC%2FusHt%2BryauA%3D%3D" rel="nofollow">https://help.aliyun.com/zh/ecs/user-guide/overview-23</a></p><p><strong><a href="https://link.segmentfault.com/?enc=aCc0EHsdvQhLdSm39NznBw%3D%3D.BQN1MFhpMshC%2FJZnhFMa6%2FZNJI%2BBIygZjScrpTnNwvW69QNSLT6zPPKQE8zApDyVTO0tGoSQBr5YPKUlsHQD6%2B0ljdR26hRYtqspbcc1U7c%3D" rel="nofollow">原文链接</a></strong></p><p><strong>本文为阿里云原创内容,未经允许不得转载。</strong></p>
Nacos 2.3.0 正式版发布,Nacos Controller 项目开源
https://segmentfault.com/a/1190000044585158
2024-01-24T14:36:45+08:00
2024-01-24T14:36:45+08:00
阿里云云栖号
https://segmentfault.com/u/aliyunqi
0
<h2>新版本发布</h2><p>Nacos 2.3.0-BETA 版本经过 1 个多月的社区测试,修复了部分的问题并对部分新功能的使用进行了少量优化后,于 2023 年 12 月 7 日正式发布。</p><p>Nacos 2.3.0 版本基于 2.3.0-BETA 版本为基础,主要进行了如下更新:</p><ul><li>基于能力协商机制,支持通过 Grpc 的方式进行持久化服务实例的注册及删除。</li><li>Console UI 中显示更多内容,例如部署模式等。</li><li>对参数校验功能的实现方式进行优化。</li><li>对 TopN 指标的实现进行重构,优化准确性和内存消耗。</li></ul><p>详细的更新日志请查看:</p><pre><code>## Feature
[#11393] Support register or deregister persistent instance by grpc.
## Enhancement&Refactor
[#11275] Enhance console ui deploy, show more information like `mode`.
[#11298] Strip groupNamePrefix of instance serviceName at register or deregister.
[#11310] Simplify the validate method for serviceinfo.
[#11342] Simplify BatchDeregister instances conditions to ip and port.
[#11343] Simplified parameters checker control logic.
[#11352] Refactor topN logic to enhance memory usage and accuracy.
## BugFix
[#10353] Handling DataIntegrityViolationException and DuplicateKeyException together.
[#11299] Fix console ui auth pagination failure.
[#11382] Fix console ui listening query pagination failure.
[#11384] Fix console ui comparing configuration failure.
[#11390] Fix Config EncryptionPluginService order problem.
[#11442] Fix listen configuration check failed without namespace.
## Dependency
[#11216] Declare httpcore as direct dependency to fix avoid conflict.
[#11396] Upgrade jackson same with spring boot dependency.
[#11439] Upgrade some UI component to solve security problem.</code></pre><h2>Nacos Controller 项目开源</h2><p>在云原生下,应用代码与运行环境可以通过 Helm 或 Kustomize 等软件进行交付、维护、CICD,但应用的 Nacos 配置依然需要手工地迁移、或使用控制台修改发布配置。借助于 Nacos Controller[1]项目,我们可以将 Nacos 配置管理下移到 Kubernetes 集群中,又或是可以将 Kubernetes 中 ConfigMap 配置上移到 Nacos 控制台中,从而实现统一管理能力。</p><h3>Nacos 配置下移到 Kubernetes 集群中</h3><h4>工作机制</h4><p>Nacos Controller 监听集群内的 DC 资源,当 DC 资源发生变化时,Nacos Controller 将其中的配置内容同步到 Nacos Server 中。</p><p><img src="/img/remote/1460000044585160" alt="图片" title="图片"></p><h4>简易 Demo</h4><p>在 Nacos Controller 中,我们定义了一份 CRD:DynamicConfiguration(简称 DC),我们将 Nacos 配置保存在 ConfigMap 中,对配置的任何修改都通过 DC 将其中的配置同步到对应的 Nacos 服务端中。在后续的配置维护中,直接修改对应的 ConfigMap 即可。以下是一份简易的 Demo 示例:</p><pre><code>apiVersion: nacos.io/v1
kind: DynamicConfiguration
metadata:
name: dc-demo-cluster2server
spec:
dataIds:
- data-id1.properties
- data-id2.yml
nacosServer:
endpoint: <your-nacos-server-endpoint>
namespace: <your-nacos-namespace-id>
group: <your-nacos-group>
authRef:
apiVersion: v1
kind: Secret
name: nacos-auth
strategy:
syncPolicy: Always
syncDirection: cluster2server
syncDeletion: true
objectRef:
apiVersion: v1
kind: ConfigMap
name: nacos-config-cm
---
apiVersion: v1
kind: ConfigMap
metadata:
name: nacos-config-cm
namespace: default
data:
data-id1.properties: |
key=value
key2=value2
data-id2.yml: |
app:
name: test
---
apiVersion: v1
kind: Secret
metadata:
name: nacos-auth
data:
ak: <base64 ak>
sk: <base64 sk></code></pre><h3>Kubernetes 配置上移到 Nacos 控制台</h3><h4>工作机制</h4><p>首先需要用户创建 DC 资源指定需要同步哪些 DataId,Nacos Controller 根据读取到的 DC 配置,选择性监听 Nacos Server 中的相关配置并将配置改动同步到 Kubernetes 集群中。</p><p><img src="/img/remote/1460000044585161" alt="图片" title="图片"></p><h4>简易 Demo</h4><p>云原生下,应用除了需要加载 Nacos 配置外,还可能依赖一些环境变量,比如 JVM 参数通过环境变量注入。做得比较好的方式是通过 ConfigMap 等 Kubernetes 原生方式管理配置,通过引用的方式传递给应用 Pod。在 Nacos Controller 中,我们可以定义一份 DC,将 Nacos 服务端中的某些 DataId 同步到 Kubernetes 集群中的 ConfigMap 中,从而实现配置的统一管理。以下是一份示例 Demo:</p><pre><code>apiVersion: nacos.io/v1
kind: DynamicConfiguration
metadata:
name: dc-demo-server2cluster
spec:
dataIds:
- APP1_JVM_PARAMS
- APP2_JVM_PARAMS
nacosServer:
endpoint: <your-nacos-server-endpoint>
namespace: <your-nacos-namespace-id>
group: <your-nacos-group>
authRef:
apiVersion: v1
kind: Secret
name: nacos-auth
strategy:
syncPolicy: Always
syncDirection: server2cluster
syncDeletion: true
---
apiVersion: v1
kind: Secret
metadata:
name: nacos-auth
data:
ak: <base64 ak>
sk: <base64 sk></code></pre><h3>云原生下的配置管理最佳实践</h3><p>在使用 Kubernetes 的场景下,一个微服务应用的配置被分割成两部份,一部分存放管理在 Kubernetes 集群中的 Secret 或 ConfigMap 中,另一部份存放管理与 Nacos 配置中心。对于运维人员,我们需要知道哪些配置是存放在何处且同时需要对两个平台的配置管理操作均有所了解,一来是增加了运维人员的知识门槛,二来是增加了应用配置运维的操作成本。通过 Nacos Controller 项目,我们将应用的所有配置集中于一处管理,降低应用配置运维的门槛与复杂性。</p><p><img src="/img/remote/1460000044585163" alt="图片" title="图片"></p><h4>面向 Kubernetes 运维偏好的用户</h4><p>通过 Nacos Controller 项目,我们将应用与应用配置的交付和维护集中在 Kubernetes 集群中。</p><p><img src="/img/remote/1460000044585164" alt="图片" title="图片"></p><p>以下通过一份 Helm 应用 Chart 包说明如何集中管理。</p><pre><code>.
├── Chart.yaml
├── charts
├── conf
│ ├── application-dev.properties
│ ├── application.properties
│ ├── consumer-app.properties
│ └── provider-app.yaml
├── templates
│ ├── consumer.yaml
│ ├── dc.yaml
│ └── provider.yaml
└── values.yaml</code></pre><p>以上是一份 Chart 包目录结构,其中 conf 目录存放的是 Nacos 配置,文件名即 DataId,文件内容即对应的 Content。在 templates/dc.yaml 中,我们定义一份 ConfigMap 来组装这些配置。templates 目录中的 consumer.yaml 与 provider.yaml 分别是应用定义。</p><pre><code>apiVersion: v1
kind: ConfigMap
metadata:
name: nacos-config
namespace: {{ .Release.Namespace }}
data:
{{- range $path, $_ := .Files.Glob "conf/**" }}
{{ $path | base }}: |-
{{ $.Files.Get $path | indent 4}}
{{- end }}</code></pre><p>使用上述方式定义好应用与配置后,可以借助 git 实现应用、配置的版本管理。当需要发布应用或配置时,修改对应文件后,执行 helm upgrade 命令即可。</p><h4>面向 Nacos 运维偏好的用户</h4><p>Nacos 配置管理能力使得应用可以动态调整运行配置,但对于一些特殊的参数,如 JVM 参数、特殊环境变量、特殊目录文件等内容,Nacos 配置管理依然无法涵盖。在 Kubernetes 集群中,我们一般将环境变量或一些特殊文件配置写入 ConfigMap 中,通过 envFrom 能力将内容引用到环境变量中或者 volumeMount 挂载到文件系统中。这样的配置管理能力与 Nacos 配置管理能力是散开的,不利于统一管理。借助于 Nacos Controller,我们将这些配置上移到 Nacos 控制台中,进行统一管理。</p><p><img src="/img/remote/1460000044585165" alt="图片" title="图片"></p><p>以下是一份 Demo 应用,通过 Nacos 控制台管理 JVM 启动参数:</p><pre><code>apiVersion: apps/v1
kind: Deployment
metadata:
name: demo-app
spec:
replicas: 1
selector:
matchLabels:
app: demo-app
template:
metadata:
labels:
app: demo-app
spec:
containers:
- name: demo-app
image: openjdk:8 #替换为你的应用镜像
command: ["/bin/sh", "-c", "java -jar ${JVM_PARAMS} /app.jar"]
env:
- name: JVM_PARAMS # 从ConfigMap中载入JVM参数到环境变量中
valueFrom:
configMapKeyRef:
name: nacos-config
key: APP1_JVM_PARAMS
---
apiVersion: nacos.io/v1
kind: DynamicConfiguration
metadata:
name: nacos-config
spec:
dataIds:
- APP1_JVM_PARAMS
- APP2_JVM_PARAMS
nacosServer:
endpoint: <your-nacos-server-endpoint>
namespace: <your-nacos-namespace-id>
group: <your-nacos-group>
authRef:
apiVersion: v1
kind: Secret
name: nacos-auth
strategy:
syncPolicy: Always
syncDirection: server2cluster
syncDeletion: true
---
apiVersion: v1
kind: Secret
metadata:
name: nacos-auth
data:
ak: <base64 ak>
sk: <base64 sk></code></pre><p>在 Nacos 控制台中,修改 DataId:APP1_JVM_PARAMS 后,配置将自动同步到集群的 ConfigMap 中。只需重启相关应用,则对应的 JVM 参数将自动变化。成功实现将应用的所有配置集中管理在 Nacos 上。</p><h2>展望</h2><h3>2.X 后续计划</h3><p>从 2021 年 3 月 2.0.0 正式版发布至今,2.X 版本已经走了接近2年时间,如今 2.3.0 版本发布,完成了大部分功能的插件化提炼,在之后的 2.3.X 版本中,会主要对当前版本的问题进行修复,并做出小范围的功能优化。同时对于 2.4.0 版本,会作为一个 Nacos3.0 的过度版本,对大量代码进行优化重构,在提升稳定性、健壮性的同时,提升易用性和可观测性,向 Nacos3.0 版本平稳过度。</p><h3>3.0 计划</h3><p>Nacos 社区同时也开启了关于 Nacos3.0 的畅想和规划,Nacos 将会从统一控制面、支持国产化、存储计算分离等方向进一步演进 Nacos 的功能和架构,欢迎社区积极参与到新版本的建设中。</p><p><img src="/img/remote/1460000044585166" alt="图片" title="图片"></p><p><img src="/img/remote/1460000044585167" alt="图片" title="图片"></p><h3>About Nacos</h3><p>Nacos 致力于帮助您发现、配置和管理微服务。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据及流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。Nacos 是构建以“服务”为中心的现代应用架构 (例如微服务范式、云原生范式) 的服务基础设施。</p><p><strong>相关链接:</strong></p><p>[1] Nacos Controller</p><p><a href="https://link.segmentfault.com/?enc=xZdMY0vsR4pSUv%2BNv0xE8w%3D%3D.yAzQFWMf6ns1Vf2kSsyRCfBvCD0Gs15%2FRq4tCU11GfBTonwxqrLTra2JZSzoyAed" rel="nofollow">https://github.com/nacos-group/nacos-controller</a></p><p>[2] Karsonto</p><p><a href="https://link.segmentfault.com/?enc=tO24eBI0rL6KuF9nRH8F9w%3D%3D.IQw%2BQ75%2F8GDfyGg1MFPeHBXDCOzjy%2BbLA8fZDyDKqQs%3D" rel="nofollow">https://github.com/karsonto</a></p><p>[3] Daydreamer-ia</p><p><a href="https://link.segmentfault.com/?enc=L1RkoUTwSjw4okOP6wRGJA%3D%3D.loVKzLQ93DeUOPRfpu6SaSTjrbG97XImYYAr%2F8jGedX1TVWRrHn%2FjiKBIVBBAvw5" rel="nofollow">https://github.com/Daydreamer-ia</a></p><p>作者: 杨翊</p><p><strong><a href="https://link.segmentfault.com/?enc=O4QTIeRNOtrgN0RLmezHfw%3D%3D.JvhHeRLQgcqtcGNFWnK0%2FIcrC9MszjESCCyNZNj6skdHTwzm6IIFUeZNIWBG%2FEgBfy%2BJq%2FIwWtJ3OT06xzxw67Cw7VLpHMTgbiWbh%2BY6EtE%3D" rel="nofollow">原文链接</a></strong></p><p><strong>本文为阿里云原创内容,未经允许不得转载。</strong></p>
从方法论到最佳实践,深度解析企业云原生 DevSecOps 体系构建
https://segmentfault.com/a/1190000044584499
2024-01-24T10:49:45+08:00
2024-01-24T10:49:45+08:00
阿里云云栖号
https://segmentfault.com/u/aliyunqi
0
<h2>01 引言</h2><p>安全一直是企业上云关注的核心问题。随着云原生对云计算基础设施和企业应用架构的重定义,传统的企业安全防护架构已经不能够满足新时期下的安全防护要求。为此企业安全人员需要针对云原生时代的安全挑战重新进行系统性的威胁分析并构建适合企业自身的威胁情报系统,同时在云原生安全体系方法论的指导下,结合云服务商提供的安全产品能力构建端到端的 DevSecOps 流程,维持企业应用全生命周期的持续安全水位。</p><p>本文分为四部分,其中第一部分会介绍当下云原生安全的现状以及企业应用在云原生化转型中面临的主要安全挑战;在第二部分中会概要性介绍云原生安全相对成熟的一部分安全体系方法论;在第三部分中会结合之前介绍的理论基础,介绍如何通过部署和实时阿里云 ACK 容器服务和 ACR 容器镜像服务中提供的一些实用的安全产品能力,帮助企业实现或优化 DevSecOps 流程;最后,在第四部分会总结介绍企业在实践 DevSecOps 过程中需要遵循的安全最佳实践。</p><h3>云原生安全挑战</h3><p><img src="/img/remote/1460000044584501" alt="图片" title="图片"></p><p>云原生时代对企业安全的挑战主要来自以下三方面:</p><ul><li>云原生平台基础设施架构:云原生平台层组件相较于传统架构引入了更多的配置项和隔离层,这就给企业安全管理运维人员提出了更高的运维要求。如何保证平台基础设施层的默认安全性,如何在遵循最小化权限原则基础上进行授权操作,如何建立云原生应用系统的安全审计和监控能力,这些新的挑战都需要云服务商和企业安全管理运维人员协同构建并最终实施到企业云原生化转型后的系统应用架构中。</li><li>DevOps 软件供应链:云原生弹性、敏捷和动态可扩展的特征极大地改变了传统应用部署模式,应用自身的生命周期被大幅缩短,而企业应用的迭代效率则大幅提升,在企业供应链架构变革的同时需要构建和实施适配供应链各阶段的安全防护能力。</li><li>应用范式上的改变:随着微服务架构的普适,传统的基于南北向流量的安全边界模式已经变得不使用,企业需要更加细粒度的身份认证和访问控制;同时 Serverless 和函数计算等技术要求云服务商在基础设施层具备更强的安全隔离性和监控能力,而应用的容器形态则需要新的运行时安全监控告警和资产管理模式与之对应。</li></ul><p>面对重重的安全挑战,企业的安全现状是如何呢?上图是一些主流云原生安全领域厂商在今年发布的最新报告。其中图片左侧来自 Sysdig 今年的云原生安全使用调查报告,报告显示仍然有 87% 的容器镜像中包含严重或高危等级的漏洞,同时 90% 的企业应用授权并没有被实际使用;从右侧 Paloalto 今年的云原生安全现状报告中企业客户反馈的 Top 5 挑战中也可以看出,面对云原生时代新的安全挑战,企业无论在组织架构、文化和安全运维上都还没有做好充分的准备。</p><p><img src="/img/remote/1460000044584502" alt="图片" title="图片"></p><p>供应链安全也是近两年成云原生安全领域的焦点,我们知道创新和效率是企业发展的关键,在云原生时代的企业开发流程中,开源软件和开发工具可以帮助推动企业提升研发效率。在云原生时代,企业对开源生态越来越依赖,三方软件包的安全成为了无法回避的问题。为此 Gartner 预测:“到 2025 年,全球将有 45% 的组织的软件供应链受到攻击,比 2021 年增加三倍”。在 sonatype 今年的统计中,仅仅在今年已经有超过 24 万 5 千个软件包中被发现包含漏洞,这个数字是从 19 年到 22 年之合的两倍。</p><p>由此可见企业的供应链安全也成为攻击者的主要攻击目标,在调查中我们也发现,多数的受访者都清楚的知道来自供应链的安全风险,但只有不到十分之一的企业受访者表示会在生产供应链生命周期的每个阶段进行安全审核和部署防护措施。由此可见企业安全人员的风险意识与有效的供应链风险管理和防护措施的实施之间还是存在了明显的脱节。</p><p><img src="/img/remote/1460000044584504" alt="图片" title="图片"></p><p>在传统的软件开发流程中,安全人员通常是在系统交付之前才开始介入进行安全审核工作,这样的安全流程显然已经无法满足云原生时代下软件供应链的快速迭代流程。</p><p>来自 Gartner 的分析师 David Cearley 早在 2012 年就首次提出了 DevSecOps 的概念。相较与传统软件开发的安全流程,DevSecOps 强调从企业安全文化意识,安全流程左移以及构建全链路的自动化流程等几个要点来加固新时期下企业软件供应链安全。Gartner 预测,到 2025 年将有 60% 的企业采用并实践 DevSecOps。DevSecOps 模型强调安全和整体软件开发流程的紧密结合,同时也强调了在不降低企业应用开发迭代速度的前提下,通过执行全面的自动化安全防护措施来确保应用制品和供应链管道的安全性。</p><p>在当下,绝大多数的企业云原生安全的发展都落后于应用的云原生化进程,而主要的改进方向也集中在下面这三个方向:</p><ul><li>身份和访问管理:线上授予的权限与实际需要的权限之间存在巨大差异,无疑会给攻击者可乘之机。</li><li>漏洞和配置管理:大多数的企业生产镜像都没有经过安全加固和最小化的裁剪收敛,另外很多线上应用因为开发调式的一时方便而在容器层配置了过高的特权。</li><li>监控和响应:缺少针对容器资产的运行时监控和防护手段,针对突发的攻击事件也无法有效完成定位和溯源。</li></ul><p>这些都是企业应用在云原生化进程中亟需优化和解决的主要安全方向。</p><h2>02 云原生安全体系方法论</h2><p><img src="/img/remote/1460000044584505" alt="图片" title="图片"></p><p>安全在本质上是一个对系统风险发现、定位和管理的流程。在了解云原生安全,而威胁建模可以在应用设计开发的早期阶段,帮助安全人员识别企业应用架构中潜藏的安全风险和设计缺陷。</p><p>在上图中,左边是针对云上资源的典型攻击路径分析,我们看到在传统的云服务架构下,针对身份和控制面的不当配置以及网络攻击是攻击者可以利用的主要途径,攻击者可以通过漏洞利用、非授权访问和数据窃取等手段攻击企业服务和数据;而在右边的云原生 K8s 集群的典型攻击路径中,由于云原生技术架构的复杂性,容器应用、运行时、K8s 编排引擎、镜像仓库以及内核层都可能给整个应用系统引入新的风险,同时在网络侧,不同容器微服务应用之间的东西向流量也提供给攻击者更多的可利用目标。而近年来不断爆出云原生社区相关的 CVE 漏洞中,攻击者可以利用的攻击方式也是多种多样,像一般的提权、仿冒、篡改、抵赖、拒绝服务等典型攻击手段都出现在了近两年公开披露的漏洞利用方式中。</p><p>为此,需要企业安全人员在传统基础设施架构威胁之外尽可能全面的获取安全威胁信息。同时在企业应用架构发生动态变化的同时,也需要重新评估当前威胁建模下的安全机制和模型矩阵是否也需要随之调整。</p><p><img src="/img/remote/1460000044584506" alt="图片" title="图片"></p><p>ATT&CK 框架是网络攻击中涉及的已知策略和技术的知识库,其中阿里云也是国内首家针对云原生容器和 Kubernetes 的攻防场景,提出并发布相应 ATT&CK 攻防矩阵的云服务商。在 ATT&CK 矩阵中详细描述了攻击者在云原生和 Kubernetes 环境发起攻击的过程和手段,可以帮助企业构建容器化应用安全体系,也是企业构建云原生威胁情报体系可以利用和借鉴的基本框架。</p><p>整个威胁矩阵由不同的行和列组成,其中行代表了攻击技术,列代表了攻击战术手段。矩阵从左至右可以代表一个通常的容器侧攻击路径。通过了解矩阵中每一个攻击阶段攻击者可以利用的技术手段,可以帮助企业安全运维人员有针对性地进行安全设计和测试演练,当安全事件发生时,也可以帮助有效实施对应的止血和预先的防护措施。</p><p><img src="/img/remote/1460000044584507" alt="图片" title="图片"></p><p>为了进一步理解云原生应用安全风险并构建完整的安全防护方案,企业安全运维人员还需要先进的分析方法,覆盖对应用侧风险、开源组件风险、云基础设施风险和应用运行时风险的完整感知。</p><p>为此 Gartner 牵头在已有的云安全态势管理(CSPM)、云基础设施授权管理(CIEM)和云工作负载保护平台(CWPP)等传统主流云平台安全模型的基础上,提出了 CNAPP 云原生应用保护平台框架,面向云原生应用从开发到运行时刻的全生命周期流程,帮助企业安全团队和 DevSecOps 架构师提供完整视角的应用风险可见性和相应的解决方案。基于 CNAPP 理论框架,信通院在 2022 年云原生产业联盟年会上发布了《云原生应用保护平台(CNAPP)能力要求》,在 CNAPP 理论框架的基础上,进一步细化了规范要求。</p><p>从架构图中可以看到 CNAPP 框架集成了之前多个成熟规范的核心特性,可以:</p><ul><li>更好地适配云原生应用高速迭代的敏捷特性,通过自动化手段减少错误配置和管理。</li><li>减少参与供应链 CI/CD 管道的工具数量。</li><li>降低云原生应用安全合规实施复杂性和成本。</li></ul><p><img src="/img/remote/1460000044584508" alt="图片" title="图片"></p><p>对于企业应用,安全需求分析、安全测试、安全开发和反复的加固措施也同时伴随着应用的迭代。我们知道企业安全文化意识以及开发、安全运维团队之间的流程协同是 DevSecOps 能够有效实施的关键,在 CNAPP 框架中,也同样强调研发和运维侧双向反馈飞轮,加强企业安全可视性和对风险的洞察力,从整体上改善企业安全态势。上图中的研发和运维侧双向反馈飞轮主要分为下面两个方向:</p><ul><li>从开发到生产:基于安全左移原则,将安全集成到开发人员的工具链中,在代码创建阶段就通过自动化构建管道触发安全测试,以降低后续安全风险和运维成本。</li><li>从生产到开发:需要企业安全管理人员全面监控线上应用和平台配置,并结合运行时安全配置上下文,提前识别风险并考虑风险处理等级预案,同时将相应的加固措施落实到新的开发迭代流程中。</li></ul><p>只有通过这样不断循环反馈,才能保证在云原生下应用的高速迭代的过程中持续的安全水位。</p><p><img src="/img/remote/1460000044584509" alt="图片" title="图片"></p><p>企业在 DevSecOps 的落地实践中可以充分利用云原生技术,同时结合云服务上的安全产品能力以及部署成熟的安全三方产品也可以帮助企业快速构建 DevSecOps 能力。</p><p>企业应用的安全性需要贯穿应用程序的整个生命周期。开发是整个应用生命周期的第一个阶段,其结果是创建用于部署和配置应用的云原生模版、容器镜像、应用二进制等云原生制品,这些制品正是运行时被攻击利用的主要源头,相应这个阶段针对不同制品安全扫描就显得格外重要。</p><p>构建分发阶段包括基于 CI/CD 自动化流程的各种系统测试,尤其针对开源软件,需要进行明确的漏洞风险分级卡点机制,同时加入自动化的加签机制以支持制品的可信校验。</p><p>部署阶段负责进行一系列 “飞行前 ”检查,以确保将部署到运行环境中的应用程序符合整个企业组织的安全和合规规范。</p><p>运行时阶段的安全包括计算、存储和访问控制三个关键领域的安全能力。运行时环境的安全性取决于前几个阶段安全实践的有效性,同时需要企业在配置管理、身份和访问控制以及运行时威胁检测方向上基于安全原则实现高效的自动化监控和管理能力,并且通过全局性的安全资产管理和态势感知能力不断发现风险并反馈到生产开发及供应链各环节。</p><p>最后,企业应用安全需要防患于未然,完备的审计和溯源分析能力以及精准的风险阻断能力可以帮助企业安全运维人员从容应对突发的攻击事件,并在规划的指导下做出快速的决策和响应。</p><p><img src="/img/remote/1460000044584510" alt="图片" title="图片"></p><p>最后,安全左移和循环反馈是指导企业基于 DevSecOps 理念实施安全防护的主要原则。在应用制品的供应链生命周期中应尽早地以自动化方式嵌入安全,通过引入自动化的安全扫描和巡检机制,在早期发现并治理常见的软件 CVE 漏洞,可以帮助团队以低成本的方式扼杀风险,同时整体提升团队安全意识。</p><p>企业在落地并实践了安全左移理念后,并不意味着安全工作的结束。在应用的生产运行阶段,安全管理人员可以采集并掌握更全面的安全上下文信息,并通过威胁分析发现更多在供应链环节无法暴露的安全设计和配置上的问题,只有通过不断的反馈和更新,才能够保持企业应用系统的整体安全水位,同时应对无法预知的安全挑战。</p><h2>03 阿里云容器服务 ACK & 容器镜像服务 ACR 安全产品能力</h2><p>通过上面的介绍,我们对云原生安全面临的挑战以及当下比较成熟的云原生安全理论体系有了初步的了解,下面我会具体介绍阿里云 ACK 和 ACR 服务中面向企业提供了哪些安全相关的产品能力,可以帮助企业实现或优化 DevSecOps 流程。</p><p><img src="/img/remote/1460000044584511" alt="图片" title="图片"></p><p>首先,围绕 DevSecOps 流程中的核心防护能力和自动化要求,阿里云 ACK 和 ACR 服务也沉淀了 DevSecOps 产品能力,帮助企业实现安全可信的软件供应链。</p><p>在镜像构建阶段,客户提交源代码变更后,自动触发 ACR EE 的云原生应用交付链功能,开始容器镜像构建,支持自动安全扫描,如果识别到镜像中存在风险,会自动阻断构建流程并钉钉报警。用户可以一键修复镜像中存在的 CVE 漏洞。在镜像交付阶段,ACR 和 ACK 可以基于客户的秘钥进行镜像的加签与验签,确保整个交付链路无篡改。在容器应用运行时,云安全中心可以对 ACK 集群中运行时风险进行防护、感知,以及阻断处理。</p><p>今年,我们推出了集群容器安全概览功能,可以帮助企业安全管理员更好感知集群配置、应用镜像、容器运行时的安全风险,提升整体安全水位。</p><p><img src="/img/remote/1460000044584512" alt="图片" title="图片"></p><p>DevSecOps 的实践依赖企业内部深层次的协同,而不同的工具和实践流程会阻碍跨部门协作的高效性和生产力。通过标准化的平台能够简化部门间沟通和学习成本,让供应链流程更加透明高效。</p><p>ACK、ACR 充分利用云原生技术,在企业供应链流程的关键路径上构建了核心能力,面向企业安全管理员提供了开箱即用的产品能力,安全人员可以通过简单的可视化白屏操作完成制品校验,安全巡检、策略实施等供应链安全防护能力,同时通过不同维度的可视化监控和报表直观的了解并管理应用安全,帮助企业安全管理人员第一时间洞察风险,应对攻击。</p><p><img src="/img/remote/1460000044584513" alt="图片" title="图片"></p><p>默认状态下的安全性是整个系统安全体系的根基,不仅决定了生产系统的稳定性,也直接关联了上层安全方案的运维和实施成本。为此,在企业应用系统的设计阶段,安全性就应当作为基本且必要的需求融入设计环节,并在安全专家的指导下审核架构设计中潜藏的风险。</p><p>企业应用使用哪种凭据访问云资源?基于默认安全和权限最小化原则,在应用内直接使用 AK 以及在节点上直接绑定云资源访问权限都是安全上不推荐的做法,此时可以将 RRSA 方案集成到企业应用设计和编码环节,通过 RRSA 方案,可以实现基于 K8s serviceaccount,与阿里云 RAM 服务完成基于 OIDC 协议的访问控制认证,并实现以应用维度最小化隔离授权云资源访问权限。</p><p><img src="/img/remote/1460000044584514" alt="图片" title="图片"></p><p>密钥管理一直是企业应用上云的核心问题,云服务商有哪些安全方案可以帮助保护应用密钥?用户又应该在 K8s 环境中采取哪些安全措施帮助管理和使用密钥?应用密钥应该存储在哪里?这些都是企业客户经常会问到的一些基本问题。为此,首先应避免密钥在应用中的硬编码问题。在应用系统开发部署的供应链流程中,任何一个环节对敏感密钥的硬编码都有可能导致泄露风险。通过使用云上 KMS 服务,可以在应用开发、测试、构建等生命周期流程中使用统一方式进行密钥的读写,避免硬编码出现;同时云上的 KMS 服务支持自动化的密钥轮转能力,进一步降低了敏感信息泄露传播的安全风险,同时也可帮助企业应用满足合规需求。</p><p>通过部署 ack-secret-manager 插件可以将 KMS 凭据管家中管理的企业密钥以 K8s secret 的形式同步导入到业务集群中,企业应用可以直接通过文件挂载的方式使用密钥,在避免密钥硬编码问题的同时保证了业务代码的兼容性,在新版本的 ack-secret-manager 中还支持对接KMS服务升级后的专属 KMS 实例,提供更强的密钥安全性隔离保证。</p><p>K8s 社区基于 CSI 存储标准扩展实现了 secrets-store-csi-driver 用于将存储在外部密钥管理服务中的密钥以 volume 存储卷的形式挂载到应用 pods 中。和 ack-secret-manager 方案不同,该机制避免了 K8s secret 实例的创建,带来的好处一是避免 etcd 中出现明文 secret 信息,二来可以在大规模场景下避免 secret 堆积;同时应用仍旧可以保持原先的文件路径方式读取密钥,避免了额外的程序改造代价。</p><p>基于该插件机制我们实现了阿里云自己的 secrets-store-csi-driver-provider,并且支持通过 ACK 应用市场在集群中一键化部署该插件,同样可以将阿里云 KMS 凭据管家中保存的密钥凭据以文件形式同步到应用容器中,同时支持后端凭据修改后的同步更新能力,保证业务容器中密钥信息的实时性。</p><p>当然这里也会有“最后一把密钥”的问题,由于插件需要调用 KMS 凭据管家服务的权限,如何在集群中保护插件对 KMS 服务请求的凭据呢?这里推荐使用 RRSA 方案,可以将 KMS 凭据的请求权限绑定在插件使用的独立 serviceaccount 上,避免将权限泄露给应用 pod 中。</p><p><img src="/img/remote/1460000044584515" alt="图片" title="图片"></p><p>对于数据安全性有严格要求的场景,比如当下火热的 AI 大模型,金融支付、隐私认证或涉及知识产权的核心数据计算,除了保证这些核心敏感信息在读写和传输过程中的安全性,还需保证机密信息在云上节点内存运算和存储过程中的安全可信。今年我们还和 Intel 以及 CoCo 社区合作,基于 Intel TDX 机型实现了新一代的可信执行加密环境,帮助实现企业数据全生命周期的安全可信。</p><p><img src="/img/remote/1460000044584516" alt="图片" title="图片"></p><p>在应用运行时,云原生工作负载区别于传统基于虚机的应用服务有如下特点:</p><ul><li>短暂的生命周期,只有秒级的生命周期;</li><li>编排引擎会根据节点实时资源动态调度工作负载,网络IP等应用元数据可能随应用重启不断变化;</li><li>出于基础设施不可变性,对运行时环境的修改在工作负载重启后不会保留。</li></ul><p>正因为云原生工作负载自身特点,在应用运行时,当前大多数云原生安全产品对容器侧用户态进程的检测分析都存在不足。而 eBPF 天然的技术优势是提升云原生应用安全可观测性和实现精细化安全事件响应的有力武器。</p><p>在 ACK 集群中,我们提供了针对 K8s 应用的 exec 活动审计能力,通过 eBPF agent 可以实时获取容器负载中执行的系统调用,并关联映射到在容器实例中执行的具体进程,从而帮助安全运维人员获取攻击者进入到容器实例后发起攻击的命令审计,有效帮助针对安全事件的溯源和止血。</p><p>同时我们也和 SLS 日志服务提供的强大日志分析检索能力结合,针对云原生的典型漏洞,提供了可疑的漏洞利用活动的溯源和告警能力,并且通过时间线图表的方式直观的展现给企业安全人员。</p><p><img src="/img/remote/1460000044584517" alt="图片" title="图片"></p><p>员工离职后的权限清理问题也是困扰很多企业权限管理员的难题。在 ACK 默认提供的 x509 证书认证模式下,企业安全运维人员很可能由于疏漏在删除 RAM 账号或角色前忘记吊销和清理 kubeconfig 权限。</p><p>通过 ack-ram-authenticator 组件,ACK 托管集群可以通过 Webhook 方式、基于阿里云 RAM 完成请求认证。相较于 ACK 集群默认提供的 x509 证书认证模式,使用 ack-ram-authenticator Webhook 认证方式有如下优点:</p><ul><li>适配企业通过云 SSO 场景,提供灵活可控的数据面 RBAC 授权;</li><li>角色 SSO 对接场景下 apiserver 审计日志中包含企业 IDP 中的身份信息,有效支持对扮演同一角色的不同 IDP 用户的行为审计;</li><li>企业员工离职删除 RAM 账号或 RAM 角色时,可自动清理其在账号所有 ACK 集群中的认证访问权限。</li></ul><h2>04 企业 DevSecOps 安全最佳实践</h2><p><img src="/img/remote/1460000044584518" alt="图片" title="图片"></p><p>“木桶的最大容积取决于最短的一块木板”,云原生安全同样遵循这样的木桶原则。由于云原生技术栈的复杂性,企业安全管理和运维人员更需要在安全准则的指导下,全面充分的了解全局安全风险,提升系统“最低点”安全水位。</p><p>零信任安全最早由 Forrester 首席分析师 John Kindervag 在 2010 年提出,其核心思想是“Never Trust, Always Verify”。在零信任安全模型中,只要处于网络中,默认情况下任何用户都不可信,任何时刻任何环境下设备和服务的身份权限都需要被持续验证。</p><p>权限最小化原则是企业安全运维中最基本也是最重要的准则之一。传统应用架构下,系统的权限管理员需要基于权限最小化原则对内部人员授权。在云原生架构下,授权管理不止针对企业中的账号系统,同时需要考虑松耦合微服务架构下众多服务身份的授权。</p><p>安全左移不仅可以有效降低软件自身漏洞而导致的应用风险,同时也能够有效降低企业开发运维成本。</p><p><img src="/img/remote/1460000044584519" alt="图片" title="图片"></p><p>企业安全管理人员需要在安全系统设计中规划和覆盖应用周期中的每个阶段,在安全左移和循环反馈原则的指导下,结合 CNAPP 等规范框架的理论指导下完成安全产品能力的建设。</p><p>这里也列举了企业生产供应链中在开发,构建部署、运行时和反馈阶段环节需要具备的一些核心能力,时间关系就不一一介绍了。</p><p><img src="/img/remote/1460000044584520" alt="图片" title="图片"></p><p>DevSecOps 在企业的落地实践离不开企业文化理念上的转变,在 DevSecOps 体系中,安全应当是企业内部团队共同的目标,而不应只是安全团队自身的职责;企业开发、运维和安全团队应当协同起来,设定统一的目标并共担责任,同时定义团队之间的交流互动方式,能够有效提升业务迭代效率。</p><p>下面几个方向是企业管理人员在企业文化 DevSecOps 转型中需要关注的重点方向:</p><ul><li>人员:拥有合适的人才是 DevSecOps 的基础。安全培训和培养安全拥护者一直是让安全变得重要的首选解决方案;同时 DevSecOps 需要在安全和效率之间取得适当的平衡,另外持续学习,掌握最新的漏洞和策略对于保证应用程序的安全至关重要。</li><li>流程:制定正确的流程可以确保每个人都站在同一起跑线上,并为安全一致性和凝聚力奠定基础。</li><li>工具:成功实施 DevSecOps 战略的最后一个要素是工具。Kubernetes 安全领域拥有众多工具,可以解决 Kubernetes 和云原生安全的各个层面的问题。当然,在研究和实施安全工具时,也需要避免使用存在重大缺陷的工具。</li><li>绩效:在重视生产效率和版本迭代的前提下,可以将 DevSecOps 的实施列入团队绩效考核,并且通过一些具体指标和分级问责机制的建立也是让 DevSecOps 快速融入团队的有效途径。</li></ul><h2>结语</h2><p>最后,欢迎大家选择和使用更多的阿里云 ACK 和 ACR 服务中提供的安全产品能力,让我们共同努力,让 DevSecOps 流程落地实践到更多的企业生产流程中。</p><p>作者:匡大虎</p><p><strong><a href="https://link.segmentfault.com/?enc=ZuJdzC%2B746KMCVQunz4DSw%3D%3D.KoCjR%2Bi1Acc9Uz8BkzLcFbQxijgY0B%2BUpm4tcgiMqF4WDfWxrHS3aqHQh%2Fowfzg0k%2FDkjN7aK79PKvw%2B%2F4N%2BG81g0VIfkRRsPfF1uqjSjdA%3D" rel="nofollow">原文链接</a></strong></p><p><strong>本文为阿里云原创内容,未经允许不得转载。</strong></p>
考试查分场景重保背后,我们如何进行可用性测试
https://segmentfault.com/a/1190000044581799
2024-01-23T15:28:45+08:00
2024-01-23T15:28:45+08:00
阿里云云栖号
https://segmentfault.com/u/aliyunqi
0
<p>随着通过互联网音视频与知识建立连接的新学习方式在全国范围内迅速普及,在线教育/认证考试的用户规模呈井喷式增长。但教育容不得半点马虎与妥协,伴随用户规模不断增长,保证系统稳定性、有效避免千万考生考试时遭遇故障风险,成为行业认证机构/部门解决的首要难题。</p><p>在某次行业认证考试后,考生登陆查分系统时遭遇白屏、卡顿等问题。因此,行业认证机构/部门开始探索系统稳定性评估的路径。不同于传统线下行业可模拟出对等的生产环境,在线教育/行业认证的压测难以实现同级别的服务集群。数据构造不真实、场景不符实际使用都会造成压测任务与真实场景的偏差。此外,压测工具缺乏安全性、人力成本、IT 成本投入大等问题亦亟待解决。因此,想要完美承受高压检验,就需要进行细致的调研与准备工作。</p><p>为了帮助更多在线教育、认证机构/部门避免以上问题,我们完整复盘如何进行一次完整性能测试,涵盖部署架构资源风险输出与优化、应用实时监控与告警(可观测性)、系统容量评估与性能优化(压测)、活动远程保障与事后项目复盘。</p><h2>第一步:需求调研与目标制定</h2><p>为了更好的协调多方力量及保证项目执行足够聚焦,先设定一个业务目标。面对一个存在“白屏、卡顿”等问题的 Web 系统,与业务团队沟通初步制定「系统可以支撑 5 万 QPS 访问量」的目标。由于即将来临新的业务高峰,本次压测的初衷并不是在两周内对应用系统进行大幅度技术改造,而是通过压力测试发现应用的重大性能瓶颈并对之进行优化改造,并通过流量摸高方式了解系统真实服务能力,辅以分流等手段保障服务的可用性。</p><h2>第二步:资源评估</h2><h3>(一)工具评估</h3><p>进行高并发服务保障,除了对应用的服务能力进行一定扩容之外。由于行业认证机构/部门此前在云上未进行过压力测试,因此需要购买压测工具以及相应的监控工具,这里使用了阿里云性能测试 PTS、应用实时监控服务 ARMS,这里需要注意的是:</p><ul><li>性能测试 PTS,工具本身不收费,根据流量进行收费,所以需要根据压测规模、压测目标、压测次数,提前预估压测资源包的额度。首次开通性能测试 PTS,赠送 5000 VUM 免费额度,可以用来帮助团队熟悉工具的使用或进行初次测试。</li><li>应用实时监控服务 ARMS,目前按照数据写入量进行计费,提供每个月 50 GB 免费额度,这个数据写入量与 JVM 进程数量、存储时间相关,免费额度基本满足本次压测需求。</li><li>Web 应用防火墙 WAF,由于本次压力测试是在真实生产环境进行,流量会过 WAF。由于 WAF 按照流量计费,压测目标超过用户所购买的 WAF 规格包。WAF 3.0 版本,当前规格带宽 100M,5K QPS,压测目标 5 万 QPS,超出部分按量计费,不使用不收费,按 45K QPS 估算,0.15/QPS/天,按 3 次压测+分数查询首日,共 4 次预估费用 2.7 万元。</li></ul><h3>(二)资源梳理</h3><ul><li>与研发团队对齐业务系统架构、业务资源容量情况及压测环境、压测工具和业务接口信息沟通。</li><li>关键业务接口梳理完成 (非全量,关键 API)。</li><li>重保压测资源与费用评估。以 5 万 QPS 为目标,系统压力测试费用评估,包括测试所需的 ECS 、PTS、ARMS、WAF 等费用。</li><li>确定最终资源使用规划。按生产等比配置测试环境,机器数量 6 台,升级新购资源费用,初步费用评估完成。</li></ul><h2>第三步:压测摸高</h2><h3>(一)第一轮压测:问题初现</h3><p>在完成压测环境、系统数据准备以及压测场景配置之后。开通 ARMS 完成 Java 应用接入,同时提供压测环境的服务器清单,开始 PTS 压测环节。其中,因为域名所属行业特殊,PTS 压测域名需要开白才可以。我们开始第一轮压测。</p><p>【压测结果】</p><p>「登录-查分」并发用户数 3000,平均 RT 1631ms,平均 TPS 1964,错误数 1.7 万。</p><p><img src="/img/remote/1460000044581801" alt="图片" title="图片"></p><p>【问题发现】</p><p>应用压测过程中有大量的 5s 超时问题,后续调整 PTS 超时时间。</p><p><img src="/img/remote/1460000044581802" alt="图片" title="图片"></p><p>【问题发现】</p><p>概览所有环节中,验证码环节耗时最长,RT 平均能达到 7s 。</p><p><img src="/img/remote/1460000044581804" alt="图片" title="图片"></p><p>调整 GTM 主备配置互换,启动第一轮压测,最高 3K QPS 不及预期。同时,调整 tomcat 应用连接池大小至 4096。因为与生产环境共用,只能业务空闲时间进行压测,导致压测进度与预期不符,调整 SLB 转发规则并指向测试服务器组。同时,阿里云建议后续研发团队可将验证码信息存储到 Redis 中来提升性能。从压测情况看研发侧优化效果较好,但 RT 波动较大。云原生应用平台团队给出一些优化建议后,RT 波动问题明显改进。</p><p><img src="/img/remote/1460000044581805" alt="图片" title="图片"></p><h3>(二)第二轮压测:持续改进</h3><p>在优化了一些中间件优化之后,我们基本逐渐提升并发用户数继续进行第二轮测试,并持续改进。</p><p>【压测结果】</p><p>「登录-查分」并发用户数 1 万,平均 RT 1560ms,平均 TPS 6082,错误数 6.2 万。</p><p><img src="/img/remote/1460000044581806" alt="图片" title="图片"></p><p>「登录-查分」并发用户数 2 万,平均 RT 2916ms,平均 TPS 6831,错误数 3390。</p><p><img src="/img/remote/1460000044581807" alt="图片" title="图片"></p><p>【问题发现】</p><p>通过对比测试,我们发现应用承载能力就是 1 万并发用户数、平均 RT 1.5s。提升 1 倍并发用户后,服务器平均 TPS 没有提升,只是 RT 增加了 1 倍。</p><p>针对上述问题,研发团队进行了优化。通过在内网使用 Jmeter 测试,看到单台服务器性能有明显提升,并发现 Redis 存在可优化点。进一步分析发现,很多慢请求都是访问用户的自建 Redis,但研发团队反馈 Redis 延时很小,并且切换到阿里云 Redis 后未发现改进。因为之前验证码环节性能很差,压测环境都跳过该环节。目前这部分优化已经完成,在测试增加了验证码环节。验证码环节压测需要特殊配置,配置好后继续测试。当天结果瓶颈还未找到,QPS 稳定在 1.2 万、RT 2-3s,再加大压到 5 万,无明显改善。</p><h3>(三)第三轮压测:问题突破</h3><p>因为目前整体服务承载能力多次优化后,稳定无法提升,阿里云建议尝试通过增加服务器数量压测,由此判断是应用服务器性能,还是数据库服务器性能导致目前瓶颈。如果横向扩展应用服务器性能能提升,就是应用服务器问题,否则就是数据库这种单点服务的问题。应用服务器从 6 台增加到 8 台,服务能力并未看到线性上升,QPS 增加到 1.3 万左右。结合此现状,可以判断是单点问题限制,推断可能是 Oracle 数据库、Redis,但研发团队反馈压测时两个产品链接不多,响应速度在毫秒级。经过对压测报告的分析,发现滑块验证处理比较慢,耗时较长,研发团队将滑块验证改为字符验证码。并发起新一轮的压测。</p><p><img src="/img/remote/1460000044581808" alt="图片" title="图片"></p><p>【压测结果】</p><p>添加 Redis 后,3 万用户,3 分钟,性能几乎翻倍。「登录-查分」并发用户数 3 万,平均 RT 1514ms,平均 TPS 20145,错误数 2960。</p><p><img src="/img/remote/1460000044581809" alt="图片" title="图片"></p><p>「登录-查分」并发用户数 5 万,平均 RT 4552ms,平均 TPS 13744,错误数 21.6 万。</p><p><img src="/img/remote/1460000044581810" alt="图片" title="图片"></p><p><img src="/img/remote/1460000044581811" alt="图片" title="图片"></p><p>【问题发现】</p><p>通过对比测试,发现应用服务器的承载能力在翻倍提升后,稳定在 2 万 TPS。即便把并发提升到 5 万,该指标也未能再继续提升。Redis 扩容后(64c 128g *3),性能提升 1 倍,RTS 稳定在 2.2 万,RT 1-2s 。尝试使用阿里云 Redis(7c8g 4db)压测,但与自建 Redis 相比规格小太多,测试结果性能提升不大。</p><p>应用 8 台服务器最高 QPS 到 2.5 万,按照 5 万 QPS,届时分流需要拆分 2.5 万到静态页面。测试压测单台分流服务器静态页面 RTS 支撑能力为 4 万,静态页面使用 404 页面是否合理待评估。</p><p>「登录-繁忙」并发用户数 2.5 万,平均 RT 582ms,平均 TPS 41772,错误数 10.9 万。</p><p><img src="/img/remote/1460000044581812" alt="图片" title="图片"></p><p>SLB 负载不均是健康检查失败导致的,静态页返回 404,SLB 层面不会抑制请求转发,会正常分发请求给该应用服务器。</p><h2>第四步:上线保障</h2><p>在上述多轮压测以及优化之后,我们进行最后一轮压测:业务服务器+静态页面 压测达到预期业务目标 5 万 QPS,按 3 : 1 比例分发请求,度过业务高峰后快速关闭静态页服务器。</p><p>【压测结果】</p><p>「登录-查分」并发用户数 2.5 万,平均 RT 1030ms,平均 TPS 22965,错误数 44(6 台生产机器总体处理能力)。</p><p><img src="/img/remote/1460000044581813" alt="图片" title="图片"></p><p>「登录-查分」并发用户数 2.5 万,平均 RT 396ms,平均 TPS 64887,错误数 72.2 万。</p><p><img src="/img/remote/1460000044581813" alt="图片" title="图片"></p><p>【压测摸高】</p><p>10 台应用服务处理能力最高 2.5 万 TPS,其中 3 台应用服务器上同时部署静态页面,应用程序和静态页面权重比例 1 : 1压测。并发 4 万、RT 396ms、TPS 64887ms、达到预期目标 5 万 TPS。最后一次持续高并发压测,并发 2.5 万,RT有抖动,TPS 维持在 2 万,成功率 99% 以上。通过最后的压测结果,结合资源现状进行保障方案落地:开放查分入口首日,静态页面与应用程序权重比例调整为 100 : 30 ,总体处理能力 3 万 TPS。</p><p>【开放查分】</p><p>晚 23 时开放查分,流量小于预期,系统平稳运行度过峰值 QPS 1.6W。</p><p><img src="/img/remote/1460000044581814" alt="图片" title="图片"></p><h2>第五步:优化总结</h2><p>经过多轮的压测以及前期优化,应用及架构找到多个瓶颈点并进行改造优化,比如验证码模块性能差、单 Redis 改为集群 Redis、应用多线程处理能力、业务处理能力随资源增加而线性提升等都进行相应的验证和优化。在现有条件下,优化后的应用和架构的健壮性大幅提升,积累了该应用的资源容量评估经验,后续可以随着业务量增减,有数据依据的增减资源,日常保持好水位线即可。同时,我们梳理了诸多日常优化方案,其中包括:</p><h3>一、安全风险预警。</h3><p>重保期间请求流量尚未经过 Web 应用防火墙,缺失常见攻击防御能力,后续考虑请求流量过 WAF 且动静资源分离,静态资源通过 CDN 加速分发。一方面,减轻业务服务器对静态资源处理压力和带宽压力;另一方面,有效降低 WAF 带宽压力与成本。</p><h3>二、数据库产品存在单点风险与升降配不灵活问题。</h3><p>在 ECS 云服务器上的自建 Oracle 数据库存在单点故障风险,一旦单个服务出现异常整个平台会彻底不可用。自建的 Oracle 数据库与 Redis 服务,无法灵活改配,不便于日常使用与重保期间进行能力切换。后期计划通过改造使用云上的数据库,加强可用性的同时,灵活升降配,进一步贴近当前业务需求。</p><h3>三、应用存在大规格服务器资源无法利用问题。</h3><p>目前应用单体架构耦合度高,无法经济的单独部署更多涉及性能瓶颈的模块。后续计划对应用内部模块进行拆分,以便让应用可以有更合理的部署架构。另外,针对目前问题,后续重保期间扩容的应用服务器采用更多低规格服务器来提升性能。从现在的 64C128G 变为 16C32G,从而获得 4 倍应用服务能力。</p><h3>四、在日常研发中使用 PTS 进行持续压测。</h3><p>通过本次重保压测,研发团队已经在阿里云 PTS 产品团队支持下充分掌握该工具的使用方法。该工具拥有的快速创建多地压测节点的能力充分利用的阿里云平台的多地域优势,能快速模拟实际业务场景进行全链路压测,大大的节约了应用问题发现与改进时间。是本次重保环节中的核心功臣。</p><h3>五、继续在日常应用服务环节使用 ARMS 监控。</h3><p>通过 ARMS 应用监控,在压测过程中发现很多细节问题,为快速的定位问题提供极大便利,大大提升问题定位效率,是不可多得的运维必备工具。</p><h2>第六步:查漏补缺</h2><h3>一、PTS 是一款非常容易上手且便捷的压力测试工具,使用 PTS 可以迅速提升测试效率;</h3><p>1)使用自带的录制控件可以快速录制场景,自动捕捉需要压测的接口;</p><p>2)产品公共云值班同学能耐心给予产品问题解答,即便是新手也可以立即上手使用;本次测试过程中,研发团队是第一次使用该产品,交付团队也不是熟手,但是使用十分丝滑,整个过程中并未觉得不顺手;</p><h3>二、通过压测发现系统瓶颈的过程是一个持续寻找问题的过程,压测能给系统压力然后暴露出系统的瓶颈;</h3><p>1)单 Web 服务器并发能力需要第一步得到答案。分布式架构或者单体架构都没关系,重要的是要获取每个服务角色的单机能力。服务器的规格并不是越大越好,比如这次我们最后都无法给予一个 64C128G 的 Web 服务器超过 50% 压力,合适的规格是业务规划最重要的评估项。</p><p>2)确认单 Web 服务节点的能力后,就可以提升服务器数量进行整体压测,这样扩展下去就能知道在达到压测目标的情况下,每个服务器角色需要多少台。除非是严重的 Web 服务角色节点性能问题,短期内提升服务器数量都可以大规模提升服务能力。</p><p>3)想要更快的暴露系统架构中的单点瓶颈,可以横向扩展的服务器扩展到一定规模。这种单点瓶颈一般就是数据库,例如关系型数据库、缓存数据库、分布式数据库。如果压测到单点瓶颈,优化关系型数据库最简单的方式就是提升服务器规格;如果无可提升就需要使用读写分离来分担压力。如果使用可以横向扩展的数据库,就可通过扩容节点来提升能力,使系统整体服务能力提升。在高并发场景下,使用内存数据库无疑是提升能力的快速通道,尤其是考试查分这种只读场景。</p><h3>三、短时间内能做的事情十分有限,重保这种高并发场景要做的就是保障系统可用性;</h3><p>1)我们本次压测的系统是一个适用于传统自建 IDC 机房并有一定技术历史包袱的系统,采用 Windows + Oracle + 单体架构,想要在短期内改变架构很难。为了保障近期重要的高并发场景,研发团队聚焦于把解决严重的性能缺陷,扛过保障时点。</p><p>2)服务分流是保障系统可用性的最简单手段,8 台 Web 服务器测试得到的应用最高 QPS 才 2 万余,单台 Web 服务器能承载的繁忙页 QPS 就能达到 1 万 QPS。所以,关键时刻保障部分用户可用即可。在完全不可用与排队间取舍,一起排队用已是最优解。</p><p>3)上线前一定要做好保障演练。前端 SLB 最大能承载的流量就是 5 万 QPS,这也是本次演练的目标。因此设计了正式应用服务器承载 3 万 QPS 流量,繁忙页承载 2 万 QPS 流量,在 SLB 端配置权重比例。ARMS 应用监控是秒级监控且调整 SLB 权重实时生效,但只对新连接请求生效,原有长连接不受新权重影响。</p><p>作者:暮角</p><p><strong><a href="https://link.segmentfault.com/?enc=VxNIaIpNGkr7DQyovM5k6Q%3D%3D.19zzw%2FZJDfTccOwa9IDEGNhZXwyOPFQrAUAmnhFG6zwggkHgnxGAXQZiXo4LVxFL" rel="nofollow" title="?utm_content=g_1000388712">原文链接</a></strong></p><p><strong>本文为阿里云原创内容,未经允许不得转载。</strong></p>
解密最受欢迎的开源 Serverless 框架:流量篇
https://segmentfault.com/a/1190000044581189
2024-01-23T14:54:39+08:00
2024-01-23T14:54:39+08:00
阿里云云栖号
https://segmentfault.com/u/aliyunqi
0
<p><img src="/img/remote/1460000044581191" alt="图片" title="图片"></p><p>对于 web 应用来说,通过请求流量的并发数、qps、rt 等指标,可以很好的衡量当前的 web 服务质量。Knative 中提供了基于请求驱动的 Serverless 能力,包括多版本管理流量,流量访问,基于流量的弹性以及监控等。本文从流量角度出发,为您解密 Knative 相关的能力。</p><p>Knative 是一款基于 Kubernetes 的开源 Serverless 应用编排框架,其目标是制定云原生、跨平台的 Serverless 应用编排标准。Knative 主要功能包括基于请求的自动弹性、缩容到 0、多版本管理、基于流量的灰度发布、函数部署以及事件驱动等。</p><h2>流量管理</h2><h3>如何做蓝绿发布</h3><p>我们首先看一下,在 K8s 中如果要做基于流量的蓝绿发布需要怎么做?</p><p><img src="/img/remote/1460000044581193" alt="图片" title="图片"></p><p>首先需要创建对应的 K8s Service 与 Deployment,如果需要弹性,则还需要配置 HPA,然后在流量灰度发布时,要创建新的版本。以上图为例,创始版本是 v1,要想实现流量灰度发布,我们需要创建一个新的版本 v2。创建 v2 时,要创建对应的 Service、Deployment、HPA。创建完之后通过 Ingress 设置对应的流量比例,最终实现流量灰度发布的功能。显然,在 K8s 要做基于流量的蓝绿发布,需要管理多种资源,并且随着版本的迭代,管理起来会更加复杂。</p><p>而在 Knative 做到基于流量的灰度发布,只需要面向 Knative Service 一个资源对象,调整流量比例即可。</p><p><img src="/img/remote/1460000044581194" alt="图片" title="图片"></p><p>Knative 提供了 Serverless 应用模型的抽象:Service。Knative Service 中包含两部分配置,一部分用于配置工作负载,叫做 Configuration,每次 Configuration 内容更新都会创建一个新的 Revision。另一部分 Route 主要负责 Knative 的流量管理。可以这样理解:Knative Revision</p><p><img src="/img/remote/1460000044581195" alt="图片" title="图片"></p><p>Ingress + Service + Deployment + 弹性(HPA) 。一个 Knative Service 流量配置示例如下:</p><pre><code>apiVersion: serving.knative.dev/v1
kind: Service
metadata:
name: example-service
namespace: default
spec:
...
traffic:
- percent: 0
revisionName: example-service-1
tag: staging
- percent: 40
revisionName: example-service-2
- percent: 60
revisionName: example-service-3</code></pre><p>不同的 revision 版本之间只需要配置对应的流量比例,即可进行流量的蓝绿发布。而回滚到原版本的操作亦是如此,只需要将新版本的流量切回到 0,原版本设置为 100 即可。</p><h3>指定 tag 进行版本验证</h3><p>在实际发布新版本上线时,对于新版本我们往往需要在切入生产流量之前验证这个版本是否有问题,但这时候新版本流量为 0,如果进行验证呢?Knative 中提供了 tag 机制可以做到。也就是对某个版本打上 tag,然后 Knative 会自动生成改 tag 的访问地址。</p><p>例如,上面的 example-service-1 版本中设置了 staging 的 tag,就会创建一个 <a href="https://link.segmentfault.com/?enc=V1dIukFZvIhhWF0U0JX9cA%3D%3D.MJJM8gaoqBTTLdU0W%2BtvYtT%2Bykxfr%2BtGmsr9pKaQh5IHrT%2B5OAwzK8i4FdtEPXBf8Q9lE%2FMr9iDgVWKszdstBg%3D%3D" rel="nofollow">http://staging-example-service.default.example.com</a> 的访问地址。通过这个访问地址就可以直接验证 example-service-1 版本,而不用担心线上流量访问该版本,做到了指定版本验证的能力。</p><h3>Revision 版本的 GC 策略</h3><p>Knative Service 每次修改就会创建新的版本,而随着迭代的加速,必然会导致很多历史版本,那么对历史版本如何清理呢?Knative 中提供了版本自动清理能力。可以通过 config-gc 配置 GC 策略。这里的参数说明一下:</p><ul><li>retain-since-create-time:表示 revision 从创建时间开始多长时间保留,默认是 48 小时。</li><li>retain-since-last-active-time:表示从最后一次活跃状态(表示被 route 引用,即使 traffic 配置为 0,只要被引用也就表示活跃)开始多长时间保留,默认是 15 小时。</li><li>min-non-active-revisions:最少非活跃的版本数,默认是 20 个版本数。</li><li>max-non-active-revisions:最大非活跃的版本数,默认是 1000 版本数。</li></ul><pre><code>apiVersion: v1
kind: ConfigMap
metadata:
name: config-gc
namespace: knative-serving
labels:
app.kubernetes.io/name: knative-serving
app.kubernetes.io/component: controller
app.kubernetes.io/version: "1.8.2"
data:
_example: |
# ---------------------------------------
# Garbage Collector Settings
# ---------------------------------------
# Duration since creation before considering a revision for GC or "disabled".
retain-since-create-time: "48h"
# Duration since active before considering a revision for GC or "disabled".
retain-since-last-active-time: "15h"
# Minimum number of non-active revisions to retain.
min-non-active-revisions: "20"
# Maximum number of non-active revisions to retain
# or "disabled" to disable any maximum limit.
max-non-active-revisions: "1000"</code></pre><p>例如,如果要配置立即回收 inactive revision,可以这样配置:</p><pre><code>min-non-active-revisions: "0"
max-non-active-revisions: "0"
retain-since-create-time: "disabled"
retain-since-last-active-time: "disabled"</code></pre><p>例如,如果要配置只保留 10 个 inactive revision,可以这样配置:</p><pre><code>retain-since-create-time: "disabled"
retain-since-last-active-time: "disabled"
max-non-active-revisions: "10"</code></pre><h2>流量访问</h2><h3>多网关支持</h3><p>为了满足不同场景的诉求,我们提供了多样化的网关能力,包括 ALB、MSE、ASM 以及 Kourier 网关。</p><h4>ALB</h4><p>阿里云应用型负载均衡 ALB(Application Load Balancer) 之上提供更为强大的 Ingress 流量管理方式,提供全托管免运维的方式,并且提供自动弹性能力。</p><p><img src="/img/remote/1460000044581196" alt="图片" title="图片"></p><p>配置 ALB 网关,只需要在 config-network 进行如下设置</p><pre><code>apiVersion: v1
kind: ConfigMap
metadata:
name: config-network
namespace: knative-serving
labels:
app.kubernetes.io/name: knative-serving
app.kubernetes.io/component: networking
app.kubernetes.io/version: "1.8.2"
data:
ingress.class: "alb.ingress.networking.knative.dev"
...</code></pre><h4>微服务网关 MSE</h4><p>MSE 云原生网关是兼容 K8s Ingress 标准的下一代网关产品,将传统的流量网关和微服务网关功能合并。Knative 结合 MSE 网关支持基于请求的精准自动弹性(mpa),支持精准控制单个 Pod 请求并发处理数。</p><p><img src="/img/remote/1460000044581197" alt="图片" title="图片"></p><p>配置 MSE 网关,只需要在 config-network 进行如下设置:</p><pre><code>apiVersion: v1
kind: ConfigMap
metadata:
name: config-network
namespace: knative-serving
labels:
app.kubernetes.io/name: knative-serving
app.kubernetes.io/component: networking
app.kubernetes.io/version: "1.8.2"
data:
ingress.class: "mse.ingress.networking.knative.dev"
...</code></pre><h4>服务网格 ASM(Istio)</h4><p>阿里云服务网格(简称 ASM)是一个统一管理微服务应用流量、兼容 Istio 的托管式平台。通过流量控制、网格观测以及服务间通信安全等功能,服务网格 ASM 可以全方位地简化服务治理。</p><p><img src="/img/remote/1460000044581198" alt="图片" title="图片"></p><p>Knative 天然支持与 Istio 的集成,因此只需要在 config-network 配置 istio.ingress.networking.knative.dev 即可:</p><pre><code>apiVersion: v1
kind: ConfigMap
metadata:
name: config-network
namespace: knative-serving
labels:
app.kubernetes.io/name: knative-serving
app.kubernetes.io/component: networking
app.kubernetes.io/version: "1.8.2"
data:
ingress.class: "istio.ingress.networking.knative.dev"
...</code></pre><h4>Kourier</h4><p>Kourier 是一个基于 Envoy 架构实现的轻量级网关,提供 Knative Revisions 流量分发,支持 gRPC 服务、超时和重试、TLS 证书和外部认证授权等功能。</p><p><img src="/img/remote/1460000044581199" alt="图片" title="图片"></p><p>只需要在 config-network 配置 kourier.ingress.networking.knative.dev 即可:</p><pre><code>apiVersion: v1
kind: ConfigMap
metadata:
name: config-network
namespace: knative-serving
labels:
app.kubernetes.io/name: knative-serving
app.kubernetes.io/component: networking
app.kubernetes.io/version: "1.8.2"
data:
ingress.class: "kourier.ingress.networking.knative.dev"
...</code></pre><p>上述网关总的来说,ALB 专注与应用负载均衡,云原生网关 MSE 专注于微服务场景,而 ASM 提供了服务网格(Istio)的能力,用户可以结合自身的业务场景选择相应的云产品网关产品,当然如果用户仅需基础的网关能力,也可以选择 Kourier。</p><p>选择适合自己的 Knative 网关请参考:<a href="https://link.segmentfault.com/?enc=ueY6qWqh6rAlzZ711uhoLw%3D%3D.qyZsEtwX2hXbIjRCwJD5fJTJ%2FwPXD9FzGJiIsNeHZxvjjQvyltRXU2zsB5GykCG8ApHsT574y%2FQcaFXyh%2Fu5VRZULzhhYQdRien27Mtr%2FT0PKTiuvVbrCYX2JER6sbx1" rel="nofollow">https://help.aliyun.com/zh/ack/serverless-kubernetes/user-gui...</a></p><h3>多协议支持</h3><p>Knative 支持多种访问协议:HTTP、gRPC 以及 WebSocket。一个 Knative gRPC 服务配置示例如下:</p><pre><code>apiVersion: serving.knative.dev/v1
kind: Service
metadata:
name: helloworld-grpc
spec:
template:
metadata:
annotations:
autoscaling.knative.dev/class: kpa.autoscaling.knative.dev
spec:
containers:
- image: docker.io/moul/grpcbin # 该镜像是一个用于测试gRPC的工具,它通过提供gRPC服务来响应请求。
env:
- name: TARGET
value: "Knative"
ports:
- containerPort: 9000
name: h2c
protocol: TCP</code></pre><p>gRPC 服务在 Knative 服务中 port 字段下的 name 设置为 h2c。</p><p>此外,为了满足单个服务同时暴露 HTTP 和 gRPC 的诉求,我们也扩展了 Knative 能力,支持同时配置 HTTP 和 gRPC 服务暴露,配置示例如下:</p><pre><code>apiVersion: serving.knative.dev/v1
kind: Service
metadata:
name: helloworld-grpc
annotations:
knative.alibabacloud.com/grpc: grpcbin.GRPCBin
spec:
template:
metadata:
annotations:
autoscaling.knative.dev/class: kpa.autoscaling.knative.dev
spec:
containers:
- image: docker.io/moul/grpcbin
args:
- '--production=true'
env:
- name: TARGET
value: "Knative"
ports:
- containerPort: 80
name: http1
protocol: TCP
- containerPort: 9000
name: h2c
protocol: TCP</code></pre><h3>自定义域名</h3><p>在 Knative 中,可以对单独的 Knative Service 自定义域名,也支持全景的域名后缀配置,此外也支持自定义 path。</p><h4>为单独服务自定义域名</h4><p>如果想自定义单个 Service 的域名,可以使用 DomainMapping。DomainMapping 配置模版如下:</p><pre><code>apiVersion: serving.knative.dev/v1alpha1
kind: DomainMapping
metadata:
name: <domain-name>
namespace: <namespace>
spec:
ref:
name: <service-name>
kind: Service
apiVersion: serving.knative.dev/v1
tls:
secretName: <cert-secret></code></pre><ul><li><domain-name> 设置服务域名</li><li><namespace> 设置命名空间,与服务所在的命名空间一致</li><li><service-name> 目标服务名称</li><li><cert-secret>(可选)证书 secret 名称</li></ul><h4>自定义全局域名后缀</h4><p>可以通过修改 config-domain,配置全局域名后缀。如使用 <a href="https://link.segmentfault.com/?enc=%2FkGFtfhaLVB1e1r9IPcH%2Bg%3D%3D.qOmHa0oslqPXTRElz2witv49UwXW28Lrcv%2BgibMbJr0%3D" rel="nofollow">http://mydomain.com</a> 替换掉 <a href="https://link.segmentfault.com/?enc=ngEMk5vOf7IgFqvtZSqHGA%3D%3D.oMd5JEtO1uUz2iE0FNfkj2rpK0CP4lVeSQSqBAml5DQ%3D" rel="nofollow">http://example.com</a>。修改配置如下即可:</p><pre><code>apiVersion: v1
kind: ConfigMap
metadata:
name: config-domain
namespace: knative-serving
data:
mydomain.com: ""</code></pre><h4>自定义 Path</h4><p>此外,可以通过 <a href="https://link.segmentfault.com/?enc=SWUaO7C1s7r%2BY0q%2Fvupdfw%3D%3D.qxWDd5vxx9itgE38bBTDa540MYtXvSO8fIprPHUw5qx7hmujvQJDXA8xHQFLjc0%2F" rel="nofollow">http://knative.aliyun.com/serving-ingress</a> 注解,配置自定义的路由 Path,示例如下:</p><pre><code>apiVersion: serving.knative.dev/v1
kind: Service
metadata:
name: coffee-mydomain
annotations:
knative.aliyun.com/serving-ingress: cafe.mydomain.com/coffee
spec:
template:
metadata:
spec:
containers:
- image: registry.cn-hangzhou.aliyuncs.com/knative-sample/helloworld-go:160e4dc</code></pre><h2>流量弹性</h2><p>Knative 提供基于流量请求的自动扩缩容 KPA(Knative Pod Autoscaler)能力。实现原理是:Knative Serving 会为每个 Pod 注入一个名为 queue-proxy 的 QUEUE 代理容器,该容器负责向 Autoscaler 报告业务容器的并发指标。Autoscaler 接收到这些指标之后,会根据并发请求数及相应的算法,调整 Deployment 的 Pod 数量,从而实现自动扩缩容。</p><p><img src="/img/remote/1460000044581200" alt="图片" title="图片"></p><p>Knative Pod Autoscaler(KPA)基于每个 Pod 的平均请求数(或并发数)进行自动扩缩容,Knative 默认使用基于并发数的自动弹性,每个 Pod 的最大并发数为 100。此外,Knative 还提供了目标使用率(target-utilization-percentage)的概念,用于指定自动扩缩容的目标使用率。</p><p>基于并发数弹性为例,Pod 数计算方式如为:Pod 数=并发请求总数/(Pod 最大并发数*目标使用率)。</p><p>例如,如果服务中 Pod 最大并发数设置为 10,目标使用率设置为 0.7,此时如果接收到了 100 个并发请求,则 Autoscaler 就会创建 15 个 Pod(即 100/(0.7*10)≈15)。</p><p>此外当请求为 0 时,支持 Pod 数自动缩容到 0 。</p><p>具体 Knative 弹性介绍详见:《解密最受欢迎的开源 Serverless 框架弹性技术实现》</p><h2>流量监控</h2><p>Knative 如何采集流量指标,关键还是 queue-proxy。queue-proxy 除了用于流量弹性之外,还提供 Promethues 指标暴露,如请求数,并发数,响应时长等。其端口说明如下:</p><p>• 8012:queue-proxy 代理的 http 端口,流量的入口都会到 8012<br>• 8013:http2 端口,用于 grpc 流量的转发<br>• 8022:queue-proxy 管理端口,如健康检查<br>• 9090: queue-proxy 的监控端口,暴露指标供 autoscaler 采集,用于 kpa 扩缩容<br>• 9091:prometheus 应用监控指标(请求数,响应时长等)<br>• USER_PORT,是用户配置的容器端口,即业务实际暴露的服务端口,在 ksvc container port 配置的</p><p><img src="/img/remote/1460000044581201" alt="图片" title="图片"></p><p>通过 Prometheus 采集到的关键指标如下:</p><p><img src="/img/remote/1460000044581202" alt="图片" title="图片"></p><p>此外 Knative 提供了 grafana 大盘:<a href="https://link.segmentfault.com/?enc=YZxA2WLEsX4dlMG1NgBzcw%3D%3D.egGXTC9SkM%2BWBtNMMmqED6kHKVUv7Q%2B1zq1qiG3JHeVHxxa4VYFiYe9M%2FD2I6odHAatYaDL%2BWUTQb8%2BNxjh0gTbZ3uZqe7p52LrXKBF4%2BjA%3D" rel="nofollow">https://github.com/knative-extensions/monitoring/tree/main/grafana</a></p><p>阿里云容器服务 Knative 集成了该 grafana大盘, 提供了开箱即用的可观测能力,通过大盘可以查看请求数、请求成功率、Pod 扩缩容趋势以及请求响应延迟等。Overview:可以查看 Knative 的请求量、请求成功率、4xx(客户端错误)、5xx(服务器端错误)和 Pod 扩缩容趋势的监控数据。</p><p><img src="/img/remote/1460000044581203" alt="图片" title="图片"></p><p>大盘数据的纵轴 ops/sec 表示每秒处理请求数。</p><p>Response Time:可以查看 Knative 的响应延迟数据,包括 P50、P90、P95 和 P99。</p><p><img src="/img/remote/1460000044581204" alt="图片" title="图片"></p><p>Autoscaler:可以查看 Knative 的请求并发数的详细数据。</p><p><img src="/img/remote/1460000044581205" alt="图片" title="图片"></p><p>Resource Usages:可以查看 Knative 的资源使用量情况,包括 CPU 和内存。</p><p><img src="/img/remote/1460000044581206" alt="图片" title="图片"></p><p>基于这些指标,我们可以很容易计算出 1 个请求的资源使用量。</p><h2>小结</h2><p>本文介绍了 Knative 流量管理、流量访问、基于流量的弹性以及监控,并且我们提供了丰富的云产品网关能力,适用于不同的业务场景。可以看到基于 Knative,可以轻松做到基于流量的按需使用、自动弹性的 Severless 能力。</p><p>作者:元毅</p><p><strong><a href="https://link.segmentfault.com/?enc=kb0iQ8FhLlRaen2Tb5U7Dg%3D%3D.R1E8YsSM6xZZPmzIKp012F325UPXt7oX1oFzLRiIm1B3gN6KY%2FuECVDammjkUEBXPbDRjVuZeRv54DiJ9%2FDP36Tgz%2BaWYLsj47U6ATD7YCk%3D" rel="nofollow">原文链接</a></strong></p><p><strong>本文为阿里云原创内容,未经允许不得转载。</strong></p>
Mixtral 8X7B MoE 模型基于阿里云人工智能平台PAI实践合集
https://segmentfault.com/a/1190000044578752
2024-01-22T17:59:41+08:00
2024-01-22T17:59:41+08:00
阿里云云栖号
https://segmentfault.com/u/aliyunqi
0
<p>Mixtral 8x7B大模型是Mixtral AI推出的基于decoder-only架构的稀疏专家混合网络(Mixture-Of-Experts,MOE)开源大语言模型。这一模型具有46.7B的总参数量,对于每个token,路由器网络选择八组专家网络中的两组进行处理,并且将其输出累加组合,在增加模型参数总量的同时,优化了模型推理的成本。在大多数基准测试中,Mixtral 8x7B模型与Llama2 70B和GPT-3.5表现相当,因此具有很高的使用性价比。</p><p>阿里云人工智能平台PAI是面向开发者和企业的机器学习/深度学习平台,提供包含数据标注、模型构建、模型训练、模型部署、推理优化在内的AI开发全链路服务。</p><p>本文介绍如何在PAI平台针对Mixtral 8x7B大模型的微调和推理服务的最佳实践,助力AI开发者快速开箱。以下我们将分别展示具体使用步骤。</p><h2>使用PAI-DSW轻量化微调Mixtral 8x7B MOE大模型</h2><p>PAI-DSW是云端机器学习开发IDE,为用户提供交互式编程环境,同时提供了丰富的计算资源。我们在智码实验室(<a href="https://link.segmentfault.com/?enc=enHoQY2T5NTzebK0%2BS4Sdw%3D%3D.bC5DwxjTleiOkjG3Ei2aV7VseUId4RysxZIrECMGxlM%3D" rel="nofollow">https://gallery.pai-ml.com/</a>)Notebook Gallery中上线了两个微调Mixtral 8x7B MOE大模型的示例,参见下图:</p><p><img src="/img/remote/1460000044578754" alt="图片" title="图片"></p><p>上述Notebook可以使用阿里云PAI-DSW的实例打开,并且需要选择对应的计算资源和镜像。</p><h3>使用Swift轻量化微调Mixtral 8x7B MOE大模型</h3><p>Swift是魔搭ModelScope开源社区推出的轻量级训练推理工具开源库,使用Swift进行这一大模型LoRA轻量化微调需要使用2张GU108(80G)及以上资源。在安装完对应依赖后,我们首先下载模型至本地:</p><pre><code>!apt-get update
!echo y | apt-get install aria2
def aria2(url, filename, d):
!aria2c --console-log-level=error -c -x 16 -s 16 {url} -o {filename} -d {d}
mixtral_url = "http://pai-vision-data-inner-wulanchabu.oss-cn-wulanchabu-internal.aliyuncs.com/mixtral/Mixtral-8x7B-Instruct-v0.1.tar"
aria2(mixtral_url, mixtral_url.split("/")[-1], "/root/")
!cd /root && mkdir -p AI-ModelScope
!cd /root && tar -xf Mixtral-8x7B-Instruct-v0.1.tar -C /root/AI-ModelScope
import os
os.environ['MODELSCOPE_CACHE']='/root'</code></pre><p>当模型下载完毕后,我们使用Swift一键拉起训练任务:</p><pre><code>!cd swift/examples/pytorch/llm && PYTHONPATH=../../.. \
CUDA_VISIBLE_DEVICES=0,1 \
python llm_sft.py \
--model_id_or_path AI-ModelScope/Mixtral-8x7B-Instruct-v0.1 \
--model_revision master \
--sft_type lora \
--tuner_backend swift \
--dtype AUTO \
--output_dir /root/output \
--ddp_backend nccl \
--dataset alpaca-zh \
--train_dataset_sample 100 \
--num_train_epochs 2 \
--max_length 2048 \
--check_dataset_strategy warning \
--lora_rank 8 \
--lora_alpha 32 \
--lora_dropout_p 0.05 \
--lora_target_modules ALL \
--batch_size 1 \
--weight_decay 0.01 \
--learning_rate 1e-4 \
--gradient_accumulation_steps 16 \
--max_grad_norm 0.5 \
--warmup_ratio 0.03 \
--eval_steps 300 \
--save_steps 300 \
--save_total_limit 2 \
--logging_steps 10 \
--only_save_model true \
--gradient_checkpointing false</code></pre><p>模型训练完成后,我们将学习到的LoRA权重合并到模型Checkpoint中:</p><pre><code>!swift merge-lora --ckpt_dir '/root/output/mistral-7b-moe-instruct/v3-20231215-111107/checkpoint-12'</code></pre><p>其中,ckpt_dir参数的值需要替换成模型LoRA权重保存路径。为了测试模型训练的正确性,我们可以使用transformers库进行离线推理测试:</p><pre><code>from transformers import AutoModelForCausalLM, AutoTokenizer
model_id = "/root/output/mistral-7b-moe-instruct/v3-20231215-111107/checkpoint-12-merged"
tokenizer = AutoTokenizer.from_pretrained(model_id, device_map='auto')
model = AutoModelForCausalLM.from_pretrained(model_id, device_map='auto')
text = """[INST] <<SYS>>
You are a helpful, respectful and honest assistant. Always answer as helpfully as possible, while being safe. Your answers should not include any harmful, unethical, racist, sexist, toxic, dangerous, or illegal content. Please ensure that your responses are socially unbiased and positive in nature.
If a question does not make any sense, or is not factually coherent, explain why instead of answering something not correct. If you don't know the answer to a question, please don't share false information.
<</SYS>>
写一首歌的过程从开始到结束。 [/INST]"""
inputs = tokenizer(text, return_tensors="pt")
outputs = model.generate(**inputs, max_new_tokens=512)
print(tokenizer.decode(outputs[0], skip_special_tokens=True))</code></pre><h3>使用Deepspeed轻量化微调Mixtral 8x7B MOE大模型</h3><p>我们也可以使用Deepspeed对Mixtral 8x7B MOE大模型进行LoRA轻量化微调。同样的,我们需要使用2张GU108(80G)及以上资源。我们首先下载模型至本地:</p><pre><code>!apt-get update
!echo y | apt-get install aria2
def aria2(url, filename, d):
!aria2c --console-log-level=error -c -x 16 -s 16 {url} -o {filename} -d {d}
mixtral_url = "http://pai-vision-data-inner-wulanchabu.oss-cn-wulanchabu-internal.aliyuncs.com/mixtral/Mixtral-8x7B-Instruct-v0.1.tar"
aria2(mixtral_url, mixtral_url.split("/")[-1], "/root/")
!cd /root && tar -xf Mixtral-8x7B-Instruct-v0.1.tar</code></pre><p>第二步,我们下载一个示例古诗生成数据集,用户可以根据下述数据格式准备自己的数据集。</p><pre><code>!wget -c https://pai-quickstart-predeploy-hangzhou.oss-cn-hangzhou.aliyuncs.com/huggingface/datasets/llm_instruct/en_poetry_train_mixtral.json
!wget -c https://pai-quickstart-predeploy-hangzhou.oss-cn-hangzhou.aliyuncs.com/huggingface/datasets/llm_instruct/en_poetry_test_mixtral.json</code></pre><p>第三步,我们可以修改示例命令的超参数,并且拉起训练任务。</p><pre><code>!mkdir -p /root/output
!deepspeed /ml/code/train_sft.py \
--model_name_or_path /root/Mixtral-8x7B-Instruct-v0.1/ \
--train_path en_poetry_train_mixtral.json \
--valid_path en_poetry_test_mixtral.json \
--learning_rate 1e-5 \
--lora_dim 32 \
--max_seq_len 256 \
--model mixtral \
--num_train_epochs 1 \
--per_device_train_batch_size 8 \
--zero_stage 3 \
--gradient_checkpointing \
--print_loss \
--deepspeed \
--output_dir /root/output/ \
--offload</code></pre><p>当训练结束后,我们拷贝额外配置文件至输出文件夹:</p><pre><code>!cp /root/Mixtral-8x7B-Instruct-v0.1/generation_config.json /root/output
!cp /root/Mixtral-8x7B-Instruct-v0.1/special_tokens_map.json /root/output
!cp /root/Mixtral-8x7B-Instruct-v0.1/tokenizer.json /root/output
!cp /root/Mixtral-8x7B-Instruct-v0.1/tokenizer.model /root/output
!cp /root/Mixtral-8x7B-Instruct-v0.1/tokenizer_config.json /root/output</code></pre><p>我们同样可以使用transformers库进行离线推理测试:</p><pre><code>import os
from transformers import AutoModelForCausalLM, AutoTokenizer
import torch
model_id = "/root/output/"
tokenizer = AutoTokenizer.from_pretrained(model_id)
model = AutoModelForCausalLM.from_pretrained(model_id,device_map='auto',torch_dtype=torch.float16)
text = """[INST] Write a poem on a topic 'Care for Thy Soul as Thing of Greatest Price': [/INST]"""
inputs = tokenizer(text, return_tensors="pt").to('cuda')
outputs = model.generate(**inputs, max_new_tokens=20)
print(tokenizer.decode(outputs[0], skip_special_tokens=True))</code></pre><p>如果用户需要将上述模型部署为EAS服务,需要将格式转换成safetensors格式:</p><pre><code>state_dict = model.state_dict()
model.save_pretrained(
model_id,
state_dict=state_dict,
safe_serialization=True)</code></pre><h2>使用PAI-EAS在线部署Mixtral 8x7B MOE大模型</h2><p>PAI-EAS是PAI平台推出的弹性推理服务,可以将各种大模型部署为在线服务。当Mixtral 8x7B MOE大模型微调完毕后,我们可以将其部署为PAI-EAS服务。这里,我们介绍使用PAI-SDK将上述模型进行部署。首先,我们在PAI-DSW环境安装PAI-SDK:</p><pre><code>!python -m pip install alipai --upgrade</code></pre><p>在安装完成后,在在命令行终端上执行以下命令,按照引导完成配置AccessKey、PAI工作空间以及 OSS Bucket:</p><pre><code>python -m pai.toolkit.config</code></pre><p>我们将训练好的模型上传至OSS Bucket。在下述命令中,source_path为模型Checkpoint保存的本地路径,oss_path为上传至OSS的目标路径:</p><pre><code>import pai
from pai.session import get_default_session
from pai.common.oss_utils import upload
print(pai.__version__)
sess = get_default_session()
# 上传模型到默认的Bucket
model_uri = upload(
source_path="/root/output",
oss_path="mixtral-7b-moe-instruct-sft-ds"
)
print(model_uri)</code></pre><p>PAI 提供了Mixtral 8X7B MOE 模型部署镜像和部署代码,用户可以通过相应的部署配置,将微调后的模型部署到PAI-EAS。</p><pre><code>from pai.model import RegisteredModel
from pai.predictor import Predictor
# 获取PAI提供的Mixtral模型服务配置(目前仅支持乌兰察布)
inference_spec = RegisteredModel(
"Mixtral-8x7B-Instruct-v0.1",
model_provider="pai",
).inference_spec
# 修改部署配置,使用微调后的模型
infer_spec.mount(model_uri, model_path="/ml/model")
# 部署推理服务服务
m = Model(inference_spec=infer_spec)
predictor: Predictor = m.deploy(
service_name = 'mixtral_sdk_example_ds',
options={
"metadata.quota_id": "<ResourceGroupQuotaId>",
"metadata.quota_type": "Lingjun",
"metadata.workspace_id": session.workspace_id
}
)
# 查看服务的Endpoint和Token
endpoint = predictor.internet_endpoint
token = predictor.access_token</code></pre><p>以上配置项中,metadata.quota_id是用户购买的灵骏资源配额ID,在购买了灵骏资源之后,用户可以从PAI控制台页面的资源配额入口获取相应的信息。</p><p>部署的推理服务支持 OpenAI 的 API 风格进行调用,通过推理服务的详情页,用户可以获得服务访问地址(Endpoint)和访问凭证(Token)。使用 cURL 调用推理服务的示例如下:</p><pre><code># 请注意替换为使用服务的Endpoint和Token
export API_ENDPOINT="<ENDPOINT>"
export API_TOKEN="<TOKEN>"
# 查看模型list
curl $API_ENDPOINT/v1/models \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $API_TOKEN"
# 调用通用的文本生成API
curl $API_ENDPOINT/v1/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $API_TOKEN" \
-d '{
"model": "Mixtral-8x7B-Instruct-v0.1",
"prompt": "San Francisco is a",
"max_tokens": 256,
"temperature": 0
}'
curl $API_ENDPOINT/v1/chat/completions \
-H "Authorization: Bearer $API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"model": "Mixtral-8x7B-Instruct-v0.1",
"messages": [
{"role": "user", "content": "介绍一下上海的历史"}
]
}'</code></pre><h2>使用PAI-QuickStart微调和部署Mixtral 8x7B MOE大模型</h2><p>快速开始(PAI-QuickStart)集成了国内外AI开源社区中优质的预训练模型,支持零代码或是SDK的方式实现微调和部署Mixtral 8x7B MOE大模型,用户只需要格式准备训练集和验证集,填写训练时候使用的超参数就可以一键拉起训练任务。Mixtral的模型卡片如下图所示:</p><p><img src="/img/remote/1460000044578755" alt="图片" title="图片"></p><p>我们可以根据实际需求上传训练集和验证集,调整超参数,例如learning_rate、sequence_length、train_iters等,如下所示:</p><p><img src="/img/remote/1460000044578756" alt="图片" title="图片"></p><p>点击“训练”按钮,PAI-QuickStart开始进行训练,用户可以查看训练任务状态和训练日志,如下所示:</p><p><img src="/img/remote/1460000044578757" alt="图片" title="图片"></p><p>如果需要将模型部署至PAI-EAS,可以在同一页面的模型部署卡面选择资源组,并且点击“部署”按钮实现一键部署。模型调用方式和上文PAI-EAS调用方式相同。</p><p><img src="/img/remote/1460000044578758" alt="图片" title="图片"></p><h2>相关资料</h2><p>阿里云人工智能平台PAI:</p><p><a href="https://link.segmentfault.com/?enc=gDe0MhP6Or3UO2TdYA39VQ%3D%3D.YH5GycQm5S%2B32hb%2BHtsX96%2ByZZusXh5j55yIA8twjl02hHKtPpGhCleZQuUYba1D" rel="nofollow">https://www.aliyun.com/product/bigdata/learn</a></p><p>交互式建模PAI-DSW:</p><p><a href="https://link.segmentfault.com/?enc=LJ5wM8knyMFGG9ffAWkUgA%3D%3D.Lpndbk8C2tLzIy0cjNh5qb8CttP8C0yypmpTu26gAD5oZrIxcsCUa0zTOMFg6Hx6" rel="nofollow">https://www.aliyun.com/activity/bigdata/pai/dsw</a></p><p>模型在线服务PAI-EAS:</p><p><a href="https://link.segmentfault.com/?enc=jsPzBYuHrMkvMHVW6Jo1GQ%3D%3D.5lQVl6yooi7Vf0B27V1AyH5EU11rm4SxRSaN9nCCuYt7Sv84DOq%2F9fDBjn7YupvsDsWOvGmyMt4QblQhCHh0IQ%3D%3D" rel="nofollow">https://www.aliyun.com/product/bigdata/learn/eas</a></p><p>PAI 快速开始:</p><p><a href="https://link.segmentfault.com/?enc=M0Hian%2BHRiBH8aq5GxhrHw%3D%3D.apsyBuS7I7Xf9hziNLAwHlv9wBkiANcmEaDEuliOdjqQrUypc2MHfCsDJkuKTRDafzvnFcXxx3LKiL9hP0OHJQ%3D%3D" rel="nofollow">https://help.aliyun.com/zh/pai/user-guide/quick-start-overview</a></p><p>PAI Python SDK:</p><p><a href="https://link.segmentfault.com/?enc=H3rssJC%2BH3wMQD%2B1pvo9tA%3D%3D.DxKpTpRQFqM4vcqR3b6OzAfrow1S%2FdLutqm7iuCdoxRJupSY9XDkdST084cyVgZK" rel="nofollow">https://github.com/aliyun/pai-python-sdk</a></p><p>阿里云PAI灵骏智算服务:</p><p><a href="https://link.segmentfault.com/?enc=5%2FzWkq%2FOrCz0PmBlTsS8Bw%3D%3D.IYhatnc6%2FPlBg7GxqqKXtf%2BzM4KO7Oxe%2BoabNfH69cDNQjBn30bnVxlWxsJd5piSiPJt9NmmqRCdiWHF4WvB4g%3D%3D" rel="nofollow">https://www.aliyun.com/product/bigdata/learn/pailingjun</a></p><p>作者:熊兮、贺弘、临在</p><p><strong><a href="https://link.segmentfault.com/?enc=axjde4jDBbUmW26MqLupxQ%3D%3D.ffn6fyVegK2yZ1cJtFhUf3kOxYugOvksFJj9Z4dQPBlgd3VcnE0E6gfKBY7OOb70R81OTkERd2Ju8FVJB380WyNlc5tIdCY1KcTDkTcDqYk%3D" rel="nofollow">原文链接</a></strong></p><p><strong>本文为阿里云原创内容,未经允许不得转载。</strong></p>
Mixtral 8X7B MoE 模型在阿里云PAI平台的微调部署实践
https://segmentfault.com/a/1190000044578622
2024-01-22T17:32:54+08:00
2024-01-22T17:32:54+08:00
阿里云云栖号
https://segmentfault.com/u/aliyunqi
0
<h2>引言</h2><p>Mixtral 8x7B 是Mixtral AI最新发布的大语言模型,在许多基准测试上表现优于 GPT-3.5,是当前最为先进的开源大语言模型之一。阿里云人工智能平台PAI是面向开发者和企业的机器学习/深度学习平台,提供了对于 Mixtral 8x7B 模型的全面支持,开发者和企业用户可以基于 PAI-快速开始(PAI-QuickStart)轻松完成Mixtral 8x7B 模型的微调和部署。</p><h3>Mixtral 8x7B 模型介绍</h3><p>Mixtral 8x7B 是基于编码器(Decoder-Only)架构的稀疏专家混合网络(Sparse Mixture-Of-Experts,SMoE)开源大语言模型,使用 Apache 2.0 协议发布。它的独特之处在于对于每个 token,路由器网络选择八组专家网络中的两组进行处理,并且将其输出累加组合,因此虽然 Mixtral 8x7B 拥有总共 47B 的参数,但每个 token 实际上只使用13B的活跃参数,推理速度与13B模型相当。</p><p>Mixtral 8x7B 支持多种语言,包括法语、德语、西班牙语、意大利语和英语,支持的上下文长度为32K token,并且在所有的评估的基准测试中均达到或优于 Llama-2-70B 和 GPT-3.5,特别是在数学、代码生成和多语言基准测试中,Mixtral 大大优于 Llama-2-70B。</p><p><img src="/img/remote/1460000044578624" alt="图片" title="图片"></p><p>$$
图源: https://arxiv.org/abs/2401.04088
$$</p><p>Mixtral AI 同时也发布了 Mixtral 8x7B 指令微调版本 Mixtral-8x7B-Instruct-v0.1,该版本通过监督微调和直接偏好优化(Direct Preference Optimization, DPO)进行了优化,以更好地遵循人类指令,对话能力领先于目前的其他开源模型的指令微调版本。</p><p><img src="/img/remote/1460000044578625" alt="图片" title="图片"></p><p>$$
图源: https://huggingface.co/spaces/lmsys/chatbot-arena-leaderboard
$$</p><h3>PAI-QuickStart 介绍</h3><p>快速开始(PAI-QuickStart)是阿里云人工智能平台PAI的产品组件,它集成了国内外 AI 开源社区中优质的预训练模型,涵盖了包括大语言模型,文本生成图片、语音识别等各个领域。通过 PAI 对于这些模型的适配,用户可以通过零代码和 SDK 的方式实现从训练到部署再到推理的全过程,大大简化了模型的开发流程,为开发者和企业用户带来了更快、更高效、更便捷的 AI 开发和应用体验。</p><p><img src="/img/remote/1460000044578626" alt="图片" title="图片"></p><h2>运行环境要求</h2><ul><li>本示例目前仅支持在阿里云乌兰察布地域,使用灵骏集群环境运行。</li><li>资源配置要求:GPU 推荐使用 GU108(80GB显存),推理需要2卡及以上资源,LoRA微调需要4卡及以上资源。</li><li>阿里云 PAI 灵骏智算服务资源开通和管理请参考官网文档:灵骏智算资源的购买开通</li></ul><h2>通过PAI控制台使用模型</h2><p>开发者可以在 PAI 控制台的“快速开始”入口,找到 Mixtral-7x8B-Instruct-v0.1 的模型,Mixtral-7x8B-Instruct-v0.1 的模型卡片如下图所示:</p><p><img src="/img/remote/1460000044578627" alt="图片" title="图片"></p><h3>模型部署和调用</h3><p>PAI 提供的 Mixtral-7x8B-instruct-v0.1 预置了模型的部署配置信息,用户仅需提供推理服务的名称以及部署配置使用的资源信息即可将模型部署到PAI-EAS推理服务平台。</p><p>当前模型需要使用灵骏资源组进行部署,请确保选择的资源配额(Quota)中至少有 >=2张GU108 GPU卡的计算资源。</p><p><img src="/img/remote/1460000044578628" alt="图片" title="图片"></p><p>部署的推理服务支持 OpenAI 的 API 风格进行调用,通过推理服务的详情页,用户可以获得服务访问地址(Endpoint)和访问凭证(Token)。使用 cURL 调用推理服务的示例如下:</p><pre><code># 请注意替换为使用服务的Endpoint和Token
export API_ENDPOINT="<ENDPOINT>"
export API_TOKEN="<TOKEN>"
# 查看模型list
curl $API_ENDPOINT/v1/models \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $API_TOKEN"
# 调用通用的文本生成API
curl $API_ENDPOINT/v1/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $API_TOKEN" \
-d '{
"model": "Mixtral-8x7B-Instruct-v0.1",
"prompt": "San Francisco is a",
"max_tokens": 256,
"temperature": 0
}'
curl $API_ENDPOINT/v1/chat/completions \
-H "Authorization: Bearer $API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"model": "Mixtral-8x7B-Instruct-v0.1",
"messages": [
{"role": "user", "content": "介绍一下上海的历史"}
]
}'</code></pre><p>同时也可以通过 OpenAI 的 SDK进行调用,用户首先需要安装 SDK:</p><pre><code># 安装服务调用SDK
python -m pip install openai</code></pre><p>通过SDK调用推理服务的示例代码如下:</p><pre><code>import openai
# 请使用服务详情页获取的访问地址(ENDPOINT)和访问凭证(TOKEN)替换以下代码的配置。
openai.api_key = "<TOKEN>"
openai.base_url = "<ENDPOINT>" + "/v1"
# 调用对话API
completion = openai.chat.completions.create(
model="Mixtral-8x7B-Instruct-v0.1",
temperature=0.0,
top_p=0.8,
frequency_penalty=0.0,
messages=[{"role": "user", "content": "请介绍下你自己。"}],
# stream=True,
)
# 打印输出内容
print(completion.choices[0].message.content)</code></pre><h3>模型微调训练</h3><p>PAI 为 Mixtral-8x7B-Instruct-v0.1 模型配置了微调算法,支持用户以开箱即用得方式对 Mixtral-8x7B-Instruct-v0.1 进行微调。</p><p>训练算法支持使用 Json 格式输入,每条数据由问题、答案组成,分别用"instruction"、"output"字段表示,例如:</p><pre><code>[
{
"instruction": "Write a poem on a topic 'On a Political Prisoner': \n",
"output": "She that but little patience knew,\r\nFrom childhood on, had now so much\r\nA grey gull lost its fear and flew\r\nDown to her cell and there alit,\r\nAnd there endured her fingers' touch\r\nAnd from her fingers ate its bit.\r\nDid she in touching that lone wing."
},
{
"instruction": "Write a poem on a topic 'To His Love': ",
"output": "He's gone, and all our plans\r\n Are useless indeed.\r\nWe'll walk no more on Cotswold\r\n Where the sheep feed\r\n Quietly and take no heed.\r\n His body that was so quick\r\n Is not as you\r\nKnew it, on Severn river\r\n Under the blue\r\n Driving our small boat through."
}
]</code></pre><p>当完成数据的准备,用户可以将数据上传到对象存储 OSS Bucket 中,或是通过指定一个数据集对象,选择在 NAS/CPFS 存储上的数据集。用户也可以使用PAI预置的公共读数据集,直接提交任务测试算法。</p><p>算法需要使用 >=4 x GU108(80GB显存)的GPU资源,请确保选择使用的资源配额内有充足的计算资源。</p><p><img src="/img/remote/1460000044578629" alt="图片" title="图片"></p><p>训练算法支持的超参信息如下,用户可以根据使用的数据,计算资源等调整超参,或是使用算法默认配置的超参。</p><p><img width="723" height="285" src="/img/bVdbc45" alt="" title=""></p><p><img src="/img/remote/1460000044578630" alt="图片" title="图片"></p><p>点击“训练”按钮,PAI-QuickStart 开始进行训练,用户可以查看训练任务状态和训练日志。</p><p><img src="/img/remote/1460000044578631" alt="图片" title="图片"></p><p>通过页面的 TensorBoard 入口,用户也可以一键打开 TensorBoard 查看模型的收敛情况。</p><p><img src="/img/remote/1460000044578632" alt="图片" title="图片"></p><p>如果需要将模型部署至PAI-EAS,可以在同一页面的模型部署卡面选择资源组,并且点击“部署”按钮实现一键部署。模型调用方式和上文直接部署模型的调用方式相同。</p><h2>通过PAI Python SDK使用模型</h2><p>PAI-QuickStart 提供的预训练模型,也支持通过PAI Python SDK进行调用,我们首先需要安装和配置PAI Python SDK,开发者可以在命令行执行以下代码完成。</p><pre><code># 安装PAI Python SDK
python -m pip install alipai --upgrade
# 交互式得配置访问凭证、PAI工作空间等信息
python -m pai.toolkit.config</code></pre><p>如何获取 SDK 配置所需的访问凭证(AccessKey),PAI 工作空间等信息请参考文档:如何安装和配置PAI Python SDK。</p><h3>模型部署和调用</h3><p>通过 PAI 在模型上预置的推理服务配置,用户仅需提供使用的资源信息,以及服务名称,即可轻松的将 Mixtral 模型部署到 PAI-EAS 推理平台。</p><pre><code>from pai.session import get_default_session
from pai.model import RegisteredModel
from pai.common.utils import random_str
from pai.predictor import Predictor
session = get_default_session()
# 获取PAI QuickStart 提供的模型
m = RegisteredModel(
model_name="Mixtral-8x7B-Instruct-v0.1",
model_provider="pai",
)
# 查看模型默认的部署配置
print(m.inference_spec)
# 部署推理服务
# 需提供使用灵骏资源配额ID(QuotaId),要求至少 >= 2张GU108(80G显存)GPU卡的计算资源.
predictor = m.deploy(
service_name="mixtral_8_7b_{}".format(random_str(6)),
options={
# 资源配额ID
"metadata.quota_id": "<LingJunResourceQuotaId>",
"metadata.quota_type": "Lingjun",
"metadata.workspace_id": session.workspace_id,
}
)
# 获取推理服务的Endpoint和Token
endpoint = predictor.internet_endpoint
token = predictor.access_token</code></pre><p>推理服务的调用请参考以上的 PAI-EAS 部署推理的章节,或是直接使用 PAI Python SDK 进行调用。</p><pre><code>from pai.predictor import Predictor
p = Predictor("<MixtralServiceName>")
res = p.raw_predict(
path="/v1/chat/completions",
method="POST",
data={
"model": "Mixtral-8x7B-Instruct-v0.1",
"messages": [
{"role": "user", "content": "介绍一下上海的历史"}
]
}
)
print(res.json())</code></pre><p>当测试完成,需要删除服务释放资源,用户可以通过控制台或是SDK完成:</p><pre><code># 删除服务
predictor.delete_service()</code></pre><h3>模型的微调训练</h3><p>通过 SDK 获取 PAI QuickStart 提供的预训练模型之后,我们可以查看模型配置的微调算法,包括算法支持的超参配置以及输入输出数据。</p><pre><code>from pai.model import RegisteredModel
# 获取PAI QuickStart 提供的 Mixtral-8x7B-Instruct-v0.1 模型
m = RegisteredModel(
model_name="Mixtral-8x7B-Instruct-v0.1",
model_provider="pai",
)
# 获取模型配置的微调算法
est = m.get_estimator()
# 查看算法支持的超参,以及算法输入输出信息
print(est.hyperparameter_definitions)
print(est.input_channel_definitions)</code></pre><p>目前,Mixtral-8x7B-Instruct-v0.1 提供的微调算法仅支持灵骏资源,开发者需要通过 PAI 的控制台页面,查看当前的资源配额 ID,设置训练任务使用的资源信息。同时在提交训练作业之前,用户可以根据算法的超参支持,配置合适的训练任务超参。</p><pre><code># 配置训练作业使用的灵骏资源配额ID
est.resource_id = "<LingjunResourceQuotaId>"
# 配置训练作业超参
hps = {
"learning_rate": 1e-5,
"per_device_train_batch_size": 2,
}
est.set_hyperparameters(**hps)</code></pre><p>微调算法支持3个输入,分别为:</p><p>1.model:Mixtral-8x7B-Instruct-v0.1 预训练模型<br>2.train:微调使用的训练数据集<br>3.validation:微调使用的验证数据集</p><p>数据集的格式请参考以上章节,用户可以通过 ossutils,控制台操作等方式上传数据到 OSS Bucket,也可以使用 SDK 提供的方法上传到用户配置的Bucket。</p><pre><code>from pai.common.oss_utils import upload
# 查看模型微调算法的使用的输入信息
# 获取算法的输入数据,包括模型和供测试的公共读数据集.
training_inputs = m.get_estimator_inputs()
print(training_inputs)
# {
# "model": "oss://pai-quickstart-cn-wulanchabu.oss-cn-wulanchabu-internal.aliyuncs.com/huggingface/models/Mixtral-8x7B-Instruct-v0.1/main/",
# "train": "oss://pai-quickstart-cn-wulanchabu.oss-cn-wulanchabu-internal.aliyuncs.com/huggingface/datasets/llm_instruct/en_poetry_train_mixtral.json",
# "validation": "oss://pai-quickstart-cn-wulanchabu.oss-cn-wulanchabu-internal.aliyuncs.com/huggingface/datasets/llm_instruct/en_poetry_test_mixtral.json",
# }
# 上传用户数据,请注意替换一下的本地文件路径和上传的OSS Bucket路径.
train_data_uri = upload("/path/to/local/train.json", "path/of/train/data")
validation_data_uri = upload("/path/to/local/validation.json", "path/of/validation/data")
# 替换使用开发者的训练数据
# training_inputs["train"] = train_data_uri
# training_inputs["validation"] = validation_data_uri</code></pre><p>开发者可以参考以上的训练数据格式准备数据,然后将train和validation输入替换为自己的训练和验证数据集,即可轻松得提交模型微调训练作业。通过 SDK 打印的训练作业链接,用户可以在 PAI 的控制台上查看训练任务状态以及日志信息,同时也可以通过 TensorBoard 查看训练作业的进度和模型收敛情况。</p><pre><code>from pai.common.oss_utils import download
# 提交训练作业,同时打印训练作业链接
est.fit(
inputs=training_inputs,
wait=False,
)
# 打开TensorBoard查看训练进度
est.tensorboard()
# 等待训练任务结束
est.wait()
# 查看保存在OSS Bucket上的模型路径
print(est.model_data())
# 用户可以通过ossutils,或是SDK提供的便利方法下载相应的模型到本地
download(est.model_data())</code></pre><p>用户可以查看文档,了解更多如何通过 SDK 使用 PAI-QuickStart 提供的预训练模型:使用预训练模型 — PAI Python SDK。</p><h2>结论</h2><p>Mixtral-8x7B 是当前最为先进的开源大语言模型之一,借助于MoE架构,具有很高的使用性价比,通过 PAI QuickStart 开发者可以轻松地完成Mixtral模型的微调和部署。当然PAI QuickStart 也提供了更多的先进、不同领域的模型,欢迎开发者前来探索使用。</p><h2>相关资料</h2><ul><li>Mixtral 8x7B 模型:<a href="https://link.segmentfault.com/?enc=DDlxk5nQMIM%2B1p8SvSRpJQ%3D%3D.ppo3%2BRb%2BYAoIBvxOKVmrRCYspSehTAAzJ4q2OQsh5g%2F3nWHLEaA6y8s9rdO1l8tH" rel="nofollow">https://mistral.ai/news/mixtral-of-experts/</a></li><li>PAI 快速开始:<a href="https://link.segmentfault.com/?enc=67azp6htmwwncSKWF1RRBA%3D%3D.r8QymSpFK%2F6MuBRiwbo8xvrQUI1bhzv1l7MkCwtyOz65ej7Nok4fB%2BnVFmy2Fhx63EMvMqv1li83xeUQnF2F2w%3D%3D" rel="nofollow">https://help.aliyun.com/zh/pai/user-guide/quick-start-overview</a></li><li>PAI Python SDK:<a href="https://link.segmentfault.com/?enc=61jwoYU9l%2F%2FOK1UijWLPhg%3D%3D.visnvS6PMboMinWRboXmyhcuUZgMsei2y9KlR%2ByIBOoAImTPHBCXCfnarqTXDd9g" rel="nofollow">https://github.com/aliyun/pai-python-sdk</a></li><li>阿里云PAI灵骏智算服务:<a href="https://link.segmentfault.com/?enc=cbkoJHgUbb2At6mqAhB2gQ%3D%3D.zVqyKu1%2FR0nCtsXurWLHUseBoMW8OUKI%2Fue2p6XvxRp1F0ipfeB39zWakmt9NPRSYLxS9qsgQX88Os0Gv50rIQ%3D%3D" rel="nofollow">https://www.aliyun.com/product/bigdata/learn/pailingjun</a></li></ul><p>作者:熊兮、求伯、一耘</p><p><strong><a href="https://link.segmentfault.com/?enc=Gh9jSWcUkMVSf0lZw3ZVYA%3D%3D.s6fpTTUuZ0ielefTRn1C7Icsjjm9CxW51x%2BxGvQFJBvNk1HwMACfx0Y0MZ4dcDUpirgB7i%2FFRaZo7VM92jZyPf0OhVeFgax%2F6zHSMkNo0Po%3D" rel="nofollow">原文链接</a></strong></p><p><strong>本文为阿里云原创内容,未经允许不得转载。</strong></p>
调研 7 个开源项目后,这家数据合规平台如何构建高性能网关
https://segmentfault.com/a/1190000044567476
2024-01-18T16:46:44+08:00
2024-01-18T16:46:44+08:00
阿里云云栖号
https://segmentfault.com/u/aliyunqi
0
<h2>用九智汇介绍</h2><p>用九智汇是一家面向企业提供数据合规、隐私保护相关产品和解决方案的数据合规公司,致力于帮助客户在合法合规、充分保护用户隐私的基础上发挥数据的最大价值,已服务众多世界 500 强企业。当前我们的产品交付主要基于云原生相关的基础设施和开源技术栈,如 Kubernetes、Istio、Apache Dubbo、Alibaba Nacos 等,既支持以 SaaS 的方式提供开箱即用、标准、可配置化的产品服务,亦支持以混合云、私有云的方式进行私有化部署。</p><h2>需求背景</h2><p>在服务客户的的过程中,来自于客户跟网关相关的需求主要体现在以下三个方面:</p><ul><li>提供开放 API 供企业内部系统进行集成调用,实现全流程自动化。</li><li>能够自定义 SaaS 产品的访问域名,二级域名甚至一级域名,增强企业员工的品牌感知。</li><li>私有化部署时,能不依赖于客户的基础设施能力,对公网提供服务并保障稳定和安全。</li></ul><p>为了满足以上的客户诉求,以及支撑公司整个产品体系和能力的建设,我们的技术团队希望通过找到一款合适的网关产品来满足客户的需求,同时也能满足以下技术要求:</p><ul><li>基于云原生,跟我们当前基于云原生的技术架构相匹配。</li><li>开源并且开源协议满足商业化使用要求,有长期的发展规划 RoadMap。</li><li>性能至少不差于 Nginx Ingress,能够解决配置频繁变更导致 Nginx 进程频繁重启连接瞬时断开后并发重连的问题。</li><li>支持插件,可以开发自定义插件。</li><li>可以根据域名、路由配置不同的插件,以实现在不同业务场景下使用不同的认证鉴权方式。</li><li>具备将 HTTP 请求转换为微服务 RPC 请求的能力,微服务 API 能通过网关的可配置能力,快速地对外提供开放 API 服务,内部、外部使用同一套 API,提升研发效率。</li><li>网关核心组件和控制台分开部署,并且网关控制台的技术架构方便进行定制化开发,可通过控制台提供的 API 实现域名、证书、路由等自动化配置。</li><li>至少能够将安全网关和流量网关二合一,降低私有化部署的复杂度和维护成本。</li></ul><p><img src="/img/remote/1460000044567478" alt="图片" title="图片"></p><p>除了已经在使用的 Nginx Ingress,我们调研了 Ambassador、Kong、APISIX、Gloo、Spring Cloud Gateway 等产品,最终决定选择 Higress。</p><h2>为什么选择 Higress</h2><p>1)Higress 进入我们视野,首先是因为它基于云原生的,在广泛被使用的 envoy、istio 的基础上进行开发,跟我们当前基于 Kubenetes 的技术架构完全匹配,技术团队完全可以通过云原生社区学习和掌握相关的能力并独立运维。</p><p>2)Higress 是开源的,基于 Apache-2.0 协议,对商用比较友好,即使完全没有社区的帮助,我们也可以根据自己的需求进行自定义和修改,来满足特定的客户需求和公司产品能力建设需要。另外我们在调研和测试 Higress 开源版本过程中,Higress 开源团队的支持非常及时和给力,这给了我们非常大的信心。</p><p>3)Wasm 插件机制,跨语言支持,开发可以选择自己熟悉的语言进行插件开发,大幅降低了插件的开发难度,插件可以动态加载和卸载而无需重启网关,提供了强大的灵活性和扩展性,并且在安全性和性能上完全能够满足我们的需要。</p><p>4)HTTP 转 Dubbo 能力,结合认证鉴权 Wasm 插件,我们可以将内部使用的 RPC API 和提供给外部使用的 Open API 统一,只用开发一套标准的 RPC API,即可同时服务内部系统和外部系统的需要。开发只用将内部的 API 配置即可上线到 Open API 目录中,能够极大地提高了研发效率。</p><p>5)我们当前在使用 Nginx Ingress 作为网关,最终我们希望只有一个网关产品,所以需要把 Nginx Ingress 的配置平滑迁移到 Higress,由于 Higress 兼容 Nginx Ingress 绝大部份 Annotation,所以迁移成本较低。</p><h2>已经使用了哪些 Higress 能力</h2><h3>1.开发自定义 Wash 插件对 Open API 调用进行认证鉴权</h3><p>Higress 开源版本已经提供了如 hmac-auth、jwt-auth、basic-auth 等认证鉴权插件,但这些插件并不能完全满足我们的需要,如:</p><ul><li>访问凭证只能写在插件的 yaml 中,不能动态调用其他服务或存储进行校验。</li><li>访问凭证校验通过后,需要根据调用的密钥所归属的企业租户,在 header 中设置访问租户信息,只允许访问属于该租户的数据。</li></ul><p>所以我们参考官方文档使用 GO 语言开发自己的认证鉴权、设置 Header 插件,流程如下图:</p><p><img src="/img/remote/1460000044567479" alt="图片" title="图片"></p><p><strong>a.使用 Go 语言开发、编译、测试</strong></p><pre><code>#1、在plugins/wasm-go/yong9ai-***-auth目录下执行
go mod init yong9ai-***-auth
#2、编写main.go文件,按需实现onHttpRequestHeaders、onHttpRequestBody等方法
#3、编译生成WASM文件(Windows下将单引号改为双引号)
go mod tidy
tinygo build -o main.wasm -scheduler=none -target=wasi -gc=custom -tags='custommalloc nottinygc_finalizer' ./main.go
#4、使用docker-compose启动envoy和httpbin进行测试</code></pre><p><strong>b.使用 Higress wasm-go builder 构建插件镜像</strong></p><pre><code>#1、在plugins/wasm-go目录下执行
PLUGIN_NAME=yong9ai-***-auth make build
#2、push到镜像仓库</code></pre><p><strong>c.配置插件,基于域名开启指定插件对所有请求进行认证鉴权</strong></p><pre><code>apiVersion: extensions.higress.io/v1alpha1
kind: WasmPlugin
metadata:
annotations:
higress.io/wasm-plugin-description: 用九智汇***认证鉴权
higress.io/wasm-plugin-title: yong9ai-***-auth
labels:
higress.io/resource-definer: higress
higress.io/wasm-plugin-built-in: "false"
higress.io/wasm-plugin-category: custom
higress.io/wasm-plugin-name: yong9ai-***-auth
higress.io/wasm-plugin-version: 1.0.0
name: yong9ai-***-auth-1.0.0
namespace: higress-system
spec:
defaultConfig: {}
defaultConfigDisable: true
matchRules:
- config:
namespace: ***
serviceName: ***
servicePort: ***
serviceSource: ***
configDisable: false
domain:
- ***.yong9ai.com
phase: AUTHN
priority: 1000
url: oci://****.cn-shanghai.cr.aliyuncs.com/**/**:yong9ai-***-auth-1.0.0</code></pre><h3>2.使用 Http 转 Dubbo 能力对外暴露 Open API</h3><p>我们内部使用了同样是阿里开源的 Dubbo 作为微服务框架,并使用 Nacos 作为注册中心。通过使用 Higress 的 Http 转 Dubbo 能力,可以将内部使用的标准 Dubbo Service 以 Open API 提供给客户使用。</p><p><strong>a.创建服务来源(配置 McpBridge)</strong></p><pre><code>apiVersion: networking.higress.io/v1
kind: McpBridge
metadata:
name: default
namespace: higress-system
spec:
registries:
- domain: nacos-***.***
nacosGroups:
- DEFAULT_GROUP
nacosNamespaceId: public
name: Nacos
port: 8848
type: nacos2</code></pre><p><strong>b.配置 Http2RPC</strong></p><pre><code>apiVersion: networking.higress.io/v1
kind: Http2Rpc
metadata:
name: ***-***-***-service
namespace: higress-system
spec:
dubbo:
group: DUBBO
methods:
- headersAttach: '*'
httpMethods:
- POST
httpPath: /api/open/**/**/**/post.json
params:
- paramKey: request
paramSource: BODY
paramType: >-
com.yong9ai.***.***.***.***.***.***.param.****Request
serviceMethod: ***
service: com.yong9ai.***.***.***.***.***.***.api.****Service
version: 1.0.0</code></pre><p><strong>c.配置路由</strong></p><pre><code>apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
higress.io/destination: '***.***.svc.cluster.local:8080'
higress.io/ignore-path-case: 'true'
higress.io/match-method: POST
higress.io/ssl-redirect: 'true'
labels:
higress.io/domain_datacls.openapi.yong9ai.work: 'true'
higress.io/resource-definer: higress
name: ***-***-service-***
namespace: higress-system
spec:
ingressClassName: higress
rules:
- host: ***.yong9ai.com
http:
paths:
- backend:
resource:
apiGroup: networking.higress.io
kind: McpBridge
name: default
path: /api/open/**/**/**/post.json
pathType: Exact
tls:
- hosts:
- ***.yong9ai.com
secretName: yong9ai-***</code></pre><p>结合认证鉴权、设置 Header 插件,将 Dubbo Service 暴露为 Open API,这样就不用维护 Dubbo、HTTP 两套 API 接口和实现,开发成本、维护难度都得到大幅降低,当然定义 API 的时候得考虑更多。</p><h3>3.基于开源 Higress-console 进行自定义修改,暴露 Dubbo 服务实现自动化</h3><p>开源的 higress-console 提供了简单、基础、开箱即用的 Web 控制台,但是只提供了最简单的基本管理能力,但它有两个优点:</p><ul><li>后端基于 SpringBoot,前端基于 React,开发非常容易上手。</li><li>和 Higress 核心组件分开部署,console 频繁迭代和部署不会影响网关的核心功能。</li></ul><p>实际上我们大部分的业务需求也主要在 console 端,上面的两个优点也非常方便对 console 进行自定义和修改。目前,我们实现的主要功能是,通过修改 higress-console 代码对外提供 Dubbo Service,供业务系统调用实现流程自动化。比如在企业租户设置二级乃至一级自定义域名是,业务系统可以调用 higress-console 的 Dubbo Service 创建域名、证书和路由实现全流程无需人工介入。</p><p>未来,我们计划继续在开源 higress-console 基础上,开发适合我们自己业务的 Open API 相关的管理和管控能力,进一步提高效率。</p><h3>4.迁移 Nginx Ingress 到 Higress</h3><p>目前我们已经迁移了部分 Ningx Ingress 流量到 Higress 中,主要是通过阿里云 SLB 的流量权重设置来实现的,如下图:</p><p><img src="/img/remote/1460000044567480" alt="图片" title="图片"></p><p>从目前已经切换的流量运行情况来看,稳定性很好,另外基于我们测试结果,Higress 的性能是优于 Nginx Ingress 的。由于我们经常需要变更配置,之前考虑到 Nginx 配置变更需要重启进程导致连接瞬时断开后并发重连的问题,所有变更操作强制放到晚上进行,现在在白天也可以进行。</p><p>后续,我们准备将所有 Nginx Ingress 流量迁移到 Higress,并且考虑在混合云、私有云方式私有化部署交付是替换 Nginx Ingress,统一使用 Higress,降低维护多套网关的复杂度和成本。</p><h2>最后</h2><ul><li>HTTP 转 Dubbo 是个非常好的 Feature,可以满足我们大部分场景的需求,希望社区可以持续迭代,继续做强这个功能,解放研发的生产力。</li><li>从社区周会了解到,Higress 商业团队在不断加大对开源社区的投入,同时也建立了开源版和社区版的 feature/bugfix 同步机制,以社区版为基础,商业版基于社区版进行扩展,这是一条正确的道路,坚决支持,希望坚持到底。</li><li>希望有更多的社区同学参与开源版本 higress-console 的建设,在易用性和功能丰富性上越来越强,我们在合适的时候也会贡献自己的力量。</li></ul><p>作者:张俊,杭州用九智汇科技有限公司系统架构师</p><p><strong><a href="https://link.segmentfault.com/?enc=RFCbFyproygkeKHt7ue6GQ%3D%3D.3dJJDWsCk8rvdvZjP2fTodQjRB2SsUjCZqWNcyMeX1lY8cZwo1L%2F2uOtSZblkbbg87nL74JStDsFZF2byLuwOEJNHs52Jmsd7nNwNIEwEso%3D" rel="nofollow">原文链接</a></strong></p><p><strong>本文为阿里云原创内容,未经允许不得转载。</strong></p>
阿里云 ACK 云原生 AI 套件中的分布式弹性训练实践
https://segmentfault.com/a/1190000044566028
2024-01-18T11:09:04+08:00
2024-01-18T11:09:04+08:00
阿里云云栖号
https://segmentfault.com/u/aliyunqi
0
<p>众所周知,随着时间的推移,算力成为了 AI 行业演进一个不可或缺的因素。在数据量日益庞大、模型体量不断增加的今天,企业对分布式算力和模型训练效率的需求成为了首要的任务。如何更好的、更高效率的以及更具性价比的利用算力,使用更低的成本来训练不断的迭代 AI 模型,变成了迫切需要解决的问题。而分布式训练的演进很好的体现了 AI 模型发展的过程。</p><h2>Distributed Training</h2><p>分布式训练一般分为两种类型,数据并行和模型并行。数据并行是指每个训练 Worker 都保存有一份模型的副本,然后将大规模的数据进行切分,分布到每个训练 Worker 上进行计算,最后再进行集合通信统一计算结果的过程。在相当一段的时间内,该种模式是分布式训练的主流模式,因为模型的规模足以放进单个训练 Worker 之中,而数据的规模才是整体训练效率的瓶颈。利用分布式数据并行可以充分利用集群中的算力资源,并行处理庞大的数据集,以达到加速训练的效果。</p><p>而模型并行则是在模型非常庞大的情况下将模型进行切分,分布到不同的训练 Worker 中,然后训练数据按照模型的结构分布经过不同的训练 Worker,以达到用分布式的算力来训练大模型的效果。现在的大语言模型由于其体量的庞大,所以一般都是使用模型并行的模式来进行训练。</p><p><img src="/img/remote/1460000044566030" alt="图片" title="图片"></p><p>基于数据并行的分布式训练又分为两种不同的架构。</p><ul><li>Parameter Server 架构:有一个中心化的 Parameter Server 用来存储分布式训练的梯度,每一个训练 Worker 在进行每个 Step 的训练前都需要先从 Parameter Server 中先 pull 到最新的梯度信息,在这个 step 训练结束后再将训练的结果梯度 push 到 Parameter Server。在 Tensorflow 中,PS 模式的训练一般为异步的分布式训练,该情况下对于任务的全部 Worker 来说,其无需等待其他 Worker 的训练流程去同步梯度,只需要根据流程完成自身的训练即可。这种模式多用于基于 Tensorflow 的搜推广场景。</li><li>AllReduce 架构:一个去中心化的同步的分布式训练模式,在分布式训练中一般采用 Ring-All Reduce,每个训练 Worker 只与自身左右 Rank 的 Worker 进行通信,这样就能形成一个通信环,经过环形通信可以使得每一个 Worker 中的梯度都同步到了其他的 Worker 中并完成计算。这种模式多用于 CV、NLP 的应用场景。</li></ul><p><img src="/img/remote/1460000044566031" alt="图片" title="图片"></p><h2>Elastic Training</h2><p>上面我们介绍了分布式训练,现在来了解一下弹性分布式训练。什么是弹性训练?具体可以总结为三大块的能力:</p><ul><li>训练规模弹性改变:这里主要指的是弹性改变训练的 Worker 数目,扩容增加 Worker 数量以提升训练速度,缩容减少 Worker 数量以腾出部分集群资源;</li><li>训练过程弹性容错:由于部分因素导致任务异常或可预见问题如 Spot 回收事件预示下的整体任务的容错,避免因为少部分 Worker 失败而直接导致的整个任务的失败;</li><li>训练资源弹性伸缩:可以根据任务需要或者问题处理的判断来动态变更任务训练 Worker 的资源配置以达到一个更合理的任务 Worker 资源配比。</li></ul><p><img src="/img/remote/1460000044566032" alt="图片" title="图片"></p><p>而弹性训练的能力带来的意义,大概也可以总结为三点:</p><ol><li>大规模分布式训练容错,有效提升训练任务运行的成功率;</li><li>提升集群算力利用率,充分利用弹性来协调在离线任务的资源分配;</li><li>降低任务训练成本,使用可被抢占或稳定性稍差但成本更低的实例来进行训练从而整体层面降低成本。</li></ol><p><img src="/img/remote/1460000044566033" alt="图片" title="图片"></p><h3>PS Elastic Training</h3><p>在 PS 模式下进行的弹性训练,由于其为异步模式,弹性的关键在于训练数据的划分。当其中一部分 Worker 失败之后,未被训练的数据或者失败 Worker 中的数据可以被剩下的 Worker 继续训练,当新的 Worker 加入之后,可以与现有的 Worker 一起参与进行训练。</p><p><img src="/img/remote/1460000044566034" alt="图片" title="图片"></p><h4>DLRover</h4><p>在蚂蚁 AI Infra 团队开源的项目 DLRover 中,其实现了 Training Master 来参与弹性训练。由 Training Master 来负责对任务的监听、数据集的划分、各角色资源的弹性。其中数据集的划分是弹性训练的关键,在 Master 中有一个 Dataset Shard Service 的角色来负责具体数据集的划分。</p><p>其将整个的数据集按照 Batch Size 进行切分,分为各个 Task Data,然后将 Task Data 放进数据集队列中供各个训练 Worker 进行消费。在 Dataset Shard Service 中存在着两个队列,所有未被训练消费的 Task Data 在 TODO 队列中,而正在被训练的 Task Data 则是在 DOING 队列,直到该 Data 训练结束 Worker 给出信号后,该 Task Data 才会完全出队。如果有训练 Worker 中途异常退出,检测超时的 Task Data 会重新进入 TODO 队列以供其他正常 Worker 进行训练。</p><p><img src="/img/remote/1460000044566036" alt="图片" title="图片"></p><p>DLRover 在 Kubernetes 上设计了一个 CRD ElasticJob,由 ElasticJob Controller 监听并创建一个 DLRover Master,再由该 Master 来创建 PS 和 Worker 的 Pod,并控制 PS 和 Worker 的弹性。</p><p><img src="/img/remote/1460000044566037" alt="图片" title="图片"></p><h3>AllReduce Elastic Training</h3><p>在 AllReduce 模式下进行的弹性训练,由于其为同步模式,弹性的关键在于如何保证训练的同步,同时还有为了同步梯度而建立起来的通信环的保持。当其中一部分 Worker 失败之后,剩下的 Worker 可以重建通信环继续训练,当新的 Worker 加入之后,可以与现有的 Worker 重建通信环进行训练。</p><p><img src="/img/remote/1460000044566038" alt="图片" title="图片"></p><h4>Elastic Pytorch</h4><p>Elastic Pytorch 是 Pytorch 中 AllReduce 模式的弹性分布式训练,其本质在每个 Worker 上启动一个 Elastic Agent,利用该 agent 的 monitor 对各个训练进程进行 listen,并且根据 Worker 进程的正常与否的情况来动态的在 Master 中的 Rendezvous Server 中进行注册 Worker 的信息,从而完成整个训练任务过程的弹性。目前这个过程可以在 Kubernetes 中利用 Pytorch Operator 运行。</p><p><img src="/img/remote/1460000044566039" alt="图片" title="图片"></p><h4>Elastric Horovod</h4><p>Horovod 是一个分布式的弹性训练框架,可以应用于 Tensorflow 或者 Pytorch 的分布式训练。同样是 AllReduce 模式的弹性分布式训练,Elastic Horovod 可以在运行过程中动态的自行触发调整训练 Worker 的数量,而不需要重启整个训练任务或者重新从持久化的 Checkpoint 中恢复训练状态,从而达到避免中断训练任务的目的。</p><p><img src="/img/remote/1460000044566040" alt="图片" title="图片"></p><p>为了可以在 Kubernetes 上很好的运行 Elastic Horovod,ACK 团队实现了 Elastic Training Operator,其中有三个 CR。TrainingJob 是运行 Elastic Horovod 的任务承载,ScaleIn、ScaleOut 则分别作为任务缩容和扩容的触发 CR。用户可以通过以上三个 CR 来达到完成整个 Horovod Elastic 过程的目的。</p><p><img src="/img/remote/1460000044566041" alt="图片" title="图片"></p><p>用户可以通过提交 TrainingJob 来提交自己的 Elastic Horovod 任务,通过提交 ScaleIn 和 ScaleOut 来提交这个 Elastic Horovod 任务的缩容和扩容动作任务。</p><p><img src="/img/remote/1460000044566042" alt="图片" title="图片"></p><h2>ACK 云原生 AI 套件 Elastic Training</h2><p>基于上面几种(DLRover、Elastic Pytorch、Elastic Horovod)在 Kubernetes 中的弹性训练框架的方案,云原生 AI 套件提出了在 Spot 场景下的云原生 AI 弹性训练解决方案:</p><p>随着模型不断增大,AI 作业训练成本不断攀升,节省成本逐渐称为各行各业的关键命题。面向在 ACK 上做 AI 模型训练且成本敏感的客户,ACK 云原生 AI 套件在 ACK 上期望推广的弹性训练场景为基于抢占式实例 Spot 的弹性节点池作为底层训练资源的云原生 AI 弹性训练解决方案。</p><p>整体方案的目标在于以下几点:</p><ol><li>期望将更多类型更多训练场景的 AI 训练任务在集群中以弹性的方式尽可能多的运行在成本更低的抢占式实例上;</li><li>这些训练任务可以根据客户需求动态的占用集群中空闲的资源,以达到资源利用率提升的目的;3. 使用该种弹性训练方式对客户 AI 训练任务的精度影响处于一个可以接受的范围内,不影响其最终的效果表现;</li><li>使用该种弹性训练方式可以使得客户的训练任务不会因为资源回收或者其他原因而导致整个任务进程的中断,进而丢失训练结果。</li></ol><p>目前在 ACK 上,ACK 云原生 AI 套件提供了对 Elastic Horovod、DLRover (Tensorflow PS)、Elastic Pytorch 的支持,可以覆盖对 NLP、CV、搜推广场景的 AI 训练任务的支持,基本上涵盖了目前市面上的绝大多数的 AI 任务训练场景。</p><p><img src="/img/remote/1460000044566043" alt="图片" title="图片"></p><p>ACK 云原生 AI 套件提供了一个弹性训练控制组件 Elastic-Job-Supervisor,Elastic-Job-Supervisor 目前主要面向 Spot 场景做各个场景下弹性训练的控制。其可提供的 Spot 场景下的弹性训练能力有:</p><p>Max Wait Time:若最大等待时长之前无法满足训练任务的资源请求时,则任务终止资源的等待,避免部分 Worker 申请资源后造成的浪费;</p><p><img src="/img/remote/1460000044566044" alt="图片" title="图片"></p><p>Checkpoint Saving:拥有实例回收通知机制,使得训练任务在接收到抢占式实例回收的通知时进行自动的 Checkpoint Save 操作,以避免训练结果的丢失;</p><p><img src="/img/remote/1460000044566045" alt="图片" title="图片"></p><p>Fail Tolerance:提交了一个分布式弹性训练任务,当部分实例被回收时,该分布式训练任务可以做到仍继续运行,不会因为部分 Worker 的回收而导致中断;</p><p><img src="/img/remote/1460000044566046" alt="图片" title="图片"></p><p>Job Recovery:当集群中重新加入训练可用资源时,之前由于资源不足而 Suspended 的任务可以重新拉起继续进行训练,或者之前被缩容的分布式训练任务可以自动扩容到预设的 Replica 进行训练,这里又分为两种策略:</p><ul><li>如果不满足预设的 Worker 数目,任务就会一直 Pending,知道满足了资源要求才会重启 Worker 恢复训练任务,该种情况下因为总 Worker 数不变,所以 Global Batch Size 就不变,进而最终精度也会得到保证。问题就在对资源是强要求,可能处在一直等待资源的状态中;</li><li>可以接受动态改变 Worker 的数量进行训练,即使不满足预设的 Worker 数量仍然不影响训练,也就是动态改变了 Global Batch 的大小。这种情况下是会影响模型最终训练的精度,可以通过选择合适的 Optimizer 算法和 Learning Rate 调整算法来尽可能的保证精度,或者使用梯度累积等方法来保证精度;</li></ul><p><img src="/img/remote/1460000044566047" alt="图片" title="图片"></p><p><img src="/img/remote/1460000044566048" alt="图片" title="图片"></p><p>Cost Observability:在使用抢占式实例进行训练时,可以利用 ACK 的 FinOps 对整体的训练成本的监控计算,展示基于抢占式实例 Spot 的弹性训练带来的成本节省。</p><p><img src="/img/remote/1460000044566049" alt="图片" title="图片"></p><p><img src="/img/remote/1460000044566050" alt="图片" title="图片"></p><p>可以通过例子看到,通过实验验证,不同类型的分布式训练的副本数在一定的范围进行弹性的改变,加以一些相关的优化,其对精度的影响均处于可以接受的范围之内。在成本方面,通过在抢占式实例 Spot 上进行弹性变化 Worker 数量,可以在整体上将整个训练任务的花费成本降低到一个比较可观的值。与正常的按量付费云资源比起来,在 ResNet 上的测试可以达到 92% 的成本节省,在 BERT 上的测试可以达到 81% 的成本节省。</p><p>目前在较为热门的 LLM 场景下,ACK 云原生 AI 套件正在积极探索 DeepSpeed 等 LLM 训练框架下的弹性训练方案,以求将降低成本、提升训练成功率、提升资源利用率的效果用在 LLM 的训练之中。</p><p>作者:霍智鑫</p><p><strong><a href="https://link.segmentfault.com/?enc=hdKP8OkNPwRzeGP11bDuoQ%3D%3D.GRyvzHM5J57HytXPU1ummjFTwNOpSkYEU%2Bs03gxdHifcmFnR2xbFqfpsOtzOfAq0wwvG7GhcCxvz65au0fHKFjVobnJxv69io%2BBL7YrQHZ8%3D" rel="nofollow">原文链接</a></strong></p><p><strong>本文为阿里云原创内容,未经允许不得转载。</strong></p>