RSS 2.0 Feed

Tuesday, April 29, 2008

 

周五在San Francisco举行的Web 2.0 Expo上,Microsoft正式公布了新的Live Mesh平台。Live Mesh不仅仅是一个用户平台,也更是一个开发者平台。而借此,Microsoft也第一次大声地喊出:PC不再是计算的中心了,而Services才是平台的中心。

对于用户,现在IT的趋势是个人拥有越来越多的终端:手机,PDA,笔记本电脑,台式机,XBox,iPod,等等。而另一方面,各个终端上的社会网络和信息资源又很难保持一致或进行整合。手机上有一堆号码,笔记本上有一堆会议记录,台式机上有一堆照片,XBox上有一堆网友。但如果你什么时候想在开会的时候偷个空看看哪些XBox的玩友正好在线呢,Oops,不好意思,做不到,因为事先没有把这部分内容同步过来。

而对于开发者,他们希望他们所写的应用程序不但能在常用的计算平台上运行,也希望当用户在使用移动设备或者有网络能力的娱乐设备的时候,同样能使用他们的应用程序。设想,如果你开发了一个共享照片的服务,在台式机或者笔记本上运行的好好的,但你是否也希望当你的用户手边只有一个手机的时候,他同样可以轻松地使用你的程序的mobile版本来下载他所想要的照片呢。写个用户界面是小事,难的地方是在于如何在手机平台上无缝地获取存储在cloud (cloud as in cloud computing)中的资料。而Live Mesh就是想为开发者提供解决这样问题的平台,而不是让每个人绞尽脑汁地开发如此底层又吃力不讨好的服务。

Live Mesh的核心概念在于以下几点:

1. 服务是平台的中心,而不是终端(PC也好,手机也罢,服务应该是独立于硬件的)。

2. 统一的API集。无论你的程序是运行在离线的客户端,还是作为浏览器的plug-in,还是作为一个动态网页(后台连接Live Mesh的cloud storage),还是一个连线的桌面程序,所有的模式需要使用的API应该是一致的。

3. 开放的可扩展的数据模型。

4. 弹性的应用程序模型。开发者可以写仅支持连线状态的程序,也可以写同时支持离线和连线状态的程序,也可以写仅作为浏览器插件的程序,等等。Live Mesh不强制某一种应用程序模型,一切完全由开发者决定他们想支持的用户场景(user scenario)。

 

Picture_15

 

CNET上有一些报道可以帮助有兴趣的朋友开始了解Live Mesh:

Live Meshing on the Gillmor Gang

Microsoft Live Mesh platform takes on Google, Adobe

而这里有Ori Amiga的介绍Mesh程序开发的视频:

Ori Amiga: Programming the Mesh

 

=====================================================================================

这半年经历了很多人事变动,周围的事一直不是很安定,希望以后的一段时间能安静地做些技术。关于Live Mesh我还有不少想写的,虽然对它的某些内容我还有自己的看法,但总体来说这是一个好方向。这次微软推出Live Mesh后收到的评价也颇为正面,和以往一出来什么东西都被口诛笔伐得一文不值大为异趣。可见群众的眼光还是雪亮的,大家并不针对你这个人/公司来评价你的产品,Google做得不好的要批评,Microsoft做得好的也可以表扬。做技术的本来就该如此,政治还是留给别人去搞吧。

posted @ | Feedback (0) |

Saturday, November 17, 2007

Windows Live Contacts Control是另一个应用很广的控件,第三方开发者只需要在自己的服务器端放置一个channel文件,然后就可以在任何网页中通过安插一段简单的Javascript来显示Contacts Control了。当访问者用他们的Windows Live ID登录后,Contacts Control可以显示他们所有的联系人已经相关的地址、电话等信息(当然,前提是相关联系人已经输入了这些信息 - 在注册Live ID的时候,通过Messenger客户端,通过http://login.live.com都可以)。你可以在这里试试Contacts Control的实例:

http://dev.live.com/mashups/trycontactscontrol/

Contacts Control还有一个“变体”,叫Presence Control,它可以用来显示你联系人当前的在线信息,你可以到这里试用看看:

http://dev.live.com/mashups/trypresencecontrol/

不过,你无法在FireFox中使用Presence Control,原因是Presence Control其实在底层调用了Messenger Client的一个ActiveX接口,而在FireFox里是无法调用native的ActiveX接口的。不过这个问题可能很快就有迂回解决的方法了,我会在那个新的API发布后写blog介绍的。

 

要改变这两个Control的外观也很容易,只要简单设置一些参数就好了,具体的信息你可以在这里获得:

http://dev.live.com/contactscontrol/

你可以看到这些Control都已经本地化了,要使用中文界面的话只要把language/market参数设为zh-cn就好了。

 

最后顺便提一句,Dev Live组其实已经发布了一个控件包,你可以在Visual Studio 2008 (Orcas)下安装这个控件包,然后在集成开发环境(IDE)中就可以简单地往网页上拖放这些控件了。这个控件包里包括:

Contacts Control

IDLogin Control

IDLoginView Control

SilverlightStreamingMedia Control.

请参看这里的消息:http://dev.live.com/blogs/devlive/archive/2007/11/08/167.aspx

 

注:有必要说明的是:Contacts Control和Windows Live Data Contacts API用的是完全不同的技术。两者的目的也是不同的,Contacts Control (以及其他的PresenceControl,SpacesPhotosControl等)是为了给第三方网络开发人员提供轻量级的控件集使他们可以在很小的技术投入下能迅速利用Windows Live积累的用户信息资源来丰富用户体验。而Windows Live Data更像一个平台级的API,它致力于提供大量的原始数据而不是直接的终端体验,至于如何整合使用这些数据完全由第三方开发人员决定。

==========================================================================================================================

关于Windows Live服务访问速度的问题开心大哥已经和我说过了,事实上这个并非服务本身的问题,因为大部分Windows Live服务在欧美地区都有大量用户在使用并且没有访问速度的问题。中国区用户的大部分问题其实都源自于Windows Live数据中心的部署,我不知道有多少内容是我可以在公开的blog上说明的,只能说很多Windows Live的team都意识到了这个问题,也在想办法提供解决方案。

 

posted @ | Feedback (1) |

Thursday, November 15, 2007

好吧,我承认6个月前我们就发布了Windows Live Data Alpha。为什么现在“再”发布一次Alpha,别问我,that's something out of my control, : (

 

Anyway,版本号还是Alpha,但确实是有新的Feature,现在除了用户的AddressBook,开发者还可以通过Windows Live Data来取得用户的Spaces Photos! Yup, 你现在不用一个个地跑去你朋友的MSN Spaces去看他们最新的照片了,你可以自己写一个desktop程序或者web application来获取所有朋友的Spaces相册和照片。

DevLive上有两个API的开发文档,也提供了各自的Interactive SDK (Contacts, SpacesPhotos)。

Angus的blog上也有图文并茂的介绍

其实这个版本主要的改进是在后台,也就是为了应对越来越大的用户流量所做的架构和技术上的改变,但这些对于Windows Live Data的用户来说都是没有太大意义的,他们需要的是看得见摸得着的新的feature(比如这次SpacesPhotos的API)。在以后的开发中我们也会注意内部infrastructure的改进和可见的feature的更新之间的平衡。

嗯,下一个是什么  Hotmail? Calendar? Events? 想想看,等Windows Live Data onboard了这些Live Service后,通过这个接口,第三方的开发者可以接触到多大容量的用户信息啊,然后再对这些信息进行整合又能开发出多少有趣的mashup呢。

 

posted @ | Feedback (4) |

ASP.NET中你可以通过继承IHttpHandler这个接口来实现一个同步(Synchronous)处理用户请求的类。比如你希望对于一切类型为fakephp的请求都通过你的Http Hanlder来处理,你可以实现以下这个类:

 

using System; using System.Web; public class FakePHPHttpHandler : IHttpHandler { public void ProcessRequest(HttpContext context) { //let's pretend we can handle PHP stuff } public bool IsReusable { get { return true; } } }

然后通过在IIS里将你的dll注册为.fakephp的handler就可以了。这些在以下的MSDN文档里都有介绍:

http://msdn2.microsoft.com/en-us/library/system.web.ihttphandler.aspx

 

这里想说的是如何实现一个异步(Asynchronous)d的HTTP Handler。说起来其实也简单,只要实现IHttpAsyncHandler这个接口就好了。

IHttpAsyncHandler有两个method:

 

Public method BeginProcessRequest
Initiates an asynchronous call to the HTTP handler.

Public method EndProcessRequest
Provides an asynchronous process End method when the process ends.

这显然是和.NET Framework中标准的Asynchronous Programming Model (或者叫“异步模式”, Asynchronous Pattern)是一致的:

参考: Asynchronous Programming Overview

异步模式的优势是ASP.NET的worker thread不会等待BeginProcessRequest返回而是会掉头去接收其他的用户请求(当然你也可以要求worker thread等待,不过这样就等于变成了Synchronous Handler)。因为通常处理一个web request的后台时间需要比较长。假设你每秒只能处理10个用户请求,在同步模式下如果有11个人同时访问你的服务,就有一个人会看到500 Internal Server Error之类的错误消息了。但如果是异步模式,worker thread只要调用BeginProcessRequest,而根据Asynchronous Programming Overview,BeginProcessRequest应该立刻返回(“立刻”的含义是它不应该进行长时间的操作,而应该调用QueueUserWorkItem之类的API将耗时的任务放到新线程里执行),这样worker thread就可以腾出手去接收下一个user request了。

注:ASP.NET的max worker thread上限可以通过processModel configuration element里的maxWorkerThreads属性来改变(参考:Improving ASP.NET Performance 以及 processModel element),但最大的值也只是100 (range from 5 to 100, default 20)。

由此引出的问题自然是:当异步操作完成时, ASP.NET是如何知道并做相应处理的。这有一下几种选择:

1) 当调用BeginProcessRequest的时候,ASP.NET可以同时传入一个AsyncCallback的delegate,而在你完成异步操作后,你应该调用这个回调函数来通知ASP.NET。

2) ASP.NET可以不停地查看IAsyncResult (这个是BeginProcessRequest的返回值)IsCompleted属性来确认异步操作是否已经完成了,当然,当你完成异步操作时,你有义务将IsCompleted设成true。

3) ASP.NET也可以等待AsyncWaitHandle的信号,AsyncWaitHandle是IAsyncResult的另一个属性,这个和经典的Win32里waiting on kernel object是类似的。

4) ASP.NET可以直接调用EndProcessRequest。

注意:3) 和 4) 是Asynchronous Programming Overview里规定的标准的blocking execution的方式,也就是说,如果你的主线程在异步操作完成前无法再做任何工作时,它可以通过3) 或者 4)来等待异步操作的完成。

从理论上来说,你应该保证你的IHttpAsyncHandler能满足以上所有4种方式。但现实中,你未必一定如此做。那么哪些是我们必须实现以匹配ASP.NET的要求的呢?或者ASP.NET究竟是如何实现异步调用及返回的呢?

事实上,ASP.NET采用了方法1,也就是说,在调用BeignProcessRequest的时候,ASP.NET传入了一个AsyncCallback,而你应该在完成异步操作后调用这个callback,而在这个AsyncCallback里,ASP.NET又调用了你的EndProcessRequest来做收尾工作。

根据上面的讨论,我们可以如下设计我们的Asynchronous Http Hanlder:

 

public class AsyncFakePHPHttpHandler : IHttpAsyncHandler { private void ProcessRequestCallback(object state) { AsyncResult async = (AsyncResult)state; // this is where the real work is done ProcessRequest(async.context); async.isCompleted = true; if (null != async.asyncCallback) async.asyncCallback(async); } public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback asyncCallback, object state) { AsyncResult async = new AsyncResult(context, asyncCallback, state); // if the callback is null, we can return immediately and let EndProcessRequest do all the job // if callback is not null, we will use our thread pool to execute the necessary asynchronous operations // what happens in ASP.NET is that the callback in NOT null, so QueueUserWorkItem will be used if (null != async.asyncCallback) threadPool.QueueUserWorkItem(ProcessRequestCallback, async); return async; } // this design also satisfies method 4), we implement it this way to follow the Asynchronous Pattern as much as we can public void EndProcessRequest(IAsyncResult result) { AsyncResult async = (AsyncResult)result; if (null == async.asyncCallback) ProcessRequest(async.context); } }

 

总结一下实现异步Http Handler的要点:

1) 所有在BeginProcessRequest中的耗时操作(比如IO什么的)都应该采用异步调用(比如BeginRead/EndRead)或者生成新的线程去执行。不错,你可以设计一个blocking BeginProcessRequest,没有人能阻止你这么做。But that's a BAD BAD idea.

2) 实现BeginProcessRequest/EndProcessRequest的目的是允许ASP.NET来异步调用你的Http Handler

3) 你应该创建一个实现IAsyncResult接口的类,在BeginProcessRequest中你会生成一个该类的实例并返回给ASP.NET(注意BeginProcessRequest的返回值类型)。而根据Asynchronous Pattern,ASP.NET在调用EndProcessRequest的时候会把这个实例再传回给你,你可以用这个实例来判断你所执行的任务的当前状态。

4) 我个人感觉比较容易导致困惑的是这里“两段式”的异步调用操作。首先ASP.NET是通过BeginProcessRequest/EndProcessRequest来异步调用我们的Http Handler的。然后我们在BeginProcessRequest又再次用异步模式(用QueueUserWorkItem或者其他的Begin*/End*操作)去完成真正的工作。实际上第二步的异步调用才是真正生成另一个thread来处理工作的地方。ASP.NET调用我们的BeginProcessRequest只是一种形式上的协议通知,因为是我们告诉ASP.NET:Hey,我是一个异步的handler。ASP.NET说:那好吧,既然你这么说的,我就用你异步的接口来调用你。事实上,在HttpRuntime的源代码中,可以看到ASP.NET的操作如下:

                if (app is IHttpAsyncHandler) {
                    // asynchronous handler
                    IHttpAsyncHandler asyncHandler = (IHttpAsyncHandler)app;
                    context.AsyncAppHandler = asyncHandler;
                    asyncHandler.BeginProcessRequest(context, _handlerCompletionCallback, context);
                }
                else {
                    // synchronous handler
                    app.ProcessRequest(context);
                    FinishRequest(context.WorkerRequest, context, null);
                }

====================================================================

最后的题外话,关于IIS/ASP.NET处理请求的工作流也是一个很有趣的问题,下面的这篇文章很棒(but the author's English writing kinda sucks, : ) )。比如,从中我们可以知道,整个流程中其实牵涉了两个Queue,一个是Kernel mode下的,一个是User mode下的,而后者就是ASP.NET所使用的Application Queue,而ASP.NET的worker thread就是从这个Queue里去取下一个需要处理的请求的。

Dissection of an ASP.NET 2.0 request processing flow

posted @ | Feedback (4) |

Friday, November 09, 2007

这些天在考虑Windows Live Data新的DataAccessModule (DAM) 的设计,由于用户的大量增加,原来server端2-tier的设计已经无法满足要求了。原来的情况下,所有的用户请求全在接受到该请求的host上处理完成,但现在需要加入consistent hashing来分散用户请求的处理(因为用户人数的大量增加)。即,每个用户都有一个key,当前端(frontend)接受到一个用户请求(request)后,通过对这个key做consistent hashing,将请求分散到不同的后端host上处理。从2-tier到n-tier(这里我只提了frontend和后端的processing host,但其实还有其他几个分布式的tier)的转变是DAM架构的设计陡然变得复杂许多。所以我们必须严格证明这样的改变是有必要的,不然何必没事找事把东西弄得更复杂呢。最明显的,原来2-tier下请求的处理用的是同步模式(synchronous model),但n-tier下,我们必须使用异步模式(asynchrnous model),这样才可以使前端frontend能不断接受请求而不比等待后端的processing host完成工作(后端的工作显然比前端耗时要长的多)。

考察的重点在于ASP.NET对于connection pool,work thread等一系列benchmark statistics的要求和限制,因此看了一些资料,觉得很好,于是分享给大家(ASP.NET的大牛大概都看过了,呵呵):

1. Contention, poor performance, and deadlocks when you make Web service requests from ASP.NET applications

2. Improving .NET Application Performance and Scalability, Chapter 6 — Improving ASP.NET Performance

3. processModel Element (ASP.NET Settings Schema)

 

下一篇blog我想写一下ASP.NET下应该如何实现异步请求处理,以及ASP.NET内部是如何支持异步处理的。下午看了些.NET framework的源代码,觉得有些意思。

posted @ | Feedback (1) |

Thursday, November 08, 2007

今天Microsoft发布了又一个有趣的应用:Windows Live Messenger IM Control。你可以将Windows Live Messenger IM Control放置于你的主页、blog、或者社交网站(social network website like Facebook)个人页面上,这样访问那个页面的朋友就可以通过IM Control直接和你交流了。IM Control支持IE6, IE7, FireFox 2.0 on Windows以及FireFox 2.0 on Mac OS,并有32种语言界面可选择。

 

以下是简单的翻译介绍(原文出自Angus Logan的blog

1. 首先访问:http://settings.messenger.live.com/applications/websettings.aspx,然后用你的Windows Live ID登陆。

 

2. 选择"Allow anyone on the Internet to see my online status and send me messages":

 

3. 简单地选择你显示“在线状态”的方式:

选项一是只显示一个小图标

选项二是显示完整的Messenger对话框

 

4. 将上面的HTML代码粘贴到你的个人主页、blog、或者社交网站个人页面上。

 

5. 当有人访问配置了IM Control的那个页面时,他/她就可以通过IM Control(按底下的Begin a Conversation)给你发送即时消息了。

 

6. 你可以使用这个网页来测试IM Control: http://settings.messenger.live.com/Applications/CreateHtml.aspx

 

这边是我现在的在线状态 

你也可以通过这个给我发送消息 (最近比较忙碌,so,请手下留情,: ) )

 

觉得这会是个很有趣的应用,比如有在淘宝开店的朋友们就可以在他们的商品页上放一个IM Control,然后即时给浏览他们商品的客户提供服务,: )

 

posted @ | Feedback (11) |

Wednesday, November 07, 2007

上周的buzz word当然是Google的OpenSocial,本来打算周末写一点东西的。结果周六和朋友去BBQ并Halo 3了一天,周日又回公司解决一个bug,昨天回到家实在太累了倒头睡了10个小时,所以一直拖到今天才动手写这个。

 

现在很多关于OpenSocial的讨论都集中在两个主题上:

1. OpenSocial有多Open

2. OpenSocial有多Powerful

我看到的大部分对OpenSocial的批评都集中在第一点上:比如Valleywag说的OpenSocial就是个PR Scam,说OpenSocial根本就不Open。其实完全没必要反应这么激烈,类似的事情又不是没发生过:先给一个硕大的名目,然后下面是一个很弱或者很复杂的标准,最后每个adopter各自搞一套利己不利人的实现。这个用脚趾头就可以想到了,你想MySpaces会把自己积累的用户数据漏出去给Plaxo, LinkedIn, Orkut或者whatever么?反之亦然,你以为这些都是慈善机构啊?最让我哑然失笑的还是ReadWriteWeb上Marshall Kirkpatrick提的第二个问题

Will one network be able to pull in bio, friend and interest data from another?

太天真了吧?

而OpenSocial有多Powerful,从仓促成行而发布的Dev文档上来看OpenSocial API实在是很弱http://code.google.com/apis/opensocial/docs/index.html

老冒说它言过其实,也确实如此。其实如果把这个看作Alpha版,大家也不会苛求功能上要如何如何强大,问题还是这个名称太耸人听闻。OpenSocial,人的脑子嗡的一下就晕了。连忙凑近了要看个究竟,本以为会是九阳真经的,结果发现是残缺的紫霞秘笈。

更大的问题是现有的OpenSocial的实现的安全性实在是千疮百孔。我的同事Scott Isaacs说:It took me 15 seconds to find a gaping security hole on Ning (注:Ning.com是OpenSocial的partner之一). 然后这个漏洞就开始散播开来了:

http://www.semanticwave.com/blog/

http://www.haroldtherebel.com/2007/11/03/peer-prescience/

http://theharmonyguy.com/

从严格意义上来说这个不是OpenSocial的责任,因为OpenSocial只是定义一套API,它可以说自己并不负责security,security是由实现者自己负责的。但我觉得其实OpenSocial的仓促发布才是根本原因,如果不是为了早些出台一个反制Microsoft/Facebook的内容,Google完全有能力在OpenSocial API的底下加固一个security mechanism。

对于Facebook来说,OpenSocial真的不是问题,即使Facebook不去实现,也很容易想见过不了多久就会有其他什么人发布一套基于FBML的OpenSocial实现。所以,如果OpenSocial有足够的影响力,不管Facebook自己做不做,它都会上OpenSocial这条船的。

对于Microsoft来说,应该还是拭目以待吧。这样的标准化策略对微软来说已经不是新鲜事了,从Java到Web service,微软参与过的没有参与过的,反正都见了不少了。Web services搞了那么多年了,那么多大腕参与,现在是个什么状况大家也都心里清楚。OpenSocial如果真的能走远走稳,微软给Windows Live提供一个OpenSocial的实现也不是没可能。反正一个API也不能置谁于死地。

我个人是喜欢标准化的,所以觉得OpenSocial是个好事,不管是微软搞的还是Google搞的,只是因为这样的故事看多了,成功的又很少,所以现在也审美疲劳了。

另:关于Orkut的OpenSocial实现里用到的iframe的通讯机制,如果你有兴趣的话,可以参考以下的资料。Windows Live Contacts Gadget里用到的channel mechanism要比Orkut里的强大多了,这个是题外话:

Secure Cross-Domain Communication in the Browser

Danny Thorpe's blog

[注:以上所有内容属作者个人观点,不代表任何第三方意见和立场。]

posted @ | Feedback (4) |

Monday, October 29, 2007

在餐馆里等晚饭上桌的时候,我翻看着第12期的The Architecture Journal。其时阅读的正是里面的一篇An Application-Oriented Model for Relational Data,在文后的Resources里找到了channel9采访Jose Blakeley(architect working on the ADO.NET Entity Framework)和Dr. Peter Chen (inventor of Entity-Relationship Model)的视频

Dr Peter Chen最初论述Entity-Relationship Model的文章(The Entity-Relationship Model - Toward a Unified View of Data)发表于1976年的ACM TODS,这个简单的事实又一次勾起了我心中存在了很久的一个问题:为什么计算机科学的理论研究和实际应用之间的时差经常这么巨大呢。

我在读硕士的时候在Database group做过两年的research assistant,当时就读了很多二三十年前的paper,而这种情况也不仅仅局限于Database research。Artificial Intelligence, Computer Graphics,很多Computer Science的分支学科都是这样。举个简单的例子,AI里现在很热门的Probablistic Modeling的基础Bayesian Network的很多相关内容都是几十年前的研究成果了。有时会觉得我们在21世纪还读这些1970年代的文章还有没有用?但更现实的是很多70年代的文章里的思想和内容现在都重新翻出来如获至宝地被咀嚼着。

一个原因可能是大部分research的内容确实是没有太大实际价值的,这些大量没有实际价值的成果掩盖了那些少数的有前瞻性的研究。这需要时间的检验和过滤。

第二个原因我想是因为那些真正有insight的观点本来就是超越他们当时的环境的,囿于当时的客观局限,大部分人都无法理解或无法验证这些真知灼见的内涵。就比如爱因斯坦可以很早地推论出大尺度环境下牛顿定律的不成立,但真的要用实验来证实这样的推论,可能还一时无法企及,而因为缺乏实践证明,所以很多人,即使是那些当时拥有最深度思维的头脑,都觉得相对论的结果是难以接受的。

第三个原因是人对自然的认识本身就是一个螺旋上升的过程。即使我们观察到的内容和现象和几十年前相同,但我们对它们的理解却已经达到了另外一个层次,好比一个螺旋上不同层次但同一纬度的两点,从顶上看,它们处于同一位置,但从侧面看,它们已是不同高度。我猜Dr. Chen现在再回头看他自己当年的paper,应该也会有更深的体会和理解了吧。

 

Fun Fact: Google的理论基础之一是Larry Page和Sergey Brin发表于1998年的The Anatomy of a Large-Scale Hypertextual Web Search Engine以及The PageRank Citation Ranking: Bringing Order to the Web ,也许Google这么成功就是因为他们能很快把理论投入应用?(笑...)

 

posted @ | Feedback (4) |

Tuesday, October 16, 2007

Check it outhttp://events.live.com

www.evite.com 运行了已经不少时间了,现在Windows Live也推出了这样的服务:

Windows Live Events还没有公开的API,不过programmability一直是我们(也是Google,Yahoo,Facebook, etc)所关注的内容。你可以在http://dev.live.com 找到最新的基于Windows Live平台的SDK。相信不久就会有更多的Live Service推出它们的API.

posted @ | Feedback (1) |

Sunday, October 07, 2007

上一篇blog还是在6月底写的,然后就是第一年的performance review,再有beta版的开发工作,一直都没有更新。

 

到今天Windows Live Data的Beta基本已尘埃落定(其实两周前已经code freeze了,我又花了一周解决了一些deployment configuration的问题),10月17日是预定的发布日,剩下的这两个星期除了紧急的bug fix外,主要的精力都会放在正式部署(release to production)上。我也有机会可以放放羊,随便看看感兴趣的技术话题,写写自己的一些project.

 

关于Windows Live Data在Alpha版发布的时候我已经介绍过了:Introducing Windows Live Data。Alpha版在最近几周的用户量暴增,令我们小小意外了一下。不过我相信beta会吸引更多的开发人员,一来我们终于有了一个scalable solution,而来beta版说增加的服务也比Alpha版唯一提供的Windows Live AddressBook有意思多了。至于具体是什么,到beta正式发布的那天,我自然会再介绍的。

 

今天因为自己的一个project看了些关于DataSet vs Custom Entity的文章。DataSet vs Custom Entity一直是multi-tier web application/service里很热门的一个争论性话题,如果再加上紧密相关的O/R Mapping,如果排一个Top 10 Issues in Web Application/Serivce的榜单,我觉得这个内容很有希望上榜。

 

如果你有关注最新的LINQ和Entity Data Model的话,也会注意到这些和DataSet vs Custom Entity的讨论有很多的联系。

 

列几个我觉得写的不错的文章:

DataSet vs Custom Entities by Paolo Pialorsi  写得清晰简单,适合初涉者阅读,免得被下面很枯燥的文章搞得哈欠连天的。

Binary Serialization of ADO.NET Objects by Dino Esposito 不是直接谈DataSet vs Custom Entity的,但serialization是比较两者的一个重要关键,所以是值得一读的背景材料。这篇讲的是ASP.NET 1.0中如何处理DataSet的Serialization的。这里有我的阅读笔记:http://docs.google.com/View?docid=dgtfxjqr_1g33dpq

Binary Serialization of DataSets by Dino Esposito 仍然是讲DataSet serialization的,不过这次是ASP.NET 2.0中的改进了(yes!! we have really binary serialization in ASP.NET 2.0!!)。同样,这篇也比较枯燥,我也有简单的阅读笔记:http://docs.google.com/View?docid=dgtfxjqr_2dvvpxz

DataSets vs. Collections by Dino Esposito 读了前面两篇背景资料,终于可以讨论正题了,这篇就是。

Returning DataSets from WebServices is the Spawn of Satan and Represents All That Is Truly Evil in the World by Scott Hanselman 有趣的标题,有趣的文章。

Nix the DataSet?????? by Andrew Conrad 从O/R角度来讨论

The Evolution Of LINQ And Its Impact On The Design Of C# by Anson Horton 最后看看最新的LINQ和EDM

 

之所以列出两篇讨论ASP.NET 1.0 和2.0关于dataset serialization实现的文章是因为我觉得研究一个问题,对它的历史发展和演化做一个了解对我们领会最新的设计思路和思想是很有帮助的。我们不仅可以知道现在是如何做的,也可以知道过去是如何做的,缺陷在哪里,新的设计又是怎么改进那些缺陷的。毕竟,知其然仍是其次,知其所以然才是提高自己设计思维的根本,对么?

posted @ | Feedback (4) |

Thursday, June 28, 2007

Get your free 500MB here: http://folders.live.com

 

 

And let us know what you think

(北京时间6/28/2007, 9:30AM,  刚经朋友提醒查明:中国区服务尚未开通,我faint...)

更新:谢谢aspnetx提供的方法:中国区的用户“在你的IE浏览器把英语-美国[en-US]设置成默认语言就可以”

(但至少还可以下载吧,比如:http://folders.live.com/self.aspx/FXxXLAw2eAI/Public/%e6%9a%97%e6%81%8b%e6%83%85%e4%b9%a6(%e4%bf%9e%e6%80%9d%e8%bf%9c_BiZ%e4%b9%90%e5%9b%a2).mp3

posted @ | Feedback (16) |

Monday, June 25, 2007

前些天正好需要处理一些csv文件(就是逗号分隔文件,常用excel的应该很熟悉),于是想早早.NET里是不是已经有这样的类库了。最后还真的发现了一个。不过有趣的是那个类(Microsoft.VisualBasic.FileIO.TextFieldParser)只有VB.NET的版本。

不过我们是在.NET平台上么,CLR的好处不是只拿来吹吹的。VB.NET写的类,在C#程序里一样能用:

1. 首先Add Refenece(Microsoft.VisualBasic):

2. 然后声明使用的namespace:

using Microsoft.VisualBasic;

3. 接着就可以写代码了, 我加了一些很简单的Schema的功能:

 

using Microsoft.VisualBasic.FileIO; using System; using System.Collections; using System.Collections.Generic; using System.IO; namespace MS.Live.Cumulus.Autopilot.Watchdog { public class CsvParser { /* fields */ TextFieldParser csvParser = null; Dictionary<string, int> textSchema = null; /* methods */ public CsvParser(string inputFile) { csvParser = new TextFieldParser(inputFile); csvParser.TextFieldType = FieldType.Delimited; csvParser.Delimiters = new string[] { "," }; } public CsvParser(Stream inputStream) { csvParser = new TextFieldParser(inputStream); csvParser.TextFieldType = FieldType.Delimited; csvParser.Delimiters = new string[] { "," }; } public void SetSchema(string[] schema) { textSchema = new Dictionary<string, int>(schema.Length); int index = 0; foreach (string field in schema) textSchema.Add(field, index++); // may throw an exception if duplicated field names exist in schema } public string ReadLineRaw() { return csvParser.ReadLine(); } public string[] ReadLine() { return csvParser.ReadFields(); } public string[] ReadFields(string[] filter) { if (null == textSchema) throw new Exception("The parser has no schema defined."); string[] allFields = ReadLine(); string[] result = new string[filter.Length]; for (int i = 0; filter.Length > i; i++) result[i] = allFields[textSchema[filter[i]]]; return result; } /* properties */ public bool IsEndOfData { get { return csvParser.EndOfData; } } }

4. 最后测试一下:

 

public void TestCsvParser() { CsvParser parser = new CsvParser("input.csv"); try { parser.ReadFields(new string[] { "Address" }); Assert.Fail("This line should not be reached"); } catch (Exception) { } parser.SetSchema(new string[]{ "Name", "PhoneNumber", "Address" }); string[] row = parser.ReadLine(); Assert.IsTrue("FakeID1" == row[0] && "FakePhoneNumber1" == row[1] && "FakeAddress1" == row[2]); Assert.IsTrue("FakeID2,FakePhoneNumber2,FakeAddress2" == parser.ReadLineRaw()); row = parser.ReadFields(new string[]{ "Address", "Name" }); Assert.IsTrue(2 == row.Length && "FakeAddress3" == row[0] && "FakeID3" == row[1]); row = parser.ReadFields(new string[]{ "Name", "PhoneNumber", "Address" }); row = parser.ReadFields(new string[]{ "Name", "PhoneNumber", "Address" }); Assert.IsTrue(3 == row.Length && "FakeID5" == row[0] && "hello,Fake\"PhoneNumber5" == row[1] && "FakeAddress5" == row[2]); Assert.IsTrue(true == parser.IsEndOfData); }

 

测试的输入文件如下:

FakeID1,FakePhoneNumber1,FakeAddress1
FakeID2,FakePhoneNumber2,FakeAddress2
FakeID3 , FakePhoneNumber3,FakeAddress3

FakeID4, FakePhoneNumber4 ,FakeAddress4
FakeID5, "hello,Fake""PhoneNumber5", FakeAddress5

posted @ | Feedback (2) |

Thursday, May 10, 2007

Windows Live Data是一个旨在让第三方开发者在任何一个Windows Live用户访问他们网站时,利用每个特定用户的Windows Live Service和Data(当然,前提是用户信任这个第三方的开发者/网站并给于了开发者/网站相应的权限来访问他们的个人数据)来提供更丰富更个性化的用户体验的项目。你可以把Windows Live Data看成是一个Web API,它现在只开放了指向用户地址簿(就是你的hotmail/msn messenger里的那些联系人)的接口。你也可以把Windows Live Data看成是一个authentication系统。但Windows Live Data最本质的还是一个基于HTTP/HTTPS的提供数据访问支持的REST协议。

 

Windows Live Data在Mix 07上发布的是Alpha版本的系统,开放的接口也只有用户的地址簿(Address Book)。但很快的,我们会开放Spaces Photo的接口。进入Beta后,会有越来越多的Windows Live Service通过Windows Live Data来开放他们的数据,而对于第三方开发者/网站来说,他们只需要通过一个通用的协议,一个通用的authentication系统,就可以访问到各种不同的windows live service的信息(如address book, spaces photo, spaces blog, expo listing, live favorites, etc)。

Windows Live Data支持三种不同的authentication的方式(下面有详细介绍的文章链接)。用户也可以通过username/password的方法来访问自己的数据。你可以想象在Windows Live Data的帮助下,我们可以开发出各种各样的mashup应用。

如果你想开始了解一下Windows Live Data,可以从下面这篇文章开始(注,这篇不是微软的官方文档,但我觉得写得很短小精干,10分钟就读完了):

http://weblog.infoworld.com/stratdev/archives/2007/05/data_wants_to_b.html

 

然后MSDN里有更详细的介绍文档:

Windows Live Data

以及专门讨论addressbook接口的:

Contacts API

如果你对协议感兴趣的话,可以看看Web3S的spec和FAQ:

Web3S Spec, FAQ

如果读文档没劲的话,也可以看看在Mix 07上的现场演讲:

Play (Silverlight)Download WMV

最后,有问题的话,可以到这里讨论:

Forum

 

注:Windows Live Data现在还处于Alpha版,所以我们并不建议你基于它搭建什么稳定的产品。这个现在还是实验系统,我们希望能有更多的开发人员来试用它并提供宝贵的反馈。

posted @ | Feedback (11) |

Wednesday, April 25, 2007

昨天处理了一个奇怪的duplicated data entry的问题。我们的ASP.NET前台网页里有这么一个HtmlButton控件:

<button runat="server" type="submit" id="yesButton" onserverclick="yesButtonClick">Click this</button>

 

在codebehind的yesButtonClick代码里我们会向一个web service发送一个请求来添加一个数据项:

protected void yesButtonClick(object sender, EventArgs e) { // send request to the database web service }

 

在独立的UI automation测试的时候我们并没有发现问题。但在stress test的时候,我们发现数据库在很偶然的情况下会有两个一摸一样的数据项,并且他们的creation time stamp也是一摸一样的。而我们一直以为所有的数据项都是可以通过一个data field来唯一确认的,所以重复的data entry会给后来的程序逻辑带来很大的麻烦。

很显然在stress test的时候,我们在更新数据库的时候触发了很不容易发现的race condition而导致两个添加数据库记录的同时被执行了,而数据库方面也没有primary key这样的唯一性支持,而只是在添加一条记录前检查一下表内是否已经有了同样的一条记录,如果有就不添加,如果没有再添加,而这显然是无法避免race condition的,是数据库接口设计上的失误。

关键问题在于为什么我们的ASP.NET会同时触发两个添加记录的请求。研究了一下后才发现原来是yesButtonClick给调用了两次。一次是因为onserverclick(被ASP.NET的引擎转化为这样的客户端javascript: onclick=__doPostBack(...) ),另一次是因为type="submit"这个属性。因为每个aspx页面的最外层都是一个巨大的form,这个form的method是POST,action就是缺省就是页面本身。所以当把一个button的属性设置为submit的时候,button click这个时间就会自动触发一个form post,这样在服务器端,yesButtonClick就又被调用了一次。

解决的方法很简单,只要去掉type="submit"就好了。

我觉得这也许算不上一个bug,因为对ASP.NET引擎来说它生成的都是完全合法的html和javascript。但为什么有submit button引起的form post会在服务器端触发button click event handler是我不解的,或者说,我觉得不应该这样设计,或者至少该有个什么样的警告。而且我可以想见在某些情况下程序员有足够的理由一定要放上type="submit"这个属性,那时候怎么办?只能看着yesButtonClick被调用两次?

希望对以后碰到过同样的问题的朋友有些帮助。

posted @ | Feedback (4) |

Monday, April 23, 2007

想不出blog的标题时,我通常就写上Random Thoughts以作权宜,: )

Project的Alpha版已经进入RC2了,我们的项目会在一个星期后的Mix 07上发布,从去年9月中正式开始开发到今天Alpha版的基本尘埃落定,终于可以收拾一下散乱的心情做下来按自己的步调工作和学习一段时间了。

我们可能成功可能失败,但毕竟这是对几年来业界里于Web Service/SOAP/WSDL/UDDI等概念盲目狂热的一种很好的反思。我依稀记得我第一次接触SOAP时觉得这个东西居然也能自称“simple” (object access protocol) 实在是太大言不惭,而后来发现的更多很诡异的设计越发让我目瞪口呆。比如说WSDL和Proxy class这个东东,试想,你发布一个Web Service version 1.0后有很多用户下载了你的WSDL,生成了他们的Proxy class,编译了他们的程序,大家都很开心地过着和谐的生活。但某一天,用户突然发现他们的客户端全完了,不能用了,原因是你升级到version 2.0了,你原来的web service里定义了一个叫做weekday的enum类型,有7个值(monday - Sunday)。而在v2.0里这个enum含有8个值了(为了庆祝全球人民大团结,联合国决定一个星期有8天,第8天叫Crapday)。问题是这个enum类型通过WSDL和proxy class被紧耦合于客户端的程序中,但现在你的服务端的enum已经有13个值了...... 于是你告诉大家客户端也要跟着升级,而升级唯一的方法(注:在实际生活中被使用的,而不是理论上的it should work this way)就是通过email附件把新的WSDL文件发给各位亲爱的用户,他们要重新生成Proxy class,重新编译(without knowing if it will blow away their whole project or not),重新进行客户端unit testing,重新....... 于是客户很生气,后果很严重......

所以很庆幸有这么一个机会可以亲手做一些anti Web Service/Soap/Wsdl/Uddi的东西。我们只想尽量的利用http协议提供的能力,不去发明什么眼花缭乱的evenlop、action header、blahblah,就是利用基于http的REST协议来存取分布式的数据,看看我们能做到什么程度。当然所有美好的想法都要经过实践的检验,我们做了自己心中的技术,但是否为大家所接受,我们无法预言,: )

Anyway,下星期天就要去Las Vegas参加Mix 07了。我一向懒怠拍照,希望这次能勤奋些做些现场报道回来给大家看看,: )

另:偶然发现,我在intern时做过的一些东西现在已经收入MSDN了:http://msdn2.microsoft.com/en-us/library/ms776235.aspx  呵呵,我并没有参与最后收录MSDN前的编辑工作,不过看起来变化不大,甚至连screen shot也是那时我在自己的test machine上截取的那些。不知道有多少人真的熟悉MUI技术或者对它感兴趣,我那时候总是要和别人解释:no, it's not about doing English-Chinese translation,: )

"刚才在Keso那里看到贝壳网的创业以失败告终,突然触动了一个心事。以前这个想法一直很模糊,但刚才突然一下子很明朗了:很想有一天能放下一切,去杭州为一个startup工作一段时间。在那样的山水间纯粹地为自己的理想工作,应该是一件很快乐的事。" (以上引用自我的msn spaces blog)

posted @ | Feedback (6) |