产业互联网时代的单笔高可用与鲁棒性 |菜鸟技术中心

今日菜鸟受邀出席QCon全球软件开发大会,并做《产业互联网时代的单笔高可用与鲁棒性》主题发言,本文为该演讲主要内容。以下将从单笔高可用的定义、做单笔高可用的原因、落地单笔高可用的途径三个层面分享菜鸟的经验。希望能给对架构感兴趣的读者有所帮助,助力企业更好地设计出贴合自身业务场景的高可用体系和鲁棒性架构。

目录
  • 1. 什么是「产业互联网」
    • 1.1 产业互联网的定义
    • 1.2 菜鸟,客户价值驱动的全球化产业互联网公司
  • 2. 什么是「单笔高可用」
    • 2.1 什么是高可用
    • 2.2 产业互联网对高可用的要求更高
    • 2.3 消费互联网与产业互联网高可用策略对比
  • 3. 如何建设单笔高可用「工具能力」
    • 3.1 菜鸟高可用日志框架,可观测基础
    • 3.2 「单笔全链路排查」能力,助力工单排查提效
    • 3.3 「单笔异常核对」能力,验证上下游数据一致性
    • 3.4「单笔异常注入」能力,反向验证高可用效果
  • 4. 产业互联网的「鲁棒性架构」
    • 4.1 产业互联网更需要「鲁棒性架构」
    • 4.2 「防抖组件」,让重试更简单
  • 5. 菜鸟高可用「产品建设」实践
    • 5.1 以「业务场景」为视角的观测产品
    • 5.2 面向「治理流程」的异常日志治理产品
  • 6. 总结

 

5月26日,QCon 全球软件开发大会于广州召开,菜鸟受邀亮相此次科技盛会,与来自字节跳动、华为、腾讯、美团、蚂蚁、网易、 Google等70+行业大咖,同台分享企业技术创新和最新实践。 
本次QCon大会共策划了15+专题,60余场分享。在“稳定性即生命线”专题中,菜鸟网络高级技术专家已晨发表了《产业互联网的单笔高可用和鲁棒性》主题演讲,从理念、工具、架构、产品四个方面体系化论述,分享菜鸟单笔高可用体系的最新实践,和拆解现有高可用工具/产品背后的底层逻辑。以下是该演讲主要内容。
产业互联网时代的单笔高可用与鲁棒性 |菜鸟技术中心

菜鸟网络高级技术专家-已晨演讲现场

现有的高可用理念与产品,如系统可用率、MTBF/MTTR、可观测等,更多是在高并发的消费互联网场景。菜鸟作为一家物流产业互联网公司,物流的长链路、多节点、复杂业务需求场景和消费互联网有着天然差异,对高可用的诉求也迥然不同。「单笔高可用」是菜鸟在产业互联网的新架构下,在高可用方向上的一个探索与实践。

 1.什么是产业互联网

▐ 1.1 产业互联网的定义
国务院在2022年初印发的《“十四五”数字经济发展规划》(以下简称《规划》)中,明确了“十四五”时期要“以数据为关键要素,以数字技术与实体经济深度融合为主线,加强数字基础设施建设,完善数字经济治理体系,协同推进数字产业化和产业数字化,赋能传统产业转型升级,培育新产业新业态新模式,不断做强做优做大我国数字经济”
其中,“数字产业化”是指为产业数字化提供数字技术、产品、服务、基础设施和解决方案,以及完全依赖于数字技术、数据要素的各类经济活动。数字产业包括电子商务、网约车、文娱、社交媒体、搜索、数字金融等,这类企业通常也被称为“消费互联网”企业;“产业数字化”是指利用数据与数字技术对传统产业进行升级、转型和再造的过程。传统产业包括农业、制造业、交通、物流等,用“数智化”或“互联网技术”升级后的传统行业企业,也被称为“产业互联网”企业。
2020年,我国数字经济核心产业增加值占国内生产总值(GDP)比重达到7.8%,《规划》指出,在“十四五”期间需要大力推进产业数字化转型。中国的互联网从“消费互联网时代”逐步进入到了“产业互联网时代”。
▐ 1.2 菜鸟,客户价值驱动的全球化产业互联网公司

菜鸟扎根于物流产业,自2013年公司成立起,坚持把物流产业的运营、场景、设施和互联网技术做深度融合。目前已形成面向商家、消费者和物流合作伙伴3类客户的5大核心服务板块:国际物流、国内供应链、消费者物流、全球地网和物流科技。

产业互联网时代的单笔高可用与鲁棒性 |菜鸟技术中心

菜鸟“5美金10日达”产品,是用互联网技术和手段帮助产业降本提效的典型案例。“5美金10日达”让中国卖家花5美金送到全球20个国家,10个工作日到货。并在此基础上提供了“Y美金X日达”,为跨境的商家和消费者提供了更多确定性、物美价廉的物流服务。

 2.什么是单笔高可用

▐ 2.1 什么是高可用

我们通常说的“高可用”一般是指“系统服务”的高可用,是系统可用时间与“本来”可用总时间的比率,通常用“几个9”描述,比如99.99%的系统可用率就代表全年不可用时长为52分钟,99.999%的可用率就代表全年不可用时长5.26分钟。「系统」高可用更适用于消费互联网,这是由于消费互联网的业务生命周期和商家模式都是围绕着“系统服务”展开,系统不可用将直接影响消费者的使用,进而影响公司的收益。

在做系统高可用时,会使用两个关键指标,即平均故障间隔时间(MTBF, Mean Time Between Failure)和平均恢复时间(MTTR, Mean Time To Recover)。前者的本质是通过增加冗余,提升整体系统的可靠性和容错性,尽可能延长两次故障之间的间隔时间;后者是故障发生之后,通过监控、排查和应急响应快速将故障止血,缩短故障恢复时间。阿里巴巴安全生产提出的“1-5-10”就是“1分钟感知,5分钟定位,10分钟止血”的缩写,是降低MTTR的典型实践。

产业互联网时代的单笔高可用与鲁棒性 |菜鸟技术中心

▐  2.2 产业互联网对高可用的要求更高

由于产业互联网是对“生产过程”做数字化,任何一笔订单的异常在商业上都会是一个确定性的损失,所以,产业互联网不仅仅要求系统可用性,还要求每笔订单或每笔请求都可用。拿包裹履约来举例,消费者在下单后商家发货,整个包裹的流转会经过很多物流节点,也会经过很多物流系统。链路上任何一个节点故障,都会影响包裹配送。

在系统和系统之间,包裹是以“单”的形式存在和流转,比如物流系统中有发货单、补货单、履约单、拣选单、配送单等等。“单”的本质是契约,产业互联网的上下游就是通过“单”这种契约形式进行交互和协同的。不同于消费互联网的系统围绕着消费者的体验展开,产业互联网的系统围绕着生产过程,以“单”作为核心实体展开。这在菜鸟也有着明确的体现,比如菜鸟在过去几年,系统不可用类的故障只占一小部分,剩下的都是跟“单”相关的故障,同时在工单里边也有一个必填的字段就是“单号”。

我们通过经验可以知道,链路中的节点越多,整体失败的概率也越大。高标准要求叠加高失败概率,让产业互联网必须要做单笔高可用性,当然也面临着更大的挑战。我们下面从监控、链路、日志、应急防御等8个维度,来看下消费互联网和产业互联网在高可用策略上的区别。

▐ 2.3 消费互联网与产业互联网高可用策略对比

产业互联网时代的单笔高可用与鲁棒性 |菜鸟技术中心

以看出来,产业互联网的高可用策略,在消费互联网的基础上,有贴合产业的特点。比如在产业互联网的日志中普遍会打印“业务单号”和“单据状态”;在链路追踪中,除了通过TraceId查看一次完整RPC的调用链路外,还有通过业务单号排查的业务全链路;在监控方面,除了指标类监控,还有上下游数据一致性核对监控;在故障演练方面,相比于构造系统不可用,更关注如何构造单笔数据异常;在应急防御方面,产业互联网会更看重“鲁棒性架构”,从架构层面做单笔高可用的支撑。

产业互联网时代的单笔高可用与鲁棒性 |菜鸟技术中心
菜鸟的单笔高可用会从理念、工具、架构、产品四个维度体系化展开。以「面向失败设计」作为核心理念,整体包括6个步骤,分别是:
1. 构建统一的、结构化日志组件,为「可观测」打下基础。
2. 以工单作为突破口,建设单笔全链路排查能力(被动排查)。
3. 主动识别单笔异常,在用户感知前解决。
4. 建设“真实”、“无损”的单笔异常注入能力,对单笔高可用做反向验证。
5. 提升系统架构的鲁棒性,对故障主动防御,提升用户体验。

6. 整体技术能力以「易用的」产品透出。

 3.如何建设单笔高可用工具能力

▐ 3.1 菜鸟高可用日志框架,可观测基础

云原生可观测性中的Metrics, Tracing, Logging被奉为可观测性的三大支柱。除了指标类监控之外,还从日志、链路、事件等多个不同角度对系统做全方位的观测。
产业互联网时代的单笔高可用与鲁棒性 |菜鸟技术中心

但在企业的实际落地过程中,会发现三大支柱的数据非常割裂,由于分属于不同的研发团队,产业也是各自为战,再加上监控、日志大多没有规范的要求,可观测性在企业落地挑战还是非常大的。为了打通指标、链路和日志的数据,我们选择了它们3个共同的依赖:日志,并且要“结构化的日志”。

产业互联网时代的单笔高可用与鲁棒性 |菜鸟技术中心
通过结构统一、易于切分的结构化日志,打通上层的监控、链路及低成本存储平台,实现对可观测性三大支柱的串联。在阿里巴巴的可观测工具中metrics, logging, tracing都离不开结构化的日志,比如:

● Sunfire,阿里内部广泛使用的监控平台,天然具备切分日志的能力,把采集到的日志切分成kv键值对,并汇聚其中的关键指标,产出业务指标监控。

● 鹰眼/ARMS,阿里云的链路追踪平台,通过traceId和rpcId串联起上下游,包括业务应用和中间件。

● SLS/ODPS,阿里云日志存储平台,重要的日志全量存储在SLS或ODPS中。每行日志都会自动打印traceId和rpcId,作为链路追踪的索引信息。

产业互联网时代的单笔高可用与鲁棒性 |菜鸟技术中心

我们把应用抽象为业务入口、核心逻辑、下游依赖这3层,每一层分别打不同的日志文件。用一次RPC调用的traceId串起来整个流程,有4类结构化的日志文件。

● 入口日志:会打印系统内置的字段(traceId、rpcId、耗时、是否成功等),还会打印业务单号,以及业务单的状态等。入口日志主要用来做服务入口的黄金指标监控(流量、成功率、错误数耗时),也方便通过单号排查问题。
● 出入参日志:记录服务入口的出入参信息。
● 调用下游日志:下游依赖服务日志,记录下游的性能表现。

● 错误日志:输出错误堆栈,会记录traceId和rpcId,更方便追踪异常节点。

通过菜鸟日志组件的建设,让研发同学更容易打印标准的、结构化的日志,给上层的可观测能力提供了有效支撑。

▐ 3.2「单笔全链路排查」能力,助力工单排查提效
菜鸟的研发同学每个月要处理比较多的业务工单,对于异常单据的排查能力是刚需。鸟的链路很长,涉及到很多个物流节点、物流系统,其中有N种单据模型,比如交易单、物流单、电子面单、仓储单、运单等,彼此相关但又彼此不同。

当一个单号出现异常的时候,可能是由于某个物流系统的异常导致的卡单,这就涉及全链路的数据排查。而每个业务团队只能查本域的数据,无权限或无能力查询其他域的数据/日志,需要有一个横向平台串联起所有的上下游数据。

产业互联网时代的单笔高可用与鲁棒性 |菜鸟技术中心
基于对全链路排查场景的理解,我们对排查平台进行了领域建模,其中,业务链路可以有多个业务域,业务域可以有多个单据实体,单据实体上关联事件、数据和排查规则。

产业互联网时代的单笔高可用与鲁棒性 |菜鸟技术中心

输入一个单号之后,可以自动把全链路上的上下游各个数据串起来,有数据库的数据、各种日志数据,聚合成这个数据链路图。页面右上角的小医生会提示识别到的异常原因,当做工单排查的时候,就可以一眼看出来卡在哪个环节,以及问题是什么了。

▐ 3.3单笔异常核对」能力,验证上下游数据一致性
大家平时用到的监控系统,包括zabbix、Prometheus,都属于指标类监控系统。指标类监控的本质是一段时间内对系统内指标的统计。比如《Google SRE运维解密》提到的Google监控系统的黄金指标:流量、延迟、成功率、饱和度,都是统计类的指标。
产业互联网时代的单笔高可用与鲁棒性 |菜鸟技术中心
然而,指标类监控无法快速感知到产业互联网中的单笔异常。拿黄金指标监控的成功率举例,在每天1亿包裹的基数下,99.99%的成功率意味着每天有1万笔包裹的异常,而任何一个包裹没有送达都必然会是工单、投诉,甚至是故障。曾经在菜鸟发生过单笔异常故障,一笔包裹在出库之后,包裹出库消息在回传过程中出现失败,系统包裹状态一直“未出库”。由于未出库的包裹是允许直接退款的,消费者在收到货后,成功地发起了退款,商家财货两失。
产业互联网时代的单笔高可用与鲁棒性 |菜鸟技术中心

这种场景需要通过数据一致性核对监控来搞定,比如在上面的故障案例中,可以通过实时核对配送系统和仓储系统每一笔单据状态来发现这种异常。指标类监控和一致性核对监控,也可以用分布式系统中的CAP原理来解释:

产业互联网时代的单笔高可用与鲁棒性 |菜鸟技术中心
可以看出,消费互联网和产业互联网在业务模式上的差异,也影响了对监控系统的选型和设计。菜鸟有实时核对和离线数据核对平台,数据模型和数据架构上比较类似。比如实时核对监控系统,实时采集数据库的binlog,把上下游的数据通过单号关联,将流式的数据组装成“宽表”;然后对宽表数据进行校验,不满足校验规则的数据会生成告警任务,最后由用户闭环处置。

产业互联网时代的单笔高可用与鲁棒性 |菜鸟技术中心

产品示意图:

产业互联网时代的单笔高可用与鲁棒性 |菜鸟技术中心

不符合校验规则的数据会透出,交由研发值班同学处理。异常数据里边会包括单号、上下游的库表等信息。

产业互联网时代的单笔高可用与鲁棒性 |菜鸟技术中心
目前实时核对平台平均每天核对数百亿+条数据,发现了很多次线上故障,是指标类监控的有力补充。
▐ 3.4「单笔异常注入」能力,反向验证高可用效果
当我们做了架构升级或稳定性优化之后,想要真实地验证效果,就会用到混沌工程常见的故障注入能力,按照爆炸半径的大小,依次是:

1. 基础设施故障,比如机房故障,或断网。

2. 主机故障,比如宿主机宕机。

3. 容器故障,比如漂移、或者CPU打满。

4.服务故障,比如频繁FGC、OOM或下游异常或下游的延迟。

产业互联网时代的单笔高可用与鲁棒性 |菜鸟技术中心

这些异常注入能力在产业互联网落地,会面临两个问题:

1. 异常注入不够真实,现有的攻击能力目的是让“系统不可用”,产业互联网更关注有没有“异常的单子”(数据一致性)。

2. 真实异常不敢注入,用户对服务失败的容忍度更低。比如用户寄件/取件场景,每次异常注入都可能造成用户体验折损,甚至是工单或投诉。
产业互联网的异常注入不仅仅是要控制爆炸半径,最好要做到无损。我们相应的策略是:
1. 通过篡改旁路数据的方式来构造单笔异常的单子,验证一致性核对监控的有效性,如果没任何告警就有问题。

2. 通过对测试流量的攻击,达到无损且真实的异常注入。比如对于单笔订单数据的篡改方案,我们不会真实地篡改用户的数据,而是篡改旁路数据。

产业互联网时代的单笔高可用与鲁棒性 |菜鸟技术中心

对采集到数据库的binlog,之后做旁路数据做篡改,看是否有相应的监控告警出来,支持指定篡改的数据条数,可以自动给出结论,可以常态化地定时执行。

产业互联网时代的单笔高可用与鲁棒性 |菜鸟技术中心

如果有告警,则证明攻击成功;否则视为攻击失败,并同时生成一个缺失监控的风险单,由研发同学添加监控,完成整体的闭环。

 4.产业互联网的鲁棒性架构

笔高可用的工具能力更侧重于在异常发生之后的应对策略,我们希望可以从架构层面对异常做更主动的防御,从上游解决问题成本会更低。在本章,我会分享什么是鲁棒性架构,为什么产业互联网更需要鲁棒性架构,以及通过防抖组件的案例介绍我们是如何做鲁棒性架构的。

▐ 4.1 产业互联网更需要鲁棒性架构

维基百科对鲁棒性的定义,指系统在执行过程中,面对错误、异常及非法输入,仍能正常运行的能力。系统的鲁棒性不足,不是系统逻辑上的bug,而是不能有效应对外部世界的失败。比如在调用下游时,没有考虑到可能出现网络超时或者被下游限流等异常场景,导致单子在系统中流转时卡住;再比如系统对用户的输入没有做长度限制,超出了DB字段长度限制,把MySQL的插入失败异常直接抛出给了用户。

菜鸟系统类工单中有很多鲁棒性不足导致的工单,在数量上与bug类的工单持平。对于鲁棒性不足的问题,类似于订正数据,重推一下消息这种方案可以很容易临时解决,而真正要彻底消除这类问题则需要投入成本做架构升级。提升系统鲁棒性还有一个难点是鲁棒性比较抽象,一线研发对此无统一认知。为了让大家对鲁棒性有更大的体感,我们需要首先把鲁棒性这个抽象的名词做具象化。在分析了菜鸟近2000个工单之后,我们抽象出来系统鲁棒性不足的四大类12小类问题。
产业互联网时代的单笔高可用与鲁棒性 |菜鸟技术中心
如何把相对抽象的架构理念落地?我们从目标制定、效果度量、能力建设、文化运营四个方面多管齐下,体系化提升系统鲁棒性。
产业互联网时代的单笔高可用与鲁棒性 |菜鸟技术中心
在对“鲁棒性工单”的度量方面,我们抽取了研发同学在处理工单中的关键词,比如“重试”、“抖动”、“超时”、“延迟”等,做了一个鲁棒性工单报表。并针对性地建设工具和组件能力,接下来我会结合“防抖组件”的建设来具体分享。

在实践了近1年之后,一线研发对鲁棒性架构的认知逐步深入,鲁棒性工单数量也有了明显的收敛趋势。

▐ 4.2「防抖组件」,让重试更简单
经过细化分析,我们发现在鲁棒性工单中很多是因为下游调用异常导致的,“重试”这个关键词,在工单中出现的比例也非常高。
产业互联网时代的单笔高可用与鲁棒性 |菜鸟技术中心
我们对比了研发同学常用的几种重试工具发现,重试策略的丰富性和产品的易用性普遍不足。
产业互联网时代的单笔高可用与鲁棒性 |菜鸟技术中心
基于对已有工具的分析,我们设计了菜鸟统一的防抖组件。它提供了一个非常轻量级的接入流程。在运行时,会自动拦截下游的返回结果。当发现下游有异常时,会根据用户配置的防抖规则做自动的重试。当超过最大重试次数以后,会把异常流水记录下来,并发给处理人完结;这里通过了hsf和metaq两种通道确保不丢消息,确保每一笔异常都能被及时地处理解决。
产业互联网时代的单笔高可用与鲁棒性 |菜鸟技术中心
通过方便的接入流程,丰富的重试策略,让重试变得更简单。上线以来已经累计避免了百万次的调用失败卡单。

 5.菜鸟高可用产品建设实践 

前面从单笔高可用的理念、工具、架构方面对单笔高可用体系做了阐述,下面进入文章的最后一部分,从两个产品化的实战案例,从用户视角给大家做一些参考。

▐ 5.1 以「业务场景」为视角的观测产品

研发和做产品有着非常不同的套路,核心是思维模式的转变。做技术实现更多是站在研发自身的视角去看,要如何分层、分模块、用什么样的设计模式,更优雅地解决技术挑战。做产品化是站在用户的视角去看这件事情,怎么样能让我的操作路径最短。

产业互联网时代的单笔高可用与鲁棒性 |菜鸟技术中心

我们的很多平台更多是站在平台能力的视角下,比如我们大大小小有20+款高可用产品,分别从监控、预警、根因定位、预案恢复、链路、演练的视角做了很多平台。当研发同学收到一条告警之后,他需要在各个平台之间切换,收集散落在各平台的数据,在大脑中拼凑出一副完整的图。平台比较简单,而用户非常崩溃。

好用的产品,要站在用户任务的视角去思考,对用户来说,ta直接感知的不是监控和链路,而是归属于具体业务场景的监控和链路。比如消费者下单、商家发货等。当我收到某个业务场景告警的时候,如果有一个平台能以这个业务场景视角把所有平台能力整合起来,那一定可以减少我观测和决策的成本。这需要对已有的平台能力做解构,再以“业务场景”为视角重构。
 

比如对这个真实的历史故障做推演,预估让新人做到在3分钟内定位原因,可以极大缩短故障恢复时间,操作路径:

产业互联网时代的单笔高可用与鲁棒性 |菜鸟技术中心
1. 当收到异常告警时,点击详情会跳转到这个页面。
2. 快速框选到成功率下跌的时间段,所有页面上的图形都会动态联动。
3. 自动按照错误码的数量做倒排,快速找到跟本次异常最相关的错误码。
4. 当用户选中traceId的时候,可以快速用这个traceId做链路排查(我们预判用户是要拿着traceId做一次搜索)。

5. 会有一个弹框展示跟这个traceId所有相关的上下游信息,用红色的角标提示用户哪个节点有异常,点开可以查看异常的详情。

产业互联网时代的单笔高可用与鲁棒性 |菜鸟技术中心

▐ 5.2 面向「治理流程」的异常日志治理产品

在看过无数个工单之后,我发现很多研发同学在处理工单时会把异常日志贴出来,比如:
产业互联网时代的单笔高可用与鲁棒性 |菜鸟技术中心
这给我们提了一个醒,在工单这座“冰山”的下面,还隐藏着大量的异常日志未被治理。对异常日志治理的价值,相信无需过多论证,然而,线上很多应用每天还是有很多Error和Exception日志,即使治理也都是偏运动战,无法长久保持。比如线上的某个应用,有大量异常日志(当然属于没有影响的噪声)
产业互联网时代的单笔高可用与鲁棒性 |菜鸟技术中心
核心原因我认为是现有的产品不是面向治理流程,而是面向观测流程。核心表现为以下三个阻塞点:

1. 研发不知道线上都有哪些异常日志。很少有人会主动关注异常日志,一般还是在工单或告警来的时候响应式地查日志。在信息过载的背景下,产品需要从「人找风险」的模式变成「风险找人」的模式。

2. 研发判断「哪些异常日志需要治理」成本较高。单纯提供异常类型、数量等信息是远远不够的,一般需要根据异常日志的历史数据趋势、异常日志的详情、通过traceId看链路详情、翻代码才能判断,这几个信息需要跳转到多个平台(数据还不一定能有)。

3. 研发治理异常日志的成本太高。修改日志相关代码、测试、走一遍发布流程,顺利的话也得1天,更别提变更窗口、发布封网等阻塞性因素。
综合来看,我们需要一款面向治理流程的产品,会结合上文提到的菜鸟日志SDK,自动拦截RPC调用异常和研发主动打印的log.error,通过对标准异常日志的采集、汇聚和存储,建设异常日志中心,并通过风险任务完成对研发的触达和闭环。
产业互联网时代的单笔高可用与鲁棒性 |菜鸟技术中心
异常日志治理产品示例
产业互联网时代的单笔高可用与鲁棒性 |菜鸟技术中心
产品支持按照应用分组、异常类型进行独立观测,支持将异常日志一键标记为噪声;通过多维度数据辅助研发同学决策,并集成到了变更风控流程中,做变更风险的拦截。点击详情可以看到异常日志的采样信息,所有异常堆栈以采样的形式存储,进一步降低成本。

产业互联网时代的单笔高可用与鲁棒性 |菜鸟技术中心

 6.总结 

互联网经过多年的发展,高可用理念、策略、工具都已经很成熟,但大都是适合消费互联网的系统高可用理念和技术。菜鸟作为一家物流产业互联网公司,“高可用建设”面临高业务复杂性、高标准要求、低失败容忍度的挑战,这让我们在系统高可用基础上,逐步开始探索「单笔高可用」。可以发现,所有的理念和工具都有其适用场景,对自身业务的理解和抽象,是做好高可用的前提。
END
产业互联网时代的单笔高可用与鲁棒性 |菜鸟技术中心

 

 

阅读更多好文

本篇文章来源于微信公众号:菜鸟技术星球

本文来自投稿,不代表TakinTalks稳定性技术交流平台立场,如若转载,请联系原作者。

(0)
下一篇 2024年4月8日 上午8:30

相关推荐

发表评论

邮箱地址不会被公开。