金沙国际唯一官网网址-金沙国际唯一平台官网登录

热门关键词: 金沙国际唯一官网网址,金沙国际唯一平台官网登录

搭建故障演练平台,六年打磨

原标题:去哪儿系统高可用之法:搭建故障演练平台

金沙国际唯一官网网址 1

Classloader担当将Class加载到JVM中,何况规定由非常ClassLoader来加载(父优先的品级加运载飞机制)。还会有一个任务正是将Class字节码重新解释为JVM统一供给的格式

作者介绍

Ali妹导读:压缩故障的最佳点子正是让故障平常性的产生。通过不停重复退步进度,持续晋级系统的容错和弹性技巧。前几天,Alibaba把六年来在故障演习领域的新意和进行汇浓缩而成的工具举办开源,它就是“ChaosBlade”。假诺你想要升高开采功用,无妨来打探一下。

1.Classloader类结构剖判

王鹏,二零一七年投入去哪儿机票工作部,重要从事后端研究开发工作,前段时间在机票工作部担当行程单和故障演习平台以及公共服务ES、数据同步中间件等生死相依的研究开发职业。

金沙国际唯一平台官网登录,高可用架构是保障服务稳固性的主干。

(1)首要由七个章程,分别是defineClass,findClass,loadClass,resolveClass
  • <1>defineClass(byte[] , int ,int) 将byte字节流深入分析为JVM能够分辨的Class对象(直接调用这几个点子生成的Class对象还尚未resolve,那些resolve将会在这几个指标真正实例化时resolve)

  • <2>findClass,通过类名去加载对应的Class对象。当大家落到实处自定义的classLoader平日是重写那一个主意,依据传入的类名找到对应字节码的文书,并经过调用defineClass剖判出Class独享

  • <3>loadClass运维时能够透过调用此措施加载多个类(由于类是动态加载进jvm,用略带加载多少的?)

  • <4>resolveClass手动调用那些使得被加到JVM的类被链接(剖判resolve那些类?)

去哪个地方网二〇〇六年创制到现在,随着系统规模的逐级扩展,已经有好七个应用系统,那一个连串里面包车型地铁耦合度和链路的复杂度不断抓实,对于我们营造分布式高可用的系统架构具备不小挑衅。大家需求二个平台在运行期自动注入故障,核算故障预案是不是起效——故障练习平台。

Alibaba在海量互联网服务以及每年双11情景的实践进程中,沉淀出了席卷全链路压测、线上流量管理调节、故障练习等高可用宗旨本事,并通过开源和云上劳动的款型对外出口,以帮扶集团顾客和开辟者享受阿里Baba(Alibaba)的技能红利,提升开支成效,收缩专门的学问的塑造流程。

(2)完结自定义ClassLoader日常会继续USportageLClassLoader类,因为那些类实现了相当多措施。

一、背景

举个例子,借助Ali云品质测量试验 PTS,高作用创设全链路压测体系,通过开源组件 Sentinel 完结限流和贬低作用。这一遍,经历了 6 年时刻的精雕细琢和实行,累计在线上进行练习场景达数万次,大家将Alibaba在故障演练领域的创新意识和实施,浓缩成三个混沌工程工具,并将其开源,命名称为ChaosBlade。

2.ClassLoader的阶段加载机制

那是某工作部的系统拓扑图:

ChaosBlade 是什么?

ChaosBlade 是一款遵从混沌工程实施原理,提供丰裕故障场景完结,扶助布满式系统进步容错性和可复苏性的无知工程工具,可实现底层故障的注入,特点是操作简单、无侵入、扩大性强。

ChaosBlade 基于 Apache License v2.0 开源左券,这段时间有 chaosblade 和 chaosblade-exe-jvm 七个酒馆。

chaosblade 包含 CLI 和使用 Golang 完毕的基本功能源、容器相关的愚拙实验施行实施模块。chaosblade-exe-jvm 是对运行在 JVM 上的利用施行混沌实验的实施器。

金沙国际唯一官网网址,ChaosBlade 社区持续还恐怕会加多 C++、Node.js 等任何语言的愚钝实验试行器。

金沙国际唯一官网网址 2

(1)JVM平台提供三层的ClassLoader,那三层ClassLoader能够分为两类,分别是劳务JVM自己的,和劳务周边普通类的。分别是:
  • <1>BootstrapClassLoader:首要加载JVM自个儿专业所急需的类,该ClassLoader未有父类加载器和子类加载器

  • <2>ExtClassLoader:那些类加载器一样是JVM本身的一某个,然实际不是由JVM完成,主要用来加载System.getProperty(“java.ext.dirs”)目录地下的类,如本机的值“D:javajdk7jrelibext;C:WindowsSunJavalibext”

  • <3>AppClassLoader:加载System.getProperty("java.class.path")(注意了在ide中运作程序时,该值经常是该类型的classes文件夹)中的类。全部的自定义类加载器不管直接完成ClassLoader,是承继自U奥迪Q3LClassLoader或其子类,其父加载器(注意:父加载器与父类的各自)都以AppClassLoader,因为无论是调用哪个父类的构造器,最后都将调用getSystemClassLoader作为父加载器,而该办法再次回到的正是AppClassLoader。(当应用程序中尚无其余自定义的classLoader,那么除了System.getProperty(“java.ext.dirs”)目录中的类,其余类都由AppClassLoader加载)

金沙国际唯一官网网址 3

为什么要开源?

大多厂家一度伊始关怀并追究混沌工程,稳步变成测验系统高可用,创设对系统音信不可缺点和失误的工具。但混沌工程领域这两天还地处三个火速形成的品级,最棒推行和工具框架未有统一规范。实践混沌工程大概会带来一些隐私的业务危机,经验和工具的缺点和失误也将进而阻止 DevOps 职员奉行混沌工程。

混沌工程领域这段时间也会有不菲卓越的开源工具,分别覆盖有个别世界,但那些工具的行使方法差别,当中多少工具上手难度大,学习花费高,混沌实验技艺单一,使众多少人对混沌工程领域缩手缩脚。

Alibaba公司在混沌工程领域曾经推行多年,将混沌实验工具 ChaosBlade 开源指标,大家期待:

  • 让更多少人明白并走入到混沌工程领域;
  • 缩水营造混沌工程的门道;
  • 还要依据社区的力量,完善更加多的无知实验现象,共同推进混沌工程领域的前进。
(2)Jvm加载class文件到内有着二种办法,隐式加载和出示加载,平常那三种艺术是长短不一使用的
  • <1>隐式加载:是透过JVM来自动加载供给的类到内部存款和储蓄器的不二等秘书籍,当有个别类被使用时,JVM开采此类不在内部存款和储蓄器中,那么它就能够活动加载该类到内部存储器

  • <2>显示加载:通过调用this.getClasss.getClassLoader.loadClass(),Class.forName,本身达成的ClassLoader的findClass方法

系统里头的借助非常复杂、调用链路很深、服务期间平昔不分支。在这种复杂的信赖性下,系统产生了几起故障:

ChaosBlade 能解决哪些难点?

权衡微服务的容错本领

透过模拟调用延迟、服务不可用、机器能源满载等,查看爆发故障的节点或实例是不是被自动隔开分离、下线,流量调节是或不是科学,预案是不是有效,同有时间观看系统一体化的 QPS 或 RT 是还是不是受影响。在此基础上得以缓慢扩展故障节点范围,验证上游服务限流降级、熔断等是或不是有效。最终故障节点扩张到央求服务超时,推测系统容错红线,衡量系统容错本领。

证实容器编排配置是不是站得住

透过模拟杀服务 Pod、杀节点、增大 Pod 能源负载,观看系统服务可用性,验证别本配置、财富限制配置以及 Pod 下安插的容器是或不是站得住。

测量试验 PaaS 层是不是健全

因而模拟上层财富负载,验证调节系统的有用;模拟信任的布满式存储不可用,验证系统的容错本事;模拟调解节点不可用,测量试验调治任务是还是不是自动员搬迁移到可用节点;模拟主备节点故障,测量试验主备切换是不是健康。

证实监察和控制告警的时效性

透过对系统注入故障,验香港证肆期货(Futures)交易监督委员会察和控制目的是还是不是可信赖,监察和控制维度是不是全面,告警阈值是或不是合理,告警是还是不是火速,告警接收人是不是科学,公告门路是或不是可用等,提高监督告警的纯正和时效性。

一定与消除难题的应急才具

经过故障突袭,随机对系统注入故障,考查相关人士对难题的应急力量,以及难题反馈、管理流程是或不是合理,达到以战养战,操练人一定与缓和难点的力量。

(3)上级委托机制:当二个加载器加载类字时,先委托其父加载器加载,若加载成功则反映给该加载器,若父加载器不可能加载,则由该加载器加载
  • 弱注重挂掉,主流程挂掉,修改报废凭据的开支情状,下单主流程失利;
  • 主干服务调用量陡增,某服务超时引起相关联的具备服务“雪崩”;
  • 机房网络也许某个机器挂掉,不可能提供基本服务。

成效和特点

地方丰盛度高

ChaosBlade 扶助的无知实验现象不止覆盖基础能源,如 CPU 满载、磁盘 IO 高、互联网延迟等,还包括运维在 JVM 上的利用试验现象,如 Dubbo 调用超时和调用相当、钦定方法延迟或抛格外以及再次来到特定值等,同期涉嫌容器相关的实验,如杀容器、杀 Pod。后续会持续的加码实施现象。

应用轻松,易于明白

ChaosBlade 通过 CLI 情势实施,具备本身的通令提醒意义,能够大致急迅的侧面使用。命令的书写遵从Alibaba公司内多年故障测量试验和练习实行抽象出的故障注入模型,档次鲜明,易于阅读和精晓,收缩了混沌工程实施的门道。

情景扩展方便

抱有的 ChaosBlade 实验实施器同样遵守上述提到的故障注入模型,使实验现象模型统一,便于开辟和护卫。模型本身老妪能解,学习开销低,能够依照模型方便神速的扩展越多的鸠拙实验现象。

金沙国际唯一官网网址 4

3.什么样加载class文件:

分为五个步骤 加载字节码到内部存款和储蓄器、Linking、类字节开端化赋值

八个故障原因:

ChaosBlade 的演进史

EOS(2012-2015):故障演习平台的最早版本,故障注入手艺通过字节码加强情势贯彻,模拟常见的 RPC 故障,解决微服务的强弱注重治理难点。

MonkeyKing(2016-2018):故障练习平台的晋级版本,充分了故障场景(如:能源、容器层场景),开首在生育条件开展局地规模化的演习。

AHAS(2018.9-至今):Ali云应用高可用服务,内置练习平台的全部效用,协理可编写制定演习、演习插件扩张等力量,并结合了架构感知和限流降级的效果。

ChaosBlade:是 MonkeyKing 平台底层故障注入的贯彻工具,通过对演习平台底层的故障注入本事开展抽象,定义了一套故障模型。合营顾客本身的 CLI 工具举办开源,援救云原生客户张开混沌工程测量试验。

金沙国际唯一官网网址 5

(1)加载字节码到内部存款和储蓄器:(这一步经常通过findclass()方法完毕)

以ULacrosseLClassLoader为例:该类的构造函数返现必需制定贰个URAV4L数据技艺创制该对象,该类中隐含三个U奥迪Q5LClassPath对象,U汉兰达LClassPath会判别传过来的U昂CoraL是文件恐怕Jar包,创造相应的FileLoader或然JarLoader只怕默许加载器,当jvm调用findclass时,那一个加载器将class文件的字节码加载到内部存款和储蓄器中

  • 系统强弱正视混乱、弱信任无降级;
  • 系统流量剧增,系统容积不足,未有限流熔断机制;
  • 硬件财富互联网出现难题影响系统运作,未有高可用的网络架构。

方今规划

职能迭代:

  • 巩固 JVM 演习场景,帮衬越来越多的 Java 主流框架,如 Redis,GRPC
  • 拉长 Kubernetes 演习场景
  • 追加对 C++、Node.js 等应用的支撑
(2)Linking:验证与分析,包罗3步:
  • <1>字节码验证

  • <2>类策画:筹划代表各类类中定义的字段、方法和完成接口所需的数据结构

  • <3>深入分析:这几个阶段类装入器转入类所采纳的别的类

五光十色的主题素材,在这种复杂的信任结构下被加大,一个凭仗二十七个SOA服务的系统,每一个服务99.99%可用。99.99%的35次方≈99.7%。0.3%代表一亿次呼吁会有3,000,00次失利,换算成时间大致每月有2个钟头服务不平稳。随着服务信赖数量的变多,服务动荡的概率会呈指数性升高,这么些标题最后都会转化为故障表现出来。

社区共同建设:

招待待上访谈 ChaosBlade@GitHub,插手社区共同建设,包含但不防止:

  • 架构划虚拟计
  • 模块设计
  • 代码落成
  • Bug Fix
  • Demo样例
  • 文书档案、网址和翻译

正文小编:中亭

翻阅原版的书文

正文来源云栖社区合营同伙“ Ali才能”,如需转发请联系最先的著作者。

(3)初步化class对象,推行静态开始化器并在这阶段末尾初始化静态字段为暗中同意值

二、系统高可用的方法论

4.大范围加载类错误深入分析

什么构建贰个高可用的种类啊?首先要分析一下不可用的因素都有哪些:

(1)ClassNotFoundException:

日常是jvm要加载一个文书的字节码到内部存储器时,未有找到这几个字节码(如forName,loadClass等艺术)

金沙国际唯一官网网址 6

(2)NoClassDefFoundError:

常备是使用new关键字,属性引用了有些类,继承了有些类或接口,但JVM加载那个类时发现这几个类不设有的要命

高可用系统独立实行

(3)UnsatisfiedLinkErrpr:

如native的章程找不到本机的lib

理论上来讲,当图中负有的政工都做完,大家就能够感觉系统是一个实在的高可用系统。但便是那样吗?

5.常用classLoader(书本此处其实是对tom加载servlet使用的classLoader剖判)

那么故障演练平台就热闹登台了。当上述的高可用实行都做完,利用故障演习平台做三遍真正的故障练习,在系统运维期动态地注入一些故障,从而来注解下系统是不是依据故障预案去实践相应的降级恐怕熔断战术。

(1)AppClassLoader:

加载jvm的classpath中的类和tomcat的宗旨类

三、故障练习平台

(2)StandardClassLoader:

加载tomcat容器的classLoader,另外webAppClassLoader在loadclass时,开采类不在JVM的classPath下,在PackageTriggers(是一个字符串数组,满含一组不能够使用webAppClassLoader加载的类的包名字符串)下的话,将由该加载器加载(注意:StandardClassLoader并不曾覆盖loadclass方法,所以其加载的类和AppClassLoader加载没什么分别,并且使用getClassLoader重临的也是AppClassLoader)(其余,借使web应用直接放在tomcat的webapp目录下该利用就能够通过StandardClassLoader加载,估算是因为webapp目录在PackageTriggers中?)

故障练习平台:核算故障预案是还是不是确实的起作用的阳台。

(3)webAppClassLoader如:

Servlet等web应用中的类的加载(loadclass方法的平整详见P169)

故障类型:主要包含运维期卓殊、超时等等。通过对系统某个服务动态地注入运营期非常来达到模拟故障的指标,系统依照预案施行相应的宗旨验证系统是不是是真正的高可用。

6.自定义的classloader

1、故障演习平台的完全架构

(1)必要选用自定义classloader的气象
  • <1>不在System.getProperty("java.class.path")中的类公事无法被AppClassLoader找到(LoaderClass方法只会去classpath下加载特定类名的类),当class文件的字节码不在ClassPath就需求自定义classloader

  • <2>对加载的一点类须求作极度管理

  • <3>定义类的实际效果机制,对曾经修改的类重新加载,完结热布置

故障练习平台框架结构重要分为四局地:

(2)加载自定义路线中的class文件
  • <1>加载特定来源的某个类:重写find方法,使特定类大概特定来源的字节码 通过defineClass获得class类并赶回(应该切合jvm的类加载标准,其余类仍选取父加载器加载)

  • <2>加载自顶叁个是的class文件(如通过互联网盛传的经过加密的class文件字节码):findclass中加密后再加载

金沙国际唯一官网网址 7

7.实现类的热计划:

  • (1)同叁个classLoader的多个实例加载同五个类,JVM也会识别为七个

  • (2)无法重复加载同叁个类(全名一样,并利用同一个类加载器),会报错

  • (3)不该动态加载类,因为对象呗引用后,对象的性格结构被涂改会引发难点

小心:使用不一致classLoader加载的同一个类公事获得的类,JVM将作为是三个分歧类,使用单例形式,强制类型转变时都可能因为这一个原因出标题。

  • 前台突显系统(WEB):呈现系统之间的拓扑关系以及各类AppCode对应的集群和办法,能够选拔具体的法子进行故障的流入和平化解除;
  • 公布连串(Deploy):其一种类重视用来将故障演习平台的Agent和Binder包宣布到对象应用程式的机械上还要运转试行。前台呈现系统会传递给公布平台要实行故障注入的AppCode以及目的APP的IP地址,通过那多个参数揭橥系统能够找到呼应的机械进行Jar包的下载和开发银行;
  • 服务和指令分发系统(Server):其一系列主要性是用来命令的散发、注入故障的意况记录、故障注入和平化解除操作的逻辑、权限校验以及有关的Agent的回来音信接收效果。前台页面已经接入QSSO会对当前人能够操作的IP列表做故障注入,防备风险。后端命令分发的模块会和布局在目的APP上的Agent进行通讯,将下令推送到Agent上进行字节码编织,Agent施行命令后回去的内容通过Server和Agent的长连接传回Server端;
  • Agent和Binder程序:Agent肩负对目的APP做代办并且做字节码巩固,具体代理的方式可以由此传输的通令来调控,代理方法后对章程做动态的字节码加强,这种字节码巩固全数无侵入、实时生效、动态可插拔的性状。Binder程序首若是因而发表种类传递过来的AppCode和开发银行端口(ServerPort)找到对象APP的JVM进度,之后实践动态绑定,完结运营期代码巩固的效用。

原书链接

如上内容只是个人笔记纪录,越来越多完整内容请购买作者原书籍查看。《深刻解析JavaWeb本领内部情形》

2、 Agent全部架构

日前AOP的完结有二种方法:

  • 静态编织:静态编织产生在字节码生成时根据早晚框架的平整提前将AOP字节码插入到指标类和艺术中;
  • 动态编织:在JVM运营期对内定的格局成功AOP字节码加强。常见的方法大大多运用重命名原有艺术,再新建三个同名方法做代办的专门的工作格局来成功。

静态编织的主题材料是即使想退换字节码必得重启,那给支付和测量试验进度导致了极大的紧Baba。动态的格局即使能够在运营期注入字节码实现动态拉长,但未有统一的API很轻便操作不当。基于此,我们采用动态编织的办法、标准的API来标准字节码的扭转——Agent组件。

Agent组件:经过JDK所提供的Instrumentation-API达成了应用HotSwap本事在不重启JVM的情状下达成对轻巧方法的增高,无论大家是做故障练习、调用链追踪(QTrace)、流量摄像平台(Ares)以及动态扩展日志输出BTrace,都亟需二个怀有无侵入、实时生效、动态可插拔的字节码加强组件。

Agent的风浪模型

如图所示,事件模型主要可分为三类事件:

金沙国际唯一官网网址 8

BEFORE在艺术试行前事件、THROWS抛出极度事件、RETU酷威N再次来到事件。那三类事件能够在点子实行前、重临和抛出格外那三种景况做字节码编织。

日常来讲代码:

// BEFORE

try {

/*

* do something...

*/

foo();

// RETURN

return;

} catch (Throwable e) {

// THROWS

}

事件模型能够完毕多个功用:

  • 在方法体试行在此之前一直重回自定义结果对象,原有办法代码将不会被实施;
  • 在方法体再次回到在此之前再度布局新的结果对象,以致足以改换为抛出非常;
  • 在方法体抛出极度之后再也抛出新的这个,以至能够改造为正规再次来到。

Agent怎样防御“类污染”

在开荒Agent的时候,第一个使用是故障练习平台,那么这一年其实大家并无需Agent实施的长河中有自定义结果对象的回到,所以首先个版本的Agent采纳硬编码的法子开展动态织入:

金沙国际唯一官网网址 9

故障类加载模型

率先介绍下多少个类加载器:

  • BootstrapClassLoader辅导类加载器加载的是JVM自己供给的类,那一个类加载使用C++语言实现的,是虚构机本人的一有个别;
  • ExtClassLoader它担负加载<JAVA_HOME>/lib/ext目录下照旧由系统变量-Djava.ext.dir钦点位路线中的类库;
  • AppClassLoader它承担加载系统类路线java-classpath或-D java.class.path钦点路径下的类库,也正是大家日常选用的classpath路线;
  • CommonClassLoader以及下面的都是汤姆cat定义的ClassLoader。

Agent和有关的lib会放到AppClassLoader这一层去加载,利用Javasist做字节码的织入,所以Javasist的加载器便是AppClassLoader。

可是想更改的是汤姆cat WebClassLoader所加载的com.xxx.InvocationHandler这么些类的Invoke方法,区别的ClassLoader之间的类是不能够相互拜会的,做字节码的转移并不须求那么些类的实例,也不要求回到结果,所以可以通过Instrument API得到那几个类加载器,而且能够凭借类名称获取到那些类的字节码举办字节码调换。故障类Drill.class和变形后的com.xxx.InvocationHandler.class重新load到JVM中,完毕了插桩操作。

以Dubbo为例表达下哪些注入故障和平化解除故障:

金沙国际唯一官网网址 10

Dubbo调用的流入进度

  • 服务A调用服务B在Client端的Proxy层做AOP;
  • 开发银行Agent而且生成叁个Drill类invoke方法,抛出三个运维期非常;
  • 字节码变形:在代码第一行从前增添Drill.invoke();
  • 设若想更改格外类型,改造Drill类就能够,换到Sleep 3s ClassRedifine过后会重复load到JVM完结故障类型的中间转播或然解除。

超越的标题

上边的秘籍相似很完美的缓慢解决了难点,然则随着平台的选择专业线要对众多接口和方法同一时候开展故障演习,那么大家转移的Drill类里面就能够有各样:

if method==业务线定义方法

do xxx

何况很轻易拼接出错何况难以调试,只可以把变化的类输出为文件,查看自身写的字节码编写翻译成class文件是还是不是精确,几乎太痛心了!

怎么解决?

新的架构必要缓和几个难题:

  • 类隔绝的主题材料:不要污染原生APP;
  • 事件的达成是可编写翻译的;
  • 援助回到自定义的结果。

下一版本的Agent完成就时有产生了,把具备Agent的类和促成的遵守抽象出来,放到一个自定义的AgentClassLoader里面,字节码注入到指标APP后方可经过反射的主意来调用具体的事件达成。

金沙国际唯一官网网址 11

类加载模型

  • 在BootstrapClassLoader里面注入Drill类作为通信类;
  • Agent会接受命令,依照事件类型对InvocationHandler做字节码变形,注入到对象APP;
  • 在对象APP调用的时候,调用Drill.invoke(targetJavaClass,targetJavaMethod, targetThis, args)传递过来多少个参数(目的类、方法、实例、自己参数等);
  • Drill类通过反射的方法调用AppClassLoader里面的求实事件完成,举例BEFORE事件的实践代码,来成功注入后的逻辑推行。

Agent的总体架构

Agent的共同体架构如图所示:

金沙国际唯一官网网址 12

  • 帮忙差异的模块的投入,比方Mock、流量摄像、故障演习等;
  • 支撑QSSO的权杖验证;
  • 支撑测量检验和虚伪蒙受的无资金接入;
  • 帮衬电动安排无需人工参加;
  • 支撑各个故障命令的揭穿和实践、 超时 、非常以及数额的归来;
  • 支撑形式等第的编写制定以及代码实行流程的编写制定;
  • 支撑在随便的Web容器施行Agent代理。

四、如何行使

利用的利润是很明显的:

  • 零开销接入,无需申请其余财富;
  • 故障注入解除,没有要求重启服务;
  • 能够提供具备集群的拓扑结构。

然则怎么本事准确使用呢?如下图所示:

金沙国际唯一官网网址 13

动用方法

步骤一、输入AppCode;

步骤二、选拔故障方法;

步骤三、钦点机器;

步骤四、注入故障。

五、总结

故障演练平台最核心的正是Agent组件——字节码编织框架,那一个框架是纯Java的依照Instrumentation-API的AOP建设方案。它能够方便研究开发职员对此字节码插桩拆桩操作,可以很轻便的达成故障演练、流量录像以及别的的运用模块。

作者:王鹏

来自:Qunar技能沙龙订阅号(ID:QunarTL)

dbaplus社会群众体育应接广大技艺职员投稿,投稿邮箱:editor@dbaplus.cn重回今日头条,查看越来越多

主编:

本文由金沙国际唯一官网网址发布于网络世界,转载请注明出处:搭建故障演练平台,六年打磨

您可能还会对下面的文章感兴趣: