Archive for April, 2006

近日思考四则

最近忙的晕头转向,直接的后果是ToRead List已经堆积如山,在这个信息过载的时代,我唯一的办法就是,放弃。
把在思考的一些东西,留在这里,本来都想仔细研究然后消化的,看来还是放在以后吧。
1) Live Clipboard
Ray Ozzie的最新大作,其实不能算新,都已经快2个月了。下面是一些Demo:

Simple Web page-based Demo
ScreenCast of Live Clipboard Demo

一定要亲自试试第一个Demo,你会被震撼的。再看看用来实现的技术,JavaScript + XML,不由得让我又想起了AJAX。相同的是,简单的、已存在多时的技术,却能带来非凡的体验。不同的是,只要你运用AJAX,用户就能感觉到,而Live Clipboard,只有大家都认可并且运用,才能更大发挥出它的价值。这也给它的前景蒙上了一层阴影。
Ray Ozzie的一句话让我印象很深:

I believe RSS has the potential to be the “UNIX pipe of the internet”, and that one of the simplest and most pervasive “mesh” needs that many of us have is to provide connections for things such as contacts, [...]

Subscribe My Most Popular Post

还是在上周末的时候,看到了Microsoft RSS Team的SLE(Simple List Extensions)扩展。三个单词中,最重要的是List,SLE主要是用来解决Feed订阅阅读模式的某种特定需求而产生的:

Treat Feed as List
Define customized sorting functions
Define customized filting functions

从订阅者的角度来说,订阅了这种Feed,本地的Feed列表将完全和Feed服务器提供的保持同步。这种同步包括几个方面:

Feed Item的次序与服务器上完全相同,如果有更新,则Feed Reader也会更新顺序
Feed Reader不会缓存过期的Feed Item,如果某一个Item从Feed中删除,本地Feed Reader也会将它从本地(或者在线Feed Reader Storage)删除。

简单的说,你通过Feed Reader看到的Feed应该与Feed Publisher发布的完全一致。
这种特定应用的需求会有很多,比如典型的几种应用:

Top 10 Best Seller – 比如Top 10 畅销书籍,Top 10 Music等等,对这种Feed的关注通常是更加关注于当前那10个;
Wish List – 如果我已经得到了某个东西,就会把它从SLE中拿去,这样,订阅了我的Wish List的人也就不会再看到这个,不会送重复的东西了:);
Open Positions – 当前职位列表,过期的职位通常意义不大。

可以看到,这些应用都有一些共同的特点,就是Feed本身更倾向于一种通知(Notification),过期的Item意义不大,而且,通常,这个List本身的次序是很重要的。
Specification很简单,通过以下这个声明来确定某个Feed是否是SLE(支持RSS2.0 & Atom),下面是一个RSS 2.0中的例子:
<rss version="2.0"  xmlns:cf="http://www.microsoft.com/schemas/rss/core/2005">
  <channel>
    <cf:treatAs>list</cf:treatAs>
    <title> Top 10 Popular [...]

Deja Vu

Deja Vu,来源于法语,中文一般翻译为:一种似曾相识的感觉。也就是觉得曾经经历过,估计这种感觉很多人都有过吧?
Wikipedia上Deja Vu的定义为:

The term déjà vu (French:"already experienced", also called paramnesia) describes the experience of feeling that one has witnessed or experienced a new situation previously. The term was created by a Frenchpsychicresearcher,Emile Boirac (1851–1917) in his book L’Avenir des sciences psychiques (The Future of Psychic Sciences), which expanded upon an essay he wrote while [...]

Windows RSS Platform Preview

曾经翻译过Longhorn中的RSS,那是Microsoft正式在Longhorn中加入RSS支持的白皮书。大概2个星期前吧,看到了Microsoft RSS Team Blog上面提到的Screen Saver的例子,才发现随着IE7 Beta2的发布,已经可以看到这个RSS Platform了。
大概看了一下整个文档,然后用C#编了个简单的小程序试了试,还不错,API还算合理好用,这下Desktop平台的对RSS支持变得非常容易了。
Windows RSS Platform的Online Reference在这里。

Subscribe to new feeds, and enumerate existing subscriptions.
Easily access properties of feeds (channels), feed items, and enclosures.
Manage and organize feeds into folders.
Listen for and respond to feed and feed folder events.
Check the status of the background Feed Download Engine, or modify settings.
Normalize the [...]

也说 Adapter Pattern

米嘉刚发了一篇Extension Object/Interface模式,周五很忙,但还是抽空看完了。不错,把Eclipse里面究竟为什么用Extension Object以及为什么用讲的很清楚。我自己非常喜欢看各种关于设计模式的书和文章,每一次读都会有不同的认识。终于今晚有时间,就也来说说Adapter。
按照GoF的说法,Adapter的意图是将一个类的接口转化为我们需要的其它的接口。这通常发生在这种情况下,比如我们拿到某个软件包甚至源码,但是我们不能修改她的接口,或者修改存在着潜在的风险。
其实,我觉得这不是最关键的问题,关键的问题是我们为什么不能改变自己的接口?为什么不干脆就直接使用软件包的接口算了?
仔细分析一下,其实Adapter算是我们平常用的最多的一种设计模式,可能甚至多到连你自己都没有意识到你是在用Adapter。我来举个例子,也是Adpater运用的一种最典型的情况:多态编程。

在XerdocDS中,对硬盘所有文件的扫描都是通过IParser的多态调用来进行解析的,这个接口是我们不能改变的。而事实上,很多具体的Parser,都有现成类可用,只不过接口和我们的不一样,比如上面的HTMLParser。这就需要用Adapter来适配一下。
在这种多态调用的结构下,我们都是针对接口来进行访问的,你不可能更改整个体系的接口,所以,必须要采用Adapter来进行适配。
再深究一下,可以发现,这种Adapter是针对对象的适配,也就是在对象的层面上来扩展功能。如果我希望给类扩展接口呢?很简单,多重继承(C++)就派上用场了。
小到这样的类结构设计,大到整个软件架构,Adapter的运用也非常广。我现在在做的一个Web Service,存在两个版本,由于中间一些比较大的变化,新版本已经几乎是一个完全新的Service,从接口到内部算法,都做了很大的改变。这样,新的Service中的接口已经和老版本完全不同,但是,我们还是有很多老的用户在使用老的Web Service接口,这就需要一个Adapter,在内部起一个适配的作用,以便来达到和老版本的兼容性。
可以说,上面举的例子都是Adapter比较经典的用法,本质上说,就是让由于接口的不一致而不能在一起工作的类,在一起工作的一种模式。
Eclipse把这种模式更加发扬广大。Eclipse的一大目标就是要无限扩展。除了插件的部分,扩展现有类的接口也是很重要的一个部分。很显然,我们不能修改现有类的接口,那么,如何给一个现有的类动态的增加新的功能呢?Decorator可以在相同接口下添加其它功能,而Adapter就可以添加其它的接口来添加需要的功能。这样,即可以无限扩充了系统的功能,又保证了系统现有类的纯洁性,也就是单一指责原则。不会造成各种正交功能的对类的污染。
在Eclipse中,所有希望在将来被扩展的类,都需要实现这个接口。
public interface IAdaptable { 
    public Object getAdapter(class adapter);
}
这和上面的需求正好相反,这里不是为了满足现有不匹配或者兼容的需求,而是为了满足未来可能的需求,而使用Adapter。叫Adapter似乎不太合适,叫Extension比较合适,呵呵。好像Eclipse早期的版本里面也确实不叫IAdaptable而叫做IExtensiable吧。
这样带来的问题就是未来的需求会很多,可能会有各种各样的Adapter,如何更好的管理、调用这些Adapter?Eric Gamma的AdapterManager和IAdapterFactory就派上了用场。
IAdapterFactory用来生产某些种类的适配器,而这些Factory和具体需要适配的类的关系由AdapterManager来维护,非常清楚。只需要在系统启动的时候把AdapterFactory都注册到AdapterManager中,然后在需要的时候来进行查询相应的查询即可,具体实现可以看看米嘉的文章。
之所以做出这样的设计,也是和OO设计的一些基本原则密不可分的,比如"针对接口编程"原则,比如"单一职责原则"。其实,这些原则也都是和现实世界密不可分的,比如针对接口编程对应到现实生活中,也就是针对标准进行设计。这样,各家的各种产品才能在一起工作。Adapter的经典例子便是不同制式的电源插销,去香港出差的时候,如果你不带一个大转小的Adapter,肯定无法进行工作:P。
最后举个简单的例子,比如Eclipse的SWT有一些UI元素,Button、List等等,你现在需要做一个Save All功能,就是把这些UI对象的状态序列化到硬盘上,并且能够下次再读取出来。
我可以定义一个接口,叫做:IPersistenable,然后让这些UI元素(Button、List等等)都实现这个接口,然后我就可以这样了:
public interface IPersistensable {
    public void save();
}
public void saveAll() {
    for(IPersistenable p : uiList) {
        p.save();
    }
}
现在的问题是,我无法或者不想改变Button、List等的代码。这时候,就可以采用下面这种方式了:
public void saveAll() {
    for(PlatformObject o : uiList) {
        IPersistensable p = o.getAdapter(IPersistensable.class);
        if(p != null) {
            p.save();
        }
    }
}
也就是说,我们需要实现一个Button->IPersistentable的Adapter,然后将它注册到AdapterManager中,就可以动态的为Button、List等类添加了新的IPersistensable接口。

How NLB works

这两天试了一下 Microsoft NLB(Network Load Balance),顺手记些笔记。
1)Aim:higher availability, greater scalability, 使用一种分布算法将访问Clustern的负载均衡分布到多台Host Server上,并且可检测主机故障并自动将流量重新分配给其它Host Server。
2)配置起来非常简单,需要注意的就是单播和多播的方式,以及Port Rule的配置。
3)NLB的实现有单播和多播的方式,在单播模式下,所有的Host Server都被赋予一个虚拟的Mac地址(02-BF开头,其后跟随的内容则取决于配置的Cluster IP 地址, 这也正是Token Ring不支持NLB的原因,令牌环网络不允许多台主机共用一个 MAC 地址),并且所有的Host Server都会有相同的一个虚拟IP地址,访问这个虚拟地址的IP数据报将会被所有的Host Server接收到。说起来简单,其实为了应对各种Switch和Hub,NLB采用了几种方法来实现,比如HUB的Broadcast,比如对一些Switch的Disable Learning,等等。当所有的Host Server都接收到请求此NLB的包后,会由一个Distributed Mapping算法,根据客户端的IP,Port,预先配置的负载比重等其他信息,确定具体由哪一个Host具体执行这个请求,其它Host简单的丢弃这个Message。
如果是多播,就会分配一个二层多播MAC地址专用于NLB的通讯,但是需要在Router上添加静态的ARP映射,将Cluster IP映射到多播的MAC地址。其后是一样的。
对了,如果是单播,Host Server之间会无法访问,为什么?如果你熟悉ARP协议,这个问题应该不难想到。
4)Port Rule,也就是端口规则。其实不难理解,试想一个Web Application,如果Client对Server的每次访问被定向到不同的Host Server上,那么像Shopping Cart等这种基于Session的程序将无法工作。NLB提供了很多种Port规则,比如相同Client IP Mapping到同一个Host Server,相同IP和Port Mapping到同一个Host Server,或者相同IP C网段映射到同一个Host Server等等。
5)Host Server之间保持HeartBeat,来确定所有的Host Server都还活着,否则就要重新Converge。HeartBeat也是发送到Host Virtual IP的,具体的IP祯也需要修改其中的SRC MAC地址和DES MAC地址。
6)来张Architect图:

7)有篇介绍NLB技术具体实现的非常好的文章,读完就会明白它是怎么work的了。
http://www.microsoft.com/technet/prodtechnol/windows2000serv/deploy/confeat/nlbovw.mspx