免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: wlmqgzm
打印 上一主题 下一主题

[C++] ASIO,无锁,高并发,高可靠, 统一,网络架构,抗DOS,低端4核心服务器CPU 每秒87万QPS ECHO [复制链接]

论坛徽章:
36
子鼠
日期:2013-08-28 22:23:29黄金圣斗士
日期:2015-12-01 11:37:51程序设计版块每日发帖之星
日期:2015-12-14 06:20:00CU十四周年纪念徽章
日期:2015-12-22 16:50:40IT运维版块每日发帖之星
日期:2016-01-25 06:20:0015-16赛季CBA联赛之深圳
日期:2016-01-27 10:31:172016猴年福章徽章
日期:2016-02-18 15:30:3415-16赛季CBA联赛之福建
日期:2016-04-07 11:25:2215-16赛季CBA联赛之青岛
日期:2016-04-29 18:02:5915-16赛季CBA联赛之北控
日期:2016-06-20 17:38:50技术图书徽章
日期:2016-07-19 13:54:03程序设计版块每日发帖之星
日期:2016-08-21 06:20:00
61 [报告]
发表于 2015-10-24 17:25 |只看该作者
不过,能引出故事来才好玩,楼主还有没相关的故事,都给讲一下,提高大伙兴致

论坛徽章:
9
程序设计版块每日发帖之星
日期:2015-10-18 06:20:00程序设计版块每日发帖之星
日期:2015-11-01 06:20:00程序设计版块每日发帖之星
日期:2015-11-02 06:20:00每日论坛发贴之星
日期:2015-11-02 06:20:00程序设计版块每日发帖之星
日期:2015-11-03 06:20:00程序设计版块每日发帖之星
日期:2015-11-04 06:20:00程序设计版块每日发帖之星
日期:2015-11-06 06:20:00数据库技术版块每周发帖之星
日期:2015-12-02 15:02:47数据库技术版块每日发帖之星
日期:2015-12-08 06:20:00
62 [报告]
发表于 2015-10-25 13:44 |只看该作者
本帖最后由 wlmqgzm 于 2015-10-26 09:15 编辑

回复 44# wlmqgzm

漫谈针对"socket_handle复用"的 高可靠性解决方案.

仔细分析流程,  最终找到了更简单的解决办法, 就是其实, 在我的代码中, 所有的操作都是在ASIO的class中, ASIO已经为用户考虑并处理过了此问题, 我不需要再包装一层, 呵呵呵.

好吧, 不使用原始native_handle,  只使用ASIO的情况下, 最优的解决方案就是不用解决.

后台的管理数据的索引项, 已经全部是采用accept_time(微秒)了, 保证不会重复.

使用HASH表查找速度也快.

性能提高到32万QPS, 后台数据管理全部采用accept_time(微秒)作为主索引, 形成了唯一性, 减少了管理代码的数量, 降低了难度.
管理数据形成双索引结构, 对不同时间要求的数据使用不同的索引, 管理数据的定时器降低到了10ms, 提高了拆线的检测反应的时间,
acceptor, timer1全部用unique_ptr集中管理, 析构代码中主动提前释放, 减少管理代码复杂度,
整个系统可以更简单更安全更快速的退出, 对整体析构增加了时间追踪代码,  退出前全部连接的安全拆线流程增加到了二级(第一级是标准流程,第二级是超过某个特定时间强制退出), 对析构流程再次进行了详细的分析, 保证不留死角, 不留隐患.



   

论坛徽章:
9
程序设计版块每日发帖之星
日期:2015-10-18 06:20:00程序设计版块每日发帖之星
日期:2015-11-01 06:20:00程序设计版块每日发帖之星
日期:2015-11-02 06:20:00每日论坛发贴之星
日期:2015-11-02 06:20:00程序设计版块每日发帖之星
日期:2015-11-03 06:20:00程序设计版块每日发帖之星
日期:2015-11-04 06:20:00程序设计版块每日发帖之星
日期:2015-11-06 06:20:00数据库技术版块每周发帖之星
日期:2015-12-02 15:02:47数据库技术版块每日发帖之星
日期:2015-12-08 06:20:00
63 [报告]
发表于 2015-10-26 15:58 |只看该作者
本帖最后由 wlmqgzm 于 2015-10-26 16:23 编辑

IOS_SERVICE的调度能力: 每秒可完成280万次调度事件.

对ASIO的底层IO_SERVICE调度进行了测试,  1000万次多任务队列调用和分发执行平均只用了3.6秒,
双核心绑定一个IOS_SERVICE, 调度能力降低, 1000万次调度花了4.6秒,
单核心绑定一个IOS_SERVICE, 调度能力比较高, 1000万次调度花了2.6秒,  
总体大约平均每次调度能力是3.6X10-7秒, 每秒可完成280万次调度事件.   

因此, 目前我的代码32W QPS ECHO,  ASIO IO_SERVICE的处理能力只发挥了11%的调度能力, 后续增加CPU, 这里应该不是瓶颈,
按双核下ECHO SERVER,11%调度能力推断, 推论可知, 多CPU绑定IOS_SERVICE, 性能还可大幅度提高,
目前的ECHO SERVER单个IO_SERVICE最好不要绑定超过8核, 超过8核心以后, 55%的调度能力, 就成为主要瓶颈了,
过几天, 拿到了4核心8线程的最低端的服务器CPU以后, 会有更多的测试报告.
预期: 新CPU的处理能力将过100万QPS ECHO, 等几天吧,    

看论坛中部分帖子说, IOS_SERVICE的单个调度能力大约只有每秒15-16万, 这个说法应该是错误的. 我测试下来, 大约是每秒200万-400万的调度能力.

另外, 由于在本机测试, 测试中发现机器一半的处理能力是被测试程序ab占用了, 2者的CPU占有率基本接近, 这样分析下来, 实际的处理能力或者已经超过50万QPS.

Tasks: 210 total,   1 running, 209 sleeping,   0 stopped,   0 zombie
%Cpu(s): 37.6 us, 44.4 sy,  0.0 ni,  0.7 id,  0.0 wa,  0.0 hi, 17.2 si,  0.0 st
KiB Mem:  32866188 total, 32018836 used,   847352 free,    87688 buffers
KiB Swap:  2097148 total,        0 used,  2097148 free.   402992 cached Mem

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND   
25585 guo       20   0  320500   4464   3136 S  97.9  0.0   0:23.92 mysql1     
25650 guo       20   0  342740 243728   3420 S  97.9  0.7   0:23.85 ab     

这里的ab是测试程序, mysql1是我的程序, 名字下次改, 是把以前的一个mysql客户端程序的project拿来copy用的, 一直也没有改名字.

论坛徽章:
15
射手座
日期:2014-11-29 19:22:4915-16赛季CBA联赛之青岛
日期:2017-11-17 13:20:09黑曼巴
日期:2017-07-13 19:13:4715-16赛季CBA联赛之四川
日期:2017-02-07 21:08:572015年亚冠纪念徽章
日期:2015-11-06 12:31:58每日论坛发贴之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-07-12 22:20:002015亚冠之浦和红钻
日期:2015-07-08 10:10:132015亚冠之大阪钢巴
日期:2015-06-29 11:21:122015亚冠之广州恒大
日期:2015-05-22 21:55:412015年亚洲杯之伊朗
日期:2015-04-10 16:28:25
64 [报告]
发表于 2015-10-26 16:16 |只看该作者
本帖最后由 yulihua49 于 2015-10-26 16:19 编辑
wlmqgzm 发表于 2015-10-26 15:58
IOS_SERVICE的调度能力: 每秒可完成280万次调度事件.

对ASIO的底层IO_SERVICE调度进行了测试,  1000万次 ...

那个15万+的限制是epoll响应的限制,如果不用epoll没这个限制。
多个epoll队列(epfd)可以成倍的提高。

论坛徽章:
9
程序设计版块每日发帖之星
日期:2015-10-18 06:20:00程序设计版块每日发帖之星
日期:2015-11-01 06:20:00程序设计版块每日发帖之星
日期:2015-11-02 06:20:00每日论坛发贴之星
日期:2015-11-02 06:20:00程序设计版块每日发帖之星
日期:2015-11-03 06:20:00程序设计版块每日发帖之星
日期:2015-11-04 06:20:00程序设计版块每日发帖之星
日期:2015-11-06 06:20:00数据库技术版块每周发帖之星
日期:2015-12-02 15:02:47数据库技术版块每日发帖之星
日期:2015-12-08 06:20:00
65 [报告]
发表于 2015-10-26 18:08 |只看该作者
本帖最后由 wlmqgzm 于 2015-10-26 21:52 编辑

回复 64# yulihua49

没有仔细看ASIO的原代码, 不过根据资料介绍, BOOST ASIO底层还是封装的 SELECT /EPOLL这些,  它自己也是建立在别的组件上的.

目前我的代码实测 每秒32万QPS ECHO, 其中每个QPS等效一个收epoll和一个发epoll, 大约每秒等效64万epoll qps, 不太清楚Boost ASIO的底层是怎么做到的.

因为现在我的代码中read_handle, write_handle全部是绑定在一个多线程io_service上的, 没有做区分.

-------------------------------------------------------------------------------------------------------------------------------------------------
从本贴开贴以来, 基本内部测试完毕了ECHO SERVER,

全部测试代码, 和废弃代码, 以及修改调试代码总量大约5000行(我的习惯,所有废弃或者修改代码前粘贴放到一个专用文件中, 以便回查),

所有自己认为可能是瓶颈的地方, 然后改进代码, 我觉得可以暂时告一段落了.  已经找不到任何值得优化的地方了.  目前的CPU条件下, 32万QPS ECHO, 就是极限了

主要的代码全部是C++构件, 经过清理, 今天最终入库的清洁代码,

(最终还是去掉了spsc lock-free queue, 因为Boost io_service处理能力足够强, 非瓶颈, 改用io_service.post, 减少代码量 )

1)class Asio_tcp_server构件全部代码, 1300行.

2) class Asio_thread_pool构件全部代码, 130行.

3) 公用组件error_message等小c语言函数库  342行

全部ECHO SERVER代码总量1800行. 编译后大小:211.56Kbyte.  体积非常小.

该ECHO SERVER与别的代码差别最大的一个功能点是: 支持抗DOS, 内置数据结构, 可以高效查询, 针对单个IP限制并发socket数量, 效率非常高, 完全不会拖慢正常的业务流程.
  

论坛徽章:
9
程序设计版块每日发帖之星
日期:2015-10-18 06:20:00程序设计版块每日发帖之星
日期:2015-11-01 06:20:00程序设计版块每日发帖之星
日期:2015-11-02 06:20:00每日论坛发贴之星
日期:2015-11-02 06:20:00程序设计版块每日发帖之星
日期:2015-11-03 06:20:00程序设计版块每日发帖之星
日期:2015-11-04 06:20:00程序设计版块每日发帖之星
日期:2015-11-06 06:20:00数据库技术版块每周发帖之星
日期:2015-12-02 15:02:47数据库技术版块每日发帖之星
日期:2015-12-08 06:20:00
66 [报告]
发表于 2015-10-26 21:33 |只看该作者
本帖最后由 wlmqgzm 于 2015-10-26 21:53 编辑

后续重点

第一步: 做 "安全检测层"的代码和测试, 这个东西蛮有意思的....   

前面57楼的故事"TCP/IP校验不足造成的黑客入侵事件", 采用什么样的校验数据结构, 可以避免此事件的发生???  
传说即使是大拿很多的Google内部早期某系统也曾经遇到过类似的情况,    
现在正在设计帧结构, 害怕自己不能够一次性考虑周全.  唉, 又缺乏资料. 第一次做................很惨的样子...........


第二步:  就是测试做一个准同步内存数据库, 类似简化的REDIS或者Memcache一样高速数据缓冲层类似的东西, 但是要比他们更简单些, 不需要更新数据,

说白了就是一个全内存数据库,  架构的难点就是数据的同步, 有再同步机制.

初步的架构思路已经完成, 计划做到与MYSQL数据库准同步, 同步周期大约在1-2秒左右的误差, 就是说准同步系统. 该内存数据库基本没有自己的命令集, 全部数据来自MYSQL, 没有自己的硬盘等存储, 是一个开销小, 性能超强的全新架构.

同时, 由于是准同步, MYSQL基本没有开销, 不会拖累MYSQL的运行, 比目前的MYSQL主从同步机制要节约很多, 不增加IO,  是一个高性能的内存数据库, 用户只能查询, 不能修改, 修改数据直接改MYSQL, 数据同步于MYSQL, 这个就是MYSQL的内存镜像伴侣,  然后, 就是评测性能等.  改进等...... 这个好难的, 唉, 慢慢做吧. 千万不能丧失勇气..

我从未做过数据库架构, 这也是第一次. 先做简单的内存数据库吧.

第三步其实也有了一点思路, 就是准同步内存数据库集群, 这个更难的, 看第2步的效果, 先做单机, 如果设计能够达标的话...

论坛徽章:
9
程序设计版块每日发帖之星
日期:2015-10-18 06:20:00程序设计版块每日发帖之星
日期:2015-11-01 06:20:00程序设计版块每日发帖之星
日期:2015-11-02 06:20:00每日论坛发贴之星
日期:2015-11-02 06:20:00程序设计版块每日发帖之星
日期:2015-11-03 06:20:00程序设计版块每日发帖之星
日期:2015-11-04 06:20:00程序设计版块每日发帖之星
日期:2015-11-06 06:20:00数据库技术版块每周发帖之星
日期:2015-12-02 15:02:47数据库技术版块每日发帖之星
日期:2015-12-08 06:20:00
67 [报告]
发表于 2015-10-26 22:02 |只看该作者
本帖最后由 wlmqgzm 于 2015-10-27 12:09 编辑

正在进行网络自修复协议栈的设计,  初步计划使用32字节做协议栈, 数据头, 数据尾, 以及各类校验, 长度, 定义等.

协议栈内部的数据切分为一个完整数据包, 数据包长度4字节表示, 这样, 再上层协议将得到一个数据包, 而不是数据流.

//  数据头20字节,  数据中4字节, 数据尾8字节, 一共是32字节开销,  其中使用了3个校验码,  12字节, 最终做到每个字节都有2次32位不相关校验,  
//  本代码做到了10-19次方的错误检出率
//  加上TCP的16位检测,总共是10-23次方的错误检出率

先放出来2个控制字节的定义:  每个比特如果为0, 表示未定义, 控制字节是最底层的控制码流, 携带在消息包上, 要考虑所有人的通用需求.

* bit_char  define  这个是通用字节  */
// 定义是  一个请求消息
#define char1_bit_ask                          ( 1 << 0 )

//定义是 一个响应消息
#define char1_bit_response                 ( 1 << 1 )

// 定义是 小字节序,
#define char1_bit_little_endian         ( 1 << 2 )

// 定义是 大字节序,
#define char1_bit_big_endian                ( 1 << 3 )

// 定义是  对于该类型(该版本)的消息长度固定, 即消息解包后, 全部是始终固定长度的变量
#define char1_bit_length_fix              ( 1 << 4 )

// 定义是  对于该类型(该版本)的消息长度可变, 即消息解包后存在可变数组等非固定长度变量
#define char1_bit_length_variable    ( 1 << 5 )

// 定义是  下一个消息包的序列号是连续的, 不可跳跃的
#define  char1_bit_next_continue     ( 1 << 6 )

// 定义是  需要 收到确认消息,  
#define  char1_bit_need_receive_ack   ( 1 << 7 )

=================================================================
//定义第2个字节 主要用于回复
// 定义是  请求重发
#define char2_bit_resend     ( 1 << 0  )

// 定义 原因是 出错
#define char2_bit_find_error     ( 1 << 1  )

// 定义 请求 重连
#define char2_bit_ask_close      ( 1 << 2  )



控制字节, 还在仔细设计中, 先放出来这些, 后面再根据情况做增补.

对于, 上一层软件, 这一层提供了数据高可靠性, 超高的性能, 数据包完整, 不需要考虑网络错误,断线,自动校验, 自动重连, 自动重发等等问题.

不会有收到半个数据包的情况, 不会有网络错误存在, 不会丢失1个字节. 简化了高层的设计.

然后, 在这个层次以后, 是Google protobuff或者faltbuff, 也支持直接struct读写, 实现最高性能, 后续的东西以后再谈, 呵呵呵

论坛徽章:
9
程序设计版块每日发帖之星
日期:2015-10-18 06:20:00程序设计版块每日发帖之星
日期:2015-11-01 06:20:00程序设计版块每日发帖之星
日期:2015-11-02 06:20:00每日论坛发贴之星
日期:2015-11-02 06:20:00程序设计版块每日发帖之星
日期:2015-11-03 06:20:00程序设计版块每日发帖之星
日期:2015-11-04 06:20:00程序设计版块每日发帖之星
日期:2015-11-06 06:20:00数据库技术版块每周发帖之星
日期:2015-12-02 15:02:47数据库技术版块每日发帖之星
日期:2015-12-08 06:20:00
68 [报告]
发表于 2015-10-26 22:39 |只看该作者
本帖最后由 wlmqgzm 于 2015-10-27 15:46 编辑

网络自修复协议栈的设计, 第一次设计这种协议栈, 好惨啊.....  刚开始做, 没有任何参考资料,   可能考虑不够周全, 先放出来, 在做代码中会不断修改      

目前, 总共已经定义了总长度为 32字节的各类控制码,校验码,  数量有些过多, 后续会想办法减少一些字节, 提高性能.

// head 是固定长度,便于读取和分析.
struct  message_head
{
  //数据头连校验码一共使用了20个字节, 头四个字节, 很多游戏公司的结构中都省略了, 我这里先多设计一些, 最后, 还要砍掉一些
  unsigned char bitchar1;       //  按照字节定义很多参数, 便于后续处理
  unsigned char bitchar2;      // 按照字节定义很多参数, 便于后续处理, 主要是用于回复
  unsigned char bitchar3;       //  备用
  unsigned char codec_type;     // 数据编码类型 0 未定义,  1 struct copy, 2 user define  3 . boost serialized 4.   google protobuf,  5 Google FlatBuffers  .......
  unsigned short message_number;   // 连接内部序列号, 循环使用, 发送端按顺序使用  2字节, 序列号很重要, 可以一次性发送多条数据,并且查询可以在一条连接上并发进行, 返回结果也是异步的, 适合多线进程的处理.
unsigned short ack_message_number;   // 接收最大确认序列号,
  unsigned int   message_type;   //  消息类型, 4字节
  unsigned short message_data_segment  //  数据子段编号, 从0开始, 这样把大数据拆分为不大于64Kbyte的小段, 分段转发
  unsigned short message_data_length;  //  数据长度,2字节
  unsigned int   crc32c;   // 数据头的校验码, 4字节
}

// 数据
struct message_data
{
  char data[];
  unsigned int crc32c;  // 4字节校验码
}

//  数据尾一共是8字节
struct message_tail
{
   unsigned int crc32c;     //  整体的crc32c校验码
   //  整体的crc32c校验码,   先crc32c(4字节同步码), 接着再crc32c(message_head)(含校验码) 再crc32(message_data)(含校验码);
   //  这里crc32(4字节同步码), 起到给一个非零的初值作用,  不能少这一步,  否则对head的再校验就无意义, 没有起到增强错误检出率的作用
   char sync_code[]="0123";  // 4字节同步码,   数据对齐专用
}

论坛徽章:
9
程序设计版块每日发帖之星
日期:2015-10-18 06:20:00程序设计版块每日发帖之星
日期:2015-11-01 06:20:00程序设计版块每日发帖之星
日期:2015-11-02 06:20:00每日论坛发贴之星
日期:2015-11-02 06:20:00程序设计版块每日发帖之星
日期:2015-11-03 06:20:00程序设计版块每日发帖之星
日期:2015-11-04 06:20:00程序设计版块每日发帖之星
日期:2015-11-06 06:20:00数据库技术版块每周发帖之星
日期:2015-12-02 15:02:47数据库技术版块每日发帖之星
日期:2015-12-08 06:20:00
69 [报告]
发表于 2015-10-27 09:38 |只看该作者
本帖最后由 wlmqgzm 于 2015-10-27 12:10 编辑

回复 61# cokeboL

故事倒是挺多的, 各类IT人的悲惨故事,  都是在实践中碰到的问题, 五花八门, 无奇不有. 要是光讲故事的话, 真的是说几天都说不完, 太多了.   还是做代码第一.  

有些是友商, 有些是自己人, 有些是业内传闻,   总之, 搞IT都不容易.

好多故事平时倒想不起来,  做到相关代码或者相关事情的时候,  一下子就全想起来了, 算给自己一个提醒, 还有就是该如何做某类产品的架构.
   

论坛徽章:
9
程序设计版块每日发帖之星
日期:2015-10-18 06:20:00程序设计版块每日发帖之星
日期:2015-11-01 06:20:00程序设计版块每日发帖之星
日期:2015-11-02 06:20:00每日论坛发贴之星
日期:2015-11-02 06:20:00程序设计版块每日发帖之星
日期:2015-11-03 06:20:00程序设计版块每日发帖之星
日期:2015-11-04 06:20:00程序设计版块每日发帖之星
日期:2015-11-06 06:20:00数据库技术版块每周发帖之星
日期:2015-12-02 15:02:47数据库技术版块每日发帖之星
日期:2015-12-08 06:20:00
70 [报告]
发表于 2015-10-27 10:05 |只看该作者
本帖最后由 wlmqgzm 于 2015-10-27 12:20 编辑

这个算是大数据的底层架构之一:  网络错误自修复统一协议栈, 这一层是Google一直没有开源的一层架构.

正在  自修复协议栈的开发, 正在做代码中. 这一层提供给应用层一个高可靠全透明的网络环境, 数据的读写结构是struct, 最终目标是访问远端数据跟访问本地共享内存中的一样简单可靠.

自修复协议栈的设计看上去很简单, 似乎怎么定义都可以,

协议栈的核心就是定义TLVV: type, length, value, verify. 最后还有一个可选项control.  其中, 做代码的时候, 最难的部分是control, 这个是底部错误流程的体现,

其实, 这个层多数游戏公司也都有做类似的东西. 各类网络接口, 都有类似的东西,

就是只有大公司有统一架构, 其他部门直接调用库就可以了, 不需要考虑底层的东西. 过滤掉全部错误处理.

里面的门道很多的. 由于是底层库, IO层, 效率要求高, 可靠性要求高, 对应用层来说, 没有什么错误可见,  这层是一个高可靠的透明的东西, 自动重发,自动重连,自动数据校正, 跟访问本地内存的可靠性一样高.

所有的数据都跟UDP一样, 有完整性, 应用层收发的结构不是数据流, 是struct.  

这一层协议栈控制字节如果有流控设计, 下一层使用UDP也是可以的.

设计上要注意的地方也多,  先说4个点:

1)校验码的位置有讲究: 校验码要放在数据的结尾, 中间任何一Byte字节丢失后, 校验码由于被移位的原因, 一定会被检出.  放在前面, 对于丢字节的情况, 存在一定概率未被检出.

2)同步码很重要; 很多人不设计同步码的. 其实, 同步码长度要求不高, 允许与数据重复, 只有同步出错才用到. 找同步的时候, 结合校验码, 就跳过了疑似同步码, 对于单个数据包被破坏, 只要有同步头在, 最多丢弃这个包, 后续的数据包都是完整的. 再同步是相当的容易. 同步头一般放到最后或者最前, 个人倾向放到最后.

3)控制字节的位置重要: 一般要放到最前方的字节,出错概率最小.单字节无大小序, 对于后面的处理方便.
控制字节最终决定控制流程, 统一架构的设计主要在这里体现, 大公司里一般非做此层库的, 一般不接触此控制字节的内容, 因为这些对上层是透明的, 看不到.

4)校验字节的校验方法很重要: 校验方法有很多, 为了可靠, 每个字节的32位校验+不支持情况下Boost crcr32c软件校验, 至少要有2次非相关的校验, 带来64位校验的效果, 只有2倍的处理复杂度, 提高到64位校验的精确度. 校验方法尽量采用硬件校验, 目前采用的是intel CPU自带的SSE4.2指令校验, 校验方法是crc32c, 校验速度基本是内存瓶颈.   标准的64位校验性能比较低.
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP