暂时未有相关云产品技术能力~
作者:阿里云可观测Kafka 作为当前广泛使用的中间件产品,承担了重要/核心业务数据流转,其稳定运行关乎整个业务系统可用性。本文旨在分享阿里云 Prometheus 在阿里云 Kafka 和自建 Kafka 的监控实践。Kafka 简介Kafka 是什么?Kafka 是分布式、高吞吐、可扩展的实时数据流平台。Kafka 广泛用于日志收集、监控数据聚合、流式数据处理、在线和离线分析等大数据领域,已成为大数据生态中不可或缺的部分。Producer:通过 push 模式向 Kafka Broker 发送消息。发送的消息可以是网站的页面访问、服务器日志,也可以是 CPU 和内存相关的系统资源信息。Kafka Broker:用于存储消息的服务器。Kafka Broker 支持水平扩展。Kafka Broker 节点的数量越多,集群的吞吐率越高。Group:通过 pull 模式从 Kafka Broker 订阅并消费消息。ZooKeeper:管理集群的配置、选举领导(Leader)分区,并且在 Group 发生变化时,进行负载均衡。Kafka 特点优势1. 通信模式:支持列队和发布/订阅两种通信模式。2. 高吞吐量、低延迟:在较廉价的硬件上,Kafka 也能做到每秒处理几十万条消息,延迟最低只有几毫秒。3. 持久性:Kafka 可以将消息持久化到普通磁盘。4. 可扩展性:Kafka 集群支持热扩展,可以动态向集群添加新节点。5. 容错性:允许集群中节点失败(若副本数量为 n,则允许 n-1 个节点失败)。需要注意的问题1. Topic/分区数过多,导致性能急速下降:Kafka Topic/分区过多(如,对于普通磁盘,单机超过 500 个topic/分区),会导致存储碎片化,load 会发生明显的飙高现象,topic/分区越多,load 越高,发送消息响应时间越长。2. 消息丢失:以下 2 种使用不当的场景,可能导致消息丢失,应根据业务场景避免。生产消息:如果 acks!=all 或者消息副本数不大于1,则在Kafka Broker机器异常宕机时,可能导致消息丢失。 消费消息:消费端在未完全处理完消息时即提交offset,则在消费端异常时,可能导致部分消息丢失。 3. 重复消费:生产者可能由于某种原因(如网络抖动或 Kafka broker 宕机)没有收到 Kafka broker的成功确认,然后重复发送消息,最终导致消费者收到多个相同的业务消息。此场景需要消费者支持的消息幂等性来解决。4. 消息乱序:Kafka 只能保证同一分区内的消息有序性,不同分区之间消息不能保证有序性。5. 不支持事务Kafka 典型适用场景1. 大数据领域:网站行为分析、日志聚合、应用监控、流式数据处理、在线和离线数据分析等领域。2. 数据集成:将消息导入 MaxCompute、OSS、RDS、Hadoop、HBase 等离线数据仓库。3. 流计算集成:与 StreamCompute、E-MapReduce、Spark、Storm 等流计算引擎集成。Kafka 核心概念Broker:一个 Kafka 服务端节点。集群(Cluster):由多个 Broker 组成的集合。消息(Message):也叫 Record,Kafka 中信息传递的载体。消息可以是网站的页面访问、服务器的日志,也可以是和 CPU、内存相关的系统资源信息,但对于消息队列 Kafka 版,消息就是一个字节数组。Producer:向 Kafka 发送消息的应用。Consumer:从 Kafka 接收消息的应用。消费者组(Consumer Group):一组具有相同 Group ID 的 Consumer。当一个 Topic 被同一个 Group 的多个 Consumer 消费时,每一条消息都只会被投递到一个 Consumer,实现消费的负载均衡。通过 Group,您可以确保一个 Topic 的消息被并行消费,提高 Kafka 的吞吐量。主题(Topic):消息的主题,用于分类消息。在每个 Broker 上都可以创建多个 Topic。副本(Replica):每一个分区都有多个副本。当主分区(Leader)故障的时候会选择一个备分区(Follower)上位,成为 Leader。在 Kafka 中默认副本的最大数量是 10 个,且副本的数量不能大于 Broker 的数量,Follower 和 Leader 是在不同的机器,同一机器对同一个分区也只可能存放一个副本。分区(Partition):一个有序不变的消息序列,用于存储消息。一个 Topic 由一个或多个分区组成,每个分区中的消息存储于一个或多个 Broker 上。在一个分区中消息的顺序就是 Producer 发送消息的顺序。位点(Offset):分区中每条消息的位置信息,是一个单调递增且不变的值。消费位点:分区被当前 Consumer 消费了的消息的最大位点。堆积量:当前分区下的消息堆积总量,即最大位点减去消费位点的值。堆积量是一个关键指标,如果发现堆积量较大,则 Consumer 可能产生了阻塞,或者消费速度跟不上生产速度。此时需要分析 Consumer 的运行状况,尽力提升消费速度。可以清除所有堆积消息,从最大位点开始消费,或按时间点进行位点重置。重平衡(Rebalance):消费者组内某个消费者实例挂掉后,其他消费者实例自动重新分配订阅主题分区的过程。Rebalance 是 Kafka 消费者端实现高可用的重要手段。 Zookeeper:Kafka 集群依赖 Zookeeper 来保存集群的的元信息,以保证系统的可用性。主要 Kafka 版本介绍0.x:早期孵化版本。1.x:优化 Streams API、增强可观测性和可调试性、支持 Java9、优化 SASL 认证等、优化 Controller 管理等。2.x:性能显著提升、增强 ACL 支持、支持 OAuth2 bearer、支持动态更新 SSL、增强可观察能力、支持 Java 11(不再支持 Java 7)、支持增量协作再平衡等。3.x:去掉 zookeeper 依赖、支持 Java 17(不再支持 Java8 和 Scala 12)、不再支持 v0 和 v1 消息、性能大幅提升等。 推荐使用 2.x 和 3.x 版本。Kafka Metric 监控参考模型结合 Kafka 的体系架构和使用场景,我们从 Metrics 采集、监控大盘、告警指标等3方面定义了 Kafka Metric 监控的参考模型。Metrics 采集 即我们需要采集哪些 Kafka 相关的 Metric,以便能完成业务监控。下面分别从 Producer、Broker 和 Consumer 三个方面进行讨论。1. Producer 指标生产者是将消息推送到 Broker Topic 的应用。如果生产者失败,消费者将得不到新的信息。我们建议关注如下 Producer 的主要指标。2. Broker 指标因为所有消息都必须通过 Kafka Broker 才能被使用,所以对集群中 Broker 的监控是最核心的。我们建议关注如下主要指标:3. Consumer 指标Consumer 是 Kafka 消息终点。我们建议关注如下主要指标:4. Zookeeper 指标ZooKeeper 是 Kafka 的一个关键组件(v3.x 之前),ZooKeep 停机将使 Kafka 停止运行。Kafka 监控大盘 建议默认监控大盘至少包含以下指标 panel:1. Producertopic 消息生产量随时间的变化:便于我们快速确定流量来源,并为基础设施的变更配置提供依据。请求/响应速率随时间的变化:密切关注峰值和下降对于确保连续服务可用性至关重要。请求平均延迟随时间的变化:由于延迟与吞吐量有很强的相关性,观察此变化,有助于我们判断是否需要修改 batch.size 参数。IO 等待随时间的变化:如果我们发现等待时间过长,就意味着生产者无法足够快地获取所需的数据。 2. Broker存在失效副本的分区数量的变化:如果此指标突增,则很可能某个 Broker 发生了异常。ISR 数量变化:除 Broker 或 Partition 数量变化会触发 ISR 数量变化外,其它情况下的当前指标变化都需要我们注意。有效 Broker 数量变化。有效 Controller 数量变化。离线分区数的变化:此指标大于 0,则意味着这些数量的分区不可用,该分区的消费者和生产者都将被阻塞。Leader 选举速率和耗时的变化:发生选举,则意味着某个 Leader 的丢失;耗时过长,则会导致此期间消息无法接收生产者消息和消费者的请求。请求耗时:通常该值应相当稳定,波动很小。 网络流量:提供潜在瓶颈所在位置的信息,为我们判断是否启用消息的端到端压缩提供依据。生产/拉取 purgatory 消息数量:通过观察 purgatory 中消息数量,有助于我们确定消息生产或拉取耗时长的原因。 3. Broker JVMFull GC 频率和耗时:GC 频率高或耗时长,都对 Broker 性能有重大影响。据此,我们可以判断是否需要对内存进行扩容。4. Consumergroup 消费延迟数量的变化:该指标越大,则消息堆积越多。消费流量的变化:显示消费消息的网络流量/消息流量大小变化。拉取数据速率的变化:消费者是否健康的重要指标。 5. Zookeeper待处理的请求数的变化。平均请求响应耗时的变化:如果耗时突增,则可能导致整个 Kafka 集群的协调机制受阻。客户端连接数的变化:连接数的突变,通常伴随着 Broker 的加入、退出或丢失。打开的文件句柄数和剩余数的变化:如果剩余数不足,则可能导致 Broker 无法连接到 Zookeeper。同步请求 pending 数量的变化。 Kafka 告警规则 我们建议配置如下告警规则:1. Producer发送失败消息数:当前发送失败的消息达到一定数量时告警。发送重试消息数:当单位时间内发送重试的消息数量达到阀值时告警。发送耗时长:发送耗时大于 x 毫秒。 2. BrokerController 正常:有效 Controller 数量不为 1。无离线分区:离线分区数大于 0。无 UnClean Leader 选举:Unclean Leader 选举速率大于 0。Broker 不可用:有效 Broker 数量减少。ISR 收缩:Topic 分区的 ISR 数量小于 n。分区不可用:Topic 分区处于 Under Replicated 状态。Topic/分区容量:Topic/分区数量大于 n。实例消息流入/出量:当前实例的流量超过或低于某个阀值时告警。Topic 消息流入/出量:当前某个 Topic 的流量超过或低于指定阀值时告警。磁盘容量:磁盘使用率大于 x%(参考值:85%)。CPU 使用率:大于 80%。 3. Broker JVM:FullGC 频率:对频繁的 FGC 告警。4. Consumer消息堆积:group 消费延迟数量大于 n(根据业务流量,适当配置 n 的大小)。5. Zookeeper同步请求 pending 数量大于 n。Kafka 典型问题场景及其排查/解决方法Topic 消息发送慢,并发性能低 1. 场景描述某个或某几个 Topic 的消息并发发送性能低。在指标上直接体现为 Producer 的平均请求延迟大、平均生产吞吐量小。2. 问题原因通常消息发送慢有如下几种典型原因:网络带宽不足,导致IO等待。消息未压缩,导致网络流量超负荷。消息未批量发送,或批量阀值配置不恰当,导致发送速率慢。Topic分区数量不足,导致Broker接收消息积压。Broker磁盘性能低,导致磁盘同步慢。Broker分区数总量过多,导致碎片化,磁盘读写过载。 3. 排查/解决办法根据上述原因,我们逐一查看对应的监控指标/大盘,定位并解决问题:确认 Producer 的“平均 I/O 等待时间”指标是否符合预期或有陡增?以便确认 Producer 到 Broker 之间的网络带宽是否满足业务流量要求?如果不满足,则需要硬件资源扩容。确认 Producer 的“平均压缩率指标”,确保压缩率符合预期?如果压缩过低,则需要 Producer 端进行排查、修正。确认 Producer 的“平均请求包大小”是否过小?如果是的话,则需要考虑加大 Producer 发送消息的 batchsize,同时调整 linger.ms 的阀值,以避免请求消息碎片化。查看 Topic 分区数,分区数较小时,考虑增加分区数,以水平扩展 Broker 的并发接收消息容量。确认 Broker 磁盘 IO 使用率是否在安全范围内?如果使用率已经较高,则考虑水平扩容 Broker 数量以分担磁盘压力,或升级磁盘为 SSD 以提升 IO 性能。确认 Broker 的 CPU 使用率是否在安全范围内?如果使用率已经较高,则考虑垂直或水平扩容 Broker,同时考虑增加 Topic 分区数,以提升 Topic 并发接收消息能力。查看集群的总分区数和单个 Broker 的分区数量,确保在规划的容量范围内。否则应考虑水平扩容 Broker 数量,以避免碎片化磁盘读写导致的性能下降。 Topic 消息堆积1. 场景描述某个或某几个 Topic 的消息堆积持续增加。在指标上直接体现为 group 消费延迟数量持续增加。2. 问题原因通常消息堆积有如下几种典型原因:Producer 生产消息流量增大。Consumer 由于业务变化导致消费延迟增加。Consumer 数量不足。Consumer 数量频繁变化,导致 Group 不断做再平衡(Rebalance)。Broker 未收到 Consumer 消费确认消息。 3. 排查/解决方法根据上述可能的原因,我们逐一查看对应的监控指标/大盘,定位并解决问题:确认 Producer 的“消息生产量”指标是否有明显增加?如果有显示增加,则我们需要对应增加消费者数量。确认 Consumer 的“消息消费流量”指标是否明显下降?如果有显示下降,则说明消费者的业务处理耗时增加,我们需要确认业务消耗,或增加消费者数量。通过 Kafka Broker 提供的命令,确认 Topic 对应的 Consumer 数量与实际的 Consumer 数量是否一致?如果不一致,则说明某些 Consumer 未正确连接到 Broker,需要排查 Consumer 是否正常运行。观察 Consumer 的数量是否频繁变化而触发反复再平衡(Rebalance),如果是,则我们需要排查确认各个 Consumer 是否正常运行。由于网络或其它原因,可能导致 Consumer 与 Broker 之间的连接不稳定,Consumer 能持续消费消息,但 Broker 却始终认为消息未确认,导致消费位点不变。此时可能需要确认 Consumer 与 Broker 之间的网络稳定性、甚至重启 Consumer。 4. 自建 Prometheus 监控 Kafka 的痛点自建 Prometheus 观测 Kafka,我们将面临的典型问题有:由于安全、组织管理等因素,用户业务通常部署在多个相互隔离的 VPC,需要在多个 VPC 内都重复、独立部署 Prometheus,导致部署和运维成本高。每套完整的自建观测系统都需要安装并配置 Prometheus、Grafana、AlertManager 等,过程复杂、实施周期长。开源 Kafka JMX Agent 在某些场景下占用 CPU 高,对自建 Kafka 业务有一定干扰。对于阿里云消息队列 Kafka 版(简称阿里云 Kafka),自建 Prometheus 无法监控到,导致无法实现一站式、全局视角的监控建设。对于部署在 ECS 上的自建 Kafka,自建 Prometheus 缺少与阿里云 ECS 无缝集成的服务发现(ServiceDiscovery)机制,无法根据 ECS 标签来灵活定义抓取 targets。如果自行实现类似功能,则需要使用 GOlang 语言开发代码(调用阿里云 ECS POP 接口)、集成进开源 Prometheus 代码、编译打包后部署,实现门槛高、过程复杂、版本升级困难。开源 Grafana Kafka 大盘不够专业,缺少结合 Kafka 原理/特征和最佳实践进行深入优化。缺少 Kafka 告警指标模板,需要用户自行研究、配置告警规则,工作量大,且很可能缺少 Kafka 领域的专业技术沉淀。对比阿里云 Prometheus 监控是一款全面对接开源 Prometheus 生态,支持类型丰富的组件观测,提供多种开箱即用的预置观测大盘,且提供全面托管的混合云/多云 Prometheus 服务。除了支持阿里云容器服务、自建 Kubernetes、Remote Write 外,阿里云 Prometheus 还提供混合云+多云 ECS 应用的 metric 观测能力;并且支持多实例聚合观测能力,实现 Prometheus 指标的统一查询,统一 Grafana 数据源和统一告警。阿里云 Prometheus 提供了阿里云 Kafka 和自建 Kafka 的全套支持。使用阿里云 Prometheus 监控 Kafka下面分别介绍如何使用阿里云 Prometheus 监控阿里云 Kafka 和自建 Kafka。使用阿里云 Prometheus 监控阿里云 Kafka 阿里云 Kafka 针对开源的 Apache Kafka 提供全托管服务,解决开源产品的痛点。用户只需专注于业务开发,无需部署运维。相较于开源 Apache Kafka,消息队列 Kafka 版成本更低、弹性更强、可靠性更高。阿里云 Kafka 现已默认集成了阿里云 Prometheus 监控。由于阿里云 Kafka 无需用户部署和运维,因此 Prometheus 监控聚焦在“使用 Kafka”场景,主要透出的指标有:实例/Group/Topic 各级的流量指标Group 和 Topic 的消息堆积指标实例磁盘使用率指标Group 的 Rebalance 指标 查看阿里云 Kafka 监控大盘 阿里云 Kafka 提供了实例、Group 和 Topic 等三个监控大盘。通过这三个大盘,用户可以快捷、清晰地掌握 Kafka 消息的生产和消费情况,快速定位使用阿里云 Kafka 过程中遇到的问题。用户可登录阿里云 Kafka 控制台,进入 Kafka 实例详情界面“Prometheus 监控”菜单或 tab 页查看。https://kafka.console.aliyun.com/阿里云 Kafka 实例监控大盘阿里云 Kafka 消费组监控大盘阿里云 Kafka Topic 监控大盘使用阿里云 Prometheus 配置阿里云 Kafka 告警 用户可以登录阿里云 Prometheus 控制台,进入“云服务监控”实例的“集成中心”界面,选择“云产品自监控集成”tab,点击“消息队列 Kafka”,弹出窗口中的“告警”tab 页,即可查看和新增阿里云 Kafka 的 Prometheus 告警。创建 Prometheus 告警的详细操作步骤,详见 Prometheus 告警规则文档。https://help.aliyun.com/document_detail/331981.html阿里云 Prometheus 提供了 13 条默认告警指标(持续更新中),涵盖了实例、Group 和 Topic 的关键指标,方便用户快速配置常见告警规则。使用阿里云 Prometheus 监控自建 Kafka 除了阿里云 Kafka 外,阿里云 Prometheus 同时提供了自建 Kafka 的监控接入能力。支持容器服务(包含 ACK、ASK、注册集群等)和 ECS 这两个环境类型的 Kafka 监控,提供基础和高级两个版本:基础版:收集 Broker 数量、Topic 分区、消息组 Lag 等基础指标,Kafka 服务端无端任何配置或重启。 高级版:除基础版能力外,通过 JMX Agent,收集生产者、服务端、消费者及其内部各模块的的重要指标,实现全链路、一体化的专家级 Kafka 监控。但需要进行 JMX Agent 注入和进程重启。 与阿里云 Kafka 的监控场景不同,自建 Kafka 时,用户除了需要关注“使用 Kafka”的例行指标外,还需要进一步关注“运维 Kafka”的内部指标。因此需要深入抓取 Kafka 生产者、服务端、消费者及其内部各模块的重要指标,以便分析和排查 Kafka 本身各环节的可能问题,因此我们推荐使用高级版,以便全面掌握自建 Kafka 的运行状态。对于 ZooKeeper 和其它基础监控(磁盘、网络等),请参考使用 Prometheus 监控 ZooKeeper 和 Node Exporter 组件接入配置 Prometheus 监控。https://help.aliyun.com/document_detail/161845.htmlhttps://help.aliyun.com/document_detail/445268.html使用阿里云 Prometheus 进行自建 Kafka 的基础监控 1. 部署自建 Kafka 的基础监控登录阿里云 Prometheus 控制台,访问 ARMS 接入中心,点击组件应用“Kafka(基础版)”的“添加”按钮,在弹出界面选择 Kafka 所部署的环境(目前支持“阿里云容器服务环境”和“阿里云 ECS 环境”),选择 Kafka 所在的 Prometheus 实例,然后填写配置信息。配置连接 Kafka 所需的各项信息:Exporter 名称:当前 Kafka 监控唯一命名。Kafka地址:填写 Kafka Broker 的连接地址。多个 Broker 地址之间使用逗号或分号来分隔。容器服务内,则可以使用 Kafka Broker 的 IP 或 Service 地址。ECS 环境内,则可以使用 Kafka Broker 的 IP 或 DNS 地址。 metrics 采集间隔(秒):监控数据采集时间间隔。Kafka版本:选择确定 Kafka 服务端的版本号,目前最高支持 3.2.0。开启 SASL:选择确定 Kafka 服务端是否使用 SASL。SASL 用户名:如果开启 SASL,则填写对应的用户名。SASL 密码:如果开启 SASL,则填写对应的用户名密码。SASL 方法:选择确定 SASL 方法,目前支持 plain、scram-sha512 和 scram-sha256 等三种。开启 TLS:选择确定 Kafka 服务端是否使用 TLS。忽略 TLS 安全校验:如果 Kafka 服务端开启 TLS,且是自签名证书,则选择忽略 TLS 安全校验。2. 查看自建 Kafka 的基础监控大盘进入 Prometheus 实例的集成中心,点击“Kafka(基础版)”,在弹出界面选择“大盘”tab 页,点击大盘缩略图,即可查看对应 Grafana 大盘。基础版监控大盘主要展示:Kafka Broker 数量。每个 Topic 的分区数。每个 Topic 的消息入/出/堆积数量。每个 Topic 的 ISR(In-Sync Replicas)数量。3. 配置自建 Kafka 的基础监控告警进入 Prometheus 实例的集成中心,点击“Kafka(基础版)”,在弹出界面选择“告警”tab 页,即可查看/新增当前 Prometheus 实例的 Kafka 基础版告警规则。创建 Prometheus 告警的详细操作步骤,详见 Prometheus 告警规则文档。https://help.aliyun.com/document_detail/331981.html目前 Kafka 基础版监控提供了 4 个告警指标。用户可根据实际情况,实例化告警规则。Consumer Topic 消息堆积。分区数量过多:为 Kafka Broker 定义保护性告警,避免分区数量过多导致性能急剧下降。存在 Under Replicated 分区。有效 Broker 数量减少。使用阿里云 Prometheus 进行自建 Kafka 的高级监控部署自建 Kafka 的高级监控 首先需要用户按照部署和配置 JMX Agent 文档,自行在 Kafka Producer、Broker 和 Consumer 端安装和配置 JMX Agent,以便将暴露 Kafka Metric 给阿里云 Prometheus。然后访问 ARMS 接入中心,点击组件应用“Kafka(高级版)”的“添加”按钮,在弹出界面选择 Kafka 所部署的环境(目前支持“阿里云容器服务环境”和“阿里云 ECS 环境”),选择 Kafka 所在的 Prometheus 实例,然后填写监控接入的配置信息。Exporter 名称:当前Kafka监控唯一命名。kafka实例名称:Kafka实例名称,通过该名称,将Kafka Producer、Broker和Consumer进行关联,实现Topic全链路的大盘展示。JMX Agent监听端口:部署JMX Agent时配置的监听端口。metrics采集路径:Prometheus采集JMX Agent的http path,默认是 /metrics。metrics采集间隔(秒):监控数据采集时间间隔。Pod/ECS标签/值:部署JMX Agent时,给Pod/ECS配置的标签和标签值,Prometheus通过此标签进行服务发现(Service Discovery)。 查看高级监控大盘 进入Prometheus实例的集成中心,点击“Kafka(高级版)”,在弹出界面选择“大盘”tab页,点击大盘缩略图,即可查看对应Grafana大盘。高级版监控提供了Intance和Topic两个视角的大盘。自建Kafka Instance大盘 展示 Kafka Broker 内部各项指标:核心指标:展示Broker数量、OffLine分区数、Under Replicated分区数、Contrller数量、CPU/网络等关键信息。JVM指标:展示JVM的内存和GC关键信息。分区指标:展示分区数量、ISR、Unclean Leader选举、Replica Lag、Offline分区、Under Replicated分区等明细信息。时间指标:展示Produce、Request、Fetch等各个环境的时间指标。集群流量指标:展示集群的总体流量指标。Broker流量指标:展示Broker粒度的流量明细指标。 自建 Kafka Topic 大盘 展示各个Kafka Topic全链路指标:Producer:展示Producer端的关键指标,包括消息发送速度、消息压缩率、发送延迟等。Server(即Kafka Broker):展示该Topic对应的分区数、入/出消息速率、入/出消息流量。Consumer:展示消息消费速率、消费延迟和Rebalance等。 配置自建Kafka的高级监控告警 进入Prometheus实例的集成中心,点击“Kafka(高级版)”,在弹出界面选择“告警”tab页,即可查看/新增当前Prometheus实例的Kafka高级版告警规则。Kafka高级版提供Producer、Instance和Consumer三方面的告警指标,供用户选择和配置。创建Prometheus告警的详细操作步骤,详见Prometheus告警规则文档。自建Kafka Producer:提供了消息发送失败率、消息发送耗时、消息发送重试率等3个告警指标,方便用户对Producer端的异常进行告警。自建Kafka Instance:提供了分区数量过多、存在OffLine分区、存在UnClean Leader选举、存在Under Replicated分区、有效Broker数量减少、有效Controller数量、实例消息拒绝量、实例消息流入/出量、Topic消息流入/出量等13个告警指标,覆盖了Kafka Broker各方面异常。自建Kafka Consumer:提供了消息消费堆积告警指标,通过该告警规则,用户能第一时间掌握消费异常情况。结束语阿里云Prometheus的Kafka监控,以阿里云消息队列Kafka丰厚运维实践为基础,结合Kafka社区运维建议,提供了阿里云Kafka和自建Kafka监控的一体化解决方案。针对自建Kafka的场景特点,提供了基础版和高级版监控接入,满足用户不同场景、不同深度的Kafka监控需求。同时支持容器服务环境和ECS环境的Kafka部署,满足用户不同环境的监控需求。Kafka高级版提供200+个有效metric、10+个关键大盘panel、60+个辅助大盘Panel、17个告警指标(持续更新中),为用户提供全链路、一体化的专家级Kafka监控支撑,保障业务稳定运行。后续我们将持续优化自建Kafka高级版的部署便利性,以进一步简化用户部署JMX Agent的操作。同时还将深度优化JMX Agent的性能,减少对自建 Kafka Broker的CPU消耗。点击此处,免费开通 Prometheus 监控!
作者:银桑背景11 月 5 日,在 2022 杭州 · 云栖大会上,数字化安全生产平台 DPS 重磅发布,助力传统运维向 SRE 转型,在数字化安全生产平台 DPS 重磅发布中提到了 DPS 诞生的背景,希望解决的企业问题以及核心的功能点,其中提到了 DPS 目前的两大业务场景:"1-5-10"故障快恢和"变更三板斧"故障预防,本文将阐述 “1-5-10”故障快恢场景的背后的设计与实现。1-5-10 介绍1-5-10 对应故障的“1 分钟发现-5 分钟响应-10 分钟恢复”,是定义故障处理的时效性目标。在阿里巴巴内部经过多年的实践,1-5-10 早已成为各个业务稳定性、基础设施稳定性以及大促保障的重要牵引指标,目的是缩短故障恢复时长(MTTR),降低故障影响。DPS 通过将阿里云高可用产品体系与阿里巴巴安全生产理论体系相结合,实现了 1-5-10 的产品化落地。下图是 1-5-10 的产品架构图: 1-5-10 场景包括事前稳定性分析,事中应急处理,事后持续运营三个步骤。事前稳定性分析是 1-5-10 的前提,包括业务分析,风险分析以及组织分析三个维度。DPS 通过专家咨询服务加产品线,服务组,业务场景拓扑等产品功能相结合的方式来实现。事中应急处理是 1-5-10 的核心,包括以下几个部分: 故障发现:通过建立围绕业务应用的全链路监控能力,能够实时监控业务健康度,如发现稳定性问题通报至应急保障服务组进行排查,降低故障发生的可能性。故障响应:通过建立应急响应渠道和全链路故障定位能力,能够快速拉通故障排查人员,基于 AIOps 智能故障定位和基于 ChatOps 进行故障状态更新和通知流转,提升故障处理效率。故障快恢:通过建立完善的故障快恢体系,基于方案内置丰富的快恢能力,能够根据不同的故障类型智能化推荐合适的快恢预案,缩短故障恢复时长。事后的持续运营是 1-5-10 的效果度量,包括以下几个部分: 结果指标:用来衡量稳定性保障的结果,核心是业务可用率,重大故障收敛数目以及无重大故障时长。能力指标:从提升稳定性能力的角度来分析,核心就是 1-5-10 的达标率,并且支持从故障,事件,组织,人员,团队等多维度来进行分析。以上是 1-5-10 场景的整体产品能力介绍,下面展开介绍 1 分钟发现,5 分钟响应以及 10 分钟快恢是如何设计与落地。1 分钟发现要做到故障的一分钟发现,首先需要有完善的监控/告警体系,其次需要有明确的故障结构化定义。在实际应用中,会遇到如下的一些问题:面临问题业务监控的复杂性导致问题的淹没一个生产业务监控,涵盖了各式各样的指标,从业务层面、应用层面、服务层面、系统层面,基础设施层面等等,比如下面:网络传输监控(丢包,延迟)服务器系统状态(CPU、load)虚拟机,容器监控应用运行状态(成功率、qps)业务运行状态(订单创建量…)用户体验(白屏、内容错误)当故障发生的时候,可能上述任何一层的指标都会出现异常,如果不能对指标进行合理的分层和针对性的建设,就会被淹没在一堆指标告警监控里面,不但可能忽略真正的问题,还有可能使得运维人员难以应付。监控数据和故障不能有效关联什么是故障? 在日常运营中,无论什么原因导致服务中断、服务品质下降或用户服务体验下降的现象,称为故障。只有清楚定义业务故障,并且将故障监控进行关联才能做到真正故障的快速发现。然而在生产业务中,往往只聚焦于监控治理,而忽略了故障定义的重要性。解决思路监控指标分类可以将指标能否直接反馈业务功能是否可用,将指标分为如下类别:业务指标:业务指标可以直观的反馈业务或者系统功能是否正常可用,常用的指标有业务请求吞吐量、业务成功率、业务错误率、业务性能;另外对于金融类的业务来说,数据正确性也是要观测的指标,比如资金对账、数据一致性等。业务指标的监控方式优先采用日志监控,通过对业务日志的加工,识别出成功率、响应率、业务身份等等因素,因此需要业务日志有比较好的格式化,对于资损类的故障监控可以通过订阅 binlog、业务消息的方式来进行对账。服务指标:服务指标是指能够反馈业务依赖的接口服务是否可用的指标,统计的指标类型类似于业务指标,只不过一个接口维度,同样可以分为吞吐率、成功率、错误率以及性能。 比如对于一个数据库服务,对于一个查询服务来说,它的几个指标如下:环境指标:环境指标又可以是资源指标,用来反馈底层基础设施或者依赖服务可用率,对于资源类的指标可以分为四个类型 使用率是资源繁忙的时间百分比,或正在使用的资源容量的百分比。饱和度是资源无法服务 (通常已排队) 的请求工作量的度量。错误表示资源产生的工作中可能无法观察到的内部错误 。可用性表示资源响应请求的时间百分比。此指标仅针对可以主动定期检查可用性的资源定义。异常事件:监控指标相对是连续的,对于一些离散的,不频繁的异常可以通过事件(Event)监控来进行获取,并且相对于单一的监控指标,事件还提供了一些上下文的信息,事件举例:以上要求 DPS 不但需要支持不同类型数据采集,还需要针对数据根据应用维度、业务维度分类处理。故障结构化定义发现体系建设的对象是故障, 怎么去快速发现已经发生的故障以及潜在可能变成故障的风险,因此对于能够直接反映系统功能是否可用的指标要重点建设, 所以监控指标的处理优先级就是:核心指标监控 → 非核心监控(业务,服务)→ 系统监控(环境指标)。核心指标监控核心指标监控就是能够直接反馈功能是否可用,核心指标的下跌或者其他异常一定会导致不同程度的故障,因此对于核心指标要通过故障场景的方式来定义应急平台上,所谓的故障场景包含了以下几个方面:核心指标监控故障等级定义负责的产品线负责的处理人员可能的影响面出现问题之后的预案比如对于交易下单业务下跌这一应急场景来说,可以有如下例子:这里重点是故障等级怎么来定义? 故障等级定义可以考虑影响点以及影响面联合来定义:影响点:可以是用户体验,资金损失以及社会舆情。影响面:变化服务,持续时间,投诉数量,资损金额等。非核心监控:因为故障一旦发生,后面会有一连串的应急制度,所以对于故障要谨慎定义并且收敛,那么对于非核心监控的变化,我们可以采用风险预警的方式,风险预警就是对可能会导致故障的因素做出预警,同样也会涉及到产品线,处理人员,预案等信息,同时预警会有一个升级成故障的机制,比如预警多次或者影响面扩大。上面的核心监控和非核心监控都需要有横向的监控值班人员来进行统一关注,特别是故障发生之后需要有技术支持类的角色来进行组织和响应处理。系统监控:因为系统监控异常的概率非常高,特别是大规模集群下,部分机器的 CPU,内存等资源发生变化是常有的事情,对于这些系统级别的告警,只需要配置普通的告警规则即可,由各个应用系统人员独自去处理即可;如果是大规模的机器故障,必然会导致核心或者非核心监控的告警,这些系统监控指标可以作为定位的数据来源。以上要求 DPS 不但需要确立故障模型,以便故障的结构化定义,还需要基于监控数据的故障定级以及通告能力。产品落地DPS 在发现体系产品化上具备全链路监控、故障场景结构化,以及智能告警三个能力。应用全链路监控通过与阿里云可观测体系深度集成,DPS 实现了从用户体验端到基础设施端的全链路监控,包括业务日志监控、APM 监控、前端监控、基础设施监控等。故障场景结构化监控数据本身不具备业务含义,以单条 Trace 调用链路为例,能够知晓它经过了哪些应用和接口,但是无法了解代表的业务,很难做到业务维度的精准监控。DPS 提供了全息业务链路治理功能,可通过请求参数、cookie 等上下文标记对调用链路进行染色形成业务链路,对染色后的链路按照业务维度进行聚合生成业务活动,构建从产品线->业务活动->业务链路->故障场景的治理体系。DPS 支持按照业务受损程度,数据影响面以及舆情影响面来划分不同的故障等级,并且支持按照故障的持续时间和影响面来自动对故障进行升降级。智能告警当事件/故障产生以后,需要通过告警触达到处理人员。在一个重大业务故障的持续时间内,不光已有的告警事件会继续发送,由于爆炸半径的不断扩大也会产生新的告警事件,DPS 会对告警事件进行过滤,降噪聚合等操作,根据事件的时间,影响面,业务特征等归纳到相同的故障下,避免告警的持续通告。5 分钟响应要做到故障的 5 分钟响应,首先需要有一套标准的应急响应流程,其次需要能够快速定位问题,作出恢复决策。在实际应用中,会遇到如下的一些问题:面临问题应急协同缺乏标准流程驱动故障发生后的应急操作,往往需要多个技术团队和技术工种协作完成,涉及到研发,运维,测试等不同角色,谁来组织应急,谁来处理,谁来做决策,需要有一定的应急机制,来确保相关人员能够快速响应和高效协作。故障应急需要从故障源采集环境信息,关联不同的环境信息,分析故障原因,采取行动(展示、推送、处理、通知。但是当处理故障的规模放大,面对着多系统、多团队的软件组织,如何能够高效地完成信息的采集、传递和处理?无法快速定位问题导致故障产生的原因有很多,比如流量问题、网络问题、编码问题、依赖服务问题,基础设置问题,还有配置变更问题,牵一发而动全身,在复杂的系统架构和业务链路下,如何能够有效地查询到故障的上下文信息,快速定位问题?解决思路应急协同流程标准化可以将故障处理流程中的人员角色分为三类: 负责协调的技术支持人员,负责应急的处理人员以及负责决策的指挥人员。技术支持人员技术支持在应集中起到了非常关键的作用,对内,要有效组织直接处理人员的集中和协作;对外,负责对接业务部门同步信息,同时屏蔽各方对技术团队和故障处理人员的干扰。当出现一个严重故障后,技术支持通常要做如下关键事项:确定故障影响面以及定级。当故障产生之后,需要根据故障定级标准,快速做出初步判断,确认影响面,以及故障等级。组织应急。对于无法马上恢复或需要定位排查的故障,需要将相关技术团队主管和开发人员召集在一起,可以是线下会议室的形式,也可以是线上即时通讯拉群的方式,同时确认故障处理主要指挥者。信息通报。组织应急之后,需要每隔一段时间,对故障进展做一次信息同步。同时,如果等级和故障信息变化,也要同步出来,直至故障排除,业务恢复。并且技术支持要确保处理故障人员能够相对地专注在故障处理上,而不是响应来自各方的询问。处理人员处理人员由一线研发负责,要遵循“先签到,再止血,后恢复”的原则,即在技术支持进行故障通告后,研发在处理前需要进行签到通告,以防止多人处理引发的冲突问题。在处理中要优先止血,防止故障影响面的扩大,这就需要能够快速判断故障的初因以及执行合理的预案。最后是故障的彻底恢复,包括根因定位以及影响面的消除。决策指挥人员指挥人员用于重大故障恢复时候的决策,当严重故障涉及到了多个业务影响面,无法由研发人员独立做出决策,就需要上升。以上要求 DPS 不但需要将应急流程通过平台流程来驱动,并且需要为不同的角色人员提供特定的功能以帮助其更好地进行故障处理。故障初因与根因定位在进行故障定位需要从初因和根因两个方面来处理。初因即导致故障的直接因素,需要能够快速给出结论,以便于故障的快速止血,根因即导致故障的根本原因,在复杂的系统中要彻底定位问题往往耗费许久,因此根因定位一般用于故障的恢复以及复盘改进。初因定位包括全局变更诊断,比如故障发生前的发布变更,配置变更或者是数据变更,像在阿里有 80%的故障是由于变更导致,因此需要能够快速的收集并且查询到指定时间的变更操作,对可疑变更进行回滚操作。此外也可从业务链路维度进行初因定位,查看当前故障业务的上下游业务是否异常,如果是因为上下游业务影响导致,则需要对上下游业务进行降级之类的处理。根因定位包括代码 BUG 类定位,进程内资源不足,基础设施异常等方面。产品落地DPS 在响应体系上包含了故障单,ChatOps 以及智能定位三块能力。故障单当故障产生以后,便会自动生成故障单,故障单上规定了故障的处理流程,并且自动绑定当前故障的技术支持人员,应急处理人员,相关人员只需要通过 DPS 按照流程进行故障处理即可。面向技术支持人员,DPS 提供了故障通告,等级变更,故障时间线,故障影响面管理等功能,帮助其更好地进行组织协调面向应急处理人员,DPS 会自动根据故障场景定义推荐合适的快恢预案,为了保证执行安全预案不会自动执行,处理人员可根据推荐建议选择面向指挥决策人员,DPS 提供了安全生产大盘,提供了全局的业务影响面视角以及故障处理视角,帮助其了解故障影响面和不同人员的处理状态ChatOpsChatOps 能够给故障处理流程带来更好的透明度,实现信息共享的同时提升应急效率和便捷性。像钉钉,企业微信都是作为 ChatOps 承载平台的好选择,基于这些平台的开放能力,DPS 打造了一个应急机器人,通过应急机器人可以直接在手机端进行故障处理,包括签到,进展更新,快恢执行等,获取和 PC 控制台一样的使用体验。智能定位DPS 在定位上能力包括:基于故障场景拓扑的初因定位,借助于人工配置的故障场景拓扑关系来作出推断。举个例子,比如购物车和下单是两个上下游的业务,两个业务分处于不同团队,当购物车故障产生导致了下单业务故障,DPS 会自动向双方的故障应急群发送通告,告知故障原因以及影响面,并且在两个群同步故障进展。基于全息业务链路的初因定位,一旦开启全息业务功能,则无需手动创建拓扑关系,DPS 会自动识别出业务链路上下游节点的异常,关联到故障单上。基于阿里云可观测 Insight 技术的根因定位,通过 Insight 技术可精准定位到具体哪一台机器,哪一条调用链路的异常。10 分钟快恢1-5-10 场景的核心是快恢,发现体系和响应体系建设都是为了快速的恢复故障。要建设快恢体系首先需要建立起快恢能力,其次要针对故障特征合理使用快恢能力。面临问题故障恢复的手段有很多,比如应用重启,系统回滚,机器下线,重新发布,扩容限流等等,但是这些快恢能力分散在不同的系统里面,难以管控。在云原生下各类平台框架爆发式增长,开发者可以很便捷地引入各类技术,但是存在概念和使用方式差异化的问题,比如限流能力多个框架都可提供,但是不同框架间的定义却不相同,增加了认知和配置成本。由于缺乏快恢能力的标准化建设,导致快恢能力缺乏统一的度量标准,能力间难以组合和复用,新的快恢能力难以快速集成到平台。快恢能力的使用不存在银弹一说,能力选择上要考虑实施成本以及时效性等多方面因素,同时一些严重故障可能需要多种快恢能力的组合,比如应用集群里面某台机器出现了异常,重启以及下线隔离都可解决问题,很明显隔离相比重启有更好的时效性。解决思路通过定义快恢的公共抽象模型以及每个能力分类的抽象模型,实现快恢能力标准化,来降低不同产品间的认知成本和配置成本。快恢能力声明式设计,即对于使用方来说只需要知晓快恢的最终成功与否,而不需要关心中间过程,但是往往快恢系统本身是不提供这样面向终态的能力,而是命令式的原子能力,这就需要有个中间层来对这些能力进行封装。比如企业使用了阿里云 ECS,需要通过 API 来执行 ECS 重启,但是 ECS 的重启 API 是异步执行,即执行重启之后,返回成功并不代表重启成功,需要调用查询 API 来不断的轮询。这段重启后再轮询的逻辑实现由于不属于业务正常逻辑,而是为快恢做的封装,因此这段逻辑在承担快恢平台角色的 DPS 里是最合适的。类似这样的案例还有很多,因此平台需要支持快恢能力的扩展。快恢能力推荐,即根据故障的特征以及快恢执行时效性来推荐适合的快恢能力,以阿里电商架构的业务故障为例,每一层的快恢手段都会有所差异,比如: 单元级故障,采用切流机房级故障,采用隔离切流接入层故障,采用切流链路级故障,采用降级依赖应用层故障,采用切流,重启,降低数据层故障,采用主备切换产品落地DPS 在快恢体系建设上包括快恢能力标准化定义,云原生化的快恢产品接入以及快恢预案三块能力。快恢能力标准化定义通过对阿里快恢的数据分析,DPS 将快恢分为重启,回滚,扩容,切流,限流以及降级六板斧六个类别,并且已经完成重启和切流的快恢能力模型设计。拿切流举例,切流本质上是将流经某个地址的流量进行再分配的过程,因此 DPS 设计切流模型时分为流量地址,流量筛选以及流量路由三个部分,对于网关组件(ApiSix、Ingress...)等,流量地址即入口域名,流量筛选即根据 Http、Tcp 等方式对流量进行筛选,流量路由即不同地址的流量分配。数据库的主备切换也可以抽象成写流量的调度,主变成备的过程,即写流量从主 100%,备 0% 到主 0%,备 100% 的过程。需要注意的是 DPS 定位故障快恢,在模型定义要简易清晰,因此只抽象出不同快恢产品的通用模型,不会去兼容快恢产品的所有配置规则。云原生的接入方式DPS 定义了快恢产品的 CRD 模型,在 CRD 里面针对不同快恢能力做了模型规范,开发者只需提供快恢产品的 CR,就可完成快恢系统的接入,流程如下图所示:其中 CR 里面包含了快恢执行的镜像,镜像由开发者实现,镜像的创建,扩容以及版本管理都由 DPS 平台负责。容器镜像需暴露一下接口:快恢执行接口,用于执行快恢能力快恢连接测试接口,用于验证快恢系统可用性快恢查询接口,用于异常情况下的结果查询快恢参数提供接口,用于获取参数的可选项,方便使用者进行填写快恢预案快恢能力要通过快恢预案来执行,快恢预案定义了快恢能力的执行策略,主要包括以下内容:触发策略,可与故障场景以及监控告警做关联,当命中触发条件,自动推荐快恢预案。审批策略,对于高危的预案设置不同层级的审批策略,保证预案执行的安全性。运行策略,可对多个不同类型快恢能力进行组合执行。通知策略,可通过多种方式对预案的全生命周期进行通知推送,保证预案执行的透明。可观测策略,借助于 DPS 的可观测能力,实现执行过程中受损业务的监控。总结数字化转型下如何保证业务连续性?1. 首先思想观念要转变,从被动运维向主动运维再到持续改。2. 协作方式的转变,必须要有业务思维,从业务场景出发,打破团队边界,让普通业务人员也参与到安全生产的运维保障中。3. 技术方式的转变,要不断提升自动化运维水平,通过打造一体化平台,为业务保障人员提供统一的工作界面和空间,统一能力标准,统一实现接口,实现能力复用和组合,并且加强数据化运营。1-5-10 场景作为 DPS 推出的首个业务场景,在阿里安全生产最佳实践的基础上,结合外部企业客户诉求持续性的改进优化 ,以帮助企业更好建设故障应急响应机制,提升业务连续性。受限于篇幅,本文中还存在很多未展开的讨论细节,后续也会陆续更新。如果您对于数字化安全生产平台 DPS 有任何疑问,欢迎使用钉钉扫描二维码加入钉钉交流群,期待与您共创!
作者:涂鸦背景随着云原生技术不断普及,越来越多的业务应用开始向云原生架构转变,借助容器管理平台 Kubernetes 的不可变基础设施、弹性扩缩容和高扩展性,助力业务迅速完成数字化转型。其中,集群入口流量管理方式在云原生技术演进过程中逐步通用化、标准化,用户通过 Kubernetes 定义的 Ingress 资源来管理外部访问集群内部服务的方式。微服务架构下,有一些需求开发,涉及到微服务调用链路上的多个微服务同时发生了改动,通常每个微服务都会有灰度环境或分组来接受灰度流量,我们希望通过进入上游灰度环境的流量,也能进入下游灰度的环境中,确保1个请求始终在灰度环境中传递,即使这个调用链路上有一些微服务没有灰度环境,这些应用请求下游的时候依然能够回到灰度环境中。通过 MSE 提供的全链路灰度能力,可以在不需要修改任何您的业务代码的情况下,能够轻松实现上述能力。Kubernetes 网关概述Kubernetes 集群对外暴露流量的方式主要分为三种,Node Port、LoadBalancer 以及 Ingress。对于 Node Port 而言,实现了朴素的端口和后端 Pod 的一一对应,不仅存在单点问题,而且由于端口范围的限制,一旦后端的服务数量上升,会出现无端口可用的情况;而对于 LoadBalancer 来说,其解决 Node Port 的单点问题和端口数量的问题,奈何它是一个纯粹的流量转发资源,并没有路由配置能力,也无法管理后端众多的 Service 应用,所以 Ingress 的诞生就是必然的结果。Ingress 不仅有这天然的路由定义的能力,也扮演者后端众多 Service 管理者的角色。不过这里需要提一句,大众所熟知的 Ingress 资源只是单纯的一个 路由 Resource 定义,真正的实现者和执行者其实是具体的 Ingress 标准实现,包括大家所熟知的 Nginx Ingress Controller 都属于此列。在阿里云 ACK 平台上,有着众多 Ingress 的实现方式,其中包括 Nginx-Ingress 、ALB-Ingress 以及最近推出的 MSE-Ingress,本文将讲述一种较为通用的基于 MSE 微服务治理的统一方案,在 Ingress 网关上实现全链路流量灰度。如何实现在 Ingress 上实现全链路流量灰度首先我们要知道在实现全链路灰度时所必须具备的要素,然后再在 Ingress 环境中实现这些要素,就能够实现在 Ingress 网关下的全链路流量灰度。由历史经验可知,我们这里主要靠标签路由、节点打标以及流量染色这三个要素去实现。标签路由通过对服务下所有节点按照标签名和标签值不同进行分组,使得订阅该服务节点信息的服务消费端可以按需访问该服务的某个分组,即所有节点的一个子集。服务消费端可以使用服务提供者节点上的任何标签信息,根据所选标签的实际含义,消费端可以将标签路由应用到更多的业务场景中。节点打标,如果是在使用Kubernetes Service作为服务发现的业务系统中,服务提供者通过向ApiServer提交Service资源完成服务暴露,服务消费端监听与该Service资源下关联的Endpoint资源,从Endpoint资源中获取关联的业务Pod资源,读取上面的Labels数据并作为该节点的元数据信息。所以,我们只要在业务应用描述资源Deployment中的Pod模板中为节点添加标签即可。流量染色是指我们可以在请求的源头上对流量进行染色,前端在发起请求时根据用户信息或者平台信息的不同对流量进行打标。如果前端无法做到,我们也可以在微服务网关上对匹配特定路由规则的请求动态添加流量标识。此外,流量在链路中流经灰度节点时,如果请求信息中不含有灰度标识,需要自动为其染色,接下来流量就可以在后续的流转过程中优先访问服务的灰度版本。为了实现上面全链路灰度三个要素,MSE 微服务治理提出了泳道和泳道组的概念。举一个例子,我们假设应用的架构由 Nginx-Ingress 以及后端的微服务架构(Spring Cloud)来组成,后端调用链路有3跳,交易中心,商品中心,库存中心,客户端通过客户端或者是 H5 页面来访问后端服务,它们通过 Nacos 注册中心做服务发现。1) 通过设置流量规则对所需流量进行'染色','染色'流量会路由到灰度机器。2) 灰度流量携带灰度标往下游传递,形成灰度专属环境流量泳道,无灰度环境应用会默认选择未打标的基线环境。进入到 MSE 控制台的泳道的定义界面里,我们也可以发现,其对应了全链路灰度实现的三要素:快速玩转 Ingress 全链路灰度我们以 ACK Nginx-Ingress 全链路为例,快速地体验如何借助 MSE 微服务治理,实现 Ingress 的全链路流量灰度,总体的步骤如下:我们主要描述下如何将 ACK Ingress Controller 接入到 MSE 微服务中去,只需在 Nginx Ingress Controller 的 ConfigMap 增加下面两项配置即可:use-mse: truemse-app-name: ingress-canary-test mse-app-name 为自定义的名称,此时我们就可以在 MSE 控制台上看到名为 ingress-canary-test 的阿里云 Ingress 入口了:其余步骤均和 Java 应用的全链路灰度步骤一致,具体可以参考以下这篇文章:https://help.aliyun.com/document_detail/460275.html待我们配置好泳道规则后,我们打对应特征的流量就会流入的对应的泳道中去,我们可以在 MSE 控制台观察灰度的情况,以便验证全链路灰度功能是不是生效了:MSE Ingress 是 MSE 团队自主研发的 Ingress 实现,基于 MSE 云原生网关(同时兼容 Ingress 和 Istio)取代 Nginx 来实现流量托管,不仅有着更强大的性能,也有着天然的流量治理与管控基因,其全链路灰度的玩法与 ACK Nginx Ingress 基本上一致,具体步骤可以参考以下这篇文章:https://help.aliyun.com/document_detail/460375.html
本文作者:郭雨杰,阿里云智能技术专家。Prometheus 集成的 50 多款云产品中,RocketMQ 在可观测方面实现了非常完善的功能,是一个特别具有代表性的云产品。RocketMQ 如何接入 PrometheusRocketMQ 诞生于阿里内部的核心电商系统,是业务消息的首选 MQ 平台。上图是 RocketMQ 5.0 的系统全貌,在接入层、核心组件和底层运维方面做了非常大的改进,具有功能多样、高性能、高可靠、可观测、易运维等众多优势。Metrics、Tracing、Logging 是可观测能力的三大支柱。1. Metrics:RocketMQ 以 Prometheus+Grafana 这种在开源领域广泛使用的产品组合为用户提供了开箱即用的 Dashboard。指标涵盖了消息量、堆积量、各阶段耗时等,该大盘结合 RocketMQ 团队在消息领域多年的研发和运维经验打磨的最佳实践模板,并提供了持续的迭代更新能力。2. Tracing:RocketMQ 首次引入了 OpenTelemetry tracing 的开源标准,按照消息的维度,重新组织了抽象的 span 拓扑。3. Logging:Logging 方面主要进行了一些客户端日志的标准化处理,能够更简单方便地利用日志定位问题。RocketMQ 的所有可观测性数据都是围绕一条消息在生产端、服务端处理、消费阶段展开。从消息的生命周期图上,可以看到一条消息从 Producer 开始发送到 MQ server 接收到的耗时;如果是定时消息根据 Ready time 可以知道定时的时间;从 Consumer 的角度上看,可以知道消息从开始拉取到抵达客户端的网络耗时;从抵达客户端的时间到开始处理消息的等待处理资源耗时;从开始处理消息到最后返回的 ACK 的处理耗时。消息在生命周期的任何一个阶段,都可以清晰地被定义并且被观测到,这就是 RocketMQ 可观测的核心理念。RocketMQ 团队贡献的 RocketMQ exporter 已被 Prometheus 官方的开源 Exporter 生态所收录,提供了 Broker、Producer、Consumer 各个阶段丰富的监控指标。Exporter 基本逻辑是通过在内部启动多个定时任务周期性地从 MQ 的集群上拉取数据,然后将数据规范化后通过端点暴露给Prometheus。MQAdminExt 类封装了 MQAdmin 暴露的各种接口逻辑。从结构上看,RocketMQ 的 Exporter 是站在第三方视角的观察者角色,而所有的指标来自于 MQ 集群的内部。Prometheus 在应用程序中暴露监控指标的过程需要注意以下两点:1. Exporter 部署模式的选择分为将 Prometheus client 内嵌到应用程序的直接观测模式以及应用程序之外的独立 Exporter 模式。直接观测模式具有主流语言支持、性能更优、免运维的优势,劣势为代码耦合。Exporter 模式具有解耦合、开源生态丰富的优势,最大的缺点是需要单独的运维 Exporter 组件,在云原生微服务的应用架构模式下需要部署多个 Exporter 对运维带来不小的负担。对于部署模式的选择没有优劣之分,一般建议对应用代码有掌控权限的条件下,选择直接观测模式,对应用代码无掌控权限的条件下选择 Exporter 模式。2. 尽量避免指标维度发散而引起的高基数问题。由于 Prometheus 的指标模型扩展维度只需要添加一个 label非常的方便,很多用户将需要的尽可能多的维度都添加到指标中,这就必然会引入一些不可枚举的维度,比如常见的 userid、url、email、ip 等。Prometheus总体的时间线数量按照指标以及维度的组合乘积关系来计算,因此高基数问题不仅带来了巨大的存储成本,而且会由于瞬时返回的数据过多,对查询侧带来不小的性能挑战,并且严重的维度发散使得指标本身失去了统计上的意义。因此,在使用过程中,应尽量避免指标维度发散问题。我们在使用 Prometheus Client 时也会遇到高基数问题,尤其是 RocketMQ 的指标,提供了账号、实例、 topic、 消费者 Group ID 等多个维度的组合使得整体的时间线数量处于一个很高的量级。实践过程中我们针对 Prometheus 原生的 Client 做了两点针对性的优化,目的是有效地控制 Exporter 的高基数问题带来的内存隐患。RocketMQ 的生产环境中,需要做到对售卖租户的客户级监控。每个客户的 RocketMQ 资源都按照租户进行严格隔离。如果为每一个租户部署一套 Exporter ,则会对产品的架构、运维等方面都带来非常大的挑战。因此在生产环境中,RocketMQ 选择了另一种接入 Prometheus 的方式。RocketMQ 5.0 的架构方面做出了较大的改进。多语言瘦弱客户端底层统一使用了 gRPC 协议将数据发送到服务端,同时 MQ server 也拆分为了可拆可合的 CBroker(proxy)和 SBroker 两个角色。架构变更的同时,RocketMQ 5.0 在客户端和服务端同时引入了 OpenTelemetry tracing 标准埋点的规范。全链路 Tracing1. 客户端嵌入了OpenTelemetry Exporter,将 Tracing 的数据批量发送到 proxy。2. proxy 本身作为一个 collector 整合了客户端上报的以及自身的 tracing 数据。3. tracing 的存储支持用户自定义 collector,商业版托管存储,开源版本存储上报到自己的平台。4. 针对消息的生命周期,重新设计了 span 的拓扑模型。准确多样的 Metrics1. 在服务端对收到的 tracing 数据进行二次聚合计算,得到的计算后的指标符合OpenMetrics 规范。2. 可以无缝地集成到 Prometheus 存储和 Grafana 的大盘展示。RocketMQ span 拓扑模型。该拓扑模型针对 Prod、Recv、Await、Proc、ACK/Nack 阶段分别做了重新规范化的埋点处理,同时将 OpenTelemetry的 tracing 模型中的 attributes 部分规范提交到 OpenTelemetry specification 标准组织并得到收录。以上的改进使得消息轨迹功能得到了极大的增强,不仅可以根据消息的基本信息查询相关轨迹,还能对消息的生命周期的各个阶段一目了然。点开 trace ID ,还可以看到详细的追踪信息,并且可以关联看到生产者、消费者以及相关资源,比如机器信息的展示。RocketMQ 的指标数据为什么要接入到 Prometheus ?因为 Prometheus 天然契合了云原生的架构,在开源领域 Prometheus 处于 metrics 事实规范地位。Prometheus 为云原生架构而生,与 Kubernetes 天然集成,具有自动发现、多层次采集的能力、强大的生态、通用的多模指标模型、以及强大的 PromQL 的查询语法等特点。RocketMQ 是基于 trace 数据进行二次计算为 metric 来对接 Prometheus 的。前文讲到了 RocketMQ 5.0 引入了 OpenTelemetry tracing 埋点,我们将客户端和服务端上报的 tracing 数据统一存储到阿里云日志系统中,基于 tracing 数据根据多个维度进行二次聚合,产生了符合 Prometheus 指标规范的时序数据。在 ARMS 团队内部,通过实时 ETL 工具将日志数据转化为指标按租户存储到 Prometheus 系统中。RocketMQ 控制台深度集成了 Grafana 的大盘和 Alarm 告警模块,用户只需要在 RocketMQ 的实例监控页面中开通 Prometheus 即可一键获取自己名下的大盘和告警信息。ARMS Prometheus 集成了众多的云产品监控指标,针对云产品的多租需求提供了一套完整的解决方案。阿里云的云产品除了需要对产品自身的指标进行监控外,同时需要对产品售卖的租户指标进行监控。云产品针对租户资源划分,主要分为租户独占资源模式和租户共享资源模式。租户独占资源模式具有租户单独占用部署资源,隔离性好的特点,识别指标的租户信息只需要打上租户指标即可;租户共享资源模式指租户之间会共享部署资源,识别指标的租户信息需要云产品自行添加租户信息。ARMS Prometheus 监控相对于开源的 Prometheus 采用了采集和存储分离的架构,采集端具有多租识别和分发能力,存储端内置了多租能力,租户之间的资源完全隔离。ARMS Prometheus 会为每个阿里云用户创建一个 Prometheus 云服务的实例,来存储用户对应的阿里云的云产品指标,真正地解决了以往监控系统数据分散形成的数据孤岛问题,同时为每个云产品提供了深度定制、开箱即用的大盘和告警能力。上图为 RocketMQ 默认集成的 Grafana 大盘示例。大盘提供 Overview 概览、Topic 消息发送、Group ID 消息消费等细粒度的监控数据支撑。相较于开源实现,该大盘提供了更多更准确的指标数据,同时结合了 RocketMQ 团队在消息领域的多年运维经验打磨的最佳实践模板,并提供了持续迭代更新的能力。RocketMQ可观测最佳实践单纯地关注消息系统提供的可观测数据只能发现一部分的问题,在一个真实的微服务系统中,用户需要关注整个技术栈全局中的接入层、业务应用、中间件、容器、底层 IaaS的可观测数据才能准确地定位问题。上图是一个非常典型的消息系统上下游的应用结构。上游订单系统发送消息,下游库存系统、营销系统订阅消息,实现上下游的解耦。如何在这样一个复杂的业务系统中发现问题、解决问题,需要对整个系统的可观测性做全面梳理。首先需要对系统中的各个组成部分可观测数据进行收集,Metric、Trace、Log 的三大支柱必不可少。Metric 衡量了应用状态,通过指标告警可以快速地发现问题;Trace 数据可以做到请求级别的全周期的跟踪路径,通过排查调用链路可以快速地定位问题;Log 数据详细记录了系统产生的事件,通过日志分析可以快速地排查故障。上图为 ARMS Kubernetes 监控沉淀的诊断经验。通过在应用的技术栈端到端、自顶向下的全栈关联方式,为我们在横向、纵向将可观测问题诊断定位提供了实践思路参考。对于跟业务相关的组件而言,需要更多地关注影响用户体验的 RED 指标,在资源层应该更多地关注资源饱和度相关的指标。同时需要横向地关注日志、事件、调用链关联,只有多方位、全视角的可观测才可以更加清晰地排查定位问题。上图为一个消息堆积场景的例子。首先需要理解消息堆积的指标含义。一条消息在 Producer 发送后,在消息队列中的处理以及 Consumer 消费的三个阶段分别处于 Ready、inFlight、Acked 状态。需要重点关注两个指标,已就绪消息量(Ready message)表示已就绪的消息条数,该消息量的大小反映了还未被消费的消息规模,在消费者异常的情况下,就绪消息的数据量会变多;消息排队时间(Queue time)表示最早一条就绪消息的就绪时间和当前的时间差,该时间大小反映了还未被处理消息的时间延迟情况,对于时间敏感的业务而言是一个非常重要的度量指标。消息堆积的原因主要有两点,消费端故障或消费能力不足导致,或者上游生产端消息量过大,下游消费能力不足导致。对于生产端更应该关注消息的发送健康度,可以针对发送成功率进行告警。出现告警时,需要关注 load、发送耗时、消息量等指标,判断是否有消息量的突然变化;对于消费端应该关注消费是否及时的消费健康度,可针对就绪消息的排队时间进行告警。当出现告警时,需要关联地关注消息的处理耗时、消费的成功率、消息量、load 等相关指标,判断消息的消息量、消费处理的耗时的变化,并查询是否有 ERROR 日志、trace 等相关信息。用户可以使用阿里云 ARMS 产品,能够更方便快捷地处理以上排查过程。收到告警信息之后,通过查询业务拓扑、异常标注以及业务指标的变化,一键地查看关联的调用链信息,在调用链上可以获得业务处理各个阶段的处理时长、是否存在异常等相关信息。调用链的每个 span 节点可以下钻实时查询调用堆栈和耗时分占比,将问题定位到业务代码级别。如果用户接入的日志中按照 ARMS 规范关联到调用链的 traceID ,还可一键关联查看对应的日志详情,最终定位问题的根因。当问题出现时,除了方便快捷的问题定位过程,还需要针对告警提供相对完善的告警处理和应急响应机制。ARMS 告警为用户提供了告警配置、告警排班、告警处理的全流程功能,方便客户建立应急处理、事后复盘和机制优化。同时 ARMS 的智能告警平台支持10+监控数据源的集成以及多渠道数据推送。基于钉钉的 CHARTOPS 让告警可协作、可追溯、可统计,并且能够提供异常检查、智能降噪等算法能力,有效减少无效告警,并且可以在告警中基于应用的上下文得到告警的根因分析。阿里云 ARMS 监控从上到下云涵盖了用户的终端、应用、云服务/三方组件、容器、基础设施的全方位、立体化、统一监控和统一告警能力,是企业构建一站式可观测的最佳实践平台。
作者:木吴关注阿里云云原生公众号,后台回复关键词【FC】查看论文原文!近日,阿里云函数计算产品团队撰写的关于 Serverless 调度的创新性论文被 ACM SoCC 国际会议长文录用。去年阿里云函数计算团队首个提出在 FaaS 场景下的去中心化快速镜像分发技术,团队所作论文被计算机系统领域的顶级会议 USENIX ATC’21 录用,入选中国计算机协会(CCF)推荐 A 类国际会议列表(👉详情点击阅读);今年阿里云函数计算不断突破:发布基于函数画像的调度算法论文并被国际云计算的首要会议 ACM SoCC 录用,真正做到能够保证提升函数资源利用率的同时,达到性能高稳定性。ACM Symposium on Cloud Computing(以下简称 SoCC)是由美国计算机协会主办、聚焦云计算技术的一项学术会议,是云计算的首要会议。它汇集了对云计算感兴趣的研究人员、开发人员、用户和实践者,是唯一由 SIGMOD(数据管理特别兴趣组)和 SIGOPS(操作系统特别兴趣组)联合主办的会议, 这个会议在近些年蓬勃发展,旨在聚集数据库和计算机系统两大领域的学者,共同推进云计算技术在工业界的研究与发展。此次被录用的论文为《Owl: Performance-Aware Scheduling for Resource-Efficient Function-as-a-Service Cloud》。论文灵感诞生于阿里云 Serverless 产品函数计算,函数计算是阿里云的函数即服务(Function-As-A-Service)产品。阿里云函数计算是事件驱动的全托管计算服务。通过函数计算,您无需管理服务器等基础设施,只需编写代码并上传。函数计算会为您准备好计算资源,以弹性、可靠的方式运行您的代码,并提供日志查询、性能监控、报警等功能。现阶段已经覆盖了事件驱动、音视频处理、游戏、物联网、新零售、AI 等实际业务场景,并服务于阿里云、高德、支付宝、淘宝、CBU 等多个业务或项目中。上图是一个经典的 FaaS 调度系统的架构,调度器负载将不同的函数实例调度到集群中的节点上运行。由于 FaaS 产品函数数量多、函数粒度小、执行时间短的特点,节点的资源利用率较低。简单地将更多的实例调度到同一个节点上虽然能够一定程度地提升资源利用率,但是也带来了资源争抢和性能下降。论文针对这个问题创新地提出了基于函数画像的调度算法,在提高资源利用率的同时达到了较好的性能稳定性:1. 对于高频调用的函数,调度器会识别不同函数实例在同一个节点共置时的性能表现,以此指导函数实例的调度;2. 对于低频调用的函数,调度器会统计其执行过程中的实际资源消耗,以此来指导函数实例的调度,同时调度器会监控函数的执行延时,当出现延时上升时通过隔离的手段进行缓解;3. 调度器还针对闲置的实例进行迁移,将它们从利用率低的节点迁移到利用率高的节点以释放闲置节点。为了评估算法的效果,论文根据生产环境典型的函数负载,抽象了 10 个函数,它们覆盖了不同的编程语言、资源消耗、执行时长、外部依赖。列表如下:实验结果表明,在 100 个节点规模下,OWL 调度算法能够节省 43.8% 的资源,同时函数执行延时没有明显的增加:调度延时也没有明显增加:目前 OWL 的函数画像能力也已经应用在函数计算线上环境,并取得了不错的效果。此次论文入选 ACM SoCC,是阿里云在 Serverless 调度领域的又一次创新。附论文信息All On Serverless《Owl: Performance-Aware Scheduling for Resource-Efficient Function-as-a-Service Cloud》作者:田黄石,李苏毅,王骜,王威,吴天龙,杨皓然论文概述:在云计算中,FaaS 是一种非常流行的产品形态,主流的云产商都提供了对应的平台。作为平台构建者我们观察到大部分的函数实例的 CPU 和内存利用率都不高,造成集群节点的利用率也不高。一个简单的做法是在节点上超额放置更多的函数实例,但是这可能会带来资源争抢和性能下降。另外,函数的外部依赖也可能导致函数的性能下降。在本文中,我们设计了 OWL 调度系统来解决这些问题,达到高资源利用率和性能稳定性。对于低频调用的函数,调度器会统计其执行过程中的实际资源消耗,以此来指导函数实例的调度,同时调度器会监控函数的执行延时,当出现延时上升时通过隔离的手段进行缓解;对于高频调用的函数,调度器会识别不同函数实例在同一个节点共置时的性能表现,以此指导函数实例的调度。同时调度器还针对闲置的实例进行迁移,将它们从利用率低的节点迁移到利用率高的节点以释放闲置节点。我们实现了 OWL 原型系统并根据生产环境的负载构造了一组测试集。实验结果表明,OWL 调度系统能够减少 43.8% 的资源消耗并有效缓解性能下降。点击此处,直达阿里云函数计算 FC!
作者:创头条在经济面临下行压力、疫情反复等不确定因素之下,推动数字化转型就成为了许多企业的“救命稻草”。然而,较高的数字化转型门槛、不成系统的数据服务,以及缺乏规范的行业标准等都成了企业数字化转型路上的“绊脚石”。2015 年,袋鼠云成立并毅然投身于具有巨大想象力的数字经济发展浪潮,经过7年努力实践,不断完善自己的数字化服务能力,在牢固地基的基础上不断向上搭建应用层,致力于让更多的企业能够一站式完成数字化转型。如今,袋鼠云已成功服务 5000 多家客户,涵盖金融、政务、教育、制造等 20+行业。11 月初,袋鼠云刚刚宣布完成过亿元 C+轮融资。袋鼠云秉承着“让数据产生价值”的使命,以科技创新驱动发展,不断迭代优化解决方案和生态结构,其中与阿里云的合作不得不说。从“打地基”到“建房子”,袋鼠云全链路布局今年 7 月,以“数智进化,现在即未来”为主题的袋鼠云 2022 产品发布会正式开幕。发布会上,袋鼠云发布了以数栈 DTinsight、易知微 EasyV、数雁 EasyDigit、数驹 DTengine 为核心的全新产品体系。该产品体系涵盖一站式大数据开发与治理平台、低代码数字孪生平台、数据智能分析与洞察平台、极速湖仓引擎,将在储存计算、开发治理和应用三个层面助力更多企业一站式完成数字化转型。这次全新产品体系升级帮助袋鼠云实现了从“数字化基础设施供应商”升级为“全链路数字化技术与服务提供商”,也标志着它从“基础层”到“应用层”的拓展。对此,袋鼠云董事长陈吉平表示:“Google 的安卓生态体系成熟之前,得做好安卓操作系统,同样,微软生态体系,包括 Office 崛起之前,是先做了 Windows 操作系统。用户选择某个平台,更看中的是上面所附带的应用。我们现在做事情的逻辑跟它们是一样。”过去,袋鼠云专注于“打地基”,做好基础技术底座与数据治理服务,在技术层和数据价值挖掘上发挥出最大的优势;如今,随着服务的深入以及客户现实需求的出现,袋鼠云在此之上不断地“建房子”,创造了更多应用层。例如在银行业,规范化指标加工与管理,自动进行指标任务的调度、指标数据生成,实现监管报送、征信报送、风险控制等场景,让信贷经营更加高效。在证券行业,通过分析行情数据、股票交易数据、两融数据、资金等数据,进行标签萃取,形成360°的证券用户标签体系,对用户进行标签的分级分类管理,实现智能选股、智能投研、风险控制等场景,助力证券业务营销与风控。在基金行业,通过分析清算系统、自营 APP、OTS 系统、客服系统等数据,搭建画像分析体系,实现“业务、技术、数据”的三位一体,精准地为用户匹配理财产品。袋鼠云未来在产品研发上将不断提升国产大数据软件的比例,通过提高技术的深度和自主掌控力。比如极速湖仓引擎“数驹 DTengine”中的大数据基础平台 EasyMR 基于最新的开源技术,提供 Spark、Flink、Trino、HDFS 等大数据组件和服务,可为企业提供大数据基础设施底座。比如,袋鼠云基于长期价值出发,于 2021 年 5 月投资成立了子公司易知微,深耕数字孪生产业生态,致力于“让每一个组织和个体都看见并受益于数字化”。自主研发、自主可控的低代码数字孪生可视化平台 EasyV,结合 WebGL、3D 游戏引擎等技术,致力于建设数字增强世界,帮助客户实现数字化管理,加速数字化转型。同时,基于 DataOps 理念,袋鼠云整合四大产品,打通不同产品之间的流程,提高产品间的协同和联动效应,打造集数据全生命周期的开发、治理、服务于一体的一站式大数据平台,大大缩短数据体系建设的周期,并降低后续的数据运营投入成本。11 月 9 日,易知微将举办在线发布会,包括自研数字孪生渲染引擎 EasyTwin、可视化 SaaS 平台 EasyV6.0,以及数据治理和数字孪生行业最佳实践等,将正式和大家见面。从“保姆式”到“管家式”to B,持续为客户创造价值陈吉平担任过阿里集团数据资产与数据安全团队负责人,还曾是淘宝第一代数据仓库建设者,见证了阿里巴巴集团数据中台“从 0 到 1”的整个过程。正是在阿里的过程中,陈吉平发现市场对大数据的强劲需求,即便是占据中国公共云市场 50%份额的阿里云也无法完全满足,阿里云急需生态合作伙伴。正在计划创业的陈吉平,随即自立门户于 2015 年 11 月成立了袋鼠云。创业维艰,陈吉平也不例外。在成立的这 7 年里,袋鼠云经历了几次不一样的困难。好在袋鼠云足够幸运,走得也足够稳,在很短时间里得到市场和投资者的认可。与众多企业一样,袋鼠云这几年也面临来自疫情的挑战。今年初,袋鼠云及时调整策略,更加注重回归商业本质,努力在现有基础上实现盈利。同时,超出同行的前瞻性也帮了袋鼠云大忙。它很早就避开了房地产、在线教育、零售等行业,而是选择了“足够牢固的洞穴”。由此,疫情之下的袋鼠云也只是“受了点皮外伤”。除了前瞻性,袋鼠云服务市场更强调主动性。陈吉平表示:“袋鼠云做的是‘管家式’to B,明显不同于传统的‘保姆式’to B。”换句话说,袋鼠云擅于主动地去发现用户需求,为用户创造价值。并且,管家式的 to B 更加注重长期的服务。通过抢占数字化的核心点,袋鼠云能够精准把握客户的内在需求,并为此持续性提出合理的解决办法,与客户之间建立一个长久的合作关系。那么何为“数字化的核心点”呢?陈吉平举例类比称:“数据挖掘好比‘挖石油’,数据治理好比‘石油冶炼’,虽然冶炼出来的石油产品也有价值,但是,最终谁能能发明柴油机或者发电机,将这些石油资源进行最大价值的扩展,转化成动能、电能之类的,那就意味着谁就掌握了数据的核心价值点。”管家式的 to B 服务还有助于全面深入地了解一个企业的现状,将各部门不同阶段数据打通,加快企业数字化转型。从“保姆”到“管家”,袋鼠云始终秉承着公司“让数据产生价值”的使命。最希望的是先“做大蛋糕”,而非急于“瓜分蛋糕”数字化转型是一个极其复杂的系统性工程,绝非能够靠一己之力就能够完成,它需要各方力量汇聚以及各种技术的共同承载。“一花独放不是春,百花齐放春满园。”袋鼠云作为数字化转型技术服务行业的先行者,深谙此理。陈吉平自然也是深知深化与生态伙伴的合作,先“做大蛋糕”的战略。当前,袋鼠云最希望做的也正是“做大蛋糕”,而非急于“瓜分蛋糕”。它希望更多同行加入进来。尤其是随着数字经济的前行,企业数字化转型逐渐深入,过去的一系列问题也逐渐暴露出来。首先最紧迫的问题之一就是行业缺乏统一标准,最终形成“数据孤岛”。“数据孤岛”问题若能不断解决,就能降低进入行业的门槛,带来更多的入局者,从而为用户提供更完善的数字化服务。袋鼠云早已观察到此类问题,并付诸努力去改变。比如,一些过去参考的系列标准的部分内容已不适用,缺乏对元数据描述、扩展、校验等内容的规范性指导。袋鼠云就联合浙江省标准化研究院等 10 余家单位制定的全国首个《数据中台 元数据规范》团体标准,让行业数据逻辑更统一,从而减少数据重复建设和数据非必要壁垒。再比如,由于不同企业的数字化转型涉及到的行业门类众多,场景也千差万别,如何精准地把握市场需求并为此提供专业化服务成了众多数据中台供应商的业务难题。对此,袋鼠云的解决办法总结起来还是两个字“合作”。袋鼠云通过与生态合作伙伴共创解决方案,满足不同客户的需求,从而给不同行业的客户创建数据的价值。如今,袋鼠云已经服务了包括厦门建发集团、厦门国贸集团、厦门象屿集团、中化集团、中交二航局、宁波舟山港股份、万向集团、蒙牛乳业等多家 500 强企业,以及中国银联、华夏银行、国泰君安、招商证券、中金公司、中国平安、杭州东站枢纽管委会、杭州西湖景区管理委员会、教育部、浙江大学、四川大学、东风本田、吉利汽车、未来电视和航天科技、航天科工、中国电子、航空工业等(排序不分先后)超 5000 家客户。成长在阿里云,携手云原生加速器,创建数字化服务生态闭环从云计算、数字化再到数智化,每一次迈步都标志着数字化转型迎来一个新的起点,整个数字化系统需要发生新的升级迭代。20 多年前,企业普遍使用 ERP、CMR 做信息化改革;10 多年前,消费互联网崛起时,互联网技术盛行;如今,在产业互联网背景下,云原生成了更多用户的选择。中国信息通信研究院的研究称,预计 2022 年云原生市场规模将超 500 亿元,并且未来发展前景十分可观。阿里云作为全球云计算领军者之一,云原生产品的集大成者,拥有最大规模的云原生应用实践。从互联网经济开始,阿里云已逐步延伸到金融、政企、旅游、教育、能源、零售等各行各业,生态合作伙伴也日渐扩大,能够帮助客户构建“全、统、通”的大数据体系。面对广阔的市场,为了打造丰富的云原生生态圈,阿里云在 2021 年正式启动了云原生加速器,经过激烈的线下路演,最终 31 家企业入选阿里云首期云原生加速器,其中超半数企业为 B 轮及以上融资,1/5 企业为 C 轮及以上,入选企业总估值超过 338 亿。袋鼠云凭借大数据开发与治理平台、数字孪生和可观测运维等技术能力,以及丰富的落地应用方案,成功入选阿里云首期云原生加速器成员名单。由于团队中强大的阿里系创业基因,袋鼠云从一开始就和阿里云有着天然的默契感,也有着较高的合作起点,自然也成为阿里云生态合作伙伴。随着转型的深入,企业的应用系统越来越多,越来越复杂,监控工具分散、故障处理时间长、运维效率低等问题也一一浮现,传统的IT系统与保障方式已不能再适应新需求的变化,能够提升数据价值、加强运维效率的数字化运维呼之欲出。正是基于市场的迫切需求,阿里云与袋鼠云携手,联合开发推出 ACOS 统一运维监控平台,产品支持多源及海量的IT及业务数据接入、完善的数据处理和分析,有效解决监控工具各自为政、数据处理和实时分析能力薄弱等难题,提升工作效率。当今的商业竞争格局之下,合作共赢已是大势所趋。“让数据产生价值”是袋鼠云的使命。为了更好地实现这个使命,袋鼠云已经从“数字化基础设施供应商”升级为“全链路数字化技术与服务提供商”。这也将成为它未来为客户创造更多价值,行稳致远的关键力量。
Grafana 9.0 是一个提升 Grafana 易用性的版本,通过全新的和改进的操作界面来获取数据,以及默认的 Grafana 警报体验。Grafana 的一个主要使命是让可观测性、数据可视化和分析更容易的惠及到每个人。对于像 Prometheus 和 Loki 这样的流行数据源,编写和理解查询可能很困难。在 Grafana 9.0 为这两个数据源提供了新的可视化查询生成器。这些可视化查询生成器将降低学习成本,帮助任何人编写、理解和学习底层查询语言。该版本还包括一个全新的强大和快速的热力图可视化,一个更容易访问的导航菜单,仪表板搜索的改进,高级安全和认证功能,等等。全新的和改进功能列表:新的 Prometheus 查询生成器新的 Grafana Loki 查询生成器新的导航条及搜索新的 Explore 功能新的 Panel 面板新的 Grafana Alerting 新的 Prometheus 查询生成器PromQL(Prometheus Query Language)是一种强大的查询语言,有着非常复杂和高级的查询语法。但对于 Prometheus 新手来说,即使是相对简单的查询语句,也是难以编写和阅读的。Prometheus 的新 UI 查询生成器正是为了解决这个问题而建立的。在 Grafana 9.0 中,你将在 Explore 中看到一个全新的可视化查询生成器界面,它允许任何人编写和学习 Prometheus 查询是如何工作的。指标(Metric)和标签过滤器(Labels)新的查询生成器允许你通过多词搜索来搜索和选择一个指标。你可以从选择一个指标或一个标签过滤器开始。对指标进行操作(Operations)Operations 字段用于通过各种函数(Functions)、区间函数(Range Function)、聚合(Aggregations)和二进制操作(Binary Operations)对感兴趣的指标进行数学操作。你可以通过 + Operation 按钮将这些操作分层。由于 Operations 是按照执行的顺序呈现的,而不是按照文本查询中的倒序排列,这使得阅读和编辑查询变得更加容易。支持多种方式来编写 PromQL您可以选择在文本编辑模式(Code)或可视化查询生成器模式(Builder)中编写 PromQL 查询。你可以在这些模式之间进行切换,同时保留你的 PromQL 修改。PromQL 执行计划(PromQL Explain)如果你是 PromQL 的新手,你可以使用第三种模式,即 Explain,通过了解已经写好的 PromQL 的执行计划。你可以在 Builder 模式和 Explain 模式之间切换,同时保留查询,以了解更多关于被查询的指标执行的操作。新的 Grafana Loki 查询生成器LogQL 是复杂而强大的查询语言。在很多方面,它比 PromQL 更复杂,需要记住的语法也更多。在 Grafana 9.0 中引入的新查询生成器将帮助您在不了解任何语法的情况下编写和理解 Loki 查询。看一下这个日志查询示例。在下图所示的 Loki 查询生成器中,你可以添加和编辑标签过滤器、解析器和函数等。Loki 查询生成器支持上面列出的 Prometheus 查询生成器的所有功能,包括 Explain 模式,以及在 Code 模式和 Builder 模式之间切换的功能。新的导航条及搜索功能Navigation Bar 可展开的导航条您可以展开导航栏以更好地了解 Grafana 的特性和已安装的集成。Starred Dashboards 收藏到导航条Grafana 9 可以让你把你的仪表盘加注星标,并从导航菜单中轻松访问它们。Command palette 快捷命令面板命令面板对于那些常用键盘快捷键的用户来说是一次很大的生产力提升。使用 cmd+K(macOS)或 ctrl+K(Linux/Windows),你可以调出一个命令面板,使导航和仪表盘搜索更加容易。根据你在 Grafana 用户界面中的位置,你可以快速运行一个查询、切换到分割视图、在仪表盘之间导航,或改变主题偏好。Dashboard 仪表板面板搜索Grafana 9.0 新的搜索不使用 SQL 查询,而是使用内存中的全文索引。这提供了更好的搜索体验,并允许在面板标题中搜索。新的 Explore 功能Explore 直接导入仪表板面板虽然 Grafana 一直支持从仪表盘移动到 Explore 而不丢失上下文的功能,但反过来却不行。Grafana 9.0 公布了一个新的 Explore 到仪表盘的工作流程,允许你直接从 Explore 模式中创建面板或仪表盘。当一个复杂的查询起作用时,你不再需要费力地复制它或重写它到一个新的仪表板。Explore 查询历史记录点击 Query History 按钮可以查询在 Explore 中运行的所有查询历史记录。新的 Panel 面板功能Heatmap 新的热力图面板新的 Heatmap 面板经历了架构上的变化,使其具有更高的性能,速度也提高了几个数量级。除了性能,Heatmap 面板上的分辨率也更高,你现在可以对色谱进行自定义和精细控制。Trace Panel 链路追踪图面板在 Grafana 9.0 中,你现在可以在仪表盘中添加 Trace 面板,通过 Trace 视图来可视化,而不是在 Explore 模式中查看它们。Panel Preview 仪表盘/面板预览该提供了所有可用仪表盘的效果预览,当您完成 PromQL 后, 推荐预览(Suggestions)可以帮助你快速找到你需要的仪表盘。新的 Grafana Alerting 告警在 Grafana 9.0.x 中默认提供了全新的告警UI(相对于 8.2.x 及更早版本)。警报状态历史记录Grafana 管理的警报的警报状态历史记录指示状态的原因 警报规则可以配置为在规则计算导致错误或无数据条件时使用“警报”或“确定”状态。此更改跟踪警报、警报(NoData)和警报(Error)之间的差异。此更改还将更新 UI 以处理新的序列化状态:过滤、排序和着色。支持多种创建方式Grafana Alerting 支持在仪表盘面板(Panel)创建告警,他会传递“dashboard UID”和“panel ID”注释将警报与之关联。Grafana Alerting 也支持直接创建告警不关联任何 Dashboard通知策略(Notification Policies)和告警压制(Silences)在通知策略(Notification Policies)中,可以通过 Maching Labels 将告警规则(Alert Rules)与告警通道(Contact Points)进行关联当您收到的告警消息过于频繁,可以使用 Sliences 对告警进行压制
作者:风敬本文篇幅超过 7 千字,通读全文大概需要 20 分钟。文章内容源自大量真实场景的沉淀和分析,建议收藏,以供查阅。在 K8s 中,Pod 作为工作负载的运行载体,是最为核心的一个资源对象。Pod 具有复杂的生命周期,在其生命周期的每一个阶段,可能发生多种不同的异常情况。K8s 作为一个复杂系统,异常诊断往往要求强大的知识和经验储备。结合实战经历以及 EDAS 用户真实场景的归纳,我们总结了 K8s Pod 的 13 种常见异常场景,给出各个场景的常见错误状态,分析其原因和排查思路。Pod 生命周期在整个生命周期中,Pod 会出现 5 种阶段(Phase)。Pending:Pod 被 K8s 创建出来后,起始于 Pending 阶段。在 Pending 阶段,Pod 将经过调度,被分配至目标节点开始拉取镜像、加载依赖项、创建容器。 Running:当 Pod 所有容器都已被创建,且至少一个容器已经在运行中,Pod 将进入 Running 阶段。 Succeeded:当 Pod 中的所有容器都执行完成后终止,并且不会再重启,Pod 将进入 Succeeded 阶段。 Failed:若 Pod 中的所有容器都已终止,并且至少有一个容器是因为失败终止,也就是说容器以非 0 状态异常退出或被系统终止,Pod 将进入 Failed 阶段。 Unkonwn:因为某些原因无法取得 Pod 状态,这种情况 Pod 将被置为 Unkonwn 状态。 一般来说,对于 Job 类型的负载,Pod 在成功执行完任务之后将会以 Succeeded 状态为终态。而对于 Deployment 等负载,一般期望 Pod 能够持续提供服务,直到 Pod 因删除消失,或者因异常退出/被系统终止而进入 Failed 阶段。Pod 的 5 个阶段是 Pod 在其生命周期中所处位置的简单宏观概述,并不是对容器或 Pod 状态的综合汇总。Pod 有一些细分状态( PodConditions ),例如 Ready/NotReady、Initialized、 PodScheduled/Unschedulable 等。这些细分状态描述造成 Pod 所处阶段的具体成因是什么。比如,Pod 当前阶段是 Pending,对应的细分状态是 Unschedulable,这就意味着 Pod 调度出现了问题。容器也有其生命周期状态(State):Waiting、Running 和 Terminated。并且也有其对应的状态原因(Reason),例如 ContainerCreating、Error、OOMKilled、CrashLoopBackOff、Completed 等。而对于发生过重启或终止的容器,上一个状态(LastState)字段不仅包含状态原因,还包含上一次退出的状态码(Exit Code)。例如容器上一次退出状态码是 137,状态原因是 OOMKilled,说明容器是因为 OOM 被系统强行终止。在异常诊断过程中,容器的退出状态是至关重要的信息。除了必要的集群和应用监控,一般还需要通过 kubectl 命令搜集异常状态信息。// 获取Pod当前对象描述文件 kubectl get po <podName> -n <namespace> -o yaml // 获取Pod信息和事件(Events) kubectl describe pod <podName> -n <namespace> // 获取Pod容器日志 kubectl logs <podName> <containerName> -n <namespace> // 在容器中执行命令 kubectl exec <podName> -n <namespace> -c <containerName> -- <CMD> <ARGS>Pod 异常场景Pod 在其生命周期的许多时间点可能发生不同的异常,按照 Pod 容器是否运行为标志点,我们将异常场景大致分为两类:在 Pod 进行调度并创建容器过程中发生异常,此时 Pod 将卡在 Pending 阶段。Pod 容器运行中发生异常,此时 Pod 按照具体场景处在不同阶段。 下文将对这具体的 13 种场景进行描述和分析。调度失败常见错误状态:UnschedulablePod 被创建后进入调度阶段,K8s 调度器依据 Pod 声明的资源请求量和调度规则,为 Pod 挑选一个适合运行的节点。当集群节点均不满足 Pod 调度需求时,Pod 将会处于 Pending 状态。造成调度失败的典型原因如下:节点资源不足K8s 将节点资源(CPU、内存、磁盘等)进行数值量化,定义出节点资源容量(Capacity)和节点资源可分配额(Allocatable)。资源容量是指 Kubelet 获取的计算节点当前的资源信息,而资源可分配额是 Pod 可用的资源。Pod 容器有两种资源额度概念:请求值 Request 和限制值 Limit,容器至少能获取请求值大小、至多能获取限制值的资源量。Pod 的资源请求量是 Pod 中所有容器的资源请求之和,Pod 的资源限制量是 Pod 中所有容器的资源限制之和。K8s 默认调度器按照较小的请求值作为调度依据,保障可调度节点的资源可分配额一定不小于 Pod 资源请求值。当集群没有一个节点满足 Pod 的资源请求量,则 Pod 将卡在 Pending 状态。Pod 因为无法满足资源需求而被 Pending,可能是因为集群资源不足,需要进行扩容,也有可能是集群碎片导致。以一个典型场景为例,用户集群有 10 几个 4c8g 的节点,整个集群资源使用率在 60%左右,每个节点都有碎片,但因为碎片太小导致扩不出来一个 2c4g 的 Pod。一般来说,小节点集群会更容易产生资源碎片,而碎片资源无法供 Pod 调度使用。如果想最大限度地减少资源浪费,使用更大的节点可能会带来更好的结果。超过 Namespace 资源配额K8s 用户可以通过资源配额(Resource Quota)对 Namespace 进行资源使用量限制,包括两个维度:1. 限定某个对象类型(如 Pod)可创建对象的总数。2. 限定某个对象类型可消耗的资源总数。如果在创建或更新 Pod 时申请的资源超过了资源配额,则 Pod 将调度失败。此时需要检查 Namespace 资源配额状态,做出适当调整。不满足 NodeSelector 节点选择器Pod 通过 NodeSelector 节点选择器指定调度到带有特定 Label 的节点,若不存在满足 NodeSelector 的可用节点,Pod 将无法被调度,需要对 NodeSelector 或节点 Label 进行合理调整。不满足亲和性节点亲和性(Affinity)和反亲和性(Anti-Affinity)用于约束 Pod 调度到哪些节点,而亲和性又细分为软亲和(Preferred)和硬亲和(Required)。对于软亲和规则,K8s 调度器会尝试寻找满足对应规则的节点,如果找不到匹配的节点,调度器仍然会调度该 Pod。而当硬亲和规则不被满足时,Pod 将无法被调度,需要检查 Pod 调度规则和目标节点状态,对调度规则或节点进行合理调整。节点存在污点K8s 提供污点(Taints)和容忍(Tolerations)机制,用于避免 Pod 被分配到不合适的节点上。假如节点上存在污点,而 Pod 没有设置相应的容忍,Pod 将不会调度到该 节点。此时需要确认节点是否有携带污点的必要,如果不必要的话可以移除污点;若 Pod 可以分配到带有污点的节点,则可以给 Pod 增加污点容忍。没有可用节点节点可能会因为资源不足、网络不通、Kubelet 未就绪等原因导致不可用(NotReady)。当集群中没有可调度的节点,也会导致 Pod 卡在 Pending 状态。此时需要查看节点状态,排查不可用节点问题并修复,或进行集群扩容。镜像拉取失败常见错误状态:ImagePullBackOffPod 经过调度后分配到目标节点,节点需要拉取 Pod 所需的镜像为创建容器做准备。拉取镜像阶段可能存在以下几种原因导致失败:镜像名字拼写错误或配置了错误的镜像出现镜像拉取失败后首先要确认镜像地址是否配置错误。私有仓库的免密配置错误集群需要进行免密配置才能拉取私有镜像。自建镜像仓库时需要在集群创建免密凭证 Secret,在 Pod 指定 ImagePullSecrets,或者将 Secret 嵌入 ServicAccount,让 Pod 使用对应的 ServiceAccount。而对于 acr 等镜像服务云产品一般会提供免密插件,需要在集群中正确安装免密插件才能拉取仓库内的镜像。免密插件的异常包括:集群免密插件未安装、免密插件 Pod 异常、免密插件配置错误,需要查看相关信息进行进一步排查。网络不通网络不通的常见场景有三个:1. 集群通过公网访问镜像仓库,而镜像仓库未配置公网的访问策略。对于自建仓库,可能是端口未开放,或是镜像服务未监听公网 IP;对于 acr 等镜像服务云产品,需要确认开启公网的访问入口,配置白名单等访问控制策略。2. 集群位于专有网络,需要为镜像服务配置专有网络的访问控制,才能建立集群节点与镜像服务之间的连接。3. 拉取海外镜像例如 gcr.io 仓库镜像,需配置镜像加速服务。镜像拉取超时常见于带宽不足或镜像体积太大,导致拉取超时。可以尝试在节点上手动拉取镜像,观察传输速率和传输时间,必要时可以对集群带宽进行升配,或者适当调整 Kubelet 的 --image-pull-progress-deadline 和 --runtime-request-timeout 选项。同时拉取多个镜像,触发并行度控制常见于用户弹性扩容出一个节点,大量待调度 Pod 被同时调度上去,导致一个节点同时有大量 Pod 启动,同时从镜像仓库拉取多个镜像。而受限于集群带宽、镜像仓库服务稳定性、容器运行时镜像拉取并行度控制等因素,镜像拉取并不支持大量并行。这种情况可以手动打断一些镜像的拉取,按照优先级让镜像分批拉取。依赖项错误常见错误状态:Error在 Pod 启动之前,Kubelet 将尝试检查与其他 K8s 元素的所有依赖关系。主要存在的依赖项有三种:PersistentVolume、ConfigMap 和 Secret。当这些依赖项不存在或者无法读取时,Pod 容器将无法正常创建,Pod 会处于 Pending 状态直到满足依赖性。当这些依赖项能被正确读取,但出现配置错误时,也会出现无法创建容器的情况。比如将一个只读的持久化存储卷 PersistentVolume 以可读写的形式挂载到容器,或者将存储卷挂载到/proc 等非法路径,也会导致容器创建失败。容器创建失败常见错误状态:ErrorPod 容器创建过程中出现了错误。常见原因包括:违反集群的安全策略,比如违反了 PodSecurityPolicy 等。容器无权操作集群内的资源,比如开启 RBAC 后,需要为 ServiceAccount 配置角色绑定。缺少启动命令,Pod 描述文件和镜像 Dockerfile 中均未指定启动命令。启动命令配置错误。Pod 配置文件可以通过 command 字段定义命令行,通过 args 字段给命令行定义参数。启动命令配置错误的情况非常多见,要格外注意命令及参数的格式。正确的填写方式可参考:初始化失败常见错误状态:CrashLoopBackOffK8s 提供 Init Container 特性,用于在启动应用容器之前启动一个或多个初始化容器,完成应用程序所需的预置条件。Init container 与应用容器本质上是一样的,但它们是仅运行一次就结束的任务,并且必须在执行完成后,系统才能继续执行下一个容器。如果 Pod 的 Init Container 执行失败,将会 block 业务容器的启动。通过查看 Pod 状态和事件定位到 Init Container 故障后,需要查看 Init Container 日志进一步排查故障点。回调失败常见错误状态:FailedPostStartHook 或 FailedPreStopHook 事件K8s 提供 PostStart 和 PreStop 两种容器生命周期回调,分别在容器中的进程启动前或者容器中的进程终止之前运行。PostStart 在容器创建之后立即执行,但由于是异步执行,无法保证和容器启动命令的执行顺序相关联。如果 PostStart 或者 PreStop 回调程序执行失败,常用于在容器结束前优雅地释放资源。如果 PostStart 或者 PreStop 回调程序执行失败失败,容器将被终止,按照重启策略决定是否重启。当出现回调失败,会出现 FailedPostStartHook 或 FailedPreStopHook 事件,进一步结合容器打出的日志进行故障排查。就绪探针失败常见错误状态:容器已经全部启动,但是 Pod 处于 NotReady 状态,服务流量无法从 Service 达到 PodK8s 使用 Readiness Probe(就绪探针)来确定容器是否已经就绪可以接受流量。只有当 Pod 中的容器都处于就绪状态时,K8s 才认定该 Pod 处于就绪状态,才会将服务流量转发到该容器。一般就绪探针失败分为几种情况:容器内应用原因:健康检查所配置规则对应的端口或者脚本,无法成功探测,如容器内应用没正常启动等。 探针配置不当:写错检查端口导致探测失败;检测间隔和失败阈值设置不合理,例如每次检查间隔 1s,一次不通过即失败;启动延迟设置太短,例如应用正常启动需要 15s,而设置容器启动 10s 后启用探针。 系统层问题:节点负载高,导致容器进程 hang 住。 CPU 资源不足:CPU 资源限制值过低,导致容器进程响应慢。 需要特别说明的是,对于微服务应用,服务的注册和发现由注册中心管理,流量不会经过 Service,直接从上游 Pod 流到下游 Pod。然而注册中心并没有如 K8s 就绪探针的检查机制,对于启动较慢的 JAVA 应用来说,服务注册成功后所需资源仍然可能在初始化中,导致出现上线后流量有损的情况。对于这一类场景,EDAS 提供延迟注册和服务预热等解决方案,解决 K8s 微服务应用上线有损的问题。存活探针失败常见错误状态:CrashLoopBackOffK8s 使用 Liveness Probe(存活探针)来确定容器是否正在运行。如果存活态探测失败,则容器会被杀死,随之按照重启策略决定是否重启。存活探针失败的原因与就绪探针类似,然而存活探针失败后容器会被 kill 消失,所以排障过程要棘手得多。一个典型的用户场景是,用户在压测期间通过 HPA 弹性扩容出多个新 Pod,然而新 Pod 一启动就被大流量阻塞,无法响应存活探针,导致 Pod 被 kill。kill 后又重启,重启完又挂掉,一直在 Running 和 CrashLoopBackOff 状态中振荡。微服务场景下可以使用延迟注册和服务预热等手段,避免瞬时流量打挂容器。如果是程序本身问题导致运行阻塞,建议先将 Liveness 探针移除,通过 Pod 启动后的监控和进程堆栈信息,找出流量涌入后进程阻塞的根因。容器退出常见错误状态:CrashLoopBackOff容器退出分为两种场景:启动后立即退出,可能原因是: 1. 启动命令的路径未包含在环境变量PATH中。2. 启动命令引用了不存在的文件或目录。3. 启动命令执行失败,可能因为运行环境缺少依赖,也可能是程序本身原因。4. 启动命令没有执行权限。5. 容器中没有前台进程。容器应该至少包含一个 long-running 的前台进程,不能后台运行,比如通过nohup这种方式去启动进程,或是用 tomcat 的 startup.sh 脚本。对于容器启动后立即退出的情况,通常因为容器直接消失,无法获取其输出流日志,很难直接通过现场定位问题。一个简易的排查方式是,通过设置特殊的启动命令卡住容器(比如使用 tail -f /dev/null),然后进到容器中手动执行命令看看结果,确认问题原因。运行一段时间后退出,这种情况一般是容器内 1 进程 Crash 或者被系统终止导致退出。此时首先查看容器退出状态码,然后进一步查看上下文信息进行错误定位。这种情况发生时容器已经删除消失,无法进入容器中查看日志和堆栈等现场信息,所以一般推荐用户对日志、错误记录等文件配置持久化存储,留存更多现场信息。几种常见的状态码如下: OOMKilled常见错误状态:OOMKilledK8s 中有两种资源概念:可压缩资源(CPU)和不可压缩资源(内存,磁盘 )。当 CPU 这种可压缩资源不足时,Pod 只会“饥饿”,但不会退出;而当内存和磁盘 IO 这种不可压缩资源不足时,Pod 会被 kill 或者驱逐。因为内存资源不足/超限所导致的 Pod 异常退出的现象被称为 Pod OOMKilled。K8s 存在两种导致 Pod OOMKilled 的场景:Container Limit Reached,容器内存用量超限Pod 内的每一个容器都可以配置其内存资源限额,当容器实际占用的内存超额,该容器将被 OOMKilled 并以状态码 137 退出。OOMKilled 往往发生在 Pod 已经正常运行一段时间后,可能是由于流量增加或是长期运行累积的内存逐渐增加。这种情况需要查看程序日志以了解为什么 Pod 使用的内存超出了预期,是否出现异常行为。如果发现程序只是按照预期运行就发生了 OOM,就需要适当提高 Pod 内存限制值。一个很常见的错误场景是,JAVA 容器设置了内存资源限制值 Limit,然而 JVM 堆大小限制值比内存 Limit 更大,导致进程在运行期间堆空间越开越大,最终因为 OOM 被终止。对于 JAVA 容器来说,一般建议容器内存限制值 Limit 需要比 JVM 最大堆内存稍大一些。Limit Overcommit,节点内存耗尽K8s 有两种资源额度概念:请求值 Request 和限制值 Limit,默认调度器按照较小的请求值作为调度依据,保障节点的所有 Pod 资源请求值总和不超过节点容量,而限制值总和允许超过节点容量,这就是 K8s 资源设计中的 Overcommit(超卖)现象。超卖设计在一定程度上能提高吞吐量和资源利用率,但会出现节点资源被耗尽的情况。当节点上的 Pod 实际使用的内存总和超过某个阈值,K8s 将会终止其中的一个或多个 Pod。为了尽量避免这种情况,建议在创建 Pod 时选择大小相等或相近的内存请求值和限制值,也可以利用调度规则将内存敏感型 Pod 打散到不同节点。Pod 驱逐常见错误状态:Pod Evicted当节点内存、磁盘这种不可压缩资源不足时,K8s 会按照 QoS 等级对节点上的某些 Pod 进行驱逐,释放资源保证节点可用性。当 Pod 发生驱逐后,上层控制器例如 Deployment 会新建 Pod 以维持副本数,新 Pod 会经过调度分配到其他节点创建运行。对于内存资源,前文已经分析过可以通过设置合理的请求值和限制值,避免节点内存耗尽。而对于磁盘资源,Pod 在运行期间会产生临时文件、日志,所以必须对 Pod 磁盘容量进行限制,否则某些 Pod 可能很快将磁盘写满。类似限制内存、CPU 用量的方式,在创建 Pod 时可以对本地临时存储用量(ephemeral-storage)进行限制。同时,Kubelet 驱逐条件默认磁盘可用空间在 10%以下,可以调整云监控磁盘告警阈值以提前告警。Pod 失联常见错误状态:UnkonwnPod 处于 Unkonwn 状态,无法获取其详细信息,一般是因为所在节点 Kubelet 异常,无法向 APIServer 上报 Pod 信息。首先检查节点状态,通过 Kubelet 和容器运行时的日志信息定位错误,进行修复。如果无法及时修复节点,可以先将该节点从集群中删除。无法被删除常见错误状态:卡在 Terminating当一个 Pod 被执行删除操作后,却长时间处于 Terminating 状态,这种情况的原因有几种:Pod 关联的 finalizer 未完成。首先查看 Pod 的 metadata 字段是否包含 finalizer,通过一些特定上下文信息确认 finalizer 任务具体是什么,通常 finalizer 的任务未完成可能是因为与 Volume 相关。如果 finalizer 已经无法被完成,可以通过 patch 操作移除对应的 Pod 上的 finalizer 完成删除操作。 Pod 对中断信号没有响应。Pod 没有被终止可能是进程对信号没有响应,可以尝试强制删除 Pod。 节点故障。通过查看相同节点上的其他 Pod 状态确认是否节点故障,尝试重启 Kubelet 和容器运行时。如果无法修复,先将该节点从集群中删除。 EDAS排障工具链EDAS 对应用全生命周期的大部分异常都有沉淀和分析,降低用户学习成本,缩短排障时间。EDAS 提供一系列解决方案和工具帮助用户解决应用生命周期中的异常问题,包括应用变更前的变更预检、应用变更和运行的事件追踪可观测、应用异常时的诊断工具。应用变更预检EDAS 在应用变更任务下发前将经过预检环节,应用变更预检可以在应用部署前检查集群状态及变更参数是否有效,能够有效避免应用变更过程出错,降低变更风险。当前应用变更预检提供集群可用资源检查、集群健康检查、各项依赖配置检查等项目,对于非预期的预检结果给出分析和处置建议。例如对于集群资源余量不满足 Pod 调度需求的异常场景,变更预检结果将显示资源检查不通过,用户能够第一时间做出针对性调整。应用事件观测EDAS 对应用生命周期中的事件进行追踪提供可观测能力。对于应用变更过程提供完整的事项展示,让用户能够白屏观测到变更中的每一个步骤和相关上下文信息。当出现异常变更情况时,将具体的事件和相关资源信息在白屏透出,并对异常事件进行分析解读并给出操作建议。例如给 Pod 配置了容器服务仓库镜像,但并未正确配置集群免密插件,EDAS 将镜像拉取失败事件抛出,并引导用户检查镜像拉取权限。诊断工具箱对于异常 Pod,通常需要连接到 Pod 容器,对业务进程进行诊断,必要时候还需要对异常进行复现。EDAS 提供云原生工具箱,让用户在网页上连接 Pod 容器 Shell,并且提供 Arthas、Tcpdump 等工具,弥补镜像软件工具包的缺失。对于 Pod 已经消失、不适合在业务 Pod 进行诊断等场景,云原生工具箱提供 Pod 复制能力,根据诊断场景不同,用户可以按需选择开启诊断 Pod。对于上文中提到的容器进程被大流量阻塞,导致 Pod 被 Liveness 打挂的场景,用户可以通过云原生工具箱,开启一个移除 Liveness 的诊断 Pod,设置全链路流量控制规则,打入一些测试流量,使用 Arthas 提供的 trace、stack、watch 等工具精准定位问题参考文档https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/Managing Compute Resources for ContainersConfigure Quality of Service for Pods - Kuberneteshttps://docs.docker.com/engine/reference/commandline/pull/#concurrent-downloadshttps://developer.aliyun.com/article/1066441https://alibaba.github.io/arthas
11 月 5 日,在 2022 杭州 · 云栖大会上,数字化安全生产平台 DPS 重磅发布,助力传统运维向 SRE 转型。阿里巴巴资深技术专家 周洋十四五规划下,各行各业全面加速数字化转型与升级。随着企业数字化业务规模变大,迭代速度加快,系统复杂度越来越高,如何保障业务稳定性这一话题也变得愈发重要。下述有几点典型场景和挑战:场景一:分布式系统面临稳定性保障新挑战近年来,虽然稳定性关注度日益提高,新技术蓬勃发展,重大故障依然频发且影响巨大。例如,2021年,某证券 IDC 故障 2 小时,导致客户无法交易,产生资损;某视频网站,服务器故障 3 小时无法访问,引发舆论……技术的不恰当使用、人为操作失误、硬件故障、自然灾害、安全攻击依然给生产带来极大风险。场景二:政策引导IT系统稳定性建设平稳推进随着数字化转型政策的推进,越来越多国民级应用诞生,大大方便了人们的日常生活,各个企业也相继推出自己的客户端。然而,大多数企业没有经历过多年互联网发展的锤炼,应对线上风险能力不足,亟需以最短时间完成稳定性运维能力的积累,少走弯路。场景三:传统运维手段已无法满足要求传统运维存在运维工具割裂、面向基础设施而非业务、被动运维、缺乏规范化的流程机制体系等问题。企业应遵循 SRE(Site Reliability Engineering)和平台运维(Platform Ops)的创新理念,通过软件来实现系统管理、问题发现、问题解决和自动化运维工作。在现实生活中,无论建造摩天大楼还是家庭工程维护,在保证工程质量的同时,更重要的是避免出现安全事故,造成人员伤害,因此需要一套标准化的工艺流程、技术标准和验收手段等。在软件行业中,同样需要标准化的技术能力和方法论,来保障线上业务稳定性。于是,从 2018 年起,阿里巴巴集团便致力于 IT 软件领域的安全生产建设:一方面加强高可用架构的基础建设,另一方面,提供 SRE 转型的流程机制体系,配合可用性能力、组织能力和灾难恢复能力等目标,形成一套完整的安全生产方法体系。为此,数字化安全生产平台(DPS)应势而生。DPS 浓缩了阿里巴巴十年运维经验,以 PlatformOps 为理念,以保障业务连续性为目标的一站式管控 SRE 运维平台,具备场景化、数字化和云原生化三大典型特征。场景化:DPS 以应急场景为中心,弱化组织架构带来的运维限制,同时,DPS 全面的监控和告警规则配置可以支持涵盖业务的各个场景。 数字化:DPS 提供数字化监控大屏、智能化告警、智能故障定位、白屏化故障快恢手段和数字化度量、人员管理等能力,为企业数字化进程添砖加瓦。 云原生化:DPS 以阿里云丰富的云原生产品作为技术支撑,且具备足够的开放性,可以与阿里云一方、二方和开源系统等进行关联。 数字化安全生产平台 (DPS) 作为阿里巴巴集团数十年互联网探索的沉淀,在平台的架构和演进方面主要关注以下几点:明确目标和场景:安全生产是全局工程,其能力取决于木桶最短板。因此安全生产需要有明确的目标和场景,且保证主体框架的完整。 打通组织架构:安全生产不仅要解决人和系统、代码的问题,还需要解决人和人、人和制度的问题。因此安全生产需要阿里和行业的优秀技术在一个体系内集成和打通。 面向未来架构: 安全生产同时关注成本和减少损失。因此,安全生产需具有一定的抗技术周期性,架构设计除了要兼容最新的技术栈,也要面向未来架构进行设计。数字化安全生产 DPS 支持两大典型业务场景:“1-5-10”故障快恢和“变更三板斧”故障预防。“1-5-10”故障快恢数字化安全生产平台提供对应急事件和故障的发现、响应和恢复的全生命周期管理。“1-5-10” 对应故障的“1 分钟发现 - 5 分钟响应- 10 分钟恢复”,是定义故障处理的时效性目标。1 分钟发现:通过建立围绕业务应用的全链路监控能力,能够实时监控业务健康度,如发现稳定性问题将秒级通报至应急保障服务组进行排查,降低故障发生的可能性。 5 分钟响应:通过建立应急响应渠道和全链路故障定位能力,能够快速拉通故障排查人员,基于AIOps智能故障定位和基于ChatOps进行故障状态更新和通知流转,提升故障处理效率。 10 分钟恢复:通过建立完善的故障快恢体系,基于方案内置丰富的快恢能力,能够根据不同的故障类型智能化推荐合适的快恢预案,缩短故障恢复时长。“变更三板斧”故障预防数字化安全生产平台 DPS 将极易引发线上故障的变更操作纳入稳定性管控体系,做到对变更操作的“可观测、可灰度、可回滚”。在“变更可管”方面,我们覆盖完善的变更系统,极大程度减少对变更系统的改造成本;在“变更可控”方面,我们提供基于时间、人员等维度的变更管控规则,预防可能出现的风险;在“变更可用”方面,我们可自动发现变更引发的故障,提供变更回滚等智能化快恢能力。如果您对于数字化安全生产平台 DPS 有任何疑问,欢迎使用钉钉扫描二维码加入钉钉交流群,期待与您共创!
容器技术已经跨越鸿沟,广泛应用于金融、通讯、制造、交通等千行百业。Kubernetes支撑的工作负载也从早期单一的互联网应用发展到数据库、AI、大数据等等,并覆盖了公共云、专有云、边缘云等多样化、动态的云环境。11月5日,2022杭州 · 云栖大会上,阿里巴巴研究员、阿里云智能云原生应用平台容器技术负责人易立在云原生峰会上发表主题演讲,发布阿里云容器服务全面智能化升级,帮助企业精益用云,以增效促降本,实现IT架构在云上的高质量发展。容器服务助力企业数字化创新经过7年的发展,阿里云容器服务产品线已经成为企业的云原生操作系统。基于阿里云容器平台,阿里集团实现了100%业务云原生上云。2021 年,阿里云发布了 ACK Anywhere,进一步拓展产品的宽度,覆盖从公共云、边缘云、到本地数据中心的各个场景。让所有需要云能力的地方,都能基于统一的容器基础设施之上。得益于阿里集团和阿里云的大规模容器应用实践,阿里云容器产品能力得到了业界的广泛认可。2022年1季度,在权威咨询机构Forrester 发布的全球公共云容器平台分析师报告中,ACK稳居全球领导者象限,这也是中国科技公司首次进入该象限;2022年2季度,在 Omida 发布的全球容器管理解决方案报告中,由于在公共云、专有云、混合云等环境完善的产品体系,ACK成为全球领导者,产品能力与规模国内领先;2022年8月,在CSDN 2022中国开发者调查报告中,有52%的国内开发者选择阿里云容器云平台。过去几年,降本增效成为了众多企业IT管理者关注的重要问题。企业已经到了精益用云的时代,提升资源效率、研发效率,IT管理效率成为关键。四大全新升级,阿里云容器服务迈入智能化时代智能化是容器平台发展的必然趋势。今天,阿里云基于过去10年的大规模容器实战经验,通过数据化手段和智能化算法,推动容器服务ACK面向基础设施层、容器编排层、应用架构层和运营治理领域 4 大维度全面升级,迈入智能化新阶段。升级1:新算力在基础设施层,利用面向云原生优化的新算力,提升计算效率。2021 年,阿里云发布了新一代云原生CPU,倚天710,基于ARMv9架构,已经在电商、阿里云内部规模化应用,实现了卓越性价比。相比 X86 芯片,典型 Web 应用性价比高50%,视频编解码应用性价比高 80%。倚天芯片面向云原生优化,vCPU 采用独立物理核,没有超线程架构中的性能争抢。可以提供更加确定性的性能。ACK 通过对芯片微架构的拓扑感知调度优化,相比开源K8s实现,帮助 Web 应用吞吐提升 20%。为了更好支持 AI、HPC等I/O密集型应用。ACK 正式提供了对eRDMA高性能容器网络支持。通过软硬一体优化的网络实现,可以提供更高的带宽与更低的延迟。应用在AI训练加速20%,微服务吞吐提升10%;ACK 支持多容器高效复用eRDMA设备,满足了容器应用部署密度的需求。为了更好支持有状态应用容器化,阿里云发布新一代容器网络文件系统 CNFS 2.0,它采用全链路加速技术,可以实现:容器应用对后端存储系统的访问并行化,提升网络带宽的利用率。对远程NAS存储的吞吐可以提升100%,满足高性能AI训练和基因计算的需求。利用元数据缓存和独有的lease机制,使得远程文件存储的元数据访问性能,提升了18倍,非常适合Web应用和CI/CD等需要对海量小文件进行访问的场景。支持文件的透明生命周期管理,可以自动将低频访问的冷数据放置在低成本的NAS低频介质或OSS中,降低存储成本50%以上。它支持对NAS/CPFS/OSS全链路可观测,帮助开发者更好诊断和优化I/O性能问题。企业与个人对数据隐私保护日益关切,机密计算技术应运而生。其中一个重要的技术是通过芯片的可信执行环境(TEE)实现数据保护。在TEE内执行的应用,不用担心来自其他应用、其他租户或者平台方的威胁。为了进一步推动机密计算的普及,阿里、蚂蚁团队在Kata Container社区与红帽、Intel等公司进行合作,将容器计算与可信执行环境相结合,推出机密容器 Confidential Container 项目,同时为 Intel® SGX、Intel® TDX等不同的TEE实现,提供了一致的容器界面。基于新一代的机密容器架构,开发者可以确保应用是通过可信软件供应链进行构建和分发的;容器应用运行在可信执行环境中,具备更小的攻击面,而且所有内存中数据是加密的并受完整性保护;应用对数据的访问是基于加密的可信数据存储服务。机密容器可以在需要隐私数据处理的场景中,如金融风控、医疗健康等,提供高效的隐私增强型算力。升级2:新平台在容器编排层,通过智能化、云边端一体的新平台,提升资源利用率和运维效率。K8s目前已经成为云时代的操作系统。希望充分利用多种应用负载之间的削峰填谷,提升K8s集群资源利用率。这也是大家常说的“混部”能力。阿里巴巴早在 2016 年就启动了云原生混部技术研发,历经多轮技术架构升级和双11锤炼,目前已实现全业务规模超千万核的云原生混部,日常CPU利用率在 50% 左右。阿里云今年开源了云原生混部项目 Koordinator,它包含三大核心能力:差异化 SLO 保障:在 Kubernetes 之上提供面向QoS 的资源调度机制,比如延迟敏感型的在线类任务,和可抢占的计算任务。通过对不同QoS应用的合理调度,可以在保障应用的稳定性的同时,提升资源利用率。QoS 感知调度:包括 CPU、GPU 拓扑感知、资源画像、热点打散等精细调度能力,帮助应用优化运行时性能效率,提升稳定性。任务调度:提供了大数据与 AI 相关的任务调度,比如批量调度、优先级抢占以及弹性 Quota等,可以更高效地支持计算任务Koordinator 项目完全兼容标准的 K8s,无需做任何侵入式修改。ACK也内建了Koordinator产品化支持:通过混部调度,在典型场景可以提升资源利用率100%;通过差异化SLO保障,在提升资源利用率的同时,让低优先级的任务对延迟敏感型任务的影响 < 5%。Kubernetes的复杂性是阻碍很多客户采用的一个重要因素。为此,ACK发布AIOps套件,通过智能化手段实现故障预防与快速定位。基于阿里团队10年大规模容器运维经验沉淀,通过专家系统和AI算法相结合的方式,提供了全栈巡检、升级检查,智能诊断等三大功能。智能诊断目前包含200+诊断项,覆盖90%的常见问题场景。以容器网络问题诊断为例,排查链路长,复杂度高,非常耗时耗力。在得物的业务场景中,利用智能诊断,可以快速定位由于网络栈异常导致的偶发性抖动问题;再如e签宝,利用智能诊断,可以在分钟级完成对Ingress、容器网络、应用和OS的全链路问题排查。ACK One 是面向多地域多集群的分布式容器平台,可以统一管理中心云、本地云、边缘云和客户IDC的K8s集群。今年阿里云在ACK One基础上,发布如下功能:提供托管的ArgoCD服务,开发者可以通过GitOps方式来实现应用的跨地域自动化交付;通过弹性感知的调度器实现,为混合云场景提供灵活的弹性算力;支持对多集群安全策略的统一管理,保障企业系统统一安全基线来看一个具体案例,在智联招聘的业务高峰期,借助ACK One弹性调度策略可以在数分钟内弹出数万核ECS和ECI等计算资源补充到IDC的在线服务集群,有效应对流量洪峰。ACK@Edge 是面向云边端一体协同的容器应用平台,基于阿里云开源的OpenYurt项目,今年对ACK@Edge 进行全新升级:在云边协同场景,阿里云推出了增强型网络边缘节点池,实现安全、稳定的云边网络互联方案。国内知名游戏企业,莉莉丝,利用增强型边缘网络节点池,让海外多地域服务器与云上 VPC 安全互通。相比专线网络资源成本降低 30%。在云端协同场景,阿里云推出了轻量化接入功能,可以通过K8s管理资源受限的设备上的容器应用。元戎启行是一个自动驾驶Startup公司,通过ACK@Edge管理车载设备应用,接入资源开销占用降低 50 %,发布运维效率提升 60% 以上。升级3:新架构在应用架构层,利用服务网格等新架构,提升应用的敏捷性、弹性与韧性。服务网格已经成为云原生应用的网络基础设施。阿里云服务网格服务ASM在4个维度进行了全新的升级:支持多种服务治理框架,可以实现Spring Cloud, Apache Dobbo等微服务应用与服务网格应用的互联互通和平滑迁移;为应用服务提供统一的身份定义, 简化零信任策略的构建与实施;提供开箱即用的Envoy插件市场, 可以拓宽服务网格的应用场景, 包括身份认证、AI Serving等场景;可以基于服务SLA指标,实现更加精准的弹性扩缩容震坤行工业超市是一家数字化的工业用品服务平台,为众多企业复工复产保驾护航。借助于ASM服务网格, 提升了平台的性能。基于ASM的软硬一体优化技术,提升TLS握手性能 75%,以及QPS 30+%。关于相关技术细节,可以参阅Intel和阿里云一起编写的技术白皮书(点击阅读原文即可下载)。专注餐饮行业数字化的合阔智云, 其业务中台的核心生产系统100%全部切换到服务网格ASM,提升应用发布效率70%,降低异常排错成本80%。升级4:新实践在运营治理领域,将通过一系列最佳实践的产品沉淀,提升企业IT在成本管理、安全治理等方面的管理效率。为了帮助企业上好云、用好云、管好云,阿里云本次发布了云原生landing zone,为企业云原生上云提供最佳实践。它包含架构规划、安全管理、财务管理、自动化运维等等8大模块。通过云原生landing zone最佳实践,已经帮助众多国内外企业客户构建了上云架构,满足企业对安全、稳定性和成本等多方面的业务诉求。围绕LandingZone 中财务管理部分,阿里云结合业财一体化实践和 FinOps 理念,推出 ACK FinOps 套件。通过数字化手段和智能化方法,帮助企业实现成本可视化、可优化、可控制。中华保险作为国内互联网金融行业的领导者,通过ACK FinOps套件,将企业 IT 成本治理周期从季度缩短到天级别,资源闲置率从 30% 降低到 10% 以内。识货团队通过应用混部和弹性等技术优化,将集群的资源利用率提升10%;整体降低计算成本20%以上。围绕 LandingZone 中安全防护部分,ACK 与 ACR 提供完备的DevSecOps的产品能力,为企业提供安全可信的软件供应链。今年,阿里云推出了集群容器安全概览,可以帮助安全管理员对集群安全水位有更好地感知,可以对集群配置、应用镜像、容器运行时的安全风险,及时发现与处置。全球领先的SaaS厂商Salesforce,在阿里云上提供先进的CRM服务应用。基于云原生 DevSecOps 能力,半年内实现 数 千次风险镜像拦截阻断, 1 万次工作负载部署策略阻断。基于全自动化软件供应链安全流程,应用安全交付效率提升 3倍。未来,希望更多的企业能和阿里云一起,利用云原生技术精益用云、增效降本,在云端进行业务创新。点击此处,免费下载《基于英特尔®架构的阿里云服务网格ASM技术加速应用服务加密通》白皮书。
作者:奥陌11 月 5 日,在 2022 杭州 · 云栖大会上,云原生技术中台 CNStack2.0 正式发布。阿里巴巴资深技术专家 谢吉宝介绍 CNStack2.0企业在数字化转型的过程中,一部分问题得到了解决,但随着 IT 水平的不断提升,新问题也在逐渐显现。业务系统越加复杂,所需的计算、存储和网络设施也变得越来越难以管理。以往一台虚拟机、一个数据库便能部署应用的时代已经一去不复返了。复杂的系统架构需要更多基础软件的支持才能良好运行,而开源社区的蓬勃发展,虽然为决策者提供了更多选择的可能性,但从选型开始问题就接踵而至。交付、运维、故障处理和选型后维护,所有这些都与业务价值无关,但又必不可少,基础软件出现问题对上层业务系统来说将是致命的,而这对于缺少丰富生产经验的运维人员来说,更是雪上加霜。随着云原生技术的深入发展和行业解决方案的不断落地,企业越来越希望看到这样一种平台,依托云原生技术能力,不但可以支撑大规模业务系统的发布与运行,也可以将内部各种复杂、零散、不统一和不标准的软硬件体系给集中管理起来,以中台化的运作方式,向企业内部源源不断的输出经过实践检验的成熟技术能力与标准体系,推动企业数字化建设向着更高效的方向发展。在这样一个趋势背景下,云原生技术中台 CNStack 隆重发布了其具有革新意义的新一代 2.0 版本。接下来我们将从几个企业数字化转型遇到的常见困难开始,向大家逐一介绍 CNStack 2.0 所具备的突破性能力,以及能给企业带来哪些核心价值。异构资源管理困难大部分企业已经从“建好云”的阶段过渡到了“用好云”,不管是共有云还是私有云,用云和上云的理念已经深入人心。但云平台的种类和数量都在不断增加,尤其是基础设施部分,这就如同 PC 时代的主机硬件,需要有更通用的操作系统加以屏蔽和提升,否则面对形形色色的 IaaS 基础设施,管理、运维和适配都将是重复且效率低下的工作。跨云、混合云和分布式云早已从理论步入生产,对异构资源的管理能力也需要更上一层楼。在某些局点的实践中,我们发现客户现场有存在多家云厂商的平台,且都分布在不同机房中,单开通资源这一项操作,就需要经历繁琐的申请过程,更不必说对整个环境体系的维护了。CNStack 2.0 面向基础设施提供了云原生化的管理手段,可以对不同厂商、不同架构(x86/ARM)、不同计算类型(CPU/GPU)和不同地域(公有云/本地云/边缘云)的资源进行管理。多集群纳管可以将分散的基础设施统一纳管到平台下,并能进行跨集群的资源分配、统一调度和集中运维,极大降低了异构基础设施的管理难度。不仅如此,CNStack 在项目实践中可以管控上千节点或上万核规模的集群资源,特别适用于零售和互联网行业等对于大规模、高并发和低成本管控的要求。而且在超融合及混部等能力的加持下,系统资源利用率可以由通常水平的 6%~12%,提升到 45%。系统软件选型与维护困难一个平台如果只能解决资源问题,其实还无法为业务提供可用的环境,因为在资源之上还存在各种系统软件,对这些系统软件进行技术选型并解决选型后的持续维护问题,也是平台必须要解决的。现如今,开源技术在软件领域有着举足轻重的地位,单 CNCF 下注册的项目就已经超过了 140 个,是否使用开源技术已经成为了评估软件标准化和开放性的必要条件之一。但问题是,这么多开源项目,该如何进行技术选型?哪些项目能满足需要?哪些版本能用于生产?哪些技术经历过大规模实战?这些都是技术选型需要考虑的问题。与此同时,对技术选型的持续维护也同样重要。版本迭代、技术革新,每次都需要投入新的人力、物力和财力才能跟得上开源社区的快速发展,否则就会面临版本生命周期终结、功能落后和性能低下等问题,更有甚者会遗留严重的安全风险,这些都是数字化决策者所不得不考虑的问题。CNStack 2.0 可以从两个方面来解决技术选型时遇到的问题。首先,平台提供了很多内置的、开箱即用的产品组件和中间件,正是这些内置组件所提供的能力才使我们所倡导的“让企业数字创新只需专注业务本身”变为可能。这些内置组件从资源管理到应用管理,从服务管理到流量管理,从可观测到可运维,从平台稳定性到数字化安全生产……渗透到了平台和业务系统的方方面面。如果想要通过开源产品搭建具备同等能力的技术中台,其投入将是无比巨大的。CNStack 背靠阿里云云原生团队,其所提供的中间件产品无论在功能、性能、规模还是可靠性方面都是有目共睹的,且经历过非常多的生产实践检验,能默默地为业务系统保驾护航。另外,在能力中心里,CNStack 还精选了各种原厂和伙伴提供的产品及组件,当内置功能不足以满足业务需要的时候可以在此进行无限扩展,并享受平台提供的一致化产品体验。多环境交付困难基于云原生技术的 PaaS 平台是近年来管理 IaaS 的首选方案。从开源到商业化,企业总能找到满足业务需要的解决方案,但也不是全然没有问题。比如,既往的工作模式和管理规范都是建立在非云原生的基础设施之上,简言之,就是以物理机或虚拟机为单元进行资源管理的。那个时候环境的申请几乎等同于准备主机节点,但这并不意味着一个环境处于可用状态,最终使用者还需要在上面部署很多系统软件和基础组件,这些软件系统的重复部署,不仅浪费人力和时间,后续维护也是一笔持续的开销,更不利于环境的复用、开支的节省和标准的建立,整体成本非常之高。当开发和测试等工作涉及多个系统和集成商的时候,环境获取成本将成倍增长,甚至失控。CNStack 2.0 的环境交付是基于容器来实现的。在系统建设之初,交付人员将基础设施资源整合成资源池(即容器集群),之后资源的申请便等同于在集群中划分配额。这些被分配的配额仅用于部署实际业务系统即可,系统软件的交付则是通过能力中心来完成。能力中心里分发的产品与组件是开箱即用的,平台管理员只需轻点鼠标即可实现全自动的安装与部署,交付即可用。能力中心分发的是组件能力,不再是资源本身,完全有可能在企业内部复用这些能力,并依此建立完善的基础软件使用标准。在实践中,资源分配和能力供给是有严格权限隔离的,完全适用于多地域、多组织和多项目的企业级管理模式。环境搭建周期从月变为天或小时,而且使用能力中心交付的组件会天然具备平台级的运维能力,不但能够提升环境搭建的效率,长期运维的成本也会一降再降。生产运维困难环境交付和应用部署都是一次性投入,而环境自身和其上业务系统的运维却是需要持续投入的。对大多数的运维人员来说,由于缺乏大规模访问下的生产运维经验,在突发状况时想做到系统的平稳运行是非常困难的,这往往不仅需要难得的实践经验,更需要专业工具或产品能力的支持。即便在正常情况下,想要确保系统稳定也是看似简单,实则困难的目标。倘若没有平台的支持,运维人员将无法预知问题的产生,产生问题时也无法做到及时止血或快速定位,最后迅速恢复和平稳升级才能让系统回归到往日的正常状态。所有这些远非“一个有经验的运维人员”所能轻易做到的。但依托 CNStack 2.0 的产品能力,保障线上系统的稳定运行只需要一个普通运维人员即可,这全都依靠了平台提供的一站式应用管理能力。复杂的业务系统催生了应用形态的多样化,微服务应用、多语言应用、批处理或定时任务应用、AI 应用和大数据应用等,所有这些在完成上线之后都需要针对性的运维和管理能力。CNStack 提供了完备的图形化运维控制台,不出平台即可完成 80% 的运维工作。同时,应用系统在发布态和运行态的稳定性也是由平台来自动保障的,运维人员仅需对规则进行配置,CNStack 的诸多特色能力,就可以让发布如丝般顺滑,让系统在突发状况时也能平稳度过并发出告警。最后,在应用故障逃脱平台的管控能力之后,系统提供的各种辅助工具和产品能力,也可以帮助运维团队精准定位故障,快速恢复系统,为研发部门介入修复赢得宝贵时间。总结诚然,在云原生运动的驱使下,将会有越来越多的企业尝试拥抱这项技术,以新的理念、新的架构和新的能力为业务注入新的活力,在这期间既往的平台解决了一些问题,又产生了一些问题,在不断的更新迭代中,加速释放创新的力量。CNStack 2.0 让企业以最低的成本和门槛享受来自技术革新的发展红利,而在遇到种种必然的困难阻碍时,也能提供强有力的支撑手段,终究能以更开放、更全面和更轻量的形态为客户打造更具竞争力的云原生技术中台产品,进而服务企业数字化转型步入下一个阶段。
11 月 5 日,2022 杭州·云栖大会上,阿里巴巴研究员、阿里云智能云原生应用平台总经理丁宇在云原生峰会上发表主题演讲,提出云原生激活应用构建新范式。在分享中发布阿里云在云原生领域多款新产品与全新升级,持续引领行业云原生技术趋势。云原生已经变成非常流行的技术趋势,从上云到用云,云原生能够从PaaS层面帮助企业解决应用构建的一系列问题。具体有三大范式正在成为现实:第一个范式是全面容器化。因为容器形成了运维的标准,成为企业上云用云的新界面,也变成开发者和应用系统交互的新界面,有利于构建高弹性、可伸缩的系统,从而实现降本增效。通过容器,企业可以享受到运维标准化、弹性架构带来的好处,也带来了软件可以无处不在的部署交付,标准化的管理运维。第二个范式是整个行业应用的核心技术互联网化。我们正在用互联网的技术、互联网的架构思想来重构应用系统,从而带来了很多好处:分布式可扩展,支撑业务敏捷迭代,构建弹性架构,从容应对流量高峰。第三个范式是应用的Serverless化。从技术角度来看,能够实现技术组件分层解耦,让应用可以做到全托管免运维,提升系统的可运维性,降低成本。通过极致弹性,能够把所有的组件覆盖,在云上构建应用变得非常简单。容器服务全面进入智能化时代虽然容器服务 ACK 大幅降低了 K8s 的门槛,但管理和运维一个大规模、分布式的集群依然充满挑战,比方说,如何调度应用,在保障稳定的同时,提升资源利用率;如何对应用进行成本规划、分析优化;当集群出现问题后,如何及时的定位和修复。智能化可以解决这些问题,智能化是容器平台发展的必然趋势,阿里云容器服务全面进入智能化时代。其中有三个升级:第一个升级,智能化的混部调度,新一代调度系统Koordinator,帮助用户提升整体资源利用率。第二个升级,智能化的成本治理,容器服务 FinOps套件,帮助用户实现上云成本可见、可控、可优化。第三个升级,智能化的运维体验,容器服务 AIOps套件,帮助用户实现数据驱动诊断决策,助力故障防御定位,自动化诊断可以覆盖 90% 以上的问题。这些能力升级,会进一步降低容器技术的使用门槛,让 ACK 做到普惠化,服务更广泛的客户群体。核心技术互联网化重磅发布一 | 微服务再升级:新增云原生网关开源云原生时代,微服务面临着新的诉求和技术挑战,尤其是在性能、高可用性和安全性方面。今天,阿里云正式开源云原生网关 Higress,它是业内首个标准化、高集成、易扩展、热更新的云原生网关。标准化:随着K8s的普及,K8s Ingress 逐渐成为云原生时代API事实标准,Higress全面支持该标准,并且在服务治理方面(包括灰度、限流、预热、超时、重试)做大幅增强,引领标准演进方向。高集成:Higress首次将流量网关、微服务网关、安全网关三合一,打造高集成网关,在入口建立高性能、安全防线,后端支持 K8s / Nacos / ECS / Serverless 多种运行时路由,打造功能最强大网关实现。易扩展:Higress 提供最丰富插件扩展机制,满足客户灵活路由和安全定制需求,支持最全面语言扩展机制;当然为了降低客户使用门槛,默认集成了数十个插件,并且通过插件市场方便开发者贡献通用能力,产生良性互动。热更新:由于传统Nginx更新规则需要 reload 会导致链接抖动,导致流量损失,对实时通信、视频、IoT无法容忍,因此 Higress 从证书、路由、安全规则、插件全部采用热更新机制,毫秒级生效且业务无感知。除了开源云原生网关之外,阿里云全面升级微服务引擎 MSE3.0,包含三大核心能力:第一大能力是注册配置中心,相比 Nacos 等主流开源方案,性能提升40%,提供70+的监控指标,提供健康检测,帮助客户实现服务异常自治。第二大能力是微服务治理,沉淀了阿里巴巴10+的实践经验,帮助客户缩短30%微服务治理落地周期,提升50%开发测试效率,消除80%线上风险。第三大能力是云原生网关,阿里云将流量网关、微服务网关、安全网关三合一,架构上也做了升级,将实例级防护升级至路由级防护,整体性能相比传统网关提升90%。重磅发布二 | 可观测再升级:让可观测数据价值最大化云原生时代,系统架构日趋复杂,提升可观测能力成为降低复杂度的唯一手段。今天可观测能力成为度量企业IT水平的标准,成本治理、业务连续性、业务增长都需要可观测技术。因此阿里云推出云原生可观测套件ACOS,从应用监控到链路追踪,帮助企业实现成本管理、风险治理、智能运维、保障数字化业务高效稳定的运行。本次云栖大会,阿里云云原生可观测套件 ACOS 三大组件也迎来重要升级。首先, Prometheus已成为不少企业的观测首选。作为容器观测事实标准的Prometheus监控,已成为阿里云50多款云产品的默认观测基础设施,并与应用实时监控服务ARMS的APM指标、eBPF指标、OpenTelemetry指标联通,将观测范围从专精容器延伸到全栈可观测。其次,作为观测界面的阿里云Grafana服务也将迎来9.0焕新升级。全新的Prometheus 和 Loki 查询语句生成器及强化后的搜索 Explore 功能,让用户获得更强的数据查询与分析能力。同时,为了应对越来越丰富的异构可观测数据源,Grafana服务与日志服务SLS、Elasticsearch等20+款可观测存储服务集成,帮助企业更简单地构建统一观测界面。一键导入/导出自建实例、自动数据导出报表,一键数据备份、恢复,用户操作审计等企业特性得到进一步增强。最后,为了帮助企业的云上应用开启多维度观测视角。应用实时监控服务ARMS在数据采集方面,OpenTelemetry 与Prometheus生态全面融合,通过 OpenTelemetry 补充业务、自定义组件埋点,在完善观测维度的同时,实现厂商无锁定。并借助 TraceExplorer 实现多来源 Trace 统一查询。重磅发布三 | RocketMQ5.0全面升级:从消息服务到云原生事件流平台消息队列一直是企业互联网架构的核心组件,阿里巴巴早在2012年就基于电商场景打造了国内流行的消息中间件RocketMQ,并贡献到Apache 社区。历经十余年的打磨,RocketMQ 取得了众多成果。Apache RocketMQ 的社区非常活跃,全球拥有700+的贡献者,超过 75% 头部企业选择使用 RocketMQ,同时超过80%的主流云厂商提供了 RocketMQ 的商业托管服务;阿里云作为 RocketMQ 的发起方和核心贡献者,十多年以来,累计服务了来自互联网、零售、汽车等20多个行业、10万企业客户;承载千万级TPS,万亿级消息洪峰。应用 Serverless 化:引领下一代应用架构随着企业用云的深入,云的能力也在不断升级,过去企业用云就是去买资源、买实例、买规格、搭应用。我们一直在说“云计算是像水电煤一样的基础设施,但是现在这一点还没有完全实现。阿里云一直在推动产品形态、研发方式的升级,希望从提供资源到提供服务,这个服务就是即插即用的能力,企业不需要管理和维护,可以实现自动伸缩免运维,平台全托管,按用量计费,真正实现了服务化、模块化,这也是云产品升级演进的方向。可以说,Serverless 奇点已来,所谓奇点,就是由平稳发展转向高速发展的转折点,预示着行业落地开始爆发。目前,阿里云已经有20多款的Serverless产品,并且会推进核心产品全面 Serverless化,Serverless 是云提供能力的最佳实现方式,也是让云计算基础设施落地到千行百业的最佳范式。除了产品形态的改变之外, Serverless同样带来了软件研发范式的改变。随着阿里云提供越来越全面的Serverless产品以后,很多云产品都变成模块化、API化、服务化,它可以进行组装,通过拖拉拽的方式就能够构建应用。所以说在 Serverless 架构下,研发方式升级到组装式研发,组装式研发可以做到流程编排、事件驱动,甚至可以做成可视化,这就彻底颠覆了原有的软件研发方式,大幅提升研发效率,灵活应对业务挑战。根据权威机构调研统计,组装式研发相比传统模式,可为研发提效50%以上。南瓜电影 7 天内全面 Serverless 化实践云原生 PaaS:CNStack2.0 重磅发布CNStack 是一款以应用为中心的云原生技术中台。它在异构的混合云基础设施上,提供统一的算力管理和优化调度,以开放、云原生的方式为不同场景下的应用提供全技术栈支持,指数级提升用户业务创新能力,加速研发效率,同时降低资源开销和运维成本,保障业务连续性,成为企业数字化转型的最佳路径。自 2021 年 CNStack1.0 发布以来,已经在多个行业的多个客户数字化转型过程中提供了帮助,并在 2022年云原生产业大会获得云原生技术创新案例大奖。今天,云原生Stack 2.0重磅发布,整个平台更加内聚,体验大幅提升,成为企业数字化转型,构建数字化应用的最佳载体。有三大能力升级:第一,统一算力支持。支持不同厂商、不同架构,CPU/GPU算力混合管理,支持管理容器虚拟机多种负载的混合调度。第二,一站式应用管理。应用的开发、测试、运维全生命周期一站式管理,容器服务、分布式应用、云边、DevOps全场景覆盖。第三,丰富易用的能力中心。丰富的云组件,为业务创新提供完整的技术栈支持。能力中心组件经过规模化验证,运维及稳定性有保障。云原生 Stack 让企业的数字化转型 不受技术约束,专注自身业务,加速实现业务目标。未来,阿里云在云原生领域将持续的引领标准,不断突破,推动领域和产业快速发展。
作者:阿里云云原生本文将详细介绍如何开发和部署 Serverless 应用,并通过阿里云函数计算控制台与开发者工具 Serverless Devs 进行应用的初始化、部署;最后分享应用的调试,通过科学发布、可观测性等介绍应用的部署和运维总结,进而实现从应用初始化到调试、发布、运维基础流程、核心步骤的探索。如何开发、部署 Serverless 应用通过控制台进行函数创建下面我们将基于 Serverless 架构,在 FaaS 平台上实现 Hello world 的输出,基本步骤可分为:1)注册账号,并登录;2)找到对应的 FaaS 产品:阿里云的函数计算;3)单击“创建函数”按钮,进行函数的创建;4)配置函数,包括函数名称、运行时(可以认为是要使用的编程语言,或者要使用的编程环境等);5)完成创建,并测试。以阿里云函数计算为例,当注册并登录阿里云账号之后,需要找到函数计算产品,并单击进入产品首页,如图所示。阿里云函数计算产品首页选择左侧的“服务及函数”,并进行服务的创建,如图所示。阿里云函数计算创建服务页面然后进行函数的创建,如图所示。阿里云函数计算创建函数页面相对于其他的云平台,在阿里云函数计算平台,我们不仅要为即将创建的函数设置函数名称、选择运行时等,还需要设置该函数所在的服务。在阿里云函数计算的体系中,引入服务的概念会带来一定的好处。相关联的函数可以放在一个服务下进行分类,这种分类实际上比标签分类更直观明了。 相关联的函数在同一个服务下共享一定的配置,例如 VPC 配置、NAS 配置,甚至某些日志仓库的配置等。 通过服务,我们可以很好地做函数环境的划分,例如对于一个相册项目,该项目可能存在线上环境、测试环境、开发环境,那么可以在服务层面做区分,即可以设定 album-release、album-test、album-dev 三个服务,进而做环境的隔离。 通过服务,我们可以很好地收纳函数。如果项目比较大,可能会产生很多函数,统一放在同一层级会显得非常混乱,这时就可以通过服务进行有效的收纳。 完成函数的创建之后,我们可以进行代码的编辑。阿里云函数计算支持从对象存储上传代码,支持直接上传代码包,以及在线编辑。除此之外,阿里云函数计算还支持直接上传文件夹,如图所示。保存代码之后,可以单击“执行”按钮进行函数的触发、测试。可以看到,系统已经输出相关日志:Hello world。至此,一个非常简单的函数就创建成功了。通过工具进行函数创建与部署通过 Serverless 开发者工具入门 Serverless 应用开发、部署、运维是非常方便的,我们以 Serverless Devs 为例介绍阿里云函数计算应用的部署,并对工具侧的函数创建、部署以及其他相关功能进行探索。Serverless Devs 是一个开源的 Serverless 开发者平台,致力于为开发者提供强大的工具链。通过该平台,开发者可以一键体验多云 Serverless 产品,极速部署 Serverless 项目。按照官方目前的描述,Serverless Devs 已经支持包括 AWS Lanbda、阿里云函数计算、百度智能云函数计算、腾讯云云函数、华为云函数工作流等在内的多个云厂商的 Serverless 相关产品。下面通过 Serverless Devs 开发者工具,以阿里云函数计算为例进行实践,探索如何创建、部署 Serverless 应用。1)安装 Serverless Devs 开发者工具(执行npm install -g @Serverless-devs/s命令)。2)设置阿里云凭证信息(执行s config add --AccessKeyID AccessKeyID --AccessKeySecret AccessKeySecret --AccountID AccountID命令)。3)建立模板项目(执行s init node.js12-http -d fc-hello-world-demo命令),初始化过程如图所示。通过 Serverless Devs 创建项目图4)进入项目目录(执行 cd fc-hello-world-demo 命令),并部署(执行 s deploy 命令),部署后的结果如图所示。通过 Serverless Devs 部署项目项目部署成功之后,可以进行更多操作,具体如下。触发函数(执行s invoke命令),结果如图所示。通过 Serverless Devs 触发函数查看线上函数详情(执行s info命令),结果如图所示。通过 Serverless Devs 查看函数详情Serverless Devs 还拥有比较完善的桌面客户端。开发者可以通过桌面客户端进行应用的创建、管理以及相关配套功能的使用,示例如下。查看应用列表,并快速创建应用,如图所示。通过 Serverless Devs 桌面客户端查看应用列表创建应用之后,可以进行应用的管理。下图是 Serverless Devs 桌面客户端管理应用界面。通过 Serverless Devs 桌面客户端管理应用其他配套功能的使用如下。如图所示为一键压测函数性能。通过 Serverless Devs 桌面客户端一键压测函数性能一键对函数资源进行调试,如图所示。通过Serverless Devs桌面客户端一键对函数资源进行调试一键查看函数多维度指标信息,如图所示。通过 Serverless Devs 桌面客户端一键查看函数多维度指标信息除此之外,Serverless Devs 还拥有较为方便的 Yaml 可视化配置功能,如下图所示。通过Serverless Devs桌面客户端进行Yaml可视化配置如何对 Serverless 应用进行调试在应用开发过程中,或者应用开发完成后,当执行结果不符合预期时,通常要进行一定的调试。但是在 Serverless 架构下,调试往往会受到极大的考验,尤其在受环境因素限制时,通常会出现这样的情况:所开发的应用在本地可以健康、符合预期地运行,但是在 FaaS 平台上则有一些不可预测的问题;或者在一些特殊环境下,本地没有办法模拟线上环境,难以进行应用的调试。Serverless 应用的调试一直备受诟病,但是各个云厂商并没有因此放弃在调试方向上的深入探索,下面我们介绍几种方式。在线调试简单调试 所谓的简单调试,就是在控制台进行调试。以阿里云函数计算为例,可以在控制台通过“代码执行”按钮进行基本的调试,如下图所示。函数计算代码编辑页面必要的时候也可以通过设置 Event 来模拟一些事件。阿里云函数计算事件页面在线调试的好处是可以使用一些线上环境进行代码的测试。当线上环境拥有 VPC 等资源时,在本地环境是很难进行调试的。断点调试 除了简单的在线调试之外,部分云厂商还支持断点调试,例如阿里云函数计算的远程调试。我们以阿里云函数计算远程调试为例,可以实现通过控制台进行函数的在线调试。当创建好函数之后,可以选择远程调试,并单击“开启调试”按钮,如图所示。函数计算远程调试页面开启调试之后,稍等片刻,系统将会进入远程调试界面,如图所示。函数计算远程调试开始页面当出现图当出现下图所示界面,我们可以进行断点调试。函数计算远程调试断点调试页面端云联调在本地进行 Serverless 应用开发时,往往会涉及一些线上资源,例如通过对象存储触发器触发函数执行,通过 VPC 访问数据库等,此时线上和线下环境不一致会让线下开发、调试面临极大的挑战。Serverless Devs 开发者工具通过搭建 Proxy 辅助函数的方法将线上和线下资源打通,可以快速帮助开发者在本地进行应用的开发与调试,这种调试方式称为端云联调。如下图所示, Serverless Devs 开发者工具会根据 Yaml 配置文件,创建辅助服务和辅助函数,并通过辅助服务和辅助函数实现线上和线下资源打通,以及完整的端云联调。Serverless Devs 端云联调原理示意图Serverless Devs 开发者工具会根据 Yaml 配置文件的内容,创建辅助服务和辅助函数(辅助服务和 Yaml 中所声明的业务服务配置是一致的)。通过触发器(包括通过 SDK、API、s proxied invoke 命令,或者其他触发器)触发辅助函数(函数计算 C),请求流量回到本地调试实例(本地环境 A),这时本地调试实例(本地函数执行环境容器)收到的 event 和 context 是真实来自线上的。本地调试实例(本地环境 A)可以直接访问以下内容:VPC 内网资源,比如 RDS、Kafka 内网地址等;一些云服务的内网地址;硬盘挂载服务(直接访问 NAS)。 端云联调流程如下:1)执行s proxied setup命令准备端云联调所需的辅助资源以及本地环境;2)对于无触发器的普通事件函数或者 HTTP 触发器,准备工作完成后,启动另一个新的终端,切换到该项目路径下,执行s proxied invoke命令调用本地函数;3)完成调试任务后,执行s proxied cleanup命令清理端云联调所需的辅助资源以及本地环境。除了通过命令使用端云联调功能外,我们也可以在 VSCode 开发者工具中使用端云联调功能,如图所示。在 VSCode 中使用端云联调功能远程调试端云联调在本地除了有一个通道服务容器外,还有一个函数计算容器,用来执行本地函数;远程辅助函数只是单纯将远程流量发送到本地。在实际调试过程中,需要登录到实例进行项目调试,此时可以选择使用远程调试。相比于端云联调,远程调试在本地只有一个通道服务容器,执行过程全部依赖线上;远程函数将执行结果返回。远程调试整体架构简图如图所示。除了通过上面远程调试架构简图所示的通道服务登录线上环境进行代码调试或问题定位之外,部分云厂商还提供了直接登录实例进行代码调试的功能。以 Serverless Devs 为例,当使用阿里云函数计算时,我们就可以直接通过 instance 命令进行线上实例登录。尽管实例登录命令已经提供了便捷的登录体验,能帮助用户解决复杂场景下的应用异常定位等问题,但是登录实例后,用户无法直接通过函数日志、监控指标来具体定位问题,还需要借助例如 coredump、tcpdump、jmap 等工具进行问题的深入排查。例如,某用户发现自己的线上程序最近出现一些函数错误提示,报错内容都是连接远程某服务时超时。该用户怀疑是函数实例与远端服务的网络连接不稳定,因此想进入实例内部,分析实例与远端服务的网络情况。此时,我们可以按照以下步骤进行问题的排查。1)如图所示,登录实例内部后,需要执行 apt-get update 和 apt-get install tcpdump 两条命令,进行 tcpdump 工具的安装。实例登录与安装软件效果图2)安装完毕后,执行 tcpdump 命令,对远端服务 IP 的请求进行抓包,并将抓包结果保存在 tcpdump.cap 文件中。3)抓包完毕后,借助 OSS 命令行工具 ossutil64,将 tcpdump.cap 文件上传到自己的 OSS,然后下载到本地借助分析工具 Wireshark 进行分析。本地调试命令行工具 大部分 FaaS 平台会为用户提供相对完备的命令行工具,如阿里云的 Funcraft,同时也有一些开源项目如 Serverless Framework、Serverless Devs 等支持多云厂商的 FaaS 平台。通过命令行工具进行代码调试的方法很简单。以 Serverless Devs 为例,本地调试阿里云函数计算方法为:首先确保本地拥有一个函数计算的项目,然后在项目下执行调试指令,例如在 Docker 中进行调试,如下面所示。通过命令行进行本地调试编辑器插件 以 VSCode 插件为例,下载好阿里云函数计算的 VSCode 插件,并且配置好账号信息之后,在本地新建函数,并且在打点之后进行断点调试,如图所示。编辑器插件中进行调试其他调试方案Web 框架的本地调试 以 Python 语言 Bottle 框架为例,若在阿里云 FaaS 平台开发传统 Web 框架,可以增加如下代码:app = bottle.default_app()并且对run()方法进行条件限制(if __name__ == '__main__'):if __name__ == '__main__': bottle.run(host='localhost', port=8080, debug=True)例如:# index.py import bottle @bottle.route('/hello/<name>') def index(name): return "Hello world" app = bottle.default_app() if __name__ == '__main__': bottle.run(host='localhost', port=8080, debug=True)和传统开发思路一样,我们可以在本地开发并在本地进行调试。当部署到线上时,只需要在入口方法处设置 index.app,即可实现平滑的部署。本地模拟事件调试 针对非 Web 框架,可以在本地构建一个方法,例如要调试对象存储触发器,代码如下:import jsondef handler(event, context): print(event)def test(): event = { "events": [ { "eventName": "ObjectCreated:PutObject", "eventSource": "acs:oss", "eventTime": "2017-04-21T12:46:37.000Z", "eventVersion": "1.0", "oss": { "bucket": { "arn": "acs:oss:cn-shanghai:123456789:bucketname", "name": "testbucket", "ownerIdentity": "123456789", "virtualBucket": "" }, "object": { "deltaSize": 122539, "eTag": "688A7BF4F233DC9C88A80BF985AB7329", "key": "image/a.jpg", "size": 122539 }, "ossSchemaVersion": "1.0", "ruleId": "9adac8e253828f4f7c0466d941fa3db81161****" }, "region": "cn-shanghai", "requestParameters": { "sourceIPAddress": "140.205.***.***" }, "responseElements": { "requestId": "58F9FF2D3DF792092E12044C" }, "userIdentity": { "principalId": "123456789" } } ] } handler(json.dumps(event), None)if __name__ == "__main__": print(test())这样通过构造一个 event 对象,即可实现模拟事件触发。通过开发者工具进行依赖安装和项目构建Serverless 架构下的应用开发和传统架构下的应用开发有一个比较大的区别是二者所关注的内容维度是不同的,例如理想状态下的前者并不需要人们关注服务器等底层资源。但是在当今的 Serverless 发展阶段,Serverless 架构下的应用开发真的不需要人们对服务器等额外关注吗?其实不是的,虽然 Serverless 架构强调的是 Noserver 心智,但是在实际生产中,有很多依赖等是无法跨平台使用的,例如 Python 语言中的某些依赖需要进行二进制编译,和操作系统、软件环境等有比较大的关系,所以项目中如果引入这类依赖,需要在和函数计算平台线上环境一致的环境中进行依赖的安装、代码的打包或项目的部署。阿里云函数计算对自身的线上函数环境有比较细致的描述,提供了相应的文档,例如使用 C、C++ 、Go 编译的可执行文件,需要与函数计算的运行环境兼容。函数计算的 Python 运行环境如下。Linux 内核版本:Linux 4.4.24-2.al7.x86_64。Docker 基础镜像:docker pull python:2.7 ; docker pull python:3.6。 但是,在实际应用开发过程中,依赖的打包依旧是让一众开发者头疼的事情。他们在很多 Serverless 应用开发过程中都会面临类似的挑战:项目在本地可以正常运行,一发布到线上就找不到某个依赖,但是实际上依赖是存在的,此时问题定位就成了非常困难的事情。目前来看,为 Serverless 应用安装依赖或者项目构建的方法通常有 3 种:1)在本地创建项目之后,自行根据云厂商提供的环境数据进行线上环境搭建,进而进行依赖的安装。这种方法相对来说自主可控,但是难度非常大,操作较为繁琐。2)用已有的开发者工具进行依赖的安装,如图所示:通过工具安装依赖示意图以 Serverless Devs 开发者工具以及阿里云函数计算产品为例,开发者只需要按照语言习惯准备对应语言的相关依赖安装文件即可,例如 Python 语言的requirements.txt,Node.js语言的package.json等。然后在当前项目下,执行s build --use-docker命令即可完成与阿里云函数计算平台线上环境一致的环境中的依赖的安装。以 Python 项目为例,开发者只需要在项目目录下完成如下操作。开发源代码;执行s build –use-docker命令之后,自动根据requirements.txt文件下载对应的依赖到本地,并且和源码一起组成交付物;执行s deploy命令将整个交付物打包,创建函数,同时设置好依赖包的环境变量,让函数可以直接输入对应的代码依赖包。3)目前,部分云厂商的 FaaS 平台控制台支持 WebIDE,阿里云的 WebIDE 拥有实现命令行程序的能力,所以也可以在控制台的 WebIDE 中直接进行依赖的安装。在线安装依赖示意图如图所示。在线安装依赖示意图新书推荐阿里云、蚂蚁集团的 4 位专家刘宇、田初东、卢萌凯、王仁达(排名不分先后)系统梳理阿里在 Serverless 架构下的 AI 经验,联袂推出新书《Serverless 架构下的 AI 应用开发:入门、实战与性能优化》。本书是关于 Serverless 架构下机器学习实战的技术书,我们希望通过简单明了的语言、真实的案例,以及开放的源代码,为读者介绍 Serverless 架构与机器学习相关的基础知识,帮助读者在 Serverless 架构下开发、上线机器学习项目。作者介绍:刘宇,阿里云 Serverless 产品经理田初东,蚂蚁集团算法工程师卢萌凯,阿里云 Serverless 高级解决方案架构师王仁达,阿里云 Serverless 工具链技术负责人
背景11 月 5 日,2022 杭州 · 云栖大会上,阿里云宣布函数计算 FC 开启全面降价,vCPU 单价降幅 11%,其他的各个独立计费项最高降幅达 37.5%。本次云栖大会上,阿里云智能总裁张建锋表示,以云为核心的新型计算体系正在形成,软件研发范式正在发生新的变革,Serverless 是其中最重要的趋势之一,阿里云将坚定推进核心产品全面 Serverless 化,帮助客户更好地实现敏捷创新。函数计算 FC 全面降价,让 Serverless 更加普惠。用户可随用随取,按量计费,用更低成本采用 Serverless 架构,尽享 Serverless 带来的研发效率提升和技术红利。关注阿里云云原生公众号,后台回复关键词【手册】查看 Serverless 产品手册!阿里云函数计算 FC 全面降价,让 Serverless 更普惠计费粒度更精细,按需付费就是省函数计算 FC 计费粒度精细,按执行环境的内存和执行时间计费,计费规格最低可达到 1 毫秒粒度的计费时长,0.05 核 vCPU、128MB内存、1/16 GPU 卡用户可以只为请求产生的资源消耗买单,极致控制成本。函数计算 FC 上线新版资源包,函数规格 vCPU、内存、磁盘等各个计费项的绑定彻底解绑,让用户可以按需自由选配,贴合自己的应用运行时开销选取规格,进一步降低资源闲置比例。预留模式作为函数计算 FC 消除冷启动的利器,新增了闲置计费仅 1/10 价格更加让业务能免除高成本的后顾之忧。据团队测算,一个集群的资源如果日均利用率在 30% 以下,或者有明显的闲置浪费,就适合使用函数计算 FC。采用函数计算 FC 之后资源利用率能够提高到 60% 甚至 90% 以上,综合成本降低 15% 到 70%。当您的业务 CPU 利用率低于 50%,或 GPU 利用率低于 30%,迁移上函数计算 FC 可以实现降本。以中小企业为例假定(中小型企业某 API 服务 QPS~8个)每月 2000 万次访问,每次访问平均 50 毫秒,每次访问平均占用 vCPU 0.25核/内存 256MB,当你将业务托管到函数计算时,可以将成本精确到每次访问 0.00000175 元,精确地衡量单位成本是函数计算 FC 节省成本利器。接下来对三种方案进行对比:1. 传统虚拟化方案按照传统的虚拟化方案,2C4G 的云主机需要 2828.4 元/年,单机可支持 8 个并发访问,但在业务高峰期(>8 个并发)时需要排队处理访问请求,有可能导致业务性能受损,而在低峰期又闲置造成资源浪费。2. 自建容器化方案自建容器化方案则对技术团队有较高的运维要求,资源成本难以定量优化,且不可避免将引入更高的人力成本。按照业内经验,日均利用率能优化至 30%(8 小时弹性资源)已经是非常不错的结果,但仍需>1416.96 元/年的云主机总成本。3. 函数计算 Serverless 化方案函数计算仅需 420 元/年(2000 万次/月*0.00000175 元/次=35 元/月),在同等情况下简单计算即可量化确认 70%-85% 的降本目标,且无需引入额外的人力成本。以企业使用为例wolai 是一款面向未来的云端信息协同平台。通过使用函数计算,wolai 开发快照保存系统,解决协同编辑算法问题。前端工程师可负责从前到后一整套开发流程,9 人团队即可保证 wolai 研发高度迭代。相比传统架构,使用函数计算可节省 50% 计算费用,人力的投入能够节省一半甚至更多。视频直播是恋爱社交 APP 伊对最为重要的业务,峰谷特征明显。为了保障业务平稳,伊对需要准备大量机器去处理任务,在流量低峰期机器资源会大量空闲浪费,而某些节假日带来的高峰却会超过集群的最大承受能力,任务排队不得不对部分业务做降级处理。在使用函数计算 FC 之后,峰谷期资源问题得到彻底解决,资源成本开支减少了 20%。互联网营销推广服务商鱼传科技,业务主要基于支付宝小程序进行承载,具有访问量波动大、流量突发预测难等特点,尤其是活动期间访问突增对小程序后端服务的稳定和弹性也是一个很大的考验。为了应对无法预测的突发流量,鱼传科技进行全系统 Serverless 化,一天只用 200 元即可支撑日活超过 50 万人的小程序,能承受突发上万 QPS。函数计算 FC 全地域&全计费项价格下调2022 年 11 月 3 日起,函数计算 FC 全地域&全计费项价格下调,最高降价幅度达 37.5%!按量付费和资源包全规格降价,日均资源利用率为 30% 时降本幅度仍可达 12% ~ 47%,实际资源利用率越低可降本空间越大。1. 按量付费全面降价:活跃 vCPU 使用量单价降价 11%,vCPU 闲置时可自动被系统回收,单价仅为活跃时的 1/10,内存使用量单价降价 20%,GPU 使用量单价降价 20%,函数调用次数单价降价 25%,公网出流量单价降价 37.5%。2. 全新的资源包购买方案:新版函数计算资源包支持各计费项自由组合购买,购买相同资源的情况下,新版函数计算资源包价格仅为按量付费价格的 29%~80%。3. 新用户免费试用:首次开通函数计算时可 0 元享免费试用额度,有效期 1 年,总价值 88 元。免费试用额度限购 1 次,内含三个试用包:50 万 vCPU*秒 + 100 万 GB*秒 + 100 万次函数调用。4. 老用户免费试用:函数计算将于 2022年12月31日24时 起取消每月 40万 GB*秒 + 100万次调用免费额度。为答谢老用户(2022年11月2日11:25分 之前开通函数计算的用户)对函数计算产品的关爱,所有老用户仍可在 2022年12月31日24 时前享有免费额度,同时也可 0 元享老用户试用套餐,有效期 1 年,总价值 88 元。免费试用额度限购 1 次,内含三个试用包:50万 vCPU*秒 + 100万 GB*秒 + 100万次函数调用。注意:购买试用套餐以后,会优先抵扣试用包的资源,我们建议您在 2023年1月1日 购买试用套餐。开始使用函数计算 FC阿里云是国内最早提供 Serverless 计算服务的云厂商。2017 年推出的函数计算 FC 是一款 FaaS 产品,这是一种以事件驱动为核心的全托管计算服务,用户只需编写代码并上传,函数计算就会自动准备好计算资源,以弹性、可靠的方式运行代码,并提供完整的可观测能力,大幅简化开发运维过程。函数计算 FC 自发布至今已经帮助上万家国内外企业在 Web、移动后端、音视频、AI 推理、批任务处理等广泛场景落地现代化应用。阿里云函数计算 FC 日调用次数超过 300 亿次,有效支撑历年双 11 百万 QPS 洪峰,业务增速超过 300%,整体规模位居国内首位。在 Forrester 发布的 2021 年第一季度 FaaS 平台评估报告中,阿里云凭借函数计算产品能力全面领先的优势,成为全球前三的 FaaS 领导者,这也是首次有国内科技公司进入 FaaS 领导者象限。今年,函数计算 FC 深入打透音视频处理、实时数据处理、GPU 三大场景,帮助开发者专注业务、降本提效。1. 音视频处理能力再突破,函数计算 FC 新增全景录制模版。通过全景录制这种所见即所得的模式,可轻松还原直播互动效果,让用户开箱即用,既能得到 SaaS 化音视频快速接入体验,又能拥有代码级的定制灵活性,可以瞬间创建多个实例进行视频多路并行转码,极大缩短了出片时间。同时,函数计算 FC 资源利用率高,算力消耗低,相比传统方案成本可降低 70% 以上。2. 让消息流动起来,函数计算 FC 实时数据处理能力再增强。函数计算 FC 与阿里云全系消息产品如 RocketMQ、Kafka、EventBridge 进行官方集成,内置上百个触发源,在消息产品控制台就可以实现“一键”对消息进行数据清洗、富化和转储,让消息发挥更大的价值。函数计算 FC 的自适应弹性可以有效应对海量消息的波峰波谷,达到亿级每分钟的事件吞吐。3. 函数计算 FC 推出 Serverless GPU,支持最小 1/16 卡的多规格 GPU 算力分割,同时提供准实时三秒冷启动,秒级弹性+秒级计费。当前 GPU 成为 AI 推理、多媒体处理的算力提供者。经过团队测算,在以上两种场景下,选择使用 GPU ,将会比选择使用传统 CPU 性能提升达到数十倍甚至百倍以上。然而,GPU 的价格一般比较高,而且使用率普遍低于 30%,这导致很多企业对 GPU 望而却步。Serverless GPU 让 GPU 算力更平价,普惠中小企业。点击此处,查看函数计算 FC 更多详情!
前言回顾 RocketMQ 的发展历程,至今已十年有余。2022 年 RocketMQ 5.0 正式发布,全面迈进云原生时代。11 月 5 日,2022 杭州 · 云栖大会上,阿里云智能高级产品专家杨秋弟在云原生峰会上发表主题演讲,发布消息队列 RocketMQ 5.0:从消息服务到云原生事件流处理平台。阿里云智能高级产品专家&Apache RocketMQ 联合创始人 杨秋弟Apache RocketMQ 发展史回顾 Apache RocketMQ 过去十年的发展历程,可分为“诞生于互联网”与“成长于云计算”两大阶段。第一个阶段是 RocketMQ 的从 0 到 1,在阿里内部规模化落地。2012 年,为了支撑超大规模电商互联网架构,阿里中间件研发了 RocketMQ,并在产品诞生初期开源,2017 年 RocketMQ 统一了阿里消息技术体系。第二个阶段是云计算。2015 年 RocketMQ 上云,这也是业界首个提供公共云 SaaS 形态的开源消息队列;2016 年,阿里把 RocketMQ 捐赠给 Apache,2017 年孵化毕业,成为国内首个 TLP 的互联网中间件。十年磨一剑,出鞘必锋芒。在这十年的过程中,通过集团打磨稳定性,依托云计算孵化创新,开源共建加速标准化建立与生态连接,RocketMQ 始终坚持开源、集团、商业三位一体的发展思路,内核演进和产品迭代齐头并进。2022 年 RocketMQ 5.0 正式发布宣告着全面迈进云原生时代。RocketMQ 5.0:从消息服务到云原生事件流平台回顾过去这十年,RocketMQ 服务于集团几乎所有的业务,在阿里云上更是累计服务了 10 万余家企业客户,覆盖互联网、零售、金融、汽车等 20 多个行业,大规模的生产实践持续累积产品的核心优势。多样性,企业级应用复杂的业务诉求,催生 RocketMQ 提供丰富的消息类型,比如定时消息、事务消息、顺序消息等等。此外,也提供了像消息轨迹、消息回溯等一系列的消息治理能力。 一致性,无论是淘宝交易还是蚂蚁支付都天然对数据一致性有着极高的要求,RocketMQ 提供的分布式事务消息是业内第一个提供该特性的消息产品,将异步解耦与数据一致性完美融合,是金融客户中不可或缺的产品能力。 稳定性,稳定性是产品的根基,更是一个系统工程,RocketMQ 长期在电商和金融领域中打磨,不仅提供最高达 99.99% SLA,更是帮助客户提供全方位的健康巡检与故障排查能力,如消息轨迹、消息回溯、死信机制等等,提供多样化的稳定性兜底手段。 高性能,在双十一的极限流量下,RocketMQ 具备无限扩展能力,支持千万级并发与万亿级消息洪峰,P9999 写延迟在 1ms 内,100%在 100ms 内。 可以说,在消息领域,尤其在业务消息领域,RocketMQ 在国内已经做到顶尖,成为企业客户的首选。而随着云原生以及数字化时代的到来,RocketMQ 也在快速的发生着变化,那么变化主要体现在哪些方面呢?首先,全面拥抱云原生。向下,消息系统自身实现云原生架构的演进,充分释放云基础设施的池化能力,全方位提高消息的核心技术指标。向上,消息产品形态持续演进,成为云原生应用架构的核心引擎。比如微服务、事件驱动、Serverless 等现代化应用架构。其次,全面拥抱实时数据。企业的数字化转型从原来的业务数字化迈向了数字业务化。对业务数据的实时洞察、实时决策成为指导业务成功的关键要素。消息队列也将从在线业务架构的基础设施,延伸到实时数据架构的基础设施,从而实现事务分析一体化。随着 5.0 的发布,RocketMQ 也正式从消息服务升级到云原生事件流处理平台。RocketMQ 5.0:云原生架构升级首先来看 RocketMQ 自身的云原生架构演进。从下面的全景图可以看出,RocketMQ 从客户端到服务端都进行了全方位的改造,具体体现在以下几个方面:1. 轻量化。RocketMQ 4.0 诞生于 2012 年的淘宝电商,当时大部分的业务还跑在物理机上,单节点计算能力强,客户端节点数少且较为稳定,因此,富客户端的接入方式不仅更加高效,更可以提供诸如客户端侧负载均衡、消息缓存、故障转移等一系列企业级特性。但这种模式在云原生时代发生了改变,轻量客户端更容易被云原生技术栈所集成。因此,RocketMQ 5.0 客户端采用轻量 SDK 设计理念,将原来富客户端的逻辑下沉到服务端,满足现代化应用轻量化、Serverless 化以及 Mesh 化的趋势,更容易被集成;同时也正是因为轻量化,使得 SDK 多语言开发成本低了很多,快速覆盖当下主流的多语言版本。2. 弹性,存算分离架构让无状态计算节点可以快速伸缩,而分级存储以及冷热分离架构更是让消息存储具备更强的弹性能力。3. 高可用,基于全新的 Leaderless 架构,去 ZK 依赖的同时,可以做到副本数灵活选择,同步异步自动升降级,实现秒级故障转移;面向云的多可用区、多地域组建全局高可用能力。4. 最后,RocketMQ 整体架构走向 Kubernetes 化,拥抱 OpenTelemetry,依托于阿里云提供的 ARMS、Prometheus 以及 Grafana 实现可观测能力的云原生化。而 RocketMQ 5.0 本次的升级,除了在技术架构云原生化之外,在产品能力以及成本优化方面都有着重大的提升,我们来逐一分解。轻量无状态消费模型RocketMQ 4.0 采用按队列消费模型,消费者完全按照队列负载均衡,非常适合批量拉取快速消费,对单一消息状态不敏感的场景,比如流计算。然而在业务消息领域,尤其是金融场景以及事件驱动架构之下,每一条消息状态都是极为重要的。再加上不同业务类型的消息处理耗时也是各不相同,从毫秒级、到秒级甚至到分钟级,队列的负载不均衡或者短暂的 Block 都可能会引发消息的局部堆积,从而影响到最终用户的体验。因此,RocketMQ 5.0 全新推出按消息负载的轻量无状态消费模型,通过 PoP 机制巧妙地在队列模型之上构建了消息模型,业务只需要关心消息而无需关心队列,所有 API 都能够支持单条消息级别控制,如消息的消费、重试、删除等。而基于消息消费模型,客户端、连接和消费都是无状态的,可在任意 Proxy 节点上飘移,真正做到轻量化。RocketMQ 5.0 提供按队列消费模型以及按消息消费模型,更好的满足事件与流的业务场景,正可谓鱼与熊掌兼得。海量消息分级存储RocketMQ 5.0 的另一个重大升级则是海量消息的分级存储。对消息队列了解的同学都知道,消息通常都是流动的短时间的存储,业内大部分消息产品对消息的保留时间都比较优先,3 天,7 天,最长 15 天不等。有限的存储空间使不仅限制了消息的保留时长,更在某些场景下可能会导致业务资损,比如在消息还没有被消费的时候,因为磁盘空间不足或者消息过期而被清除,这在金融等领域都是不可接受的。所以,RocketMQ 一直想要解决这样的问题,让存储变得更有弹性。RocketMQ 5.0 基于 ESSD、对象存储打造冷热分离以及分级存储架构,提供低成本的无限存储能力,确保消息不会因为本地磁盘空间不足而提前被清除,造成业务资损。我们提供消息存储的 Serverless,客户只需按实际存储使用量付费,而无需预购存储空间。此外,流量削峰是消息队列极为常见的场景,而由此带来的海量消息堆积能力以及在堆积情况下的性能稳定性成为衡量产品性能的核心指标。RocketMQ 5.0 基于冷热数据分离架构进一步做到读写隔离,避免在堆积的场景下影响热数据的写入性能。分级存储的冷数据碎片规整能力更是提高了冷数据的读取性能,为用户提供一致的冷读 SLA。售卖系列全线升级,最高降本 50%从前面的介绍我们已经了解到,RocketMQ 5.0 在技术架构以及产品能力上都有着明显提升。而 5.0 推出全新的售卖形态与计费策略相比 4.0 更简单、更灵活也更为普惠。实例的综合成本最高可降低 50%。接入门槛最低可降至 390 元/月,远低于自建成本。消息存储支持 Serverless 弹性能力,按需付费可大幅降低闲置成本。结合冷热分离的多级存储能力,相比开源自建可降低 67%,大幅降低消息队列的使用成本。EventBridge:云上事件枢纽事件驱动是一个起源很早的概念,早在几十年前,无论是操作系统内核的设计、还是客户端编程框架都大量采用了事件驱动技术。RocketMQ PushConsumer 提供的 API 其实就是一种事件驱动的编程范式,但在微服务应用架构当中,集成与通信才是刚需,事件驱动的价值并没有那么明显的体现。而随着云原生时代的到来,计算力的构成越来越多样化。作为云原生的代表技术,Serverless 架构范式也是事件驱动的。无论是阿里云的函数计算、还是 AWS 的 Lambda,它们的主要触发源都是各种形态的事件,云产品事件,如 OSS 文件上传触发用户基于函数进行文件加工处理;用户业务事件,如 RocketMQ 触发函数运行消费逻辑处理等等。以事件驱动为核心理念,阿里云推出了 EventBridge 产品,其使命就是打造云上的事件枢纽。通过 EventBridge 可以兑现四大业务价值:1. 统一事件枢纽。阿里云从 IaaS、PaaS 到第三方的 SaaS,每天都有数以亿计的事件产生,但却没有一种简单和统一的方式来触达这些事件;这些事件散落在各个地方形成『事件孤岛』,很难挖掘出有用的业务价值。只有充分发挥数据的规模效应,建立起数据之间的血缘关系,我们才能更好的发掘出数据的价值;所以 EventBridge 首要任务便是统一阿里云上的事件规范,拥抱 CloudEvents 事件标准,打造阿里云统一的事件枢纽。2. 事件驱动引擎。当 EventBridge 连接了海量的事件源后,基于 RocketMQ 毫秒级的事件触发能力,必将加速企业 EDA/Serverless 的架构升级。3. 开放与集成。EventBridge 提供丰富的跨云、跨平台、跨产品、跨地域以及跨账号的连接能力,能够促进云产品、应用程序、SaaS 服务的相互集成。4. 低代码。EventBridge 借助 Serverless 的应用中心,通过简单的规则匹配以及丰富的模板,即可实现事件的分发、过滤、转换等处理,进一步提升事件驱动的效率。让消息无处不在,让事件无所不及依托于 EventBridge、RocketMQ 以及函数计算 FC 的强强联合,目前 EventBridge 的事件生态已初具规模。在云产品事件集成方面,目前已经集成 200+云产品事件源,3000 多种事件类型。在数据集成与处理方面,EventBridge 与微服务应用、大数据、IoT 等场景深度集成。比如与消息生态的融合,阿里云 6 款消息队列产品通过 EventBridge 实现消息数据的互联互通,并且通过 EventBridge 的全球事件网络赋予消息全球消息路由的能力,同时也可以通过 EventBridge 提供的丰富的模板,实现 ETL 数据处理能力。在 SaaS 应用集成方面,包括钉钉、聚石塔以及云上 50 多个 SaaS 服务都可以通过 EventBridgehook 方式连接到 EventBridge。在事件触发方面,EventBridge 目前已经触达 10 多个事件目标,海量的事件源都可以通过 EventBridge 触发包括 FC/SAE 等在内的 10 多款事件目标云产品。除此之外,目前 EventBridge 已经对接了阿里云全量的云产品 API,任何一个事件都可以通过云产品 API 的方式进行触达。未来还有会更多的事件源以及事件目标接入到 EventBridge 上来。RocketMQ Streams:轻量级计算的新选择正如开篇所提到的,基于云原生架构的全面升级,RocketMQ 5.0 也将从在线业务架构的基础设施,延伸到实时数据架构的基础设施,实现事务分析一体化。将 RocketMQ Streams 打造成为轻量级计算的新选择。业内最常见如 Flink、Spark 等大数据框架大多采用中心化的 Master-Slave 架构,依赖和部署比较重,每个任务的执行都需要很大的开销,有较高的使用成本。而与之不同的是,RocketMQ Streams 着重打造轻资源,高性能的轻量计算引擎,无额外依赖,最低 1core,1g 即可完成部署,适用于大数据量、高过滤、轻窗口计算的场景,在资源敏感型场景,如消息队列流计算、安全风控,边缘计算等,RocketMQ Streams 具有有很大优势。阿里云消息团队与安全团队合作,通过对过滤场景做大量优化,性能提升 3-5 倍,资源节省 50%-80%。目前,RocketMQ Streams 已经在开源社区发布,未来计划在 2023 年 4 月在阿里云完成商业化。RocketMQ 这十年,我们一同向前RocketMQ 历经十余年的打磨,已经取得了众多成果。全球拥有 700+的贡献者,1.8w Star 数,超过 80%的主流云厂商提供了 RocketMQ 的商业托管服务,Apache RocketMQ 社区始终保持着极高的活跃度,因此,也荣获了科创中国“开源创新榜”,中日韩开源软件优秀技术奖等十多个国内外开源奖项。而阿里云作为 RocketMQ 的起源和核心贡献者,不仅 100%覆盖全集团业务,承载千万级并发万亿级消息洪峰。十多年以来更是累计服务 10w+万企业客户,覆盖互联网、零售、汽车等 20 多个行业,超过 75%的头部企业选择使用 RocketMQ。期望阿里云的消息队列 RocketMQ 可以成为广大企业客户的心之所选。也诚邀更广大的开发者来积极参与 RocketMQ 的开源社区建设,一起将 RocketMQ 打造为消息领域的引领者。欢迎扫描下方二维码加入钉钉群与 RocketMQ 爱好者一起沟通交流~点击此处,进入官网了解更多详情~
作者:斜阳引言本文主要介绍在使用 RocketMQ 时为什么需要重试与兜底机制,生产者与消费者触发重试的条件和具体行为,如何在 RocketMQ 中合理使用重试机制,帮助构建弹性,高可用系统的最佳实践。RocketMQ 的重试机制包括三部分,分别是生产者重试,服务端内部数据复制遇到非预期问题时重试,消费者消费重试。本文中仅讨论生产者重试和消费者消费重试两种面向用户侧的实现。生产者发送重试RocketMQ 的生产者在发送消息到服务端时,可能会因为网络问题,服务异常等原因导致调用失败,这时候应该怎么办?如何尽可能的保证消息不丢失呢?1. 生产者重试次数RocketMQ 在客户端中内置了请求重试逻辑,支持在初始化时配置消息发送最大重试次数(默认为 2 次),失败时会按照设置的重试次数重新发送。直到消息发送成功,或者达到最大重试次数时结束,并在最后一次失败后返回调用错误的响应。对于同步发送和异步发送,均支持消息发送重试。同步发送:调用线程会一直阻塞,直到某次重试成功或最终重试失败(返回错误码或抛出异常)。异步发送:调用线程不会阻塞,但调用结果会通过回调的形式,以异常事件或者成功事件返回。 2. 生产者重试间隔在介绍生产者重试前,我们先来了解下流控的概念,流控一般是指服务端压力过大,容量不足时服务端会限制客户端收发消息的行为,是服务端自我保护的一种设计。RocketMQ 会根据当前是否触发了流控而采用不同的重试策略:非流控错误场景:其他触发条件触发重试后,均会立即进行重试,无等待间隔。流控错误场景:系统会按照预设的指数退避策略进行延迟重试。为什么要引入退避和随机抖动? 如果故障是由过载流控引起的,重试会增加服务端负载,导致情况进一步恶化,因此客户端在遇到流控时会在两次尝试之间等待一段时间。每次尝试后的等待时间都呈指数级延长。指数回退可能导致很长的回退时间,因为指数函数增长很快。指数退避算法通过以下参数控制重试行为,更多信息,请参见 connection-backoff.md。INITIAL_BACKOFF:第一次失败重试前后需等待多久,默认值:1 秒;MULTIPLIER :指数退避因子,即退避倍率,默认值:1.6;JITTER :随机抖动因子,默认值:0.2;MAX_BACKOFF :等待间隔时间上限,默认值:120 秒;MIN_CONNECT_TIMEOUT :最短重试间隔,默认值:20 秒。ConnectWithBackoff() current_backoff = INITIAL_BACKOFF current_deadline = now() + INITIAL_BACKOFF while (TryConnect(Max(current_deadline, now() + MIN_CONNECT_TIMEOUT))!= SUCCESS) SleepUntil(current_deadline) current_backoff = Min(current_backoff * MULTIPLIER, MAX_BACKOFF) current_deadline = now() + current_backoff + UniformRandom(-JITTER * current_backoff, JITTER * current_backoff)特别说明:对于事务消息,只会进行透明重试(transparent retries),网络超时或异常等场景不会进行重试。3. 重试带来的副作用不停的重试看起来很美好,但也是有副作用的,主要包括两方面:消息重复,服务端压力增大远程调用的不确定性,因请求超时触发消息发送重试流程,此时客户端无法感知服务端的处理结果;客户端进行的消息发送重试可能会导致消费方重复消费,应该按照用户ID、业务主键等信息幂等处理消息。 较多的重试次数也会增大服务端的处理压力。 4. 用户的最佳实践是什么1)合理设置发送超时时间,发送的最大次数发送的最大次数在初始化客户端时配置在 ClientConfiguration;对于某些实时调用类场景,可能会导致消息发送请求链路被阻塞导致业务请求整体耗时高或耗时;需要合理评估每次调用请求的超时时间以及最大重试次数,避免影响全链路的耗时。2)如何保证发送消息不丢失由于分布式环境的复杂性,例如网络不可达时 RocketMQ 客户端发送请求重试机制并不能保证消息发送一定成功。业务方需要捕获异常,并做好冗余保护处理,常见的解决方案有两种:向调用方返回业务处理失败;尝试将失败的消息存储到数据库,然后由后台线程定时重试,保证业务逻辑的最终一致性。 3)关注流控异常导致无法重试触发流控的根本原因是系统容量不足,如果因为突发原因触发消息流控,且客户端内置的重试流程执行失败,则建议执行服务端扩容,将请求调用临时替换到其他系统进行应急处理。4)早期版本客户端如何使用故障延迟机制进行发送重试?对于 RocketMQ 4.x 和 3.x 以下客户端开启故障延迟机制可以用:producer.setSendLatencyFaultEnable(true)配置重试次数使用:producer.setRetryTimesWhenSendFailed()producer.setRetryTimesWhenSendAsyncFailed() 消费者消费重试消息中间件做异步解耦时的一个典型问题是如果下游服务处理消息事件失败,那应该怎么做呢?RocketMQ 的消息确认机制以及消费重试策略可以帮助分析如下问题:如何保证业务完整处理消息?消费重试策略可以在设计实现消费者逻辑时保证每条消息处理的完整性,避免部分消息消费异常导致业务状态不一致。业务应用异常时处理中的消息状态如何恢复?当系统出现异常(宕机故障)等场景时,处理中的消息状态如何恢复,消费重试具体行为是什么。1. 什么是消费重试?什么时候认为消费失败?消费者在接收到消息后将调用用户的消费函数执行业务逻辑。如果客户端返回消费失败 ReconsumeLater,抛出非预期异常,或消息处理超时(包括在 PushConsumer 中排队超时),只要服务端服务端一定时间内没收到响应,将认为消费失败。 消费重试是什么?消费者在消费某条消息失败后,服务端会根据重试策略重新向客户端投递该消息。超过一次定数后若还未消费成功,则该消息将不再继续重试,直接被发送到死信队列中; 重试过程状态机:消息在重试流程中的状态和变化逻辑; 重试间隔:上一次消费失败或超时后,下次重新尝试消费的间隔时间; 最大重试次数:消息可被重试消费的最大次数。 2. 消息重试的场景需要注意重试是应对异常情况,给予程序再次消费失败消息的机会,不应该被用作常态化的链路。推荐使用场景:业务处理失败,失败原因跟当前的消息内容相关,预期一段时间后可执行成功;是一个小概率事件,对于大批的消息只有很少量的失败,后面的消息大概率会消费成功,是非常态化的。 正例:消费逻辑是扣减库存,极少量商品因为乐观锁版本冲突导致扣减失败,重试一般立刻成功。错误使用场景:消费处理逻辑中使用消费失败来做条件判断的结果分流,是不合理的。 反例:订单在数据库中状态已经是已取消,此时如果收到发货的消息,处理时不应返回消费失败,而应该返回成功并标记不用发货。消费处理中使用消费失败来做处理速率限流,是不合理的。限流的目的是将超出流量的消息暂时堆积在队列中达到削峰的作用,而不是让消息进入重试链路。这种做法会让消息反复在服务端和客户端之间传递,增大了系统的开销,主要包括以下方面:RocketMQ 内部重试涉及写放大,每一次重试将生成新的重试消息,大量重试将带来严重的 IO 压力;重试有复杂的退避逻辑,内部实现为梯度定时器,该定时器本身不具备高吞吐的特性,大量重试将导致重试消息无法及时出队。重试的间隔将不稳定,将导致大量重试消息延后消费,即削峰的周期被大幅度延长。 3. 不要以重试替代限流上述误用的场景实际上是组合了限流和重试能力来进行削峰,RocketMQ 推荐的削峰最佳手段为组合限流和堆积,业务以保护自身为前提,需要对消费流量进行限流,并利用 RocketMQ 提供的堆积能力将超出业务当前处理的消息滞后消费,以达到削峰的目的。下图中超过处理能力的消息都应该被堆积在服务端,而不是通过消费失败进行重试。如果不想依赖额外的产品/组件来完成该功能,也可以利用一些本地工具类,比如 Guava 的 RateLimiter 来完成单机限流。如下所示,声明一个 50 QPS 的 RateLimiter,在消费前以阻塞的方式 acquire 一个令牌,获取到即处理消息,未获取到阻塞。RateLimiter rateLimiter = RateLimiter.create(50); PushConsumer pushConsumer = provider.newPushConsumerBuilder() .setClientConfiguration(clientConfiguration) // 设置订阅组名称 .setConsumerGroup(consumerGroup) // 设置订阅的过滤器 .setSubscriptionExpressions(Collections.singletonMap(topic, filterExpression)) .setMessageListener(messageView -> { // 阻塞直到获得一个令牌,也可以配置一个超时时间 rateLimiter.acquire(); LOGGER.info("Consume message={}", messageView); return ConsumeResult.SUCCESS; }) .build();4. PushConsumer 消费重试策略PushConsumer 消费消息时,消息的几个主要状态如下:Ready:已就绪状态。消息在消息队列RocketMQ版服务端已就绪,可以被消费者消费;Inflight:处理中状态。消息被消费者客户端获取,处于消费中还未返回消费结果的状态;Commit:提交状态。消费成功的状态,消费者返回成功响应即可结束消息的状态机;DLQ:死信状态消费逻辑的最终兜底机制,若消息一直处理失败并不断进行重试,直到超过最大重试次数还未成功,此时消息不会再重试。该消息会被投递至死信队列。您可以通过消费死信队列的消息进行业务恢复。最大重试次数 PushConsumer 的最大重试次数由创建时决定。例如,最大重试次数为 3 次,则该消息最多可被投递 4 次,1 次为原始消息,3 次为重试投递次数。重试间隔时间无序消息(非顺序消息):重试间隔为阶梯时间,具体时间如下:说明:若重试次数超过 16 次,后面每次重试间隔都为 2 小时。顺序消息:重试间隔为固定时间,默认为 3 秒。 5. SimpleConsumer 消费重试策略和 PushConsumer 消费重试策略不同,SimpleConsumer 消费者的重试间隔是预分配的,每次获取消息消费者会在调用 API 时设置一个不可见时间参数 InvisibleDuration,即消息的最大处理时长。若消息消费失败触发重试,不需要设置下一次重试的时间间隔,直接复用不可见时间参数的取值。由于不可见时间为预分配的,可能和实际业务中的消息处理时间差别较大,可以通过 API 接口修改不可见时间。例如,预设消息处理耗时最多 20 ms,但实际业务中 20 ms内消息处理不完,可以修改消息不可见时间,延长消息处理时间,避免消息触发重试机制。修改消息不可见时间需要满足以下条件:消息处理未超时消息处理未提交消费状态 如下图所示,消息不可见时间修改后立即生效,即从调用 API 时刻开始,重新计算消息不可见时间。最大重试次数与 PushConsumer 相同。消息重试间隔 消息重试间隔 = 不可见时间 - 消息实际处理时长例如:消息不可见时间为 30 ms,实际消息处理用了 10 ms 就返回失败响应,则距下次消息重试还需要 20 ms,此时的消息重试间隔即为 20 ms;若直到 30 ms 消息还未处理完成且未返回结果,则消息超时,立即重试,此时重试间隔即为 0 ms。SimpleConsumer 的消费重试间隔通过消息的不可见时间控制。//消费示例:使用SimpleConsumer消费普通消息,主动获取消息处理并提交。 ClientServiceProvider provider1 = ClientServiceProvider.loadService(); String topic1 = "Your Topic"; FilterExpression filterExpression1 = new FilterExpression("Your Filter Tag", FilterExpressionType.TAG); SimpleConsumer simpleConsumer = provider1.newSimpleConsumerBuilder() //设置消费者分组。 .setConsumerGroup("Your ConsumerGroup") //设置接入点。 .setClientConfiguration(ClientConfiguration.newBuilder().setEndpoints("Your Endpoint").build()) //设置预绑定的订阅关系。 .setSubscriptionExpressions(Collections.singletonMap(topic, filterExpression)) .build(); List<MessageView> messageViewList = null; try { //SimpleConsumer需要主动获取消息,并处理。 messageViewList = simpleConsumer.receive(10, Duration.ofSeconds(30)); messageViewList.forEach(messageView -> { System.out.println(messageView); //消费处理完成后,需要主动调用ACK提交消费结果。 //没有ack会被认为消费失败 try { simpleConsumer.ack(messageView); } catch (ClientException e) { e.printStackTrace(); } }); } catch (ClientException e) { //如果遇到系统流控等原因造成拉取失败,需要重新发起获取消息请求。 e.printStackTrace(); }修改消息的不可见时间 案例:某产品使用消息队列来发送解耦“视频渲染”的业务逻辑,发送方发送任务编号,消费方收到编号后处理任务。由于消费方的业务逻辑耗时较长,消费者重新消费到同一个任务时,该任务未完成,只能返回消费失败。在这种全新的 API 下,用户可以调用可以通过修改不可见时间给消息续期,实现对单条消息状态的精确控制。simpleConsumer.changeInvisibleDuration(); simpleConsumer.changeInvisibleDurationAsync();6. 功能约束与最佳实践设置消费的最大超时时间和次数 尽快明确的向服务端返回成功或失败,不要以超时(有时是异常抛出)代替消费失败。不要用重试机制来进行业务限流 错误示例:如果当前消费速度过高触发限流,则返回消费失败,等待下次重新消费。正确示例:如果当前消费速度过高触发限流,则延迟获取消息,稍后再消费。发送重试和消费重试会导致相同的消息重复消费,消费方应该有一个良好的幂等设计 正确示例:某系统中消费的逻辑是为某个用户发送短信,该短信已经发送成功了,当消费者应用重复收到该消息,此时应该返回消费成功。总结本文主要介绍重试的基本概念,生产者消费者收发消息时触发重试的条件和具体行为,以及 RocketMQ 收发容错的最佳实践。重试策略帮助我们从随机的、短暂的瞬态故障中恢复,是在容忍错误时,提高可用性的一种强大机制。但请谨记 “重试是对于分布式系统来说自私的”,因为客户端认为其请求很重要,并要求服务端花费更多资源来处理,盲目的重试设计不可取,合理的使用重试可以帮助我们构建更加弹性且可靠的系统。欢迎扫描下方二维码加入钉钉群一起沟通交流~点击此处,进入官网了解更多详情~
作者:徒钟什么是消息过滤在消息中间件的使用过程中,一个主题对应的消费者想要通过规则只消费这个主题下具备某些特征的消息,过滤掉自己不关心的消息,这个功能就叫消息过滤。就如上图所描述的,生产者会向主题中写入形形色色的消息,有橙色的、黄色的、还有灰色的,而这个主题有两个消费者,第一个消费者只想要消费橙色的消息,第二个消费者只想要消费黄色的和灰色的消息,那么这个效果就需要通过消息过滤来实现。消息过滤的应用场景我们以常见的电商场景为例,来看看消息过滤在实际应用过程中起到的作用。电商平台在设计时,往往存在系统拆分细、功能模块多、调用链路长、系统依赖复杂等特点,消息中间件在其中就起到了异步解耦、异步通信的作用,特别是在双十一这样的流量高峰期,消息中间件还起到了削峰填谷的作用。而在消息中间件使用方面,电商平台因为覆盖的领域众多会产生很多的消息主题,消息收发量也随着交易量和订阅系统的增加而增大。随着业务系统的水平拆解和垂直增加,相关的消息呈现出高订阅比和低投递比的状态,比如一个主题订阅比是 300:1,即 1 个主题的订阅者有 300 个,但是投递比却只有 15:300,即一条消息只有 15 个订阅者需要投递,其他 285 个订阅者全部过滤了这条消息。那解决这些场景,就需要使用到消息过滤。举例来说,在交易链路中,一个订单的处理流程分为下单、扣减库存、支付等流程,这个流程会涉及订单操作和状态机的变化。下游的系统,如积分、物流、通知、实时计算等,他们会通过消息中间件监听订单的变更消息。但是它们对订单不同操作和状态的消息有着不同的需求,如积分系统只关心下单消息,只要下单就扣减积分。物流系统只关系支付和收货消息,支付就发起物流订单,收货就完成物流订单。实时计算系统会统计订单不同状态的数据,所有消息都要接收。试想一下如果没有消息过滤这个功能,我们会怎么支持以上消息过滤的功能呢?能想到的一般有以下两个方案:1. 通过将主题进行拆分,将不同的消息发送到不同主题上。对于生产者来说,这意味着消费者有多少消费场景,就需要新建多少个 Topic,这无疑会给生产者带来巨大的维护成本。对消费者来说,消费者有可能需要同时订阅多个 Topic,这同样带来了很大的维护成本。另外,消息被主题拆分后,他们之间的消费顺序就无法保证了,比如对于一个订单,它的下单、支付等操作显然是要被顺序处理的。2. 消费者收到消息后,根据消息体对消息按照规则硬编码自行过滤。这意味着所有的消息都会推送到消费者端进行计算,这无疑增加了网络带宽,也增加了消费者在内存和 CPU 上的消耗。有了消息过滤这个功能,生产者只需向一个主题进行投递消息,服务端根据订阅规则进行计算,并按需投递给每个消费者。这样对生产者和消费者的代码维护就非常友好,同时也能很大程度上降低网络带宽,同时减少消费者的内存占用和 CPU 的消耗。RocketMQ 消息过滤的模式RocketMQ 是众多消息中间件中为数不多支持消息过滤的系统。这也是其作为业务集成消息首选方案的重要基础之一。在功能层面,RocketMQ 支持两种过滤方式,Tag 标签过滤和 SQL 属性过滤,下面我来这两个过滤方式使用方式和技术原理进行介绍Tag 标签过滤功能介绍Tag 标签过滤方式是 RocketMQ 提供的基础消息过滤能力,基于生产者为消息设置的 Tag 标签进行匹配。生产者在发送消息时,设置消息的 Tag 标签,消费者按需指定已有的 Tag 标签来进行匹配订阅。过滤语法1. 单 Tag 匹配:过滤表达式为目标 Tag,表示只有消息标签为指定目标 Tag 的消息符合匹配条件,会被发送给消费者;2. 多 Tag 匹配:多个 Tag 之间为或的关系,不同 Tag 间使用两个竖线(||)隔开。例如,Tag1||Tag2||Tag3,表示标签为 Tag1 或 Tag2 或 Tag3 的消息都满足匹配条件,都会被发送给消费者进行消费;3. 全 Tag 匹配:使用星号(*)作为全匹配表达式。表示主题下的所有消息都将被发送给消费者进行消费。使用方式1. 发送消息,设置 Tag 标签Message message = provider.newMessageBuilder() .setTopic("TopicA") .setKeys("messageKey") //设置消息Tag,用于消费端根据指定Tag过滤消息 .setTag("TagA") .setBody("messageBody".getBytes()) .build();2. 订阅消息,匹配单个 Tag 标签//只订阅消息标签为“TagA”的消息 FilterExpression filterExpression = new FilterExpression("TagA", FilterExpressionType.TAG); pushConsumer.subscribe("TopicA", filterExpression);3. 订阅消息,匹配多个 Tag 标签//只订阅消息标签为“TagA”、“TagB”或“TagC”的消息 FilterExpression filterExpression = new FilterExpression("TagA||TagB||TagC", FilterExpressionType.TAG); pushConsumer.subscribe("TopicA", filterExpression);4. 订阅消息,匹配所有 Tag 标签,即不过滤//使用Tag标签过滤消息,订阅所有消息 FilterExpression filterExpression = new FilterExpression("*", FilterExpressionType.TAG); pushConsumer.subscribe("TopicA", filterExpression);技术原理RocketMQ 在存储消息的时候,是通过 Append-Only 的方式将所有主题的消息都写在同一个 CommitLog 文件中,这可以有效的提升了消息的写入速率。为了消费时能够快速检索消息,它会在后台启动异步方式将消息所在位点、消息的大小,以及消息的标签哈希值存储到 ConsumeQueue 索引文件中。将标签存储到这个索引文件中,就是为了在通过标签进行消息过滤的时候,可以在索引层面就可以获取到消息的标签,不需要从 CommitLog 文件中读取,这样就减少消息读取产生的系统 IO 和内存开销。标签存储哈希值,主要是为了保证 ConsumeQueue 索引文件能够定长处理,这样可以有效较少存储空间,提升这个索引文件的读取效率。整个 Tag 标签过滤的流程如下:生产者对消息打上自己的业务标签,发送给我们的服务端 Broker;Broker 将消息写入 CommitLog 中,然后通过异步线程将消息分发到 ConsumeQueue 索引文件中;消费者启动后,定时向 Broker 发送心跳请求,将订阅关系上传到 Broker 端,Broker 将订阅关系及标签的哈希值保存在内存中;消费者向 Broker 拉取消息,Broker 会通过订阅关系和队列去 ConsumeQueue 中检索消息,将订阅关系中的标签哈希值和消息中的标签哈希值做比较,如果匹配就返回给消费者;消费者收到消息后,会将消息中的标签值和本地订阅关系中标签值做精确匹配,匹配成功才会交给消费线程进行消费。SQL 属性过滤功能介绍SQL 属性过滤是 RocketMQ 提供的高级消息过滤方式,通过生产者为消息设置的属性(Key)及属性值(Value)进行匹配。生产者在发送消息时可设置多个属性,消费者订阅时可设置S QL 语法的过滤表达式过滤多个属性。过滤语法1. 数值比较:>, >=, <, <=, BETWEEN, =2. 字符比较:=, <>, IN3. 判空运算:IS NULL or IS NOT NULL4. 逻辑运算:AND, OR, NOT使用方式1. 发送消息,设置属性Message message = provider.newMessageBuilder() .setTopic("TopicA") .setKeys("messageKey") //设置消息属性,用于消费端根据指定属性过滤消息。 .addProperty("Channel", "TaoBao") .addProperty("Price", "5999") .setBody("messageBody".getBytes()) .build();2. 订阅消息,匹配单个属性FilterExpression filterExpression = new FilterExpression("Channel='TaoBao'", FilterExpressionType.SQL92); pushConsumer.subscribe("TopicA", filterExpression);3. 订阅消息,匹配多个属性FilterExpression filterExpression = new FilterExpression("Channel='TaoBao' AND Price>5000", FilterExpressionType.SQL92); pushConsumer.subscribe("TopicA", filterExpression);4. 订阅消息,匹配所有属性FilterExpression filterExpression = new FilterExpression("True", FilterExpressionType.SQL92); pushConsumer.subscribe("TopicA", filterExpression);技术原理 由于 SQL 过滤需要将消息的属性和 SQL 表达式进行匹配,这会对服务端的内存和 CPU 增加很大的开销。为了降低这个开销,RocketMQ 采用了布隆过滤器进行优化。当 Broker 在收到消息后,会预先对所有的订阅者进行 SQL 匹配,并将匹配结果生成布隆过滤器的位图存储在 ConsumeQueueExt 索引扩展文件中。在消费时,Broker 就会使用使用这个过滤位图,通过布隆过滤器对消费者的 SQL 进行过滤,这可以避免消息在一定不匹配的时候,不需要去 CommitLog 中将消息的属性拉取到内存进行计算,可以有效地降低属性和 SQL 进行匹配的消息量,减少服务端的内存和 CPU 开销。整个 SQL 过滤的处理流程如下:消费者通过心跳上传订阅关系,Broker 判断如果是 SQL 过滤,就会通过布隆过滤器的算法,生成这个 SQL 对应的布隆过滤匹配参数; 生产者对消息设置上自己的业务属性,发送给我们的服务端 Broker; Broker 收到后将消息写入 CommitLog 中,然后通过异步线程将消息分发到 ConsumeQueue 索引文件中。在写入之前,会将这条消息的属性和当前所有订阅关系中 SQL 进行匹配,如果通过,则将 SQL 对应的布隆过滤匹配参数合并成一个完整的布隆过滤位图; 消费者消费消息的时候,Broker 会先获取预先生成的布隆过滤匹配参数,然后通过布隆过滤器对 ConsumeQueueExt 的布隆过滤位图和消费者的布隆过滤匹配参数进行匹配; 布隆过滤器返回匹配成功只能说明消息属性和 SQL 可能匹配,Broker 还需要从 CommitLog 中将消息属性取出来,再做一次和 SQL 的精确匹配,这个时候匹配成功才会将消息投递给消费者 差异及对比最佳实践主题划分及消息定义主题和消息背后的本质其实就是业务实体的属性、行为或状态发生了变化。只有发生了变化,生产者才会往主题里面发送消息,消费者才需要监听这些的消息,去完成自身的业务逻辑。那么如何做好主题划分和消息定义呢,我们以订单实体为例,来看看主题划分和消息定义的原则。主题划分的原则 1. 业务领域是否一致不同的业务领域背后有不同的业务实体,其属性、行为及状态的定义天差地别。比如商品和订单,他们属于两个完全独立且不同的领域,就不能定义成同一个主题。2. 业务场景是否一致同一个业务领域不同的业务场景或者技术场景,不能定义一个主题。如订单流程和订单缓存刷新都和订单有关系,但是订单缓存刷新可能需要被不同的流程触发,放在一起就会导致部分场景订单缓存不刷新的情况。3. 消息类型是否一致同一个业务领域和业务场景,对消息类型有不同需求,比如订单处理过程中,我们需要发送一个事务消息,同时也需要发送一个定时消息,那么这两个消息就不能共用一个主题。消息定义的原则 1. 无标签无属性对于业务实体极其简单的消息,是可以不需要定义标签和属性,比如 MySQLBinlog 的同步。所有的消费者都没有消息过滤需求的,也无需定义标签和属性。2. 如何定义标签标签过滤是 RocketMQ 中使用最简单,且过滤性能最好的一种过滤方式。为了发挥其巨大的优势,可以考虑优先使用。在使用时,我们需要确认这个字段在业务实体和业务流程中是否是唯一定义的,并且它是被绝大多数消费者作为过滤条件的,那么可以将它作为标签来定义。比如订单中有下单渠道和订单操作这两个字段,并且在单次消息发送过程中都是唯一定义,但是订单操作被绝大多数消费者应用为过滤条件,那么它最合适作为标签。3. 如何定义属性属性过滤的开销相对比较大,所以只有在标签过滤无法满足时,才推荐使用。比如标签已经被其他字段占用,或者过滤条件不可枚举,需要支持多属性复杂逻辑的过滤,就只能使用属性过滤了。保持订阅关系一致订阅关系一致是指同一个消费者组下面的所有的消费者所订阅的 Topic 和过滤表达式都必须完全一致。正如上图所示,一个消费者组包含两个消费者,他们同时订阅了 Topic-A 这个主题,但是消费者一订阅的是 Tag-A 这个标签的消息,消费者二订阅的是 Tag-B 这个标签的消息,那么他们两者的订阅关系就存在不一致。导致的问题:那么订阅关系不一致会导致什么问题呢?1. 频繁复杂均衡在 RocketMQ 实现中,消费者客户端默认每 30 秒向 Broker 发送一次心跳,这个过程会上传订阅关系,Broker 发现变化了就进行订阅关系覆盖,同时会触发客户端进行负载均衡。那么订阅关系不一致的两个客户端会交叉上传自己的订阅关系,从而导致客户端频繁进行负载均衡。2. 消费速率下降客户端触发了负载均衡,会导致消费者所持有的消费队列发生变化,出现间断性暂停消息拉取,导致整体消费速率下降,甚至出现消息积压。3. 消息重复消费客户端触发了负载均衡,会导致已经消费成功的消息因为消费队列发生变化而放弃向 Broker 提交消费位点。Broker 会认为这条消息没有消费成功而重新向消费者发起投递,从而导致消息重复消费。4. 消息未消费订阅关系的不一致,会有两种场景会导致消息未消费。第一种是消费者的订阅关系和 Broker 当前订阅关系不一致,导致消息在 Broker 服务端就被过滤了。第二种是消费者的订阅关系和 Broker 当前的虽然一致,但是 Broker 投递给了其他的消费者,被其他消费者本地过滤了。使用的建议在消息过滤使用中,有以下建议:1. 不要共用消费者组不同业务系统千万不要使用同一个消费者组订阅同一个主题的消息。一般不同业务系统由不同团队维护,很容易发生一个团队修改了订阅关系而没有通知到其他团队,从而导致订阅关系不一致的情况。2. 不频繁变更订阅关系频繁变更订阅关系这种情况比较少,但也存在部分用户实现在线规则或者动态参数来设置订阅关系。这有可能导致订阅关系发生变化,触发客户端负载均衡的情况。3. 变更做好风险评估由于业务的发展,需求的变更,订阅关系不可能一直不变,但是变更订阅关系过程中,需要考虑整体发布完成需要的总体时间,以及发布过程中订阅关系不一致而对业务可能带来的风险。4. 消费做好幂等处理不管是订阅关系不一致,还是客户端上下线,都会导致消息的重复投递,所以消息幂等处理永远是消息消费的黄金法则。在业务逻辑中,消费者需要保证对已经处理过的消息直接返回成功,避免二次消费对业务造成的损害,如果返回失败就会导致消息一直重复投递直到进死信。到此,本文关于消息过滤的分享就到此结束了,非常感谢大家能够花费宝贵的时间阅读,有不对的地方麻烦指正,感谢大家对 RocketMQ 的关注,希望大家能够多多参与社区的讨论和贡献。如果您对 RocketMQ 感兴趣,也欢迎您扫描下方二维码加入钉钉群一起沟通交流~点击此处,进入官网了解更多详情~
作者:Regan Yue本文选自“Serverless 函数计算征集令”活动什么是 ServerlessServerless 是一种基于云计算的开发方法,它让开发人员可以专注于编写代码来解决业务问题,而不是处理服务器问题。它是独一无二的,因为它支持 Auto Scaling,执行应用程序所需的计算能力是按需分配的。并且使用一种称为事件驱动函数的模型来确定这些需求的范围。这就是 Serverless 架构,也称为功能即服务 (FaaS)。部署、初步体验工作开通阿里云函数计算 FC,点击下方链接跟随提示即可开通。开通地址:https://fcnext.console.aliyun.com/overview通过模版创建应用绑定 Github,然后选择好角色,点击创建这样就部署成功了。访问域名即可:无论是网页调用还是脚本调用,调用速度都比较快!可以看到使用阿里云 Serverless Devs 部署基于 Serverless 图像预测案例是十分流畅的。下面是评分和点评:上手容易度:⭐⭐⭐⭐⭐服务监控功能:⭐⭐⭐⭐⭐部署速度:⭐⭐⭐⭐执行速度:⭐⭐⭐⭐案例资源丰富度:⭐⭐⭐总体评价:⭐⭐⭐⭐体验在线编辑、再次部署通过服务列表-》服务 png-compress 详情-》函数管理-》函数详情-》函数代码可以在线编辑函数,进行开发。我将说明删除后,再次部署:整个流程很流畅,不过不知道为什么应用那里部署历史没有变化,没有看到函数的部署历史。如果是这样的话,那么函数部署如何回滚?体验后我有几方面的建议和心得:在线编辑代码功能建议上线上传文件功能函数部署建议有历史部署功能,以便可以回滚。 通过使用阿里云 Serverless Devs 部署基于 Serverless 图像预测案例,体验了阿里云 Serverless 的部分主要功能,阿里云 Serverless 的功能强大、上手容易、性能也不弱,不过目前应用模板还不够丰富,大部分是环境类模板,这方面有待加强;此外阿里云每月有 100 万次函数调用免费额度、每月前 400,000(GB-秒)函数实例资源的免费使用量,这对开发者来说十分友好。
作者:十眠流量路由,顾名思义就是将具有某些属性特征的流量,路由到指定的目标。流量路由是流量治理中重要的一环,多个路由如同流水线一样,形成一条路由链,从所有的地址表中筛选出最终目的地址集合,再通过负载均衡策略选择访问的地址。开发者可以基于流量路由标准来实现各种场景,如灰度发布、金丝雀发布、容灾路由、标签路由等。直播课程观看:https://yqh.aliyun.com/live/detail/29692微服务治理与 OpenSergo随着微服务(MicroServices) 理念的兴起,让大规模、高并发、低延迟的分布式应用成为可能。但是微服务架构是一把双刃剑,随着微服务架构复杂化,在大规模之下,再小的问题都会牵一发而动全身,因此随着微服务架构增长,如果不对微服务进行恰当的治理,微服务架构带来的效率、稳定性问题很可能会远大于微服务本身带来的架构红利。可以说,现代微服务架构的四大件:服务提供者、服务消费者、注册配置中心,当然还有容易被大家忽视但又十分重要的一点,那就是微服务治理。微服务治理的使命就是对微服务体系中的各个组件与环节进行治理,可以说做好微服务治理那就是把微服务做稳做好的必不可少的一环。在企业内部,往往存在着不同语言、不同通信协议的微服务,这种异构化的架构会导致治理微服务的过程中,业务开发者、架构师无法用统一的方式来对所有服务进行治理管控,并且这类异构会衍生出更多的痛点:业内对服务治理的能力和边界没有明确的认识,每个企业所定义的服务治理概念不一致,造成很高的理解和沟通成本。 开源微服务框架众多,对于服务治理缺乏一些标准化的约定。例如,Spring Cloud 中定义的微服务接口和 Dubbo 中定义的接口就没有办法互通,通过 Dubbo 和 Istio 管理的微服务也没有办法进行统一治理。开发者无法通过统一的配置方式来对不同框架、不同语言的服务进行统一治理管控。 缺少真正面向业务、能够减轻认知负担的抽象和标准。开发者真正想要的可能是简单的、指定服务间的调用关系和配置规则。但现在对于业务开发者来说,不仅需要了解不同微服务框架的部署架构,也要了解不同服务治理方式的概念和能力区别,认知成本很大。 基于上面这些痛点,阿里巴巴在 2022 年 1 月开始和 bilibili、CloudWego 等厂商、社区讨论服务治理如何规范化和更加普及,从而共同发起了 OpenSergo 项目。OpenSergo 是开放通用的,覆盖微服务及上下游关联组件的微服务治理项目,从微服务的角度出发,涵盖流量治理、服务容错、服务元信息治理、安全治理等关键治理领域,提供一系列的治理能力与标准、生态适配与最佳实践,支持 Java, Go, Rust 等多语言生态。OpenSergo 的最大特点就是以统一的一套配置/DSL/协议定义服务治理规则,面向多语言异构化架构,做到全链路生态覆盖。对于开发者来说可以通过同一套 OpenSergo CRD 标准配置针对微服务架构涉及到的每一个组件进行统一的治理管控,而无需关注各框架、语言的差异点,降低异构化、全链路服务治理管控的复杂度。下面我们将从流量路由这个场景入手,从常见的微服务治理场景出发。先是根据流量路由的实践设计流量路由的 Spec,同时在 Spring Cloud Alibaba 中实践遵循 OpenSergo 标准的流量路由能力。流量路由流量路由,顾名思义就是将具有某些属性特征的流量,路由到指定的目标。流量路由是流量治理中重要的一环,我们可以基于流量路由标准来实现各种场景,如全链路灰度、标签路由、金丝雀发布等。标签路由标签路由是按照标签为维度对目标负载进行划分,符合条件的流量匹配至对应的目标,从而实现标签路由的能力。当然基于标签路由的能力,赋予标签各种含义我们就可以实现各种流量路由的场景化能力。金丝雀发布金丝雀发布是一种降低在生产中引入新软件版本的风险的技术,方法是在将更改推广到整个基础架构并使其可供所有人使用之前,缓慢地将更改推广到一小部分用户。金丝雀发布是一种在黑与白之间,能够平滑过渡的一种发布方式。让一部分用户继续用旧版本,一部分用户开始用新版本,如果用户对新版本没有什么反对意见,那么逐步扩大范围,把所有用户都迁移到新版本上面来。一直都有听说,安全生产三板斧的概念:可灰度、可观测、可回滚。那么灰度发布能力就是帮助企业软件做到快速迭代验证的必备能力。在 K8s 中金丝雀发布的最佳实践如下:第一步:新建灰度 Deployment,部署新版本的镜像,打上新版本的标签。第二步:配置针对新版本的标签路由规则。第三步:验证成功,扩大灰度比例。第四步:若验证成功,将稳定版本的应用更新成最新镜像;若验证失败,把灰度的 Deployment 副本数调整到 0 或删除该 Deployment。全链路灰度全链路灰度发布就是通过线上多个应用部署灰度版本,灰度流量全部进入灰度版本,正常流量进入生产版本。灰度版本只针对灰度流量验证,有效减少风险。我们可以通过流量路由结合流量染色可以实现全链路的流量灰度能力。流量路由标准化业界微服务治理存在概念不统一、配置形式不统一、能力不统一、多框架统一管控较为复杂等问题。比如我们希望实现流量路由的能力,在 Spring Cloud 中可能需要通过 Spring Cloud 动态规则的方式进行配置,在 istio 中可能又是另一套配置方式,在其它组件上可能又是不同的配置。不同框架治理配置方式的不一致使得微服务统一治理管控的复杂度相当高。为此我们需要通过 OpenSergo 实现一套标准化的流量路由能力与实践,这样在任 OpenSergo 生态中的组件上需通过配置 OpenSergo TrafficRouter 规则,即可实现一致的流量路由能力。我们在实践了许多流量路由的场景后,将流量路由规则进行了如下的设计与抽象。OpenSergo 的流量路由规则 (v1alpha1) 主要分为如下:Workload 集合的抽象 (VirtualWorkloads):将某一组 VirtualWorkload(如 Kubernetes Deployment, Statefulset 或者一组 pod,或某个 JVM 进程,甚至是一组 DB 实例)按照一定的特征进行分类。 流量标签规则 (RouterRule):将特定特征的流量映射至特定特征所对应的 VirtualWorkloads 上。 路由链规则(RouterChain)将特定的 RouterRule 跟 VirtualWorkloads按照一定逻辑排列组合成 pipeline。 Workload 集合的抽象 (VirtualWorkloads)VirtualWorkloads 虚拟工作负载集合的抽象即 VirtualWorkload 集合,其中会将 VirtualWorkload 按照一定的特征进行分类。VirtualWorkload虚拟工作负载即 workload 集合的抽象,将一定属性特征的 workload 集合划分成一个 VirtualWorkload,其中 VirtualWorkload 可以是目标 service 集合也可以是 deployment,甚至可以是 database 的实例、库、表集合。对于通用的 workload 场景,我们可以利用 VirtualWorkloads CRD 进行描述。特别地,对于 Kubernetes workload,我们可以通过直接在 workload 上打 label 的方式进行特征标记,如在 Deployment 上打上 traffic.opensergo.io/label: gray 标签代表当前 Deployment 的标签特征为 gray。一个标准的 workloads 描述应该类似于:apiVersion: traffic.opensergo.io/v1alpha1 kind: VirtualWorkloads metadata: name: tag-rule spec: selector: app: my-app virtualWorkload: - name: my-app-gray target: my-app-gray-deployment type: deployment selector: tag: gray流量路由规则 (RouterRule)流量路由规则 (RouterRule) 将特定特征的流量映射至特定特征所对应的 VirtualWorkloads 上。假设现在需要将内部测试用户灰度到新版主页,测试用户 uid=12345,UID 位于 X-User-Id header 中,不符合条件的外部用户流量访问原版主页。那么只需要配置如下 CRD 即可:apiVersion: traffic.opensergo.io/v1alpha1 kind: RouterRule metadata: name: tag-traffic-router-rule spec: selector: app: my-app http: - name: my-traffic-router-http-rule rule: match: header: X-User-Id: # 参数名 exact: 12345 # 参数值 uri: exact: "/index" targets: - workloads: my-app-worksloads name: gray target: workloads: my-app-worksloads name: base通过上述配置,我们可以将 path 为 /index,且 uid header 为 12345 的 HTTP 流量为灰度流量,访问灰度版本的新版主页。标签路由场景的流量路由配置 假设我们希望 Header x-user-id 为 123 的流量访问 spring-cloud-a 的具备 gray 标签的实例。其中 spring-cloud-a 的标签情况如下:那么我们需要配置对应的 TrafficRouterRule 配置如下:apiVersion: traffic.opensergo.io/v1alpha1 kind: TrafficRouterRule metadata: name: tag-traffic-router-rule spec: selector: app: spring-cloud-a http: - name: my-traffic-router-http-rule rule: match: headers: X-User-Id: # 参数名 regex: "^(?!(?:\d{1,2}|100)$)[0-9]\d+$" # 参数值 queryParams: name: exact: xiaoming uri: prefix: "/" targets: - workloads: spring-cloud-a-worksloads name: gray target: - workloads: spring-cloud-a-worksloads name: base对应的 VirtualWorkloads 配置如下:apiVersion: traffic.opensergo.io/v1alpha1 kind: VirtualWorkloads metadata: name: spring-cloud-a-worksloads spec: selector: app: spring-cloud-a virtualWorkload: - name: gray target: spring-cloud-a type: deployment selector: tag: gray loadbalance: random - name: base target: spring-cloud-a type: deployment selector: tag: _base loadbalance: random金丝雀发布场景的流量路由配置我们配置了如下的金丝雀规则,希望 10% 的流量访问 spring-cloud-a 中具有 gray 标签的实例:对应的 TrafficRouterRule 配置如下:apiVersion: traffic.opensergo.io/v1alpha1 kind: TrafficRouterRule metadata: name: tag-traffic-router-rule spec: selector: app: spring-cloud-a http: - name: my-traffic-router-http-rule rule: targets: - workloads: spring-cloud-a-worksloads name: gray weight: 10 - workloads: spring-cloud-a-worksloads name: base weight: 90 target: - workloads: spring-cloud-a-worksloads name: base流量路由 Demo 演示Spring Cloud Alibaba Consumer 应用中增加 OpenSergo 的依赖,并启动 Spring Cloud Alibaba 流量路由的 Demo<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>opensergo-resource-transform</artifactId> <version>2.2.9-SNAPSHOT</version> </dependency>配置 OpenSergo 流量路由启动 OpenSergo 控制面下发 TrafficRouterRule CRD 规则 假设现在需要将灰度流量路由到 v2 版本,灰度请求符合如下条件 header:name=xiaoming,Params:location=shenzhen 的请求流量去往灰度 v2 版本,不符合条件的流量访问 v1 版本。那么只需要配置如下 CRD 即可:apiVersion: fault-tolerance.opensergo.io/v1alpha1 kind: TrafficRouterRule metadata: name: http-foo-rule labels: app: foo-app spec: http: match: headers: name: 'xiaoming' queryParams: location: 'shenzhen' targets: - name: "v2" selectors: version: "v2" target: name: "v1" selectors: version: "v1"结果验证当我们执行 curl http://127.0.0.1:18083/router-testNacosRegistration{nacosDiscoveryProperties=NacosDiscoveryProperties{serverAddr='127.0.0.1:8848', endpoint='', namespace='', watchDelay=30000, logName='', service='service-provider', weight=1.0, clusterName='DEFAULT', group='DEFAULT_GROUP', namingLoadCacheAtStart='false', metadata={preserved.register.source=SPRING_CLOUD, version=v1}, registerEnabled=true, ip='192.168.1.4', networkInterface='', port=18082, secure=false, accessKey='', secretKey='', heartBeatInterval=null, heartBeatTimeout=null, ipDeleteTimeout=null, failFast=true}}其中返回默认 v1 版本的实例当我们执行curl -H 'name:xiaoming' http://127.0.0.1:18083/router-test\?location\=shenzhenNacosRegistration{nacosDiscoveryProperties=NacosDiscoveryProperties{serverAddr='127.0.0.1:8848', endpoint='', namespace='', watchDelay=30000, logName='', service='service-provider', weight=1.0, clusterName='DEFAULT', group='DEFAULT_GROUP', namingLoadCacheAtStart='false', metadata={preserved.register.source=SPRING_CLOUD, version=v2}, registerEnabled=true, ip='192.168.1.4', networkInterface='', port=18081, secure=false, accessKey='', secretKey='', heartBeatInterval=null, heartBeatTimeout=null, ipDeleteTimeout=null, failFast=true}}其中符合流量匹配的条件,返回默认 v2 版本的实例。总结与展望流量路由是微服务流量治理中的重要的一环,当然 MSE 还提供更广范围、更多场景的微服务治理能力,包括全链路灰度、无损上下线、微服务数据库治理、日志治理等一系列的微服务治理能力。服务治理是微服务改造深入到一定阶段之后的必经之路,是将微服务做稳做好的关键。同时我们也在与 CloudWeGo、Kratos、Spring Cloud Alibaba、Dubbo、ShardingSphere 等社区共同建设 OpenSergo 微服务治理标准,将企业与社区中微服务治理的场景与最佳实践共同提取成标准规范,也欢迎更多社区与企业一起参与 OpenSergo 微服务治理标准的共建。欢迎大家加入 OpenSergo 社区交流群(钉钉群)进行讨论:34826335MSE 云原生网关、注册配置专业版预付费首购享 8 折,首购 1 年及以上享 7 折。点击此处,即享优惠!
作者:艾阳坤RocketMQ 5.0 SDK 采用了全新的 API,使用 gRPC 作为通信层的实现,并在可观测性上做了很大幅度的提升。全新统一的 API此处的 API 并不单单只是接口上的定义,同时也规定了各个接口不同的方法和行为,明确了整个消息模型。RocketMQ 过去的 API 从第一版开始,至今已经过了很长时间,长期依赖是一个缺乏变革的状态,对于一些中途打算废弃或者变更的 API 也没有进行后续的迭代。此外,接口的定义也不够清晰。因此,RocketMQ 希望在 5.0 中能够建立一个统一的规范,精简整个 API,通过引入 builder 模式来引入更多的不变性,同时做好异常管理,给开发者和用户一个更加清爽的面貌。目前 C++ 和 Java 已经进行了 5.0 API 的定义与实现,更多语言的支持也陆续在路上了。我们也欢迎更多的开发者可以参与到社区的工作中来。这里给出 5.0 客户端的仓库链接:https://github.com/apache/rocketmq-clients除了在上述接口上做的一些修改之外, RocketMQ 5.0 还规定了四种新的不同的客户端类型,即 Producer/Push Consumer/Simple Consumer/Pull Consumer。其中 Pull Consumer 还在开发中;Producer 主要还是做了接口裁剪,规范了异常管理。在功能上其实并没有做一些颠覆性的改变。Push Consumer 也是比较类似的;Simple consumer 将更多的权利将下发给用户,是一种用户可以主动控制消息接收与处理过程的消费者,特别的,5.0 的 SDK 中,Push Consumer 和 Simple Consumer 都采用 RocketMQ 的 pop 机制进行实现,一些社区的同学可能已经熟悉了。如果用户并不一定想控制或者关心整个消息的接收过程,只在乎消息的消费过程的话,这个时候 Push Consumer 可能是一个更好的选择。RocketMQ 5.0 定义了四种不同的消息类型。过去的开源版本中其实我们并没有去突出消息类型这样一个概念,后续出于维护及运维方面的需要以及模型定义的完备,才让今天的 5.0 有了消息类型的这样一个概念。1、NORMAL:普通消息。2、FIFO:满足先入先出的语义。用户可以通过定义 message group 来控制消息间的消费顺序。例如图中的 fruit 这个 topic 下,可以定义不同的 message group,在 apple 这个 message group 下,会按照发送顺序决定消息被消费的顺序,并且不同的 message group 之间不会互相干扰。3、TRANSACTIONAL:可以将一条或多条消息包成一个事务,最终用户可以根据自己的业务结果选择提交或者回滚。4、DELAY:用户可以自主地设置消息的定时时间,相比之前开源版本仅允许用户设置定时/延迟级别,5.0 的实现中还讲允许用户设置更精确的时间戳。以上四种消息是互斥的,我们会在 topic 的元数据去标识它的类型。实际在消息发送的时候如果如果出现了尝试发送的消息类型与 topic 类型不匹配的情况,也会做一些限制。实现RocketMQ 5.0 在客户端的启动过程中提前进行了更多的准备工作。比如用户提前设置要发送消息的 topic 时,Producer 会在启动过程中尝试获取对应 topic 的路由。在过去的客户端实现中,在针对于某个 topic 第一次发送消息时,需要先获取路由,这里就会有一个类似冷启动的过程。提前获取 Topic 的路由信息有两点好处:1. 不阻塞后面的发送,让消息的发送仅仅触发发送这一个动作。2. 错误前置,比如用户要往一个不存在 Topic 发送消息时,因为路由的获取参与到整个客户端的启动过程,获取路由不成功,那整个客户端启动可能就会失败,用户也是拿不到对应的 Producer 对象的。类似的,Consumer 的启动也会有这样的一个过程。除此之外,我们在客户端和服务端之间增加了一个 Telemetry 的部分,它会在客户端和服务端之间建立起了一个进行双向数据通讯的通道,客户端和服务端会在这个过程中沟通配置,比如服务端可以实现对客户端配置的下发,更好地管理客户端。此外,Telemetry 也可以将本地配置主动上报给服务端,让服务端也可以对客户端的设置有更好的了解。Telemetry 通道也会在客户端启动时尝试建立,如果这个通道没有建立成功,也会影响客户端的启动。总的来说,客户端的启动过程会尽可能将所有准备工作做好。同时在客户端和服务端之间建立 Telemetry 这样一个通讯通道。客户端内部存在一些周期性的任务,比如路由的定时更新以及客户端往服务端发送心跳等。对于上文中提到的 Telemetry 过程中,客户端的配置上报也是周期性的。Producer 在 RocketMQ 5.0 中的具体工作流程消息在发送时,会检查是否已经获取对应 topic 的路由信息。如果已经获取,则尝试在路由中选取队列,随即查看要发送的消息的类型是否与 topic 类型匹配,如果匹配,则进行消息发送。如果发送成功,则返回;否则,判断当前重试次数是否超出用户设置的上限,如果超出,则返回失败;否则轮转到下一个队列,然后对新的队列进行重试直到消费次数超出上线。而如果启动过程中没有提前获取路由,那么消息发送时依然会先尝试获取路由,然后再进行下一步操作。另外一点相对于老客户端较大的改变在于,客户端从底层 RPC 交互到上层的业务逻辑全部采用异步实现。Producer 依然会提供一个同步发送接口和异步发送接口,但同步的方法也是使用异步来实现,整个逻辑非常统一和清爽。Push Consumer 分为两部分,消息的接收和消费。消息接收流程为:客户端需要不断地从服务端拉取消息,并将消息缓存。Push Consumer 会将消息先缓存到客户端的本地,再进行消费,因此它会判断客户端本地的 Cache 是否已满,如果已满,则隔一段时间再判断,直到消息被客户端消费,Cache 尚有余量时再进行消息拉取。为了避免出现一些内存问题,Cache 的大小也是被严格限制的。消息消费过程分为两个类型,顺序类型和非顺序类型。其中非顺序类型即并发消费。消费者会先从 Cache 中获取消息,然后尝试消费消息,消费后再将消息从 Cache 中移除。消息消费成功时,会尝试将消息 ACK ,消费流程结束;如果消费失败,则尝试修改消息的可见时间,即决定下一次什么时候可见。顺序消费指对于同一个 Group 的消息,最终消费时一定是前一条消息被消费过并且得到确认后,后面的消息才能够继续消费。而消费过程与非顺序消费类似,首先尝试从 Cache 中拉取消息,如果消费成功,则将消息 ACK。ACK 成功后,将其从 Cache 中移除。特别地,如果消费失败,会 suspend 一段时间,然后继续尝试对消息进行消费。此时会判断消费次数是否超限,如果超限,则会尝试将消息放入死信队列中。相对于非顺序消费,顺序消费更复杂,因为其需要保证前一个消息消费成功后才能对后面的消息进行消费。顺序消费的消费逻辑是基于 message group 隔离的。message group 会在发送时做哈希,从而保证 message group 的消息最终会落在一个队列上,顺序消费模式本质上保证队列内部消费的顺序。此外,因为不同 message group 的顺序消息最终可能会映射到同一个队列上,这可能会导致不同的 message group 之间的消费形成阻塞,因此服务端未来会实现一个虚拟队列,让不同的 message group 映射到客户端的虚拟队列,保证他们之间没有任何阻塞,从而加速数据消息的消费过程。对于 Simple Consumer,用户可以主动控制消息接收和确认的流程。比如用户收到消息后,可以根据业务决定是否过一段时间再消费该消息,或者不需要再收到该消息。消费成功后将消息 ACK 掉,如果失败则主动修改可见时间,选择该消息下一次什么时候可见,即由用户自发地控制整个过程。可观测性Shaded Logback因为历史原因,RocketMQ 的老客户端并不是面向 SLF4J 进行编程的,而是面向 logback 的。这么做的目的其实是为了方便快捷地获取日志,不需要让用户自己去手动配置。RocketMQ 中专门有一个 logging 模块是负责日志部分的,像用户自己使用了 logback ,RocketMQ SDK 如果也直接去使用 logback,两者就会产生各种各样的冲突,这个 logging 模块就是用来保证这一层隔离性的。但是 logging 模块本身的实现并不是很优雅,也带来了一定的维护成本。因此我们采用了 shade logback 的方式来达到上文提到的隔离性。shaded logback 不仅能够避免用户的 logback 与 RocketMQ 自己的 logback 冲突,还能保持较好的可维护性,将来要想在日志上去做一些修改,也来得容易的多。具体来说,用户的 logback 会采用 logback.xml 的配置文件,通过 shade logback, RocketMQ 5.0 的客户端会使用 rocketmq.logback.xml 的配置文件,因此在配置部分就已经完全隔离了,同时在 shade 的过程中,还对原生 logback 中使用到的一些环境变量和系统变量也进行了修改,这样就保证了两者的彻底隔离。另外,使用 shadeed logback 之后,RocketMQ 5.0 客户端中的日志部分就全都是面向 SLF4J 来进行编程的了,这样一来,如果我们未来想让用户自己去完全控制日志的话,提供一个去除 logback 的 SDK 就可以了,非常方便。Trace5.0 的消息轨迹基于 OpenTelemetry 模型进行定义与实现,消息发送或接收消息的流程被定义为一个个独立的 span ,这一套 span 规范参照了 OpenTelemetry 关于 Messaging 的定义。图中这里 Process P 表示 Producer ,Process C 表示 Consumer。消息的全生命周期,从发送到接收到消费,就可以具象化为这样一个个的 span。比如,针对 Push Consumer 而言,先会有一个 receive 的 span 来表示从服务端获取消息的过程,收到消息后到会先等待消息被处理,这个也就是 await span 表示的过程,消息被处理则对应图中的 process span,消息消费结束之后,向服务端反馈消息处理结果也会有专门的 span 进行描述。我们通过 parent 和 link 来讲所有的这些 span 关联起来,这样通过一条消息的任意一个 span,就可以获得这条消息全生命周期的所有 span。不仅如此,用户还将允许可以设置一个 span context 与自己的业务链路进行关联,将 RocketMQ 5.0 的消息轨迹本身嵌入进自己的全链路可观测系统中去。MetricsTracing 相对来说成本是比较高的,因为一条消息从发送到接收,可能会有很多流程,这就伴随着很多的 span,这就导致相对来说,tracing 数据的存储查询成本相对来说比较高。我们希望诊断整个 SDK 的健康状况,同时又不希望收集太多的 tracing 信息提高成本,此时提供一份 metrics 数据就能比较好地满足我们的需求。在 SDK 的 metrics 中我们新增了诸多指标,包括不限于 Producer 中消息发送延时,Push Consumer 中消息的消费耗时和消息缓存量,可以帮助用户和运维者更快更好地发现异常。5.0 中 SDK 的 metrics 也是基于 OpenTelemetry 进行实现的。以 Java程序为例,OpenTelemetry 对于 Java 的实现本身提供了一个 agent,agent 在运行时会打点采集 SDK 的一些 tracing/metrics 信息,并将它上报到对应的 metric collector 中,这种通过 agent 来降低无侵入式数据采集的方式被称之为 automatic instrumentation,而手动在代码中实现打点采集的方式则被称之 manual instrumentation。对于 metrics 我们目前还是采用 manual instrumentation 的方式来进行数据的采集和上报的。服务端会告知客户端对应的 collector 的地址,然后客户端将 Metrics 数据上传到对应的 collector 当中去。作者介绍:艾阳坤,Apache RocketMQ 5.0 Java SDK 作者,CNCF Envoy Contributor,CNCF OpenTelemetry Contributor,阿里云智能高级开发工程师。加入 Apache RocketMQ 社区十年铸剑,Apache RocketMQ 的成长离不开全球接近 500 位开发者的积极参与贡献,相信在下个版本你就是 Apache RocketMQ 的贡献者,在社区不仅可以结识社区大牛,提升技术水平,也可以提升个人影响力,促进自身成长。社区 5.0 版本正在进行着如火如荼的开发,另外还有接近 30 个 SIG(兴趣小组)等你加入,欢迎立志打造世界级分布式系统的同学加入社区,添加社区开发者微信:rocketmq666 即可进群,参与贡献,打造下一代消息、事件、流融合处理平台。欢迎您扫描下方二维码加入钉钉群一起沟通交流~点击此处,进入官网了解更多详情~
近日,上海鼎茂信息技术有限公司(以下简称“鼎茂科技”)的鼎茂智能运维 AIOps 平台软件(V3.0)与阿里云计算有限公司(以下简称“阿里云”)的阿里云可观测套件 ACOS 经过严格测试程序,完成了首批的产品生态集成认证测试。作为入选阿里云首期云原生加速器的企业,鼎茂科技通过云原生加速器项目携手阿里云共建更加丰富的云原生产业生态圈,加速云原生落地。此前,阿里云首次提出了“被集成”战略:将行业解决方案的搭建、实施、复制交由合作伙伴,阿里云只承担基础设施(IaaS)、技术中间件(PaaS)、数据平台(DaaS)层面的产品技术。“被集成”是阿里云对业务边界进行认真思考后作出的一个重要转变,标志着阿里云生态对合作伙伴的全面开放。阿里云产品生态集成认证是面向阿里云合作伙伴自有产品、解决方案与阿里云相关产品的兼容性、可用性的技术能力认证。获得此认证,证明了鼎茂科技的技术能力、产品应用水平已满足阿里云相关产品的适配性要求。鼎茂科技是一家企业级数智运营科技公司,总部位于上海,同时拥有杭州算法中心和北京、成都分公司,以及广州、深圳、南京等地的专业技术团队。通过自主研发的 ARCANA 数智平台和场景化智能应用,为企业提供统一的数据运营新方法,实现全域 AIOps 智能运维。鼎茂科技以平台+算法为技术核心,创新突破“AI 能力闭环”和“运维场景闭环”,完成了平台级数智底座+全矩阵智能应用的产品体系建设。与多家人工智能科研院校深度合作,强化自主 AIOps 技术研发与场景泛化应用的能力,帮助企业应对快速变化和不断成长的 IT 环境,实现实时精准的洞察和全局化数智运营。阿里云可观测套件能够实时高效地接入用户环境中的多种数据源,收集用户环境中的 IT 和业务数据,进行统一的管理和存储,通过便捷和强大的建模分析工具,将数据进行关联分析、业务建模,结果实时输出给可视化、告警以及其他应用,具备统一监控、全景监控和关联分析等特点。阿里云拥有丰富的云原生产品家族,有超过 300 款的产品,近千个技术解决方案。本次鼎茂科技获得阿里云产品集成认证,代表了鼎茂科技在生态合作建设上迈过了一个新里程碑。鼎茂科技一直以生态伙伴的身份与阿里云保持着深度合作。未来,借助阿里云的“被集成”生态战略与生态集成技术的全面开放,双方的紧密合作将进入新的阶段,共同为中国数千万家企业提供数字化转型服务。
作者:安可Serverless 简介Serverless,中文意思是 “无服务器”,所谓的无服务器并非是说不需要依靠服务器等资源,而是说开发者再也不用过多考虑服务器的问题,可以更专注在产品代码上,同时计算资源也开始作为服务出现,而不是作为服务器的概念出现。Serverless 架构主要包含两部分:BaaS 和 FaaS,通常位于云端,使用时不需要关注最底层的服务器。BaaS(后端即服务:Backend as a Service)包括对象存储、云数据库、API 网关、消息推送等。FaaS(函数即服务:Functions as a Service)对计算能力进行了抽象,可以在无需管理服务器的情况下响应事件。Serverless 三大应用场景场景一:事件触发场景,有事件触发时才会执行。场景二:流量突发场景,遇到突发大流量情况时,Serverless 架构下按需加载,弹性伸缩,节省资源,负载均衡。场景三:大数据处理场景,用户只需要上传核心代码到函数计算,就可以快速完成整个工作。Serverless 的优势传统架构下,面对大流量场景,需要增加机器或者对机器升级,运维较为困难。面对高峰和低谷,无法做到按需使用,成本较高。Serverless 架构下,开发者只需专注代码开发,无需在各个云资源控制台手动开通服务和配置管理,并能够根据业务请求自动进行弹性伸缩;支持用户按需付费,成本较低;开发周期快,很大程度上提升了开发、部署的效率。具体可以查看阿里云相关文档:https://developer.aliyun.com/group/serverlessPython 实现发送邮件演示视频:https://developer.aliyun.com/live/249772import requests import yagmail # 此模块用于发邮件 import schedule # 此模块用于计划任务 from bs4 import BeautifulSoup import re ran = 0 url = 'https://tianqi.2345.com/cixian1d/70177.htm' # 定义天气预报的url loveurl = 'https://www.guaze.com/juzi/23389.html' # 定义情话的url def email(): global ran # 将ran变量声明为全局变量 web = requests.get(url) # print(web.text) page = BeautifulSoup(web.text,"html.parser") # print(ran) # print(love[ran]) weather = page.find("div",class_="real-today") # print(weather.text) web2 = requests.get(loveurl) web2.encoding = 'gb2312' page = BeautifulSoup(web2.text, "html.parser") div = page.find('div', class_="content") div = str(div.text) # print(div) grep = re.compile(r"\d+、(.*)") content = grep.findall(div) # print(content) # email函数内的内容是爬取天气和情话的,具体的地址天气你可以更换url yag = yagmail.SMTP( host='smtp.qq.com', user='xxxxxxx@qq.com', # 如过用的是qq邮箱就写smtp.qq.com,如果是163就写smtp.163.com password='xhaztrwpjffpbdhh', smtp_ssl=True # 授权码在qq邮箱里开启smtp就会生成一个 ) weather = [weather.text,"每日情话:",content[ran], # 定义发送内容 yagmail.inline(r"/.love.jpg") # 附件图片,不发图片可以删掉 ] yag.send( to=['xxxxxxxxx@qq.com'], subject='早鸭', # 邮件主题 contents=weather # 发送的内容为上面定义的weather,其中weather.text是天气预报,content[ran]是情话 ) print("发送完成") ran += 1 schedule.every().day.at("05:21").do(email) # 每天5点20分执行函数email0 #schedule.every(10).seconds.do(email) #每10秒执行一下函数email的内容,我这里用于测试 while True: schedule.run_pending(部署到阿里云 Serverless,实现自动发送1. 登录到阿里云首页2. 选择产品->弹性计算->Serverless->函数计算3.进入控制台->服务及函数->创建函数4.上传代码->上传文件夹->选择文件夹->保存并部署5.函数配置->编辑环境信息->修改函数入口6.添加触发器,实现每日定时发送触发器管理->创建触发器->定时触发器->填写名称和指定时间7. 导入依赖并部署先在终端执行以下三条命令,导入项目所需要的依赖:pip3 install yagmail -t . pip3 install schedule -t . pip3 install bs4 -t .点击右上角保存并部署:最终效果展示点击左上角测试函数,然后通过实时日志查看运行结果:总结这次实战是对 Serverless 的一次深刻的理解,收获技术的同时也提升了自己的学习能力。由于目前正在准备考研,就好久没有更新关于自学技术的文章,这回借着阿里云官方评测活动也去学一学火热的 Serverless 无服务架构的技术和思想,在这里分享这个当下流行的技术,然后结合着一些个人浅显的探索,希望能和大佬们共同学习成长!戳此处,立即查看原文!
与其说 Serverless 架构是一个新的概念,不如说它是一种全新的思路,一种新的编程范式。但是原生的 Serverless 开发框架却非常少。以 Web 框架为例,目前主流的 Web 框架“均不支持 Serverless 模式部署”,因此我们一方面要尝试接触 Serverless,一方面又没办法完全放弃传统框架,所以如何将传统框架更简单、更快速、更科学地部署到 Serverless 架构是一个值得探讨的问题。请求集成方案请求集成方案实际上就是把真实的 API 网关请求直接透传给 FaaS 平台,而不在中途增加任何转换逻辑。以阿里云函数计算的 HTTP 函数为例,当想要把传统框架(例如 Django、Flask、Express、Next.js 等)部署到阿里云函数计算平台,并且体验Serverless架构带来的按量付费、弹性伸缩等红利时,得益于阿里云函数计算的 HTTP 函数和 HTTP 触发器,使用者不仅可以快速、简单地将框架部署到阿里云函数计算平台,还可以获得和传统开发一样的体验。例如以 Python 的 Bottle 框架开发一个 Bottle 项目:# index.py import bottle @bottle.route('/hello/<name>') def index(name): return "Hello world" if __name__ == '__main__': bottle.run(host='localhost', port=8080, debug=True)之后,可以直接在本地进行调试。当想要把该项目部署到阿里云函数计算平台时,只需要增加一个 default_app 的对象即可:app = bottle.default_app()整个项目的代码如下所示:# index.py import bottle @bottle.route('/hello/<name>') def index(name): return "Hello world" app = bottle.default_app() if __name__ == '__main__': bottle.run(host='localhost', port=8080, debug=True)若在阿里云函数计算平台创建函数,将入口函数设置为 index.app 即可。除了 Bottle 框架之外,其他 Web 框架的操作方法是类似的,再以 Flask 为例:# index.py from flask import Flask app = Flask(__name__) @app.route('/') def hello_world(): return 'Hello, World!' if __name__ == '__main__': app.run( host="0.0.0.0", port=int("8001") )在创建函数的时候设置入口函数为 index.app,就可以保证该 Flask 项目运行在函数计算平台上。当然,除了使用已有的语言化 Runtime(指具体语言的运行时,例如 Python3 运行时、Node. js12 运行时),我们还可以考虑使用 Custom Runtime 和 Custom Container 来实现,例如,一个 Web 项目完成之后,可以编写一个 Bootstrap 文件(在 Bootstrap 文件中写一些启动命令)。例如要启动一个 Express 项目,把 Express 项目准备完成之后,可以直接创建 Bootstrap 文件,并将启动命令配置到该文件中:#!/usr/bin/env bash export PORT=9000 npm run star阿里云函数计算还提供了更简单的 Web 框架迁移方案。如图所示是阿里云函数计算页面传统 Web 框架迁移功能示例。阿里云函数计算页面传统 Web 框架迁移功能选择对应的环境之后,只需要上传代码,做好简单的配置,即可让传统的 Web 框架迁移至阿里云函数计算平台。如果通过开发者工具进行部署,以 Serverless Devs 为例,首先创建 index.py:# -*- coding: utf-8 -*- from bottle import route, run @route('/') def hello(): return "Hello World!" run(host='0.0.0.0', debug=False, port=9000) 然后编写资源和行为描述文件: edition: 1.0.0 name: framework #项目名称 access: "default" #密钥别名 services: framework: #业务名称/模块名称 component: fc #组件名称 actions: pre-deploy: #在部署之前运行 - run: pip3 install -r requirements.txt -t . #要运行的命令行 path: ./code #命令行运行的路径 props: #组件的属性值 region: cn-beijing service: name: web-framework description: 'Serverless Devs Web Framework Service' function: name: bottle description: 'Serverless Devs Web Framework Bottle Function' codeUri: './code' runtime: python3 handler: index.app timeout: 60 triggers: - name: httpTrigger type: http config: authType: anonymous methods: - GET customDomains: - domainName: auto protocol: HTTP routeConfigs: - path: '/*' 同时,提供对应的Bootstrap文件,即启动文件: #!/bin/bash python3 index.py完成之后,执行 deploy 指令进行部署:s deploy部署结果如图所示。Serverless Devs 部署 Bottle 框架过程根据返回的网址,可以看到部署结果预览,如下图所示。Serverless Devs 部署结果预览通过 Serverless Devs 开发者工具,我们不仅可以简单地进行传统 Web 框架的部署,还可以快速在 Serverless 架构下进行传统 Web 框架的初始化。以 Express 项目为例,只需要通过 Serverless Devs 开发者工具执行如下代码即可进行 Express.js 项目的初始化。s init start-express初始化的过程如图所示。此时,只需要进入该项目执行如下代码即可快速进行项目的部署。s deploy通过 Serverless Devs 初始化 Express 项目部署结果如图所示。打开系统分配的地址,可以看到通过 Serverless Devs 开发者工具初始化的 Express 项目,效果展示如下图所示。Express 项目完成效果展示当然,目前 Serverless Devs 开发者工具不仅支持 Express 项目的快速初始化(见表),还支持包括 Django、Flask、SpringBoot 等数十个传统框架的快速创建与部署。Serverless Devs 支持快速创建和部署的传统框架综上所述,通过阿里云函数计算进行传统 Web 框架的部署和迁移是很方便的,并且得益于 HTTP 函数与 HTTP 触发器,整个过程侵入性非常低。当然,将传统 Web 框架部署到阿里云上的可选方案也比较多。编程语言化的 Runtime:只需要写好函数入口即可。Custom Runtime:只需要写好 Bootstrap 即可。Custom Container:直接按照规范上传镜像文件即可。 部署途径也是多种多样的,具体如下。直接在控制台创建函数。在应用中心处创建 Web 应用。利用开发者工具。其他方案相对于阿里云的 HTTP 函数以及 HTTP 触发器,其他 FaaS 平台则需要借助 API 网关以及一个转换层来实现传统 Web 框架到 FaaS 平台的部署。如图所示,以 Python Web 框架为例,在通常情况下,使用 Flask 等框架时实际上要通过 Web Server 才能进入下一个环节,而云函数是一个函数,本不需要启动 Web Server,所以可以直接调用 wsgi_app 方法。传统 WSGI Web Server 工作原理示例这里的 environ 就是对 event/context 等处理后的对象,也就是所说的转换层要做的工作;start_response 可以认为是一种特殊的数据结构,例如 response 结构形态等。当然,转换工作在某些情况下还是比较麻烦的,所以很多时候我们可以借助常见的开发者工具进行传统 Web 框架的部署,例如借助开源的开发者工具 Serverless Devs、Serverless Framework 等。作者介绍刘宇,阿里云 Serverless 产品经理田初东,蚂蚁集团算法工程师卢萌凯,阿里云 Serverless 高级解决方案架构师王仁达,阿里云 Serverless 工具链技术负责人点击此处,直达阿里云函数计算 FC!
作者:王夕宁服务网格作为一种用来管理应用服务通信的基础核心技术,为应用服务间的调用带来了安全、可靠、快速、应用无感知的流量路由、安全、可观测能力。什么是服务网格技术以 Istio 为代表的 Service Mesh 技术已经存在四五年的时间了,阿里云也是第一批支持 Service Mesh 云服务的厂商。在 Service Mesh 技术中,通过把服务治理的能力进行 Sidecar 化,实现与应用程序本身的解耦。这些若干个 Sidecar 代理就形成了一个网状的数据平面,通过该数据平面可以处理和观察所有应用服务间的流量。负责数据平面如何执行的管理组件称为控制平面,是服务网格的大脑,它为网格使用人员提供公开 API,以便更容易地操纵网络行为。通过 Service Mesh,Dev/Ops/SRE 将以统一的、声明的方式解决应用服务管理问题。服务网格一种应用感知的云原生基础设施我们认为服务网格是一种应用感知的云原生基础设施。它不仅仅是服务治理,而且包括了其他几个维度的云原生应用感知的特征与能力。我们把它分为了 5 个部分,分别是:云原生应用网络云原生应用治理云原生零信任安全云原生可观测及应用弹性云原生应用生态引擎云原生应用网络首先来看云原生应用网络,分为 3 个部分来介绍。Sidecar 模式下的云原生应用网络数据面 L4 与 L7 代理解耦模式下的网络基于地域可用区信息的优先路由网络是 Kubernetes 的核心部分,涉及了 Pod 间通信、Pod 和服务间通信以及服务与外部系统间的通信等。Kubernetes 集群中使用 CNI 插件来管理其容器网络功能,使用 Kube-proxy 维护节点上的网络规则, 譬如使发往 Service 的流量(通过 ClusterIP 和端口)负载均衡到正确的后端 Pod。容器网络成为用户使用 IaaS 网络的新界面,以阿里云 ACK Terway 网络为例,基于阿里云 VPC 网络直通弹性网卡,具备高性能特征,同时无缝地跟阿里云 IAAS 网络对接。然而,kube-proxy 设置是全局的,无法针对每个服务进行细粒度控制,而且 kube-proxy 只是专在网络数据包级别上运行。它无法满足现代应用程序的需求,如应用层流量管理、跟踪、身份验证等。我们来看服务网格 Sidecar 代理模式下的云原生应用网络是如何解决这些问题的。服务网格通过 Sidecar 代理将流量控制从 Kubernetes 的服务层中解耦,将代理注入到每个 Pod,并通过控制平面操纵管理这些分布式代理,从而可以更加精细地控制这些服务之间的流量。那么在 Sidecar 代理下的网络数据包的传输是怎样的过程?当前 Istio 实现中涉及了 TCP/IP 堆栈的开销,它使用了 Linux 内核的 netfilter 通过配置 iptables 来拦截流量,并根据配置的规则对进出 sidecar 代理的流量进行路由。客户端 pod 到服务器端 pod 之间的典型路径(即使在同一主机内)至少要遍历 TCP/IP 堆栈 3 次(出站、客户端 Sidecar Proxy 到服务器端 Sidecar Proxy、入站)。为了解决这个网络数据路径问题,业界通过引入 eBPF 绕过 Linux 内核中的 TCP/IP 网络堆栈来实现网络加速,这不但降低了延迟,同时也提升了吞吐量。当然,eBPF 并不会替换 Envoy 的七层代理能力,在七层流量管理的场景下,仍然是 4 层 eBPF + 7 层 Envoy 代理的融合模式。只有在针对 4 层流量网络的情况下,跳过代理 pod 直接进入网络接口。前面讲述的是传统的 Sidecar 代理模式,除此之外,业界开始探索一种新型的数据平面模式。它的设计理念是:将数据平面分层,4 层用于基础处理,特点是低资源、高效率;7 层用于高级流量处理,特点是功能丰富(当然也需要更多的资源)。这样的话, 用户可以根据所需功能的范围,以渐进增量的方式采用服务网格技术。具体来说,在 4 层处理中,主要包括:流量管理:TCP 路由安全:面向 4 层的简单授权策略、双向 TLS可观测:TCP 监控指标及日志在 7 层处理中,则主要包括:流量管理:HTTP 路由、负载均衡、熔断、限流、故障容错、重试、超时等安全:面向 7 层的精细化授权策略可观测:HTTP 监控指标、访问日志、链路追踪那么数据面 L4 与 L7 代理的解耦模式下,Service Mesh 的网络拓扑将是什么形式?一方面,将 L4 Proxy 能力下移到 CNI 组件中,L4 Proxy 组件以 DaemonSet 的形式运行,分别运行在每个节点上。这意味着它是为一个节点上运行的所有 pod 提供服务的共享基础组件。另一方面,L7 代理不再以 Sidecar 模式存在,而是解耦出来,我们称之为 Waypoint Proxy,它是为每一个 Service Account 创建的 7 层代理 pod。4 层和 7 层代理的配置仍然保持通过 Service Mesh 控制面组件来进行下发管理。总之,通过这种解耦模式,实现了 Service Mesh 数据平面与应用程序之间的进一步解耦分离。那么, 在 Istio 的具体实现中,可以分为 3 个部分:Waypoint代理:L7 组件完全独立于应用程序运行,安全性更高;每个身份(Kubernetes 中的服务账户)都有自己专用的 L7 代理( Waypoint 代理),避免多租户 L7 代理模式引入的复杂度与不稳定性;同时,通过 K8s Gateway CRD 定义触发启用;ztunnel:将 L4 处理下沉到 CNI 级别,来自工作负载的流量被重定向到 ztunnel, 然后 ztunnel 识别工作负载并选择正确的证书来处理;与 Sidecar 模式兼容:Sidecar 模式仍然是网格的一等公民,Waypoint 代理可以与部署了 Sidecar 的工作负载进行本地通信;Service Mesh 作为云原生应用网络之场景示例:基于地域可用区信息的优先路由在这个示例中,我们部署了两套一样的应用服务到 2 个不同的可用区下,即这个部署架构图中的可用区 A 和 B。正常情况下,这些应用服务本身是遵循了同 AZ 流量路由优先的机制,也就是说可用区 A 中的应用服务 productpage 会指向本可用区中的 reviews 服务。而当本可用区服务不可用时,譬如 reviews 服务出现故障,容灾模式就会自动开启,这个时候可用区 A 中的应用服务 productpage 会指向另一可用区 B 中的 reviews 服务。这个流量拓扑是阿里云 ASM 产品提供的网格拓扑中按可用区信息展示的调用链路。在实现同 AZ 路由的过程中, 是不需要修改应用代码本身就可以完成的。同样地,在不需要修改应用代码本身的情况下,Service Mesh 自动实现故障转移以保证高可用。这个拓扑图中可以看到可用区 A 中的应用服务会自动切换到调用可用区B中的服务了。 云原生应用治理接下来看云原生应用治理,它的内容包含很多维度,这里重点摘取讲述 3 个部分。服务慢启动以支持预热能力全链路流量管理与服务框架的融合先来看下启用预热模式前后的差异。未启用预热模式:不支持新 Pod 的渐进式流量增加。每当新目标 Pod 加入时,请求方都会向该 Pod 发送一定比例的流量。这对于需要一些预热时间来提供全部负载的服务可能是不可取的,并且可能会导致请求超时、数据丢失和用户体验恶化。作为一个实际示例,上述问题体现在基于 JVM 的 Web 应用程序中,这些应用程序使用水平 pod 自动缩放。当服务刚启动时,它会被大量请求淹没,这会导致应用程序预热时持续超时。因此,每次扩展服务时,都会丢失数据。启用预热模式:预热/慢启动模式又称渐进式流量增加,用户可以为他们的服务配置一个时间段。每当一个服务实例启动时, 请求方会向该实例发送一部分请求负载,并在配置的时间段内逐步增加请求量。当慢启动窗口持续时间到达,它就会退出慢启动模式。在慢启动模式下,在添加新的目标服务 Pod 时,可以使得他们不会被大量请求压倒, 这些新目标服务可以根据指定的加速期在接受其均衡策略的请求之前进行预热。通过这两个图也可以看到, 在启用了预热模式之后, 新创建的 pod 达到均衡的负载请求所需的时间会拉长,这也反映了在一定的预热时间内,进入该 pod 的请求是逐步增加的。一个实际客户案例:扩容和滚动更新场景下支持预热实现服务优雅上线背景:Java 应用冷启动时大流量导致 CPU 打满,调用异常应用滚动更新仅仅通过 readiness 无法实现优雅上线支持预热实现服务优雅上线:ASM 感知实例的上下线,当发现一台机器刚上线时,自动将其权重给调低,过了一定的时间后(预热周期)再将权重调到 100%(权重调整比例);对应用完全没有侵入性;那这个功能是怎么在服务网格 ASM 中实现的呢,简单说,一行配置就可以实现预热、慢启动能力。这个拓扑图也是这个实际案例的脱敏简化版,可以看到通过预热功能:能够实现业务的平滑启动,完美避免业务抖动问题;启用预热功能之后,流量均衡地分布到 v1 和 v2 版本,相比未启用热功能多花费了 1 分 10 秒左右的时间,以此缓冲。全链路流量管理,两个使用场景全链路灰度发布:在生产环境正常运行的同时,开始针对部分应用服务进行灰度升级,譬如图中的 B 和 D 应用进行灰度,在不需要修改应用逻辑的情况下,利用 Service Mesh 技术就可以实现根据请求来源或者请求的头信息,动态地路由到不同版本的服务上。譬如,当请求头中包含 tag1 时,应用 A 就会调用灰度版本 B,而 C 并没有灰度版本,系统就会自动 fallback 回退到原有的版本。多版本开发环境:类似地,有一个基线环境,其他不同的开发环境可以根据需要,分别部署各自版本的部分应用服务。根据请求来源或者请求的头信息,动态地路由到不同版本的服务上。整个过程中,不需要修改应用代码逻辑,只需要针对应用打标,ASM 产品实现了一个 Traffic Label CRD 抽象定义,简化对流量和应用实例打标。应用治理与服务框架融合在遗留的应用系统中,仍然还是实现了类似 Spring Cloud 或者 Dubbo 的服务框架,服务网格 ASM 支持了多模服务治理,实现了调用互通、监控互通、治理互通。通过 MCP over xDS 协议将原有注册中心的服务信息注册到 Service Mesh 中,通过 Service Mesh 控制面组件统一管理规则配置,并以 xDS 协议统一下发管理。云原生应用的零信任安全接下来看云原生应用的零信任安全,包括:零信任的基础 - 工作负载身份零信任的载体 - 安全证书零信任的引擎 - 策略执行零信任的洞察 - 可视化与分析具体来说,构建基于服务网格的零信任安全能力体系包括了以下几个方面:1、零信任的基础 - 工作负载身份,如何为云原生工作负载提供统一的身份:ASM 产品为服务网格下的每一个工作负载提供了简单易用的身份定义,并根据特定场景提供定制机制用于扩展身份构建体系,同时兼容社区 SPIFFE 标准;2、零信任的载体 - 安全证书,ASM 产品提供了如何签发证书以及管理证书的生命周期、轮转等机制,通过 X509 TLS 证书建立身份,每个代理都使用该证书,并提供证书和私钥轮换;3、零信任的引擎 - 策略执行,基于策略的信任引擎是构建零信任的关键核心,ASM 产品除了支持 Istio RBAC 授权策略之外,还提供了基于 OPA 提供更加细粒度的授权策略;同时,支持 dry-run 模式;4、零信任的洞察 - 可视化与分析,ASM 产品提供了可观测机制用于监视策略执行的日志和指标,来判断每一个策略的执行情况等;使用服务网格实现零信任具备如下优势:Sidecar 代理生命周期独立动态配置、无需重启服务网格集中控制,降低开发心智负担加强身份认证授权系统本身安全保障集中管理并下发 OPA 授权策略简化接入第三方授权服务、OIDC 身份认证这是某平台使用网格零信任安全技术的场景。可以看到,客户使用中遵循了零信任安全架构的基本原则:工作负载身份标识服务认证服务授权TLS 加密OPA 策略最小权限访问策略云原生应用的可观测及应用弹性接下来看云原生应用的可观测及应用弹性,包括:网格可观测中心网格诊断网格拓扑网格可观测中心:统一的可观测性体系和联动分析(3 个维度)一是日志分析。通过对数据平面的 AccessLog 采集分析,特别是对入口网关日志的分析,可以分析出服务请求的流量情况、状态码比例等,从而可以进一步优化这些服务间的调用;第二个可观测性能力是分布式追踪能力。为分布式应用的开发者提供了完整的调用链路还原、调用请求量统计、链路拓扑、应用依赖分析等工具,可以帮助开发者快速分析和诊断分布式应用架构下的性能瓶颈,提高微服务时代下的开发诊断效率;第三个可观测性能力是监控能力。根据监视的四个维度(延迟,流量,错误和饱和度)生成一组服务指标, 来了解、监视网格中服务的行为。网格诊断:检测网格配置的潜在问题及提供改进措施根据我们对 Service Mesh 技术的客户支持和实战经验,在服务网格 ASM 中:内置 30+ 项诊断规则、最佳实践针对每个 Istio 资源对象提供语法的静态检查支持多个 Istio 资源对象的执行语义的动态验证针对诊断出的问题提供相应的改进措施网格拓扑:提供对服务网格行为的即时洞察除了强大的网格流量拓扑可视化之外, 还提供了回放功能可以选定过去时间段的流量。云原生应用的生态引擎接下来看云原生应用的生态引擎,包括 3 个部分:插件市场能力中心新场景定义开箱即用的 EnvoyFilter 插件市场、WebAssembly 插件全生命周期管理基于内置的模板, 用户只需要根据对应的参数要求, 进行简单配置, 就可以部署出对应的 EnvoyFilter 插件。通过这样的机制, 使得数据平面成为更易可扩展的插件集合能力。能力中心: 服务网格与生态系统的集成整合能力围绕服务网格技术, 业界存在着一系列以应用为中心的生态系统。其中, 阿里云托管服务网格 ASM 支持了以下多种生态系统,列举如下。蓝绿发布、 渐进式交付、GitOps、CI/CD支持了与 Argo Rollout、Flagger 以及云效等系统的集成实现了应用的蓝绿或者金丝雀发布微服务框架兼容支持 Spring Boot/Cloud 应用无缝迁移至服务网格进行统一纳管和治理。Serverless支持 Knative 运行于托管的服务网格 ASM 之上, 用于部署和运行 Serverless 工作负载, 并基于服务网格实现了在各个版本之间的流量路由。AI ServingKubeflow Serving 是谷歌牵头发起的一个基于 Kubernetes 支持机器学习的社区项目,它的下一代名称改为 KServe,该项目的目的是可以通过云原生的方式支持不同的机器学习框架,基于服务网格实现流量控制和模型版本的更新及回滚。Policy As CodeOPA(Open Policy Agent)/声明式策略表达语言 Rego:在使用 Kubernetes Network Policy 实现三层网络安全控制之上,服务网格 ASM 提供了包括工作负载身份、对等身份和请求身份认证能力、Istio 授权策略以及更为精细化管理的基于 OPA(Open Policy Agent) 的策略控制能力。一般来说,构建基于服务网格的零信任安全能力体系包括了以下几个方面:零信任的基础 - 工作负载身份,零信任的载体 - 安全证书,零信任的引擎 - 策略执行,零信任的洞察 - 可视化与分析。此外,我们也在探索拓宽服务网格驱动的新场景,我这里举一个 AI Serving 示例。这个需求来源也是来自我们的实际客户,这些客户使用场景就是希望在服务网格技术之上运行 KServe 来实现 AI 服务。KServe 平滑运行于服务网格之上,实现模型服务的蓝/绿和金丝雀部署、修订版本之间的流量分配等能力。支持自动伸缩的 Serverless 推理工作负载部署、支持高可扩展性、基于并发的智能负载路由等能力。云原生基础设施的关键层,企业数字化转型的重要桥梁作为业内首个全托管 Istio 兼容的服务网格产品 ASM,一开始从架构上就保持了与社区、业界趋势的一致性,控制平面的组件托管在阿里云侧,与数据面侧的用户集群独立。ASM 产品是基于社区开源的Istio定制实现的,在托管的控制面侧提供了用于支撑精细化的流量管理和安全管理的组件能力。通过托管模式,解耦了 Istio 组件与所管理的 K8s 集群的生命周期管理,使得架构更加灵活,提升了系统的可伸缩性。托管式服务网格 ASM 在成为多种类型计算服务统一管理的基础设施中,提供了统一的流量管理能力、统一的服务安全能力、统一的服务可观测性能力、以及基于 WebAssembly 实现统一的代理可扩展能力,以此构筑企业级能力。可以点击文末“此处”查看具体的内容介绍。总结如下,服务网格作为一种用来管理应用服务通信的基础核心技术,为应用服务间的调用带来了安全、可靠、快速、应用无感知的流量路由、安全、可观测能力。可以看到,服务网格加持下的云原生应用基础设施带来了重要的优势,总结为以下六个方面。优势之一:异构服务统一治理多语言多框架的互通与治理、与传统微服务体系融合的双模架构精细化的多协议流量控制、东西向与南北向流量的统一管理统一的异构计算基础设施的自动服务发现优势之二:端到端的可观测日志、监控与跟踪融合的一体化智能运维直观易用的可视化网格拓扑、基于颜色标识的健康识别体系内置最佳实践、自助式网格诊断优势之三:零信任安全端到端 mTLS 加密、基于属性的访问控制 (ABAC)OPA 声明式策略引擎、全局唯一的工作负载身份(Identity)带有仪表板的完整审计历史记录及洞察分析优势之四:软硬结合性能优化首个基于 Intel Multi-Buffer 技术提升 TLS 加解密的服务网格平台NFD 自动探测硬件特征, 自适应支持诸如 AVX 指令集、QAT 加速等特性首批通过可信云服务网格平台以及性能评测先进级认证优势之五:SLO 驱动的应用弹性服务级别目标 (SLO) 策略基于可观测性数据的应用服务的自动弹性伸缩多集群流量突发下的自动切换与故障容灾优势之六:开箱即用扩展 & 生态兼容开箱即用的 EnvoyFilter 插件市场、WebAssembly 插件全生命周期管理与 Proxyless 模式的统一融合,支持 SDK、内核 eBPF 方式兼容 Istio 生态系统,支持 Serverless/Knative,AI Serving/KServe
作者:子白AHPA 介绍背景Kubernetes 中应用实例数设置有固定实例数、HPA 和 CronHPA 三种策略。使用最多的是固定实例数,但是很多业务都存在波峰波谷,如果采用固定实例数的方式会造成较大的资源浪费。Kubernetes 中提供了 HPA 及 CronHPA 两种机制实现按需扩容实例数量,减少资源浪费。CronHPA 是用户设定定时规则,在固定时间进行实例数伸缩。但是设定定时规则较为复杂,如果定时间隔设置较大就会造成资源浪费。HPA 可以根据应用实时负载设置实例数量,当应用负载高时扩容,当应用负载低时则缩容实例。HPA 是基于实时负载进行扩容,只有当负载已经比较高时才会触发扩容,但此时业务已经处在高负载中因此业务部分流量出现响应慢或者超时的问题,即存在“弹性滞后”的问题。为此,我们提出了一种智能化弹性伸缩方案 AHPA,可以根据历史时序数据进行主动预测,提前扩容,避免弹性滞后。同时,会根据实时数据动态调整主动预测结果,兼容周期变动等场景。图 1 各种弹性伸缩策略对比图AHPA 架构图 2 AHPA 框架图AHPA 整体架构如图 2 所示,分为数据采集、预测及弹性伸缩三大部分。Data CollectionData Collection 模块负责从数据源收集数据并将数据转为统一的格式传入给 Prediction 模块。数据源支持如 Prometheus、Metrics Serve、Log Service 以及其他自定义的监控平台。指标包含 CPU、Memory、GPU 等资源指标,也包括 QPS、RT 等业务指标,同时也支持其他用户自定义指标。Adapter 模块负责将从多个数据源收集的各类指标转为统一的格式输入给 Prediction 模块。PredictionPrediction 模块负责根据输入指标预测所需的 Pod 数量。Preprocessing 负责数据预处理,如过滤非 Running 状态的 Pod 利用率、处理缺失数据等。完成预处理后将时序数据传递给 RobustScaler[1]算法模块。该模块将在第二部分详细介绍。Revise 模块负责对 RobustScaler 模块给出的预测 Pod 数量进行修正。RobustScaler 分为 Proactive 和 Reactive 两种模式,用户也会为应用 Pod 数量设置上下限。为保证应用平稳运行,我们采取尽快扩,缓慢缩的策略,因此 Revise 模块会取 Proactive、Reactive 及用户设置的上下限中最大值作为预测的 Pod 数量。ScalingScaling 模块负责执行 Pod 扩缩容。弹性伸缩策略分为两类:auto 及 observer 模式。auto:根据 Prediction 给出的 Pod 数量自动调整observer:dryrun 模式,不调整 Pod 数量。用户可以通过这种方式观察 AHPA 工作是否符合预期。 AHPA 部署方式图 3 AHPA 部署图AHPA 在 Kubernetes 中部署图如上所示,分为 AHPA Algorithm 及 AHPA Controller 两部分。AHPA Algorithm Deployment 是负责 AHPA 中算法相关的部分,对应架构图中的 Prediction 模块。AHPA Controller 负责数据收集及弹性扩缩容的执行,对应架构图中的 Data Collection 及 Scaling 模块。AHPA 引入 CRD(CustomResourceDefinition)资源以配置弹性伸缩策略,每个应用(Deployment)对应一个 CRD 资源。使用 CRD 的优势在于可以透出多种算法配置,具有较强的灵活性。CRD 的配置示例如下:apiVersion: autoscaling.alibabacloud.com/v1beta1 kind: AdvancedHorizontalPodAutoscaler metadata: name: ahpa-demo spec: scaleStrategy: observer metrics: - type: Resource resource: name: cpu target: type: Utilization averageUtilization: 40 scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: php-apache maxReplicas: 100 minReplicas: 2 prediction: quantile: 95 scaleUpForward: 180 instanceBounds: - startTime: "2021-12-16 00:00:00" endTime: "2022-12-16 24:00:00" bounds: - cron: "* 0-8 ? * MON-FRI" maxReplicas: 15 minReplicas: 4 - cron: "* 9-15 ? * MON-FRI" maxReplicas: 15 minReplicas: 10 - cron: "* 16-23 ? * MON-FRI" maxReplicas: 20 minReplicas: 15spec.scaleTargetRef 用于指定这个 CRD 资源关联的应用,spec.metrics 用于指定采集的时序指标,spec.scaleStrategy 用于设置弹性策略,包括 auto、observer 模式。spec.prediction字段用于设置算法相关指标。spec.maxReplicas 及 spec.minReplicas 设定了应用的Pod数量的上下界。有些应用存在明显的波峰浪谷,因此需要针对不同时段设置不同的上下界。因此,我们提供了 spec.instanceBounds 可以设置不同时段边界保护,也可以起到定时弹性的作用。具体参数及说明如表 1 所示。表 1 AHPA CRD 核心参数列表及说明高可用性异常在复杂系统中不可避免,因此我们在部署时采用了高可用性架构。Algorithm 与 Controller 组件都采用 Deployment 方式部署,当 Pod 发生异常时会自动杀死异常 Pod 并创建新的 Pod,保证业务平稳运行。当接入的业务应用较多时,Algorithm 及 Controller 均可水平扩展以满足高并发需求。为了保证 AHPA 组件升级过程中业务无感知,Algorithm 和 Controller 组件基于 Service 进行通信,Algorithm 及 Controller 可以独立升级。升级时采用滚动升级方式,即先创建新的 Pod,等待新的 Pod 可以对外提供服务后再杀死旧 Pod。可观测性我们提供了 Kubernetes Event、Prothemetheus、Dashboard 等多种方式透出 AHPA 组件运行状态,方便客户监控 AHPA 运行状态及定位问题。如设置 observer 模式后,用户可以通过查看 Dashboard 预估 AHPA 生效结果。Predict CPU Oberserver:蓝色表示 HPA 实际的 CPU 使用量,绿色表示 AHPA 预测出来的 CPU 使用量。绿色曲线大于蓝色,表明预测的 CPU 容量充足。Predict POD Oberserver:蓝色表示使用 HPA 实际的扩缩容 Pod 数,绿色表示 AHPA 预测出来的扩缩容 Pod 数,绿色曲线小于蓝色,表明预测的 Pod 数量更少。AHPA Algorithm-RobustScaler 算法时序预测是 AHPA 算法的核心能力。现有的时间序列预测算法大致可以分为两大类:统计学算法如 ARIMA、 ETS、 GARCH 等;机器学习算法和深度学习算法如广义线性模型、XGBoost、LSTM、CNN、RNN 等。Kubernetes 中 metrics 数据一般采用 Prometheus 存储,综合效率成本等因素,一般业务数据存储周期为 7 天。7 天数据量作为训练集过小,训练出的机器/深度学习模型准确性较差。AHPA 用于实时弹性扩容,对于预测时延要求较高,统计学算法配置参数少、计算复杂度低、延时低。综合考虑,我们采用了统计学算法进行时序预测。Framework图 4 RobustScaler FrameworkRobustScaler算法框架如图 4 所示。实时指标数据(Real-time metric data)为过去Tmin分钟内的数据,用于被动预测(Proactive Planning);历史指标数据(Historical metric data)为过去Tday天数据,用于主动预测(Reactive Planning)。Forecasting首先利用 RobustPeriod[2]算法检测数据是否有周期,有几重周期以及每个周期分量的长度。如果数据存在周期性,则调用 RobustSTL[3]算法分解出数据的趋势、周期及残差项;如果数据没有周期性,则调用 RobustTrend[4]算法分解出趋势和残差项。图 5 Forecasing 模块框架图RobustPeriod 利用特殊的小波变换 MODWT 来隔绝多周期之间的相互干扰,从而检测出时序数据中的多周期。RobustSTL 针对周期性数据,首先从时序数据中分解出趋势项,然后分解出周期项,最后根据残差项修正,以上过程多次迭代直至收敛。RobustTrend 算法针对非周期性数据,从时序数据中分解出趋势及残差。Resource ModelResourceModel 模块用于构建资源模型,该模型的输入为指标时序数据,输出为 Pod 数量。模型选用了统计学中的排队论[5]模型。具体的模型与输入的指标有关,单指标一般采用线性模型,多指标时往往采用非线性模型。Proactive planningForecasting 模块使用 RobustSTL 算法将时序数据分解为趋势项,周期项Si,t及残差项Tt, 下一时刻的指标值计算方式如下。主动预测:将历史周期项直接向右平移作为未来周期项的预测,将趋势项用指数平滑等经典的时序模型预测得到未来趋势分量的预测,残差部分利用分位数回归森林得到未来残差的上界预测。Reactive planningForecasting 模块使用 RobustTrend 算法将无周期数据分解为趋势项Tt,残差项rt。当前时刻的指标可以表示为yt=Tt+rt,下一时刻的指标值由最近h分钟指标计算得出,公式如下。其中wi表示i时刻的指标权重,该值由i时刻的指标值及与时刻与i当前时刻差共同决定。模型训练及预测算法使用过程如下。主动预测1. 获取最近Tday天数据2. 对数据进行分析,基于 Forecasting 模块分解出数据周期、趋势及残差。Proactive Planning 模块根据 Forecasting 模块分解出的信息进行预测。预测结果为接下来Thour小时的指标值。3. 根据最近Tday数据构建 Resource Estimation 模型。该模型的输入为第二步预测出的指标值,输出为预期 Pod 数量。被动预测1. 获取最近Tmin分钟数据2. 对数据进行分析,基于 Forecasting 模块分解出数据趋势及残差。Reactive Planning 模块根据 Forecasting 模块分解出的趋势及残差信息预测下一时刻的指标值。3. 将第二步预测出的指标值输入主动预测构建出的 Resource Estimation 模型中,计算下一时刻 Pod 数量。应用扩缩容最终 pod 数量取主动及被动预测的最大值,计算公式如下。算法效果评估AHPA 算法可以帮助客户识别业务是否存在周期性当数据存在周期性时,AHPA 对数据缺失、毛刺以及业务变更引发的数据周期变化等有很强的鲁棒性当数据不存在周期性时,AHPA 因具备一定的预测能力,可以提前感知数据趋势变化;对数据丢失、噪音等有很强的鲁棒性结论极致弹性是云核心优势之一,在云原生时代用户对弹性的诉求也越发强烈。很多用户配置了 HPA 和 CronHPA 策略。HPA 可以根据应用负载更改实例数量,当应用负载较高时扩容更多的实例。CronHPA 是定时 HPA,在固定时间进行实例数伸缩。CronHPA 配置规则复杂,且存在资源浪费,HPA 存在弹性触发滞后的问题,会导致业务稳定性下降。为此,我们提出了一种智能化弹性伸缩组件 AHPA,核心算法使用达摩院决策智能时序团队提供的 RobustScaler,该算法已被数据库顶会 ICDE 2022 录用。RobustScaler 可以自动识别指标数据是否具有周期性,并且在周期变更、毛刺、数据缺失等场景下都具有很强的鲁棒性。AHPA 组件可以在容器服务 ACK 的组件中心里一键安装,安装成功后即可通过 CRD 资源为应用配置弹性伸缩策略,具体请参考官方帮助文档《AHPA 弹性预测》[6]。Reference[1] Qian, H. , Wen, Q. , Sun, L. , Gu, J. , Niu, Q. , & Tang, Z. . (2022). Robustscaler: qos-aware autoscaling for complex workloads. The 38th IEEE International Conference on Data Engineering (ICDE 2022)[2] Qingsong Wen, Kai He, Liang Sun, Yingying Zhang, Min Ke, and Huan Xu. 2021. RobustPeriod: Robust Time-Frequency Mining for Multiple Periodicity Detection. In Proceedings of the 2021 International Conference on Management of Data (SIGMOD '21).[3] Qingsong Wen, Jingkun Gao, Xiaomin Song, Liang Sun, Huan Xu, Shenghuo Zhu. (2019). RobustSTL: A Robust Seasonal-Trend Decomposition Algorithm for Long Time Series. Proceedings of the AAAI Conference on Artificial Intelligence, 33(01), 5409-5416.[4] Qingsong Wen, Jingkun Gao, Xiaomin Song, Liang Sun, Jian Tan. RobustTrend: A Huber Loss with a Combined First and Second Order Difference Regularization for Time Series Trend Filtering. IJCAI 2019[5] 《运筹学》教材编写组. 运筹学(第三版)[M]. 清华大学出版社, 2005.[6]《AHPA 弹性预测》https://help.aliyun.com/document_detail/416041.html
作者:刘如鸿背景合阔智云(www.hexcloud.cn) 是专注于为大中型零售连锁行业,提供全渠道业务中/前台产品和解决方案,并建立以消费者为中心的全渠道交易和敏捷供应链的新一代零售运营协同平台。合阔智云提供了从全渠道交易管理到订单履约再到门店供应链完整的餐饮零售连锁解决方案,整个方案采取微服务设计,并深度使用了 Kubernetes 作为生产调度平台。技术现状整个业务系统采用微服务架构,但不同业务场景在不同阶段选择了不同的技术语言来开发,如 Python、Golang 和 Java,甚至有部分应用使用了 Nodejs,因为技术栈的缘故,Spring Cloud 或者 Dubbo 这样的全家桶并不适合我们,为了能够适应业务需要,我们选择了下面的策略:不依赖于单一语言和单一技术框架,允许使用更加合适业务的开发语言,如快速业务迭代使用 Python,基础服务和云原生部分使用 Golang,核心的业务系统使用 Java 服务内部使用 gRPC 通信,服务接口定义依赖于 Protobuf 原则上跨服务通信不依赖于消息队列,消息队列只用于服务自身的调度与补偿,这样子降低了消息系统本身的复杂性 所有系统不直接暴露 HTTP,需要提供 HTTP 服务的,使用团队开发的 grpc-proxy 来实现 HTTP to gRPC 的转码代理工作原则上应用只处理业务本身的问题,所有基础架构部分的能力都转由 K8s 来负责,包括:网关服务发现负载均衡指标与监控健康检查故障恢复当前挑战早期所有技术人员只需要专注业务的编写,其他所有的工作全部交给 K8s,在流量比较小业务相对简单的情况下,这个运行非常流畅。然而,随着应用数量的增加,业务变得越加复杂,外部流量也在不断增长,由此带来了应用链路调用更加复杂等新的运维难题:内部调用用的是 gRPC 协议,应用端没有做特别处理,导致基于 HTTP2 的长连接协议无法实现负载均衡,尤其是单一客户端调用变大的情况下,服务端无法有效负载; 因为应用本身比较薄,应用调用链路无法透明化,每次新的发布部署容易出问题。在 2022 年之前,我们使用 Linkerd,初步解决了服务在负载均衡和调用链路上的治理难题,但我们大部分的基础架构都是依赖于阿里云,比如:日志使用 SLS应用监控使用 ARMS链路追踪使用 XTrace仪表盘使用 Grafana容器监控使用 Prometheus为了简化基础架构的复杂性,我们在基础服务上的基本原则是使用云厂商而非自建,而 Linkerd 在实际的使用过程中遇到了一些问题:需要使用自建的基础设施,无法和阿里云提供的基础设施很好的融合应用可观测性比较简单Sidecar 使用默认配置,控制能力相对较少,在应对一些复杂一点的场景,无法做到灵活配置而可观测性是服务网格的基石,在一套自建的基础架构上,我们会偶发的出现链路被熔断、某个端口无法访问的场景,最终的解决方案就是取消注入或者重新注入来解决。基于服务网格 ASM 的探索集群现状我们目前有两个生产集群,合计 150 台 ECS,2500 个 Pod,不同开发语言应用的特点如下:Golang 用于用户基础架构以及计算密集型性的应用系统,总体内存占用不会超过 500M,部分服务会随着临时性的内存而增长,如文件的导入导出服务; Python 用于早期业务敏捷迭代构建的业务系统,都是单进程多线程工作模式,单一 Pod 内存占用不高,但一个 Deploy 需要更多的 ReplicaSet 数量; Java 用于全渠道在线交易业务构建的系统,单一 Pod 需要耗费的资源比较多,但同等情况下单一 Pod 的处理能力比较强。两个集群包括了不同的应用场景:ACK-PROD:早期针对大型客户专有部署的应用集群,每个客户的规模体量比较大,应用资源的隔离通过namespace和调度绑定来隔离; ACK-SAAS:针对 SME/KA 全新开发的 SaaS 平台,所有客户都使用统一的计算资源。调研阿里云服务网格 ASM我们知道, 服务网格作为一种用来管理应用服务通信的基础核心技术, 为应用服务间的调用带来了安全、可靠、快速、应用无感知的流量路由、安全、可观测能力。我们针对开源社区 Istio 和阿里云服务网格 ASM 产品分别进行了调研, 通过试用了解到作为云厂商的产品, ASM 具备了若干生产使用的功能和实战经验,具体来说, ASM 增强了多协议支持以及动态扩展能力,提供精细化服务治理,完善零信任安全体系,并持续提升性能及大规模集群支持能力,降低在生产环境落地服务网格的门槛。商业版适用于有多语言互通,服务精细治理需求,在生产环境大规模使用服务网格的场景。详细的介绍可以参见:https://help.aliyun.com/document_detail/176082.html通过调研, 我们了解到作为业内首个全托管 Istio 兼容的服务网格产品 ASM,一开始从架构上就保持了与社区、业界趋势的一致性,控制平面的组件托管在阿里云侧,与数据面侧的用户集群独立。ASM 产品是基于社区开源的 Istio 定制实现的,在托管的控制面侧提供了用于支撑精细化的流量管理和安全管理的组件能力。通过托管模式,解耦了 Istio 组件与所管理的 K8s 集群的生命周期管理,使得架构更加灵活,提升了系统的可伸缩性。 托管式服务网格 ASM 在成为多种异构类型计算服务统一管理的基础设施中, 提供了统一的流量管理能力、统一的服务安全能力、统一的服务可观测性能力、以及实现统一的代理可扩展能力, 以此构筑企业级能力。可以通过点击"阅读原文"查看具体的内容介绍。基于上述的调研, 我们决定开始使用阿里云服务网格 ASM 产品进行迁移。迁移到阿里云 ASM第一轮第一次注入:ACK-PROD我们首先将一个足够规模体量的单一客户生产环境(门店供应链)(每天 50 万笔订单,1500 万库存流水)注入 Istio,因为这个环境的使用场景不是全天候的,出现问题会有半个小时的缓冲时间来解决问题,并且应用系统做了完善的自动补偿,确保在出现问题我们取消 Istio 以后业务也能够正常恢复,第一次注入非常成功。第二次注入:ACK-PROD然后我们将另外一个门店供应链的生产环境也做了 Istio 注入,相对于第一个环境,规模体量小一点,但业务环境更加复杂,有更多的应用服务在运行,第二次注入非常成功。第三次注入:ACK-SAAS随着前面两次的成功实践,我们在一个更加重要的实时生产系统(门店全渠道交易)的基础服务部分引入了 Istio,因为这些服务只使用 Golang 编写,都是一些实时处理要求比较高,但业务相对简单的,第三次注入成功。第四次注入:ACK-SAAS我们在生产环境开始注入部分交易链路,注入以后系统生产可用,在第二天高峰期发现了会有部分服务出现 istio-proxy crash 导致应用不可用,从而影响了部分应用的正常运行。鉴于对生产环境的谨慎,我们重新复盘了出现问题的场景,最终得到的结论是:Java 应用的启动对于资源的要求比较苛刻,我们没有提前配置好更加合理的启动参数,将会导致 Java 应用启动缓慢; 检查机制不完善,将会导致流量打给还没有完全准备就绪的服务,此时 K8s 的健康检查机制会在多次没有响应时会再次重启服务; Istio Sidecar 默认的设置也会推慢整个 Pod 的启动时间,之前应用的假设是 15s 内完成启动,随着 Sidecar 代理的注入,有时候会遇到更长的时间; Java 应用提供 gPRC 服务的时候,istio-proxy 会出现某种特殊情况的 Crash,这也是导致生产服务不可用的直接原因。简单而言,在 istio-proxy 存在部分 bug 的情况下,我们的应用的快速启动策略和健康检查机制的不合理,直接导致了注入 Sidecar 代理的部分服务生产不可用。针对这个问题,我们在阿里云工程师的支持之下,在另外一个环境复现并做了改进,主要的改进如下:针对 istio-proxyCRASH 问题,社区已经有了解决方案,在阿里云工程师的支持下,我们升级了 Sidecar,并做了 A/B 测试,确定复现了这个 Crash 的场景; 针对 Java 应用一开始分配更多的CPU资源来加快 Java 应用启动,在测试过程中,如果默认分配 0.2 调整到 1.5,启动时间最长的会从 6 分钟减少到 40 秒; 调整 Sidecar 配置,根据应用优化 istio-proxy 的启动速度;第二轮在方案得到确认以后,我们开始了第二轮的 Istio 升级。第一次注入:ACK-SAAS我们将 SaaS 的供应链业务注入 Istio,除了升级过程中遇到部分服务资源不足的问题,其他都非常顺利;第二次注入:ACK-SAAS-QA我们在测试环境复现了启动速度慢的问题,并通过更加合理的启动参数配置验证了在 CPU 初始化申请对于 Java 应用的影响;第三次注入:ACK-SAAS-QAA/B 测试 Istio crash 场景,确认新的 Sidecar 已经修复这个问题;第四次注入:ACK-SAAS正式完成全渠道交易的 Istio 生产注入;第五次注入:ACK-SAAS将剩余的应用全部完成注入。 此外,服务网格 ASM 相比社区 Istio 能够实现更加丰富的能力,如流量标签、配置推送优化等能力。在实际的应用场景中,我们充分利用配置推送优化能力。在默认情况下,由于无法确定数据平面内所有工作负载与服务之间的关系,服务网格数据平面内的所有 Sidecar 都必须保存数据平面集群内所有服务信息的全量配置。同时,一次针对控制平面或数据平面的修改(例如在控制平面新建一条虚拟服务规则),都会导致控制平面向数据平面的所有 Sidecar 推送新的配置。而在我们的数据平面 Kubernetes 集群中的工作负载数量比较多, 默认情况下会增加 Sidecar 对数据平面集群的资源消耗,同时控制平面会面临较大的配置推送负担,降低控制平面的效率与可用性。ASM 提供了选择性服务发现和 Sidecar 资源推荐功能,帮助优化配置推送效率。 服务网格 ASM 可以通过分析数据平面 Sidecar 产生的访问日志获取数据平面服务之间的调用依赖关系,为数据平面中的每个工作负载自动推荐 Sidecar 资源。为工作负载推荐 Sidecar 资源后:Sidecar 配置内将仅保留该 Sidecar 对应工作负载所依赖的服务信息。 当该 Sidecar 资源对应的工作负载无依赖关系的服务发生改变,或与该服务相关的资源发生改变(例如虚拟服务等),都不会引起控制平面向该 Sidecar 的配置推送。服务网格ASM 通过访问日志分析自动推荐 Sidecar CR 经过优化后, Sidecar 配置大小从原来的 40 多M减少为 5M, 控制面配置推送时间也随之大大减少。总之, 经过一个多月的反复测试和确认,我们终于完成了基于服务网格 ASM 的核心生产系统切换,相对于之前的服务网格方案,给我们带来了很多益处。方案优势及进展规划完备的可观测性以及应用监控通过服务网格对应的控制面盘,我们发现了很多之前应用本身的问题,比如:不合理的应用补偿策略不合理的应用部署(比如把大数据查询和应用处理放在同一个服务)不合理的应用报错...而这些问题随着服务网格的上线,我们变得一清二楚,进而非常方便的推动应用架构的改造。流量与资源的均衡这是我们上线服务网格的初衷,随着我们将所有应用放到服务网格,我们真正做到了在 CPU、内存、网络利用率的均衡,通过通过应用调用的监控来看,所有请求数量和错误也非常均衡的分配在不同的 Pod 上,不用再去担心随着流量的增长因为负载不均衡而导致横向扩展失效更加强大的流量治理能力在没有 Istio 之前,我们基于自身业务需要做了一些“手工”的流量治理工作,比如:东西流量:基于基于租户与门店的流量隔离,允许我们可以允许需要针对某一个租户某一个门店发布指定服务南北流量:针对业务场景进行灰度测试,比如某一个租户的美团订单处理使用新的接单服务为某个租户提供自定义域名...这些工作都是基于 K8s CRD 构建的,随着服务网格的上线,我们发现 Istio 可以帮助我们实现更多,比如灰度发布、熔断、限流、流量标签等。这些能力将在未来持续不断提升我们线上业务的稳定性。
作者:周波Why RocketMQ Connect在业务系统,或者大数据系统中不同数据源之间的数据同步是十分常见的,传统的点对点的数据同步工具,在面临越来越多的数据源点对点的数据同步会产生 N*N 的问题,开发成本,维护成本都是非常高的,因为上下游是耦合的,一个数据源的逻辑调整,也可能会影响多个数据管道之间的数据同步。引入消息中间件将上下游解耦这些问题是不是就迎刃而解了?通过消息中间件上下游的数据源的处理逻辑相对独立,但是如果我们直接用 RocketMQ 的生产者消费者来构建数据管道还需要考虑以下挑战。1. 异构数据源越来越多,如何实现任意数据源的数据同步?2. 高性能,如何高效的在源数据源到目的数据源的数据同步?3. 高可用,故障处理能力,当一个节点挂掉是否这个节点的任务就停止了,任务重新启动是否还可以断点续传。4. 弹性扩缩容,是否可以根据系统数据的变动动态的增加减少节点?5. 集群监控,运维管理,随着数据管道的增多,如何管理,运维监控这些数据管道也变的越来越复杂。我们通过 RocketMQ 的生产者消费者开发一个完整的数据管道是比较简单的,可能几天就可以完成,但是如果想一起解决上述这些问题可能需要几个月才能完成,而且一旦我们完成了这样一个系统,就会发现,它与 RocketMQ Connect 是一个非常类似的系统,而上述这些问题是 RocketMQ Connect 都已经完美解决的问题。下面将系统化的介绍一下 RocketMQ Connect 是如何解决这些问题的。RocketMQ Connect 介绍什么是 RocketMQ ConnectRocketMQ Connect 是 RocketMQ 数据集成重要组件,可将各种系统中的数据通过高效,可靠,流的方式,流入流出到 RocketMQ,它是独立于 RocketMQ 的一个单独的分布式,可扩展,可容错系统,它具备低延时,高靠性,高性能,低代码,扩展性强等特点,可以实现各种异构数据系统的连接,构建数据管道,ETL,CDC,数据湖等能力。RocketMQ Connect 具备以下优势:1. 上下游解耦,因为上下游都是通过 RocketMQ 做数据中转的,所以上下游系统是异步解耦的,上下游系统变化不会互相影响,只需要关注与 RocketMQ 的数据同步。2. 低延迟,流式数据传输,秒级甚至毫秒级延迟。3. 可靠性高,集群部署,支持 failover,数据可回放。4. 扩展性强,通过 Connect API 可以实现与任意系统之间建立连接。5. 实现简单,专注数据拷贝,无需关注分布式,故障转移、弹性伸缩等能力。6. 可伸缩,支持动态扩缩容。7. 配置化,低代码,已经支持的数据源只需简单配置就可完成不同数据源之间的,不支持的数据源,只需要实现 Connect API 专注数据拷贝即可快速完成新的数据源的支持。Connector 工作原理 RocketMQ Connect 是一个独立的的分布式,可伸缩,容错的系统,它主要为 RocketMQ 提供与各种外部系统的数据的流入流出能力。用户不需要编程,只需要简单的配置即可使用 RocketMQ Connect,例如从 MySQL 同步数据到 RocketMQ,只需要配置同步所需的 MySQL 的账号密码,链接地址,和需要同步的数据库,表名就可以了。Connector的使用场景构建流式数据管道在业务系统中,利用 MySQL 完善的事务支持,处理数据的增删改,使用 ElasticSearch,Solr 等实现强大的搜索能力,或者将产生的业务数据同步到数据分析系统,数据湖中(例如 Hudi),对数据进一步处理从而让数据产生更高的价值。使用 RocketMQ Connect 很容易实现这样的数据管道的能力,只需要配置 3 个任务,第一个从 MySQL 获取数据的任务,第二、三个是从 RocketMQ 消费数据到 ElasticSearch、Hudi 的任务,配置这 3 个任务就实现了从 MySQL 到 ElasticSearch,MySQL 到 Hudi 的两条数据管道,既可以满足业务中事务的需求,搜索的需求,又可以构建数据湖。1. 系统迁移随着业务的发展,往往会对旧的系统进行系统优化,甚至重构,在新的系统中可能选用新的组件,新的技术框架,旧的系统又无法直接停机将数据迁移到新系统。如何动态的将数据从旧存储系统迁移到新的存储系统,例如旧的系统使用的是 ActiveMQ,新的系统选用了 RocketMQ,只需要配置一个从 ActiveMQ 到 RocketMQ 的 Connector 任务即可实时的将旧系统的数据迁移到新系统,实现旧系统的 ActiveMQ 上的数据迁移到新系统 RocketMQ 中,同时也不影响业务,用户无感知。2. CDC图片来源:https://luminousmen.com/post/change-data-captureCDC 作为 ETL 模式之一,可以通过近乎实时的增量捕获数据库的 INSERT、UPDATE,DELETE 变化,RocketMQ Connect 流式数据传输,具备高可用,低延时等特性,通过 Connector 很容易实现 CDC。数据的序列化与转换前面对 RoketMQ Connect 已经有了基本的介绍,知道 RocketMQ Connect 可以实现很多数据源之间的数据同步,那么这些数据在 RocketMQ Connect 中是如何流转和处理的呢?Converter 和 Transform在数据的序列化和转换有十分重要的作用,下面介绍下 Converter 和 Transform。Converter 和 Transform 和 Connector 一样都属于 RocketMQ Connect 的插件,可以使用 RocketMQ Connect 内置的实现,也可以自定义实现个性化的处理逻辑,通过 RocketMQ Connect Worker 插件加载能力可以将自定义实现加载到 Worker 运行时中,通过简单的配置既可以使用自定义的插件。Converter:转换器,主要负载数据的序列化和反序列化。Converter 可以将数据和数据的 Schema 进行转换并且完成序列化,还可以与Schema Registry配合,将 Schema 注册到 Schema Register 中。Transform:单消息转换,对 Connect 数据对象进行转换,例如过滤掉不需要的数据, 字段过滤,替换数据 Key,大小写转换等,都可以通过 Transform 进行转换。Connector 的数据处理的基本流程,Source Connect 从源数据系统获取数据封装成 Connect 标准的数据对象,然后经过 Transform 对单条数据进行转换,转换后的数据会经过 Converter,Converter 会将数据和 Schema 处理成支持的格式并进行序列化,如果是支持 Schema Registry,Converter 会将数据的 Schema 注册到 Schema Registry 中,然后序列化数据,最后将序列化后的数据发送到 RocketMQ 中。Sink Connect 处理流程是从 RocketMQ Topic 拉取数据,经过数据的反序列化,然后对每条消息进行转换,如果配置了 Transform,最后 Connector 将数据写入到目标存储。RESTful 接口Connector Worker 节点提供了 RESTful 接口方便 Connector 的创建,停止,配置信息获取接口,使用这些接口可以很方便的管理 Connector,只需要调用对应的接口带上对应的配置即可,下面介绍一些常用的接口。•POST /connectors/{connector name}•GET /connectors/{connector name}/config•GET /connectors/{connector name}/status•POST /connectors/{connector name}/stop通过这些 API 即可向 Connect Worker 创建 Connector,停止 Connector,查询 Connector 的配置和状态。Metrics可观测性在许多系统中都扮演着非常重要的作用,它可以帮助观察系统运行情况,系统是否正常运行,系统的高峰期,空闲期是在什么时候,帮助对系统进行监控问题定位等等。Worker 提供了丰富的 Metrics 信息,可以通过 Metrics 观察到所有 Worker 总的 tps,消息数量,还可以观察到每个 task 的 tps,成功处理的数量和处理失败的数量等等,通过这些 Metrics 信息可以很方便的运维 Connector。将 Metrics 信息展示在 Prometheus 中是很多系统的选择,Prometheus 也提供了接入方式,通过实现一个 Prometheus Exporter 即可,新增或者修改 Metrics 修改这个 Exporter 即可,这是一种将 Metrics 接入 Prometheus 的方式。通过 RocketMQ Connect 可以提供一种新的接入方式,实现一个通用的 Sink Prometheus Connector,Source Connector 是获取 Metrics 所需的 Connector,例如 RocketMQ 和 RocketMQ Connect 的 Metrics 信息都写在了文件里,那么获取 Metrics 的 Connector 就是 SFTP Source Connector,这样就可以将 Metrics 信息通过 Connector 的方式接入 Prometheus。Connector 数据质量RocketMQ Connect 和 RocketMQ 一样,实现了 at least once 的语义,即保障至少一次。Source Connector 发送消息到 RocketMQ 失败,producer 会重试,如果重试失败,可以选择跳过,还是停止任务,可以通过配置进行选择。Sink Connector 拉取消息同样会重试,并且在重试达到一定次数时会将消息发送到死信队列,进而保障消息不丢失。Connector 部署在创建 Connector 时,一般是通过配置完成的,Connector 一般包含逻辑的 Connector 连接器和执行数据复制的 Task 即物理线程,如下图所示,两个 Connector 连接器和它们对应的运行 Task 任务。一个 Connector 也可以同时运行多个任务,提高 Connector 的并行度,例如下图所示的 Hudi Sink Connector 有 2 个任务,每个任务处理不同的分片数据,从而增加 Connector 的并行度,进而提高处理性能。RocketMQ Connect Worker 支持两种运行模式,集群和单机集群模式,顾名思义,有多个 Worker 节点组成,推荐最少有 2 个 Worker 节点,组成高可用集群。集群间的配置信息,offset 信息,status 信息通过指定 RocketMQ Topic 存储,新增 Worker 节点也会获取到集群中的这些配置,offset,status 信息,并且触发负载均衡,重新分配集群中的任务,使集群达到均衡的状态,减少 Woker 节点或者 Worker 宕机也会触发负载均衡,从而保障集群中所有的任务都可以均衡的在集群中存活的节点中正常运行。单机模式,Connector 任务运行在单机上,Worker 本身没有高可用,任务 offset 信息持久化在本地。适合一些对高可没有什么要求或者不需要 Worker 保障高可用的场景,例如部署在 K8s 集群中,由 K8s 集群保障高可用。Connector 原理概念Connector 连接器,定义数据从哪复制到哪,是从源数据系统读取数据写入 RocketMQ,这种是 SourceConnector,或从 RocketMQ 读数据写入到目标系统,这种是 SinkConnector。Connector 决定需要创建任务的数量,从Worker 接收配置传递给任务。Task 是 Connector 任务分片的最小分配单位,是实际将源数据源数据复制数据到RocketMQ(SourceTask),或者将数据从 RocketMQ 读取数据写入到目标系统(SinkTask)真正的执行者,Task 是无状态的可以动态的启停任务,多个 Task 是可以并行执行的,Connector 复制数据的并行度主要体现在 Task 数量上。通过 Connect 的 API 也可以看到 Connector 和 Task 各自的职责,Connector 实现时就已经确定数据复制的流向,Connector 接收数据源相关的配置,taskClass 获取需要创建的任务类型,通过 taskConfigs 指定最大任务数量,并且为 Task 分配好配置。Task 拿到配置以后从数据源取数据写入到目标存储。通过下面的两张图可以清楚的看到,Connector 和 Task 处理基本流程。Worker Worker 进程是 Connector 和 Task 运行环境,它提供 RESTful 能力,接受 HTTP 请求,将获取到的配置传递给 Connector 和 Task。除此之外它还负责启动 Connector 和 Task,保存 Connector 配置信息,保存 Task 同步数据的位点信息,负载均衡能力,Connect 集群高可用,扩缩容,故障处理主要依赖 Worker 的负责均衡能力实现的。从上面这张图,看到 Worker 通过提供的 REST API 接收 http 请求,将接收到的配置信息传递给配置管理服务,配置管理服务将配置保存到本地并同步给其它 Worker 节点,同时触发负载均衡。从下面这张图可以看到 Connect 集群中多个 Worker 节点负载均衡后在各自节点启动 Connector 和 Task 的情况。Worker集群的服务发现学习和使用 RocketMQ 的时候,我们知道 NameSrv 是 RocketMQ 服务注册与发现的重要组件,具备简单轻量易运维等特性。通过前面 Connector 部署方式的介绍,RocketMQ Connect Worker 是可以集群方式部署的,那么 Worker 节点之间的服务发现是如何实现的呢?Worker 的服务发现是否依赖外部组件?在使用一项技术或者中间件的时候,尽量少的依赖额外的组件,这对系统的稳定性,可维护性都非常重要,学习成本也会低一些,这也很容易理解,如果多依赖一个组件,就需要多维护一个,学习成本和后期维护成本就会越高。RocketMQ Connect 也是这个原则,尽量少或者不依赖额外的外部组件。通过前面对 RocketMQ Connect 的介绍我们知道 RocketMQ Connect 是 RocketMQ 数据集成,数据流入流出的重要组件,所以 RocketMQ Connect 的运行是依赖一个 RocketMQ 集群的,能否利用RocketMQ的特性实现 Worker 的服务发现呢?答案是肯定的。通过 RocketMQ 客户端有消费客户端变化通知机制,只需要在每个 Worker 启动一个消费者,设置相同的 ConsumerGroup,注册监听 NOTIFY_CONSUMER_IDS_CHANGED 事件即可,增加或减少 Worker 节点就会触发 NOTIFY_CONSUMER_IDS_CHANGED 事件,监听到这个事件就可以触发 Worker 集群的负责均衡,通过 RocketMQ 客户端接口既可以获取所有 Worker 对应的客户端标识,最后根据在线的客户端和任务进行负载均衡。配置同步Topic 的订阅消费分为两种,集群消费,广播消费,不过不同的客户端使用不同的 ConsumerGroup 也可以达到广播消费的目的,RocketMQ Connect Worker 之间元数据的同步就是根据这种原理实现的。所有的 Worker 节点订阅相同的 Topic(connector-config-topic),每个 Worker 节点使用不同的 consumerGroup,这样就可以实现广播的方式消费同一个 Topic,每个 Worker 节点只需要配置发生变化时向 connector-config-topic 发送配置信息,即可实现各个 Worker 节点间的配置同步。位点同步位点同步与配置同步类似只是使用的是不同的 Topic 和 consumerGroup服务发现与配置/位点管理:Connector 配置管理和 Task 任务的位点管理是类似的,除了需要将配置和位点信息持久化到本地,还会将配置和位点信息同步给集群的其它 Worker 节点,这个同步方式也是通过所有 Worker 节点订阅相同的 Topic,使用不同的 consumerGroup 实现的。负载均衡Connect 的负载均衡和 RocketMQ 消费端负载均衡是类似的。都是在每个节点上运行相同的负载均衡算法,只不过负载均衡的对象不一样,RocketMQ 消费端负载均衡是相同 ConsumerGroup 消费端与 MessageQueue 之间负载均衡,Connect 是 Worker 节点与 Connector,Worker 节点与 Task 之间的负载均衡,不过逻辑是类似的,负载均衡算法获取到所有 Worker 和所有的 Connector,Task,并对这些信息排序,根据当前 Worker 节点在排序中所有 Worker 的位置,排序后的 Connector,Task 位置与当前的 Worker 位置取模,就可以为当前 Worker 节点分配好需要运行那些 Connector 和那些 Task,然后 Worker 在本节点启动这些 Connector 和 Task。Worker 扩缩容,Worker 宕机,新增 Connector 配置都会触发重新分配,因此 Worker 集群是弹性的可以故障处理,动态扩缩容的。Connector插件加载Worker 加载 Connector 插件 jar 包类似于 Tomcat 加载 War 包。Tomcat 加载 War 包并不会像 jvm 加载类一样使用双亲委派模型对类进行加载,而是使用自定义的 ClassLoader 加载类,使用不同的 ClassLoader 加载不同的 War 包的不同的类。这样可以避免不同的 War 包中引用相同的 jar 包因为版本的不同各种包引用问题,Worker 也是一样,在加载不同的类插件时为其创建单独的 ClassLoader,从而避免相同的类,因为不同 War 包引用相同 jar,并且版本不同而导致的各种包引用问题,在类加载方面 Worker 像一个分布式的 Tomcat。动手实现 Connector了解了 RocketMQ Connect 的实现原理,下面看一下如何自己实现一个 Connector。看下面这个场景:业务数据写入到 MySQL,然后同步到 Hudi,通过 Hudi 构建数据湖,这个跟我们开头讲到的场景比较相似。通过 Connector 如何实现这个流程?通过前面的介绍,应该清楚,需要实现两个 Connector,一个是从 MySQL 到 RocketMQ 的 SourceConnector,第二个是从 RocketMQ 读数据写入到 Hudi 的 Sink Connector。以 MySqlSourceConnector 为例介绍如何自己写一个 Connector。首先要实现一个 SourceConnector,实现类 MySqlConnectorImpl 继承 SourceConnector 接口,实现配置初始化,taskClass,taskConfigs 等接口。taskClass 方法指定创建 MySqlTask,taskConfigs 将接收到的 Connector 配置并分好每个 Task 配置,这些配置包含连接 MySql 实例相关的账号,密码,address,port 等。Worker 启动 MySqlTask 并将配置传给 MySqlTask,MySqlTask 创建到 MySql 实例的链接并获取 MySql Binlog,解析 Binlog,并将解析的数据封装成 ConnectRecord 放到 BlockingQueue,poll 接口从 BlockingQueue 中取数据返回。这样就实现了一个 Connector。将写好的 Connector 打包放到 Worker 指定目录加载到 Worker 进程,通过请求 Worker http 接口创建 MySqlSourceConnector。Worker 启动 MysqlConnector,通过 MySqlConnector taskClass 获取 MySqlTask 并启动 Task,WorkerSourceTask 从 poll 接口获取数据,然后把获取到的数据通过 Producer 发送到 RocketMQ,这样就完成了 MySql 到 RocketMQ 的数据同步的 Connector。Connector 现状与未来CDC 方面已与 debezium 完成适配,jdbc 标准协议也已支持并且在此基础上与 openmldb 社区合作开发了与面向机器学习数据库 openmldb 的 Connector,数据湖方面与 Hudi 也建立了链接,不久的将来还会与 Doris,clickhouse,es 等流行的存储建立连接,如果有熟悉的的存储,每个人都可以通过 OpenMessaging Connect API 开发一个 RocketMQ 连接器。提到 OpenMessaging Connect API,简单介绍一下 OpenMessaging,OpenMessaging 是 Linux 基金会下一个开源组织,致力于制定消息领域的标准,除了 OpenMessaging Connect Api 还有存储方面的标准 OMOI,压测方面的标准 OMBI,流计算方面的标准 OMS 等等。Connector TutorialQuickStarthttps://github.com/apache/rocketmq-connectRocketMQ Connect & OpenMLDBOpenMLDB 是一个开源机器学习数据库,提供线上线下一致的生产级特征平台。通过与 OpenMLDB 社区合作,RocketMQ 与机器学习数据库 OpenMLDB 建立连接。RocketMQ Connect & Debeziumhttps://mp.weixin.qq.com/s/YNjylhmo1IlvAEKwpjjMkg总结本文介绍了 RocketMQ Connect 的概念,然后讲解了 RocketMQ Connect 的实现原理,对服务发现,配置同步,位点同步,负载均衡都有了初步的介绍,接着以 MySqlSourceConnector 为例讲解了如何自己实现一个 Connector,最后对 Connect API 和生态做了一些介绍,提供了一些 RocketMQ Connect 相关的上手教程,希望本文对学习 RocketMQ Connect 有帮助,更希望感兴趣的同学能参与进来一起贡献社区,实现一个自己熟悉的存储系统到 RocketMQ 的 Connector。作者介绍:周波,阿里云智能高级开发工程师, Apache RocketMQ Committer 。参考链接:rocketmq-connecthttps://github.com/apache/rocketmq-connectapihttps://github.com/openmessaging/openconnect加入 Apache RocketMQ 社区十年铸剑,Apache RocketMQ 的成长离不开全球接近 500 位开发者的积极参与贡献,相信在下个版本你就是 Apache RocketMQ 的贡献者,在社区不仅可以结识社区大牛,提升技术水平,也可以提升个人影响力,促进自身成长。社区 5.0 版本正在进行着如火如荼的开发,另外还有接近 30 个 SIG(兴趣小组)等你加入,欢迎立志打造世界级分布式系统的同学加入社区,添加社区开发者微信:rocketmq666 即可进群,参与贡献,打造下一代消息、事件、流融合处理平台。加入钉钉群与 RocketMQ 爱好者一起广泛讨论:
开源生态的繁荣发展推动着云原生技术快速演进。参与到开源社区的贡献中,不仅可以深入学习正在流行的前沿技术、提升自己的代码水平、建立开发者个人影响力,更是在通过开发者的力量用技术创造更好的世界。为了帮助更多开发者感受开源社区的魅力,了解如何更快地参与社区贡献,阿里云云原生团队将打造一系列围绕 KubeVela、OpenYurt、Koordinator、OpenKruise、Fluid 等云原生开源项目的训练营。2022 年 9 月 27 日-10 月 21 日,我们将从基于 KubeVela 插件生态的制作和贡献开始,帮你开始真正意义上的开源社区贡献者之旅!训练营限时免费加入▶训练营报名时间:2022年9月27日-10月21日▶训练营直播课程时间:2022年10月18日-10月19日 16:00-17:00课程安排自学课了解云原生应用交付生态发展现状KubeVela 入门:基本介绍、快速安装及交付第一个应用CUE 语言基础入门了解 KubeVela 插件体系 直播课授课讲师:董天欣(雾雾),KubeVela 社区核心维护者,阿里云高级开发工程师10 月 18 日 16:00-17:00 「如何在 velaux 页面部署 wordpress helm 应用」10 月 19 日 16:00-17:00 「如何为 KubeVela 社区贡献自己制作的插件」 学习任务:任务 1: 了解 KubeVela 社区体系任务 2: 完成跟学课程学习任务 3: 学会使用 velaUX 插件上传应用资源拓扑图任务 4: 向社区贡献自己制作的插件任务 5: 分享参营心得或学习笔记 参营礼包全部完成学习和打卡任务的同学均可获得训练营电子证书成功被 KubeVela 社区合并正式插件,有机会晋升 KubeVela Contributor完成全部任务并通过审核的前 50 名用户,获得 KubeVela 社区贴纸一套完成全部任务并通过审核的前 20 名用户,获得 KubeVela 限量随行杯一个完成全部任务并通过审核的前 10 名用户,获得 KubeVela 限量 T 恤一件相信在本次训练营中,你会能感受到如何用自己的力量促成开源社区中的有效协作,体会帮助更多开发者降低新技术学习的乐趣和成就感!点击此处,直达训练营现场,赶快报名吧!!
Gartner:可观测性成为数据驱动型决策最强支撑近日,全球权威 IT 研究与顾问咨询公司 Gartner 发布《2023 年十大战略技术趋势》报告。报告围绕优化、扩展和开拓三大主题展开,「应用可观测性」再次成为其中热门趋势之一。Gartner 杰出研究副总裁 Frances Karamouzis 表示:“为增加盈利,企业 IT 高管在持续加快数字化转型的同时,需将目光从节约成本转向新的卓越运维方式。,可观测性以高度统筹与整合的方式将用户数字化操作所产生的可观测数据进行反馈并创造决策循环,提高组织决策有效性。如能在战略中予以规划并执行,可观测性将成为数据驱动型决策的最强支撑。”但伴随着 IT 技术高速发展,企业在落地可观测过程中必然遭遇三大阻隘。首先,蓬勃发展的开源/商业可观测产品生态与逐渐无法满足云原生 IT 运维需求的传统企业监控体系,造成新老工具、数据与工具的割裂。 如何选择与平衡成为CTO、CIO 必须面对的选择题。其次,当微服务架构以及分布式架构被越来越多应用于企业业务,以日志为例的典型可观测数据,计算成本与存储成本以指数级增长。在行业形势愈发严峻的当下,可观测成本投入高昂且难以预估,应用场景往往停留在单点排查或基础监控告警上,大张旗鼓的落地可观测基础设施,回报价值未知。以上几点,这都难以说服CTO、CIO们投入愈发吃紧的运维预算与人力进行可观测性建设。为解决以上难题,深耕可观测领域的阿里云于今年6月推出阿里云云原生可观测套件ACOS,该产品套件由阿里云 Prometheus 服务、阿里云 Grafana 服务、链路追踪 OpenTelemetry组成,这三款开源流行度最高、生态集成最广的事实标准是云原生可观测套件ACOS的“核心”,旨在通过开放标准打通所有阿里云可观测产品实现全链路数据标准化,并连接企业存量可观测数据资产,与阿里云应用托管平台集成。全面覆盖用户体验(UEM)、应用观测(APM)、云服务观测、成本管理、应急协同效率等场景。帮助企业高效构建开放、高质量、低成本的统一可观测体系。云原生可观测 ACOS 的独特价值相较于其他可观测商业化或开源解决方案,云原生可观测套件在采集、存储、计算、告警、查询、可视化六大环节做到与开源标准的全面兼容与优化提升。同时,将阿里巴巴集团以及阿里云服务海量用户的可观测经验进行产品化输出。这包含超过 50 款阿里云主流云服务的运行指标、大盘和告警规则预置模板。从基础设施到容器,从应用到用户体验,从成本分析到运维效能分析,在接入第一天就做到全链路高质量观测。自发布以来,众多行业客户借助阿里云原生可观测套件 ACOS 快速构建统一可观测体系。以友邦人寿为例,友邦人寿对应用进行容器化、微服务化改造,以适应业务与性能要求。但随着访问链路与部署复杂度提升,观测微服务和 K8s 运行,并构建全栈可观测能力成为巨大挑战。借助 ACOS,友邦人寿将可观测性覆盖研发生产全周期,将研发态与运维态指标关联与展现,从而有效度量研发效率。同时,将多容器集群及应用服务的观测进行统一,将应用性能指标、全局调用链、日志相融进行快速根因定位的同时,形成指挥决策、仪表盘展示、告警推送的多维度观测能力,大幅提升运维服务效率。云原生可观测 ACOS 焕新升级本次云栖大会,阿里云云原生可观测套件 ACOS 三大组件也迎来重要升级。首先,作为容器观测事实标准的阿里云 Prometheus 监控,观测范围从专精容器延伸到全栈可观测。为了帮助更多企业构建统一观测体系,Prometheus 监控已成为阿里云 50+款云产品默认观测基础设施,并与应用实时监控服务 ARMS 的 APM 指标、eBPF 指标、OpenTelemetry 指标联通,以及将企业的 ECS(非 K8s 集群)、K8s 集群、非阿里云集群进行 Prometheus 实例聚合,帮助企业一键开启全球与异构架构下的统一可观测中心。在服务外部客户同时,阿里云 Prometheus 监控不断通过内部场景进行打磨,目前已能够支持千万核的容器观测及数十亿级别时间线的时序存算能力。对于时序监控场景的核心技术难点,如海量动态监控对象采集能力、高基数时间线发散收敛、长周期查询、突发流量下误报漏报等场景进行针对性优化,使得阿里云 Prometheus 监控真正成为无处不在,大规模生产可用的可观测基础设施。在赋予企业强大观测能力的同时,Prometheus 推出全新包年包月计费形式,同等业务规模下,平均相较于自建成本降低 60%。满足不同业务规模用户的观测需求,并尽可能减轻企业的运维成本压力。其次,作为观测界面的阿里云 Grafana 服务也将迎来 9.0 焕新升级。全新的 Prometheus 和 Loki 查询语句生成器及强化后的搜索 Explore 功能,让用户获得更强的数据查询与分析能力,更低门槛的创建可视化大盘与告警。同时,为了应对越来越丰富的异构可观测数据源,Grafana 服务与日志服务 SLS、Elasticsearch 等 20+款可观测存储服务集成,帮助企业更简单的构建统一「运维&业务」观测界面。一键导入/导出自建实例、自动数据导出报表,一键数据备份、恢复,用户操作审计等企业特性进一步增强。最后,为了帮助企业的云上应用开启多维度观测视角,应用实时监控服务 ARMS 也迎来巨大升级。在数据采集方面,在完整支持 Opentelemetry SDK 的同时,指标数据可完全通过与 Prometheus 标准进行存储与计算,补充业务、自定义组件埋点。在完善观测维度的同时,避免厂商锁定。并借助 TraceExplorer 实现多来源 Trace 统一查询。与此同时,eBPF 技术以及 Continuous Profiling 作为目前可观测领域最为热门的细分领域,阿里云可观测团队也进行积极探索。本次大会阿里云可观测团队开放基于 eBPF 技术的“轻量版应用监控”预览,帮助企业快速获得无侵入、全语言的应用监控能力,并及时感知集群全局拓扑结构。同时,与 Alibaba Dragonwell 团队联合推出 Continuous Profiling 功能,能够以极低功耗持续分析代码级别的性能开销,覆盖传统链路、指标和日志覆盖不到的细节,实现代码级生产环境性能问题定位及全天候主动剖析,让应用观测视角更丰富,观测颗粒度更细致。在不断探索更多可观测场景服务阿里巴巴集团以及海量企业用户的同时,阿里云可观测凭借其完备的产品能力与良好的生态集成能力及出色的成本优势,收获了国内外行业机构的高度认可。阿里云应用实时监控服务 ARMS 在今年获得中国信通院首批可观测产品先进级认证。同时,阿里云连续两年进入 Gartner APM 与可观测魔力象限,今年更是成为唯一入选的中国厂商。万物皆云的时代,可观测性让云计算更易用高效,最大程度释放业务稳定性、安全性、经济性价值。“观测力”已成为每个 IT 人的必备核心竞争力。不止于观测,可观测帮助企业分析、洞察并实现高质量的决策与业务创新。而阿里云将不断推动可观测技术演进与落地实践,帮助企业获得最具性价比的可观测性,真正实现高质量数字化转型与创新。
Gartner:可观测性成为数据驱动型决策最强支撑近日,全球权威 IT 研究与顾问咨询公司 Gartner 发布《2023 年十大战略技术趋势》报告。报告围绕优化、扩展和开拓三大主题展开,「应用可观测性」再次成为其中热门趋势之一。Gartner 杰出研究副总裁 Frances Karamouzis 表示:“为增加盈利,企业 IT 高管在持续加快数字化转型的同时,需将目光从节约成本转向新的卓越运维方式。,可观测性以高度统筹与整合的方式将用户数字化操作所产生的可观测数据进行反馈并创造决策循环,提高组织决策有效性。如能在战略中予以规划并执行,可观测性将成为数据驱动型决策的最强支撑。”但伴随着 IT 技术高速发展,企业在落地可观测过程中必然遭遇三大阻隘。首先,蓬勃发展的开源/商业可观测产品生态与逐渐无法满足云原生 IT 运维需求的传统企业监控体系,造成新老工具、数据与工具的割裂。 如何选择与平衡成为CTO、CIO 必须面对的选择题。其次,当微服务架构以及分布式架构被越来越多应用于企业业务,以日志为例的典型可观测数据,计算成本与存储成本以指数级增长。在行业形势愈发严峻的当下,可观测成本投入高昂且难以预估,应用场景往往停留在单点排查或基础监控告警上,大张旗鼓的落地可观测基础设施,回报价值未知。以上几点,这都难以说服CTO、CIO们投入愈发吃紧的运维预算与人力进行可观测性建设。为解决以上难题,深耕可观测领域的阿里云于今年6月推出阿里云云原生可观测套件ACOS,该产品套件由阿里云 Prometheus 服务、阿里云 Grafana 服务、链路追踪 OpenTelemetry组成,这三款开源流行度最高、生态集成最广的事实标准是云原生可观测套件ACOS的“核心”,旨在通过开放标准打通所有阿里云可观测产品实现全链路数据标准化,并连接企业存量可观测数据资产,与阿里云应用托管平台集成。全面覆盖用户体验(UEM)、应用观测(APM)、云服务观测、成本管理、应急协同效率等场景。帮助企业高效构建开放、高质量、低成本的统一可观测体系。云原生可观测 ACOS 的独特价值相较于其他可观测商业化或开源解决方案,云原生可观测套件在采集、存储、计算、告警、查询、可视化六大环节做到与开源标准的全面兼容与优化提升。同时,将阿里巴巴集团以及阿里云服务海量用户的可观测经验进行产品化输出。这包含超过 50 款阿里云主流云服务的运行指标、大盘和告警规则预置模板。从基础设施到容器,从应用到用户体验,从成本分析到运维效能分析,在接入第一天就做到全链路高质量观测。自发布以来,众多行业客户借助阿里云原生可观测套件 ACOS 快速构建统一可观测体系。以友邦人寿为例,友邦人寿对应用进行容器化、微服务化改造,以适应业务与性能要求。但随着访问链路与部署复杂度提升,观测微服务和 K8s 运行,并构建全栈可观测能力成为巨大挑战。借助 ACOS,友邦人寿将可观测性覆盖研发生产全周期,将研发态与运维态指标关联与展现,从而有效度量研发效率。同时,将多容器集群及应用服务的观测进行统一,将应用性能指标、全局调用链、日志相融进行快速根因定位的同时,形成指挥决策、仪表盘展示、告警推送的多维度观测能力,大幅提升运维服务效率。云原生可观测 ACOS 焕新升级本次云栖大会,阿里云云原生可观测套件 ACOS 三大组件也迎来重要升级。首先,作为容器观测事实标准的阿里云 Prometheus 监控,观测范围从专精容器延伸到全栈可观测。为了帮助更多企业构建统一观测体系,Prometheus 监控已成为阿里云 50+款云产品默认观测基础设施,并与应用实时监控服务 ARMS 的 APM 指标、eBPF 指标、OpenTelemetry 指标联通,以及将企业的 ECS(非 K8s 集群)、K8s 集群、非阿里云集群进行 Prometheus 实例聚合,帮助企业一键开启全球与异构架构下的统一可观测中心。在服务外部客户同时,阿里云 Prometheus 监控不断通过内部场景进行打磨,目前已能够支持千万核的容器观测及数十亿级别时间线的时序存算能力。对于时序监控场景的核心技术难点,如海量动态监控对象采集能力、高基数时间线发散收敛、长周期查询、突发流量下误报漏报等场景进行针对性优化,使得阿里云 Prometheus 监控真正成为无处不在,大规模生产可用的可观测基础设施。在赋予企业强大观测能力的同时,Prometheus 推出全新包年包月计费形式,同等业务规模下,平均相较于自建成本降低 60%。满足不同业务规模用户的观测需求,并尽可能减轻企业的运维成本压力。其次,作为观测界面的阿里云 Grafana 服务也将迎来 9.0 焕新升级。全新的 Prometheus 和 Loki 查询语句生成器及强化后的搜索 Explore 功能,让用户获得更强的数据查询与分析能力,更低门槛的创建可视化大盘与告警。同时,为了应对越来越丰富的异构可观测数据源,Grafana 服务与日志服务 SLS、Elasticsearch 等 20+款可观测存储服务集成,帮助企业更简单的构建统一「运维&业务」观测界面。一键导入/导出自建实例、自动数据导出报表,一键数据备份、恢复,用户操作审计等企业特性进一步增强。最后,为了帮助企业的云上应用开启多维度观测视角,应用实时监控服务 ARMS 也迎来巨大升级。在数据采集方面,在完整支持 Opentelemetry SDK 的同时,指标数据可完全通过与 Prometheus 标准进行存储与计算,补充业务、自定义组件埋点。在完善观测维度的同时,避免厂商锁定。并借助 TraceExplorer 实现多来源 Trace 统一查询。与此同时,eBPF 技术以及 Continuous Profiling 作为目前可观测领域最为热门的细分领域,阿里云可观测团队也进行积极探索。本次大会阿里云可观测团队开放基于 eBPF 技术的“轻量版应用监控”预览,帮助企业快速获得无侵入、全语言的应用监控能力,并及时感知集群全局拓扑结构。同时,与 Alibaba Dragonwell 团队联合推出 Continuous Profiling 功能,能够以极低功耗持续分析代码级别的性能开销,覆盖传统链路、指标和日志覆盖不到的细节,实现代码级生产环境性能问题定位及全天候主动剖析,让应用观测视角更丰富,观测颗粒度更细致。在不断探索更多可观测场景服务阿里巴巴集团以及海量企业用户的同时,阿里云可观测凭借其完备的产品能力与良好的生态集成能力及出色的成本优势,收获了国内外行业机构的高度认可。阿里云应用实时监控服务 ARMS 在今年获得中国信通院首批可观测产品先进级认证。同时,阿里云连续两年进入 Gartner APM 与可观测魔力象限,今年更是成为唯一入选的中国厂商。万物皆云的时代,可观测性让云计算更易用高效,最大程度释放业务稳定性、安全性、经济性价值。“观测力”已成为每个 IT 人的必备核心竞争力。不止于观测,可观测帮助企业分析、洞察并实现高质量的决策与业务创新。而阿里云将不断推动可观测技术演进与落地实践,帮助企业获得最具性价比的可观测性,真正实现高质量数字化转型与创新。
作者:黄备、洛浩深圳鱼传科技有限公司是专注以精准营销和互联网生态产品运营为核心的综合互联网营销推广服务商。通过整合全网优质媒体资源,并结合智能数据模型和 AI 标签算法,向企业提供包括流量矩阵搭建运营、媒介流量采买、投放模型设计、产品营销策划、数据监控分析、效果运营等多层次服务。作为函数计算的资深用户,鱼传科技的 CTO 和技术负责人跟我们聊了鱼传科技的 Serverless 旅程。目前鱼传科技的业务主要基于支付宝小程序进行承载,小程序具有轻量、打开方便、内容可以快速更新等特点,为了适应市场的快速变化和多变的客户诉求,对敏捷开发提出了更高的要求。鱼传科技的业务特点,还具有访问量波动大、流量突发预测难等特点,尤其是活动期间访问突增对小程序后端服务的稳定和弹性也是一个很大的考验。而阿里云函数计算是典型的 Serverless 计算平台,具备极强的弹性能力,可以做到百毫秒弹性扩缩,可以很好的支撑业务弹性扩展。同时对函数计算,用户上传代码即可运行,无需关注和维护服务器,也极大地提高了后端开发效率。这些特点使得函数计算成为很多企业支撑小程序/移动 APP 的优先选择,尤其是有突发流量或者流量波动较大的业务场景。如下是基于鱼传科技的第一视角呈现的 Serverless 落地实践。复杂交互小程序如何应对访问量激增?2018 年底,我们开始尝试使用函数计算。当时,公司的核心业务是在支付宝上制作一些小程序。“多多有礼”小程序就是在那个时候上线的,“多多有礼”是一款主打互动领奖的小程序,当前已经积累了百万日活的规模,是一款非常受用户欢迎的产品。然而在 2018 年,“多多有礼”最初上线时,我们遇到了已有业务系统难以承载突增流量的难题。那时我们的业务都跑在服务器上面,为了能抗住高并发流量,我们准备了大概三、四台高配服务器做负载均衡,然而在业务并发高峰期,服务崩掉的情况还是经常发生。因为这个小程序涉及到的业务逻辑,和应用后端交互比较多,有很多复杂流程,比如打卡、签到、庄园运营等,所以遇到突增流量,单纯增加服务器数量很难扛住。另外我们还遇到了资源利用率低的问题。“多多有礼”在初期上线的时候,业务高峰期并发大概在 1000-2000,但业务低峰期可能也就几十,这是因为小程序设计的用户打卡、签到等动作,使得用户量非常容易在早上、晚上,或者某一个特定时间暴增。在这种情况下我们再用 ECS 的话,不仅需要按照峰值流量预留足够的 ECS 资源,维护起来也会变的非常复杂,资源利用率很难做上去,费用也会成倍的增加。所以我们当时非常迫切地想把这个事情从我们系统里解耦,如果能简化我们的运维复杂度,还能引入弹性能力就好了。经过调研我们发现当时阿里云,只有函数计算 FC 这款产品具备相应的特点,所以我们就开始尝试把整个业务都迁到阿里云函数计算上来。经过这 3 年多的使用,我们把新的应用、可以迁移的旧应用、内部应用/外部应用等都陆续迁移上函数计算了。可以这么说,如果函数计算崩了,我们公司的业务基本也就瘫了。但是经过这 3 年来的使用,发现函数计算的稳定性还是超预期的,比我们维护使用服务器的时候,业务稳定性和性能都有大幅提升,现在峰值可以达到数万 QPS、数千函数并发同时稳定运行。而且我们和函数计算也建立了专门的技术支持群,有任何技术问题,都能很快得到响应,这也是为啥我们敢把公司所有的业务都基于函数计算来部署的原因。使用函数计算,真正帮助我们解决了很多稳定性和性能问题。“多多有礼”小程序页面最佳实践再来分享下我们使用函数计算的一些最佳实践,希望也能帮助到其他用户使用函数计算。1. 开发流程我们公司的主要技术栈是基于 PHP 语言,也会使用一些 Web 框架,像 Lavaral,针对 Web 框架,为了能在函数计算上运行起来,我们也对框架做了些适配,一个项目拆成一个或多个文件,对应多个函数,单个文件有的1万行代码,基础文件一百行左右。但是现在函数计算配合 Serverless Devs 工具支持了多语言 Web 框架的“0”改造迁移,我们也在尝试使用。目前我们每个开发会独立负责一个函数服务,服务下面每个函数会作为一个小的应用,部分项目会跨服务依赖一些功能函数,但是我们都会尽可能都独立开。函数计算也支持了层功能,后面会用层来部署公共函数、依赖,比如给用户发红包,代码只用写一份。另外对新招进来的开发来讲,函数计算上手门槛还是很低的,不用管理服务器搭环境,可以直接在线编辑代码、部署、测试。2. 流水线和灰度发布我们本地一直采用的 SVN 存储代码,SVN 提交代码支持触发 Action,我们封装了函数计算的 API 接口,可以通过关键字触发函数和服务的发布。为了避免发布影响线上服务,我们还使用了函数计算的版本和别名的功能。正常线上业务会发布成新的版本,同时把 HTTP 流量入口绑定的 release 别名指向新的版本,这样就完成了发布过程,如果最新的代码出现问题,可以更改别名的指向,就能达到一键回滚到上个版本。同时我们也会创建一个测试别名,会先完成版本的测试后,才会把承载现网流量的 release 别名指向到新版本。这样通过别名的能力就区分出了线上环境和测试环境,非常方便。3. 运维管理对函数计算来讲,基本是不需要关心资源维护的,像我们最依赖的弹性能力。但是对于业务运维来讲,监控日志就成了非常关键的手段。函数计算集成了 SLS,每次请求都会生成一条日志,可以比较方便的过滤出错误日志,对线上问题排查还是比较方便的。另外函数计算也提供了比较全的监控视图,我们最常用的就是请求量、错误次数、并发、执行耗时等指标,针对错误次数也加了告警,这样开发就可以直接兼业务运维,效率成倍增加。效果对比对比之前使用服务器,函数计算确实给我们带来了很大的便利性,我们也是最早吃螃蟹的人,基本伴随着函数计算一路成长,我们也非常高兴的看到,函数计算的功能越来越丰富,体验也越来越好。总结下来:1. 稳定性增强开发不需要去关心后端服务的搭建运维,只需要编写函数就能够为小程序提供稳定可靠并且弹性伸缩的服务。并且随着小程序访问量增加,函数计算能够支持更大的并发配额,即使应对大促活动流量高峰也能够如丝般顺滑。对于稳定性的提升,这个是对我们最大的帮助。2. 开发上手快,不用维护服务器使用函数计算“上手快,不用维护服务器”也是很吸引我们的一个点。很多人对于 “Serverless”技术有一些误解,认为这个火热的技术可能会难以学习、理解,其实不然。在实际使用过程中,我们曾经尝试让一些开发新人在生产过程中直接使用函数计算,在实操的过程中,这些开发上手非常快,他们只需要关心自己的代码就可以了,也非常乐于使用。3. 价格低服务好,想买技术支持之前我们对于函数计算的使用费用没有做过细致的统计,刚发现支撑一个日活超过 50 万人的小程序,使用函数计算费用大约在 200 元/日左右,对我们的业务来讲,这个费用还是很便宜的。我们日常使用也会遇到一些问题,函数计算团队能及时、耐心的给予技术支持,我曾与团队的同学开玩笑说,特别想在函数计算上多花点钱,想买技术支持。云计算时代真正的弹性计算Serverless 技术最大的优势就是免运维,同时提供弹性能力和按需付费。我们选择使用 Serverless 就是觉得它是真正的弹性计算,是未来的趋势。如果我使用比如像弹性 ECS 这样的产品,如果我的业务发展需要上量,就需要人工去“起”机器,或者执行一些弹性策略。但 Serverless 却能够让我不用考虑后端的所有的运维工作,实现自动的弹性伸缩,所以我们认为 Serverless 是云计算时代真正的弹性计算。最后,我们也想对函数计算提一些建议:1. 期望函数计算的调用入口能够支持访问 IP 固定,因为一些政府监管的要求,需要加 IP 黑白名单。2. 函数的版本发布,能够支持针对单个函数精准发布,更加精准的实现灰度。作者介绍:鱼传科技 CTO 黄备、阿里云架构师洛浩
作者: 孤弋(李颜良)从几个数字开始说IDC 预计到 2024 年,由于采用了微服务、容器、动态编排和 DevOps 等技术,新增的生产级云原生应用在新应用的占比将从 2020 年的 10% 增加到 60%,其中微服务的 workload 在企业内将超过 80% 。上面的四点是云原生时代所代表的四个核心技术。其中,我们的开发同学可能对于微服务比较热衷,从近几年的趋势来看,Java 领域的微服务框架日趋成熟,和云原生的结合也越来越紧密。从 EDAS 中的数据来看,Spring Cloud + Kubernetes 基本上已经成为了微服务架构形态下的主流配搭。但是另外一个数据让我产生了更多的好奇,就是目前在云原生场景下有过微服务生产经验的开发人员不足 8% 。为什么会是这个样子?我觉得主要原因有两个:首先,是因为本身微服务的学习曲线比较陡峭,好不容易学会精通一个框架,可以进行生产实践了,可是马上又面临了云原生诸多复杂的概念和复杂环境搭建的技术挑战,这个两个因素结合在一起对于每一个人充满的都是对于未知世界的恐惧,这样在一些战略定力不那么强的团队中,最后落地效果就不太好。针对这一条,我觉得大家只需要跟进我们团队的一些产品和相关课程就行了,云原生团队有大量的相关课程在阿里云大学上供大家学习,很多产品也提供了不错的工具;同时在各个领域都有很多的数字化转型的经验,其中包括微服务在研发团队中践行落地的经验。感兴趣的伙伴可以给我们留言,我们可以择期进行深入的沟通交流。其次,对于开发人员而言,一直有一个错误的认知就是云原生应用和普通开发的应用是没有区别的,因为对于开发者而言,还是一样写代码,还是一样发布部署,还是一样排查诊断。但是这里还真的不太一样,哪里不一样呢?Heroku 给我们总结出来了 12 条要素,在圈内叫做 12 factor apps,既简单理解下来,符合这个十二条要素的应用,才能叫做云原生应用。Twelve Factor Apps这个十二条我列在了这里,橙色的部分,和我今天的内容相关。下面我每一条做一下简单的讲解:第一条:Codebase,既一份代码,多处部署。反过来理解就是多个部署都是一份代码,而且 得 是一份代码。那什么时候不是?比如我们直接上生产环境中调整但是忘了同步回来的时候,也就是说,这一条是约束我们的研发流程,保证代码在各个环境中的一致性。第二条:是显示声明依赖关系,这一条很好理解,写 Java 的同学都会使用 ant、maven、gradle 这样的工具对于一些依赖进行显示声明。但是我们往往容易忽略两点,第一点,是依赖一个 snapshot 版本,最后因为缺少有效的跟踪而导致线上故障。第二点是一个隐含的依赖,既代码运行时环境的依赖系统软件、执行引擎等应都当是做应用的一部分。第三条:Config,常规理解是代码配置分离。这里严格意义上,是讲的是整个运行环境(镜像)与配置要做隔离,什么意思呢?这里的核心是所依赖配置,是否能在运行启动的过程中,通过常规的运维手段能进行灵活替换,这些运维手段包括:比如更改环境变量,更改启动参数,通过分布式配置服务等。第四条:Backing Services,所有后端服务,其实包括所有发生网络调用的情形,我们都需要同一视角去对待。当作附加资源有两种意思,第一是资源应当准的资源访问的接口与方式,比如在 Java 中的 URI 接口。还有一种理解就是既然是资源,就需要考虑他的可用性,既然所有后端服务都是资源,那么我们也要一视同仁的去治理资源的可用性。第五条:Build,Release,Run 之所以要严格分开,这是三个领域我们关注的能力也会不一样。首先 Build 更注重实效;而 Release 要注重策略;Run 阶段更注重流量治理,要尽可能的做到流量无损耗。第六条:Stateless,单纯进程维度的无状态主要是进程启动过程中对于数据的依赖。无状态的目的,是为了更好的做快速伸缩甚至自动的弹性伸缩,Stateless + 启动无需干预是弹性的关键一步。第七条:Port Binding,是指所有对外暴露的服务都通过端口暴露,这里是与之相反的是有一些应用通过 unix socket 或者 IPC 之类的访问方式会极大增加大规模服务运维场景下的复杂度。第八条:Processes,这里的理念其实是当服务容量需要弹性时,推荐使用 Scale out,而非进程内的 Scale up,Scale Out 能使应用最大化的利用各种规格下的系统资源,而 Scale Up 的对于 JVM 类似的机制而言,往往会带来额外的系统开销和更复杂的 GC 策略。第九条:Disposability,快速启动的场景我们应该拉长来看,回到第五条的 Run 阶段,Run 阶段应该从一个全新的环境准备好开始到进程真正拉起开始服务为止,即包括环境准备、程序包拉取,也包括进程启动后续的所有流程。而优雅终止则容易忽略类似于消息、调度任务、线程池等后台任务的处理。第十条:Dev/Prod parity ,理解容易,落地比较困难。要达成这一点的前提,理论上是要避免一切在环境中人为的操作。云原生中有一条叫做“不可变基础设施”,其实和这一条在对应,但是不可变基础设施指的在运行时需严格 follow 在代码中声明的配置,如果要变则需要重新声明。第十一条:Logging Event,是推荐日志当成事件流处理,确切的说就是建议将所有日志都打印到标准输出中,而不是使用配置文件。同时使用专门的集中存储的日志服务把日志内容收集然后统一进行聚合、清理、查询。这样不仅运维标准简单。而且可以解耦本地磁盘依赖,云原生场景下的应用,要做好磁盘数据随时可能消失的准备。第十二条:后台管理任务指的是一些维护性质的任务,比如清理日志、缓存、订正某些数据等等。我们应该把这些都当成本身业务的一部分,不能游离在整个产品体系之外。既同样需要遵循前面 11 条,如:一份代码,显示声明,代码和配置解耦,无状态等等。常规开源软件方式搭建首先,是需要准备一个微服务环境,最为基础的在微服务场景下需要一个服务注册发现的组件(如:Nacos),当然随着我们的业务越来越复杂,需要的组件肯定会越来越多比如:APM 组件、日志服务组件等等。然后,我们本地会使用一个 IDE,搭建代码工程,开始进行开发。在 Java 中,使用 mvn 进行依赖包的管理。第三,我们将代码提交到 git 仓库中,所有针对环境变更的操作,都应该遵循 Build/Release/Run 的流程严格区分开。现在 Jenkins 可以很好的达到这个效果,在在 Jenkins 中创建一条流水线包含多个任务,分别是:程序构建变异、构建镜像。镜像上传;最后针对 K8s 的发起一次对应的 workload 的变更。EDAS Core 将开源四步变成一步EDAS 团队提供了一种更简便的方式,它是产自于阿里云云产品 EDAS 的一个简单的实现,包括 EDAS 中的部分应用周期管理和微服务治理能力,且自带 webshell,他最简化的安装只需要 4C8G。它轻量、简便,笔记本上可拉起,也可安装在任意一套标准的 K8s 集群上,可免费用于开发测试。可以将上述步骤四步变成一步:安装步骤第一步,我们先将 EDAS Core 的安装包下载,并解压。第二步,将确认好集群相关的 kubeconfig 文件并放至对应的位置。第三步,进入到安装目录并执行安装脚本,整个过程大概历时 7-8 分钟。使用 EDAS Core 无需准备复杂的 Dockerfile 和镜像,只需要依次选择相对应的环境,并上传常规的程序包上传并设置相应的规则参数就好了。而且微服务相关的 Nacos 组件搭建、地址参数配置等都会默认管理好。同时使用 EDAS 也做了一个官方 Jenkins 插件专门用来和 Jenkins 对接,只需要在插件中提供 EDAS 应用 ID,和部署包的地址。就可以完成流水线的对接。微服务开发下的痛点环境搭建只是第一步,微服务的开发中,其中一个痛点是一个系统是自己开发的应用,如何加入到一个原来大的生态集群中。以及两个应用需要同步上线一个新的能力,如何在不影响别人的情况下,这个两个人可以根据一定流量规则进行精准联调。如下图:端云互联为了解决上面的两个问题,我们推荐给您的是 Alibaba Cloud Toolkit 中的《端云互联》功能,在这个方案中只需要提供一台 ssh 端口能联通的跳板机就能很完美的解决上面两个问题:同时在精准联调的场景下,可以在 EDAS 中创建一个泳道组并指定好入口应用,在云上设置好流量规则。同时让两个开发人员同时加入到这一个泳道组中。随后所有满足规则的流量则会精准的路由到彼此的节点上。不仅如此,Cloud Toolkit 中还提供了另外一个能力是可以直接从 IDE 中一键部署到环境中,也提供了一键进入 POD 的 Webshell 能力,方便我们进行排查诊断,此能力近期也会上线在 EDAS 商业版本中。当我们把所有的应用都开发好了之后,我们要面对很多新的环境的准备,比如我们要准备新的测试环境、压测环境、预发、生产 等等,运维同学每一次准备环境的过程都会随着应用的增多而备受煎熬。EDAS Core 针对这种场景,特开发了一键将所有应用上云的功能。最后的彩蛋:成都环境推出免费版本为了打消上云之后有的同学会担心所花费的商业版本的费用的顾虑,EDAS 在 8 月底的时候,在成都环境公测了一种新的应用形态,这种形态下 EDAS 将管控、微服务治理、APM 监控三个能力进行了分拆,大家可以根据自己的需要灵活定制,欢迎大家试用反馈。
作者:杨翊(席翁)距离 2.1.1 版本发布2个月后,Nacos 社区又迎来一波大更新。本次发布包含了 2 个 server 版本,1 个 go-sdk 版本以及新语言 SDK 的预告。Nacos 2.1.22.1.2 主要增强了控制台的 UI 效果,变更了控制台的样式,使得内容更加紧凑美观;另外 2.1.2 对客户端大小进行了优化,大幅降低了客户端的 jar 包大小,同时还提供了纯净版 java-client,方便没有依赖 gRPC 或希望使用非 shaded 版本客户端用户使用,可以到 Java SDK[1] 中查看纯净版使用方式。最后 2.1.2 修复了许多旧版本的问题,提高了稳定性。具体变更内容可参考变更日志:## Enhancement [#6112] Unified derby-data variables. [#7929] Reduce nacos-client jar size by minijar. [#8941] Support Fuzzy Query in Authority Control--for api change. [#8956] Internationalize product description content in nacos console. [#8976] Create new namespace with duplicate namespace show name. [#9091] build pure nacos-client when release. [#9210] Naming Distro sync support revision. ## Refactor&dependency [#8611] Close old datasource connection. [#8650] Make cluster/report both receive and send metadata. [#9013] refactor rpcClient and grpcClient to support set configuration. [#9014] refactor TpsMonitorPoint. [#9177] Upgrade org.yaml.snakeyaml version from 1.30 to 1.32 [#9325] Add switch for naming async query. ## BugFix [#8882] Fix nacos-client 2.1.0 start error when using endpoint configuration. [#8910] Fix calculate instance count error when using batch register. [#8925] Fix the value of hasQueryString is always false. [#8928] Fix the replaceAll operation is invalid for server list. [#8931] Fix BatchInstanceData can't serialize problem. [#8934] Fix header lost when request retrying. [#8947] Fix the authentication/encryption plugin are not loaded on the nacos server. [#9023] Fix corner case config dataId 'cipher-' can't be create. [#9047] Fix ServerListMgr is not shutdown in nacos-client. [#9060] Fix print logs for NamingTraceEvent continuously. [#9062] Fix unsubscribe service failed problem. [#9101] Fix the ConnectionTimeout property in the datasource connection is overwritten problem. [#9227] Fix instance change event subscribe failed in 2.1.1 when no setting scope. [#9230] Fix error event order for snapshot loading. [#9269] Fix RpcClient parse ipv6 address error problem. [#9271][#6876] Fix 'JraftServer' NPE after server exceptionally shutdown. [#9277] Fix ClientServiceIndex not clean when service removed. [#9305] Fix build resource with error dataId. [#9311] Fix cache not removed when listener adding delay. [#9323] Fix service checking problem in 1.x http openAPI.2.2.0-BETA2.2.0 版本是 2.X 中一个较为重要的版本,它包含了一些较为重大的改动:首先,2.2.0 将会删除旧的冗余代码,即 1.X 模式服务发现和双写相关代码。删除后,2.2.0 版本将无法从 Nacos 1.X 服务器升级,只能从至少 2.0.0 版本升级。此更改不会影响对 1.X 客户端请求的适配,用户仍然可以使用 1.X 客户端链接 2.2.0 版本服务端。其次,2.2.0 将会合并部分阿里巴巴编程之夏 2022 和开源之夏 2022 的课题结果,例如V2 版本的 openAPI[2]和数据源插件[3]。其他课题也将在未来版本中发布。最后,2.2.0 增强了在 2.1.1 版本被列为 beta 功能的轨迹追踪插件和批量注册,这使它们更易于使用。关于如何开发和使用轨迹追踪插件,可以参考文末插件文档[4]进行开发。由于这个版本中有许多重要的变化,所以社区计划做一个预发布的 BETA 版本。根据 BETA 测试的结果,下一个版本计划是 BETA2 或 GA 版本,欢迎广大用户积极下载[5]试用测试,帮助社区尽早发现问题。注意:2.2.0-BETA 是一个预发布的 beta 版本,可能存在一些问题,请尽量避免在生产环境中使用。2.2.0-BETA 版本具体变更内容可参考变更日志:## feature [#5863][#9331] Support batch register and batch deregister service. [#8308] Add v2 openAPI for nacos 2.0. [#8312] Support datasource plugins. [#8481] Support track tracing plugins. [#9366] Support Ldaps authentication. ## Enhancement [#7930] Reomve old redundant codes about 1.x naming. ## BugFix [#9334] Fix group_id data length different in many tables. [#9341] Fix can not create bean ldapAuthenticationProvider. [#9351] Fix instance count error in prometheus metrics.多语言 SDKGoNacos Go SDK v2.1.1[6]版本也在近期发布了正式版本,在 v2.1.0 带来大量新特性和改进的基础上,进一步加强了使用的稳定性,欢迎大家升级使用。RustRust 语言是最近非常如火如荼的新编程语言生态,Nacos 社区的小伙伴第一时间加入了对 rust 生态的建设,目前 nacos-rust-sdk[7]已完成基础的功能建设工作,同时实现了配置中心的核心功能,已发布 v0.1.1 版本供社区试用。随着社区小伙伴的逐渐完善和更多愿意贡献的贡献者加入,nacos-rust-sdk 很快也能够支持注册中心的功能,发布 1.0 的正式版本,这里也欢迎更多对 rust 有兴趣,希望找个项目练手的小伙伴加入一起建设 nacos-rust-sdk。PHPPHP 语言作为老牌服务端编程语言,以往有不少用户询问关于 PHP 客户端的问题;虽然社区中有很多根据 openAPI 自行开发的 PHP 客户端,但一直没有功能较全的版本和愿意持续维护捐献的 PHP 客户端实现,导致社区中一直没有属于 nacos-group 的 PHP 客户端。今年由 huangwh2014 贡献到社区的 PHP 客户端终于能够让 PHP 的项目能够接入 Nacos,享受 Nacos 所带来的各种功能。由于该版本的 PHP 客户端[8]仍然是基于 openAPI 进行开发的,因此不具备 gRPC 的能力,希望社区的各位小伙伴积极参与项目,早日让 PHP 客户端进入 2.X 的时代。社区编程之夏&开源之夏经历了 6 月-9 月的夏日,Nacos 的编程之夏和开源之夏活动也圆满结束。参与课题的9位同学也完成了他们的开源社区体验。在此期间,有些同学完成了 Nacos 新 openAPI,新插件的开发;有些同学完成了 Nacos 对 K8s,Mesh 化的探索;也有些同学深耕于 Nacos 客户端与服务端的协商机制。根据当前功能的完成程度和 Nacos 社区的版本的规划,这些重要的改动会在后续版本中逐渐与大家见面。在这里感谢参加编程之夏与开源之夏的同学和导师们的热情付出,同时也感谢阿里巴巴和中科院举办的优秀的开源活动。期待明年再见。CommitterNacos 社区新晋级了两位 Committer 同学。自由开发者 onewe 同学主要优化统一了 Nacos 客户端的配置参数的加载逻辑,同时优化了 LDAP 鉴权插件和大量控制台使用内容,找到并修复了不少 Nacos 的问题。经社区 PMC 及 Committer 的投票表决,提名为 Nacos 社区的 Committer。另外来自小米科技的 chenhao26-nineteen 同学主要完成了 Nacos 批量注册的新功能,并且使用该新功能优化了 Nacos-Sync 的同步逻辑,极大提升了 Nacos-Sync 的性能,同时也修复了不少 Nacos 的问题。经社区 PMC 及 Committer 的投票表决,提名为 Nacos 社区的 Committer。期望更多小伙伴一起参与贡献~~About NacosNacos 致力于帮助您发现、配置和管理微服务。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据及流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。Nacos 是构建以“服务”为中心的现代应用架构 (例如微服务范式、云原生范式) 的服务基础设施。Nacos 社区同时也开启了关于 Nacos 3.0 的畅想和规划,欢迎社区积极参与到新版本的建设中。最后欢迎大家钉钉扫码加入 Nacos 社区群相关文档链接[1] Java SDKhttps://nacos.io/zh-cn/docs/v2/guide/user/sdk.html[2] V2 版本的 openAPIhttps://nacos.io/zh-cn/docs/v2/guide/user/open-api.html[3] 数据源插件https://nacos.io/zh-cn/docs/v2/plugin/datasource-plugin.html[4] 插件文档https://nacos.io/zh-cn/docs/v2/plugin/trace-plugin.html[5] 下载链接https://github.com/alibaba/nacos/releases/tag/2.2.0-BETA[6] Go SDK v2.1.1https://github.com/nacos-group/nacos-sdk-go/releases/tag/v2.1.1[7] nacos-rust-sdkhttps://github.com/nacos-group/nacos-sdk-rust[8] PHP 客户端https://github.com/nacos-group/nacos-sdk-php
本文作者:蔡高扬,Apache RocketMQ Committer, 阿里云智能技术专家。近期,RocketMQ Operator[1] 正式发布 0.3.0 版本,该版本包含了哪些特性与优化?让我们一探究竟。镜像地址:apache/rocketmq-operator:0.3.0OperatorHub地址:https://operatorhub.io/operator/rocketmq-operator重点特性ISSUE #39 支持 RocketMQ Dashboard 部署@liuruiyiyang将 RocketMQ Dashboard[2] 纳入RocketMQ Operator 管控,支持一键部署并管理 RocketMQ Dashboard,方便用户对 RocketMQ 进行白屏化管理。ISSUE #84 JVM参数生成适配容器化部署@overstep123RocketMQ 镜像的启动脚本中能根据实际的CPU、内存资源生成 JVM 启动参数,但计算资源时取的是宿主机的数据,通过 Kubernetes resources 设置的资源配额无法感知。在该 ISSUE 中,优化为先获取 cgroup 中的CPU、内存配额,如能获取到数据且不超出宿主机的资源大小,则以 cgroup 中的数据为准生成 JVM 启动参数。ISSUE #96 operator-sdk 版本升级@gobbqoperator-sdk 是 RocketMQ Operator 的基础代码与构建框架,先前使用的 0.11.x 版本已不再兼容,社区也有反馈使用现行 operator-sdk 无法构建,影响开发活动,因此将其升级为 1.16 版本。此外更新 apiextensions.k8s.io/v1beta1 等已废弃的 API 版本,使得 RocketMQ Operator 支持 Kubernetes v1.22及以上版本。ISSUE #105 支持从 Kubernetes 集群外部访问 @shangjin92Kubernetes 集群中的 RocketMQ 默认只能从集群中的 Pod 访问。为了使 Kubernetes 集群外的应用可使用 RocketMQ,扩展 Name Service CRD、Broker CRD 支持 hostNetwork,同时 Broker 向 Name Server 注册时使用 Node IP。外部应用访问 Name Server 的地址配置为 Name Server 所在的 Node IP,即可获取 Broker 的Node IP 从而访问到 Broker。更多的特性或bugfix可查阅release notes[3]。在这里对大家的贡献表示感谢,希望大家继续参与到新版本的贡献中。使用 RocketMQ Operator 快速部署 RocketMQ 集群接下来,我们使用 RocketMQ Operator 0.3.0 版本,展示如何在 Kubernetes 集群中快速创建部署一个 RocketMQ 服务集群,并支持应用从 Kubernetes 集群外访问。待部署的 RocketMQ 集群如下图所示:集群中包含2个 Name Server 和1个 Broker集群,Broker集群中包含2主2备,提供高可用服务。RocketMQ Operator 负责部署和管理这些模块。1、准备好一套 K8s 集群,并在你的 K8s 节点上配置好 kubectl 连接信息。2、克隆 rocketmq-operator 仓库到上一步的节点上$ git clone --branch 0.3.0 https://github.com/apache/rocketmq-operator.git $ cd rocketmq-operator3、执行如下脚本安装 RocketMQ Operator$ sh install-operator.sh4、检查 RocketMQ Operator 是否安装成功成功安装时,rocketmq-operator pod 处于 Running 状态:$ kubectl get po | grep rocketmq-operator NAME READY STATUS RESTARTS AGE rocketmq-operator-84466597d4-jxhgd 1/1 Running 0 28s5、构建用于 K8s 集群部署的 RocketMQ 5.0 镜像$ (cd images/namesrv/alpine/ && sh build-namesrv-image.sh 5.0.0 ) $ (cd images/broker/alpine/ && sh build-broker-image.sh 5.0.0 )6、apply CR 部署 RocketMQ 集群执行 kubectl apply -f demo_cluster.yaml,快速部署一个RocketMQ集群。demo_cluster.yaml 内容如下:apiVersion: rocketmq.apache.org/v1alpha1 kind: NameService metadata: name: name-service spec: size: 2 nameServiceImage: apacherocketmq/rocketmq-nameserver:5.0.0-alpine-operator-0.3.0 imagePullPolicy: IfNotPresent hostNetwork: true dnsPolicy: ClusterFirstWithHostNet resources: requests: memory: "2Gi" cpu: "1000m" limits: memory: "2Gi" cpu: "2000m" # storageMode can be EmptyDir, HostPath, StorageClass storageMode: EmptyDir # hostPath is the local path to store data hostPath: /data/rocketmq/nameserver # volumeClaimTemplates defines the storageClass volumeClaimTemplates: - metadata: name: namesrv-storage spec: accessModes: [ "ReadWriteOnce" ] resources: requests: storage: 1Gi --- apiVersion: v1 kind: ConfigMap metadata: name: broker-config data: broker-common.conf: | BROKER_MEM: " -Xms2g -Xmx2g -Xmn1g " flushDiskType=ASYNC_FLUSH # set brokerRole to ASYNC_MASTER or SYNC_MASTER. DO NOT set to SLAVE because the replica instance will automatically be set!!! brokerRole=ASYNC_MASTER --- apiVersion: rocketmq.apache.org/v1alpha1 kind: Broker metadata: # name of broker cluster name: broker spec: hostNetwork: true # size is the number of the broker cluster, each broker cluster contains a master broker and [replicaPerGroup] replica brokers. size: 2 # replicaPerGroup is the number of each broker cluster replicaPerGroup: 1 brokerImage: apacherocketmq/rocketmq-broker:5.0.0-alpine-operator-0.3.0 imagePullPolicy: IfNotPresent resources: requests: memory: "4Gi" cpu: "2000m" limits: memory: "4Gi" cpu: "4000m" allowRestart: true # storageMode can be EmptyDir, HostPath, StorageClass storageMode: EmptyDir # hostPath is the local path to store data hostPath: /data/rocketmq/broker # scalePodName is [Broker name]-[broker group number]-master-0 scalePodName: broker-0-master-0 env: - name: BROKER_MEM valueFrom: configMapKeyRef: name: broker-config key: BROKER_MEM # volumes defines the broker.conf volumes: - name: broker-config configMap: name: broker-config items: - key: broker-common.conf path: broker-common.conf # volumeClaimTemplates defines the storageClass volumeClaimTemplates: - metadata: name: broker-storage spec: accessModes: [ "ReadWriteOnce" ] resources: requests: storage: 2Gi上述例子仅供开发测试使用,因其 storageMode 的值配置为 EmptyDir,存储数据会随着 Pod 的删除而删除。在生产环境使用时,应使用 HostPath 或 StorageClass 挂载存储来持久化数据。两种配置的详细使用说明可参考 RocketMQ Operator 使用文档[4]。7、查看 Pod 状态,可查看成功部署2个 Name Server,4个 Broker。由于这些 Pod 采用 Host Network,其 IP 与所在节点的 IP 相同。# kubectl get po -owide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES broker-0-master-0 1/1 Running 0 79s 172.16.0.23 172.16.0.23 <none> <none> broker-0-replica-1-0 1/1 Running 0 79s 172.16.0.24 172.16.0.24 <none> <none> broker-1-master-0 1/1 Running 0 79s 172.16.0.25 172.16.0.25 <none> <none> broker-1-replica-1-0 1/1 Running 0 79s 172.16.0.251 172.16.0.251 <none> <none> name-service-0 1/1 Running 0 79s 172.16.0.25 172.16.0.25 <none> <none> name-service-1 1/1 Running 0 77s 172.16.0.23 172.16.0.23 <none> <none> rocketmq-operator-84466597d4-jxhgd 1/1 Running 0 37m 172.16.0.22 172.16.0.251 <none> <none>至此,RocketMQ Operator 已成功拉起一套 RocketMQ 集群。接下来我们对该集群进行检查。查看集群状态进入任意一个 Broker Pod,执行 sh mqadmin clusterlist 查看集群信息:$ kubectl exec -it broker-0-master-0 -- sh ~/rocketmq/broker/bin # sh mqadmin clusterlist #Cluster Name #Broker Name #BID #Addr #Version #InTPS(LOAD) #OutTPS(LOAD) #Timer(Progress) #PCWait(ms) #Hour #SPACE #ACTIVATED broker broker-0 0 172.16.0.25:10911 V5_0_0 0.00(0,0ms) 0.00(0,0ms) 0-0(0.0w, 0.0, 0.0) 0 462803.97 0.1100 true broker broker-0 1 172.16.0.24:10911 V5_0_0 0.00(0,0ms) 0.00(0,0ms) 2-0(0.0w, 0.0, 0.0) 0 462803.97 0.1200 false broker broker-1 0 172.16.0.23:10911 V5_0_0 0.00(0,0ms) 0.00(0,0ms) 0-0(0.0w, 0.0, 0.0) 0 462803.97 0.1100 true broker broker-1 1 172.16.0.251:10911 V5_0_0 0.00(0,0ms) 0.00(0,0ms) 2-0(0.0w, 0.0, 0.0) 0 462803.97 0.2200 false在上图的例子中,可以见到有两组 Broker 集群,分别是 broker-0、broker-1,每组集群中,BID=0的是主节点,其余为备节点。消息收发测试在上述 K8s 集群之外的一台机器(需与 K8s 节点网络可达)中,安装 JDK 等依赖包,下载 RocketMQ 并解压:$ yum -y install java-1.8.0-openjdk-devel unzip telnet $ wget https://archive.apache.org/dist/rocketmq/5.0.0/rocketmq-all-5.0.0-bin-release.zip unzip rocketmq-all-5.0.0-bin-release.zip 设置 NAMESRV_ADDR 环境变量,其值为 Name Server 所在节点 IP:9876(本例子中取 172.16.0.25:9876)。进入解压后的目录,运行 tools.sh 脚本启动示例 Producer 发送消息:$ export NAMESRV_ADDR=172.16.0.25:9876 $ sh bin/tools.sh org.apache.rocketmq.example.quickstart.Producer SendResult [sendStatus=SEND_OK, msgId=7F0000010C9B76ED55285BE804980000, offsetMsgId=AC10001900002A9F0000000000000000, messageQueue=MessageQueue [topic=TopicTest, brokerName=broker-0, queueId=0], queueOffset=0] SendResult [sendStatus=SEND_OK, msgId=7F0000010C9B76ED55285BE804B70001, offsetMsgId=AC10001900002A9F00000000000000E7, messageQueue=MessageQueue [topic=TopicTest, brokerName=broker-0, queueId=1], queueOffset=0] SendResult [sendStatus=SEND_OK, msgId=7F0000010C9B76ED55285BE804B90002, offsetMsgId=AC10001900002A9F00000000000001CE, messageQueue=MessageQueue [topic=TopicTest, brokerName=broker-0, queueId=2], queueOffset=0] ...继续运行 tools.sh 脚本启动示例 Consumer,将打印刚才发送的消息:$ sh tools.sh org.apache.rocketmq.example.quickstart.Consumer Consumer Started. ConsumeMessageThread_please_rename_unique_group_name_4_1 Receive New Messages: [MessageExt [brokerName=broker-1, queueId=0, storeSize=231, queueOffset=0, sysFlag=0, bornTimestamp=1666095532223, bornHost=/172.16.0.38:43968, storeTimestamp=1666095532234, storeHost=/172.16.0.23:10911, msgId=AC10001700002A9F0000000000000000, commitLogOffset=0, bodyCRC=601994070, reconsumeTimes=0, preparedTransactionOffset=0, toString()=Message{topic='TopicTest', flag=0, properties={MIN_OFFSET=0, TRACE_ON=true, MAX_OFFSET=125, MSG_REGION=DefaultRegion, CONSUME_START_TIME=1666095549194, UNIQ_KEY=7F0000010C9B76ED55285BE804BF0004, CLUSTER=broker, WAIT=true, TAGS=TagA}, body=[72, 101, 108, 108, 111, 32, 82, 111, 99, 107, 101, 116, 77, 81, 32, 52], transactionId='null'}]] ...未来展望下一步 RocketMQ Operator 将全面拥抱 RocketMQ 5.0,重点实现主备自主切换集群支持、Proxy部署、Container对等部署、Docker镜像与 rocketmq-docker 项目统一等特性,持续完善 RocketMQ Operator 。欢迎大家使用RocketMQ Operator,提出宝贵建议,也可以通过调查问卷[5]方式向社区提供你的使用场景、期望特性等信息。相关链接[1] RocketMQ Operator项目:https://github.com/apache/rocketmq-operator[2] https://github.com/apache/rocketmq-dashboard[3] Release Notes: https://github.com/apache/rocketmq-operator/releases/tag/0.3.0[4] https://github.com/apache/rocketmq-operator/blob/master/README.md[5] https://github.com/apache/rocketmq-operator/issues/20加入 Apache RocketMQ 社区十年铸剑,Apache RocketMQ 的成长离不开全球接近 500 位开发者的积极参与贡献,相信在下个版本你就是 Apache RocketMQ 的贡献者,在社区不仅可以结识社区大牛,提升技术水平,也可以提升个人影响力,促进自身成长。社区 5.0 版本正在进行着如火如荼的开发,另外还有接近 30 个 SIG(兴趣小组)等你加入,欢迎立志打造世界级分布式系统的同学加入社区,添加社区开发者微信:rocketmq666 即可进群,参与贡献,打造下一代消息、事件、流融合处理平台。微信扫码添加小火箭进群另外还可以加入钉钉群与 RocketMQ 爱好者一起广泛讨论:钉钉扫码加群关注「Apache RocketMQ」公众号获取更多技术干货
本文作者:李伟 - Apache RocketMQ Committer,RocketMQ Python客户端项目Owner ,Apache Doris Contributor,腾讯云消息队列资深开发工程师,著有《RocketMQ分布式消息中间件(核心原理与最佳实践)》。RocketMqueue101RocketMQ拥有诸多出色的特性:比如多副本机制,RocketMQ支持存储层的多副本Dledger,它是基于 Raft 协议的一致性存储库,保证能够从存储层实现多副本;比如ACL 鉴权机制,用于确定哪些 producer 能生产、哪些消费者组能消费,以及服务端的消息过滤;比如事务消息,它是 RocketMQ 实现的生产者事务,生产者向 broker 发送一条事务消息,由生产者执行本地事务。如果执行成功,则向 broker 端发送 commit 事件,消费者才能消费;如果本地事务处理失败,则发送rollback事件,使消费者无法消费该消息。比如Request-Reply ,它是类似于同步 RPC 调用的过程,用户相同的逻辑用消息来实现,能够实现同步 RPC 调用的过程,可以将调用API和发送消息两套逻辑进行统一。广播消息指消息发出后,订阅它的所有消费者都能消费到所有实例。负载均衡消费指默认策略下,同一个消费者组的消费者都能平均地消费消息,具体策略可自行调整。RocketMQ支持Pull、Push和Pop三种消费模式,支持java、go、cpp、python、c#等多种语言。搭建RocketMQ集群的流程如下:第一步:安装NameServer集群。NameServer集群包含一个或多个NameServer节点。启动服务时,默认监听 9876 端口。NameServer集群搭建好之后,启动一套Broker集群。第二步:搭建Broker集群,使用经典master-slave部署模式, master 提供读写,同时会将数据存储和元数据同步一份到 slave 。通过 10912 的 HA 端口做数据同步。第三步:写生产者代码生产。生产者集群包含多个生产者实例,通过 broker 的 10911 和 10909 端口向 broker 发送数据。第四步:消费者通过 10911 或10909端口向 broker 拉取数据。生产者或消费者实例启动时,会先配置NameServer地址,由生产者或消费者从NameServer集群上拉取topic、Queue和Broker等路由信息,然后根据路由信息发送或拉取消息。生产者和消费者均与broker之间存在 channel 连接。如果生产者或消费者长时间没有与 broker 联系,则 broker 会将连接剔除。以下为RocketMQ101相关名词解析:生产者包含生产者组和生产者实例。生产者组是若干个生产者实例的组合,且RocketMQ希望同一个生产者组内的实例行为一致。消费者组和消费者实例也同理。行为一致指生产者实例都生产同一种类型的消息,比如都生产订单消息,包括创建订单、订单发货、订单删除等步骤。行为一致的好处在于消息的生产和消费比较规整,不会出现混乱。Topic 是消息的分类,为字符串形式,可以通过 topic 将某集群内的全部消息进行分类,所有 topic 的消息组成全量的消息。而Tag 又属于 topic 的子分类。消费者在订阅消息时,必须先指定topic再指定 tag ,这样的一条记录被称为订阅关系。如果订阅关系不一致,则会导致订阅混乱,发生重复消费或不消费、消息堆积等情况。Queue类似于分区,但它是逻辑上的概念,并不是物理存储上的概念。Property类似于 header,property 包含除了主要信息以外的扩展信息,比如消息属于哪个业务 ID、发送者IP 等。向某个 topic 发送消息时,能够指定 property 。NameServer中包含 broker 与 cluster 的关系、Queue\ topic 与broker 的关系,即路由信息。Broker中包含以下四部分:① CommitLog——常规的文件存储。RocketMQ 发送的数据会append到 CommitLog。② Consumer queue——消费者在消费 topic 时,topic 中包含多个queue,每一个queue都被称为 consumer queue,每个消费者对于每个 consumer queue 都存在消费进度。③ index——在 dashboard 上能够根据 key 来查询消息。④ Dledger commitlog——由Dledger 存储库来管理的 CommitLog,能够实现多副本。RocketMQ的生产消费模型十分简单。如上图,Topic A 有四个queue,其中 queue1、queue2 在 Master Broker 1 上,queue3、queue4在 Master Broker 2 上。ProducerGroup A 下有两个生产者实例,分别向两个 broker 的 queue 发送消息。Consumer Group A 也有两个消费者 consume 1和consume 2。从四个queue里取消息时,每个消费者默认的策略是依次向 queue1、queue2、queue3、queue4 循环发消息,以此最大程度地保证消息分布均匀。消费者的消费模式有负载均衡和广播消费消费两种。负载均衡策略下,比如共有4条queue,则consumer instant1和consumer instant2会分别被分配到2个queue,具体分配到哪两条需由算法决定。广播消费策略下,假设 topic 有 100 条消息,则 consumer instance 1 和 consumer instance 2每一个消费者实例都会消费到 100 条消息,即同消费者组的每个消费者示例都会消费到全量的消息。RocketMQ 生态项目RocketMQ生态项目包含以下几个部分:客户端:客户端主要分为Java客户端与非Java客户端,其中RocketMQ Java 客户端是最原生的客户端,与RocketMQ的编写语言一致,功能也最为齐全。计算:RocketMQ支持轻量级的预计算,比如轻量级的 ETL。RocketMQ-Flink 能够直接对接 Flink,方便将RocketMQ数据传输到 Flink 做计算,利用 Flink 强大的生态同步到下游多种类型的目的地。RocketMQ-Connect与RocketMQ-Streams是轻量级的计算框架,功能更简单、轻量,部署运维也更容易。管控:RocketMQ-Dashboard 拥有简单稳定且功能强大的管控端,能够支持常用的运维操作比如修改配置、禁用消费者等。云原生:RocketMQ-Docker 支持打包 RocketMQ 源码成为Docker image 项目,能够支持各种不同平台的打包。RocketMQ-Operator支持RocketMQ上K8s,能够支持比如重启进程、下发配置、拉起集群等操作。监控:RocketMQ-Exporter目前能够支持80+指标,可直接导入到Prometheus做告警和监控。开源项目可通过Prometheus的数据配置 Grafana 做大盘,实现监控能力。此外,Prometheus能够支持Hook回调,方便公司用户将RocketMQ指标监控对接到自己的告警平台。云原生是技术行业的趋势,能够减少成本、方便运维和管理。RocketMQ新版本实现了存储计算分离,支持更快速、更方便地上 K8s 。EDA 事件驱动和无服务也是大势所趋,比如腾讯云的云函数、阿里云的 eventbridge 等产品都是 Serverless、EDA场景,能够直接集成RocketMQ。微服务领域,RocketMQ也提供了诸多原生支持。电商、金融等传统领域正在进行数字化转型,消息传递、指标、日志传递等需求都能够利用 Rocket MQ 简单快速地实现。总而言之,RocketMQ能够利用自己强大的生态项目,支持企业各种各样形态的数据传输和计算。RocketMQ数据流构建RocketMQ的数据流构建主要包含消息、CDC数据流、监控数据流以及湖仓数据流。CDC数据主要负责记录记录数据变更,监控数据流包括业务监控和常规监控。消息的构建如上图所示。以订单服务为例,订单服务收到创建订单的请求,创建成功后会将订单的基本信息通过RocketMQ发送给 B 服务。假设B服务为短信服务消费,由B服务向客户发送短信通知,包含订单相关的详细信息。RocketMQ发送消息至B服务时,通过重试和死信实现最终一致性,以保证消息能够成功发送给消费者。RocketMQ有 16 次重试机会,且为阶梯性重试,能够持续十几个小时。RocketMQ 支持通过Canal/Flink CDC、RocketMQ-collect 的方式,将 Binlog 等数据提供给计算平台,再由RocketMQ Flink、RocketMQ Streams 等进行轻量级的计算。计算完成后,将结果转发给下游数据库比如MySQL、ES、Redis等,进行异构或同构的数据同步。RocketMQ支持从flume读取日志文件发送至RocketMQ,再通过 RocketMQ Collect 或RocketMQ Flink等将日志数据进行消费、ETL 转换或发送至 ES 。ES 已与ELK 产品打通,可以在 Kabana上查看日志。除了日志,RocketMQ能够在业务系统做后端监控埋点,通过 RocketMQ client 将监控埋点数据发到RocketMQ,再通过RocketMQ Flink 或RocketMQ Streams 消费数据并发送给业务监控平台或数据湖仓库等,生成在线报表或实时报表。前端监控大部分通过 HTTP 请求发送至RocketMQ,再通过RocketMQ相关的轻量级计算框架,根据不同诉求将数据汇总至不同的后端,比如 ES 或自建平台。所有数据都能入到湖仓,因为所有数据都会有数据分析、数据挖掘或出统计报表的诉求。比如前后端的监控、 TP 数据库里的业务数据、日志文件的指标数据或日志文件都能通过对应的工具发到 RocketMQ,通过RocketMQ 提供的轻量级计算工具进行计算,然后发送到下游的 Hive、Doris、Clickhouse 或Hudi等数据库或数据仓库,产出报表、实时大盘、实时数据表等。RocketMQ 能够采集各种数据,比如metrics、TP数据、log的数据,然后通过RocketMQ 提供的轻量级计算工具进行计算,最终汇总到同构/异构的数据库、数据仓库或数据湖等。数据构建流程中,RocketMQ 作为中间核心的传输链路,是否能够借助本身的特性避免偶然性的因素影响数据的传输?RocketMQ 的架构十分简单,而简单也意味着稳定和可靠。因此,使用RocketMQ 做核心数据链路时,其稳定性和可靠性能够避免很多意外,减少不可控因素。网络抖动往往无法避免,它可能导致数据丢失,而RocketMQ 能够通过重试机制保证数据的最终一致。比如消息只发一半时发生了网络抖动,网络恢复如何保证数据最终能够被消费者完整地消费?默认的消费机制下,RocketMQ 有16次重试机会,按阶梯重试,重试间隔逐渐增加,最大限度地让消费者能够消费到数据。如果 16 次重试后依然没有消费成功,则消息会进入死信队列,由人工介入处理。产生死信消息后,RocketMQ 能够产生告警,以快速发现并处理问题。针对数据丢失,RocketMQ 提供了消息轨迹,帮助快速定位,找到问题所在。消费者消息是否成功发送、 broker 是否存储成功、消费者是否成功消费到等问题,都可以通过消息轨迹进行确认。针对带宽打满的问题,RocketMQ提供了服务端过滤的功能。假设Topic内是访问日志,将 tag 设为域名,消费者组可以只订阅某个域名下的访问日志,RocketMQ能够在服务端对消息进行过滤,再发送给消费者组。Broker 只会将属于消费者的域名消息发送给消费者,不会发送所有消息,因此能节约大量带宽,可高达80%-90%。RocketMQ 5.0RocketMQ5.0 架构有两个重大改变,实现了存储计算分离以及轻量级客户端。存储和计算分离主要为数据层面,将做存储和计算的 broker 拆分成了存储的 broker 和计算的 broker,两类broker各司其职,分别负责存储和计算。此前,RocketMQ的客户端生态较为丰富,但各个客户端的功能差异较大,难以实现一致。RocketMQ5.0 彻底地解了该问题,实现了轻量级的基于gRPC的多语言客户端。RocketMQ5.0 将此前客户端的重逻辑比如 rebalance 等转移至由Cbroker负责处理,使客户端逻辑变得非常轻量,客户端只剩消息消费或发消息调用接口,各个语言的逻辑容易统一,兼容性更好,不会出现实现方式不同导致逻辑不一致。RocketMQ5.0 除了存储和计算分离以外,还实现了数据面和控制面的拆分。控制面主要负责接入,此前只能通过NameServer的方式接入,而现在除了NameServer以外还提供了一种新的通过LB Group的方式接入,更简单易用。LB Group 能够方便大家用更简单的方式接入,逻辑集群的接入可以通过LB group 来实现,比如哪些客户端应该连到哪些集群,这也是NameServer难以实现的能力。一组NameServer会管理一个物理集群,物理集群可拆分为多个逻辑集群,每个逻辑集群能够分给不同的租户使用。Rocket MQ 可以看作是一个通道,通道有上游和下游,且不同行业的上下游不一样,通道中的数据也不一样。互联网已经涉及到每一个领域,但是垂直领域的发展依然非常欠缺。比如配送互联网涉及到交通运输等,需要有交通运输方面的专家与互联网技术进行深度结合,才能对配送行业引起深远广泛的影响。未来,我们需要技术人员深耕于某一行业,做出真正适用于行业的优秀的互联网产品。当前,RocketMQ已经能够支持事件和流。工业互联网行业非常重要的一个元素是IoT事件,它可能来自于各种终端设备,每天都会产生大量的、持续的事件,这些大量的数据都需要队列进行传输,提供给下游做计算。因此,RocketMQ未来的发展将着力于事件和流。RocketMQ已经推出了 RocketMQ Collect、RocketMQ Flink和RocketMQ streams ,在流计算上逐渐发力,形成了一整套完善的生态,能够帮助用户快速构建流式应用。而消息更是 RocketMQ 的擅长之处,能够帮助用户在不同场景的消息下方便、快速地接入使用。RocketMQ 已经开源了MQTT等协议,使接入设备更快速方便。随着RocketMQ 5.0的发布,RocketMQ 在处理消息、事件和流上实现了统一,有了越来越强大的优势,存储和计算分离的特性也使其能提供更低的成本,使企业上云更省钱、更省力,也更省人力。加入 Apache RocketMQ 社区十年铸剑,Apache RocketMQ 的成长离不开全球接近 500 位开发者的积极参与贡献,相信在下个版本你就是 Apache RocketMQ 的贡献者,在社区不仅可以结识社区大牛,提升技术水平,也可以提升个人影响力,促进自身成长。社区 5.0 版本正在进行着如火如荼的开发,另外还有接近 30 个 SIG(兴趣小组)等你加入,欢迎立志打造世界级分布式系统的同学加入社区,添加社区开发者微信:rocketmq666 即可进群,参与贡献,打造下一代消息、事件、流融合处理平台。微信扫码添加小火箭进群另外还可以加入钉钉群与 RocketMQ 爱好者一起广泛讨论:钉钉扫码加群关注「Apache RocketMQ」公众号,获取更多技术干货
作者:丁宇11月5日,2022杭州·云栖大会上,阿里巴巴研究员、阿里云智能云原生应用平台总经理丁宇在云原生峰会上发表主题演讲,提出云原生激活应用构建新范式,并表示Serverless将引领下一代应用架构。阿里云将坚定推进核心产品全面Serverless 化,帮助客户最大限度的减轻运维工作,更好的实现敏捷创新。云计算时代,企业上云后,应用构建依然面临很多挑战,如何保障系统资源的弹性、降本增效;如何做到应用敏捷开发,实现业务快速迭代;如何保障系统的稳定以及业务的连续性,这些问题没有完全解决。我们看到,云原生已经变成非常流行的技术趋势,从上云到用云,云原生能够从PaaS 层面帮助企业解决应用构建的一系列问题。具体有三大范式正在成为现实:第一个范式是全面容器化。因为容器形成了运维的标准,成为企业上云用云的新界面,也变成开发者和应用系统交互的新界面,有利于构建高弹性、可伸缩的系统,从而实现降本增效。当下所有的负载都在容器化,包括耳熟能详的微服务、在线应用到整个数据库、大数据、AI、中间件等,所有的工作负载都在容器化。通过容器,我们可以享受到运维标准化、弹性架构带来的好处,也带来了软件可以无处不在的部署交付,标准化的管理运维。第二个范式是整个行业应用的核心技术互联网化。我们正在用互联网的技术、互联网的架构思想来重构应用系统,从而带来了很多好处:分布式可扩展,支撑业务敏捷迭代,构建弹性架构,从容应对流量高峰。举例来说,准备一场促销活动、一场跨年晚会,都可能有不可预期的流量高峰,数字化系统需要应对不确定的流量,必须要用互联网架构来实现;此外保障系统高可用、高可靠,保障业务的连续性,也是互联网技术能够带给企业的红利。第三个范式是应用的Serverless化。从技术角度来看,能够实现技术组件分层解耦,让应用可以做到全托管免运维,提升系统的可运维性,降低成本。通过极致弹性,能够把所有的组件覆盖,在云上构建应用变得非常简单。以前构建应用,需要买ECS实例,搭建开源软件体系然后维护它,流量大了扩容,流量小了缩容,整个过程很复杂繁琐。用了Serverless服务以后,这些问题都简化了,从半托管到全托管,所有的服务API化,无限容量充分弹性,可以组装使用,能够感受到生产力大幅度的改变。也会在软件开发的全生命周期进行优化,升级研发模式,让开发者更多的聚焦在业务上,加速迭代。以上这三个范式代表着云原生非常主流的演进方向。全面容器化:容器服务进入智能化时代Gartner预测,到2022年,超过75%的全球组织会在他们的生产环境中运行容器化的应用,而这一数据在2020年才不到30%。 我们看到,容器技术已经跨越鸿沟,从早期的互联网行业到现在的千行百业,都在生产系统中使用。虽然 ACK 大幅降低了K8s的门槛,但管理和运维一个大规模、分布式的集群依然充满挑战,比方说,如何调度应用,在保障稳定的同时,提升资源利用率;如何对应用进行成本规划、分析优化;当集群出现问题后,如何及时的定位和修复。智能化可以解决这些问题,智能化是容器平台发展的必然趋势。阿里云基于过去10年的大规模容器实战经验,通过数据化手段和智能化算法,推动容器服务ACK走向智能化。其中有三个升级:第一个升级,智能化的混部调度,新一代调度系统Koordinator,帮助用户提升整体资源利用率,智能化混部调度助力识货 App节省 20% 资源成本。第二个升级,智能化的成本治理,容器服务 FinOps套件,帮助用户实现上云成本可见、可控、可优化,中华保险基于容器 FinOps 套件实现资源闲置率从30%降低到 10%。第三个升级,智能化的运维体验,容器服务 AIOps套件,帮助用户实现数据驱动诊断决策,助力故障防御定位,自动化诊断可以覆盖 90% 以上的问题,得物 App 基于容器 AIOps 套件定位问题时间从周缩短到小时。这些能力升级,会进一步降低容器技术的使用门槛,让 ACK 做到普惠化,服务更广泛的客户群体。核心技术互联网化互联网中间件产品有三个特点:第一个就是开源全兼容,完全没有厂商锁定,像微服务、消息、服务注册发现、网关等,都是跟开源完全兼容的。第二个特点是大量的企业级特性加持,包括性能、稳定性、扩展性等。互联网分布式技术的先进性需要非常好的场景锤炼,阿里云的优势就在于多年双11复杂场景的打磨,基于双11的加持以及海量客户的应用,使得阿里云互联网技术在企业级特性上有非常强劲的优势。第三个特点有丰富的技术类解决方案,包括异地多活,应用容灾的方案、技术中台、业务中台的方案,以及混部、混沌工程和全链路压测方案等。云原生中间件实现了开源、自研和商业化的三位一体,能够助力更多企业使用标准开放的技术实现数字化转型。重磅发布一 微服务再升级:新增云原生网关开源云原生时代,微服务面临着新的诉求和技术挑战,尤其是在性能、高可用性和安全性方面。今天,阿里云正式开源云原生网关 Higress,它是业内首个标准化、高集成、易扩展、热更新的云原生网关。标准化:随着K8s的普及,K8s Ingress 逐渐成为云原生时代API事实标准, Higress全面支持该标准,并且在服务治理方面(包括灰度、限流、预热、超时、重试)做大幅增强,引领标准演进方向。高集成:Higress首次将流量网关、微服务网关、安全网关三合一,打造高集成网关,在入口建立高性能、安全防线,后端支持K8s/Nacos/ECS/Serverless多种运行时路由,打造功能最强大网关实现。易扩展:Higress提供最丰富插件扩展机制,满足客户灵活路由和安全定制需求,支持最全面语言扩展机制;当然我们为了降低客户使用门槛,默认集成了数十个插件,并且通过插件市场方便开发者贡献通用能力,产生良性互动。热更新:由于传统Nginx更新规则需要reload会导致链接抖动,导致流量损失,对实时通信、视频、IoT无法容忍,因此Higress 从证书、路由、安全规则、插件全部采用热更新机制,毫秒级生效且业务无感知。除了开源云原生网关之外,阿里云全面升级微服务引擎MSE3.0,包含三大核心能力:第一大能力是注册配置中心,相比Nacos等主流开源方案,性能提升40%,提供70+的监控指标,提供健康检测,帮助客户实现服务异常自治,例如禾连健康这家医疗行业的SaaS企业,通过MSE注册配置中心,提升开源注册配置中心性能达50%,解决了业务高速发展中的扩展性问题,保障全国 200 多个城市、2000 多家医院体验业务的稳定性超99.99%。 第二大能力是微服务治理,沉淀了阿里巴巴10+的实践经验,帮助客户缩短30%微服务治理落地周期,提升50%开发测试效率,消除80%线上风险。例如纺织产业互联网企业致景科技,未修改任何代码就接入了MSE微服务治理所有能力。微服务实施周期下降 30%,构建开发测试环境从天降低到分钟。第三大能力是云原生网关,阿里云将流量网关、微服务网关、安全网关三合一,架构上也做了升级,将实例级防护升级至路由级防护,整体性能相比传统网关提升90%。例如移动支付企业费芮互动利用MSE构建了零信任架构,大幅提升业务入口安全性,通过软硬一体完成TLS卸载,性能提90%,并采用软硬件一体化,响应时间下降50%。重磅发布二 可观测再升级:让可观测数据价值最大化云原生时代,系统架构日趋复杂,提升可观测能力成为降低复杂度的唯一手段。今天可观测能力成为度量企业IT水平的标准,成本治理、业务连续性、业务增长都需要可观测技术。因此阿里云推出云原生可观测套件ACOS,从应用监控到链路追踪,帮助企业实现成本管理、风险治理、智能运维、保障数字化业务高效稳定的运行。本次云栖大会,阿里云云原生可观测套件ACOS三大组件也迎来重要升级。首先, Prometheus已成为不少企业的观测首选。作为容器观测事实标准的Prometheus监控,已成为阿里云50多款云产品的默认观测基础设施,并与应用实时监控服务ARMS的APM指标、eBPF指标、OpenTelemetry 指标联通,将观测范围从专精容器延伸到全栈可观测。其次,作为观测界面的阿里云Grafana服务也将迎来9.0焕新升级。全新的Prometheus 和 Loki 查询语句生成器及强化后的搜索 Explore 功能,让用户获得更强的数据查询与分析能力。同时,为了应对越来越丰富的异构可观测数据源,Grafana服务与日志服务SLS、Elasticsearch等20+款可观测存储服务集成,帮助企业更简单的构建统一观测界面。一键导入/导出自建实例、自动数据导出报表,一键数据备份、恢复,用户操作审计等企业特性得到进一步增强。最后,为了帮助企业的云上应用开启多维度观测视角。应用实时监控服务ARMS在数据采集方面,OpenTelemetry 与Prometheus生态全面融合,通过 OpenTelemetry 补充业务、自定义组件埋点,在完善观测维度的同时,实现厂商无锁定。并借助 TraceExplorer 实现多来源 Trace 统一查询。重磅发布三 RocketMQ5.0全面升级:从消息服务到云原生事件流平台消息队列一直是企业互联网架构的核心组件,阿里巴巴早在2012年就基于电商场景打造了国内流行的消息中间件RocketMQ,并贡献到Apache 社区。历经十余年的打磨,RocketMQ 取得了众多成果。Apache RocketMQ 的社区非常活跃,全球拥有700+的贡献者,超过75%的头部企业选择使用RocketMQ,同时超过80%的主流云厂商提供了RocketMQ的商业托管服务;阿里云作为 RocketMQ 的发起方和核心贡献者,十多年以来,累计服务了来自互联网、零售、汽车等20多个行业、10w+万企业客户;承载千万级TPS,万亿级消息洪峰。当下,阿里云 RocketMQ 5.0 正式商业化,从内核到生态全面拓宽,全新升级为云原生事件流平台,深耕事件驱动和事件流处理两大核心场景。在未来,企业开发者基于RocketMQ事件流平台,既可以轻松驱动微服务、Serverless应用;也可以基于RocketMQ重构当下的流处理任务,以更加轻量化、低代码的形态,高效的完成CDC、ETL等流处理需求。Serverless 奇点已来:引领下一代应用架构随着企业用云的深入,云的能力也在不断升级,过去企业用云就是去买资源、买实例、买规格、搭应用。我们一直在说“云计算是像水电煤一样的基础设施,但是现在这一点还没有完全实现。阿里云一直在推动产品形态、研发方式的升级,希望从提供资源到提供服务,这个服务就是即插即用的能力,企业不需要管理和维护,可以实现自动伸缩免运维,平台全托管,按用量计费,真正实现了服务化、模块化,这也是云产品升级演进的方向。可以说,Serverless 奇点己来,所谓奇点,就是由平稳发展转向高速发展的转折点,预示着行业落地开始爆发。目前,阿里云已经有20 多款的 Serverless产品,并且会推进核心产品全面Serverless化,Serverless 是云提供能力的最佳实现方式,也是让云计算基础设施落地到千行百业的最佳范式。回顾阿里云在Serverless 领域的演进历程:2017年推出的函数计算是一款FaaS产品,这是一种以事件驱动的全托管计算服务,用户只需编写代码并上传,函数计算就会自动准备好计算资源,以弹性、可靠的方式运行代码,并提供完整的可观测能力,大幅简化开发运维过程。2018年推出的Serverless 应用引擎SAE是业内首款面向应用的Serverless PaaS平台,屏蔽底层IaaS和Kubernetes的复杂度,提供了零代码改造、成本更优、效率更高的应用托管方案,帮用户实现单体Web应用、微服务应用以及定时任务的Serverless化。同年领先业界推出 Serverless 容器服务ASK,基于弹性容器实例ECI(Elastic Container Instance),可以实现 1min 扩容 2000个 pod,降低了 Kubernetes 使用门槛,让用户更专注于应用程序,而不是管理底层基础设施。2020年阿里云开源 Serverless Devs,成为业内首个支持主流 Serverless服务/框架的云原生全生命周期管理的平台。2022年9月该项目正式进入CNCF Sandbox,也成为业内首个入选的Serverless工具项目。除了产品形态的改变之外, Serverless 同样带来了软件研发范式的改变。随着阿里云提供越来越全面的Serverless产品以后,很多云产品都变成模块化、API化、服务化,它可以进行组装,通过拖拉拽的方式就能够构建应用。所以说在Serverless架构下,研发方式升级到组装式研发,组装式研发可以做到流程编排、事件驱动,甚至可以做成可视化,这就彻底颠覆了原有的软件研发方式,大幅提升研发效率,灵活应对业务挑战。根据权威机构调研统计,组装式研发相比传统模式,可为研发提效 50%以上。 以南瓜电影为例,因为一场热映电影,南瓜电影一小时用户增加了一百万,流量暴涨引发网站服务一度中断,临时云上扩容也无法及时满足巨大的流量。传统架构没有改变云上的效率,南瓜电影开始转向Serverless架构,三天时间完成了核心应用的上线,第五天100%的切换,第六到七天把核心的30多个应用切换到Serverless上,最终带来扩容效率提升10倍,成本下降超过 40%,研发效率提升 70%,这就是 Serverless 带来的价值:真正让开发者回归业务本身,让企业做得更少而收获更多。未来,阿里云在云原生领域将持续的引领标准,不断突破,推动领域和产业快速发展。
作者:云原生峰会小组今天,企业应用构建依然面临很大挑战,资源如何按需使用,实现降本增效?如何在复杂系统架构下,充分保障业务稳定和连续性?如何做到应用的敏捷和业务的智能化?如何保障系统的可信和安全?企业亟需充分挖掘云计算的技术红利,助力业务发展,创造更多的商业价值。云原生可以激活应用构建范式,以解决企业在新时期遇到的挑战。15位重磅嘉宾齐聚探讨云原生阿里云智能云原生应用平台总经理丁宇、中国信息通信研究院云大所副所长栗蔚、阿里云智能容器服务负责人易立识货运维总监瞿晟荣、小红书基础架构部负责人贺晋如、阿里云可观测负责人周小帆、阿里云可观测& Serverless 负责人司徒放新东方教育科技集团云教室直播平台技术负责人么敬国、心动网络TapTap/IEM/AI平台负责人陈欣昊阿里云智能高级产品专家董振华、禾连健康CTO邓志豪、阿里云智能高级产品专家杨秋弟、阿里云智能资深技术专家云原生PaaS负责人谢吉宝、阿里云智能资深技术专家高可用架构负责人周洋硬核科技等你来玩!为探寻企业数字化转型的未来方向及技术重点深度解密云原生技术新动向11 月 5 日(本周六)杭州云栖小镇-云原生峰会B 馆 B2-1阿里云将联手识货、传音、禾连健康、新东方、心动网络、小红书等实战企业技术负责人分享云原生最新技术与经验,助力更多企业落地云原生。11 月 5 日,杭州云栖小镇 B 馆,我们不见不散!
作者:Koordinator 团队Koordinator 从 2022 年 4 月发布以来,迄今一共迭代发布了 8 个版本。项目经历的大半年发展过程中,Koordinator 社区吸纳了包括阿里巴巴、小米、小红书、爱奇艺、360 在内的大量优秀工程师,贡献了众多的想法、代码和场景,一起推动 Koordinator 项目的成熟。11 月 3 日,在 2022 杭州 · 云栖大会上,阿里云智能云原生应用平台负责人丁宇宣布,Koordinator 1.0 正式发布。如果你对混部、调度领域不太关注,可能对 Koordinator 还没有做过太深入的了解。本文就借着 v1.0 发布时机,为你详细的梳理一次 Koordinator 项目的发展脉络,解读它的核心思想和愿景,掌握这个正在快速发展的云原生混部系统的技术理念。项目的前生今世Koordinator,名字取自 coordinator,K for Kubernetes,发音相同。语意上契合项目要解决的问题,即协调编排 kubernetes 集群中不同类型的工作负载,使得他们以最优的布局、最佳的姿态在一个集群、一个节点上运行。容器混部技术最早起源于 Google 内部的一个 Borg 系统,在其论文公开发表(2015)之前在行业上一直是非常神秘的存在。在业界,基于 Hadoop 的大数据任务调度技术先行,在比较早期很好的解决了企业对于大数据计算的诉求。熟悉历史的同学应该知道,云原生容器调度编排系统 Kubernetes 开源于 2014 年, 而 Kubernetes 正是受 Borg 设计思想启发,由 Borg 系统的设计者结合云时代应用编排的需求重新设计而来。Kubernetes 良好的扩展性使其能适应多样的工作负载,帮助用户很好的解决工作负载日常运维效率。随着 Kubernetes 的蓬勃发展,逐步成为行业的事实标准,越来越多的工作负载开始运行在 Kubernetes 之上,特别是在这两年,大数据相关的负载逐步迁移到 Kubernetes 之上。阿里巴巴早在 2016 年就启动了混部技术研发,到今年,内混部系统经历了三轮大的架构升级,并经历多年“双11”峰值流量的锤炼。目前,阿里巴巴实现全业务规模超千万核的云原生混部,混部 CPU 利用率超 50%,混部技术帮助 2022 年“双11”计算成本大幅下降。在这个过程中,阿里巴巴混部也走过了一些弯路,积累了大量的生产实践经验。为了帮助企业少走弯路,更快速的拿到云原生混部带来的资源效率红利,阿里巴巴在 2022 年 4 月份正式对外发布的 Koordinator 开源项目。通过建立一个中立的开源社区,帮助企业实现在标准 Kubernetes 之上的多种类型负载混部的调度解决方案,以达到云上、云下一致的云原生混部架构,降低系统运维成本,保持长期可持续发展的健康形态。Koordinator 自发布以来,在开源制度与规范上不断向 Kubernetes 等前辈学习,逐渐形成了较为完善的社区运作机制。在这里,我们会淡化每一位社区成员的雇主、职务,以用户、开发者的身份参与到社区建设中。同样,Koordinator 未来的 roadmap 与发展规划,也将源于所有成员与用户的反馈、需求与共识,而非阿里巴巴自身制定。因此,对于每一位云原生爱好者,不管你是初识调度领域或是混部场景的亲身经历者,都欢迎你关注和参与到 Koordinator 项目中,共同打造一套面向未来的开源混部体系。标准、通用的混部解决方案混部需要一套完整、自闭环的调度回路,但在企业应用混部的过程中,将要面临的两大挑战是:应用如何接入到混部平台应用如何在平台上能够运行稳定、高效 Koordinator 吸取了阿里巴巴内部多年的生产实践经验教训,针对这两大挑战针对性的设计了解决方案,旨在帮助企业真正意义上的用上混部,用好 Kubernetes,而不是秀技术秀肌肉。Koordinator 1.0 的整体架构如下图所示,为了用户提供了完整的混部工作负载编排、混部资源调度、混部资源隔离及性能调优解决方案,帮助用户提高延迟敏感服务的运行性能,挖掘空闲节点资源并分配给真正有需要的计算任务,从而提高全局的资源利用效率。大规模生产实践锤炼2021 双 11 之后阿里对外宣布了“首次!统一调度系统规模化落地,全面支撑阿里巴巴双 11 全业务”:作为阿里巴巴的核心项目,阿里云(容器团队和大数据团队)联合阿里巴巴资源效能团队、蚂蚁容器编排团队,历时一年多研发和技术攻坚,实现了从“混部技术”到今天“统一调度技术”的全面升级。今天,统一调度已实现阿里巴巴电商、搜推广、MaxCompute 大数据的调度全面统一,实现了 Pod 调度和 task 高性能调度的统一,实现了完整的资源视图统一和调度协同,实现了多种复杂业务形态的混部和利用率提升,全面支撑了全球数十个数据中心、数百万容器、数千万核的大规模资源调度。作为云原生混部的践行者,阿里巴巴是真刀真枪的在生产环境中推进混部技术理念,并在去年双 11 完成了超过千万核的混部规模,通过混部技术帮助阿里巴巴双 11 节约超过 50% 的大促资源成本,在大促快上快下链路上提速 100%,助力大促实现丝滑的用户体验。正是在双 11 这样的峰值场景驱动之下,阿里的混部调度技术持续演进,积累了大量的生产实践经验,到今天已经是第三代即云原生全业务混部系统。Koordinator 的架构基于阿里巴巴内部的超大规模生产实践,结合阿里云看到的企业容器客户的真实诉求,在标准化、通用化上做出了更多的突破,实现首个基于标准 Kubernetes 的生产可用的开源混部系统。支持丰富的负载类型混部是一套针对延迟敏感服务的精细化编排+大数据计算工作负载混合部署的资源调度解决方案,核心技术在于:精细的资源编排,以满足性能及长尾时延的要求,关键点是精细化的资源调度编排策略及 QoS 感知策略;智能的资源超卖,以更低成本满足计算任务对计算资源的需求,并保证计算效率的同时不影响延迟敏感服务的响应时间。 上图是 Koordinator 混部资源超卖模型,也是混部最关键最核心的地方。其中超卖的基本思想是去利用那些已分配但未使用的资源来运行低优先级的任务,如图所示的四条线分别是资源使用量(红线),短生命周期可超卖量(蓝线),长生命周期可超卖量(浅蓝),以及资源总量(黑线)。该资源模型足够精炼的同时也具备很强的灵活性,支持丰富的在线资源编排类别,支持短生命周期的批处理任务(MapReduce 类别),以及实时计算类的生命周期任务。Koordinator 整个混部资源调度的大厦构建在这样一个资源模型的基础之上,配合上优先级抢占、负载感知、干扰识别和 QoS 保障技术,构建出混部资源调度底层核心系统。Koordinator 社区将围绕这个思路投入建设,持续将混部场景的调度能力展开,解决企业面临的真实业务场景问题。零侵入,低接入成本企业接入混部最大的挑战是如何让应用跑在混部平台之上,这第一步的门槛往往是最大的拦路虎。Koordinator 针对这一问题,结合内部生产实践经验,设计了“零侵入”的混部调度系统:对 Kubernetes 平台的零侵入:无需修改任何 Kubernetes 原生组件,而是以插件的方式增强混部需要的各种能力对工作负载编排系统的零侵入:无需修改计算任务的管理引擎(operator),而是以配置化的方式管理混部策略参数,简化应用接入的难度支持系统的平滑升级:已有的 Kubernetes 集群的调度器可以平滑升级到 Koordinator,存量的 Pod 的标准调度能力可以无损接管到 Koordinator 中 通过在这三方面的努力,降低用户在生产环境中引入 Koordinator 的难度,只在帮助用户解决生产环境应用混部的第一道拦路虎。版本特性深入解读自 2022 年 4 月份 Koordinator 发布以来,社区围绕在混部资源的一层调度而构建,解决任务混部最核心的资源编排、资源隔离的问题。在版本迭代过程中,Koordinator 社区始终围绕三大能力而构建,即任务调度、差异化 SLO 以及 QoS 感知调度能力。任务调度Enhanced Coscheduling Koordinator 在启动之初,期望支持 Kubernetes 多种工作负载的混部调度,提高工作负载的运行时效率和可靠性,其中就包括了机器学习和大数据领域中广泛存在的具备 All-or-Nothing 需求的作业负载。例如当提交一个Job 时会产生多个任务,这些任务期望要么全部调度成功,要么全部失败。这种需求称为 All-or-Nothing,对应的实现被称作 Gang Scheduling(or Coscheduling) 。为了解决 All-or-Nothing 调度需求,Koordinator 基于社区已有的 Coscheduling 实现了 Enhanced Coscheduling:支持 Strict/NonStrict 模式,解决大作业场景长时间得不到资源问题支持 AI 场景多角色联合的 coscheduling 策略,例如一个 TF 训练 Job 中包含 PS 和 Worker 两种角色,并且两种角色都需要单独定义 MinMember,但又期望两种角色的 All-or-Nothing 都满足后才能继续调度 Enhanced ElasticQuota Scheduling 企业的 Kubernetes 一般由多个产品和研发团队共用一个规模比较大的 Kubernetes 集群,由资源运维团队统一管理集群内大量 CPU/Memory/Disk 等资源。Koordinator 为帮助用户管理好资源额度,提升资源额度的使用效率,实现降本增效,Koordinator 基于基于社区 ElasticQuota CRD 实现了 Enhanced ElasticQuota Scheduling ,具备如下增强特性:兼容社区的 ElasticQuota CRD,用户可以无缝升级到 Koordinator支持树形结构管理 Quota,契合企业的组织架构支持按照共享权重(shared weight)保障公平性允许用户设置是否允许借用 Quota 给其他消费对象 Koordinator ElasticQuota Scheduling 通过额度借用机制和公平性保障机制,Koordinator 把空闲的额度复用给更需要的业务使用。当额度的所有者需要额度时,Koordinator 又可以保障有额度可用。通过树形管理机制管理 Quota,可以方便的与大多数公司的组织结构映射,解决同部门内或者不同部门间的额度管理需求。Fine-grained Device Scheduling 在 AI 领域,GPU、RDMA、FPGA 等异构资源被广泛的应用,Koordinator 针对异构资源调度场景,提供了精细化的设备调度管理机制,包括:支持 GPU 共享,GPU 独占,GPU 超卖支持百分比的 GPU 调度支持 GPU 多卡调度NVLink 拓扑感知调度(doing) 差异化 SLO差异化 SLO 是 Koordinator 提供的核心混部能力,保障资源超卖之后的 Pod 的运行稳定性。Koordinator 定了一一组 Priority & QoS,用户按照这一最佳实践的方式接入应用,配合完善的资源隔离策略,最终保障不同应用类型的服务质量。CPU Supress Koordinator 的单机组件 koordlet 会根据节点的负载水位情况,调整 BestEffort 类型 Pod 的 CPU 资源额度。这种机制称为 CPU Suppress。当节点的在线服务类应用的负载较低时,koordlet 会把更多空闲的资源分配给 BestEffort 类型的 Pod 使用;当在线服务类应用的负载上升时,koordlet 又会把分配给 BestEffort 类型的 Pod 使用的 CPU 还给在线服务类应用。CPU Burst CPU Burst 是一种服务级别目标 (SLO) 感知的资源调度功能。用户可以使用 CPU Burst 来提高对延迟敏感的应用程序的性能。内核的调度器会因为容器设置的 CPU Limit 压制容器的 CPU,这个过程称为 CPU Throttle。该过程会降低应用程序的性能。Koordinator 自动检测 CPU Throttle 事件,并自动将 CPU Limit 调整为适当的值。通过 CPU Burst 机制能够极大地提高延迟敏感的应用程序的性能。基于内存安全阈值的主动驱逐机制 当延迟敏感的应用程序对外提供服务时,内存使用量可能会由于突发流量而增加。类似地,BestEffort 类型的工作负载可能存在类似的场景,例如,当前计算负载超过预期的资源请求/限制。这些场景会增加节点整体内存使用量,对节点侧的运行时稳定性产生不可预知的影响。例如,它会降低延迟敏感的应用程序的服务质量,甚至变得不可用。尤其是在混部场景下,这个问题更具挑战性。我们在 Koordinator 中实现了基于内存安全阈值的主动驱逐机制。koordlet 会定期检查 Node 和 Pods 最近的内存使用情况,检查是否超过了安全阈值。如果超过,它将驱逐一些 BestEffort 类型的 Pod 释放内存。在驱逐前根据 Pod 指定的优先级排序,优先级越低,越优先被驱逐。相同的优先级会根据内存使用率(RSS)进行排序,内存使用率越高越优先被驱逐。基于资源满足的驱逐机制 CPU Suppress 在线应用的负载升高时可能会频繁的压制离线任务,这虽然可以很好的保障在线应用的运行时质量,但是对离线任务还是有一些影响的。虽然离线任务是低优先级的,但频繁压制会导致离线任务的性能得不到满足,严重的也会影响到离线的服务质量。而且频繁的压制还存在一些极端的情况,如果离线任务在被压制时持有内核全局锁等特殊资源,那么频繁的压制可能会导致优先级反转之类的问题,反而会影响在线应用。虽然这种情况并不经常发生。为了解决这个问题,Koordinator 提出了一种基于资源满足度的驱逐机制。我们把实际分配的 CPU 总量与期望分配的 CPU 总量的比值成为 CPU 满足度。当离线任务组的 CPU 满足度低于阈值,而且离线任务组的 CPU 利用率超过 90% 时,koordlet 会驱逐一些低优先级的离线任务,释放出一些资源给更高优先级的离线任务使用。通过这种机制能够改善离线任务的资源需求。L3 Cache 和内存带宽分配(MBA) 隔离 混部场景下,同一台机器上部署不同类型的工作负载,这些工作负载会在硬件更底层的维度发生频繁的资源竞争。因此如果竞争冲突严重时,是无法保障工作负载的服务质量的。Koordinator 基于 Resource Director Technology (RDT, 资源导向技术) ,控制由不同优先级的工作负载可以使用的末级缓存(服务器上通常为 L3 缓存)。RDT 还使用内存带宽分配 (MBA) 功能来控制工作负载可以使用的内存带宽。这样可以隔离工作负载使用的 L3 缓存和内存带宽,确保高优先级工作负载的服务质量,并提高整体资源利用率。QoS 感知调度、重调度Koordinator 差异化 SLO 能力在节点侧提供了诸多 QoS 保障能力能够很好的解决运行时的质量问题。同时 Koordinator Scheduler 也在集群维度提供了增强的调度能力,保障在调度阶段为不同优先级和类型的 Pod 分配合适的节点。负载感知调度 超发资源可以极大的提升集群的资源利用率,但也会凸显集群内节点之间资源利用率不均匀的现象。这个现象在非混部环境下也是存在的,只是因为 Kubernetes 原生是不支持资源超发机制,节点上的利用率往往不是很高,一定程度上掩盖了这个问题。但当混部时,资源利用率会上升到比较高的水位时就暴露了这个问题。利用率不均匀一般是节点之间不均匀以及出现局部的负载热点,局部的负载热点会可能影响工作负载的整体运行效果。另一个是在负载高的节点上,在线应用和离线任务之间可能会存在的严重的资源冲突,影响到在线应用的运行时质量。为了解决这个问题, Koordinator 的调度器提供了一个可配置的调度插件控制集群的利用率。该调度能力主要依赖于 koordlet 上报的节点指标数据,在调度时会过滤掉负载高于某个阈值的节点,防止 Pod 在这种负载较高的节点上无法获得很好的资源保障,另一方面是避免负载已经较高的节点继续恶化。在打分阶段选择利用率更低的节点。该插件会基于时间窗口和预估机制规避因瞬间调度太多的 Pod 到冷节点机器出现一段时间后冷节点过热的情况。精细化 CPU 调度 随着资源利用率的提升进入到混部的深水区,需要对资源运行时的性能做更深入的调优,更精细的资源编排可以更好的保障运行时质量,从而通过混部将利用率推向更高的水平。我们把 Koordinator QoS 在线应用 LS 类型做了更细致的划分,分为 LSE、LSR 和 LS 三种类型。拆分后的 QoS 类型具备更高的隔离性和运行时质量。通过这样的拆分,整个 Koordinator QoS 语义更加精确和完整,并且兼容 Kubernetes 已有的 QoS 语义。而且我们针对 Koordinator QoS,设计了一套丰富灵活的 CPU 编排策略,如下表所示。不同的 QoS 类型的工作负载具备不同的隔离性:Koordinator Scheduler 会针对 LSE/LSR 类型的 Pod 分配具体的 CPU 逻辑核,并更新到 Pod Annotation 中,由单机侧 koordlet 配合,把调度器分配的 CPU 更新到 cgroup 中。调度器在分配 CPU 时,会根据 CPU 拓扑结构分配,默认尽可能的保障分配的 CPU 属于同一个 NUMA Node 以获得更好的性能。并且 CPU 调度时,支持 Pod 根据需要设置不同的互斥策略,例如一个系统中多个核心的服务部署在相同的物理核上,性能表现比较差,但分开就完全没问题,此时就可以配置互斥策略,调度器会尽可能的把这种互斥属性的 Pod 分配使用不同的物理核。并且在打分阶段,调度器会参考集群的整体情况,选择符合 CPU 编排要求的节点。资源预留(Reservation) Koordinator 支持在不侵入 Kubernetes 已有的机制和代码前提下,实现了资源预留的原子能力(Reservation)。Koordinator Reservation API 允许用户不修改 Pod Spec 或者存量的 Workload(例如 Deployment, StatefulSet)即可以预留资源。资源预留在容量管理、碎片优化、调度成功率和重调度等场景有重要作用:当有重要的工作负载在未来某段时间需要资源时,可以提前预留资源满足需求。用户在 PaaS 上发起扩容时,可以通过资源预留能力尝试预留,预留成功后发起扩容,保障 PaaS 的 SLA。用户在 PaaS 上发布时,如果应用采用了滚动发布的能力,可以通过资源预留保留即将销毁的 Pod 持有的资源,在滚动发布时,新建的 Pod 可以复用预留下来的原有资源,能够有效提高滚动发布的成功率。碎片优化场景中,可以通过资源预留占住空闲的碎片资源,并把可被整理的 Pod 迁移到这些节点。重调度时在发起驱逐前,先尝试预留资源,预留成功后发起驱逐,避免驱逐后无资源可用影响应用的可用性。 灵活可扩展且安全的重调度器 调度器调度时是根据当时集群内的情况和配置,做出综合的判断,选择出一个最合适的节点分配给 Pod 使用。但随着时间和工作负载的变化,原本最合适的节点也会变差,差异化 SLO 和调度器都提供了丰富的能力帮助改善这些问题,但差异化 SLO 更多还是关注在自身单机的情况,无法感知全局的变化。从控制的角度看,我们也需要根据集群内的情况做出决策,把异常的 Pod 驱逐迁移到更合适的节点,让这些 Pod 有机会可以更好的对外服务。因此 Koordinator Descheduler 应运而生。我们认为 Pod 迁移是一个复杂的过程,涉及到审计、资源分配、应用启动等步骤,还夹杂着应用的发布升级、扩容/缩容场景和集群管理员的资源运维操作。因此,如何管理 Pod 迁移过程的稳定性风险,保证应用不会因为 Pod 的迁移影响可用性,是一个非常关键的必须解决的问题。为了让大家更好的理解,举几个场景:社区的重调度器内置的多个重调度策略根据自身逻辑判断某个 Pod 是否要被迁移,需要迁移时调用 Kubernetes Eviction API 发起驱逐。但是这个过程并不关注被驱逐的 Pod 在将来是否可以分配到资源。因此存在大量 Pod 被驱逐后因为没有资源而处于 Pending 状态的情况。如果应用此时有大量请求进来,又因为没有足够的可用的 Pod 导致可用性异常。 另外,社区重调度器调用的 Kubernetes Evcition API 虽然会检查 PDB 确保在安全范围内驱逐,但是众所周知,众多的 workload Controller 在发布和缩容场景都是通过直接调用 Delete API 的形式销毁 Pod,此时并不会被 PDB 限制。这就导致重调度时如果遇到上述场景,是很可能引发严重的稳定性问题。 我们认为 Pod 腾挪不是一个简单的后台自动化逻辑,有相当多的场景和用户期望由人工介入手工迁移 Pod,甚至期望重调度时发起的自动迁移请求应该被拦截掉,经过审批决定是否执行。 Koordinator 基于 CRD 定义了一个名为 PodMigrationJob API。重调度器或者其他自动化自愈组件通过 PodMigrationJob 可以安全的迁移 Pod。PodMigrationJob Controller 在处理 PodMigrationJob 时会先尝试通过 Koordinator Reservation 机制预留资源,预留失败则迁移失败;资源预留成功后发起驱逐操作并等待预留的资源被消费。中间的过程都会记录到 PodMigrationJobStatus 中,并产生相关的 Event。我们在 Koordinator 中实现了一个全新的 Descheduler Framework。我们认为重调度场景:需要一个插件化机制实现自定义的重调度策略,但又不希望这个抽象过于复杂;需要具备基本的插件管理能力,通过配置启用和禁用插件;具备统一的插件配置下发机制,方便插件自定义参数;并能够方便的扩展和使用统一的 Evictor 机制;另外期望用户能够基于 controller-runtime 实现 controller 并纳入统一的插件管理机制。 Koordinator descheduler framework 提供了插件配置管理(例如启用、禁用,统一配置等)、插件初始化、插件执行周期管理等机制。并且该框架内置了基于 PodMigrationJob 实现的 Controller,并作为 Evictor Plugin 方便被各种重调度插件使用,帮助重调度插件安全的迁移 Pod。基于 Koordinator descheduler framework,用户可以非常容易的扩展实现自定义重调度策略,就像基于 Kubernetes scheduling framework 的实现自定义的调度插件一样简单。并且用户也可以以插件的形式实现 controller,支持基于 Event 触发重调度的场景。Koordinator 的未来规划Koordinator 社区将不断丰富大数据计算任务混部的形态,拓展包括 Hadoop YARN 等计算框架混部支持,丰富任务混部解决方案,项目上持续的完善干扰检测、问题诊断体系,推进更多的负载类型融入 Koordinator 生态,并取得更好的资源运行效率。Koordinator 社区将持续的保持中立的发展趋势,联合各厂商持续的推进混部能力的标准化,也欢迎大家加入社区共同推进混部的标准化进程。
11 月 3 日,2022 杭州·云栖大会上,阿里云智能总裁张建锋表示,以云为核心的新型计算体系正在形成,软件研发范式正在发生新的变革,Serverless 是其中最重要的趋势之一,阿里云将坚定推进核心产品全面Serverless 化,帮助客户更好地实现敏捷创新。“我们希望让用户做得更少而收获更多,通过Serverless化,用云就像用电一样简单。”张建锋表示,Serverless 让云计算从一种资源真正变成一种能力,未来云将全面Serverless化,更加接近“电网”模式,按计算的调用次数付费。Serverless 并不是不用服务器,它是将服务器全权托管给了云厂商,根据业务流量大小自动弹性伸缩,开箱即用免去维护成本,按使用量计费。用户无需关心和管理底层IT资源,只要聚焦业务代码,根据实际请求处理业务。依托于 Serverless 架构,云上研发方式正在发生根本性的改变。从过去的集中式研发、分布式研发,到云上的组装式研发,实现了软件研发的服务化、模块化、可编排、可组装。无论是2万用户还是2000万用户体量,基于 Serverless 构建的IT架构都可以自适应伸缩,峰值秒级自动扩容、峰谷自动缩容。基于 Serverless 产品,云产品都变成模块化、API 化、服务化,它可以进行组装,通过拖拉拽的方式就能够构建应用,并通过流程驱动和事件驱动,让应用构建可视化,从而获得更强大的应用能力。 阿里云是国内最早提供 Serverless 计算服务的云厂商。2017 年推出的函数计算 FC 是一款 FaaS 产品,这是一种以事件驱动的全托管计算服务,用户只需编写代码并上传,函数计算就会自动准备好计算资源,以弹性、可靠的方式运行代码,并提供日志查询、性能监控、报警等功能。2018年领先业界推出 Serverless 容器服务 ASK,基于弹性容器实例 ECI(Elastic Container Instance),可以实现 1min 扩容 2000个 pod,降低了 Kubernetes 使用门槛,让用户更专注于应用程序,而不是管理底层基础设施。2019年推出首款面向应用的 Serverless PaaS(SAE),提供成本更优、效率更高的一站式微服务和 K8s 托管方案,零改造实现 web/微服务/任务的迁移。2020年开源 Serverless 开发者平台 Serverless Devs,这是业内首个支持主流 Serverless 服务/框架的云原生全生命周期管理平台。2022 年 9 月,Serverless Devs 正式成为 CNCF 官方沙箱项目,也成为 CNCF 首个 Serverless Tool 项目。2022年 Serverless 应用中心发布,它是一个 Serverless 应用全生命周期管理平台,用户不需要在部署应用之前进行额外的克隆、构建、打包和发布操作,就可以快速部署和管理应用。权威分析机构 Gartner 预测,2025 年将有 50% 以上的全球企业部署 Serverless 架构。从应用场景上来看,除小程序外,Serverless 还受到电商大促、音视频转码、AI 算法服务、游戏应用包分发、文件实时处理、物联网数据处理、微服务等场景的青睐。世纪联华是最早试水 Serverless 的新零售代表,当发现老架构无法满足大促时流量爆炸问题,于是果断将会员系统、交易系统、支付系统等放在阿里云函数计算上处理,告别了靠扩展机器支撑大体量业务,促销准备时间从周级缩短到小时级,研发运维提效 30%,成本下降 40%,真正的把促销活动变成常态;流媒体平台南瓜电影从创业之初架构就构建在阿里云之上,是一个典型的“生于云,长于云”的企业。但随着业务的不断发展,原有的系统架构逐渐暴露了很多问题。因为一场热映电影,南瓜电影新用户量 1 小时内增加了 100 万,流量暴涨引发网站服务一度中断,临时云上扩容也无法及时满足巨大的流量。痛定思痛,开始走向 Serverless 转型之路,基于阿里云 Serverless 应用引擎 SAE 产品,3 天完成核心应用 API 网关上线,第 5 天验证结束 100% 流量打到 SAE 上,第 6-7 天把其余 30 多个系统快速迁移到 SAE。7天完成 Serverless 架构升级,使用 SAE 后,运维效率提升 70%,成本下降超过 40%,扩容效率提升 10 倍以上。目前,阿里云已经拥有超过 20 款 Serverless 产品,其中阿里云函数计算 FC 日调用次数超过 200 亿次,有效支撑历年双 11 百万 QPS 洪峰,业务增速超过 300%,整体规模位居国内首位。在 Forrester 发布的 2021 年第一季度 FaaS 平台评估报告中,阿里云凭借函数计算产品能力全面领先的优势,成为全球前三的 FaaS 领导者,这也是首次有国内科技公司进入 FaaS 领导者象限。
引言随着云计算的普及,企业用到越来越多云产品,例如:ECS、RDS、Redis 等。服务众多企业之后,阿里云可观测团队发现在运维场景愈发精细化的今天,对于指标按需再加工、对于告警规则的灵活设置成为刚需,云监控等基础默认监控能力,无法满足当下的运维需求,例如:查看各 Region ECS CPU 使用率 Top10;为 Kafka 服务连续 10 分钟堆积增量超过 500 的 ConsumerGroup 设置告警;基于磁盘空间的变化预测清理时间,避免告警无法及时处理导致故障。 与此同时,Prometheus + Grafana 成为可观测性事实标准。运维团队可以使用 Prometheus 监控云原生 Kubernetes 体系 Node、ApiServer、workload 等基础指标的同时,还可以通过 Prometheus Exporters 采集各种组件(如 Redis、Kafka 等)和业务应用的相关指标,最后通过 Grafana 进行整体可视化展示,借助 AlertManager 进行告警,实现云原生时代的指标可观测闭环。回到最开始的话题,随着云产品应用愈发普及,基于“Prometheus + Grafana”的指标可观测体系是否可以针对云产品的相关指标提供更加精细化的加工与应用能力,实现对云产品的指标可观测闭环?答案是肯定的。自建 Prometheus 监控云产品的挑战虽然 Prometheus 官方社区维护了很多 Exporter,第三方厂商或者主流开源项目也参与到贡献及维护中。但由于云产品的特殊性,如果用户想要通过自建 Prometheus 去监控云产品,就需要用户通过 Prometheus Exporter 形式将观测到的 Metric 数据收集到服务端。但这里就会出现一些关于 Exporter 的额外工作量:额外的研发工作量虽然官方提供了四种语言(Go/Java/Python/Rubby)的正式客户端库用来开发一个集成 http server 的 Exporter 库,并提供了完整的开发规范。但这需要运维工程师针对不同云产品开发定制 Exporter(调用企业云监控实时导出服务获取 Metric 数据),对于开箱即用的云服务而言,拖慢了业务上线效率。额外的 Exporter 资源消耗由于 Exporter 本身提供了一个 REST 服务器,会带来一些线程消耗,随着 Exporter 接入云产品越多、指标越多消耗的资源也会随之越多。可以看到,虽然运维工程师可以通过自研 Eexporter 完成对于云产品的监控,但有没有更简单的方式?阿里云 Prometheus 服务(下面简称 Prometheus)成为最佳选择,提供全托管、开箱即用的云产品指标监控能力,并结合常见运维场景,预置若干多维度监控大盘以满足常见监控场景。针对不同云产品可观测性集成情况,提供「企业云监控集成」以及「云产品自监控集成」两种不同接入模式,最大限度的降低运维接入成本。如何通过阿里云 Prometheus 服务监控云产品根据不同云产品的 Prometheus 集成情况,Prometheus 服务的云产品监控分为「企业云监控集成」以及「云产品自监控集成」两种形式,接下来我们将进行详细解读。企业云监控集成阿里云部分云产品在产品控制台默认集成了 Prometheus 监控,但还有众多云产品尚未集成 Prometheus。为了能通过 Prometheus 服务监控这部分云产品,我们提供企业云监控集成模式,通过企业云监控获取监控指标,指标上报流量费用由云监控收取(收费标准),Prometheus 免费存储及应用。在用户运维成本未增加的前提下,获得了 Prometheus 更精细与灵活的的指标加工与应用能力。部署形式如下图:Exporter:以 Pod 方式部署在 Prometheus 企业云监控集成的托管 K8s 集群,通过调用企业云监控实时导出 API 收集已集成的云产品指标数据;Agent:Arms Prometheus AgentAlarm:定义集成的云产品告警模板Grafana:提供已集成的云产品默认大盘 对于云产品控制台目前尚不支持Prometheus监控的产品,通过该方式实现产品指标监控,目前支持 25 款云产品并不断扩增。企业云监控集成目前仅支持国内 Region,海外 Region 暂未开放。云产品接入后,包含全部 Region 监控指标。目前已接入产品包括:弹性计算类:阿里云 ECS;存储类、阿里云 SLS、阿里云 OSS;网络类:阿里云 ALB、阿里云 API 网关、阿里云 Connector、阿里云 CDN、阿里云 CEN、阿里云 DCDN、阿里云 Cloud NAT、阿里云 EIP;大数据类:阿里云 E-MapReduce、阿里云 Elasticsearch、阿里云 Logstash;数据库类:阿里云 PolarDB、阿里云 RDS PostgreSQL、阿里云 RDS MySQL、阿里云 Redis、阿里云 RDS SQLServer、阿里云 Hologres、阿里云 ADB、阿里云 DRDS、阿里云 DTS;安全类:阿里云 WAF; 云产品自监控集成目前,部分云产品在各自控制台提供了自身产品的可观测性,但这些云产品的指标及看板散落在各个控制台。为了能将这些数据进行统一展现。Prometheus 服务提供了云产品自监控集成形式,云产品自监控集成的相关指标来源于各云产品,为运维团队提供更加便捷的日常运维监控界面。部署形式如下:Exporter:以 Pod 方式部署在云产品侧 K8s 集群,负责收集云产品指标数据;Agent:Arms Prometheus AgentAlarm:定义告警模板Grafana:提供云产品默认大盘 Prometheus 自监控集成 Tab 页是云产品控制台支持 Prometheus 监控的所有云产品的概览页,展现当前账号下云产品的 Promehtheus 集成状态、指标占比、大盘预览、告警配置。目前已接入的产品包括:数据库类:阿里云 Clickhouse、阿里云 Lindorm、云数据库 MongoDB;消息队列类:消息队列 RabbitMQ、消息队列 Kafka、消息队列 RocketMQ;中间件类:企业级分布式应用服务 EDAS、微服务引擎 MSE - 云原生网关、微服务应用引擎 SAE、应用高可用服务 AHAS;运维类:Grafana 服务、性能测试 PTS; 最佳实践企业云监控集成云产品接入 登录 Prometheus 控制台,点击左侧菜单“接入中心”选择任意云产品后弹出接入页面,选择待接入的云产品安装即可,安装完成后会创建一个名为“企业云服务”的 Prometheus 实例。监控指标点击“云服务实例”,选择相应云产品图标会弹出一个包含指标、大盘和告警 3 个 tab 页的窗口。指标页默认包括:指标、类别、描述 3 项基本信息,已集成云产品除默认项外还包括最近 10 分钟的指标量和占比。ECS 如图:Grafana 大盘大盘页默认显示该云产品的所有 Grafana 默认大盘缩略图。已集成的云产品点击缩略图或 Title 链接会跳转至阿里云 Grafana 监控大盘,未集成的云产品点击缩略图或 Title 链接会显示 Grafana 监控大图。ECS 实例详情:提供 ECS 实例的 CPU、内存、磁盘、网络等系统指标的监控,筛选维度包括:区域、ECS 标签、实例名、实例 ID;ECS 全局公网大盘:提供 ECS 实例公网流入、流出带宽合计、TOP 等指标;ECS 实例利用率排序大盘:支持 region 和全局维度 TOP 实例,主要指标:CPU 利用率、内存利用率、网络连接等;ECS 资源区域分布大盘:支持 ECS 实例、CPU、内存、磁盘、网络连接等按区域分布统计; 告警配置 告警页默认显示该云产品配置的所有告警规则:点击“创建 Prometheus 告警规则”通过默认告警模板设置或自定义 PromQL 完成告警规则的创建(自定义 PromQL 指标名可参考步骤“云产品指标”)。默认告警规则 CPU 利用率AliyunEcs_cpu_total{} > 80内存利用率AliyunEcs_memory_usedutilization{} > 90磁盘利用率:磁盘使用率超过 90%时需要进行磁盘清理AliyunEcs_diskusage_utilization{} > 90磁盘剩余空间不足:当磁盘剩余空间小于 5G 时考虑清理AliyunEcs_diskusage_free{} < 1024*1024*1024*5热点指标 云产品自监控集成在开通云产品并创建实例时,会有开通 ARMS Prometheus 相关选项,创建完成后即可通过 Prometheus 实现该产品的指标监控。以“MSE 服务-云服务网关”为例:1. 创建实例时开通 Prometheus 监控2. 产品控制台监控入口Grafana 专业版云服务实例默认使用 Grafana 共享版,如果默认大盘不能满足运维团队可观测需求或者想在默认大盘基础上进行优化,可增购 Grafana 专家版或高级版。关于阿里云 Prometheus 监控阿里云 Prometheus 服务是基于云原生可观测事实标准 - Prometheus 开源项目构建的全托管监控服务。默认集成常见云服务,兼容主流开源组件,全面覆盖业务监控/应用层监控/中间件监控/系统层监控。通过开箱即用的 Grafana 看板与智能告警功能,并全面优化探针性能与系统可用性,帮助企业快速搭建一站式指标可观测体系。助业务快速发现和定位问题,减轻故障给业务带来的影响,并免去系统搭建与日常维护工作量,有效提升运维监控效率。与此同时,阿里云 Prometheus 作为阿里云可观测套件的重要组成部分,与 Grafana 服务、链路追踪服务,形成指标存储分析、链路存储分析、异构构数据源集成的可观测数据层,同时通过标准的 PromQL 和 SQL,提供数据大盘展示,告警和数据探索能力。为 IT 成本管理、企业风险治理、智能运维、业务连续性保障等不同场景赋予数据价值,让可观测数据真正做到不止于观测。
引言随着云计算的普及,企业用到越来越多云产品,例如:ECS、RDS、Redis 等。服务众多企业之后,阿里云可观测团队发现在运维场景愈发精细化的今天,对于指标按需再加工、对于告警规则的灵活设置成为刚需,云监控等基础默认监控能力,无法满足当下的运维需求,例如:查看各 Region ECS CPU 使用率 Top10;为 Kafka 服务连续 10 分钟堆积增量超过 500 的 ConsumerGroup 设置告警;基于磁盘空间的变化预测清理时间,避免告警无法及时处理导致故障。 与此同时,Prometheus + Grafana 成为可观测性事实标准。运维团队可以使用 Prometheus 监控云原生 Kubernetes 体系 Node、ApiServer、workload 等基础指标的同时,还可以通过 Prometheus Exporters 采集各种组件(如 Redis、Kafka 等)和业务应用的相关指标,最后通过 Grafana 进行整体可视化展示,借助 AlertManager 进行告警,实现云原生时代的指标可观测闭环。回到最开始的话题,随着云产品应用愈发普及,基于“Prometheus + Grafana”的指标可观测体系是否可以针对云产品的相关指标提供更加精细化的加工与应用能力,实现对云产品的指标可观测闭环?答案是肯定的。自建 Prometheus 监控云产品的挑战虽然 Prometheus 官方社区维护了很多 Exporter,第三方厂商或者主流开源项目也参与到贡献及维护中。但由于云产品的特殊性,如果用户想要通过自建 Prometheus 去监控云产品,就需要用户通过 Prometheus Exporter 形式将观测到的 Metric 数据收集到服务端。但这里就会出现一些关于 Exporter 的额外工作量:额外的研发工作量虽然官方提供了四种语言(Go/Java/Python/Rubby)的正式客户端库用来开发一个集成 http server 的 Exporter 库,并提供了完整的开发规范。但这需要运维工程师针对不同云产品开发定制 Exporter(调用企业云监控实时导出服务获取 Metric 数据),对于开箱即用的云服务而言,拖慢了业务上线效率。额外的 Exporter 资源消耗由于 Exporter 本身提供了一个 REST 服务器,会带来一些线程消耗,随着 Exporter 接入云产品越多、指标越多消耗的资源也会随之越多。可以看到,虽然运维工程师可以通过自研 Eexporter 完成对于云产品的监控,但有没有更简单的方式?阿里云 Prometheus 服务(下面简称 Prometheus)成为最佳选择,提供全托管、开箱即用的云产品指标监控能力,并结合常见运维场景,预置若干多维度监控大盘以满足常见监控场景。针对不同云产品可观测性集成情况,提供「企业云监控集成」以及「云产品自监控集成」两种不同接入模式,最大限度的降低运维接入成本。如何通过阿里云 Prometheus 服务监控云产品根据不同云产品的 Prometheus 集成情况,Prometheus 服务的云产品监控分为「企业云监控集成」以及「云产品自监控集成」两种形式,接下来我们将进行详细解读。企业云监控集成阿里云部分云产品在产品控制台默认集成了 Prometheus 监控,但还有众多云产品尚未集成 Prometheus。为了能通过 Prometheus 服务监控这部分云产品,我们提供企业云监控集成模式,通过企业云监控获取监控指标,指标上报流量费用由云监控收取(收费标准),Prometheus 免费存储及应用。在用户运维成本未增加的前提下,获得了 Prometheus 更精细与灵活的的指标加工与应用能力。部署形式如下图:Exporter:以 Pod 方式部署在 Prometheus 企业云监控集成的托管 K8s 集群,通过调用企业云监控实时导出 API 收集已集成的云产品指标数据;Agent:Arms Prometheus AgentAlarm:定义集成的云产品告警模板Grafana:提供已集成的云产品默认大盘 对于云产品控制台目前尚不支持Prometheus监控的产品,通过该方式实现产品指标监控,目前支持 25 款云产品并不断扩增。企业云监控集成目前仅支持国内 Region,海外 Region 暂未开放。云产品接入后,包含全部 Region 监控指标。目前已接入产品包括:弹性计算类:阿里云 ECS;存储类、阿里云 SLS、阿里云 OSS;网络类:阿里云 ALB、阿里云 API 网关、阿里云 Connector、阿里云 CDN、阿里云 CEN、阿里云 DCDN、阿里云 Cloud NAT、阿里云 EIP;大数据类:阿里云 E-MapReduce、阿里云 Elasticsearch、阿里云 Logstash;数据库类:阿里云 PolarDB、阿里云 RDS PostgreSQL、阿里云 RDS MySQL、阿里云 Redis、阿里云 RDS SQLServer、阿里云 Hologres、阿里云 ADB、阿里云 DRDS、阿里云 DTS;安全类:阿里云 WAF; 云产品自监控集成目前,部分云产品在各自控制台提供了自身产品的可观测性,但这些云产品的指标及看板散落在各个控制台。为了能将这些数据进行统一展现。Prometheus 服务提供了云产品自监控集成形式,云产品自监控集成的相关指标来源于各云产品,为运维团队提供更加便捷的日常运维监控界面。部署形式如下:Exporter:以 Pod 方式部署在云产品侧 K8s 集群,负责收集云产品指标数据;Agent:Arms Prometheus AgentAlarm:定义告警模板Grafana:提供云产品默认大盘 Prometheus 自监控集成 Tab 页是云产品控制台支持 Prometheus 监控的所有云产品的概览页,展现当前账号下云产品的 Promehtheus 集成状态、指标占比、大盘预览、告警配置。目前已接入的产品包括:数据库类:阿里云 Clickhouse、阿里云 Lindorm、云数据库 MongoDB;消息队列类:消息队列 RabbitMQ、消息队列 Kafka、消息队列 RocketMQ;中间件类:企业级分布式应用服务 EDAS、微服务引擎 MSE - 云原生网关、微服务应用引擎 SAE、应用高可用服务 AHAS;运维类:Grafana 服务、性能测试 PTS; 最佳实践企业云监控集成云产品接入 登录 Prometheus 控制台,点击左侧菜单“接入中心”选择任意云产品后弹出接入页面,选择待接入的云产品安装即可,安装完成后会创建一个名为“企业云服务”的 Prometheus 实例。监控指标点击“云服务实例”,选择相应云产品图标会弹出一个包含指标、大盘和告警 3 个 tab 页的窗口。指标页默认包括:指标、类别、描述 3 项基本信息,已集成云产品除默认项外还包括最近 10 分钟的指标量和占比。ECS 如图:Grafana 大盘大盘页默认显示该云产品的所有 Grafana 默认大盘缩略图。已集成的云产品点击缩略图或 Title 链接会跳转至阿里云 Grafana 监控大盘,未集成的云产品点击缩略图或 Title 链接会显示 Grafana 监控大图。ECS 实例详情:提供 ECS 实例的 CPU、内存、磁盘、网络等系统指标的监控,筛选维度包括:区域、ECS 标签、实例名、实例 ID;ECS 全局公网大盘:提供 ECS 实例公网流入、流出带宽合计、TOP 等指标;ECS 实例利用率排序大盘:支持 region 和全局维度 TOP 实例,主要指标:CPU 利用率、内存利用率、网络连接等;ECS 资源区域分布大盘:支持 ECS 实例、CPU、内存、磁盘、网络连接等按区域分布统计; 告警配置 告警页默认显示该云产品配置的所有告警规则:点击“创建 Prometheus 告警规则”通过默认告警模板设置或自定义 PromQL 完成告警规则的创建(自定义 PromQL 指标名可参考步骤“云产品指标”)。默认告警规则 CPU 利用率AliyunEcs_cpu_total{} > 80内存利用率AliyunEcs_memory_usedutilization{} > 90磁盘利用率:磁盘使用率超过 90%时需要进行磁盘清理AliyunEcs_diskusage_utilization{} > 90磁盘剩余空间不足:当磁盘剩余空间小于 5G 时考虑清理AliyunEcs_diskusage_free{} < 1024*1024*1024*5热点指标 云产品自监控集成在开通云产品并创建实例时,会有开通 ARMS Prometheus 相关选项,创建完成后即可通过 Prometheus 实现该产品的指标监控。以“MSE 服务-云服务网关”为例:1. 创建实例时开通 Prometheus 监控2. 产品控制台监控入口Grafana 专业版云服务实例默认使用 Grafana 共享版,如果默认大盘不能满足运维团队可观测需求或者想在默认大盘基础上进行优化,可增购 Grafana 专家版或高级版。关于阿里云 Prometheus 监控阿里云 Prometheus 服务是基于云原生可观测事实标准 - Prometheus 开源项目构建的全托管监控服务。默认集成常见云服务,兼容主流开源组件,全面覆盖业务监控/应用层监控/中间件监控/系统层监控。通过开箱即用的 Grafana 看板与智能告警功能,并全面优化探针性能与系统可用性,帮助企业快速搭建一站式指标可观测体系。助业务快速发现和定位问题,减轻故障给业务带来的影响,并免去系统搭建与日常维护工作量,有效提升运维监控效率。与此同时,阿里云 Prometheus 作为阿里云可观测套件的重要组成部分,与 Grafana 服务、链路追踪服务,形成指标存储分析、链路存储分析、异构构数据源集成的可观测数据层,同时通过标准的 PromQL 和 SQL,提供数据大盘展示,告警和数据探索能力。为 IT 成本管理、企业风险治理、智能运维、业务连续性保障等不同场景赋予数据价值,让可观测数据真正做到不止于观测。
作者:三辰前言大家好,今天给大家带来 MSE 高可用方向的重要功能——风险管理的发布。阅读这篇文章,你将能够了解以下知识点和能力:熟悉微服务体系高可用如何设计掌握如何控制系统中的风险了解MSE微服务引擎风险管理功能能解决什么风险熟悉如何使用风险管理功能了解风险管理更多高级功能的未来规划微服务高可用如何设计大促场景如何做高可用阿里巴巴十几年的大促经验,积累了一套成熟的微服务高可用评估体系。我们现在以大促场景为例,谈谈如何做好高可用。大促高可用首先从架构上看,内部的电商、物流、文娱等业务系统,都是基于 MSE 微服务引擎提供的云原生网关和 Nacos 注册配置中心构建的微服务体系。并且在整个链路上基于 MSE 的 Sentinel 覆盖限流降级的能力,基于 ARMS 的 Prometheus 和 Tracing 能力做好链路的可观测。底层容器化,基于 K8s 这一套成熟的调度体系,解决资源利用率、快速交付和弹性的问题。在大促即将到来之前,通过 PTS 提供的全链路压测能力,对整个大促涉及的所有链路进行端到端的压测,模拟真实大促流量,观测每个业务子系统的表现,验证限流降级预案执行准确无误。峰值前快速弹性上线,峰值后快速缩容下线。MSE 微服务引擎介绍基于这一套双十一大促实践经验,阿里中间件团队将这一套微服务最佳实践开源,并提供了一套完整的商业化解决方案。以满足外部客户对高性能、高可用、高集成度和安全的述求。微服务引擎(Micro Service Engine,简称 MSE)是一个面向业界主流开源微服务生态的一站式微服务平台。高可用设计思路系统组成 那么,一套微服务系统如果从零开始搭建,应该如何设计保证高可用呢?我们用一张简单的图来表示一个微服务系统的基本架构。微服务系统全链路包含网关、注册配置中心、业务子系统,任何地方都是「牵一发而动全身」,一个抖动都可能会较大范围地影响整个系统。每个业务子系统之间调用关系通常也非常复杂,甚至是网状的。可能发生什么问题? 这套最小系统的每一个部分都可能发生问题,我们来看看都有哪些。先从入口的网关来看,最典型的问题就是容量不足,导致吞吐量下降。表现就是用户访问系统出现超时;也有可能是错配导致流量丢失,用户访问的页面找不到打不开,比如最流行的 Nginx,没有页面操作,都是黑屏控制,很容易出现漏配、错配的问题,也缺少配置版本的管理,非常容易失误。注册中心故障,会导致注册失败,影响大促场景下快速弹性上线,新的容器都无法注册上来。在服务调用方还可能收到空列表的情况。配置中心出问题,会导致风险预案无法下发,不能对业务降级。业务子系统更加复杂,可能出现某个子系统流量瓶颈,拖垮整个流量的情况。业务异常缺少观测手段,该打日志的地方没有任何信息。这些都需要借助服务治理的能力解决。这些问题都是以往的大促活动中真实案例,每一个高可用方案的背后,都是一段血泪史。面对风险设计 我们不得不承认一个事实:没有任何系统是百分之百没有问题的。高可用架构就是面对失败设计,或者说是面对风险设计。基础设施意外风险,最典型的就是几年前,杭州某条光缆被地铁施工挖断,导致全国的支付宝都用不了。这种风险一旦发生,业务很难承受。还有操作系统依赖上,可能有存储故障、网络抖动、时间服务不稳定、DNS 故障等等,系统 hang 死了连监控报警都有可能上不来。还有业务系统服务端故障、内存泄露,客户端连接池满,运维人为误操作等。虽然我们不可避免风险发生,但是,我们可以控制风险。高可用的本质:控制风险如何控制风险风险控制的策略大致可以分为四种策略控制风险,如下图:有了相应的策略,我们如何提前识别风险并加以控制?识别不同风险我们把风险分成几类:架构风险版本风险容量风险安全风险 架构风险例如:注册配置中心、网关、业务系统单节点都无法高可用Nacos、ZK等注册中心一致性协议对双数节点存在无法选主的问题,写请求不可用注册中心节点在可用区分布不均,可用区故障可能导致集群不可用业务系统架构风险:无注册中心容灾措施(如推空保护、服务列表缓存&降级方案)这些都可以算作架构风险。MSE 注册配置中心三 AZ 容灾架构MSE 专业版的注册配置中心,默认采用三可用区部署的容灾架构。通过 3 副本解决了单点问题,以多可用区部署的方式来减少了单一可用区不可用的风险带来的影响。集群所依赖的网络和存储实例,也都是多可用区部署的架构。这就是一个云上服务做高可用容灾的典型架构。开发者的业务架构也同样可以 follow 这个模式。业务架构风险 说到业务架构,通常一个网格状的业务调用关系,一定会有服务消费者(Consumer)和服务提供者(Provider)。1. Consumer服务消费者(Consumer)会从注册中心上订阅服务提供者(Provider)的实例列表。当遇到突发情况(例如,可用区断网,Provider 端无法上报心跳) 或 注册中心(变配、重启、升降级)出现非预期异常时,都有可能导致订阅异常,影响服务消费者(Consumer)的可用性。为了应对不可预知的情况下订阅列表异常,可以在 Consumer 侧配置推空保护。我们来看一下什么是 Consumer 端的推空保护。当 Provider 端到 Nacos 注册中心的网络出现异常,或是注册中心自身运维上下线过程中,维护的 Provider 实例列表可能出现空的情况,推送到 Consumer 端。这时,Consumer 侧订阅到了空的 Provider 列表,就会导致业务中断。如果在 Consumer 侧配置推空保护,收到空列表时会丢弃这次异常的更新操作,仍然保持上一次非空列表,确保业务调用链路的流量正常往下走。开启的方式非常简单,无论是 SCA 还是 Dubbo 框架,一个配置即可开启。推空保护支持的版本要求大家可以在我们 MSE 的高可用最佳实践帮助文档当中找到。Consumer 第二个有效措施是服务降级。Consumer 端可以根据不同的策略选择是否将某个调用接口降级,起到对业务请求流程的保护(将宝贵的下游 Provider 资源保留给重要的业务 Consumer 使用)服务降级的具体策略,包含返回 Null 值、返回 Exception 异常、返回自定义 JSON 数据和自定义回调这个降级过程是全自动,无需干预的过程。只要配置的策略被触发了,治理平台会自动执行预案,并且可以在控制台上清楚地观测到。2. Provider服务提供者(Provider)自身的可用性遇到问题,需要紧急下线,或者是日常运维上下线时,实例列表在注册中心上的更新不及时导致流量有损,就需要一系列措施来保障它的高可用。离群实例摘除 心跳续约是注册中心感知实例可用性的基本途径。Provider 在大流量下可能出现异常,但有时候服务不是完全不可用,它与注册中心之间的心跳续约仍然存在,但是某些系统资源耗尽是简单的心跳机制无法感知的。例如:Request 处理的线程池满依赖的 RDS 连接异常或慢 SQL 微服务治理中心提供离群实例摘除:基于异常检测的摘除策略:包含网络异常和网络异常 + 业务异常(HTTP 5xx)设置异常阈值、QPS 下限、摘除比例下限 离群实例摘除的能力是一个补充,根据特定接口的调用异常特征,来衡量服务的可用性。降级过程完全自动。无损上下线 通常我们不做任何措施的情况下,我们的服务上下线都是有损的。有损下线无损下线,又叫优雅下线、或者平滑下线,都是一个意思。首先看什么是有损下线:Provider 实例进行升级过程中,下线后心跳在注册中心存约以及变更生效都有一定的时间,在这个期间 Consumer 端订阅列表仍然没有更新到下线后的版本,如果鲁莽地将 Provider 停止服务,会造成一部分的流量损失。无损下线可以通过 MSE 微服务治理平台的能力,开启无损上下线。无侵入、无改造地无感开启。无损下线的流程整合在发布流程中,对应用进行停止、部署、回滚、缩容、重置等操作时,无损下线会自动执行。免去繁琐的运维脚本逻辑的维护。版本风险任何软件版本都有一个迭代过程,不断增强功能和优化的过程当中,也会无意中引入一些问题。在我们 Nacos 过去发布的版本当中,就存在一些客户端版本在特定条件下会出现严重问题的缺陷。例如:Nacos-Java-Client:v1.4.1 DNS 失败后心跳线程无法自愈;或者是一些社区维护的多语言版本客户端,存在一些功能的缺失。服务端版本也是同样的。由 MSE 专业的商业化团队维护,无论是注册中心还是网关都在不断地迭代收敛各类性能问题和功能缺陷,版本总是越发展越趋向于稳定,一些过去存在严重缺陷的版本,我们也会通过这次发布的风险管理功能给开发者们透出。案例 某客户在阿里云上使用 K8s 集群部署了许多自己的微服务,但是某一天,其中一台节点的网卡发生了异常,最终导致服务不可用,无法调用下游,业务受损。ECS 故障节点上运行着 K8s 集群的核心基础组件 CoreDNS 的所有 Pod,它没有打散,导致集群 DNS 解析出现问题。该客户的服务发现使用了有缺陷的客户端版本(nacos-client 的 1.4.1 版本),这个版本的缺陷就是跟 DNS 有关——心跳请求在域名解析失败后,会导致进程后续不会再续约心跳,只有重启才能恢复。这个缺陷版本实际上是已知问题,阿里云在 5 月份推送了 nacos-client 1.4.1 存在严重 bug 的公告,但客户研发未收到通知,进而在生产环境中使用了这个版本。案例中存在的风险:CoreDNS 没有按节点打散,单点架构风险依赖客户端版本风险没有被通知,没有有效收敛容量风险容量评估一直是一个复杂的事情。每年每个大促,阿里内部都会做一次全链路的压测,目的就是确保每个业务和系统的容量做到最佳的评估。容量风险带来的雪崩效应能够像洪水一样,瞬间摧毁整个系统。说它复杂,是因为每个子系统都有不同的评估指标和标准。注册中心:Provider 数量、连接数、QPS/TPS配置中心:配置长轮询数、连接数、QPS/TPS网关:并发连接数、新建连接数、带宽、QPS不同条件下(短/长连接、包大小、是否 https/gzip)的 QPS 容量是不同的真实条件更加复杂业务系统:吞吐能力(QPS/TPS/RT)、上下游依赖的处理能力 比如注册中心关注 Provider 数量、连接数、TPS;配置中心关注长轮询请求的量;网关更加复杂,并发连接数、新建连接数、带宽、QPS;甚至不同条件下,比如请求是长连接还是短连接、每个 HTTP 包的大小、是否是 HTTPS、是否 gzip 压缩,都是影响容量上限的因素。业务系统除了需要评估自身的吞吐能力之外,还需要关注上下游依赖的处理能力,遵循木桶原理,通过全链路压测的方式,来找到那个短板。网关容量评估策略 这里简单分享一个大促下网关的容量评估方法。大促的特点是什么?第一个是瞬时流量非常高,秒级突发流量,我们需要做好过载保护的限流措施,除了正常流量之外,还需要预留好足够的容量水位应对突发的网络攻击。第二个是大促会有热点商品,网关针对热点商品提前预热流量,确保底层业务系统处于最佳状态。第三个是梳理和保障核心链路,大促期间,一些非主链路的,锦上添花的功能就可以直接在网关侧降级掉,避免不必要的流量打到业务系统上。我举一个我自己体会很深的一个例子,就是钉钉当时因为疫情,学校都通过钉钉在家上网课,为了保障核心视频链路的通畅,所有无关的功能就被降级掉了。比如表情标签,点赞这些功能,一般人不会因为不能点赞而抱怨功能异常产生舆情,降级也是合理的。安全风险开源产品总会时不时报出安全漏洞,无论是产品自身还是第三方依赖。注册中心(Nacos、ZooKeeper)、网关(Envoy)相关安全漏洞客户端的第三方依赖漏洞(log4j 等) 安全能力:注册配置中心公网 Endpoint 白名单 ACL 控制MSE 云原生网关获得信通院安全评级认证网关支持 WAF 本地防护目前,MSE 已经具备较高的安全能力。很多客户都为了调试方便,注册配置中心的公网 Endpoint 没有设置 ACL,容易被攻击。我们建议将 ACL 开启。网关支持本地 WAF 等防护能力,并且获得了信通院安全评级认证。风险管理功能介绍到这里,大家应该充分掌握了如何有效地控制系统中的风险。本次 MSE 发布的风险管理功能,目地就是让开发者能够简单高效地识别和控制风险,给大家一个 MSE 产品相关的风险控制的最佳实践指导。功能页面风险管理已覆盖 MSE 中 Nacos、ZooKeeper、云原生网关三大子产品。在实例页面中的菜单上可以找到:针对每一个实例,我们会给出当前实例的风险列表,覆盖架构、版本、容量、安全等方面。每个风险都会给出相应的解决方案和建议,如果需要扩容或升配,建议在业务低峰期操作。未来规划过去,风险的识别都依赖人工感知,甚至滞后,到了风险发生时再采取措施就为时已晚了。现在,MSE 相关产品都已经能够做到系统自动化的识别风险信息,并且主动推送到使用产品的负责人。我们完成了风险识别、透出、诊断链路的建设,后续还会不断建设完善更多的诊断方式,增加对风险的识别能力。未来,我们还会探索风险自愈能力的建设。我们希望把一些明确的风险问题能够做到自愈,让用户无需感知风险收敛的过程。感知容量风险,自动弹性;在可运维时间内无感知自愈;提供一个用户可主动订阅的事件中心,帮助用户快速感知异常事件。作者介绍:三辰,云原生微服务基础架构技术专家、MSE 架构-高可用负责人。更多 MSE 特性,欢迎进钉钉群交流~
作者:ServerlessServerless 架构将成为未来云计算领域重要的技术架构,将会被更多的业务所采纳。进一步深究,Serverless 架构在什么场景下有优秀的表现,在什么场景下可能表现得并不是很理想呢?或者说,有哪些场景更适合 Serverless 架构呢?Serverless 架构的应用场景 Serverless 架构的应用场景通常是由其特性决定的,所支持的触发器决定具体场景。如图 1-1 所示,CNCF Serverless Whitepaper v1.0 描述的关于 Serverless 架构所适合的用户场景如下。异步并发,组件可独立部署和扩展的场景。突发或服务使用量不可预测的场景。短暂、无状态的应用,对冷启动时间不敏感的场景。需要快速开发、迭代的业务。1-1 CNCF Serverless Whitepaper v1.0 描述的 Serverless 架构所适合的用户场景CNCF 除基于 Serverless 架构的特性给出 4 个适用的用户场景之外,还结合常见的触发器提供了详细的例子。响应数据库更改(插入、更新、触发、删除)的执行逻辑。对物联网传感器输入消息(如 MQTT 消息)进行分析。执行流处理(分析或修改动态数据)。数据单次提取、转换和存储需要在短时间内进行大量处理(ETL)。通过聊天机器人界面提供认知计算(异步)。调度短时间内执行的任务,例如 CRON 或批处理的调用。机器学习和人工智能模型。持续集成管道,按需为构建作业提供资源。CNCF Serverless Whitepaper v1.0 基于 Serverless 架构的特点,从理论上描述了 Serverless 架构适合的场景或业务。云厂商则站在自身业务角度来描述 Serverless 架构的典型应用场景。通常情况下,当对象存储作为 Serverless 相关产品触发器时,典型的应用场景包括视频处理、数据 ETL 处理等;API 网关更多会为用户赋能对外的访问链接以及相关联的功能等,当 API 网关作为 Serverless 相关产品的触发器时,典型的应用场景就是后端服务,包括 App 后端服务、网站后端服务甚至微信小程序等相关产品的后端服务。一些智能音箱也会开放相关接口,这个接口也可以通过 API 网关触发云函数,获得相应的服务等;除了对象存储触发以及 API 网关触发,常见的触发器还有消息队列触发器、Kafka 触发器、日志触发器等。Web 应用或移动应用后端如果 Serverless 架构和云厂商所提供的其他云产品结合,开发者能够构建可弹性扩展的移动应用或 Web 应用程序 ,轻松创建丰富的无服务器后端。而且这些程序在多个数据中心可用。图 1-2 所示为 Web 应用后端处理示例。1-2 Web 应用后端处理示例实时文件/数据处理在视频应用、社交应用等场景下,用户上传的图片、音视频往往总量大、频率高,对处理系统的实时性和并发能力都有较高要求。此时,对于用户上传的图片,我们可以使用多个函数对其分别处理,包括图片的压缩、格式转换等,以满足不同场景下的需求。图 1-3 所示为实时文件处理示例。1-3 实时文件处理示例我们可以通过 Serverless 架构所支持的丰富的事件源、事件触发机制、代码和简单的配置对数据进行实时处理,例如:对对象存储压缩包进行解压、对日志或数据库中的数据进行清洗、对 MNS 消息进行自定义消费等。图 1-4 所示为实时数据处理示例。1-4 实时数据处理示例离线数据处理通常,要对大数据进行处理,我们需要搭建 Hadoop 或者 Spark 等相关的大数据框架,同时要有一个处理数据的集群。但通过 Serverless 技术,我们只需要将获得到的数据不断存储到对象存储,并且通过对象存储配置的相关触发器触发数据拆分函数进行相关数据或者任务的拆分,然后再调用相关处理函数,之后存储到云数据库中。例如:某证券公司每 12 小时统计一次该时段的交易情况并整理出该时段交易量 top5;每天处理一遍秒杀网站的交易流日志获取因售罄而产生的错误,以便准确分析商品热度和趋势等。函数计算近乎无限扩容的能力可以使用户轻松地进行大容量数据的计算。利用 Serverless 架构可以对源数据并发执行 mapper 和 reducer 函数,在短时间内完成工作。相比传统的工作方式,使用 Serverless 架构更能避免资源的闲置,从而节省成本。数据 ETC 处理流程可以简化为图 1-5。1-5 数据 ETL 处理示例人工智能领域在 AI 模型完成训练,对外提供推理服务时,基于 Serverless 架构,将数据模型包装在调用函数中,在实际用户的请求到达时再运行代码。相对于传统的推理预测,这样做的好处是无论是函数模块还是后端的 GPU 服务器,以及对接的其他相关机器学习服务,都可以进行按量付费以及自动伸缩,从而在保证性能的同时确保服务的稳定。图 1-6 为机器学习(AI 推理预测)处理示例。1-6 机器学习(AI 推理预测)处理示例物联网(IoT)领域目前,很多厂商都在推出自己的智能音箱产品—用户对智能音箱说一句话,智能音箱通过互联网将这句话传递给后端服务,然后得到反馈结果,再返给用户。通过 Serverless 架构,厂商可以将 API 网关、云函数以及数据库产品结合起来,以替代传统的服务器或者虚拟机等。Serverless 架构一方面可以确保资源能按量付费,即用户只有在使用的时候,函数部分才会计费;另一方面当用户量增加时,通过 Serverless 架构实现的智能音箱系统的后端也会进行弹性伸缩,保证用户侧的服务稳定,且对其中某个功能的维护相当于对单个函数的维护,并不会给主流程带来额外风险,相对来说会更加安全、稳定等。图 1-7 为 IoT 后端处理示例。图1-7 IoT 后端处理示例监控与自动化运维在实际生产中,我们经常需要做一些监控脚本来监控网站服务或者 API 服务是否健康,包括是否可用、响应速度等。传统的方法是通过一些网站监控平台(例如 DNSPod 监控、360 网站服务监控,以及阿里云监控等)进行监控和告警。这些监控平台的原理是用户自己设置要监控的网站和预期的时间阈值,由监控平台部署在各地区的服务器定期发起请求,进而判断网站或服务的可用性。当然,这些服务器虽然说通用性很强,但实际上并不一定适合。例如,现在需要监控某网站状态码和不同区域的延时,同时设置一个延时阈值,当网站状态异常或者延时过大时,平台通过邮件等进行通知和告警。目前,针对这样一个定制化需求,大部分监控平台很难直接实现,所以开发一个网站状态监控工具就显得尤为重要。除此之外,在实际生产运维中,对所使用的云服务进行监控和告警也非常有必要。例如:在使用 Hadoop、Spark 时要对节点的健康进行监控;在使用 Kubernetes 时要对 API Server、ETCD 等的指标进行监控;在使用 Kafka 时要对数据积压量,以及 Topic、Consumer 等的指标进行监控。对于这些服务的监控,我们往往不能通过简单的 URL 以及某些状态进行判断。在传统的运维中,我们通常会在额外的机器上设置一个定时任务,以对相关服务进行旁路监控。Serverless 架构的一个很重要的应用场景就是运维、监控与告警,即通过与定时触发器结合使用,实现对某些资源健康状态的监控与感知。图 1-8 为网站监控告警示例。1-8 网站监控告警示例新书推荐阿里云、蚂蚁集团的 4 位专家刘宇、田初东、卢萌凯、王仁达(排名不分先后)系统梳理阿里在 Serverless 架构下的 AI 经验,联袂推出新书《Serverless 架构下的 AI 应用开发:入门、实战与性能优化》 。本书是关于 Serverless 架构下机器学习实战的技术书,我们希望通过简单明了的语言、真实的案例,以及开放的源代码,为读者介绍 Serverless 架构与机器学习相关的基础知识,帮助读者在 Serverless 架构下开发、上线机器学习项目。新书将在免费在 Serverless 公众号连载,欢迎大家订阅关注
作者:姚辉在 2018 年,Observability(即可观测性)首次被引入 IT 领域,并逐渐取代只关注系统整体可用性的传统监控。随着云原生技术的不断发展,企业从单体架构发展到分布式架构,使用容器部署拆分出来的一众微服务、与业务联系紧密,传统的监控仅适合报告系统的整体运行情况无法进行高度细化的分析与关联,于是需要将研发视角融入监控,发展具有比原有监控更广泛、更主动、更细粒度的能力,这种能力就是可观测性。Dubbo 3 的建设规划有上云,可观测性是上云必不可少的能力,集群间根据实例可用性负载均衡、Kubernetes 弹性伸缩、建立实例健康模型等等运用场景都需要可观测性。目前 Dubbo 3 的可观测性正在建设中,本文主要介绍 Metrics 模块基础知识与进度。零-APM 介绍APM全称是 application performance management,翻译过来就是应用的性能管理,主要是用来管理和监控软件系统的性能和可用性。可以保障线上服务的质量,是一个重要的服务治理工具。如果从系统职能上分的话,APM 系统的话可以可以分为三个子系统,分别是 Metrics、Tracing 和 Logging。Metrics 也叫指标监控,主要是负责处理一些结构化的可以聚合的一些指标数据。Tracing 又叫链路追踪,主要是围绕单次请求进行信息处理,然后所有的数据都被绑定到系统的单个请求或者说单个事务上。Logging 是日志监控,主要梳理一些非结构化的事件。Metrics 结构与类型一个 Metrics 由四部分组成,第一个是指标名称;第二个是 labels 或者说 tags 也就是标签,是一些维度数据,这些维度数据可以用来做一些过滤或者聚合查询;第三个是时间戳,就是它的时间字段;第四个就是具体的指标的一个值。除了上述四个部分之外,还有一个非常重要的字段没有体现在数据模型里,就是这条数据的指标类型。不同的指标类型的话它是会用在不同的监控场景,同时它的一些查询和可视化的一些方式,也会有一些区别。下面简单介绍一些常用的指标类型。第一个是 Gague,这个类型的特点就是他是可增可减的。比如说 CPU 负载、活跃线程数、内存使用率、磁盘使用率,这些数它都是会随着时间进行波动的。它存储和展示的都是一个瞬时值。第二个指标类型 Counter,这个类型的特点是只增不减,比如说接口请求总量,对于这个类型,一般会有几个衍生的处理,一个是可以比较两个时间点前后的一个差值,这样可以计算出这个单位时间内的请求的一个波动量。第二个就是对时间进行求导之后,就得到 QPS 这种类型的一个字段。第三个指标类型是 Summary,主要做的是一个汇总统计,比如说平均值,分位数这样的一些指标。然后这个指标类型的话主要用于接口响应延迟这样的一个场景。因为我们平时在看接口响应延迟这个指标的时候,一般除了看它的平均值,可能还会看一些那种分位数指标。第四个指标类型是 Historgram,它是一个柱状统计,一般是会先对指标进行一个分桶,分桶之后再去统计它的一些值。比如说我们的还是以那个接口响应延迟为例的话,它会比如说有一些那种可视化展示的话,展示它的那个柱状图。指标收集Dubbo 的指标体系,总共涉及三个模块,分别是指标收集、本地聚合、指标推送。指标收集:将 Dubbo 内部需要监控的指标推送至统一的 collector 中进行存储。本地聚合:指标收集获取的均为基础指标,而一些分位数指标则需通过本地聚合计算得出。指标推送:而获取指标的话有两种方式,第一种是直接访问 Dubbo 暴露的接口就可以获得 Dubbo 内部统计的指标,第二种是接入第三方服务器进行指标推送,Dubbo 会将收集和聚合后的指标通过 pull 或者push的方式推送至第三方服务器,目前只涉及 Prometheus,其中 pull 或者 push 由用户选择。 指标收集指标收集的目的是为了存储微服务的运行状态,相当于给微服务拍了一个快照,以及为进一步的分析(比如指标聚合)提供基础数据。上图为 Dubbo 的架构图,本方案中指标收集的埋点位置或者说切入位置是在 provider 中通过 SPI 的方式添加一个 Filter。这里贴了部分代码,展示了其中一部分指标收集的逻辑。我们是通过 interfaceName、methodName、group、version 四个维度的信息作为 map 存储结构的 key ,当然这四个维度的信息最后在指标导出的时候都会转换成前面 metrics 存储结构的 labels 或者说 tags。接下来给大家展示一个的是我们一个默认存储器的成员变量。运用分段锁结构的 ConcurrentHashMap 来保证并发度,其中的 MethodMetric 就是前文说的四个维度信息组成的一个 class。有一个比较重要的结构是一个 MetricsListener 的 list ,这里其实是一种生产者消费者的模式,因为默认收集器是我们默认接入的,但是如果需要收集其他指标则需要继续在此添加监听,让其他收集器监听默认收集器的状态,当默认收集器收集到了值就向监听列表推送一个事件,这样其他收集器就能收集到元信息再进一步加工处理。这里也是本地聚合实现的一个逻辑,具体细节不展示了,有兴趣的同学可以去看看 Dubbo 3.1 的代码。本地聚合-滑动窗口与 TDigest本地聚合主要使用滑动窗口与 TDigest,滑动窗口原理如图,假设我们初始有 6 个 bucket,每个窗口时间(即一个 bucket 在 current 指针下的停留时间)设置为2分钟,每次写入指标数据时,会将数据分别写入 6 个 bucket 内,也就是一条数据写六遍,我们会每隔两分钟移动一个 bucket 并且清除原来 bucket 内的数据,读取指标时,会读取当前 current 指向的 bucket 内的指标数据,以达到滑动窗口的效果。滑动窗口的作用是为了能够对近期的数据做一个聚合,使得我们每次指向的 bucket 里面存储的都是从当前时间到过去一个 bucket 生命周期(即 [ now - bucketLiveTime * bucketNum, now ] 这样一个时间区间)的指标数据。其中 bucket 的生命周期受窗口时间和 bucket 数量控制,这个支持用户自定义配置。接下来是介绍 Dubbo 分位数指标的处理,我们常说的 p99,p95 这样的指标就是分位数指标,p99 是指在 100 个请求里面,响应时延排名第 99 位的值,可以较好的反应一个服务的可用性,被称为黄金指标。Dubbo 在计算分位数指标的时候使用了 TDigest 算法,TDigest 是一个简单,快速,精确度高,可并行化的近似百分位算法。TDigest 使用的思想是近似算法常用的 Sketch,也就是素描,用一部分数据来刻画整体数据集的特征,就像我们日常的素描画一样,虽然和实物有差距,但是却看着和实物很像,能够展现实物的特征。下面是 TDigest 的原理。假如有 500 个 -30 ~ 30 间的数字,可以使用概率密度函数也就是 PDF 函数表示这一数据集该函数上的某一点的 y 值就是其 x 值在整体数据集中的出现概率,整个函数的面积相加就正好为 1 ,可以说它刻画了数据在数据集中的分布态势,也就是大家熟悉的正态分布。有了数据集对应的 PDF 函数,数据集的百分位数也能用 PDF 函数的面积表示。如下图所示,百分位数 P75 就是面积占了 75% 时对应的 x 坐标。PDF 函数曲线中的点都对应着数据集中的数据,当数据量较少时,我们可以使用数据集的所有点来计算该函数,但是当数据量较大时,只有通过少量数据来代替数据集的所有数据。这里,需要将数据集进行分组,相邻的数据分为一组,用平均数和来代替这一组数。这两个数合称为质心数,然后用这个质心数来计算 PDF,这就是 TDigest 算法的核心思想。如下图所示,质心数的平均值作为x值,个数作为 y 值,可以通过这组质心数大致绘制出这个数据集的 PDF 函数:对应的,计算百分位数也只需要从这些质心数中找到对应的位置的质心数,它的平均值就是百分位数值。很明显,质心数的个数值越大,表达它代表的数据越多,丢失的信息越大,也就越不精准。如这张图所示,太大的质心数丢失精准度太多,太小的质心数则有消耗内存等资源较大,达不到近似算法实时性高的效果。所以,TDigest 在压缩比率的基础上,按照百分位数来控制各个质心数代表的数据的多少,在两侧的质心数较小,精准度更高,而在中间的质心数则较大,以此达到 P1 或 P99 的值要比 P20 更准确的效果。指标推送之 Prometheus指标推送的作用是为了将目前 Dubbo 提供的指标进行进一步的存储、运算和可视化,目前第三方服务器只支持 Prometheus。Prometheus 是 CNCF 开源的一个应用于应用监控的系统。主要有三个模块组成,分别是获取数据,存储数据,数据查询。获取数据有 Pull 和 Push 两种方式,也是 Dubbo 接入的方式;存储数据 Prometheus 是用的时序数据库这里就不展开讲了;数据查询是其自定义的一套查询 IDL,可以接入 Grafana 这一类报警系统,当监控指标异常时候可以使用邮件报警或者电话报警。目前的设计:指标推送只有用户在设置了配置且配置 protocol 参数后才开启,若只开启指标聚合,则默认不推送指标。Promehteus Pull ServiceDiscovery:启动时根据配置将本机 IP、Port、MetricsURL 推送地址信息至中间层,暴露 HTTP ServiceDiscovery 供 Prometheus 读取,配置方式如 ,其中在 Pull 模式下 address 为可选参数,若不填则需用户手动在 Prometheus 配置文件中配置地址。 Prometheus Push Pushgateway:用户直接在 Dubbo 配置文件中配置 Prometheus Pushgateway 的地址即可其中 interval 代表推送间隔相关 Dubbo Metrics 功能我们预计会在 3.1.2 / 3.1.3 版本中正式 release 发布。服务治理与商业化Dubbo 3 的可观测性建设是 Dubbo 3 上云必不可少的一个环节。在 Dubbo 3 对标的商业化产品微服务引擎 MSE 中,针对 Dubbo 3 做了全方面的增强,以一种无侵入的方式增强 Dubbo 3 服务,使其具备完整的微服务治理能力。在建设 Dubbo 可观测性的同时,我们也在结合 OpenSergo 标准构建 Dubbo 3 的完整的服务治理体系。OpenSergo 在联合各个社区进行进一步的合作,希望通过社区来一起讨论与定义统一的服务治理标准。当前社区也在联合 bilibili、CloudWeGo 等企业、社区一起共建标准,也欢迎感兴趣的开发者、社区与企业一起加入到 OpenSergo 服务治理标准共建中。欢迎大家加入 OpenSergo 社区交流群(钉钉群)进行讨论:34826335
作者:颍川引言Prometheus + Grafana 已经成为云原生时代的可观测性事实标准。我们使用 Prometheus 观测云原生时代的 Kubernetes 体系下的 Node、ApiServer、workload 等的基础 metric,同时通过 Prometheus Exporters 采集各种组件(如 Redis、Kafka 等)和业务应用的 metric,最后通过 Grafana 展示大盘、AlertManager 进行告警,实现了云原生 Kubernetes 体系下 metric 可观测闭环。由于大量非云原生的历史系统演进到云原生体系是个长时期过程,因此这些非云原生系统的可观测闭环也是我们必须解决的问题。我们很自然地想到“既然 Prometheus + Grafana 实现了云原生体系的 metric 可观测闭环,是否可以使用这套神器来解决非云原生体系应用的同样问题呢?”,答案是肯定的。本文介绍如何使用阿里云 Prometheus 来实现非 Kubernetes 应用(即 ECS 应用)的 metric 观测。ECS 应用的典型部署场景场景 1:纯公有云 VPC业务应用部署在一个或多个 VPC 内,每个 VPC 内购买了一批 ECS,在这些 ECS 上部署了基础组件(数据库和中间件等)和业务应用。此场景下,我们需要对这些 ECS OS(Linux 或 Windows)、基础组件和业务应用本身进行 metric 观测。场景 2:公有云 VPC+线下 IDC业务除了部署公有云 VPC 上外,还需要与线下 IDC 机房进行互通互联。通常,我们使用专线方式打通云上 VPC 和线下 IDC 机房。此场景下,我们期望有一套完整的 metric 观测平台,同时解决线上 VPC 和线下 IDC 的 metric 观测。场景 3:公有云 VPC+多云 ECS业务除了部署在阿里云 VPC 上外,还通过公网与其它云上的 ECS 进行互通互联。此场景下,我们也期望有一套完整的 metric 观测平台,实现一体化全局视角观测。自建 Prometheus 观测 ECS 应用的痛点自建 Prometheus 观测 ECS 应用,我们将面临的典型问题有:由于安全、组织管理等因素,用户业务通常部署在多个相互隔离的 VPC,需要在多个 VPC 内都重复、独立部署 Prometheus,导致部署和运维成本高。 每套完整的自建观测系统都需要安装并配置 Prometheus、Grafana、AlertManager 以及各组件 Exporter,过程复杂、实施周期长。 缺少与阿里云 ECS 无缝集成的服务发现(ServiceDiscovery)机制,无法根据 ECS 标签来灵活定义抓取 targets。如果自行实现类似功能,则需要使用 Golang 语言开发代码(调用阿里云 ECS POP 接口)、集成进开源 Prometheus 代码、编译打包后部署,实现门槛高、过程复杂、版本升级困难。 常用组件的开源 Grafana 大盘不够专业,缺少结合观测组件的原理和最佳实践进行深入定制。 缺少常用组件的告警项模板,需要用户自行研究、配置告警项,工作量大,且很可能缺少各组件领域的专业技术沉淀。 阿里云 Prometheus 监控的能力框架阿里云 Prometheus 监控[1]是一款全面对接开源 Prometheus 生态,支持类型丰富的组件观测,提供多种开箱即用的预置观测大盘,且提供全面托管的混合云/多云 Prometheus 服务。除了支持阿里云容器服务、自建 Kubernetes、Remote Write 外,阿里云 Prometheus 还提供混合云+多云 ECS 应用的 metric 观测能力;并且支持多实例聚合观测能力,实现 Prometheus 指标的统一查询,统一 Grafana 数据源和统一告警。其逻辑架构如下示意:对于 ECS 应用,阿里云 Prometheus 提供以下 metric 数据采集方式:托管 exporter:提供 MySQL、Redis 等数十种常见组件[2](持续更新中)的托管部署。用户只需要在阿里云 Prometheus 控制台配置观测组件相关信息(如 IP 地址、端口等),即可实现 VPC 内 ECS 上这些组件的 metric 监控。由于线下 IDC 通过专线与 VPC 互通,因此托管 exporter 同时也能采集到线下 IDC 内的组件 metric。 非托管 exporter:对于我们暂未提供托管 exporter 的组件,或用户业务应用的自定义 metric,用户可以在 VPC 或 IDC 内部署自定义 exorter,然后在阿里云 Prometheus 控制台上配置自定义服务发现(ServiceDiscovery),最后阿里云 Prometheus 主动发现这些 exporter,并定时抓取和存储 metric。 Node/Windows exporter:它们是一类特殊的非托管 exporter,因为需要部署在每台 ECS 上,以便采集 ECS OS 上观测信息。阿里云 Prometheus 提供了 Node exporter 的原生支持,Windows exporter 原生支持也即将上线。ECS 应用场景下,自建 Prometheus 与阿里云 Prometheus 对比如何使用阿里云 Prometheus 观测 ECS 应用步骤 1:创建 VPC 实例登录 Prometheus 控制台[3],选择新建 Prometheus 实例,根据界面提示,填写实例名、选择 VPC / VSwitch / SecurityGroup / Grafana 工作区,即可创建 VPC 实例成功。操作说明详见阿里云帮助中心文档[4]。步骤 2:接入组件监控目前阿里云 Prometheus 已支持 Node exporter、MySQL、Redis、ElasticSearch、Kafka、Nginx、MongoDB、PostgreSQL、RabbitMQ、RocketMQ、BlackBox 等组件观测。阿里云 Prometheus 天然内置支持了 static_configs和aliyun_sd_configs 两种最常用/实用的服务发现方式,方便用户进行组件观测目标 ECS 的配置。此处以 MySQL 为例,简要描述接入配置方法。登录 Prometheus 控制台后,进入已创建的 VPC 实例详情的集成中心界面,新建 MySQL 接入,填写 MySQL 监控名称、MySQL 地址、端口、用户名/密码等信息即可。详细操作步骤和说明,参见阿里云帮助中心文档[5]。步骤 3:查看大盘阿里云 Prometheus 无缝集成了共享版 Grafana 和专家版 Grafana,用户无需单独安装 Grafana,即可查看各个组件的观测大盘。接入需要监控的组件后,在集成中心点击对应组件图标的已安装 Exporter,可以看到该组件的大盘略缩图和链接,点击即可进入阿里云 Grafana,查看对应观测大盘。详见阿里云帮助中心文档[6]。步骤 4:配置告警进入 VPC 实例详情的集成中心界面,进入 MySQL 组件的告警界面,即可创建 Prometheus 告警规则,详见阿里云帮助中心文档[7]。阿里云 Prometheus 提供了免运维、开箱即用的 VPC(以及和 VPC 打通的线下 IDC 机房)内 ECS 的 OS、常见中间件、业务应用的 metric 观测能力,实现了一站式的云原生和非云原生环境的 metric 观测协同和闭环。同时我们正在持续升级和丰富常用组件的观测能力(如 Windows、JMX、ClickHouse、Jenkins、Process 等),敬请期待。关于阿里云 Prometheus 监控阿里云 Prometheus 服务是基于云原生可观测事实标准 - Prometheus 开源项目构建的全托管观测服务。默认集成常见云服务,兼容主流开源组件,全面覆盖业务观测/应用层观测/˙中间件观测/系统层观测。通过开箱即用的 Grafana 看板与智能告警功能,并全面优化探针性能与系统可用性,帮助企业快速搭建一站式指标可观测体系。助业务快速发现和定位问题,减轻故障给业务带来的影响,并免去系统搭建与日常维护工作量,有效提升运维观测效率。与此同时,阿里云 Prometheus 作为阿里云可观测套件的重要组成部分,与 Grafana 服务、链路追踪服务,形成指标存储分析、链路存储分析、异构构数据源集成的可观测数据层,同时通过标准的 PromQL 和 SQL,提供数据大盘展示,告警和数据探索能力。为 IT 成本管理、企业风险治理、智能运维、业务连续性保障等不同场景赋予数据价值,让可观测数据真正做到不止于观测。更具性价比的计费选择,Prometheus 包年包月相关链接[1] 阿里云Prometheus监控https://help.aliyun.com/document_detail/122123.html[2] 常见组件https://help.aliyun.com/document_detail/251830.html[3] 应用实时监控服务ARMShttps://arms.console.aliyun.com/#/home[4] Prometheus实例 for ECShttps://help.aliyun.com/document_detail/274450.html[5] 使用阿里云Prometheus监控MySQLhttps://help.aliyun.com/document_detail/161838.html[6] 集成中心https://help.aliyun.com/document_detail/427600.html[7] Prometheus告警规则https://help.aliyun.com/document_detail/331981.html
作者:虚镜概述Continuous Profiling 在软件开发生命周期的位置CI/CD 的概念非本文重点,不解释了。从上图可以看出。Continuous Profiling(持续性能分析,下文简称为 CP)是生产向开发进行反馈的非常重要的手段。发展历史CP 概念的起源于 Google 的论文[1]:Google Wide Profiling:A continuous Profiling infrastucture for data centers基本思路CP 意义可以分解为两个:性能分析(Profile)的意义:识别计算,存储,网络上的性能瓶颈问题,建立代码和性能瓶颈的关联性,从而协助开发者优化代码,解决瓶颈问题; 持续(Continuous)的意义:让性能分析贯穿应用的整个生命周期,从而解决非持续方案(如 ]on-demand)中无法抓到现场的问题。 Profiling 的基本思想 衡量程序性能最直观的方法就是通过响应时间(Response Time,简称 RT)。但仅仅知道程序的运行时间很难指导我们如何把程序优化地更快,我们想要更进一步地了解这段时间之内到底发生了什么。让我们先从一个例子开始,了解 Linux 下的时间统计告诉了用户什么信息:下面我们利用 Linux time 计算两件事情的时间消耗:生成一个 10M 的文件,随机生成数据;(IO 密集)对上一步生成的文件做个 CRC 计算;(CPU 密集) time 的输出告诉用户 3 个信息:real:总消耗时间user:用户态消耗时间sys:内核态消耗时 观察 time 的输出,可以看出 user + sys 不等于 real,这是因为程序并不是总是 CPU 上运行的,还可能因为 IO,Lock 等等原因处于睡眠,等待的状态,这段时间既不算在 user CPU time 也不算在 system CPU time。程序在 CPU 上执行的时间(即 user CPU time + system CPU time)称为 CPU time(或 on-CPU time);程序处于睡眠等状态的时间称为 off-CPU time(or blocked time);程序实际运行的时间称为 wall clock time(挂钟时间); time 的输出 real 对应的概念的是 wall clock time,因此可以看到:对于 IO 密集型的 workload(负载),off-CPU time 是不能忽略的;对于 CPU 密集型 workload(负载),on-CPU time 基本和 wall clock time 相等; 对于一个给定的线程(Linux 上称为轻量级进程):wall clock time = CPU time + off CPU time因此 Profile 整体分为:On-CPU: where threads are spending time running on-CPU.Off-CPU: where time is spent waiting while blocked on I/O, locks, timers, paging/swapping, etc. 可以看到 Off-CPU 分析类型是一系统结果的汇总统计,因此也可以将 Off-CPU 因为引起睡眠或者等待的原因不同,可以进一步划分为 file profiling,socket profiling,lock profiling 等等类型。Continuous 的基本思想 持续(Continuous)相对的概念是按需(On-Demand)。按需(或者触发式)比较常见的问题就是无法精准的抓取现场从而导致一些偶发(难以复现)的问题无法被识别。比如上图这样一条曲线(不管它表达什么),反正是有一段异常(或者说和大部分情况不一样的情形),随着自然时间的流逝;用户发现这个异常的时候,曲线已经恢复了,因此无法在去回溯现场。这种情况下,我们发现了一段异常,但是没有更多细节,开发者就无法知道代码内部发生了什么,因此也无从谈起修复和改善代码了。持续则意味着贯穿整个程序的完整生命周期,不会漏掉任何一个历史上产生过的异常。Continuous+Profiling 带给开发者的意义是:在生产环节,永远知道代码的所有执行细节。理解 profiling用户交互和可视化 性能分析的展现形式通常以 Flame Graph 火焰图来表达:理解火焰图 对火焰图理解的本质是了解性能分析数据(profiling data)究竟是什么。性能分析数据(profiling data)就是堆栈统计数据。为了帮助读者理解,举个简单的例子:横坐标表达的一个数值,在不同的场景下,可以赋予不同的含义,比如:在 cpu profiling 上,表达花费时间多少;在 alloc profling 上,表达成内存大小;...... 纵坐标是表达是一个 stack trace。因此上图表达的含义和下面一组数据是一致的。每一行以空格分割,左边的是 stack trace,右边是数值。a();b();c() 1 a();b();d() 2 c();b() 3到这里,读者应该对性能分析(profiling)的工作原理有个感性的认识,性能分析的整体流程如图:因此实现 profiling 的关键点:获取堆栈数据(爬栈):如何护获取问题点(瓶颈)点的堆栈数据;生成火焰图; 常见的 Profiling Tools(生成堆栈数据) 常见的工具如 Linux perf,eBPF profile,DTrace,SystemTap 等等,本文将这类用于获取堆栈数据工具统称为 Profiling Tools;Linux 这类工具的用法本文不多介绍,这类工具非常通用并且有效,但对于非C系开发者是没那么友好的。高级语言绝大部分应用开发者其实并不关心很低层次的内容,比如 page fault,numa banlance,context switch,L3 Cache miss 等问题,通常都不在应用开发者的知识图谱中。这部分内容的优化也不再本文的目标读者范围,因此不多叙述。对于 Profile Tools,我们可以将其分为两类:System Profile:which shows system code paths (eg, JVM GC, syscalls, TCP), but not Java methods. language Profile:These show language methods(eg java method), but usually not system code paths.JVM Profilegolang Profile.... 不难理解,Profiling Tools 能够爬栈就是因为在特定的代码里进行的 Hook 操作,这类操作一定会产生额外的开销。因此 Profiling Tools 会带来额外的开销(Overhead),不同类型的 Profiling 的 Hook 点不同,因此不同的性能分析类型会导致不同的 Overhead。很长一段时间,无法将 Profiling 带入生产环节最重要的阻塞点就是 Overhead 太高导致应用的业务逻辑受损严重。因此评价 Profiling Tools 是否适合上生产最重要的评估就是估算 Overhead。JVM Profiling上文提到的工具基本属于 System Profiling Tools 提供的能力,这部分工具的核心能力关注的是 system code paths;对于高级语言上一些特性,能力是不够强的。下面我们了解高级语言自身的 Profiling Tools 是如何帮助开发者来做性能优化的。golang 内置 pprof[2]java11 内置 JFR[3]其他高级语言有的有自身的工具,有的没有高级语言没有自身工具,这类通常可以借助 System Profiling Tools(如 perf 或者 ebpf)来实现性能分析。 以 java 为例子,认识下 java 程序运行的代码结构 ,如下图:对于 java 开发者而言,大部分场景是不考虑 JVM code,glibc code,kernel code 出问题的可能性的,这部分代码相对稳定,而且有稳定的组织去推动解决。因此 JVM Profiling 要表达的核心其实是:爬堆栈,只爬 Java code 这一层次(java stack),这个是大部分应用开发者关注的核心部分,对于下面的部分(native stack)则不在 java 开发者关心的范围。JVM 还有一个特征,就是把 Linux 底层的概念屏蔽,替换成自己的概念体系,比如:java 开发者更关心 java 线程状态机而不是 JVM 进程的进程状态机;java 开发者更关心 java heap,stack,nio 等内存统计而不是 native heap,native stack 以及 rss,pagecache 的统计;java 开发者关心 CMS 或 G1 垃圾回收情况而不是 Page Reclaim;java 开发者更关心 synchronized,JUC 锁,而不是 OS 锁; 因此,JVM Profiling中的性能分析类型会更贴近 java 开发者的概念体系,而不是 system profile 关心的内容。举个例子,相较于 on-cpu profiling,作为 java 开发者,你是否会关心 JVM code 或者 glibc 是否存在问题,也许会,但是不可否认,这是非常少见的场景,更多关心的还是 Java code 这一层的问题,因此 JVM Profiling 的 cpu profiling 表达的是 on-cpu profiling for java code。同理对于内存申请速率 alloc profiling:system alloc profiling 关心的是用户态内存分配器(malloc 分配器或者其他的)的分配速度;JVM alloc profiling 关心的则是 TLAB 分配器的分配速度;JVM Profiling 和 System profiling 关注点是有不同的:JVM Profiling 关注的是 JVM 上的性能,而不是贯穿从用户态到内核态的整个流程,这是非常重要的一个区别,其他高级语言也是类似的情况。JVM Profiling Tools JAVA 社区有非常丰富的 JVM Profiling Tools:Async-profiler[4]:jetbrains IntelliJ IDEA[5]alibaba ArthasJProfilerHonest profiler[6]Uber JVM Profiler[7]Fight Recorder[8]JEP 349: JFR Event Streaming[9]1. JFRJFR (Java Flight Recorder)是深度嵌入在 JVM 中的功能强大的应用问题诊断与性能剖析工具,在其低开销的加持下,JFR 可在生产环境持续开启。JFR 最开始是 JRockit 和 Oracle JDK 中的商业化特性,Oracle 在 Java 11 对其进行了开源。2019 年阿里巴巴作为主要贡献者,联合 Azul、Datadog、RedHat 等公司,一起将 JFR 移植进 OpenJDK 8 中。目前 Alibaba Dragonwell 8 和 11 中也包含完整的 JFR 功能。JFR 的事件包括下面几类信息:一般信息:关于虚拟机、操作系统和记录的一般信息;内存:关于内存管理和垃圾收集的信息;代码:关于方法、异常错误、编译和类加载的信息;线程:关于应用程序和线程和锁的信息;I/O:关于文件和套接字输入、输出的信息;系统:关于正在运行 Java 虚拟机的系统、进程和环境变量的信息;类型:关于记录中的事件类型的信息。 通过 JFR 的 Event,可以覆盖几乎所有需要进行性能分析的场景:on cpu profilingalloc profilinglock profilingfile read(write) profilingsocket read(write) profiling...... JFR 非常优秀,但是在国内环境,依然存在适配问题:java 迭代速度太快了,java 已经发布了 17 了,但是国内不乏依旧跑在 java8 上的应用;而 JFR 从 11backport 到的最低版本是 8u272(8u262 只是有 JFR 的代码,但是不可用),这就导致了 8u272 之前的 java 没办法用 JFR;JFR 本身也在发展迭代中,如 jdk.ObjectAllocationInNewTLAB。jdk.ObjectAllocationOutsideTLAB 在 java16 之前的实现产生的 overhead 过高导致根本不适合在生产环境常态化采集;2. Async Profiler组合使用 Perf_events 和 AsyncGetCallTrace 解决 JVM SafePoint Bias 问题,解决了 overhead 高问题。主流的 java IDE IntelliJ IDEA 和 alibaba 的 Arthas 提供的 profiling 能力通过 Async-profiler 实现的。因此 Arms 的方案里面也借助了这个工具。Arms Continuous JVM Profiler为了更好的为用户提供价值,Arms 联合 Alibaba Dragonwell 团队,基于业界主流设计,进行了深度优化,设计出了全新的采集、分析技术方案。其中采集方案兼顾性能和财务成本,优先使用更成熟和完善的 JFR,但在JFR是商业化特性的 OracleJDK 或 Async-Profiler 性能更优的情况下,采用 Async-Profiler 作为替代方案,并且是全自动的,用户无需关注配置细节。Support listOpenJDK说明:jdk8u272 以下的版本选择 Async-Profilier 和核心原因是没有 JFR 可用;jdk8u272 之后直到 jdk16 之前,JFR 实现的 alloc 相关事件的开销比较大,因此选择 Async-Profilier;其他情况,能用 JFR 都用 JFR Oracle JDK说明:OracleJDK8 上 JFR 是商业特性,因此选择 Async-ProfilierOracleJDK11 之后的版本的 JFR 是开源特性,alloc 选择 Async-Profilier 的原因一样是因为 JFR 实现的 alloc 相关事件的开销比较大,因此选择 Async-Profilier其他情况,能用 JFR 都用 JFR。 性能分析类型目前 Arms 产品化部分包含 2 类 3 个性能分析类型,解决 java 开发者最常见的 CPU 和内存方面的问题:CPU Time:全称 On-CPU Profiling In Java Code,统计 java 代码占用 CPU 时间;Allocations:统计 TLAB 分配次数Allocated Memory:统计 TLAB 分配内存总量,单位 bytes;产品的 roadmap 中后续会考虑搞 lock,file,socket 等等性能分析的能力,这中间的主要核心考量是每一种实现对应的 overhead 评估和实现约束情况。OverHead前文说过评价一款 Profiling Tools 是否适合上生产主要是看额外开销是否足够小,Arms 提供的能力整体依赖于 Async-profiler 以及 JFR,这两个工具的开销是关键:Async-profiler:官方未给出数据性结论,只是说开销很低;JFR:按照缺省配置,整体性能下降低于 2%。[10] 因此 Async-profiler 和 Oracle 官方并没有更细节的数据,因此我们实际在进行一些测试,供参考:压力测试模型 压力测试模型如下图示:测试代码包含数据库查询、JSON 序列化、日志文件顺序写、网络收发等。压力测试客户端 使用 wrk 做并发测试,命令如下:wrk -t2 -d 10 -c 10http://172.22.230.30:8088/queryRandom客户端的压力的总体目标是把服务端的 CPU 压力控制在 50%左右。压力测试结果这里评估对应用的影响主要通过 QPS(吞吐)和 RT(时延)作为标准(系统 CPU 压力控制在 50%左右):JFR Alloc 依赖的两个 JFR Event 有非常严重的性能问题:1. jdk.ObjectAllocationInNewTLAB2. jdk.ObjectAllocationOutsideTLAB因此本测试不包含 JFR Alloc;JFR 的这个问题直到 JAVA15 以后才得到解决。我们还做了一组极限压测,将 CPU 全部打满,这种情况的出的结论为 QPS 和 RT 的开销低于 10%。这种极端情况也是存在,数据供参考。最佳实践路径CPU 高排查路径1. JVM 程序 CPU 高的传统方式我们聚焦 User time 高的情况,java 开发者的排查流程:1.定位 CPU 高的 java 进程的 pid,top;2.定位具体线程 id,top -p ${pid} -H;3.计算线程 ID 的 16 进制值,printf "%x\n" ${线程 ID};4.根据 stack trace,定位具体瓶颈点,jstack ${pid}| grep ${线程 ID} -A 10;5.查看 stack trace,识别代码,解决问题。2. 利用 Arms Continuous Java Profile 解决 JVM user 高的问题1. 确定是 JVM 业务进程导致 user CPU 升高;2. 找到 CPU 变高时间点,打开火焰图和人点方法统计,识别代码消耗,解决问题。直接定位到方法,并且把每个方法的耗时统计出来,如上图左边所示的热点方法。过滤掉线程等相关条件(当 CPU 瓶颈是因为用户代码导致的,开发者是不需要特别关心线程的,直接将所有线程中的 stack trace 全部进行统计汇总,然后按照每个方法的 Response time 进行汇总)。频繁 GC 第一步,开启压力程序,同时设定 heap 大小为 128M(-Xms128m-Xmx128m)第二步,压力程序的 gc 日志部分如下图,非常频繁的进行 gc 操作;85.013: [GC (Allocation Failure) [PSYoungGen: 29518K->3328K(36352K)] 47116K->21252K(123904K), 0.0065644 secs] [Times: user=0.02 sys=0.00, real=0.00 secs] 89.993: [GC (Allocation Failure) [PSYoungGen: 31736K->3328K(35840K)] 49660K->21260K(123392K), 0.0061679 secs] [Times: user=0.02 sys=0.00, real=0.00 secs] 94.062: [GC (Allocation Failure) [PSYoungGen: 31608K->3232K(36864K)] 49540K->21196K(124416K), 0.0070968 secs] [Times: user=0.02 sys=0.00, real=0.00 secs] 99.090: [GC (Allocation Failure) [PSYoungGen: 32934K->1344K(36864K)] 50898K->19332K(124416K), 0.0051987 secs] [Times: user=0.01 sys=0.00, real=0.01 secs] 103.114: [GC (Allocation Failure) [PSYoungGen: 29079K->2368K(37376K)] 47067K->20432K(124928K), 0.0056821 secs] [Times: user=0.01 sys=0.00, real=0.00 secs] 108.134: [GC (Allocation Failure) [PSYoungGen: 32528K->1344K(36864K)] 50592K->19464K(124416K), 0.0067361 secs] [Times: user=0.02 sys=0.00, real=0.00 secs] 113.086: [GC (Allocation Failure) [PSYoungGen: 31748K->3264K(37376K)] 49869K->21503K(124928K), 0.0059270 secs] [Times: user=0.02 sys=0.00, real=0.01 secs] 117.178: [GC (Allocation Failure) [PSYoungGen: 31709K->3328K(37376K)] 49948K->21591K(124928K), 0.0049904 secs] [Times: user=0.02 sys=0.01, real=0.01 secs] 121.192: [GC (Allocation Failure) [PSYoungGen: 32615K->3607K(37376K)] 50878K->21878K(124928K), 0.0076185 secs] [Times: user=0.01 sys=0.00, real=0.01 secs] 126.217: [GC (Allocation Failure) [PSYoungGen: 33278K->1312K(37376K)] 51549K->19615K(124928K), 0.0045188 secs] [Times: user=0.01 sys=0.00, real=0.00 secs] 131.159: [GC (Allocation Failure) [PSYoungGen: 32080K->3488K(37376K)] 50383K->21799K(124928K), 0.0046074 secs] [Times: user=0.01 sys=0.00, real=0.01 secs] 135.256: [GC (Allocation Failure) [PSYoungGen: 33274K->3488K(37376K)] 51585K->21807K(124928K), 0.0044789 secs] [Times: user=0.01 sys=0.00, real=0.00 secs] 140.276: [GC (Allocation Failure) [PSYoungGen: 33871K->1472K(37888K)] 52190K->19799K(125440K), 0.0043370 secs] [Times: user=0.01 sys=0.00, real=0.00 secs] 145.296: [GC (Allocation Failure) [PSYoungGen: 32925K->1472K(37888K)] 51252K->19799K(125440K), 0.0044817 secs] [Times: user=0.01 sys=0.01, real=0.00 secs] 150.321: [GC (Allocation Failure) [PSYoungGen: 32944K->1440K(37888K)] 51271K->19767K(125440K), 0.0041987 secs] [Times: user=0.01 sys=0.00, real=0.01 secs] 155.345: [GC (Allocation Failure) [PSYoungGen: 32896K->1472K(37888K)] 51223K->19799K(125440K), 0.0045417 secs] [Times: user=0.01 sys=0.00, real=0.00 secs] 160.374: [GC (Allocation Failure) [PSYoungGen: 33168K->1568K(37888K)] 51495K->19903K(125440K), 0.0051167 secs] [Times: user=0.01 sys=0.00, real=0.00 secs] 165.261: [GC (Allocation Failure) [PSYoungGen: 33469K->3616K(37888K)] 51804K->21959K(125440K), 0.0048307 secs] [Times: user=0.01 sys=0.01, real=0.01 secs] 170.286: [GC (Allocation Failure) [PSYoungGen: 35284K->3552K(37888K)] 53627K->21895K(125440K), 0.0143238 secs] [Times: user=0.03 sys=0.01, real=0.01 secs] 175.316: [GC (Allocation Failure) [PSYoungGen: 35008K->3584K(37888K)] 53351K->21927K(125440K), 0.0060600 secs] [Times: user=0.01 sys=0.00, real=0.00 secs] 180.338: [GC (Allocation Failure) [PSYoungGen: 35061K->3584K(37888K)] 53404K->21935K(125440K), 0.0044581 secs] [Times: user=0.01 sys=0.00, real=0.00 secs] 185.359: [GC (Allocation Failure) [PSYoungGen: 35044K->3584K(35840K)] 53395K->21935K(123392K), 0.0054453 secs] [Times: user=0.01 sys=0.00, real=0.01 secs] 190.384: [GC (Allocation Failure) [PSYoungGen: 35314K->3584K(37376K)] 53665K->21943K(124928K), 0.0050957 secs] [Times: user=0.01 sys=0.00, real=0.00 secs] 194.502: [GC (Allocation Failure) [PSYoungGen: 33085K->3584K(37376K)] 51444K->22007K(124928K), 0.0045832 secs] [Times: user=0.01 sys=0.00, real=0.01 secs] 199.526: [GC (Allocation Failure) [PSYoungGen: 33952K->1600K(37888K)] 52375K->20039K(125440K), 0.0051886 secs] [Times: user=0.01 sys=0.00, real=0.00 secs]第三步,利用 Allocated Memory 定位 collect-heap 内存是的主要申请是哪些方法:第四步,优化代码。Roadmap1. 诊断类型增强;(file io,socket io,lock 等等)2. 聚合能力增强;(merge 和 diff)3. 查询能力增强;(预处理能力,支持长时间聚合)4. 火焰图交互增强(StackFrame 表达更多含义,当前仅仅包含一个简单字符串);5. RPC tracing 和 profiling 联动;6. 多语言(其他高级语言适配);参考链接[1] Google 论文:https://storage.googleapis.com/pub-tools-public-publication-data/pdf/36575.pdf[2] golang内置pprof:https://go.dev/blog/pprof[3] java11内置JFR:https://docs.oracle.com/en/java/java-components/jdk-mission-control/8/user-guide/using-jdk-flight-recorder.html#GUID-D38849B6-61C7-4ED6-A395-EA4BC32A9FD6[4] Async-profiler:https://github.com/jvm-profiling-tools/async-profiler[5] jetbrains IntelliJ IDEA :https://www.jetbrains.com/help/idea/async-profiler.html[6] Honest profiler:https://github.com/jvm-profiling-tools/honest-profiler/[7] Uber JVM Profilerhttps://github.com/uber-common/jvm-profiler[8] Fight Recorderhttps://docs.oracle.com/en/java/java-components/jdk-mission-control/8/user-guide/using-jdk-flight-recorder.html#GUID-D38849B6-61C7-4ED6-A395-EA4BC32A9FD6[9] JEP 349: JFR Event Streaminghttps://openjdk.org/jeps/349[10] JFR Overheadhttps://docs.oracle.com/javase/8/docs/technotes/guides/troubleshoot/performissues001.html
作者:虚镜概述Continuous Profiling 在软件开发生命周期的位置CI/CD 的概念非本文重点,不解释了。从上图可以看出。Continuous Profiling(持续性能分析,下文简称为 CP)是生产向开发进行反馈的非常重要的手段。发展历史CP 概念的起源于 Google 的论文[1]:Google Wide Profiling:A continuous Profiling infrastucture for data centers基本思路CP 意义可以分解为两个:性能分析(Profile)的意义:识别计算,存储,网络上的性能瓶颈问题,建立代码和性能瓶颈的关联性,从而协助开发者优化代码,解决瓶颈问题; 持续(Continuous)的意义:让性能分析贯穿应用的整个生命周期,从而解决非持续方案(如 ]on-demand)中无法抓到现场的问题。 Profiling 的基本思想 衡量程序性能最直观的方法就是通过响应时间(Response Time,简称 RT)。但仅仅知道程序的运行时间很难指导我们如何把程序优化地更快,我们想要更进一步地了解这段时间之内到底发生了什么。让我们先从一个例子开始,了解 Linux 下的时间统计告诉了用户什么信息:下面我们利用 Linux time 计算两件事情的时间消耗:生成一个 10M 的文件,随机生成数据;(IO 密集)对上一步生成的文件做个 CRC 计算;(CPU 密集) time 的输出告诉用户 3 个信息:real:总消耗时间user:用户态消耗时间sys:内核态消耗时 观察 time 的输出,可以看出 user + sys 不等于 real,这是因为程序并不是总是 CPU 上运行的,还可能因为 IO,Lock 等等原因处于睡眠,等待的状态,这段时间既不算在 user CPU time 也不算在 system CPU time。程序在 CPU 上执行的时间(即 user CPU time + system CPU time)称为 CPU time(或 on-CPU time);程序处于睡眠等状态的时间称为 off-CPU time(or blocked time);程序实际运行的时间称为 wall clock time(挂钟时间); time 的输出 real 对应的概念的是 wall clock time,因此可以看到:对于 IO 密集型的 workload(负载),off-CPU time 是不能忽略的;对于 CPU 密集型 workload(负载),on-CPU time 基本和 wall clock time 相等; 对于一个给定的线程(Linux 上称为轻量级进程):wall clock time = CPU time + off CPU time因此 Profile 整体分为:On-CPU: where threads are spending time running on-CPU.Off-CPU: where time is spent waiting while blocked on I/O, locks, timers, paging/swapping, etc. 可以看到 Off-CPU 分析类型是一系统结果的汇总统计,因此也可以将 Off-CPU 因为引起睡眠或者等待的原因不同,可以进一步划分为 file profiling,socket profiling,lock profiling 等等类型。Continuous 的基本思想 持续(Continuous)相对的概念是按需(On-Demand)。按需(或者触发式)比较常见的问题就是无法精准的抓取现场从而导致一些偶发(难以复现)的问题无法被识别。比如上图这样一条曲线(不管它表达什么),反正是有一段异常(或者说和大部分情况不一样的情形),随着自然时间的流逝;用户发现这个异常的时候,曲线已经恢复了,因此无法在去回溯现场。这种情况下,我们发现了一段异常,但是没有更多细节,开发者就无法知道代码内部发生了什么,因此也无从谈起修复和改善代码了。持续则意味着贯穿整个程序的完整生命周期,不会漏掉任何一个历史上产生过的异常。Continuous+Profiling 带给开发者的意义是:在生产环节,永远知道代码的所有执行细节。理解 profiling用户交互和可视化 性能分析的展现形式通常以 Flame Graph 火焰图来表达:理解火焰图 对火焰图理解的本质是了解性能分析数据(profiling data)究竟是什么。性能分析数据(profiling data)就是堆栈统计数据。为了帮助读者理解,举个简单的例子:横坐标表达的一个数值,在不同的场景下,可以赋予不同的含义,比如:在 cpu profiling 上,表达花费时间多少;在 alloc profling 上,表达成内存大小;...... 纵坐标是表达是一个 stack trace。因此上图表达的含义和下面一组数据是一致的。每一行以空格分割,左边的是 stack trace,右边是数值。a();b();c() 1 a();b();d() 2 c();b() 3到这里,读者应该对性能分析(profiling)的工作原理有个感性的认识,性能分析的整体流程如图:因此实现 profiling 的关键点:获取堆栈数据(爬栈):如何护获取问题点(瓶颈)点的堆栈数据;生成火焰图; 常见的 Profiling Tools(生成堆栈数据) 常见的工具如 Linux perf,eBPF profile,DTrace,SystemTap 等等,本文将这类用于获取堆栈数据工具统称为 Profiling Tools;Linux 这类工具的用法本文不多介绍,这类工具非常通用并且有效,但对于非C系开发者是没那么友好的。高级语言绝大部分应用开发者其实并不关心很低层次的内容,比如 page fault,numa banlance,context switch,L3 Cache miss 等问题,通常都不在应用开发者的知识图谱中。这部分内容的优化也不再本文的目标读者范围,因此不多叙述。对于 Profile Tools,我们可以将其分为两类:System Profile:which shows system code paths (eg, JVM GC, syscalls, TCP), but not Java methods. language Profile:These show language methods(eg java method), but usually not system code paths.JVM Profilegolang Profile.... 不难理解,Profiling Tools 能够爬栈就是因为在特定的代码里进行的 Hook 操作,这类操作一定会产生额外的开销。因此 Profiling Tools 会带来额外的开销(Overhead),不同类型的 Profiling 的 Hook 点不同,因此不同的性能分析类型会导致不同的 Overhead。很长一段时间,无法将 Profiling 带入生产环节最重要的阻塞点就是 Overhead 太高导致应用的业务逻辑受损严重。因此评价 Profiling Tools 是否适合上生产最重要的评估就是估算 Overhead。JVM Profiling上文提到的工具基本属于 System Profiling Tools 提供的能力,这部分工具的核心能力关注的是 system code paths;对于高级语言上一些特性,能力是不够强的。下面我们了解高级语言自身的 Profiling Tools 是如何帮助开发者来做性能优化的。golang 内置 pprof[2]java11 内置 JFR[3]其他高级语言有的有自身的工具,有的没有高级语言没有自身工具,这类通常可以借助 System Profiling Tools(如 perf 或者 ebpf)来实现性能分析。 以 java 为例子,认识下 java 程序运行的代码结构 ,如下图:对于 java 开发者而言,大部分场景是不考虑 JVM code,glibc code,kernel code 出问题的可能性的,这部分代码相对稳定,而且有稳定的组织去推动解决。因此 JVM Profiling 要表达的核心其实是:爬堆栈,只爬 Java code 这一层次(java stack),这个是大部分应用开发者关注的核心部分,对于下面的部分(native stack)则不在 java 开发者关心的范围。JVM 还有一个特征,就是把 Linux 底层的概念屏蔽,替换成自己的概念体系,比如:java 开发者更关心 java 线程状态机而不是 JVM 进程的进程状态机;java 开发者更关心 java heap,stack,nio 等内存统计而不是 native heap,native stack 以及 rss,pagecache 的统计;java 开发者关心 CMS 或 G1 垃圾回收情况而不是 Page Reclaim;java 开发者更关心 synchronized,JUC 锁,而不是 OS 锁; 因此,JVM Profiling中的性能分析类型会更贴近 java 开发者的概念体系,而不是 system profile 关心的内容。举个例子,相较于 on-cpu profiling,作为 java 开发者,你是否会关心 JVM code 或者 glibc 是否存在问题,也许会,但是不可否认,这是非常少见的场景,更多关心的还是 Java code 这一层的问题,因此 JVM Profiling 的 cpu profiling 表达的是 on-cpu profiling for java code。同理对于内存申请速率 alloc profiling:system alloc profiling 关心的是用户态内存分配器(malloc 分配器或者其他的)的分配速度;JVM alloc profiling 关心的则是 TLAB 分配器的分配速度;JVM Profiling 和 System profiling 关注点是有不同的:JVM Profiling 关注的是 JVM 上的性能,而不是贯穿从用户态到内核态的整个流程,这是非常重要的一个区别,其他高级语言也是类似的情况。JVM Profiling Tools JAVA 社区有非常丰富的 JVM Profiling Tools:Async-profiler[4]:jetbrains IntelliJ IDEA[5]alibaba ArthasJProfilerHonest profiler[6]Uber JVM Profiler[7]Fight Recorder[8]JEP 349: JFR Event Streaming[9]1. JFRJFR (Java Flight Recorder)是深度嵌入在 JVM 中的功能强大的应用问题诊断与性能剖析工具,在其低开销的加持下,JFR 可在生产环境持续开启。JFR 最开始是 JRockit 和 Oracle JDK 中的商业化特性,Oracle 在 Java 11 对其进行了开源。2019 年阿里巴巴作为主要贡献者,联合 Azul、Datadog、RedHat 等公司,一起将 JFR 移植进 OpenJDK 8 中。目前 Alibaba Dragonwell 8 和 11 中也包含完整的 JFR 功能。JFR 的事件包括下面几类信息:一般信息:关于虚拟机、操作系统和记录的一般信息;内存:关于内存管理和垃圾收集的信息;代码:关于方法、异常错误、编译和类加载的信息;线程:关于应用程序和线程和锁的信息;I/O:关于文件和套接字输入、输出的信息;系统:关于正在运行 Java 虚拟机的系统、进程和环境变量的信息;类型:关于记录中的事件类型的信息。 通过 JFR 的 Event,可以覆盖几乎所有需要进行性能分析的场景:on cpu profilingalloc profilinglock profilingfile read(write) profilingsocket read(write) profiling...... JFR 非常优秀,但是在国内环境,依然存在适配问题:java 迭代速度太快了,java 已经发布了 17 了,但是国内不乏依旧跑在 java8 上的应用;而 JFR 从 11backport 到的最低版本是 8u272(8u262 只是有 JFR 的代码,但是不可用),这就导致了 8u272 之前的 java 没办法用 JFR;JFR 本身也在发展迭代中,如 jdk.ObjectAllocationInNewTLAB。jdk.ObjectAllocationOutsideTLAB 在 java16 之前的实现产生的 overhead 过高导致根本不适合在生产环境常态化采集;2. Async Profiler组合使用 Perf_events 和 AsyncGetCallTrace 解决 JVM SafePoint Bias 问题,解决了 overhead 高问题。主流的 java IDE IntelliJ IDEA 和 alibaba 的 Arthas 提供的 profiling 能力通过 Async-profiler 实现的。因此 Arms 的方案里面也借助了这个工具。Arms Continuous JVM Profiler为了更好的为用户提供价值,Arms 联合 Alibaba Dragonwell 团队,基于业界主流设计,进行了深度优化,设计出了全新的采集、分析技术方案。其中采集方案兼顾性能和财务成本,优先使用更成熟和完善的 JFR,但在JFR是商业化特性的 OracleJDK 或 Async-Profiler 性能更优的情况下,采用 Async-Profiler 作为替代方案,并且是全自动的,用户无需关注配置细节。Support listOpenJDK说明:jdk8u272 以下的版本选择 Async-Profilier 和核心原因是没有 JFR 可用;jdk8u272 之后直到 jdk16 之前,JFR 实现的 alloc 相关事件的开销比较大,因此选择 Async-Profilier;其他情况,能用 JFR 都用 JFR Oracle JDK说明:OracleJDK8 上 JFR 是商业特性,因此选择 Async-ProfilierOracleJDK11 之后的版本的 JFR 是开源特性,alloc 选择 Async-Profilier 的原因一样是因为 JFR 实现的 alloc 相关事件的开销比较大,因此选择 Async-Profilier其他情况,能用 JFR 都用 JFR。 性能分析类型目前 Arms 产品化部分包含 2 类 3 个性能分析类型,解决 java 开发者最常见的 CPU 和内存方面的问题:CPU Time:全称 On-CPU Profiling In Java Code,统计 java 代码占用 CPU 时间;Allocations:统计 TLAB 分配次数Allocated Memory:统计 TLAB 分配内存总量,单位 bytes;产品的 roadmap 中后续会考虑搞 lock,file,socket 等等性能分析的能力,这中间的主要核心考量是每一种实现对应的 overhead 评估和实现约束情况。OverHead前文说过评价一款 Profiling Tools 是否适合上生产主要是看额外开销是否足够小,Arms 提供的能力整体依赖于 Async-profiler 以及 JFR,这两个工具的开销是关键:Async-profiler:官方未给出数据性结论,只是说开销很低;JFR:按照缺省配置,整体性能下降低于 2%。[10] 因此 Async-profiler 和 Oracle 官方并没有更细节的数据,因此我们实际在进行一些测试,供参考:压力测试模型 压力测试模型如下图示:测试代码包含数据库查询、JSON 序列化、日志文件顺序写、网络收发等。压力测试客户端 使用 wrk 做并发测试,命令如下:wrk -t2 -d 10 -c 10http://172.22.230.30:8088/queryRandom客户端的压力的总体目标是把服务端的 CPU 压力控制在 50%左右。压力测试结果这里评估对应用的影响主要通过 QPS(吞吐)和 RT(时延)作为标准(系统 CPU 压力控制在 50%左右):JFR Alloc 依赖的两个 JFR Event 有非常严重的性能问题:1. jdk.ObjectAllocationInNewTLAB2. jdk.ObjectAllocationOutsideTLAB因此本测试不包含 JFR Alloc;JFR 的这个问题直到 JAVA15 以后才得到解决。我们还做了一组极限压测,将 CPU 全部打满,这种情况的出的结论为 QPS 和 RT 的开销低于 10%。这种极端情况也是存在,数据供参考。最佳实践路径CPU 高排查路径1. JVM 程序 CPU 高的传统方式我们聚焦 User time 高的情况,java 开发者的排查流程:1.定位 CPU 高的 java 进程的 pid,top;2.定位具体线程 id,top -p ${pid} -H;3.计算线程 ID 的 16 进制值,printf "%x\n" ${线程 ID};4.根据 stack trace,定位具体瓶颈点,jstack ${pid}| grep ${线程 ID} -A 10;5.查看 stack trace,识别代码,解决问题。2. 利用 Arms Continuous Java Profile 解决 JVM user 高的问题1. 确定是 JVM 业务进程导致 user CPU 升高;2. 找到 CPU 变高时间点,打开火焰图和人点方法统计,识别代码消耗,解决问题。直接定位到方法,并且把每个方法的耗时统计出来,如上图左边所示的热点方法。过滤掉线程等相关条件(当 CPU 瓶颈是因为用户代码导致的,开发者是不需要特别关心线程的,直接将所有线程中的 stack trace 全部进行统计汇总,然后按照每个方法的 Response time 进行汇总)。频繁 GC 第一步,开启压力程序,同时设定 heap 大小为 128M(-Xms128m-Xmx128m)第二步,压力程序的 gc 日志部分如下图,非常频繁的进行 gc 操作;85.013: [GC (Allocation Failure) [PSYoungGen: 29518K->3328K(36352K)] 47116K->21252K(123904K), 0.0065644 secs] [Times: user=0.02 sys=0.00, real=0.00 secs] 89.993: [GC (Allocation Failure) [PSYoungGen: 31736K->3328K(35840K)] 49660K->21260K(123392K), 0.0061679 secs] [Times: user=0.02 sys=0.00, real=0.00 secs] 94.062: [GC (Allocation Failure) [PSYoungGen: 31608K->3232K(36864K)] 49540K->21196K(124416K), 0.0070968 secs] [Times: user=0.02 sys=0.00, real=0.00 secs] 99.090: [GC (Allocation Failure) [PSYoungGen: 32934K->1344K(36864K)] 50898K->19332K(124416K), 0.0051987 secs] [Times: user=0.01 sys=0.00, real=0.01 secs] 103.114: [GC (Allocation Failure) [PSYoungGen: 29079K->2368K(37376K)] 47067K->20432K(124928K), 0.0056821 secs] [Times: user=0.01 sys=0.00, real=0.00 secs] 108.134: [GC (Allocation Failure) [PSYoungGen: 32528K->1344K(36864K)] 50592K->19464K(124416K), 0.0067361 secs] [Times: user=0.02 sys=0.00, real=0.00 secs] 113.086: [GC (Allocation Failure) [PSYoungGen: 31748K->3264K(37376K)] 49869K->21503K(124928K), 0.0059270 secs] [Times: user=0.02 sys=0.00, real=0.01 secs] 117.178: [GC (Allocation Failure) [PSYoungGen: 31709K->3328K(37376K)] 49948K->21591K(124928K), 0.0049904 secs] [Times: user=0.02 sys=0.01, real=0.01 secs] 121.192: [GC (Allocation Failure) [PSYoungGen: 32615K->3607K(37376K)] 50878K->21878K(124928K), 0.0076185 secs] [Times: user=0.01 sys=0.00, real=0.01 secs] 126.217: [GC (Allocation Failure) [PSYoungGen: 33278K->1312K(37376K)] 51549K->19615K(124928K), 0.0045188 secs] [Times: user=0.01 sys=0.00, real=0.00 secs] 131.159: [GC (Allocation Failure) [PSYoungGen: 32080K->3488K(37376K)] 50383K->21799K(124928K), 0.0046074 secs] [Times: user=0.01 sys=0.00, real=0.01 secs] 135.256: [GC (Allocation Failure) [PSYoungGen: 33274K->3488K(37376K)] 51585K->21807K(124928K), 0.0044789 secs] [Times: user=0.01 sys=0.00, real=0.00 secs] 140.276: [GC (Allocation Failure) [PSYoungGen: 33871K->1472K(37888K)] 52190K->19799K(125440K), 0.0043370 secs] [Times: user=0.01 sys=0.00, real=0.00 secs] 145.296: [GC (Allocation Failure) [PSYoungGen: 32925K->1472K(37888K)] 51252K->19799K(125440K), 0.0044817 secs] [Times: user=0.01 sys=0.01, real=0.00 secs] 150.321: [GC (Allocation Failure) [PSYoungGen: 32944K->1440K(37888K)] 51271K->19767K(125440K), 0.0041987 secs] [Times: user=0.01 sys=0.00, real=0.01 secs] 155.345: [GC (Allocation Failure) [PSYoungGen: 32896K->1472K(37888K)] 51223K->19799K(125440K), 0.0045417 secs] [Times: user=0.01 sys=0.00, real=0.00 secs] 160.374: [GC (Allocation Failure) [PSYoungGen: 33168K->1568K(37888K)] 51495K->19903K(125440K), 0.0051167 secs] [Times: user=0.01 sys=0.00, real=0.00 secs] 165.261: [GC (Allocation Failure) [PSYoungGen: 33469K->3616K(37888K)] 51804K->21959K(125440K), 0.0048307 secs] [Times: user=0.01 sys=0.01, real=0.01 secs] 170.286: [GC (Allocation Failure) [PSYoungGen: 35284K->3552K(37888K)] 53627K->21895K(125440K), 0.0143238 secs] [Times: user=0.03 sys=0.01, real=0.01 secs] 175.316: [GC (Allocation Failure) [PSYoungGen: 35008K->3584K(37888K)] 53351K->21927K(125440K), 0.0060600 secs] [Times: user=0.01 sys=0.00, real=0.00 secs] 180.338: [GC (Allocation Failure) [PSYoungGen: 35061K->3584K(37888K)] 53404K->21935K(125440K), 0.0044581 secs] [Times: user=0.01 sys=0.00, real=0.00 secs] 185.359: [GC (Allocation Failure) [PSYoungGen: 35044K->3584K(35840K)] 53395K->21935K(123392K), 0.0054453 secs] [Times: user=0.01 sys=0.00, real=0.01 secs] 190.384: [GC (Allocation Failure) [PSYoungGen: 35314K->3584K(37376K)] 53665K->21943K(124928K), 0.0050957 secs] [Times: user=0.01 sys=0.00, real=0.00 secs] 194.502: [GC (Allocation Failure) [PSYoungGen: 33085K->3584K(37376K)] 51444K->22007K(124928K), 0.0045832 secs] [Times: user=0.01 sys=0.00, real=0.01 secs] 199.526: [GC (Allocation Failure) [PSYoungGen: 33952K->1600K(37888K)] 52375K->20039K(125440K), 0.0051886 secs] [Times: user=0.01 sys=0.00, real=0.00 secs]第三步,利用 Allocated Memory 定位 collect-heap 内存是的主要申请是哪些方法:第四步,优化代码。Roadmap1. 诊断类型增强;(file io,socket io,lock 等等)2. 聚合能力增强;(merge 和 diff)3. 查询能力增强;(预处理能力,支持长时间聚合)4. 火焰图交互增强(StackFrame 表达更多含义,当前仅仅包含一个简单字符串);5. RPC tracing 和 profiling 联动;6. 多语言(其他高级语言适配);参考链接[1] Google 论文:https://storage.googleapis.com/pub-tools-public-publication-data/pdf/36575.pdf[2] golang内置pprof:https://go.dev/blog/pprof[3] java11内置JFR:https://docs.oracle.com/en/java/java-components/jdk-mission-control/8/user-guide/using-jdk-flight-recorder.html#GUID-D38849B6-61C7-4ED6-A395-EA4BC32A9FD6[4] Async-profiler:https://github.com/jvm-profiling-tools/async-profiler[5] jetbrains IntelliJ IDEA :https://www.jetbrains.com/help/idea/async-profiler.html[6] Honest profiler:https://github.com/jvm-profiling-tools/honest-profiler/[7] Uber JVM Profilerhttps://github.com/uber-common/jvm-profiler[8] Fight Recorderhttps://docs.oracle.com/en/java/java-components/jdk-mission-control/8/user-guide/using-jdk-flight-recorder.html#GUID-D38849B6-61C7-4ED6-A395-EA4BC32A9FD6[9] JEP 349: JFR Event Streaminghttps://openjdk.org/jeps/349[10] JFR Overheadhttps://docs.oracle.com/javase/8/docs/technotes/guides/troubleshoot/performissues001.html
作者:姜洪烨KubeVela 插件(addon)可以方便地扩展 KubeVela 的能力。正如我们所知,KubeVela 是一个微内核高度可扩展的平台,用户可以通过模块定义(Definition)[1]扩展 KubeVela 的系统能力,而 KubeVela 插件正是方便将这些自定义扩展及其依赖打包并分发的核心功能。不仅如此,KubeVela 社区的插件中心也在逐渐壮大,如今已经有超过 50 款插件,涵盖可观测性、微服务、FinOps、云资源、安全等大量场景功能。本文将会全方位介绍 KubeVela 插件的核心机制,教你如何编写一个自定义插件。在最后,我们将展示最终用户使用插件的体验,以及插件将如何融入到 KubeVela 平台,为用户提供一致的体验。为什么要使用 KubeVela 插件用户使用插件的一个典型方法是通过 KubeVela 团队维护的插件中心(addon catalog)[2] ,它包含了 KubeVela 团队与社区开发者精心编写的系统扩展功能,并以插件的形式发布于插件中心,这样你可以一键下载并安装这些插件。例如安装 FluxCD 可以快速给你的 KubeVela Application 提供部署 Helm Chart 的能力。相较于使用 KubeVela 的插件功能,如果你自己的内部平台想要集成一个云原生的功能,你大概会这么做:通过 Helm Chart 或者下载 yaml 文件手动安装 FluxCD 或类似的 CRD Operator。编写系统集成的代码,让用户界面可以通过统一的方式使用 FluxCD 等 CRD 的功能,在 KubeVela 系统中就是通过编写模块定义(OAM Definition)完成。 实际上,在 KubeVela 1.1 版本之前,我们也是通过类似的方式完成的。这会带来如下问题:操作繁琐:用户需要手动查阅文档如何安装 FluxCD 并处理可能发生的错误资源分散:用户需要下载不同的文件,既需要安装 Helm 安装 FluxCD 还需要下载模块定义等系统扩展的集成配置难以分发复用:用户需要手动下载模块定义就注定了这些资源难以以一个统一的方式分发给用户,也无法形成社区生态让不同的用户可以享受社区便利缺少多集群支持:KubeVela 将多集群交付作为一等公民,而这样的手动安装系统扩展的方式显然难以维护多集群的环境无版本管理:用户需要手动管理模块定义和 Controller 之间的版本 而 KubeVela 插件就是为了逐一解决这些问题而诞生的。KubeVela 插件是如何工作的KubeVela 的插件主要包含两部分:一部分是安装能力的提供者,通常是一个 CRD Operator/Controller。这个安装过程实质上就是运行一个 OAM 应用,addon 交付中所使用的功能与普通应用能力完全等价。另一部分就是扩展能力跟 KubeVela 体系的粘合层,也就是模块定义和其他的一些集成配置。OAM 模块定义为用户提供了插件扩展出的组件、运维特征以及工作流步骤等功能,也帮助 CRD Operator 提供用户友好的抽象,使得最终用户无需理解复杂的 CRD 参数,只需要根据最佳实践提供必要的参数。插件的工作机制如上图所示,KubeVela 的应用具备多集群交付的能力,所以也能帮助插件中的 CRD Operator 部署到这些集群中。模块定义文件仅需要在控制面被 KubeVela 使用,所以无需部署到被管控的集群中。提示一旦插件被安装,就会创建一个 KubeVela 应用,包含所有的相关资源和配置,这些配置都会设置 KubeVela 应用对外作为 OwnerReference(父节点)。当我们想要卸载一个插件时,只需要删除这个应用,Kubernetes 提供的资源回收机制会自动将标记了 OwnerReference 的资源一并删除。例如一个 Redis 插件,它能让用户在自己的应用中使用 Redis 集群类型的组件(Component),这样可以快速创建 Redis 集群。那么这个插件至少会包括一个 Redis Operator 来提供创建 Redis 集群的能力(通过 Application 描述),还有一个组件的模块定义 (ComponentDefinition) 来提供 Redis 集群的组件类型。所有整个插件的安装过程会将 Redis Operator 放在一个 KubeVela 应用中下发到多集群,而组件定义和 UI 扩展等配置文件则只部署到控制面集群并设置应用对象为 OwnerReference。创建自己的插件提示为保证以下内容功能全部可用,请确保你的 KubeVela 版本 为 v1.5+。我们将以 Redis 插件为例,讲解如何从头创建一个 KubeVela 插件的实际过程。本次完整的 Redis 插件代码见文末参考[3]。提示在这里我们会尽可能全面的介绍制作插件中涉及的核心知识,但是作为一个介绍性博客,我们会尽量避免讨论过深的细节以免篇幅过于膨胀,了解完整的功能及细节可以参考自定义插件文档[4]。首先我们需要思考我们要创建的插件有什么作用?例如我们假设 Redis 插件可以提供 redis-failover 类型的 Component,这样用户只需在 Application 中定义一个redis-failover Component 即可快速创建 Redis 集群。然后考虑如何达到这个目的?要提供 redis-failover 类型的 Component 我们需要定义一个 ComponentDefinition ;要提供创建 Redis 集群的能力支持,我们可以使用 Redis Operator[5]。那至此我们的大目标就明确了:编写插件的应用描述文件(OAM Application),这将会用于安装 Redis Operator (完整代码可以到插件中心的 template.cue[6]及resources/目录[7]查看。)编写 redis-failover 类型的 ComponentDefinition[8](完整代码请查看 definitions/目录[9]) 不过在开始编写之前,我们首先需要了解一个 KubeVela 插件的目录结构。后续我们会在编写的过程中详细说明每个文件的作用,在这里只需大致了解有哪些文件即可。提示命令行工具 vela addon init 可以帮助你创建目录结构的初始化脚手架。redis-operator/ ├── definitions │ └── redis-failover.cue ├── resources │ ├── crd.yaml │ ├── redis-operator.cue │ └── topology.cue ├── metadata.yaml ├── parameter.cue ├── README.md └── template.cue让我们逐一来解释它们:1. redis-operator/ 是目录名,同时也是插件名称,请保持一致。2. definitions/ 用于存放模块定义, 例如 TraitDefinition 和 ComponentDefinition。3. redis-failover.cue 定义我们编写的 redis-failover 组件类型,包含了用户如何使用这个组件的参数以及这个组件与底层资源交互的细节。4. resources/ 用于存放资源文件, 之后会在 template.cue 中使用他们共同组成一个 KubeVela 应用来部署插件。5. crd.yaml 是 Redis Operator 的 Kubernetes 自定义资源定义,在 resources/ 文件夹中的 YAML 文件会被直接部署到集群中。6. redis-operator.cue 一个 web-service 类型的 Component ,用于安装 Redis Operator。7. topology.cue 是可选的,帮助 KubeVela 建立应用所纳管资源的拓扑关系。8. metadata.yaml 是插件的元数据,包含插件名称、版本、维护人等,为插件中心提供了概览信息。9. parameter.cue 插件参数定义,用户可以利用这些参数在插件安装时做轻量级自定义。10. README.md 提供给最终用户阅读,包含插件使用指南等。11. template.cue 定义插件最终部署时的完整应用形态,包含一个 OAM 应用模板以及对其他资源对象的引用。提示在插件中制作中我们会广泛使用 CUE 语言来编排配置,如果对 CUE 不熟悉,可以花 10 分钟快速查阅入门指南有一个基本了解。parameter.cueparameter: { //+usage=Redis Operator image. image: *"quay.io/spotahome/redis-operator:v1.1.0" | string // 其余省略 }在 parameter.cue 中定义的参数都是用户可以自定义的(类似于 Helm Values),后续在 template.cue 或者 resources 中可以通过 parameter.<parameter-name> 访问参数。在我们的例子中,用户可以自定义 image ,这样后续我们创建 Redis Operator (redis-operator.cue) 的时候可以通过 parameter.image 使用用户指定的容器镜像。参数不仅可以给用户预留安装时的自定义输入,还可以作为安装时的条件进行部分安装。比如fluxcd 插件有一个参数叫 onlyHelmComponents[10],它的作用就是可以帮助用户只部署用于安装 Helm Chart 的组件能力,而其他控制器就可以不安装。如果你对于实现细节感兴趣,可以参考fluxcd 插件的部分配置[11]。在设计提供什么参数供用户自定义插件安装时,我们也应该遵循一下这些最佳实践来为用户提供更好的使用体验。最佳实践不要在 parameter.cue 中提供大量的细节参数,将大量细节抽象出少量参数供用户调节是一个更好的做法为参数提供默认值(如样例中的 image 参数)或将参数标记为可选(如样例的 clusters 参数),确保用户仅使用默认值可以得到一个可用的配置为参数提供使用说明(通过注释标记实现,见样例)尽量保持插件不同版本间的参数一致,防止因为升级导致不兼容template.cue 和 resources/ 目录这是存放我们应用描述文件的地方,即一个 OAM Application 。这描述了实际的插件安装过程。我们主要会在这里包含 Redis Operator ,给集群提供管理 Redis 集群的能力。template.cue 和 resources/ 目录本质上是相同的,都是构成 KubeVela 应用的组成部分,且都是在同一个 package 下的 CUE 文件。那为什么需要 resources 目录呢?除去历史原因,这主要是为了可读性的考虑,在 Application 中包含大量资源的时候 template.cue 可能变得很长,这时我们可以把资源放置在 resource 中增加可读性。一般来说,我们将 Application 的框架放在 template.cue 中,将 Application 内部的 Components、Traits 等信息放在 resource 目录中。template.cue template.cue 定义了应用的框架,绝大多数内容都是固定写法,具体的作用可以参考代码块中的注释。// template.cue 应用描述文件 // package 名称需要与 resources 目录中 cue 的 package 一致,方便引用 resources 目录中的内容 package main // Application 模板中多数字段均为固定写法,你需要注意的只有 spec.components output: { // 这是一个经典的 OAM Application apiVersion: "core.oam.dev/v1beta1" kind: "Application" // 不需要 metadata spec: { components: [ // 创建 Redis Operator redisOperator // 定义于 resources/redis-operator.cue 中 ] policies: [ // 这里会指定安装插件的 namespace ,是否安装至子集群等 // 多为固定写法,无需记忆,可查阅本次样例的完整代码 // https://github.com/kubevela/catalog/blob/master/experimental/addons/redis-operator/template.cue // 文档可参照 https://kubevela.net/zh/docs/end-user/policies/references ] } } // 定义资源关联规则,用于将资源粘合在一起。后续会着重介绍 // Documentation: https://kubevela.net/zh/docs/reference/topology-rule outputs: topology: resourceTopology // 定义于 resources/topology.cue 中在插件安装时,系统主要关注两个关键字:一是 output 字段,定义了插件对应的应用,在应用内部 spec.components 定义了部署的组件,在我们的例子中引用了存放在 resources/ 目录中的 redisOperator 组件。output 中的 Application 对象不是严格的 Kubernetes 对象,其中 metadata 里的内容(主要是插件名称)会被插件安装的过程自动注入。 另一个是 outputs 字段,定义了除了常规应用之外的配置,任何你想要跟插件一同部署的额外 Kubernetes 对象都可以定义在这里。请注意 outputs 中的这些对象必须遵循 Kubernetes API。 resources/ 资源文件 我们这里使用一个webservice类型的 Component 来安装 Redis Operator。当然,如果你可以接受依赖 FluxCD 的话,你也可以使用 helm 类型的 Component 直接安装一个 Helm Chart(因为 helm 类型的 Component 主要由 FluxCD 插件提供)。不过编写 addon 的一个原则是尽量减少外部依赖,所以我们这里使用 KubeVela 内置的 webservice 类型,而不是 helm。// resources/redis-operator.cue // package 名称与 template.cue 一致,方便在 template.cue 中引用以下的 redisOperator package main redisOperator: { // 这是 OAM Application 中的 Component ,它将会创建一个 Redis Operator // https://kubevela.net/zh/docs/end-user/components/references name: "redis-operator" type: "webservice" properties: { // Redis Operator 镜像名称,parameter.image 即在 parameter.cue 中用户可自定义的参数 image: parameter.image imagePullPolicy: "IfNotPresent" } traits: [ // 略 ] }你可以阅读代码块中的注释了解字段的具体作用。KubeVela 提供的资源粘合能力 值得注意的一个功能是资源关联规则 (Resource Topology)[12]。虽然它不是必须的,但是它能帮助 KubeVela 建立应用所纳管资源的拓扑关系。这就是 KubeVela 如何将各种各样的资源粘合成 Application 的。这在我们使用 Kubernetes 自定义资源(CR)的时候特别有用。// resources/topology.cue package main import "encoding/json" resourceTopology: { apiVersion: "v1" kind: "ConfigMap" metadata: { name: "redis-operator-topology" namespace: "vela-system" labels: { "rules.oam.dev/resources": "true" "rules.oam.dev/resource-format": "json" } } data: rules: json.Marshal([{ parentResourceType: { group: "databases.spotahome.com" kind: "RedisFailover" } // RedisFailover CR 会创建以下三类资源 childrenResourceType: [ { apiVersion: "apps/v1" kind: "StatefulSet" }, // KubeVela 内置 Deployment 等资源的拓扑,因此无需继续向下编写 { apiVersion: "apps/v1" kind: "Deployment" }, { apiVersion: "v1" kind: "Service" }, ] }]) }在本例中,redis-failover 类型的 Component 会创建一个 CR ,名为 RedisFailover 。但是在没有资源关联规则的情况下,假设在你的 Application 中使用了 RedisFailover ,虽然我们知道 RedisFailover 管控了数个 Redis Deployment ,但是 KubeVela 并不知道 RedisFailover 之下有 Deployment 。这时我们可以通过 资源关联规则 将我们对于 RedisFailover 的了解告诉 KubeVela,这样 KubeVela 可以帮助我们建立起整个应用下面纳管资源的拓扑层级关系。此时你将获得 KubeVela 提供的许多有用功能,效果见运行插件[13]。提示资源的拓扑关联功能给我们带来了许多有用的功能,最重要的是为 KubeVela 最终用户使用扩展能力提供了统一体验:VelaUX 资源拓扑视图,从应用到底层资源 Pod 的关联关系一应俱全,包括多集群统一的 vela exec 命令可以在不同应用组件类型关联的底层容器中执行命令,包括多集群统一的 vela port-forward 转发不同类型应用组件关联的底层容器端口,包括多集群统一的 vela log 查看不同类型应用组件关联的底层容器日志,包括多集群统一的 vela status --pod/--endpoint 查看不同类型应用组件关联的底层容器日志,获得可供访问的地址等,包括多集群definitions/ 目录Definitions 目录存放 KubeVela 模块定义(Definition)[14],包括组件定义(ComponentDefinition)、策略定义(TraitDefinition)等。这是插件中最重要的部分,因为它包含了最终用户安装这个插件以后可以获得哪些功能。有了这里定义的组件、运维特征、工作流等类型,最终用户就可以在应用中使用他们了。在插件中编写模块定义跟常规的编写流程一致,这是一个很大的话题,在这里我们就不详细展开了。你可以通过阅读模块定义对应的文档了解其中的细节:自定义组件 Component Definition[15]自定义运维特征 Trait Definition[16]自定义策略 Policy Definition[17]自定义工作流步骤 Workflow Step Definition。[18] 在本例中,我们编写 Redis 组件类型主要参照自定义组件[19]与 Redis Operator 使用文档[20],我们将组件类型命名为 redis-failover,它会创建一个 RedisFailover 的 CR ,这样刚刚添加的 Redis Operator 就可以帮助创建 Redis 集群,见文末完整代码[21]。metadata.yaml这里包含了插件的元数据,即插件的名称、版本、系统要求等,可以参考文末文档[22]。需要注意的是,本次介绍的为 KubeVela v1.5 之后的新写法,因此需要避免使用某些不兼容的元数据字段,以下样例中包含了所有的可用元数据。提示例如传统的 deployTo.runtimeCluster (安装至子集群)等元数据在新写法中已有代替(使用 topology Policy),应当使用新写法。可见完整代码中的 template.cue[23]# 插件名称,与目录名一致 name: redis-operator # 插件描述 description: Redis Operator creates/configures/manages high availability redis with sentinel automatic failover atop Kubernetes. # 展示用标签 tags: - redis # 插件版本 version: 0.0.1 # 展示用图标 icon: https://xxx.com # 插件所包含项目的官网地址 url: https://github.com/spotahome/redis-operator # 可能依赖的其他插件,例如 fluxcd dependencies: [] # 系统版本要求 system: vela: ">=v1.5.0" kubernetes: ">=1.19"运行插件至此我们已经将插件的主要部分编写完成,下载文末完整代码[24]补全部分细节后,即可尝试运行。下载得到 redis-operator 目录后,我们可以通过 vela addon enable redis-operator 安装本地的 redis-operator 插件,这种本地安装插件的方式也可以方便你再制作时做一些调试。安装完成后就可以参考插件的 README[25]试用我们的 Redis 插件了!提示这里也体现出插件的 README 的重要性,其中需要包括插件的作用、详细使用指南等,确保用户可以快速上手。在用户使用你编写的插件时,只需如下 4 行 yaml 即可在 Application 中创建包含 3 个 Node 的高可用 Redis 集群!相比于手动安装 Redis Operator 并创建 CR ,甚至逐一手动配置 Redis 集群,插件的方式极大地方便了用户。apiVersion: core.oam.dev/v1beta1 kind: Application metadata: name: redis-operator-sample spec: components: # This component is provided by redis-operator addon. # In this example, 2 redis instance and 2 sentinel instance # will be created. - type: redis-failover name: ha-redis properties: # You can increase/decrease this later to add/remove instances. replicas: 3只需 apply 仅仅数行的 yaml 文件,我们就轻松创建了如下图所示的整个复杂的资源。并且由于我们编写了资源关联规则 (Resource Topology) ,用户可以通过 VelaUX 轻松获得刚刚创建的 Redis 集群的资源拓扑状态,了解 Application 底层资源的运行状况,不再受限于 Application Component 级别的可观测性。如图我们能直接观测到整个 Application 的拓扑,直至每个 Redis Pod ,可见图中部分 Pod 仍在准备中:在执行 vela exec/log/port-forward 等命令时也可以精确地看到 Application 底层包含的资源(即支撑 Redis 集群的 3 个 Redis Pod 和 3 个 Sentinel Pod)。如果你在使用单集群,乍一看你可能不会觉得 exec 进一个 Pod 是很特殊的功能。但是一旦考虑到多集群,能够在横跨多个集群的资源中跟单集群一样以统一的方式进行选择查看能够极大的节省时间。使用 vela status 命令能获取这个 Application 的运行状态,有了资源关联规则后可以更进一步,直接通过 vela 寻找出 Redis Sentinel 的 Endpoint 来访问 Redis 集群:结语通过本文,相信你已经了解插件的作用及制作插件的要点。通过插件体系,我们将获得如下优势:将平台的能力打包成一个易于安装、便于分发复用、且可以形成社区生态的插件市场。充分复用 CUE 和 KubeVela 应用通过的强大能力,将基础设施资源灵活定义并进行多集群分发。无论扩展的资源类型是什么,均可以接入应用体系,为最终用户提供一致的体验。最后,如果你成功制作了属于自己的插件,KubeVela 社区非常欢迎开发者贡献插件至插件中心[26],这样你的插件还能够被其他 KubeVela 社区用户发现并使用!您可以通过如下材料了解更多关于 KubeVela 以及 OAM 项目的细节:项目代码库:github.com/oam-dev/kubevela 欢迎 Star/Watch/Fork!项目官方主页与文档:kubevela.io ,从 1.1 版本开始,已提供中文、英文文档,更多语言文档欢迎开发者进行翻译。项目钉钉群:23310022;Slack:CNCF #kubevela Channel加入微信群:请先添加以下 maintainer 微信号,表明进入KubeVela用户群: 戳此处:查看 KubeVela 项目官网!!相关链接[1] 模块定义(Definition)https://kubevela.net/zh/docs/platform-engineers/oam/x-definition[2] 插件中心(addon catalog)https://github.com/kubevela/catalog[3] catalog/redis-operatorhttps://github.com/kubevela/catalog/tree/master/experimental/addons/redis-operator[4] 自定义插件文档https://kubevela.net/zh/docs/platform-engineers/addon/intro[5] Redis Operatorhttps://github.com/spotahome/redis-operator[6] template.cuehttps://github.com/kubevela/catalog/blob/master/experimental/addons/redis-operator/template.cue[7] resources/https://github.com/kubevela/catalog/tree/master/experimental/addons/redis-operator/resources[8] ComponentDefinition https://kubevela.net/zh/docs/platform-engineers/components/custom-component[9] definitions/目录https://github.com/kubevela/catalog/tree/master/experimental/addons/redis-operator/definitions[10] onlyHelmComponentshttps://github.com/kubevela/catalog/blob/master/addons/fluxcd/parameter.cue[11] fluxcd 插件部分配置https://github.com/kubevela/catalog/blob/master/addons/fluxcd/template.cue#L25[12] 资源关联规则 (Resource Topology) https://kubevela.net/zh/docs/reference/topology-rule[13] 运行插件https://kubevela.io/zh/blog/2022/10/18/building-addon-introduction#%E8%BF%90%E8%A1%8C%E6%8F%92%E4%BB%B6[14] 模块定义(Definition)https://kubevela.io/docs/getting-started/definition[15] 自定义组件 Component Definitionhttps://kubevela.io/docs/platform-engineers/components/custom-component[16] 自定义运维特征 Trait Definitionhttps://kubevela.io/docs/platform-engineers/traits/customize-trait[17] 自定义策略 Policy Definitionhttps://kubevela.io/docs/platform-engineers/policy/custom-policy[18] 自定义工作流步骤 Workflow Step Definitionhttps://kubevela.io/docs/platform-engineers/workflow/workflow[19] 自定义组件https://kubevela.net/zh/docs/platform-engineers/components/custom-component[20] Redis Operator 使用文档 https://github.com/spotahome/redis-operator/blob/master/README.md[21] 完整代码https://github.com/kubevela/catalog/blob/master/experimental/addons/redis-operator/definitions/redis-failover.cue[22] 文档https://kubevela.net/zh/docs/platform-engineers/addon/intro#%E6%8F%92%E4%BB%B6%E7%9A%84%E5%9F%BA%E6%9C%AC%E4%BF%A1%E6%81%AF%E6%96%87%E4%BB%B6[23] template.cuehttps://github.com/kubevela/catalog/blob/958a770a9adb3268e56ca4ec2ce99d2763617b15/experimental/addons/redis-operator/template.cue#L28[24] 完整代码https://github.com/kubevela/catalog/tree/master/experimental/addons/redis-operator[25] READMEhttps://github.com/kubevela/catalog/tree/master/experimental/addons/redis-operator/README.md[26] 插件中心https://github.com/kubevela/catalog11 月 5 日杭州云栖小镇-云原生峰会阿里云将联手识货、传音、禾连健康、新东方、心动网络、小红书等实战企业技术负责人向你发出邀请扫码即刻参会!
近日,由阿里云撰写的关于 KOLE 创新论文被 ACM SoCC 国际会议长文录用。ACM Symposium on Cloud Computing(以下简称 SoCC)是由美国计算机协会主办、聚焦云计算技术的一项学术会议,是云计算的首要会议。它汇集了对云计算感兴趣的研究人员、开发人员、用户和实践者,是唯一由 SIGMOD(数据管理特别兴趣组)和 SIGOPS(操作系统特别兴趣组)联合主办的会议, 这个会议在近些年蓬勃发展,旨在聚集数据库和计算机系统两大领域的学者,共同推进云计算技术在工业界的研究与发展。此次被录用的论文为《KOLE: Breaking the Scalability Barrier for Managing Far Edge Nodes in Cloud》。此论文灵感诞生于阿里云边缘容器产品 ACK@Edge ,ACK@Edge 是阿里云容器服务针对边缘计算场景推出的云边一体化协同托管方案,采用非侵入方式增强,提供边缘自治、边缘单元、边缘流量管理、原生运维 API 支持等能力,以原生方式支持边缘计算场景下的应用统一生命周期管理和统一资源调度,现阶段已经覆盖了 CDN、音视频直播、物联网、物流、工业大脑、城市大脑、地产、票务、新零售、能源、交通等实际业务场景,并服务于阿里云 LinkEdge、盒马、优酷、视频云、大麦、CDN 等多个业务或项目中。KOLE 全称:A framework built on top of Kubernetes to Orchestrate Limitless (far) Edge nodes。KOLE 针对 Kubernetes 在云边一体,大规模边缘节点管理方面的挑战,创新性的提出了基于 Kubernetes的新的云边架构,通过利用新的云边通信协议以及缓存快照的方式,使 Kubernetes 能够轻松管理数百万节点。为了突破 Kubernetes 管理大量边缘节点的可扩展性限制,KOLE 的设计遵循三个标准:避免创建大量对象来持久化边缘节点的状态;避免在节点与 APIServer 中保持大量的 HTTP 连接;使用 Kubernetes CRD 支持对边缘节点及其运行的应用程序进行所需的管理操作。 基于以上原则,KOLE 创新性的使用了 MQTT 协议作为云边通信机制,MQTT 被设计用于轻量级的发布/订阅式消息传输,旨在为低带宽和不稳定的网络环境中的物联网设备提供可靠的网络服务,是专门针对物联网开发的轻量级传输协议,并且适合百万级设备连接, MQTT 协议针对低带宽网络,低计算能力的设 备,做了特殊的优化,MQTT 的传输格式非常精小,最小的数据包只有 2 个比特,相对于 HTTP 协议具有更低的能耗。经过我们大量的实验测试评估,KOLE 可以支持多达 100 万个节点,而不会给 Kubernetes 的核心组件(如 Apiserver 和 etcd)带来显著的开销。我们能够使用 KOLE 在约 73 秒内将工作负载规范分发到 100 万个节点,在 5 分钟内处理 100 万个节点注册,并在约 20 秒内使用快照中的 100 万个节点重建云状态缓存。具体特点如下:更强的处理节点心跳的性能实验数据表明 KOLE 处理所有心跳的时间几乎随着节点数量的增加呈线性增加。处理一百万个注册心跳需要 ∼9.2 秒。更低的云端控制器组件的消耗对于 100 万个节点,KOLE 控制器和 MQTT Broker 的内存消耗分别为 10.6GB 和 57.3GB,CPU 使用率适中,KOLE 控制器消耗~1.4 个核心,MQTT Broker 消耗~2 个核心。更快的工作负载分发KOLE 通过 MQTT Topic 发送到单个节点时提供了线性可扩展性。将工作负载分别分发到一百万个节点需要 73 秒。线性来自 KOLE 控制器按顺序发布所有 MQTT Topic 的事实。更高效的云状态缓存快照由于 Kubernetes 对 CRD 的限制为 1MB 大小,因此 KOLE 将云状态缓存的序列化字节流设置为为 500MB,对于一百万个节点,这意味着需要 ∼500 个快照用于保存一张快照的 CR 实例。另外为了对数据进一步压缩,KOLE 对常见的压缩算法进行了测试,最终在 KOLE 中,我们选择 gzip 作为默认压缩算法,因为它提供了高压缩比和快速压缩时间,将快照 CR 的数量从 503 个减少到 33 个(减少 93%)。在极端情况下, 我们需要从快照中恢复最原始的数据,上图展示了从快照构建云状态缓存所需要时间,其中包括从 APIServer 加载所有快照 CR 的时间以及运行解压缩算法以恢复数据结构的时间。使用 gzip 算法构建具有 100 万个节点的缓存需要 ∼20 秒。为了突出 KOLE 中快速状态恢复的优势,我们通过列出来自 APIServer 的大量单个节点对象来检查 Kubernetes List API 的性能。结果如上图所示。正如预期的那样,从 APIServer 列出大量对象是低效的。列出一百万个节点对象需要 900 秒。很多 Kubernetes 控制器如 kube-scheduler,kube-controller-manager 需要在启动过程中列出所有节点, List API 性能是他们支持大量节点的瓶颈之一。更迅速的批量节点注册实验结果表明,在拥有 100 万个节点情况下,同时批量注册成功需要 260 秒左右。此次论文入选 ACM SoCC,是阿里云在云原生容器技术领域,拓展服务边界,实现云边协同的又一次创新。附论文信息录用论文题目:KOLE: Breaking the Scalability Barrier for Managing Far Edge Nodes in Cloud作者:张杰,晋晨,黄玉奇,易立,叔同,郭飞论文概述:在边缘计算领域,越来越多的趋势是利用容器化和 Kubernetes 等云原生技术和平台来管理边缘应用程序以提高运营效率。不幸的是,Kubernetes 中每个集群支持的节点数量只有几千个,这远远少于在典型边缘计算场景中所能管理的设备节点数量。在本文中,我们提出了 KOLE 方案,这是一个扩展上游 Kubernetes 以支持大量边缘节点的框架。它用 MQTT 消息系统代替了 Kubernetes 中现有的 Apiserver 与节点的通信机制。MQTT 代理完全卸载了为 Apiserver 中的节点保持大量 HTTP 连接的开销。在 KOLE 中,我们通过在云状态缓存中维护它们来避免在 Apiserver 中创建大量单独的对象。缓存会定期生成快照以进行灾难恢复。总体而言,KOLE 通过牺牲拥有单个对象的可管理性实现了出色的可扩展性。实验结果表明,KOLE 具有可扩展性,可支持百万级别的节点。点击此处,了解边缘容器服务 ACK@Edge 更多详情!
2023年01月