深蓝色心情

过来聊聊~~~~

  BlogJava :: 首页 :: 联系 :: 聚合  :: 管理
  31 Posts :: 0 Stories :: 46 Comments :: 0 Trackbacks

#

guzz 1.2.9 build20110511 更新介绍: 

主要更新: 

本次更新主要是解决一些bug,和调整一些设计不合理的地方。 

同时感谢 高山流水 同学,提供了Maven的配置方式。maven配置方式:http://code.google.com/p/guzz/wiki/TutorialRuntime 

计数失败回调服务 
我们用一个例子来说明。在博客系统中,经常看到博文归档。也就是对老文章,首页只把曾经发表过文章的月份列出来,网友如果要查看,就点击月份来看这个月的文章列表。一般显示为“2009年7月(3篇);2007年4月(50篇)”之类的。现在我们要讨论的是,这个功能是如何实现的?最简单的办法,按照时间count group查询。 

但对于大点的博客系统,为了提高性能,一般不会每次都用group查询,实时算出月份和文章数的统计列表。更一般的做法是,创建一个归档表,按照userId-年月-文章数记录每个月的文章发表数,每发表一篇,更新一下计数。显示时,直接单条件查询此表即可。 

但这种做法,程序设计会比较复杂。每次更新时,都要先检查这个月的记录是否存在,如果存在就更新,如果不存在就先创建再更新。而且还带来了一个性能优化问题,复杂的逻辑使得计数操作无法批量处理。如果这类情况比较多,而且混合很多其他的计数,如文章评论数,新评论数,留言数,访问次数等等,在计数处理方面的设计就会非常复杂。 

“计数失败回调服务”就是用来解决这类问题的。这个服务是guzz先前发布的计数器服务的补充。计数器服务允许程序同时对多个计数操作进行高性能更新,而“计数失败回调服务”允许计数表不需要提前生成计数项的记录,在第一次计数更新时,如果计数记录不存在,可以获得回调通知,临时创建。 

例如上面说的文章归档,也只需要按照计数器服务调用一个方法记录下操作。在计数服务服务器端,实现“计数失败回调服务”。在执行更新时,如果计数服务发现要更新的记录不存在,会自动回调“计数失败回调服务”,程序临时创建即可。这使得程序设计既简单,同时又获得事务批量提交的性能优化,减少数据库的压力。 

更多介绍请参看:http://code.google.com/p/guzz/wiki/AppendCoreService?wl=zh-Hans 


其他主要更新: 
1. 增加ExecuteService服务,使得多个异步调用服务可以共享同一个线程池。 

2. 将Demon线程的检测更改为按照Thread.isDemon()判定。新版本中,只要线程为demon,不再需要线程名称必须包含特定开头字符串,即应用ignoreDemonThreadSQL的sql输出配置。 

3. 修复了发现的bug。 

4. 发布方式上,默认将源代码放到了guzz.jar中。如果不需要源代码放入,选择thin目录下class和source分开的guzz.jar包。 

什么是guzz? 

guzz是一套用来解决ORM、多数据源管理、以及通用数据计算的数据层框架,为系统在数据层的设计提供一站式解决方案。guzz可以看作是 ibatis/hibernate的一大补充和延伸,并可以取代这2个东西。 

guzz主要功能与特点: 
  • 现代大规模系统设计,技术上吸收了ibatis/hibernate的优点
  • 对于大部分场景,支持像hibernate一样的对象持久、映射和方便的增删改查,提高开发效率
  • 对于复杂场景,支持像ibatis一样,让DBA参与SQL设计的复杂数据库操作和优化,以及SQL在线调试
  • 更简洁、更好用、更容易控制的批操作接口
  • 支持在线加载与调试SQL。按照应用策略,从文件/数据库/Web Service等途径,动态提取与使用SQL语句(Dynamic SQL)
  • 支持应用程序使用大量的数据库和主从读写分离
  • 支持数据库表在多组机器间水平分布(Shard),并自动维护多组机器之间的分布式事务
  • 支持1张表按照业务规则分切成多张小表(Shadow),并支持每张小表拥有自己特殊的属性字段(Custom)
  • 支持1张大表分切后的小表,分布到不同的数据库中(VirtualDB)
  • 支持超越范式的特殊关联、非结构化数据等异构资源POJO模式的统一读取
  • 支持组件化服务(SOA)和服务相互依赖,构建企业/项目实施基础平台
  • 提供面向对象的数据库读取标签(JSP Taglib),加快页面展示层的快速变更、开发与部署
  • 支持配置管理服务器,可以使用一套软件系统对所有应用程序的配置进行统一管理
项目地址:http://code.google.com/p/guzz/ 
文档:http://code.google.com/p/guzz/wiki/WikiHomePage?tm=6 
下载:http://code.google.com/p/guzz/downloads/list 

posted @ 2011-05-12 17:27 深蓝色心情 阅读(1403) | 评论 (0)编辑 收藏

     摘要: 《手把手,教你编写1个可以并行运行在5台数据库上的留言板》

前言:

对于大规模系统而言,最复杂,往往也是最大的性能瓶颈,主要都产生在数据层。对于大型系统数据层的设计,主要包括缓存系统和数据库的可扩展性两方面。缓存系统比较简单,网上讨论的也比较多,方案也相对成熟,一般来说只要部署一大堆memcached之类的缓存服务器就可以解决了,扩展性也好;但对于可扩展的数据库层架构设计,通用方案较少,网上资料更是寥寥无几。

这也有情可原,现在的主流通用数据库框架,如hibernate和ibatis基本上都只支持1个系统运行在1台数据库上。对应的,基于这些框架的系统,也基本上只能运行在单台数据库上了,框架对数据库扩展性的支持几乎没有,开发者也只能被迫接受。

这篇文档,主要补充“重要”却被主流遗失的“数据库层可扩展”架构设计,让你的系统在“需要”时,可以随时通过增加机器就能最简单的解决数据库的性能瓶颈。   阅读全文
posted @ 2011-03-29 17:23 深蓝色心情 阅读(2338) | 评论 (0)编辑 收藏

今天,经过一个多月的线上运行,我们很荣幸的发布guzz 1.2.9分布式切表功能。分布式切表是指将一张大表分切成N张小表,并将这些小表储存到不同的数据库(机器)中,从而实现数据的分散存储和分散查询。 

对于大型系统和数据规模较大的系统,分布式切表提供了非常好的解决方案,有效的解决了大数据分散存储、查询、归档和维护等诸多的问题。但市面上流行的数据层框架,对于此特性几乎无人涉及。guzz首次将这种技术做成了通用框架级别,更全面的提供“一站式数据层解决方案”。 

guzz 1.2.9 build20110209 更新介绍: 

分布式切表: 

guzz特性。 

分布式切表以guzz的Shadow Table为基础。在Shadow Table的基础上,通过配置完成,应用不需要修改现有代码即可完成小表的分布式存储。具体请参看:http://code.google.com/p/guzz/wiki/TutorialVirtualDB?wl=zh-Hans 

至此,guzz已经通过6个层面完成了全面的数据分切支持: 


支持记录SQL执行时间: 

在打印执行的SQL和SQL参数的同时,通过 调试服务(DebugService) 两个新的参数允许打印出sql执行所花费的时间,并且允许控制只打印执行时间超过一定时长的sql语句。时间单位为纳秒。 

具体请参看:http://code.google.com/p/guzz/wiki/AppendCoreService?wl=zh-Hans 

支持hbm.xml的package属性: 

支持配置hbm.xml的类名时,指定package。用于支持某些hibernate工具自动生成的配置文件。 

其他: 

1. 更改LogService为InsertQueueService; 

2. 修复了几个bug。 

什么是guzz? 

guzz是一套用来解决ORM、多数据源管理、以及通用数据计算的数据层框架,为系统在数据层的设计提供一站式解决方案。guzz可以看作是 ibatis/hibernate的一大补充和延伸,并可以取代这2个东西。 

guzz主要功能与特点: 
  • 现代大规模系统设计,技术上吸收了ibatis/hibernate的优点
  • 对于大部分场景,支持像hibernate一样的对象持久、映射和方便的增删改查,提高开发效率
  • 对于复杂场景,支持像ibatis一样,让DBA参与SQL设计的复杂数据库操作和优化,以及SQL在线调试
  • 更简洁、更好用、更容易控制的批操作接口
  • 支持在线加载与调试SQL。按照应用策略,从文件/数据库/Web Service等途径,动态提取与使用SQL语句(Dynamic SQL)
  • 支持应用程序使用大量的数据库和主从读写分离
  • 支持数据库表在多组机器间水平分布(Shard),并自动维护多组机器之间的分布式事务
  • 支持1张表按照业务规则分切成多张小表(Shadow),并支持每张小表拥有自己特殊的属性字段(Custom)
  • 支持1张大表分切后的小表,分布到不同的数据库中(VirtualDB)
  • 支持超越范式的特殊关联、非结构化数据等异构资源POJO模式的统一读取
  • 支持组件化服务(SOA)和服务相互依赖,构建企业/项目实施基础平台
  • 提供面向对象的数据库读取标签(JSP Taglib),加快页面展示层的快速变更、开发与部署
  • 支持配置管理服务器,可以使用一套软件系统对所有应用程序的配置进行统一管理
项目地址:http://code.google.com/p/guzz/ 
文档:http://code.google.com/p/guzz/wiki/WikiHomePage?tm=6 
下载:http://code.google.com/p/guzz/downloads/list 

下一个build更新计划: 

  • 做什么哪?开源一个云服务项目?
  • 辅助诊断类功能?

posted @ 2011-02-10 15:31 深蓝色心情 阅读(1997) | 评论 (0)编辑 收藏

     摘要: 100%原创功能,目前尚未发现有任何框架实现到这种级别的大规模系统设计要求特性。

设计与使用方便,几乎为外挂式,不需要更改现有系统代码。  阅读全文
posted @ 2011-01-18 20:38 深蓝色心情 阅读(1741) | 评论 (0)编辑 收藏

GuzzServices的PHP客户端实现,已经实现了:IP反查,敏感词审查,以及从html代码中抽取纯文本和图片。

需要php服务器支持json,配置方式:http://php.net/manual/en/book.json.php

客户端的使用方式请参看examples.php中的例子。

php客户端下载


posted @ 2010-12-26 21:09 深蓝色心情 阅读(1503) | 评论 (0)编辑 收藏

guzz是一套用来解决ORM、多数据源管理、以及通用数据计算的数据层框架,为系统在数据层的设计提供一站式解决方案。guzz可以看作是 ibatis/hibernate的一大的延伸,并可以取代这2个东西。 

guzz主要功能与特点: 
  • 现代大规模系统设计,技术上吸收了ibatis/hibernate的优点
  • 支持像hibernate一样的对象化持久、映射和方便的增删改查
  • 支持像ibatis一样,让dba参与sql设计的复杂数据库操作和优化
  • 支持在线加载与调试SQL。按照应用策略,从文件/数据库/Web Service等途径,动态提取与使用SQL语句(Dynamic SQL)
  • 支持应用程序使用大量的数据库和主从读写分离
  • 支持超越范式的特殊关联、非结构化数据等异构资源的统一管理
  • 支持数据表在多组机器间水平分布(Shard),并自动维护多组机器之间的分布式事务
  • 支持1张表按照业务规则分切成多张小表(Shadow),并支持每张小表拥有自己特殊的属性字段(Custom)
  • 支持组件化服务(Service),以及服务间依赖,帮助构建企业/项目实施基础平台
  • 提供面向对象的数据库读取标签(JSP Taglib),加快页面展示层的快速变更、开发与部署
  • 支持配置管理服务器,可以使用一套软件系统对所有应用程序的配置进行统一管理
项目地址:http://code.google.com/p/guzz/ 
文档:http://code.google.com/p/guzz/wiki/WikiHomePage?tm=6 
下载:http://code.google.com/p/guzz/downloads/list 

guzz 1.2.9 build20101021 更新介绍: 

增强服务,支持服务间相互依赖 

服务在配置时,通过dependsOn属性设置依赖的服务,guzz进行IOC注入。例如您将一套通信协议设计成一个通信服务,当其他服务需要进行通信时,直接依赖通信服务完成远程调用或数据传送。 

为了说明服务的价值与使用方式,guzz设计了一些常用的基础服务,供测试或者直接使用。使用时,一般只需要几行代码,就可以完成本来的一个大模块。限于篇幅,请参看:http://www.guzzservices.com/category/developer-guide/ 

guzzservices.com中目前提供的服务包括:可以主动推送修改后配置项的系统配置管理,敏感词管理与文字过滤服务,以及通过IP查询地理位置服务。后续还将增加一些。试一下,就能发现guzz服务带来的开发与维护优势。 

服务以及注入文档:http://code.google.com/p/guzz/wiki/TutorialService?wl=zh-Hans#配置服务: 

新增random主键生成器(原创): 

random主键用于解决guid和uuid产生的主键在较短时间内比较类似,虽然不会重复,但容易被猜出来的问题。对于某些应用场景,如对外API的key,需要确保无法被猜出,这时就需要random主键策略。 

random主键生成一段随机字符串,由数字和小写字母组成。随机串长度默认为32,可以通过length属性进行调整。 

其他: 

1. 修复了一些bug; 

2. 完成英文版文档翻译。 

下一个build更新计划: 

  • 支持将一张大表分切到多台机器上。
  • 其他
posted @ 2010-10-25 08:17 深蓝色心情 阅读(1315) | 评论 (0)编辑 收藏

服务已经切换至guzzservices.com,并更改了API。请使用新的接口,具体参看:http://www.guzzservices.com/2010/man_ip_service/

使用时,需要将guzz升级到1.2.9以及以上版本。

如果您已经在使用,请尽快切换。新的地址应该不会在变化。非常抱歉进行了服务变化。


posted @ 2010-10-21 20:08 深蓝色心情 阅读(1575) | 评论 (2)编辑 收藏

最近讨论db shard的帖子比较多,感觉很多都是在参考hibernate shard的思路,但hibernate分表真的那么好吗?我觉得它最少有2个问题: 

1. 改成shard后,代码的API调用要变。代码改动很大。 
2. 设计很复杂,不清晰,逻辑关系难以理解。 

hibernate shard基本上就是为了shard而对hibernate做的增增补补,凑合用还行,根本不具备设计上的参考价值。 

对数据库分切方面,到目前为止,我觉得还是guzz的设计最清晰,如果我说的不对,欢迎理性讨论。不管您是否使用guzz,但是guzz在数据库分切方面的设计,对于清晰的设计模式,比hibernate shard更具有借鉴意义。 

guzz垂直切分 

垂直切分是指将不同的表分别存储到不同的数据库中。guzz默认配置级支持,不需要写任何代码,可以在任何时候,在需要时,将每张表存储到自己单独的一组服务器上,应该说是垂直分切的极限了。而且设计上,无论什么时候怎么分切,都不需要你改动代码。开发时你可以让所有表在一个库上;部署时,分到多个库上;以后业务增加了,再更加分散的放。 

垂直分切简单配置方式: 

1. 声明你要用多少台数据库,数据库之间什么关系。 

Xml代码 
  1. <dialect class="org.guzz.dialect.H2Dialect"></dialect>  
  2. <dialect name="mysql5dialect" class="org.guzz.dialect.Mysql5Dialect" />  
  3. <dialect name="oracle10gdialect" class="org.guzz.dialect.Oracle10gDialect" />  
  4.   
  5. <tran>  
  6.         <dbgroup name="default" masterDBConfigName="masterDB" />  
  7.         <dbgroup name="mysql" masterDBConfigName="masterDB" slaveDBConfigName="mysqlSlaveDB" dialectName="mysql5dialect" />  
  8.         <dbgroup name="oracle" masterDBConfigName="oracleDB" dialectName="oracle10gdialect" />  
  9. </tran>   

这里我们声明了3组数据库,而且数据库类型还不一样。 

2. 对每张表,配置应该存储到那个库里 

Xml代码 
  1. <a-business dbgroup="default" name="filterWord" class="com.guzzservices.business.FilterWord" />  
  2. <a-business dbgroup="mysql" name="filterWordGroup" class="com.guzzservices.business.FilterWordGroup" />  
  3. <a-business dbgroup="oracle" name="configuration" class="com.guzzservices.business.Configuration" />  

简单的配置,将三个对象分别存储到3台不同的数据库中,完成垂直分切。 

guzz水平切表 

水平切表是指将一张大表,分切成许多小表。guzz的设计是当需要水平分表时,原先代码不变,为每个需要分切的表编写一个分表策略类,配置到系统中。然后在调用前,声明分表策略即可。 
  
  整个过程只需要新写一个类,在调用出增加一行代码即可,对原始系统入侵非常小,风险可控。 

  流程总比hibernate shard要清晰很多,具体可以看http://code.google.com/p/guzz/wiki/TutorialShadowTable?wl=zh-Hans 


数据库主从分离 

从垂直分切部分可以看到,guzz也是配置性的原生支持读写分离。如果需要增加从数据库,可以随时加上,不需要改任何代码。不需要改动代码,而且配置也不复杂,应该算是设计上的极限了吧? 

你只需要在dbgroup中增加一个属性“slaveDBConfigName”,然后在一个properties文件中加上所有你需要的从数据库连接池配置即可,从数据库可以有许多台。 

这个hibernate shard根本就没有涉及到。而且guzz允许程序控制读写库选取,和proxy模式的中间件路由各有优势,毕竟更加容易控制。如果你做过内容提前审核再允许发布的系统,就会明白proxy中间件解决不了全部问题,有些读操作不允许延迟,只能读主库,而是也是读事务,proxy中间件会很尴尬。 

异构数据库 

这个hibernate以及ibatis之类的更没有了。而且也是对应用透明的,你可以随时选择增加一种数据库,然后把某些表放到上面,如增加一个H2做应用端缓存数据库,自己完成类似Timesten + oracle的架构。 

配置方式在上面的垂直分切小节也可以看到。 

数据库连接池配置 

随着表垂直和水平切分的进行,数据库会越来越多,数据源配置也会越来越多。guzz的设计是配置分组管理,类似Mysql的配置文件。每个数据源配置都在一个组内,无论增加多少都清晰了然,不会名字相互冲突。 

示例: 
Properties代码 
  1. [masterDB]  
  2. guzz.identifer=blogMasterDB  
  3. guzz.IP=localhost  
  4. guzz.maxLoad=120  
  5. driverClass=com.mysql.jdbc.Driver  
  6. jdbcUrl=jdbc:mysql://localhost:3306/blog?useUnicode=true&amp;characterEncoding=UTF-8&amp;useServerPrepStmts=true  
  7. user=root  
  8. password=root  
  9. acquireIncrement=10  
  10. idleConnectionTestPeriod=60  
  11.   
  12. [updateMasterDB]  
  13. guzz.identifer=incUpdateDB1  
  14. guzz.IP=localhost  
  15. guzz.maxLoad=20  
  16. driverClass=com.mysql.jdbc.Driver  
  17. jdbcUrl=jdbc:mysql://localhost:3306/guzzSlowUpdate?useUnicode=true&amp;characterEncoding=UTF-8  
  18. user=slowupdate  
  19. password=slowupdate  
  20. acquireIncrement=10  
  21. idleConnectionTestPeriod=60  
  22.   
  23. [logMasterDB]  
  24. ....  

如果一些数据库对某些连接池支持更好,guzz设计上还允许为不同的数据源指定不同的连接池实现。 

如果您需要分表,还是放弃hibernate shard或ibatis的设计模式吧,哪些只是临时拼凑出来的东西,设计上根本就不怎么样! 
posted @ 2010-10-18 21:02 深蓝色心情 阅读(4205) | 评论 (5)编辑 收藏

     摘要: 服务地址和接口已经更改,新的使用手册在:http://www.guzzservices.com/2010/man_ip_service/ 一.功能介绍  通过传入的IP地址,返回IP所在的地理位置。如传入“58.16.209.19”,返回“贵州省六盘水市 ”。  返回的地理位置又分为3种精确度,程序可以按照自身需要选...  阅读全文
posted @ 2010-06-22 11:59 深蓝色心情 阅读(3414) | 评论 (9)编辑 收藏


guzz是一套用来解决ORM、多数据源管理、以及通用数据计算的数据层框架,为系统在数据层的设计提供一站式解决方案。guzz可以看作是 ibatis/hibernate的一大的延伸,并可以取代这2个东西。 

guzz主要功能与特点: 
  • 现代大规模系统设计,技术上吸收了ibatis/hibernate的优点
  • 支持像hibernate一样的对象化持久、映射和方便的增删改查
  • 支持像ibatis一样,让dba参与sql设计的复杂数据库操作和优化
  • 支持在线加载与调试SQL。按照应用策略,从文件/数据库/Web Service等途径,动态提取与使用SQL语句(Dynamic SQL)
  • 支持应用程序使用大量的数据库和主从读写分离
  • 支持超越范式的特殊关联、非结构化数据等异构资源的统一管理
  • 支持数据表在多组机器间水平分布(Shard),并自动维护多组机器之间的分布式事务
  • 支持1张表按照业务规则分切成多张小表(Shadow),并支持每张小表拥有自己特殊的属性字段(Custom)
  • 支持组件化服务(SOA),构建企业/项目实施基础平台
  • 提供面向对象的数据库读取标签(JSP Taglib),加快页面展示层的快速变更、开发与部署
  • 支持配置管理服务器,可以使用一套软件系统对所有应用程序的配置进行统一管理
项目地址:http://code.google.com/p/guzz/ 
文档:http://code.google.com/p/guzz/wiki/WikiHomePage?tm=6 
下载:http://code.google.com/p/guzz/downloads/list 

1.2.8 更新介绍: 

支持(JPA)annotation 

支持按照JPA规范的annotation进行对象映射声明,同时为了实现guzz特有的功能,对annotation进行了扩展。扩展方式与hibernate类似,如果看到与hibernate annotation名字相同的注解,含义和用法也基本相同。 

更多介绍请参看使用手册: 
Guzz Annotation使用帮助:http://code.google.com/p/guzz/wiki/TutorialHbmAnnotation 

Guzz Annotation参考手册:http://code.google.com/p/guzz/wiki/AppendJPAAnnotation 

支持动态管理SQL: 

动态SQL(Dynamic SQL)不是指应用程序动态的拼接SQL语句,动态SQL是指应用程序可以动态的获取配置好的SQL语句。在获取的过程中,SQL语句如何管理,由应用系统自身决定。 

换句话说,在ibatis中,SQL语句配置到ibatis.xml文件中,在guzz中,配置到guzz.xml中。但当配置完成后,在系统运行期间这些SQL都是不能变动的,如果需要添加1个或者修改优化1个SQL语句,必须重启应用才能生效。而动态SQL允许应用系统动态的管理(添加/修改/优化/删除)sql语句以及查询结果到对象的映射关系(ORM),对于SQL的变更不再需要重启应用系统,以简化维护与应对需求变化。 

动态SQL主要有两种应用场景:SQL优化和动态数据源。具体介绍请参看:http://code.google.com/p/guzz/wiki/TutorialDynamicSQLService 

使用动态SQL的应用设计架构参考:http://guzz.javaeye.com/blog/675955 

改进远程服务设计: 

增加对hessian, burlap协议的支持。目前guzz内置支持phprpc, hessian, burlap三种协议进行RPC远程调用。使用时,三种协议可以透明替换,类似spring对RMI类协议的封装。具体介绍请参看:http://code.google.com/p/guzz/wiki/TutorialFutureService 

增加枚举类型与类型参数化支持: 

按照TopLink的模式,支持JDK5 enum。Enum在使用时和普通类型一样,不需要实现特殊的接口(hibernate要求实现接口)。Enum支持通过JPA的Enumeration注释声明,也支持在hbm.xml中通过xml定义。通过xml的定义方式参看:http://code.google.com/p/guzz/wiki/TutorialHbmXml 

类型参数化为guzz的特殊功能,用于处理动态SQL参数和Jsp Taglib条件参数时,将String类型自动转换成需要的数据类型。参数化类型主要为日期和枚举。详细介绍:http://code.google.com/p/guzz/wiki/TutorialHbmXml 

增加对数据库保留字的支持: 

在定义数据库列名时,可以用`(ESC下面的键)将列名引起来,避免字段名称与数据库保留字冲突。此功能与hibernate提供的处理保留字方法相同,但guzz只支持字段,不支持`表名`。 

增加对Microsoft SQL Server的支持(未测试): 

参考hibernate实现了一个SQL Server 2000 & 2005的dialect,不支持分页。没有测试过。Dialect实现类:org.guzz.dialect.MSSQLDialect 

Guzz已经能够支持的数据库和数据类型请参看: 
http://code.google.com/p/guzz/wiki/TutorialGuzzXml 

其他: 

1. 文档进行了大范围的补充和更新; 

2. 修复了所有已经发现的bug。 

下一版本计划: 

  • 增加对spring事务的兼容。
  • 设计一些常见的服务,推广guzz基础服务理念。
posted @ 2010-06-22 08:51 深蓝色心情 阅读(1440) | 评论 (1)编辑 收藏

仅列出标题
共4页: 上一页 1 2 3 4 下一页