2009年3月18日星期三

互联网时代的软件革命:SaaS架构设计

  前段时间看完了《互联网时代的软件革命:SaaS架构设计》这本书,感触颇深。虽然很多企业早在2000年就搞ASP(Application Service Provider,应用服务提供商),但很少见有人能写书将其中一些知识共享出来,这本书虽然写的比较晚,但也在软件行业做了一件有意义的事情。

  从内容上看,此书大致讲述了传统软件和互联网技术相结合的技术架构,以及服务器、群集、缓存、分布式文件系统以及云计算等解决方案。这本书的整体风格较为活泼,借金庸武侠人物虚构一个创业公司的业务来逐步说明问题,让一本技术书籍看起来也不算枯燥。书的开头先对SaaS的概念和一些基本的常识做了较为详细的介绍,接着较大的篇幅是在讲网站架构的相关技术,如数据库层、应用层、Web层性能优化,可配置性、可伸缩,然后讲述了一些编程方面的安全问题和离线应用,最后又提了一下云计算的实现方案和Open API。技术上没有深入的讲,点到为止。

  目前很多软件公司都在逐步从传统软件行业转向SaaS领域,这本书的目标用户就是这些传统软件公司的开发人员,这些开发者的转型,如果只是依靠自己独立摸索,要花费很大的时间和精力,而此书的作者正是一些已经转型的开发者总结的经验之谈,可以帮助后来者快速掌握相关知识,避免走一些弯路,这种知识共享的精神值得夸奖。

  不过,这本书也有一些不足之处,例如书名是《SaaS架构设计》,会误导初学者以为SaaS是一种开发技术,从内容上看,讲的面面俱到,每个方面都讲了,但很多地方都没往深层方面讲透,解决方案过于简略,也可能是因为篇幅问题吧,也可能是将开发者引进门,让开发者自己去探索。另外,这本书过多加入了阿里巴巴公司的内容有点败笔,这使得此书的中立性大打折扣,并且可能会引起同行开发者的反感,号称是“国内第一本完整介绍SaaS应用开发的书籍”,让人感觉有炒作的嫌疑,当然这种策略对于推广公司的名牌和知名度还是起到很大作用,也算是另一种新形式的企业营销,这种以出书的方式进行营销在软件行业内还很少见,是一种低成本高回报的营销方式。

  总的来说,写本书对整个软件行业是一件有意义的事情,这种乐于将知识分享的精神也值得大家学习和推广。

  最后提一句,我是从卓越网购买的这本书,送货时间只花了一天,真是太快了。

RSS客户端工具——网铃阅读器

  RSS订阅已经成为了网络上非常普及的一种新闻聚合方式了,要订阅RSS链接,当然,你必须要有一个RSS阅读器。常用的在线RSS阅读器有Google Reader、QQ阅读器、鲜果等等,然而,在这么多的选择面前,如果你希望找一款桌面式的实时RSS阅读器,不妨试试网铃阅读器。

  网铃阅读器是MSN Shell的开发者小溪开发的又一款小巧实用的免费软件,可以实现实时订阅,一旦有任何更新,你就会第一时间在桌面上收到提醒。值得一提的是,这样一个可以实时更新大量信息的软件却非常小巧,整个程序仅不到1M,运行时仅占2M内存。

  开始使用

  从网铃阅读器的官方网站下载到最新版本,官方提供安装版和绿色版两种选择,目前还是BETA版本。网铃阅读器能够运行在Windows 2000以上操作系统,需要安装Internet Explorer 6.0或以上版本。不过,经试用发现,在IE6环境下尚存在一些BUG,诸如滚动条下箭头不能点击,某些RSS链接不能订阅。所以,建议有条件朋友的尽可能在IE 7.0的系统上使用。

  首先,你当然要添加RSS链接才能收到更新提醒。第一次运行时它会提醒你没有任何订阅,询问是否马上添加网摘,点击是马上打开订阅向导。网铃阅读器提供三种订阅方式,最普通的方式,你可以输入一个RSS链接地址订阅。如果你不知道要订阅什么内容,不妨从它内置的网摘库中选择一些。网铃阅读器内置了百度、谷歌、搜狐、网易和新浪的所有网摘,共计463条之多,肯定有你感兴趣的内容。

网铃阅读器

  除此之外,使用自定义关键字订阅功能,你甚至还可以订阅搜索结果。如果你是暗黑迷,那么就使用这个功能输入“暗黑3”吧,你会实时收到有关暗黑3的最新消息。

  完成订阅后,你就会收到你的第一个提醒。从此,你不再需要为寻找更新而操心,有任何更新马上会第一时间在桌面上收到提醒。

  如果你觉得这个窗口太小,可以按一下快速查看按钮,马上会弹出一个大窗口供你浏览,你还可以随时通过按F9热键呼出快速查看窗口浏览最近更新。

网铃阅读器

  如果你偶尔看到了一条很有趣的信息,想与你朋友分享。你只需要简单地按一下引用按钮,这条信息的标题和链接就复制到了剪贴板,你可以粘贴到MSN或QQ上与好友分享。

  点击置顶按钮,提醒窗口就会被“钉住”了,直到你按关闭按钮,或取消置顶它才会关闭。在此期间,你可以放心地翻阅更新内容。不过,当一个提醒窗口被置顶的时候,后面所有的提醒都会排着队等待它关闭。所以,别忘了关闭它,否则后面排队的消息就要等急了。

  配置和选项

  网铃阅读器是一个很小巧的软件,在配置对话框中的选项并不多,但却提供了最实用的功能。你可以指定你常用的浏览器来打开网页链接;切换到你喜欢的语言界面,没错,它还是多语言的。

  在提醒选项中,甚至还提供了全屏检测功能。开启该功能后,网铃阅读器将不会在你玩游戏或看电影时弹出提醒窗口,这是一个非常体贴的设计。

  而在声音选项中,你可以任意选择喜欢的声音作为弹出提醒窗口的铃声。

网铃阅读器

  内存评测

  作为一款常驻后台运行的软件,尽可能占用少量的内存是很重要的。在这方面,网铃阅读器的表现非常出色。从任务管理器中可以看到,网铃阅读器的进程仅仅占用了2M物理内存和10M虚拟内存,并且在连续运行24小时以上仍然保持了这个数值,没有发现任何内存泄漏情况。

  以上是我们在有20条订阅网摘情况下的数值,许多人都会想到,内存使用量应该会随着订阅的网摘数量增加而增加,也许当有很多订阅的时候内存使用量就不会这么少了。为此,我们特别测试了超过100条订阅的情况。虽然在刚运行时同时检测百余条网摘使内存使用量增长到了10M左右,但当第一次检测完后,内存竟仍然保持在2M左右。

  根据网铃阅读器的开发者的解释,网铃阅读器仅使用一个单独线程监控所有订阅的网摘,仅当需要检查时才带出相应线程,并且在检查完毕后立即释放,它并不是为每一个订阅都建立一个独立线程。因此,即使是有大量的订阅,仍然可以保持最低的内存使用量。当然,检测时的内存使用量是无法避免的,大量的检测会使用略多的内存也是在所难免。

  然而,我们并不建议你订阅很多网摘。即使你不用担心内存问题,大量的订阅也会弹出大量的提醒窗口。因为信息太多而无法阅读,那就适得其反了。

网铃阅读器

  许多程序员朋友可能会觉得不可思议了,像这样一个界面如此复杂的程序,怎么可能只用这么点内存?其实,进一步仔细观察的话会发现,网铃阅读器在运行中采用了多进程的方式。我们看到常驻内存的仅仅是一个代理进程,而当有提醒窗口弹出,或是打开快速查看窗口时,还是挺占内存的。但是,那只是一时的,关闭后内存将会被完全释放,而主代理进程不会有任何内存增长。网铃阅读器的这个设计非常巧妙,可见开发者在内存问题上着实是花了一番心思了。

  同类软件比较

  其实,虽说现在的RSS阅读器很多,但我们却发现很难找出一款与网铃阅读器功能类似的软件。其主要原因是,目前绝大多数RSS阅读器都没有比较理想的实时提醒功能。

  Office Outlook,Windows Live Mail等:用这两个邮件客户端订阅RSS是最方便不过了,然而,它们都无法实时提醒你最新更新的信息。同时,50多兆的内存使用量也使其不适合常驻后台运行。

  Internet Explorer,Maxthon等:浏览器内置的RSS订阅功能,阅读起来确实挺方便,但却没有实时提醒的功能,内存占用率同样非常大。

  Google Reader、抓虾、鲜果等:在线阅读器无需安装,但必须使用浏览器打开网页才能使用,你不可能永远开着网页。显然不能满足实时信息到达提醒的需求,更不适合常驻后台运行。

  Feed Demon:这是我们能够找到的最有可比性的同类软件了,它除了有比较强大的阅读功能之外,同样也有桌面提醒功能。但是,它的桌面提醒只能看到有多少条更新,并不能看到具体内容,只是像邮件通知一样而已。30多兆的内存使用量,显然不能与网铃仅2M的使用量相提并论。而它内置的News Gator服务器访问速度也很慢,导致许多操作都很难进行。

  MSN Alert:据开发者介绍,网铃阅读器的创意就源自MSN Alert.目前,中国大陆地区的MSN Alert供应商由哪吒网提供。除了像MSN本身一样,服务器经常无法连接的问题之外,最大的遗憾是它只能一次弹出一个提醒窗口。因为无论你在它上面订阅多少RSS,最终只有哪吒网一个Alert会显示在提醒窗口中,而你需要点击相应的标签进入才能阅读更多内容。在使用上有很多不便之处,也无法真正实现每个订阅的实时提醒。

  如果只比较实时提醒功能,我们几乎找不出一款能与网铃阅读器相提并论的同类软件。但是,如果比较阅读器功能,网铃阅读器则完全不如目前绝大多数同类软件。所以,如果你只是比较注重实时提醒功能,那么网铃阅读器一定会令你爱不释手。但如果你需要一款真正的阅读器,它可能并不适合你。

  据开发者介绍,目前网铃阅读器只是BETA版本,在正式版中,将会有同样强大的阅读器功能。届时,网铃阅读器应该会成为同类软件中较为出色的一款产品了。

  内部爆料

  调试模式?据开发者小溪透露,网铃阅读器隐藏了一个调试模式。在这个模式下,你可以看到所有订阅的网摘在内部线程中的运行情况。

  进入调试模式的方式,是在启动参数中加入/debug参数。找到网铃阅读器的安装目录,一般会在C:Program FilesFeed Alert.建立一个alert.exe的快捷方式,编辑快捷方式的属性,在目标命令行最后添加/debug参数,如:"C:Program FilesFeed Alertalert.exe" /debug,注意应该添加在引号外面,并且有一个空格。然后双击这个快捷方式启动,右键单击任务栏图标,会发现弹出菜单中多了一项调试窗口。

网铃阅读器

  在这个调试窗口中,你可以看到所有订阅的线程状态,下次检查时间,最后返回的信息,以及错误日志。如果你发现了问题,而又有兴趣研究一下为什么,获取这个模式可以帮助你。将你的发现反馈给开发者,也许会在下一个版本中修复你反映的问题哦。

  网铃阅读器官方网址:http://www.feedalert.cn/

2009年3月17日星期二

从WordPress转换到Z-Blog的方法

  我以前曾经介绍过将Z-Blog数据库转换到WordPress的SQL语句,做为反例,还会有从WordPress系统转换到Z-Blog系统的SQL语句,这是一个比较奇怪的话题,估计也很少有人这么做,不过对于某些特殊情况,我们有可能会将WordPress数据库转换到Z-Blog的Access数据库,这里我介绍一下手动使用SQL语句进行转换的方法。

  首先在WordPress中建立一个和Z-Blog文章表、目录相同结构的表,建立的SQL语句如下:

CREATE TABLE blog_Article (
 log_ID int NOT NULL ,
 log_CateID int NULL ,
 log_AuthorID int NULL ,
 log_Level int NULL ,
 log_Url varchar (255)  NULL ,
 log_Title varchar (255)  NULL ,
 log_Intro longtext  NULL ,
 log_Content longtext  NULL ,
 log_IP varchar (15)  NULL ,
 log_PostTime datetime NULL ,
 log_CommNums int NULL ,
 log_ViewNums int NULL ,
 log_TrackBackNums int NULL ,
 log_Tag varchar (255)  NULL ,
 log_IsTop varchar (10) NOT NULL
)  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;

CREATE TABLE blog_Category (
 cate_ID int NOT NULL ,
 cate_Name varchar (50) NULL ,
 cate_Order int NULL ,
 cate_Intro varchar (255) NULL ,
 cate_Count int NULL
) DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;

  由于Z-Blog的数据库结构相对Z-Blog要复杂的多,因此转换之前还要进行一些目录ID的处理,其SQL语句如下:

update wp_posts, wp_term_relationships set wp_posts.post_category = wp_term_relationships.term_taxonomy_id where wp_posts.id=wp_term_relationships.object_id and wp_term_relationships.term_taxonomy_id in (select term_taxonomy_id from wp_term_taxonomy where taxonomy ='category')

  这个语句将目录ID保存到了wp_posts表中,这样以后转换会方便一些。

  接下来,执行下面的语句,转换文章表结构。

INSERT INTO blog_Article (log_ID,log_CateID,log_AuthorID,log_Level,log_Url,log_Title,log_Intro,log_Content,log_PostTime,log_CommNums) select id, post_category, post_author, 4, id, post_title, post_excerpt, post_content, post_date, comment_count from wp_posts

  转换成功后,我们需要安装一个MYSQL工具,名字叫MySQL ODBC Connector,安装完成后,在ODBC中建立一个MySQL的数据源。

  最后,打开Access文件,点“获取外部数据”-“导入”,选择“ODBC数据库”中的MySQL数据源,导入blog_Article表即可,这样就可以将WordPress的文章内容导入到Z-Blog中了。

  以上方法直接使用SQL语句转换数据库结构,适合大量数据的导入导出。少量数据可以通过导出XML文件的方式进行转换。

2009年3月16日星期一

Jaiku开源并提供源代码下载

  Google曾经收购的类Twitter平台Jaiku现在已经完全开源并且切换AppEngine上运行,早前Google曾经宣布停止Jaiku等项目的维护和开发,现在更将Jaiku完全开源提供用户免费下载,所有人都可以在自己的主机上建立和运行自己的Jaiku应用了。

  以前的Jaiku的IP从中国是无法访问的,切换到AppEngine后,现在已经可以访问,并且不需要邀请码也可以注册,我在上面的注册的一个地址访问都是正常的,但Jaiku面临的挑战是,用户愿意注册一个不再提供维护的服务吗?不过,Jaiku提供的Python源代码还是值得大家下载研究的,我们自己搭建一个“饭否”不是很有趣吗?

  Jaiku源代码项目地址:http://code.google.com/p/jaikuengine/

Google Reader翻译支持中文

  我以前曾经介绍过Google Reader支持翻译功能,可以点击文件夹或者Feed后,在“文件夹选项”和“供稿设置”里选择“翻译到我使用的语言”。目前这项功能已经支持中文。

  使用前需要将Google Reader的语言选择为中文,才能将英文的文章翻译为中文,翻译引擎使用的是Google自己的翻译引擎,说句老实话,从英文翻译为中文的文章,进行阅读的话,基本要靠“猜”才能明白意思,不过也没办法,Google翻译总体来说已经是做的最好的了。

  不过根据我的测试,从中文翻译到英文的话,效果其实还是不错的,估计是中文实在太复杂,不太好翻译过来吧。

Google Reader翻译支持中文

2009年3月15日星期日

微软Windows Live照片库升级

  前段时间MSN的自动升级另我感到很不舒服,不过升级完成后,我发现其中的Windows Live照片库(Windows Live Photo Gallery)有一些不错的新功能,修复了以前的一些BUG,从功能上已经直追Google Picasa了。这里我就介绍一些Windows Live照片库的一些特色功能。

  上传限制取消

  Windows Live的网络相册地址是photos.live.com,以前有每月500张上传照片的限制,现在这个限制取消了,用户可以随心所欲的将照片上传到多达25G空间的个人相册中,相比之下,Google Picasa网络相册仅提供1G的免费存储空间。

  提供插件支持

  通过插件可以很好的支持第三方的网络相册,Windows Live照片库默认除了支持自己的Windows Live相册之外,还支持Flickr和Picasa相册,我在Flickr上的那几百张照片,都是通过这个软件上传的,上传体验很不错。另外,使用插件,还可以支持Facebook、YouTube、SmugMug、Drupal等网络相册和服务,Windows Live的开放性可见一斑,相比之下,Google Picasa的第三方插件较少,对于Flickr等第三方相册支持也很弱。

  人脸识别功能

  Windows Live照片库可以自动识别照片中的人脸,这个功能其实Google Picasa也有脸部识别功能,不过Windows Live照片库的一大特色就是和Live Messenger整合,直接将照片中识别出来的人脸进行标记,并把这些标记与Live Messenger的好友列表相关联,这是一大特色。

Windows Live照片库

  总的来说,升级版的Windows Live照片库还是有不错的特色功能,是Google Picasa的一个有力的竞争对手。

2009年3月13日星期五

基于REST架构的Web Service设计

  先前我曾经介绍过利用Apache Axis实现基于SOAP的Web Service实现技术和相关代码,总的来说,SOAP的Web Service解决方案虽然较为成熟,且安全性较好,但是使用门槛较高,在大并发情况下会有性能问题,在互联网上使用不太普及,因此并不太适合Web 2.0网站服务使用,目前大量的Web 2.0网站使用另外一种解决方案——REST。

  REST的架构设计

  REST(Representational State Transfer)是一种轻量级的Web Service架构风格,其实现和操作明显比SOAP和XML-RPC更为简洁,可以完全通过HTTP协议实现,还可以利用缓存Cache来提高响应速度,性能、效率和易用性上都优于SOAP协议。

  REST架构遵循了CRUD原则,CRUD原则对于资源只需要四种行为:Create(创建)、Read(读取)、Update(更新)和Delete(删除)就可以完成对其操作和处理。这四个操作是一种原子操作,即一种无法再分的操作,通过它们可以构造复杂的操作过程,正如数学上四则运算是数字的最基本的运算一样。

  REST架构让人们真正理解我们的网络协议HTTP本来面貌,对资源的操作包括获取、创建、修改和删除资源的操作正好对应HTTP协议提供的GET、POST、PUT和DELETE方法,因此REST把HTTP对一个URL资源的操作限制在GET、POST、PUT和DELETE这四个之内。这种针对网络应用的设计和开发方式,可以降低开发的复杂性,提高系统的可伸缩性。

  REST的设计准则

  REST架构是针对Web应用而设计的,其目的是为了降低开发的复杂性,提高系统的可伸缩性。REST提出了如下设计准则:

  网络上的所有事物都被抽象为资源(resource);

  每个资源对应一个唯一的资源标识符(resource identifier);

  通过通用的连接器接口(generic connector interface)对资源进行操作;

  对资源的各种操作不会改变资源标识符;

  所有的操作都是无状态的(stateless)。

  使用REST架构

  对于开发人员来说,关心的是如何使用REST架构,这里我们来简单谈谈这个问题。REST不仅仅是一种崭新的架构,它带来的更是一种全新的Web开发过程中的思维方式:通过URL来设计系统结构。REST是一套简单的设计原则、一种架构风格(或模式),不是一种具体的标准或架构。REST有很多成功的使用案例,著名的Delicious和Flickr都提供基于REST风格的API使用,客户端调用也极其方便,下面是我用ASP写的一个很简单的REST举例,从中可以看出REST是多么的简单易用。

  客户端代码:

Private Function httpGet(url, method, data)
    Dim xmlhttp
    Set xmlhttp = Server.CreateObject("MSXML2.ServerXMLHTTP")
    xmlhttp.open method, url + "?" + data, False
    xmlhttp.setRequestHeader "Content-Type", "application/x-www-form-urlencoded; charset=UTF-8"
    xmlhttp.setRequestHeader "Content-Length", Len(data)
    xmlhttp.send (Null)
    If (xmlhttp.Status = 200) Then httpGet = xmlhttp.responseText
    Set xmlhttp = Nothing
End Function

Private Function httpPost(url, method, data)
    Dim xmlhttp
    Set xmlhttp = Server.CreateObject("MSXML2.ServerXMLHTTP")
    xmlhttp.open method, url, False
    xmlhttp.setRequestHeader "Content-Type", "application/x-www-form-urlencoded; charset=UTF-8"
    xmlhttp.setRequestHeader "Content-Length", Len(data)
    xmlhttp.send (data)
    If (xmlhttp.Status = 200) Then httpPost = xmlhttp.responseText
    Set xmlhttp = Nothing
End Function

Private Function httpPut(url, method, data)
    Dim xmlhttp
    Set xmlhttp = Server.CreateObject("MSXML2.ServerXMLHTTP")
    xmlhttp.open method, url, False
    xmlhttp.setRequestHeader "Content-Type", "application/x-www-form-urlencoded; charset=UTF-8"
    xmlhttp.setRequestHeader "Content-Length", Len(data)
    xmlhttp.send (data)
    If xmlhttp.Status >= 400 And xmlhttp.Status <= 599 Then
        response.write " Error Occurred : " & xmlhttp.Status & " - " & xmlhttp.statusText
    Else
        response.write xmlhttp.responseText
    End If
    If (xmlhttp.Status = 200) Then httpPut = xmlhttp.responseText
    Set xmlhttp = Nothing
End Function

Private Function httpDelete(url, method, data)
    Dim xmlhttp
    Set xmlhttp = Server.CreateObject("MSXML2.ServerXMLHTTP")
    xmlhttp.open method, url + "?" + data, False
    xmlhttp.setRequestHeader "Content-Type", "application/x-www-form-urlencoded; charset=UTF-8"
    xmlhttp.setRequestHeader "Content-Length", Len(data)
    xmlhttp.send (Null)
    If xmlhttp.Status >= 400 And xmlhttp.Status <= 599 Then
        response.write " Error Occurred : " & xmlhttp.Status & " - " & xmlhttp.statusText
    Else
        response.write xmlhttp.responseText
    End If
    If (xmlhttp.Status = 200) Then httpDelete = xmlhttp.responseText
    Set xmlhttp = Nothing
End Function

response.write httpPost("http://localhost/rest/service.asp", "POST", "do=POST")
response.write httpGet("http://localhost/rest/service.asp", "GET", "do=GET")
response.write httpPut("http://localhost/rest/service.asp", "PUT", "do=PUT")
response.write httpDelete("http://localhost/rest/service.asp", "DELETE", "do=DELETE")

  服务端代码:

Response.Write Request.ServerVariables("REQUEST_METHOD")
If (Request.ServerVariables("REQUEST_METHOD")="GET") Then
 Response.Write "DO GET" + Request("do")
ElseIf (Request.ServerVariables("REQUEST_METHOD")="POST") Then
 Response.Write "DO POST" + Request("do")
ElseIf (Request.ServerVariables("REQUEST_METHOD")="PUT") Then
 Response.Write "DO PUT" + Request("do")
ElseIf (Request.ServerVariables("REQUEST_METHOD")="DELETE") Then
 Response.Write "DO DELETE" + Request("do")
End if

  需要注意的是,IIS服务器默认是不支持ASP文件的PUT和DELETE操作,默认会返回“403 - Forbidden”错误,因此需要修改IIS的设置,修改方法是:管理根据-IIS信息服务器-网站-属性-主目录-应用程序配置-配置-映射,选择ASP - 编辑 - 修改为全部动作。

  关于更多关于REST方面的知识,建议阅读《RESTful Web Services》这本书。