存档

文章标签 ‘SOA’

Daniel-Journey Weekly Dose –2011/1/16

2012年1月16日 admin 没有评论

SOA

服务治理过程演进

LINUX

如何在Linux下来查看OS系统块的大小

getconf PAGESIZE

Java

logback与Log4J的区别

The Trove library provides high speed regular and primitive collections for Java

Put your fat Collections on a diet!

Java Collection Performance

Java Sequential IO Performance
HotSpot虚拟机对象探秘

Low GC in Java: Use primitives instead of wrappers

There are two good reason to use primitives instead of wrappers where possible.

  • Clarity. By using a primitive, you are making it clear that a null value is not appropriate.
  • Performance. Using primitives is often much faster.

Servlet 3.0 新特性详解

  1. 异步处理支持:有了该特性,Servlet 线程不再需要一直阻塞,直到业务处理完毕才能再输出响应,最后才结束该 Servlet 线程。在接收到请求之后,Servlet 线程可以将耗时的操作委派给另一个线程来完成,自己在不生成响应的情况下返回至容器。针对业务处理较耗时的情况,这将大大减少服务器资源的占用,并且提高并发处理速度。
  2. 新增的注解支持:该版本新增了若干注解,用于简化 Servlet、过滤器(Filter)和监听器(Listener)的声明,这使得 web.xml 部署描述文件从该版本开始不再是必选的了。
  3. 可插性支持:熟悉 Struts2 的开发者一定会对其通过插件的方式与包括 Spring 在内的各种常用框架的整合特性记忆犹新。将相应的插件封装成 JAR 包并放在类路径下,Struts2 运行时便能自动加载这些插件。现在 Servlet 3.0 提供了类似的特性,开发者可以通过插件的方式很方便的扩充已有 Web 应用的功能,而不需要修改原有的应用。

Architecture

历届「Jolt Awards」获奖书籍

企业应用架构模式

响应性不同于请求处理,它是系统响应请求的速度有多快。这个指标在许多系统里非常重要,因为对于一些系统而言,如果其响应太慢,用户将难以忍受——尽管其响应时间可能不慢。如果能够在处理真正完成之前就给用户一些信息表明系统已经接到请求,则响应性就会好一些。例如,进展条。

一条关于依赖性的普遍原则:领域层和数据源层绝对不要依赖于表现层。

领域逻辑的组织可以分为三种主要的模式:事务脚本、领域模型以及表模块。

事务脚本是这样一个过程:从表示层获得输入、进行校验和计算处理、将数据存储到数据库中以及调用其他系统的操作等。基本的组织方式是让每个过程对应用户可能做的一个动作。所以,我们可以将这一模型想像成一个动作或业务事务的脚本。每一个动作是由一个过程来驱动。

在领域模型中,不再是由一个过程来控制用户某一动作的逻辑,而是由每一个对象都承担一部分相关逻辑。

在许多方面,表模块是事务脚本和领域模型的一个中间地带。它围绕表而非直接围绕过程来组织领域逻辑,提供了更多的结构,而且更容易发现和移除冗余代码。但是,你无法应用许多在领域模型中可以使用的组织细粒度逻辑结构的技术,例如继承、策略和其他面向对象的设计模式。

通常,序列化LOB(大对象Large OBject)对于用来组成应用程序部分的相对独立对象群而言是最好的。但如果过多使用它,最终会把数据库弄得和事务文件系统差不多。

对于任何继承结构,一般都有三种选择。可以为一个层次中的所有类建立一个表,即单表继承;也可以为每个具体类建立一个表,即具体表继承;或者为这个层次中每一个类建立一个表:类表继承。

这三种方法有利有弊。单表继承浪费空间,但避免了连接操作;具体表继承在超类改变时不得不改变所有表,但它也避免了连接操作,允许从一个表取得一个对象;类表继承需要多个连接操作来载入一个对象,这样通常损失了性能,但它是类和表之间最简单的关系。

如果机器处在屏幕流的控制下,那么你就需要应用控制器;如果这台机器是在用户的控制下,你就不要应用控制器。

在视图方面,可以考虑三种模式:转换视图、模板视图和两步视图。

对任何并发程序的本质来说,仅仅考虑正确性是不够的,还必须考虑灵活性(即有多少并发活动可以同时进行)。人们常常需要牺牲一些正确性以获取更多的灵活性,这取决于失败的严重性和可能性以及人们对并发处理数据的需求。

并发问题有两个非常重要的解决方案:一个是隔离(isolation),一个是不变性(immutability)。

在乐观锁和悲观锁之间进行选择的标准是:冲突的频率与严重性。如果冲突很少,或者冲突的后果不会很严重,那么通常情况下应该选择乐观锁,因为它能得到更好的并发性,而且更容易实现。但是,如果冲突的结果对于用户来说是痛苦的,那么就需要使用悲观锁策略。

超时控制和检测机制处理已经出现的死锁,而其他的方法则尽力防止死锁的发生。

跨越多个请求的事务称为长事务。

在请求开始时启动事务,在请求结束时提交事务,这是请求事务。

另一种方法是尽可能晚打开事务。使用延迟事务时,应在事务外完成读取数据的操作,只在修改数据的时候启动事务。然而,这可能会导致不一致读问题。

当可以并发执行并且结果与以某种顺序依次执行的结果相同时,事务就是可串行化的(serializable)。

如果系统中有很多用户,应该考虑使用集群来提高吞吐率。会话迁移(session migration) 允许一次会话从一台服务器转移到另一台服务器,从而可以由一台服务器处理一个请求,其他服务器处理其他的请求。与其相反的方式是服务器亲和(server affinity),它要求某次特定会话的所有请求只能由同一台服务器处理。

分布对象设计第一定律:不要分布使用对象。

这种情况下,怎样有效利用多处理器资源呢?大多数情况下是使用集群系统。在每一个处理器上都部署所有的对象并在其他几个节点上复制它们。这样一来,每个处理器上的对象只需用到本地调用,从而运行更快。还可以使用细粒度接口来设计对象,从而得到更简单的编程模型和更好的可维护性

分类: 阅读 标签: , , ,

SOA 模式学习——基础概念

2011年4月24日 admin 3 条评论

作者将模式分为三类:(1)基本服务模式,是最小粒度的服务模式,已经无法再次拆分,可以认为是模式原语,多用在服务层面使用。(2)架构模式,通用的 SOA系统设计要素,多用在系统设计时,做为架构风格的一个元素。(3)复合模式,基本服务模式的组合,用来定义系统的衔接特征,多用在应用系统整合场景。

493a8455t8702668433f4&690

基本服务模式

模式名称 模式定义
Aggregator – 聚合器

因为SOA系统只能保证消息送达,而不能保证按顺序送达,所以应该把几个有顺序要求的消息聚合在一起发送。这样避免了额外考虑消息状态和顺序的开销,更有利于异步处理消息。

Service Bus– 服务总线 将多个独立的系统(已有系统、新系统)通过统一机制整合起来。
Dynamic Routing – 动态路由 可配置、非过滤的消息路由。过滤方式的路由会导致endpoint接收所有的消息,而这个动态路由则位于过滤器之前,而起它的过滤规则可配置,甚至是由endpoint一侧的应用配置。
Event-Driven Consumer – 事件驱动的消费者 阻塞的监听或轮询方式浪费资源。通过基于总线或者特定于应用的callback机制可以更高效的处理消息。
Filter – 过滤器 系统间独立于平台的一种消息处理方式,并且不引入新的系统依赖或者不必要的耦合性。注意过滤器的对外接口要一致,以便灵活组合。
Router 根据消息内容、类型等规则解耦不同应用之间的耦合,过滤规则可配置。路由可以是串行或者并行。
Translator or Transformer – 翻译转换器 各种不同系统之间消息可能采用了不同的输入输出格式。翻译转换器的作用就是把这些不同的格式转换为应用理解的格式。它位于endpoint一侧,因为一般来说根据系统和协议的不同,消息采用的格式也有所不同。有了消息翻译转换机制,系统内部就不用考虑外面的消息格式可以专心业务开发。

架构模式

模式名称 模式定义
Asynchronous Processing 异步事件风格解决服务之间的交互,例如,ATM到银行账务系统,多用该模式。在实践中,也鼓励使用这种风格,实现SOA,以弱化一致性、事务性,缓解资源受限等场景,该模式需要业务配合才能完全发挥。同步机制降低性能和可靠性,所以当然能异步尽量异步。一般会需要个消息队列之类的。异步机制能提供可扩展性,包括前端和后端
Bridge 常用在2中体系之间的交互,把一种协议转换为另一种协议。它与Translator的区别在,Translator是针对消息的,它针对链路。
Cross-Service Operation 把多个服务封装为一个服务来使用,以确保一致性、事务性,可以把该风格弱化为分布式事务风格.不同服务组成原子服务,事务性应用需要这个。
Event-Driven Dispatching 基于事件的派发,常用在pub/sub场景。
Process Aggregation 把多个过程聚合在一起,按照一定顺序进行消息处理,此时不要求一致性,每个过程都是独立的,用BPM技术更容易理解该场景。
Routing and Filtering 实现一个消息的多种渠道应用,例如,一个业务通知,通过Mail,IM、SMS、语言、甚至特殊应用传达给用户的场景,一个产品为多个渠道提到内容的场景。
Replicator 实现一份消息,服务处理的时候,同时往数据库复制一份,例如,数据备份容灾、数据采集、数据审计等。

复合模式

模式名称 模式定义
Centralized Schema 解决跨应用边界的数据共享问题
Concurrent Contracts 解决一个服务多个消费者时,每个消费者接口不同的问题。
Decomponse Capability 在业务流程不断膨胀和进化的过程中减少功能拆分影响的方法。在物理上分开的数据模型和服务定义,仅在二者生成特定服务实现的时候才组装,这样二者可以分别进化。
Enterprise Service Bus 通过一个消息总线,解决应用整合的问题,化解复杂的网状链接。
Fault-Tolerant Service Provider 在冗余的服务提供者之前加负载均衡器。需要保证服务无状态和尽可能的可重用性。
Wrapper 把遗留系统包装成通用的无状态服务。

 

参考资料

http://blog.sina.com.cn/s/blog_493a84550100iogt.html

http://www.osteching.com/2011/01/soa-patterns-simple-impression/

http://refcardz.dzone.com/refcardz/soa-patterns

分类: 软件设计 标签:

Daniel-Journey Weekly Dose-2010/9/12

2010年9月12日 admin 4 条评论
分类: 阅读 标签: , , , ,

Daniel-Journey Weekly Dose –2010/5/22

2010年5月22日 admin 没有评论

Agile

敏捷软件开发模型:SCRUM
闲话:关于敏捷

而敏捷里面所有的实践,质量是隐含的,不可侵犯的.这就是我们所说的Built Quality In.比如,刚开始写Story, 就要和测试人员定义验收条件;开发Story采用TDD的方式,通过测试来检验功能,类似于砌墙的时候先扯水平线,然后开始铺砖.

整个团队只有一个目标:产生高质量的交付

在此目标之下,以尊重 交流 反馈 勇气 简单为基本做事价值观和原则.

Agile Versus Waterfall: Part One

敏捷与能力

丰田精益生产方式中一个经常用的隐喻是“湖水和岩石”。大意是指湖水太深,你无法发现阻碍当前生产的主要原因,只有把湖水讲下去,才能发现真正的岩石在哪里。在精益生产中,湖水是指“库存”,而在软件开发中,对应的湖水则是“迭代周期”。
我们举一个例子,当发现“项目严重延期”时,通常已经是交付时间,不过开发人员最近一直加班,也挺辛苦的呀。不过如果你是项目经理或者客户,你知道开发人员的时间都花到哪儿了吗?如果采用迭代式交付,每两周一个迭代,完成一定的特性,你可能第一个迭代就发现问题

我们可以抱怨团队开发人员能力不够,不过这关敏捷的什么事儿?本来大家都知道的事情,只不过敏捷让它暴露的更严重更突出罢了,谁还会任由你“掩耳盗铃”呢。

敏捷和SCRUM回顾

Javascript

JavaScript Debugging Techniques in IE 6

Java

Top 10 (not so popular) Eclipse Shortcuts

Design Pattern

Design Patterns Uncovered: The Flyweight Pattern

image

When considering this pattern, you will need to think about intrinsic and extrinsic data. Intrinsic data is the data that makes this object instance unique. Meanwhile, extrinsic data is information that can be passed in through arguments. So, if you can make some data extrinsic for cases that you have a large number of objects, the Flyweight pattern may be exactly what you are looking for.

设计模式学习笔记(十二)——Flyweight享元模式

Flyweight模式的几个要点:

1、面向对象很好的解决了抽象性的问题,但是作为一个运行在机器中的程序实体,我们需要考虑对象的代价问题。Flyweight设计模式主要解决面向对象的代价问题,一般不触及面向对象的抽象性问题。

2、Flyweight采用对象共享的做法来降低系统中对象的个数,从而降低细粒度对象给系统带来的内存压力。在具体实现方面,要注意对象的状态处理。

3、对象的数量太大从而导致对象内存开销加大(这个数量要经过评估,而不能凭空臆断)

SOA

自底向上的ESB管理 VS. 自顶向下的SOA治理

但创建了一个SOA,自底向上的治理方法关注围绕单独ESB的集成化服务,这些ESB 可以快速装配。该方法因为需要过多的更新和重做而受到非难。

同时,相对的“自顶向下”的治理方法涉及大量严格规划和精确策略执行。这种方法也由于花费过多的时间才能产生结果而不被认可。

SOA治理策略如何抉择?

企业接受SOA的速度比较慢,大多数接受者倾向于接受自底向上的方法。

随着人们开始实施SOA,自身的技术就不够用了,这时就需要一些治理来辅助

Hariharan最后讲到:“如果企业以一种长期的愿景和蓝图来寻求SOA,那么自顶向下的方法是最佳的选择。如果并没有一项企业级的IT 策略以及长期的愿景,IT 可以选择自底向上的方法来实现和展示SOA的好处。”

Linux

使用scp 命令在两台linux上对拷文件或者文件夹

scp 本地用户名@IP地址:文件名1 远程用户名@IP地址:文件名2

拷贝文件夹命令如下:scp -r file username@ip:filepath
多加上一个-r参数即可。

Daniel-Journey Weekly Dose-2010/5/8

2010年5月9日 admin 没有评论
分类: 阅读 标签: , , , , ,

Daniel-Journey Weekly Dose-2010/4/16

2010年4月18日 admin 没有评论

Database & SQL

如何应对表结构经常变化?

第一种方法,预留字段.不管怎样,预留字段的方式还是很解决很多问题的,而且基本不影响性能,除了额外的meta信息描述外,也没有其他的负担。

第二种方法,使用复杂字段.使用复杂字段的好处就在于比较灵活,同一类型的数据可以放在一起(实际上相当于把应该是一个关联表的数据放一个字段里了),操作的性能也不错,但是复杂字段里面的内容查询比较困难.

还有一种方法,将数据的存储和索引(需要查询的内容)分开存放,相当于主表就一个key-value,value就是一个大的xml(或者其他的一坨),把需要查询的字段放到其他单独的表里去,可以参考friendfeed如何使用mysql.

还有column based db,也可以很好的解决这个问题,实际上他就本本回避了加字段的问题,不过现在似乎没有性能很好的实现

公交车路线查询系统后台数据库设计–查询算法

公交车路线查询系统后台数据库设计–关联地名和站点

SOA

SOA(面向服务的开发) 简介

微软SOA平台体系架构介绍

SOA@eBay 读后感

SOA与服务识别

面向服务架构(SOA)已被作为一种通过对齐IT和业务来促进业务机动性的方法被广泛接受。这种方法的主要不同之处在于,用相对较低的成本就能轻易 地获得某种机动性。在较高的层次,该方法试图将第n次业务变更所产生的增量成本降低到零或接近于零。组织推行SOA项目目的就是为了在他们的SOA之旅当 中尽早达到这个难以捉摸的第n个迭代。在实践中,要达到这种最佳状态的时间可能得花数年,甚至更长时间。

Architecture & Design

探秘:AOP能否解决紧密耦合的难题

虽然动态横切(其中对象的运行时行为可以改变)被认为是AOP的根基之一,但静态横切却是一种远不为人所知的技术。

Scalability

大规模集群下的http 状态解决方案

Java

Java 语言中的函数编程

Jrebel原理剖析

Reloading Java Classes 401: HotSwap and JRebel — Behind the Scenes

Difference between HashMap and IdentityHashMap

Linux

关于cronExpression的介绍

其他

我在QQ邮箱的这四年(一) [转]

张小龙(Foxmail的作者)认为互联网团队中的管理不是管人,而是管理产品体验,以产品体验为核心,产品设计和开发人 员与产品共同提升,共同进步。小龙之于QQ邮箱的影响正如乔布斯之于苹果的影响。

当时(2005)的javascript代码有很重的面向对象的味道,用传统的软件工程思想构建了 整个web框架,从软件的开发流程来说,这并没有什么问题,但是产品却有很大的问题出现了–慢,不是一般的慢,当时除了较快的电信网用户可以登陆进邮箱 之外,其他的用户基本上都被卡在登陆上。06年的大部分时间,整个团队都在解决速度慢的问题,尝试了很多方法,把js容量压缩掉了一半,js混淆之后又压 缩了很多,js文件分开为多个,但始终没有根本的转变,速度的提升仍然不能被用户接受。现在回过头分析这个问题,我觉得物理上的压缩和分割js文件之所以 解决不了问题是因为问题的根本在于js的逻辑架构上,当时的js有明显的基类和继承类结构体系,这种结构并不适合物理上的分割,即使分割开,渲染消耗的时 间是节省不下来的。

Javascript

实用的JavaScript 测试及效验工具

Daniel-Journey Weekly Dose-2010/4/11

2010年4月11日 admin 3 条评论

Architecture & Design

Mediator Pattern applied to Javascript

The diagram below is a general representation of the interaction between a mediator and colleagues. Each colleague stores a reference to the mediator and the mediator stores a reference to each colleague. Colleagues are unaware of each other and messages are broadcast through the mediator.

image

Two of the benefits of using the Mediator pattern are that that it decouples colleagues and simplifies object interaction. Instead of using the Observer pattern to explicitly set many-to-many listeners and events, Mediator allows you to broadcast events globally across colleagues. The biggest drawback of using Mediator pattern is that due to the centralized control, the mediator can become difficult to manage.

向对象开发与面向组件开发的区别
养成面向组件编程(COP)的习惯
面向组件还是面向对象

既然类和组件有着这么多类似的地方,那么传统的面向对象编程和面向组件编程有什么区别呢?简单的说,面向对象关注的是组合在一个二进制可执行文件中的各个类的关系,而面向组件的编程关注的是在彼此独立的基础上模块之间的交互性,这种交互性使得你并不需要熟悉它们内部的工作原理。

面向对象与面向组件小议

面向对象技术的基础是封装--接口与实现分离,面向对象的核心是多态--这是接口和实现分离的更高级升华,使得在运行时可以动态根据条件来选择隐藏在接口后面的实现,面向对象的表现形式是类和继承。面向对象的主要目标是使系统对象化,良好的对象化的结果,就是系统的各部分更加清晰化,耦合度大大降低。 

组件技术的主要目标是复用--粗粒度的复用,这不是类的复用,而是组件的复用,如一个dll、一个中间件,甚至一个框架。一个组件可以有一个类或多个类及其它元素(枚举、)组成,但是组件有个很明oo显的特征,就是它是一个独立的物理单元,经常以非源码的形式(如二进制,IL)存在。一个完整的组件中一般有一个主类,而其它的类和元素都是为了支持该主类的功能实现而存在的。

最后强调一点,组件的目标是粗粒度的复用,组件的核心是接口。

用Qi4j进行面向组合编程

Java

SortedMap JavaDoc

Database and SQL

Efficient Pagination Using MySQL

高效的MySQL分页

SOA

服务和耦合的真正意义

基于设计的组件:首先:SOA和基于设计的组件不一样。在一个SOA架构中的服务是分布式的。而基于设计的组件中的这些组件是代码片段,通过他们所处每个系统来打包这些片段。从这种意义上来讲,EJB 能够作为服务和组件。

基于重用的组件通常比基于重用的服务简单。在服务重用时,在重用组件中变更带来的影响更是难以控制。其中可能有使用我的服务以及我没有关注的系统。在组件中,也许也是这种情况,但每个系统不得不有意识的做决定来升级组件,所以在一个系统中任何意外的破坏都与系统中那个早期的变更有关系。

耦合:这是“耦合”的真正意义。如果一个系统的改变很可能需要另一个系统的改变,那这两个系统是紧耦合的。这是一个很难通过观察代码来衡量的标准,然而很多人相信可以用代码的度量来理解耦合。

其他

一个老程序员的感悟:做技术二十多年,突然明白的道理

Daniel-Journey Weekly Dose-2010/4/4

2010年4月4日 admin 没有评论

Java

ThreadLocal是什么

深入探讨在集群环境中使用 EhCache 缓存系统

WEB

加速Javascript:DOM操作优化

Linux

Linux内存模型

文件默认权限:umask

查看方式有两种,一种是直接输入umask,可以看到数字类型的权限设置分数,一种是加入 -S(Symbolic)参数,就会以符号类型的方式显示权限。

在默认权限的属性上,目录与文件是不一样的。由于我们不希望文件具有可执行的权力,默认情况中,文件是没有可执行(x)权限的。因此:
• 若用户建立为”文件”则默认“没有可执行(x)项目”,即只有rw这两个项目,也就是最大为666分,默认属性如下:
-rw-rw-rw-
• 若用户建立为”目录”,则由于x与是否可以进入此目录有关,因此默认为所有权限均开放,即为777分,默认属性如下:

umask指定的是“该默认值需要减掉的权限”。因为r、w、x分别是4、2、1,所以。也就是说,当要去掉能写的权限,就是输入2,而如果要去掉能读的权限,也就是4,那么要去掉读与写的权限,也就是6,

Architecture & Design

IOU 设计模式介绍及应用

IOU 思想是人们在处理日常债务关系时行之有效的一种方法,即:

  • 债务人通过可靠的第三方保管账户,向债权人发放 IOU 债务凭证;
  • 债务人通过向第三方保管账户提交结果以终止 IOU 债务;
  • 债权人凭此 IOU 债务凭证通过第三方保管账户履行债权并进行结果赎回。

债务人和债权人之间的债务关系,通过可靠的第三方保管账户,实现了在时间和空间上最大程度的分离和解耦。

IOU 设计模式是 IOU 思想在软件设计领域的应用,最早由 Allan Vermeulen 于 1996 年首次提出。在软件设计领域,债务关系发生在方法调用者和方法体之间,债务对象就是方法的返回结果。普通方法的调用模型是方法体同步执行然后返回结果,调用者必须等待结果返回后才能继续执行。在 IOU 设计模式下,方法体将立即返回一个 IOU 对象,并且承诺 IOU 对象最终一定会被终止,调用者在 IOU 对象被终止后可进行结果的赎回。在此期间,调用者无需等待就能够继续进行其它有价值的事务,从而达到了提高程序整体的并发性和异步性的目的。

IOU 设计模式完全不依赖于任何一种异步机制,IOU 对象的提供者可以选择任意有效的方式来执行服务并最终终止 IOU 对象,比如启用独立的线程/进程执行、驱动异步事件产生、通过远程方法调用或是等待用户终端输入等等。这是 IOU 模式具备普遍适用性的一个重要因素。

Q1技术回顾

SOA

Services vs. Applications

Services Applications
Perform a single or a few specialized operations. Perform a wide range of operations, and may even expose some of these operations as services.
Most often accessed by other programs. Often (but not always) accessed by humans.
Often (but not always) targets part of a larger problem domain. Often (but not always) targets a whole problem domain.
分类: 阅读 标签: , , , ,

Daniel-Journey Daily Dose-2010/2/12

2010年2月12日 admin 没有评论

Agile

Agile: The New Era

The study found that iterative and agile practices have a significant impact on defect and productivity factors, as indicated by the following points.

  • Releasing a system with 20% of the functionality complete is associated with a decrease in the defect rate of 10 defects per month per million lines of code as compared to waiting to release a product until 40% of the functionality is complete, and an increase in productivity of eight more lines of source code per person-day.
  • Continuous Integration, the idea of integrating and testing code as it is released to your source code repository, resulted in a decrease in the defect rate of 13 defects per month per million lines of code, and an increase in productivity of 17 lines of source code per person-day.

The first two are deeply embedded in the ideals of agile software development.

  • Releasing early and often to project stakeholders, using an iterative lifecycle.
  • Continuous integration, with daily builds including regression testing.
  • Teams with broad experience delivering multiple projects.
  • Careful attention to modular and loosely coupled, componentized architectures.

OOD and OOP

An (Overlooked?) Use Case for the Strategy Pattern

SOA

Enterprise Service Bus (ESB): a critical part of SOA

分类: 阅读 标签: , ,

Daniel-Journey Weekly Dose-2010/1/31

2010年1月31日 admin 没有评论
分类: 阅读 标签: ,