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都意识到了这个问题,也在想办法提供解决方案。
好吧,我承认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呢。
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:
BeginProcessRequest
Initiates an asynchronous call to the HTTP handler.
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
这些天在考虑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的源代码,觉得有些意思。
今天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,然后即时给浏览他们商品的客户提供服务,: )
上周的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
[注:以上所有内容属作者个人观点,不代表任何第三方意见和立场。]