【JS】核桃编程:前端可观测性建设之路

核桃编程:前端可观测性建设之路

阿里云云栖号发布于 今天 02:19

根据《中国少儿编程行业研究报告》及《2017-2023 年中国少儿编程市场分析预测研究报告》预测得出,少儿编程有望在3-5年内,达到少儿英语市场规模的一半,即500亿左右,发展前景广阔。

在信息化时代的今天,人工智能给人们带来了巨大变化,新时代的家长处于互联网时代,与上一代的家长思维产生较大的变化,能够注重孩子的素质教育,注重培养孩子人工智能方向的才能。少儿编程教育就是在这样的背景下快速发展起来。

核桃编程是少儿编程教育行业的领导者,致力于以科技手段促进编程教育,通过人工智能、自适应学习等先进技术和科学的教育方法,启发中国孩子的学习能力。自2017年8月成立以来,核桃编程的业务量飞速发展,仅仅3年时间付费学员人数就突破了200万,并实现了单月营收过亿。

随着核桃编程业务的快速增长,核心应用的系统规模和系统复杂度也在经历翻天覆地的变化。核桃技术团队不断通过新兴的技术手段维护整套系统架构的技术先进性。在3年时间里,技术团队至少对整体系统架构进行了6次以上的重大重构,涉及微服务化、容器化、分布式数据库等重要的技术,并尝试通过Serverless技术提升系统的弹性伸缩能力。在疫情期间,当系统负荷呈现数倍突增的情况下,核桃编程的系统架构依然经受住了考验。

随着系统架构从简单变得复杂,有一个在互联网领域老大难的问题也逐步在核桃编程中体现出来:如何提升分布式系统的可观测性?在线上编程教学场景里面,用户一个简单的操作,就有可能涉及到前后端系统的多次交互,以及多个服务端微服务应用之间的相互调用,甚至还会受到第三方服务接口的影响。任何一个环节出现故障或者性能瓶颈,都会导致用户体验的断崖式下跌,而用户体验又是决定品牌形象的核心要素,所以对于核桃技术团队而言,保证优秀的用户体验需要在系统可观测性建设上做到这几个方面:

  1. 全面而且实时的了解系统每一个对外接口的性能质量。
  2. 通过数据掌握最终用户与系统交互时感受到的系统健康程度。
  3. 当系统健康程度存在问题时,技术团队能第一时间发现问题,并及时处理。
  4. 处理问题时,能迅速定位到系统瓶颈和故障源。

任何一个技术团队要想围绕着这几个方面,从零开始建设分布式可观测体系,都是一项非常艰巨的任务,好在业界对于分布式可观测性的建设,已经有了不少成熟的方法论以及开源项目可以参考。

业界广泛认可的可观测性(observability)包含三个核心要素:Logging(离散的日志信息)、Metrics(聚合的指标)、Distributed Tracing(分布式追踪)。围绕这三个核心要素,有不少开源项目可以进行选择,帮助开发者快速建设分布式可观测体系。

【JS】核桃编程:前端可观测性建设之路

通过引入Skywalking,Prometheus等开源技术,核桃技术团队建立了完整的分布式可观测体系,能够对服务端复杂的微服务应用实现全链路追踪,并通过统一的日志服务体系收集分析业务日志。这样的努力对于系统稳定性以及用户体验的提升是立竿见影的:当系统服务端的任何一个环节出现故障或性能瓶颈的时候,技术团队都能第一时间得到通知,并快速定位问题,进行针对性处理。

相对于成熟的服务端监控技术,整个业界在客户端监控领域的技术方案一直比较欠缺。在互联网上,海量的用户使用不同厂家、不同操作系统、不同屏幕分辨率的终端设备,分布在不同的地域,又通过不同的网络运营商进行接入,甚至存在复杂的第三方依赖,包括CDN、第三方统计脚本、页面嵌套等方面。当用户体验遇到问题的时候,如果仅仅拥有服务端监控手段,很难第一时间确认问题的根源到底在于前端还是后端。即便能够排除服务端的问题,前端用户体验也受到页面渲染、JavaScript执行、网络质量、第三方接口服务质量等方面的影响,为进一步排查问题留下了非常多的挑战。

一个简单的思路是通过前端JavaScript做自定义的埋点,将最终用户的各种行为实时上报给服务端进行统计,以第一时间了解到用户体验。这个思路本身是合理的,但业务埋点、数据采集、聚合分析、视图展现等层面都有非常多的工作需要做,是一个浩大的工程。绝大多数技术团队而言,投入如此多的精力来建设这样一套前端监控方案都是不现实的。

建设前端可观测体系,最好的捷径是参考互联网领域头部企业的案例,选择云计算厂商提供的完整方案。阿里巴巴多年实战积累了一套全集团统一的前端监控方案,并开放给各个事业部接入。对于以HTML页面形式呈现的前端应用,不管是PC端/移动端网站,嵌入到移动端App的HTML5页面,都可以通过无侵入的方式接入到这套前端监控方案中。

【JS】核桃编程:前端可观测性建设之路

这套监控方案也同时通过阿里云对外输出,成为阿里云可观测性整体方案的重要组成部分,服务于广大的外部用户。

在客户端监控领域,包括ARMS前端监控和APP监控两个产品,其中ARMS前端监控专注于Web端体验数据监控,从页面打开速度、页面稳定性和外部服务调用成功率这三个方面监测Web页面的健康度,帮助使用者降低页面加载时间、减少JS错误,有效提升用户体验。

【JS】核桃编程:前端可观测性建设之路

这套方案正好能补齐核桃编程在客户端监控领域的能力缺失,所以核桃技术团队尝试在一些业务线接入阿里云ARMS前端监控。很快,他们就感受到了这套方案对于提升用户体验所带来的价值。

ARMS前端监控方案之所以能被核桃编程采纳,有一个很重要的原因是方案的接入是非常简单的,唯一要做的事情是在客户端HTML页面的Body元素中加入一段由ARMS提供的统计接入脚本(一段JavaScript代码),就能完成监控数据的自动上报。这其中不涉及到任何跟业务层主动埋点的工作,在核桃编程的多条业务线之间推广起来是非常顺利的。基于之前的经验,凡是需要在业务层主动埋点的监控方案,都需要通过行政手段来保证多个研发团队在编写代码的时候遵守既定的规则,这样的方式从长期来看都是很难落地的。包括在服务端全链路监控方面,核桃编程也始终遵循业务无侵入的思路,避免主动埋点行为。

接下来,研发人员就能从前端监控控制台全面了解应用端到端的健康程度,包括PV/UV情况统计、页面加载速度情况、JavaScript执行情况,API请求成功率等多个方面。以页面加载速度为例,ARMS可以基于客户端自动上报的监控数据,实时展示每一个页面的加载情况。

【JS】核桃编程:前端可观测性建设之路

其中,首次渲染时间、首屏时间、Dom Ready等指标都是HTML页面独有的性能指标,遵循业务标准的指标定义。这些指标数据和前端页面健康程度息息相关,影响着最终用户每一次交互行为的实际体验。

【JS】核桃编程:前端可观测性建设之路

通过页面加载瀑布图,能够按照页面加载的顺序,直观地展示各阶段的耗时情况。这些指标参数涵盖了网络层面的性能指标,当网络层面出现性能瓶颈,比如应用系统的接入带宽不能支撑用户访问流量的时候,仅仅通过服务端的监控手段,是无法洞察到的,必须依赖于客户端的实时监控数据上报。通过ARMS前端监控,核桃编程能从页面生产时(服务器端状态)、页面加载时和页面运行时这三个方面,全面了解到每一个应用系统端到端的健康程度。

【JS】核桃编程:前端可观测性建设之路

特别重要的是,ARMS前端监控能够从地理位置、浏览器、操作系统、分辨率、网络运营商、应用版本等多个维护,对性能指标进行聚合分析,从而帮助核桃编程更好地定位性能瓶颈。比如地理分布视图就能通过对地理位置的聚合分析,展现全国每一个省的页面首次渲染平均时间。当某一个地域的CDN出现故障的时候,地理分布视图能帮助核桃编程迅速定位问题的根源,而传统的监控手段是完全没有办法覆盖这类场景的。

【JS】核桃编程:前端可观测性建设之路

JavaScript错误分析和API请求分析也是核桃编程在应用系统的日常维护中非常关心的页面健康度指标。前者可以展示JavaScript错误的基本信息和分布情况,并具备回溯用户行为的能力。后者可以展示每个API的调用情况,包括调用成功率、返回信息、调用成功或失败的平均耗时等。当前端页面完全载入后,用户的操作会涉及到复杂的JavaScript执行,并在页面触发多个API调用,其中还包括对第三方提供的接口调用。

ARMS能够从最终用户的角度,真实还原前端代码执行的完整现场,帮助核桃编程快速定位来自前端的故障源。和页面加载速度统计一样,JavaScript错误分析和API请求分析都能够通过地理位置、浏览器等多种维度进行聚合分析。在线上编程教育的业务场景里面,客户端的实现包含着大量业务逻辑以及云端之间的双向交互,有一些问题只有在特定的浏览器和页面分辨率下才有可能暴露出来,这类问题就特别依赖多维度聚合分析进行排查。

在熟练掌握ARMS提供的前端可观测性能力之后,核桃编程开始把前端页面健康度指标作为日常业务迭代的检测标准,这项工作是通过与所有业务线的灰度发布计划相互配合而进行的。对于生产环境的每一次版本升级,核桃编程都会通过灰度发布的方式实现,先将小规模的用户流量导入新版本进行功能性、稳定性、健康性验证,只有满足预先定义的各项指标后,才会逐步增加导入新版本的用户流量,否则会立即对版本进行回滚。前端健康度的各种指标都是非常重要的衡量维度,而这些指标仅仅通过版本发布前的常规测试手段,是没有办法全面采集到的。核桃编程将前端健康度纳入业务迭代的衡量标准,体现着业务迭代过程中的可灰度、可观测、可回滚,这也是在阿里巴巴广为推崇的安全生产三板斧原则。

【JS】核桃编程:前端可观测性建设之路

除了通过ARMS控制台主动的观察分析,掌握各项前端业务指标之外,更重要的事情是在遇到用户体验问题时,如何第一时间得到通知和告警,防患于未然。这个诉求通过ARMS完善的报警机制可以轻松实现。核桃基于自身对前端健康度的理解,以及业界通用的方法论,创建了多种维度的报警规则,比如“最近5钟内平均页面首次渲染耗时大于1秒”等。当规则被触发时,系统会以预先指定的报警方式向报警联系人分组发送报警信息,以提醒技术团队及时解决。这些报警规则再配合上对生产故障的分级分类定义,能够帮助核桃技术团队建立一整套生产故障应对机制,真正实现实线上问题5分钟内发现,10分钟内隔离,30分钟内解决。

【JS】核桃编程:前端可观测性建设之路

核桃编程还积极探索前后端统一链路追踪技术,将API请求从前端发出到后端调用的链路串联起来,真实还原代码执行的完整现场。这是通过对前端API请求自动注入Trace信息而实现,ARMS前端监控能够在允许API自动上报的前提下,在API请求的Request Header中加入自动生成的TraceID,作为串联前后端链路的标识。这样通过调用的时间轴,可以知道是网络传输还是后端调用导致请求耗时时间过长,进一步通过后端应用的线程剖析功能,可以洞察每次请求后端的完整调用链路,对于排查系统故障和性能瓶颈带来了非常大的帮助。

完善的前端可观测体系在帮助核桃编程减少了30%以上的运维工作量的同时,还缩短了60%以上的故障定位平均耗时,极大地提升了用户体验,为业务持续发展打下了坚实的基础。核桃技术团队将基于自身的技术特点,继续探索更多前沿的云原生技术,充分享受云计算带来的红利。

核桃编程正在招聘业务架构师、运维架构师,核桃编程通过优质的课程内容和首创的AI人机双师互动学习辅导系统,现已成为国内外领先的少儿编程教育公司,产品技术团队多来自于阿里巴巴、百度等顶尖互联网公司;课程研发团队全部出身双一流高校,同时还汇集了儿童心理及行为研究等领域的顶尖人才。

作者:山猎,阿里云解决方案架构师
原文链接
本文为阿里云原创内容,未经允许不得转载

chromejavascriptchrome-devtools

阅读 110发布于 今天 02:19

本作品系原创,采用《署名-非商业性使用-禁止演绎 4.0 国际》许可协议


阿里云栖号

汇集阿里技术精粹-yq.aliyun.com

avatar

阿里云云栖号

阿里云官网内容平台!汇聚阿里云优质内容(入门、文档、案例、最佳实践、直播等)!如需转载或内容类合作,邮件[email protected] 秒级回复!

23.5k 声望

10.7k 粉丝

0 条评论

得票时间

avatar

阿里云云栖号

阿里云官网内容平台!汇聚阿里云优质内容(入门、文档、案例、最佳实践、直播等)!如需转载或内容类合作,邮件[email protected] 秒级回复!

23.5k 声望

10.7k 粉丝

宣传栏

根据《中国少儿编程行业研究报告》及《2017-2023 年中国少儿编程市场分析预测研究报告》预测得出,少儿编程有望在3-5年内,达到少儿英语市场规模的一半,即500亿左右,发展前景广阔。

在信息化时代的今天,人工智能给人们带来了巨大变化,新时代的家长处于互联网时代,与上一代的家长思维产生较大的变化,能够注重孩子的素质教育,注重培养孩子人工智能方向的才能。少儿编程教育就是在这样的背景下快速发展起来。

核桃编程是少儿编程教育行业的领导者,致力于以科技手段促进编程教育,通过人工智能、自适应学习等先进技术和科学的教育方法,启发中国孩子的学习能力。自2017年8月成立以来,核桃编程的业务量飞速发展,仅仅3年时间付费学员人数就突破了200万,并实现了单月营收过亿。

随着核桃编程业务的快速增长,核心应用的系统规模和系统复杂度也在经历翻天覆地的变化。核桃技术团队不断通过新兴的技术手段维护整套系统架构的技术先进性。在3年时间里,技术团队至少对整体系统架构进行了6次以上的重大重构,涉及微服务化、容器化、分布式数据库等重要的技术,并尝试通过Serverless技术提升系统的弹性伸缩能力。在疫情期间,当系统负荷呈现数倍突增的情况下,核桃编程的系统架构依然经受住了考验。

随着系统架构从简单变得复杂,有一个在互联网领域老大难的问题也逐步在核桃编程中体现出来:如何提升分布式系统的可观测性?在线上编程教学场景里面,用户一个简单的操作,就有可能涉及到前后端系统的多次交互,以及多个服务端微服务应用之间的相互调用,甚至还会受到第三方服务接口的影响。任何一个环节出现故障或者性能瓶颈,都会导致用户体验的断崖式下跌,而用户体验又是决定品牌形象的核心要素,所以对于核桃技术团队而言,保证优秀的用户体验需要在系统可观测性建设上做到这几个方面:

  1. 全面而且实时的了解系统每一个对外接口的性能质量。
  2. 通过数据掌握最终用户与系统交互时感受到的系统健康程度。
  3. 当系统健康程度存在问题时,技术团队能第一时间发现问题,并及时处理。
  4. 处理问题时,能迅速定位到系统瓶颈和故障源。

任何一个技术团队要想围绕着这几个方面,从零开始建设分布式可观测体系,都是一项非常艰巨的任务,好在业界对于分布式可观测性的建设,已经有了不少成熟的方法论以及开源项目可以参考。

业界广泛认可的可观测性(observability)包含三个核心要素:Logging(离散的日志信息)、Metrics(聚合的指标)、Distributed Tracing(分布式追踪)。围绕这三个核心要素,有不少开源项目可以进行选择,帮助开发者快速建设分布式可观测体系。

【JS】核桃编程:前端可观测性建设之路

通过引入Skywalking,Prometheus等开源技术,核桃技术团队建立了完整的分布式可观测体系,能够对服务端复杂的微服务应用实现全链路追踪,并通过统一的日志服务体系收集分析业务日志。这样的努力对于系统稳定性以及用户体验的提升是立竿见影的:当系统服务端的任何一个环节出现故障或性能瓶颈的时候,技术团队都能第一时间得到通知,并快速定位问题,进行针对性处理。

相对于成熟的服务端监控技术,整个业界在客户端监控领域的技术方案一直比较欠缺。在互联网上,海量的用户使用不同厂家、不同操作系统、不同屏幕分辨率的终端设备,分布在不同的地域,又通过不同的网络运营商进行接入,甚至存在复杂的第三方依赖,包括CDN、第三方统计脚本、页面嵌套等方面。当用户体验遇到问题的时候,如果仅仅拥有服务端监控手段,很难第一时间确认问题的根源到底在于前端还是后端。即便能够排除服务端的问题,前端用户体验也受到页面渲染、JavaScript执行、网络质量、第三方接口服务质量等方面的影响,为进一步排查问题留下了非常多的挑战。

一个简单的思路是通过前端JavaScript做自定义的埋点,将最终用户的各种行为实时上报给服务端进行统计,以第一时间了解到用户体验。这个思路本身是合理的,但业务埋点、数据采集、聚合分析、视图展现等层面都有非常多的工作需要做,是一个浩大的工程。绝大多数技术团队而言,投入如此多的精力来建设这样一套前端监控方案都是不现实的。

建设前端可观测体系,最好的捷径是参考互联网领域头部企业的案例,选择云计算厂商提供的完整方案。阿里巴巴多年实战积累了一套全集团统一的前端监控方案,并开放给各个事业部接入。对于以HTML页面形式呈现的前端应用,不管是PC端/移动端网站,嵌入到移动端App的HTML5页面,都可以通过无侵入的方式接入到这套前端监控方案中。

【JS】核桃编程:前端可观测性建设之路

这套监控方案也同时通过阿里云对外输出,成为阿里云可观测性整体方案的重要组成部分,服务于广大的外部用户。

在客户端监控领域,包括ARMS前端监控和APP监控两个产品,其中ARMS前端监控专注于Web端体验数据监控,从页面打开速度、页面稳定性和外部服务调用成功率这三个方面监测Web页面的健康度,帮助使用者降低页面加载时间、减少JS错误,有效提升用户体验。

【JS】核桃编程:前端可观测性建设之路

这套方案正好能补齐核桃编程在客户端监控领域的能力缺失,所以核桃技术团队尝试在一些业务线接入阿里云ARMS前端监控。很快,他们就感受到了这套方案对于提升用户体验所带来的价值。

ARMS前端监控方案之所以能被核桃编程采纳,有一个很重要的原因是方案的接入是非常简单的,唯一要做的事情是在客户端HTML页面的Body元素中加入一段由ARMS提供的统计接入脚本(一段JavaScript代码),就能完成监控数据的自动上报。这其中不涉及到任何跟业务层主动埋点的工作,在核桃编程的多条业务线之间推广起来是非常顺利的。基于之前的经验,凡是需要在业务层主动埋点的监控方案,都需要通过行政手段来保证多个研发团队在编写代码的时候遵守既定的规则,这样的方式从长期来看都是很难落地的。包括在服务端全链路监控方面,核桃编程也始终遵循业务无侵入的思路,避免主动埋点行为。

接下来,研发人员就能从前端监控控制台全面了解应用端到端的健康程度,包括PV/UV情况统计、页面加载速度情况、JavaScript执行情况,API请求成功率等多个方面。以页面加载速度为例,ARMS可以基于客户端自动上报的监控数据,实时展示每一个页面的加载情况。

【JS】核桃编程:前端可观测性建设之路

其中,首次渲染时间、首屏时间、Dom Ready等指标都是HTML页面独有的性能指标,遵循业务标准的指标定义。这些指标数据和前端页面健康程度息息相关,影响着最终用户每一次交互行为的实际体验。

【JS】核桃编程:前端可观测性建设之路

通过页面加载瀑布图,能够按照页面加载的顺序,直观地展示各阶段的耗时情况。这些指标参数涵盖了网络层面的性能指标,当网络层面出现性能瓶颈,比如应用系统的接入带宽不能支撑用户访问流量的时候,仅仅通过服务端的监控手段,是无法洞察到的,必须依赖于客户端的实时监控数据上报。通过ARMS前端监控,核桃编程能从页面生产时(服务器端状态)、页面加载时和页面运行时这三个方面,全面了解到每一个应用系统端到端的健康程度。

【JS】核桃编程:前端可观测性建设之路

特别重要的是,ARMS前端监控能够从地理位置、浏览器、操作系统、分辨率、网络运营商、应用版本等多个维护,对性能指标进行聚合分析,从而帮助核桃编程更好地定位性能瓶颈。比如地理分布视图就能通过对地理位置的聚合分析,展现全国每一个省的页面首次渲染平均时间。当某一个地域的CDN出现故障的时候,地理分布视图能帮助核桃编程迅速定位问题的根源,而传统的监控手段是完全没有办法覆盖这类场景的。

【JS】核桃编程:前端可观测性建设之路

JavaScript错误分析和API请求分析也是核桃编程在应用系统的日常维护中非常关心的页面健康度指标。前者可以展示JavaScript错误的基本信息和分布情况,并具备回溯用户行为的能力。后者可以展示每个API的调用情况,包括调用成功率、返回信息、调用成功或失败的平均耗时等。当前端页面完全载入后,用户的操作会涉及到复杂的JavaScript执行,并在页面触发多个API调用,其中还包括对第三方提供的接口调用。

ARMS能够从最终用户的角度,真实还原前端代码执行的完整现场,帮助核桃编程快速定位来自前端的故障源。和页面加载速度统计一样,JavaScript错误分析和API请求分析都能够通过地理位置、浏览器等多种维度进行聚合分析。在线上编程教育的业务场景里面,客户端的实现包含着大量业务逻辑以及云端之间的双向交互,有一些问题只有在特定的浏览器和页面分辨率下才有可能暴露出来,这类问题就特别依赖多维度聚合分析进行排查。

在熟练掌握ARMS提供的前端可观测性能力之后,核桃编程开始把前端页面健康度指标作为日常业务迭代的检测标准,这项工作是通过与所有业务线的灰度发布计划相互配合而进行的。对于生产环境的每一次版本升级,核桃编程都会通过灰度发布的方式实现,先将小规模的用户流量导入新版本进行功能性、稳定性、健康性验证,只有满足预先定义的各项指标后,才会逐步增加导入新版本的用户流量,否则会立即对版本进行回滚。前端健康度的各种指标都是非常重要的衡量维度,而这些指标仅仅通过版本发布前的常规测试手段,是没有办法全面采集到的。核桃编程将前端健康度纳入业务迭代的衡量标准,体现着业务迭代过程中的可灰度、可观测、可回滚,这也是在阿里巴巴广为推崇的安全生产三板斧原则。

【JS】核桃编程:前端可观测性建设之路

除了通过ARMS控制台主动的观察分析,掌握各项前端业务指标之外,更重要的事情是在遇到用户体验问题时,如何第一时间得到通知和告警,防患于未然。这个诉求通过ARMS完善的报警机制可以轻松实现。核桃基于自身对前端健康度的理解,以及业界通用的方法论,创建了多种维度的报警规则,比如“最近5钟内平均页面首次渲染耗时大于1秒”等。当规则被触发时,系统会以预先指定的报警方式向报警联系人分组发送报警信息,以提醒技术团队及时解决。这些报警规则再配合上对生产故障的分级分类定义,能够帮助核桃技术团队建立一整套生产故障应对机制,真正实现实线上问题5分钟内发现,10分钟内隔离,30分钟内解决。

【JS】核桃编程:前端可观测性建设之路

核桃编程还积极探索前后端统一链路追踪技术,将API请求从前端发出到后端调用的链路串联起来,真实还原代码执行的完整现场。这是通过对前端API请求自动注入Trace信息而实现,ARMS前端监控能够在允许API自动上报的前提下,在API请求的Request Header中加入自动生成的TraceID,作为串联前后端链路的标识。这样通过调用的时间轴,可以知道是网络传输还是后端调用导致请求耗时时间过长,进一步通过后端应用的线程剖析功能,可以洞察每次请求后端的完整调用链路,对于排查系统故障和性能瓶颈带来了非常大的帮助。

完善的前端可观测体系在帮助核桃编程减少了30%以上的运维工作量的同时,还缩短了60%以上的故障定位平均耗时,极大地提升了用户体验,为业务持续发展打下了坚实的基础。核桃技术团队将基于自身的技术特点,继续探索更多前沿的云原生技术,充分享受云计算带来的红利。

核桃编程正在招聘业务架构师、运维架构师,核桃编程通过优质的课程内容和首创的AI人机双师互动学习辅导系统,现已成为国内外领先的少儿编程教育公司,产品技术团队多来自于阿里巴巴、百度等顶尖互联网公司;课程研发团队全部出身双一流高校,同时还汇集了儿童心理及行为研究等领域的顶尖人才。

作者:山猎,阿里云解决方案架构师
原文链接
本文为阿里云原创内容,未经允许不得转载

以上是 【JS】核桃编程:前端可观测性建设之路 的全部内容, 来源链接: utcz.com/a/108217.html

回到顶部