Chinaunix首页 | 论坛 | 博客
  • 博客访问: 6922823
  • 博文数量: 700
  • 博客积分: 10821
  • 博客等级: 上将
  • 技术积分: 12011
  • 用 户 组: 普通用户
  • 注册时间: 2005-12-02 10:41
个人简介

大数据、ML、AI、云计算openstack、Linux、SpringCloud。

文章分类

全部博文(700)

分类: 云计算

2015-05-20 10:43:56

架构

      Ceph的提供了一个根据RADOS无限扩展的Ceph存储集群,相关内容你可以参阅REDOS-一个可伸缩的、可靠的存储服务PB级别存储集群。存储集 群客户端和每个Ceph的OSD守护进程使用CRUSH算法有效地计算有关数据位置的信息,而不必依赖于一个查找表。Ceph的高层次功能包括Ceph的 存储集群,通过 librados提供了一个原生接口,在librados基础上建立一些服务接口。Ceph OSD守护进程储存所有的数据成为一个层面的命名对象(例如,没有目录层次结构)。对象的标识符,二进制数据和元数据组成的一组名称值对。语义是完全基于 Ceph的客户端。例如,CephFS的使用元数据来存储文件属性,如文件的所有者,创建日期,最后修改日期,等等。

注意:整个集群的对象ID是唯一的,不仅仅在本地文件系统。

 扩展性和高可用性


       在传统架构中,客户谈论到一个集中的组件(如网关,代理,API,外观等),作为单点进入到一个复杂的子系统。这会带来性能和可扩展性的限制,同时引入单点故障(即,如果集中的组件出现故障,整个系统也出现故障)。

      Ceph的消除了集中式网关,使客户能够直接与Ceph的OSD守护进程进行互动。Ceph的OSD守护进程创建对象的副本,在其他Ceph的节点上,以 确保数据的安全性和的高可用性。Ceph的还采用了集群监视器,以确保高可用性。为了消除集中Ceph的使用这种算法叫做CRUSH。

   CRUSH介绍

      Ceph的客户端和Ceph的OSD守护进程都使用CRUSH算法来高效地对数据容器的信息需求进行计算,而不必依赖于一个查找表。CRUSH与旧方法相 比,提供了更好的数据管理机制,使大规模清晰地将工作分配到集群中的所有客户端和OSD守护。CRUSH使用智能的数据复制,以确保弹性,这样可以更好的 适合于超大规模存储。以下各节提供更多的细节CRUSH是如何工作的。CRUSH的详细讨论,请参阅CRUSH -控制,可伸缩的,分散的位置复制数据。

群集映射

       Cept的使用取决于Ceph的客户和Ceph的OSD守护集群拓扑知识,“群集映射”:包括5类映射

      1.监控映射

       包含集群FSID,位置,名称地址和每个监视器的端口。这也表明现在的时期里,当创建映射时,并且它最后一被改变。要查看监控映射,执行如下命令

        cept mon dump

      2.OSD映射

       包含集群FSID,当创建和最后修改映射时间,池的列表,副本大小,PG数字的OSD的列表,他们的状态(例如,up,in)。要查看一个OSD映射,执行如下         命令

         cept osd dump

      3.PG映射

       包含PG版本,其时间戳记,最后OSD映射时代,完整的比率,如PG ID,每个配置组集,代理设置,在PG的状态(例如 active + clean)和每个池数据使用         统计数据。

       4.CRUSH映射

       包含存储设备,故障域层次结构(例如,设备,主机,机架,行,空间等),并遍历层次结构存储数据时的规则的列表。要查看CRUSH映射,执行命令:
           getcrushmap –o {filename},然后通过执行crushtool -D {comp-crushmap-filename} -O {decomp-crushmap-filename}反编译。你可以查看在文本编辑器或反编        译的映射或使用命令cat查看。

       5.MDS映射

       包含了现有的MDS映射从它创建至最后一次修改的时期。它还包含池用于存储元数据,元数据服务器的列表,以及元数据服务器中。要查看MDS映射,执行         如下命令

         ceph mds dump

         每个映射保持一个重复历史关于其运行状态的变化。Ceph的监视器保持集群的主副本映射,包括集群成员的状态,变化,和Ceph的存储集群的整体健康。

高可用性监视器

     在CEPH的客户端可以读取或写入数据之前,他们必须联系一个CEPH监控组件来获得最新的集群映射副本。CEPH的存储集群可以伴随着单个监控器执行,但是,这引入了单点故障(即如果监控器出现故障,CEPH的客户端无法读取或写入数据)。

     为了增加可靠性和容错性,CEPH的监视器支持集群。在一个集群中的监视器,延迟等故障可以导致一个或多个监视器落后当前集群状态。出于这个原 因,CEPH的各监控集群状态的实例必须有协议。CEPH的总是采用了大多数的显示器(如,1,2:3,3:5,4:6,等)和PAXOS算法建立的集群 的当前状态的共识监视器。

      对于监视器配置的详细信息,请参阅“监视器参考配置”。

高可用性验证

  Ceph的客户端可以通过Ceph的监控器进行用户认证。Ceph的OSD守护程序和Ceph的元数据服务器,使用Ceph的类似Kerberos的 cephx协议来对用户进行身份验证。通过身份验证的用户获得授权后可以读,写和执行Ceph的命令。认证系统Cephx避免了单点故障,以确保可扩展性 和高可用性。想了解Cephx的详细信息以及它与Kerberos不同处,请参阅“Ceph的身份验证和授权”

启用超大规模智能守护

      在许多集群架构,集群成员的主要目的是使一个集中的接口知道哪些节点可以访问。使用集中化的管理接口,提供服务给客户端,通过一个双重分派实现PB级至exabyte 级规模,这是一个巨大的瓶颈。

       Ceph消除了这个瓶颈:Ceph的OSD守护进程和Ceph的客户端具有集群感应。像Ceph的客户一样,每个Ceph的OSD守护知道集群中的其他 Ceph的OSD守护。启用该项,在集群中Ceph的OSD守护与其他Ceph的OSD守护进程及Ceph的监视器直接互动。此外,它还能使Ceph的客 户端直接与CEPH OSD守护互动。

      Ceph的客户端,Ceph的监视器和Ceph的OSD守护互动Ceph的OSD守护对方的能力意味着Ceph的OSD守护可以利用CPU和RAM的CEPH节点来简单的处理会拖垮一个集中的服务器的任务。利用这一计算能力的能力,导致几大好处:

     1.OSDs服务直接客户端:
       任何网络设备,它所可以支持的并发连接数有限,一个集中的系统具有较低的高性能的物理极限。Ceph的客户直接联系Ceph的OSD守护程序,同时提高性 能和系统总容量,当消除单点故障时。Ceph客户端如他们需要,可以保持一个会话,并与一个特定的CEPH OSD守护进程联系而不是一个集中的服务器。

      2.OSD成员资格和状态:
        CEPH OSD守护加入集群,并报告自己的状态。在最低等级中,CEPH的OSD守护状态为开启或关闭反应,无论它是否正在运行并能够为CEPH的客户端请求提供 服务。如果一个CEPH的OSD守护进程在 CEPH的存储集群是开启或关闭状态,这种状态可能表明CEPH的OSD守护进程失败。CEPH的OSD如果一个守护程序没有运行(例如,它崩 溃),CEPH的OSD守护程序无法通知CEPH的监视器,它是关闭状态。CEPH的监视器可以通过定期PING CEPH的OSD守护,以确保它运行。然而,CEPH授权CEPH的OSD守护进程确定是否是相邻的OSD是关闭状态 ,更新群集映射并报告给CEPH的监控器。这意味着,CEPH的监控器可以保持轻量进程。想获得更多详细信息,请参阅“监测的OSD”和“心跳”相关文 档。

      3.数据清理:
        为了保持数据的一致性和干净的一部分,CEPH的OSD守护可以配置组内的对象。也就是说,CEPH的OSD守护一个配置组比较对象元数据存储在其他的 OSD布置组及其副本。清理(通常每天执行)捕捉错误或文件系统错误。CEPH的OSD守护程序也执行更深入的比较对象中的数据比特位清理。深度清理(通 常每周执行)发现坏扇区在光清理并不会发现的驱动器上。请参阅“数据清理”获得详细配置信息。

      4.复制: 
         类似于Ceph的客户端,Ceph的OSD守护进程使用CRUSH算法,但Ceph的OSD守护进程使用它来计算对象的副本应被存储(重新平衡)。一个 典型的写的情况下,客户端使用的CRUSH算法来计算存储一个对象,该对象映射一个池和配置组,然后着眼于CRUSH映射辨认主OSD配置组。客户端写在 主OSD对象确定配置组。然后,主要与它自己的拷贝CRUSH映射OSD识别二级和三级的OSD用于复制,复制的对象放置到相应的群体在二级和三级的 OSD(许多作为额外副本的OSD),并响应一旦确定对象的客户端存储成功。


 动态集群管理

 

      在可扩展性和高可用性部分中,我们解释了如何Ceph的使用CRUSH,扩展和维护高可用性集群感知和智能守护。Ceph的设计的关键是自发的,自我愈 合,Ceph的OSD智能守护。让我们更深入地看看CRUSH如何工作,用现代的云存储基础架构放置数据,重新平衡群集和动态地从故障中恢复。

    关于池

     Ceph的存储系统支持'池',这是用于存储对象的逻辑分区的概念。池设置以下参数:

  • 所有权/访问对象
  • 对象副本的数目
  • 放置组的数目
  • CRUSH规则集的使用

 

    Ceph的客户端从CEPH监视器检索群集映射,并把对象写入池。池的大小或副本的数目,CRUSH规则集和布置组的数量决定Ceph的将如何放置数据。

映射PGS至OSDs

      每个池的放置组的数量。CRUSH动态映射PGS至OSD。当CEPH的客户端存储对象时,CRUSH会映射每个对象到一个配置组。

      映射对象至配置组在CEPH的OSD守护和CEPH的客户端之间创建了一个间接层。CEPH的存储集群必须是能够增长(或收缩)和平衡它的动态存储对象。 如果CEPH的客户端“知道”哪个CEPH的OSD守护有哪些对象,这将创建CEPH的客户端和CEPH的OSD守护程序之间的紧密耦合。相 反,CRUSH算法映射每个对象到配置组,然后映射每个配置组到一个或多个CEPH的OSD守护。当新的CEPH的OSD守护和底层的OSD设备联机时, 这个间接层允许CEPH的动态平衡。下图描述了CRUSH如何映射对象至配置组,配置组至OSD。

     利用CRUSH映射和CRUSH算法的副本,客户端可以在读出或写入一个特定的对象时准确地计算OSD。

计算PG的IDS

     当Ceph的客户端绑定到一个CEPH监视器,它会撷取群集映射最新副本 。集群映射内,显示器的OSD和元数据服务器集群中的所有被客户端知道,但是,它不知道任何有关对象的位置。

            通过计算得到的对象位置

     客户端唯一所需要的输入的是对象ID和池。原因很简单:Ceph的数据存储在被命名的池(例如,“liverpool”)。当一个客户端想存储命名的对 象(例如,“john”,“paul”,“george”,“ringo”,等等),使用对象名,一个哈希数的OSD集群和池名称计算出配置组。Ceph 的客户端使用下列步骤来计算PG的ID。

1.客户端输入池ID和对象ID。(例如,池=“liverpool”和对象ID =“john”) 
2.CRUSH取得的对象ID和散列它。
3.CRUSH计算散列模数的OSD。(例如,0x58)得到一个PG的ID。
4.CRUSH得到池ID池的名称(如“liverpool”= 4)
5.CRUSH预先考虑到PG ID对应池ID(例如,4.0x58)。

      计算对象的位置的速度远远超过非正式会话执行对象的位置查询。CRUSH算法允许客户端计算对象存储,使客户端能够联系主OSD存储或检索对象。

对等操作和集

    在前面的章节中,我们注意到,Ceph的OSD守护程序检查彼此的心跳和报告至Ceph的监视器。Ceph的OSD守护程序做的另一件事被称为“对等操 作”,这是将存储所有的OSD存储布局组(PG)与所有对象(和它们的元数据)PG状态保持一致的过程。事实上,Ceph的OSD守护进程向Ceph的监 控器报告对等操作失败。对等操作的问题通常会自行解决,但是,如果问题仍然存在,您可能需要参考“Troubleshooting Peering Failure ”部分。

注意:一致的状态并不意味着PG的最新内容。

Ceph的存储群集被设计用来存储至少一个对象的两个副本(即,大小 = 2),这是最低的数据安全性的要求。对于高可用性,Ceph的存储集群存储一个对象要(例如,大小=3和最小尺寸=2)两份以上的副本,以便它可以继续运 行在 degraded状态,同时保持数据的安全性。

    参考“”,我们不明确地命名Ceph的OSD守护进程(例如,osd.0 osd.1等),而是称他们为初级,中级,等等。按照惯例,主要是第一OSD中的激活的设置,并负责协调每个配置组,它作为主要的对等过程,并且是唯一的OSD将接受客户端发起的写为对象给定的位置,它作为主要活动组。

    当一个系列的OSD负责一个配置组,该系列的OSD,我们参考他们作为激活设置。一个激活设置可参考Ceph的OSD守护进程,目前负责配置组,或Ceph的的OSD守护,负责为特定的一些特别的现阶段配置组。

    Ceph的OSD守护程序的一部分的代理设置可能并不总是up 。当在代理设置的OSD为up,它是up集的一部分 。up集是一个重要的特质,因为当一个OSD失败时,Ceph能再交换PG到其他Ceph OSD守护。

   注意:在一个PG包含osd.25,osd.32和osd.61,第一个OSD,osd25,是主要的。如果那个OSD失败了,第二个,osd32,成为主要的,并且osd.25将会被移除UP集

重新平衡

     当你添加一个CEPH的OSD守护进程到CEPH的存储集群,集群映射使用新的OSD得到更新。查看“计算PG的IDS”相关文档,这改变了集群映射。 因此,它改变对了象的位置,因为它改变了一个计算的输入。下图描绘平衡过程(尽管相当粗暴,因为它的影响力大大低于大型集群),其中一些,但不是所有的 PG从现有的OSD(OSD和OSD2)迁移到新的OSD(OSD3)。即使重新平衡,CRUSH是稳定的。许多配置组仍然在原来的配置,每个OSD得到 一些额外的容量,所以在新的OSD上在重新平衡是完成后没有新的负载峰值。

数据一致性

       作为保持数据的一致性和清理的一部分,Ceph的OSD也可以清除配置组内的对象。也就是说,Ceph的OSD可以比较放置在一个组对象元数据存储与在其 他的OSD布置组及其副本。清理(通常每天执行)捕获OSD的错误或文件系统错误。OSD还可以通过比较对象中的数据比特位进行更深层次的清理。深度清理 (通常每周执行)可以发现在平时清理中不会被发现的磁盘上的坏扇区。

    请参阅 “Data Scrubbing ”获取详细配置清理的信息。

 扩展CEPH

   

     你可以通过创建共享被称为“Ceph类”的对象类扩展Ceph。Ceph加载动态存储在 osd class dir目录(比如,默认的$libdir/rados-classes)的 .so类。当你使用一个类时,你可以创建新的有能力在Ceph对象存储中调用Ceph的本地方法的对象方法,或者使用libraries 使其他包含在自己库中的或自己创建的类的方法。

     在写入上,Ceph的类可以调用本地或类方法,执行入站数据的任何系列的操作,并产生一个写入操作结果的能被Ceph自动接收的事务。

     在读取上,Ceph的类可以调用本地或类方法,执行出站数据的任何系列的操作,并将数据返回到客户端。

CEPH的协议

   

     Ceph的客户端使用本机协议交互与Ceph的存储集群。Ceph的打包此功能到librados库,这样就可以创建自己的自定义Ceph的客户端。下图描绘了基本架构。

本地协议和LIBRADOS

     现代应用程序需要与异步通信能力的一个简单的对象存储接口。CEPH的存储集群,提供了一个简单的对象存储接口,异步通信的能力。该接口提供了直接,并行访问整个集群的对象。

  • 池操作
  • 快照和写时复制克隆
  • 读/写对象 - 创建或删除 - 整个对象或字节范围 - 附加或截断
  • 创建/设置/获取/删除XATTRs
  • 创建/设置/获取/删除秘钥/值
  • 复合操作和语义双ACK
  • 对象类

 

对象观察/通知

     客户端用一个对象可以注册持久的兴趣,并且保持一个会话的主节点OSD的开放状态。客户端可以发送通知消息,给有效的所有的监视器和当监视器收到通知。这使客户端可以使用任何对象同步/通信通道。 Architecture【架构】 _11

 数据分段

      存储设备有吞吐量的限制,从而影响性能和可伸缩性。因此,存储系统在跨多个存储设备往往支持连续块条带化存储信息,以提高吞吐量和性能。数据条带化的最常 见的形式是 RAID。与CEPH的条带化的RAID类型最相似的是RAID 0,或“带区卷”。CEPH的条带化提供RAID 0条带,N路可靠的RAID镜像和更快的恢复。
       

      CEPH的提供了三种客户端条带类型:CEPH的块设备,CEPH的文件系统,CEPH的对象存储。CEPH的客户端改变它的数据根据它在CEPH的存储集群提供给其用户的(块设备镜像,基于REST的对象,CEPHFS文件系统目录)至对象表示格式。

建议:存储在Ceph的存储集群的Ceph的对象都没有条带化。Ceph的对象存储,Ceph的块设备,Ceph的文件系统在多个Ceph的存储集群对象 条带化他们的数据。Ceph的客户端直接写入Ceph的存储集群通过librados必须进行条带化(和并行I/O),为自己获得这些好处。

      最简单的Ceph的条带化格式1对象涉及的条带计数。Ceph的客户端写入条带单元的Ceph的存储集群对象,直到对象是其最大容量,然后再创建另一个对 象额外的数据条带。条带化的最简单的形式可能是足够小的块设备镜像,S3或Swift对象和CephFS的文件。然而,这种简单的形式没有利用Ceph的 布置组之间分发数据的能力的最大优势,因此不会很大地改善性能。下图描述了条带化的最简单的形式:Architecture【架构】 _12

        如果预期大的镜像尺寸,大规模S3或Swift对象(如视频),或CephFS的目录,你可能会看到相当大的读/写性能方面的改进,通过客户端在多个对象 内的对象集中的数据条带化。当客户端写入到其对应的对象平行条带单位,写入性能显着提高。由于对象映射到不同的布置组,并进一步映射到不同的OSD,发生 在平行的每个写动作有最大写入速度。写入至单个磁盘会被磁头移动(例如,每寻道6ms)和一台设备(如100MB/s)的带宽限制。通过写入多个对象(映 射到不同的配置组和OSD)的传播,Ceph可以减少每个驱动器的seek的数量,结合多个驱动器的吞吐量达到更快的写(或读)的速度。

注意:条带化的是独立的对象副本。由于CRUSH经过OSD复制对象,条带自动被复制。

      在下面的图中,客户端的数据得到整个对象集(在下面的图中的object set 1)包括4个对象,其中第一条条带单元是在 object 0中的 stripe unit 0 ,第四条条带单元在object 3中的 stripe unit 3。写第四条后,客户端决定是否该对象集是完整的。如果对象集是不完整的,客户端开始再一次在第一个对象中写入一个条带(下图中的object 0)。如果该对象组是完整的,在客户端创建一个新的对象组(在下面的图中的object set 2),开始在新的对象组设置 (在下面的图中的object 4 ).中的第一个对象写入一个条带至第一个对象(stripe unit 16)。

  三个重要变量决定如何Ceph的条带数据:

  •     对象的大小:在Ceph的对象存储集群有一个最大配置大小(例如,2MB,4MB,等)。对象的大小应该足够大,以容纳许多条带单元,应该是多个条带单元。
  •     条带宽度:条带有一个可配置的单元大小(例如,64KB)。Ceph的客户端将数据将会写入到同样大小的条带单位的对象,除了最后一个条带单元。条带的宽度,应该是对象尺寸的一小部分以至于一个对象可能包含许多条带单位。
  •     条带计数: Ceph的客户端写了一系列由条带计数决定的对象序列的条带单位。一系列对象被称为对象集。在Ceph的客户端写入的对象组中的最后一个对象后,它返回的对象组中的第一个对象。


重要:在把你的群集投入生产之前测试条带化配置的性能。在你条带化数据并且把它写入对象后,你不能改变这些条带化参数。

     一旦Ceph的客户端有条带化单元的条带化数据并且映射条带化单元至对象,在对象被存储作为存储磁盘上的文件之前,Ceph的CRUSH算法映射和映射对象到配置组,并且配置组至Cep的OSD守护。

注意:由于客户端写入到一个池,条带化至对象的所有数据在同一池中映射到配置组。因此,他们使用相同的的CRUSH映射和相同的访问控制。

CEPH的客户端 

    Ceph的客户端包括一些服务接口。这些包括:

    区块装置:Ceph的块设备(又名RBD)服务提供了可调整大小,自动精简配置的块设备快照和克隆。Ceph的条带块设备跨集群的高性能。Ceph的支持两个内核对象(KO)和使用librbd直接避免为虚拟化系统的内核对象的开销QEMU虚拟机管理程序。
    对象存储:Ceph的对象存储(又名,RGW)服务提供REST风格的API接口,兼容Amazon S3和OpenStack的swift。
    文件系统:Ceph的文件系统(CephFS)服务提供了一个POSIX兼容的文件系统可安装或在用户空间(FUSE)作为文件系统

    Ceph的可以运行的其他实例的OSD的MDS和监控器,可扩展性和高可用性。下图描绘了高层次的架构。

CEPH的对象存储 

     CEPH的对象存储守护进程,RADOSGW,是一个FASTCGI的服务,提供一个RESTFUL的 HTTP API存储对象和元数据。层顶部CEPH的存储集群与自己的数据格式,并保持自己的用户数据库身份验证和访问控制。RADOS网关采用一个统一的命名空 间,这意味着你可以使用OPENSTACK的SWIFT兼容的API或亚马逊S3兼容的API。例如,你可以使用S3-COMPTABLE的一个应用程序 的API写数据,然后使用SWIFT兼容的API与其他应用程序读取数据。

     S3/Swift对象和存储群集对象比较

      Ceph的对象存储使用的术语来形容它存储的数据对象。S3和Swift对象Ceph的写入与Ceph的存储集群的对象是不一样的。Ceph的对象存储对 象映射到Ceph的存储集群对象。S3和Swift对象不一定对应于以1:1的方式存储在所述存储群集的对象。这是可能的一个S3或Swift对象映射到 多个Ceph的对象。

      有关详细信息,请参阅Ceph Object Storage。

CEPH的块设备

     一个Ceph的块设备在Ceph的存储集群中的多个对象条带化块设备镜像,其中每个对象被映射到一个配置组和被分发,配置组中的多个对象遍布整个集群。

     重要:条带化允许RBD块设备比起单台服务器能做的有更好的表现

    自动精简配置snapshottable Ceph的块设备是虚拟化和云计算的一个有吸引力的选择。在虚拟机的情况下,人们通常使用在QEMU/KVM中的rbd网络存储驱动部署Ceph的块设 备,其中主机使用librbd给客户提供一个块设备服务。许多云计算堆栈使用libvirt的整合与虚拟机管理程序。您可以使用QEMU和libvirt 的Ceph的块设备自动精简配置支持OpenStack和CloudStack其他云解决方案。

    虽然我们在这个时候不提供librbd与其他虚拟机管理程序的支持,你也可以使用Ceph的块设备内核对象提供一个块设备到客户端。其他如Xen的虚拟化技术可以访问Ceph的块设备的内核对象(次)。这是通过命令行工具RBD实现的。

CEPH的文件系统

    Ceph的文件系统(CEPH FS)提供了一个与POSIX兼容的,基于对象的,Ceph存储集群之上分层的文件系统的一种服务。Ceph的FS文件映射到Ceph存储在Ceph存储 集群的对象。Ceph的客户端挂载CephFS的文件系统作为一个内核对象,或作为一个文件系统在用户空间(FUSE)。

      Ceph的文件系统服务包括Ceph的存储集群部署Ceph的元数据服务器(MDS)。MDS的目的是高可用性的Ceph元数据的元数据服务器驻留在内存 中存储的所有文件系统元数据(目录,文件所有权,访问模式等)。使用MDS(称为ceph-mds的守护进程)的原因是简单的文件系统操作,如列出一个目 录或改变一个目录(ls,cd命令)将使Ceph的OSD负担不必要的守护进程。所以从数据的元数据分离意味着Ceph的文件系统可以提供高性能的服务不 给Ceph的存储集群增加负担。

      Ceph的FS分离元数据从数据来看,MDS中存储元数据,文件数据存储在Ceph的存储集群的一个或多个对象。Ceph的文件系统的目的是与POSIX 兼容。Cept MDS可以作为一个单一的过程中运行,或它可以分布到多个物理机器,亦或是对高可用性或可扩展性。

参照:http://blog.csdn.net/dapao123456789/article/details/24293527


阅读(6791) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~