2008年12月28日 23:16
看到大家都在总结08,我觉得我的08没什么好总结的。那就来点新年的新构想吧。—— 好吧,主要还是家里的网络。
实践证明,有了小虫之后,全家其乐融融的坐在客厅看电视基本上已经是可望而不可及的奢求了。现在只能在小虫上床之后躲在卧室里看。于是很自然的,原先架构的在客厅电视上播放电脑视频的方案就没有了用武之地。而且随着在床上使用电脑机会的增加,每天背着14寸笔记本骑车上下班也不太现实。一只轻便的上网本配合无线的方案就摆到了眼前。
今天跟LP讨论了这样一个方案:
- 升级卧室的电视机——换成28寸(暂定)液晶。带数码接口。用于看电视和播放视频。预算 3000-4000
- 一只上网本,用于在卧室的上网、编程、聊天以及接到电视机看片。暂定EeePC系列(我看上了那个Eeebuntu系统。咔咔)。预算3000左右
- 一个NAS存储服务器。考虑到笔记本和服务器内置硬盘的不可靠性及容量限制,另外今天看到猛禽在饭否上的抱怨,感觉DVD刻录也是不靠谱的,所以决定把我一直设想的存储服务器付诸实践。考虑到价格因素,决定还是DIY。这样用2000左右的成本可以构建出安全快速并且大容量的系统。(目标,2T,SATA,RAID5)
- 无线键鼠。当播放电影时,用于远程控制。
- 现在的服务器仍然做本职的工作,但影音数据及关键性数据通过NFS存储到NAS上去。
- 加重了无线在网络架构中的比重,因此视情况而定,可能需要升级无线路由器。
整个方案的费用大约是10000,不包括安装调试和浪费在上面的时间和精力。但是这个架构尽量的保留了原有的组件,但比以前那个基于有线网络的架构要轻便灵活得多了,尤其是将存储分离之后,基本上可以尝试集中的影音存储,通过网络流式播放的方案,这样对播放机的要求就降了很多,也避免了文件拷来拷去的麻烦。只是带宽这一节恐怕是瓶颈。
不知道各位看官有没有意见和建议?
2008年12月18日 12:40
因为现在Linux接触得多了,但是因为工作原因不能放弃Windows平台,于是就选择在自己的机器上装了一个虚拟机,在虚拟机里安装一个小型的Linux以备日常测试使用。自从听说了VirtualBox之后,我毫不犹豫的将原先的VMware换成了它。原因很简单,第一小巧,第二免费。
但是VirtualBox至少在网络方面,的确是没有VMware方便。VMwaere在使用NAT模式的时候,主机上会有一个虚拟的IP,可以直接通过这个IP和客户机进行通讯。而VirtualBox的NAT是没有主机IP的,虽然客户机可以直接上网,主机和客户机之间却无法通过网络进行通讯。而如果采用Host Interface模式的话,客户机想上网就需要在主机配置路由或网桥,十分不方便。
后来久而久之的我摸索出了一种既方便上网又方便主机客户机通讯的方法,说白了其实很简单:就是在客户机上配置2块网卡,一块是NAT模式用于上网,这个是免配置的,另一块是Host Interface用于主机和客户机通讯,但是不用考虑上网的问题。
在以前的版本中,当你选中Host Interface的时候,会需要你在下面的Host Interfaces里添加一个“虚拟网卡”,这个网卡会在“网络连接”里增加一个连接图标,这相当于是跟虚拟机连接的网卡界面,我们可以为它配置一个静态IP地址,然后在客户机里,为对应的网卡配置一个同网段的静态IP地址,这样就可以通过这两个IP地址互相访问了。
但是这个做法有一个问题,因为那个虚拟的网卡是单独的,每次当我升级VirtualBox的时候,这个网卡就会失效,每次要重新配置一个新的才行。另外,当虚拟机关闭的时候,主机里对应的网络连接就会弹出一个“网络已断开”的消息,虽然没什么影响,总觉得不太爽。
今天VirtualBox 2.1出了,我一如既往的选择了升级。重启虚拟客户机的时候,一如既往的给出了一个网络界面不存在的错误。刚开始的时候我以为跟往常一样,只要去重新添加一下Host Interface就OK了。
谁知一看到配置界面,我就愣了。这次的界面不一样了,Host Interface不再是空空如也,而是将目前系统里已存在的连接界面都列在了里面,而且也没有了增加和删除的按钮。
感觉不对的我赶紧去查了一下ChangeLog,果然看到了一条:
* New Host Interface Networking implementations for Windows and Linux hosts with easier setup (replaces TUN/TAP on Linux and manual bridging on Windows)
然后再去看帮助,帮助里只提到使用了新的机制,却对设置方法只字未提。(这什么烂帮助啊……)最后没办法只好求助于社区。还好社区里有人碰到了类似的问题,解决方法也很简单,只要在虚拟机里绑定一个现有的网络连接,而在网络连接中,TCPIP属性,高级,增加一个IP地址就可以了。(相当于在同一个网卡上划分VLan)
这个做法并不能解决NAT的问题,因此我的双网卡方案还得继续,但是Host Interface的设置确实是简化了很多,不需要额外虚拟网卡的支持了,效率也可以提高很多。而且还解决了以前VirtualBox里无法正常使用ICMP echo的问题。后来想想,这种VLan方案,在Linux Host上配置也会方便很多的。
另外,VirtualBox 2.1的改进中,我比较感兴趣的还有:
- Support for 64-bit guests on 32-bit host operating systems (experimental; see user manual, chapter 1.6, 64-bit guests, page 16) 在32位系统上虚拟64位机器
- Experimental 3D acceleration via OpenGL (see user manual, chapter 4.8, Hardware 3D acceleration (OpenGL), page 66) 支持OpenGL的3D加速特性
可惜都还是实验功能。
2008年12月12日 12:34
去年的时候,猛禽写过一篇文章,其中提到了左行右立这个事,并以此说明北京人民比上海人民文明。
碰巧这几天出门坐地铁的时候,发现这个左行右立的概念又被加深了:电梯扶手的两边,贴上了红色和绿色的指示标,以更加醒目的方式提醒着大家左行右立。
然而,可以非常理所当然想到的是,效果依然是一如既往的不好。所有的电梯,仍然是满满当当的挤满着两排人流,根本没有“行”的迹象。
于是我稍微做了一下思考。我觉得,左行右立这个系统,是一个不稳定的系统!
不稳定系统的特点在于,维持这个系统运作,需要非常苛刻的条件,但是要破坏这个系统,则非常非常容易。不幸的是,左行右立正是这样一种系统。
左行右立必须依赖一个非常理想化的条件:在电梯上的左边每一个人,都有崇高的觉悟,能自觉遵守这个规则。否则的话,只要中间有一个人不想走了,后面的人觉悟再高也没有用,一样被阻止。
这种不稳定的系统,在现实中想要正常运作,实在是太困难了。
然而据说这“左行右立”是国际惯例,为什么这样一个不稳定系统在国外就可以实际运作呢?
我没有去过国外,没有亲眼看到过左行右立的实施,但是我猜想,有两种方法可以解决这个问题:
1. 增加违规成本。比如,你要是在行走区站立了,就要遭受处罚,当大家觉得违规的成本超过违规带来的好处时,大家就都不愿意违规了,这样这个系统就能维持一个稳定的运行了。
2. 降低违规带来的后果。举个例子,如果说,站立区的人较少,中间有缝隙时,即使有人在行走区站立,大家还是可以通过站立区的缝隙维持整个系统的继续运作,不至于被一个人阻塞。
然而,上海的地铁电梯恐怕两点都难以做到。第一点,在行走区站立并不是什么罪大恶极的问题,处罚过严会导致恶法;而处罚过轻又不会起到什么效果。而且还要增加执法的成本。第二点,这个就跟具体情况有关了,上海地铁一般人流量都比较大,要想开出缝隙是不大可能的。
我们不妨再回过头去想一想,为什么好好的一部电梯,要搞出左行右立的规则来。
我们知道,自动扶梯之所以诞生,就是为了减轻人们的行走负担。本意上来说,它是鼓励你站在上面休息,而不是走动的。那么为什么要做出左行右立的规则呢?这是因为,电梯的速度是有限的,有些人比如为了赶时间或者其他原因,需要以更快的速度通过。如果上下楼的通路除了电梯之外别无选择的话,那么在电梯上让出一条快速通道,的确是有必要的。我猜想,国外搞左行右立的地方,如果不是人不太多的话,应该就是有很多条电梯并且没有普通楼梯的吧?——希望有人能够确认一下我的猜想。
我们再看上海的地铁。其实在绝大多数的站厅里,自动扶梯只有一条,通常旁边还有一条普通楼梯。需要赶时间的人,就算电梯是左行右立,我觉得也不太可能真的排队去“行”那窄窄的一条行走通道,当然还是走楼梯比较快,更别说楼梯是更适合行走的了。而真的不想走的人,为什么不让他早点站上电梯呢?
所以我觉得,按上海这种实际情况,与其花大力气搞什么左行右立,不如花点心思把楼梯用起来,这样更高效也更行得通。
2008年12月10日 22:49
今天跟猛禽碰了一次头,就一些技术问题交换了一下意见。
期间猛禽提到这次SD大会上好多牛人都在提Django,而且也出现了不少Django开发的实际应用。我和猛禽都觉得有些不可思议。
因为我不是做Web出生,对于Web技术的演变一直比较迟钝。当时听说Django和TurboGears,还是通过limodou的blog。因为大家聊得比较多,于是去看了两眼。
limodou是比较倾向于Django的,但我的第一印象则是喜欢TurboGears。原因有几个。第一,当时我正好接触到CherryPy,对CherryPy的那种风格比较喜欢。第二,我发现Django可以管理多个Application,让我立刻联想到J2EE的容器以及Java应用那极其BT的部署方法,感觉不太好。第三,正如猛禽所说,Django重新造了所有的轮子,跟我的理念完全相悖。
但是因为当时手头也没有什么Web开发的东西,于是对他们的看法,也就停留在了这极其表面的第一眼上。倒是猛禽听了我的推荐,开始用TurboGears开发一些应用。
然而一段时间下来,他发现TurboGears也有不少问题。第一,TurboGears的底层所依赖的CherryPy,每次升级,变化都很大,顺带造成了TurboGears的每个版本变化也很大(但是这个问题,早期的Django也有)。第二,TurboGears因为使用了大量第三方的组件,造成了严重的依赖,首先安装的时候很不方便,很难在离线的状态下安装完整个TurboGears,其次它所依赖的组件很容易跟其他的程序冲突。当时猛禽就碰到过因为同时安装了TG和Pylons,造成了TG应用无法正常运行的情况。
后来BT群开始狗屎皮项目的时候,我就稍微慎重了一点,最后选用的不是我原先推崇的TurboGears,当然也不是Django,而是另外一个RoR风格的开发框架Pylons。Pylons框架可以说是我第一个深入使用的开发框架。使用至今,我的感觉依然和一开始没有太大的变化。Pylons其实并不是太适合作为一个从头开发的框架使用。因为严格的说,它只是一个半成品的框架,甚至没有默认的数据库操作组件。因此要完成一个项目,先期要做大量的工作。这些工作对于一个项目的开发来说,是无谓的时间浪费,因为从根本上来说,这些工作并没有为项目本身带来任何好处。
然而Pylons的一个优点也在这里,正因为它没有绑定太多的东西,所以用它做开发的时候,选择非常的多而且灵活,你可以用你习惯的,崇尚的任何框架来配合Pylons使用,从而组合出最适合你或者最适合项目的一个完整开发框架。而且Pylons的主线流程非常简单,我在从来没有接触过的情况下,只花了大约1天的时间就大致弄清了它的运作机制——这对于需要定制的系统,是非常重要的。
有的时候我在想,如果我真的接到一个任务,我会选择Pylons吗?八成不会。除非这是一个可以长期发展并且可以衍生的项目,我才愿意花一些“不必要”的时间去完善这样一个框架并在此基础上再做真正的开发。否则,当然还是一个现成可用的框架来得更好。
这么看下来,似乎值得选择的还真的只有Django了。但是我仍然持有上面提到的那些感觉不爽的意见,但是为什么现在这么多人都选择了它呢,难道他们没想到这些?还是说,这些根本就不是问题?在我开始一个实际的Django项目之前,我希望能有一个对Django比较了解的人,能够为我深入的介绍一下Django,告诉我Django到底有什么好。
2008年12月08日 23:10
今天TR在Gtalk上对我说,我的blog留言功能有bug。他辛辛苦苦写了一大段话,结果因为里面包含了一对“<<”符号,后面的文字全部被切掉了。
我自己测试了一下的确如此。而且切掉的内容在我的后台也是没有的。无奈之下只能让他复述了一遍原先留言的内容,然后我手工帮他修改了。
初步的设想是因为留言处理HTML tag的机制而导致了问题,所有的<>应该写成<和>才对。但是不能要求留言者做这样hack的动作,于是我决定还是去修改后台代码。
首先找到后台modules目录下的modules_comments.php,看了一下handlePostComment函数的代码,看到了一句
'comment' => $comment_text;
就想当然的写了一个转码小函数
function convertHTMLtag($source){
$source = str_replace('<', '<', $source);
$source = str_replace('>', '>', $source);
return $source;
}
然后将那句改成
'comment' => convertHTMLtag($comment_text);
测试发现,无效。
正在疑惑的时候突然发现页面下面有一行小字:
Small print: All html tags except <b> and <i> will be removed from your comment. You can make links by just typing the url or mail-address.
这说明系统一定已经是对HTMLtag进行了处理。我处理的其实已经是经过处理之后的文字了,那里已经不含有多余的<和>,难怪改动会无效。于是再仔细的检查代码,发现原来在pvlib.php里有一个函数strip_tags_attribute,就是对留言做预处理的。这个函数的代码中,使用了PHP内置函数strip_tags对留言文字做处理。这个函数将允许的HTML tag以外的其它所有tag简单的删除。而当留言中出现<或者>的时候,因为没有转码,也被当作是HTML tag的一部分了。所以就被删除了。
因为strip_tags是PHP的内置函数,已经没有办法进一步跟踪了。思来想去,我决定写一个新的函数替换掉它。于是,就写了下面这个函数:
function e_strip_tags($source, $allowedtags) {
preg_match_all('/<([a-zA-Z]*?)>/', $allowedtags, $temp);
$allowedtags_tag = $temp[1];
$temp = $source;
foreach($allowedtags_tag as $tag) {
$temp = preg_replace('/<(\/?'.$tag.'.*?)>/', chr(254).chr(254).'$1'.chr(255).chr(255), $temp);
}
$temp = str_replace('<', '<', $temp);
$temp = str_replace('>', '>', $temp);
$temp = str_replace(chr(254).chr(254), '<', $temp);
$temp = str_replace(chr(255).chr(255), '>', $temp);
return $temp;
}
这个函数的作用是,将除了允许的tags之外的其他tag的<和>转码成<和>,而不是将tag简单的删除。这样就能尽量的保留所有文字,不会误删,又能尽可能的维持blog留言的原有功能了。
这段代码的基本原理是,将含有允许HTMLtag的<和>先替换成两个不常用的字符串,然后将剩下的<和>转码,最后将那两个不常用字符串再转回来。
最后将strip_tags_attribute函数中的strip_tags调用换成e_strip_tags,就大功告成。
2008年12月08日 19:11
这是一次妓术RP爆发的结果。这是一个不切实际的幻想,并非严格的设计。
今天的BT妓术群里,我们讨论了一下云计算和网格计算。我个人对于基于p2p的网格计算是很看好的。但是猛禽告诉我,云计算现在已经商用化了,但是网格计算却声音越来越小,并没有我想象的那样有前途。
没关系,就让我们来YY一下,我想象中的网格网络应该是一个什么样子吧。
我想象中的网格网络,每一个网格节点,是一个通用的,能够搭建各种网络设施的通用p2p节点,而不是像现在这样基于应用的节点。整个网络由庞大数量的,松散的,不稳定的节点所构成。
每一个节点有一个底层服务,这个服务包含一个可裁剪的虚拟机和一个智能路由。每一个节点藉由此服务贡献自己的计算、存储、带宽等能力。但不限于特定的应用。
在一些节点上,实现了一些特定的应用。这些应用提供了一个服务入口,相当于目前网络架构中的“服务器”,但是这些服务器并不需要自己提供全部的资源,它只需要提供一个服务入口,后端的计算、带宽、存储均通过特定的接口,交由网格完成,网格会负责将计算、带宽、存储分配到若干节点上,并行处理。然后将结果汇总至服务入口,由服务入口呈现给用户。
所有的存储、带宽和计算请求,将被封装成若干个用“统一代码”编写的“任务包”,每一个任务包的计算量、存储量都很小。当一个节点获得一个请求的时候,会根据自身的计算能力领取一个或多个任务包进行处理,并同时通过智能路由将任务包发送至周边的其他节点。处理完成后,通过路由将结果返回。
考虑到每一个节点都是不稳定的,每个任务包都可能由多个节点同时处理。如果是存储,因为存储的信息需要长期存在但节点可能不会长期存在,所以需要采用更复杂的打散算法将数据分散冗余,最大限度保证整体数据可用性。
每个节点在启动时会建立智能路由通道,并向全系统告知自己的存在。
整个网络中没有“超级节点”,所有节点的地位都是相等的。
但是所有节点都遵循一种特定的规范,以相同的机制工作。
每一个单独的节点,只知道周围的有限个节点的存在(避免信息洪泛)。但是整个网络中,所有的节点都互相关联。不存在死节点。
现在想到的需要解决的一些问题:
- 安全。由于每一个节点都不可控而且不安全,所以我们不能在节点上存储有序的信息,只能存储各种不同的信息打散混合后产生的无序信息。
- 效率。如何保证整个系统的效率,如何保证上面说到的打散信息能够快速合并成有序信息。
- 公平。如何保证大家贡献和获取的相对平等,如何对付刻意欺骗者。
最后我想聊一下这个系统的可行性。实际上我觉得这个系统并非完全不可行。这个系统的核心在于一个松散耦合的分离式系统,现在的Internet其实就是这样一个系统,每一个服务器出问题都不会导致整个Internet的瘫痪。而一个实际不存在的“虚拟操作系统”,它的核心在于“协议”,所有的节点都必须遵循相同的协议进行工作。PC系统的统一接口也让我们看到了这种协议诞生的可能。至于那些我想到和没想到的问题,我想现有的p2p应用、云计算应用应该可以给出不少有用的经验,假以时日,应该是可以解决的。
我仍然觉得这样的一种网络是很吸引人的。希望它会变成现实。
2008年12月04日 20:15
这周有几天在外面,无法上网,于是将电脑里存了好久的书又翻出来看了一看。突然发现平时从来不会去看这些书,只有断网了才会想着去看,果然是“书非断网不能读也”。囧
我看的其中一本是《代码之美(Beautiful Code)》的免费电子版(精简版)。这本书很不错,改天有机会应该去买一本回来收藏。我留下深刻印象的一段是,书中演示了一段通过单元测试改进二分查找算法的例子。(当然,前面一个正则表达式的例子也相当不错)
很多谈单元测试的书都会说,单元测试除了验证代码功能正确之外,还能改进代码的质量。但是这种泛泛而谈的话,会给我一种模糊的感觉,似乎掌握了什么,但真的操作起来却无从下手。而这里给出的这个实例,真真切切的告诉我们如何利用单元测试改进代码。我想把这一段凭自己的记忆在这里重复一遍:
在二分查找算法中有一行取中点的代码:
int mid = (low + high) / 2;
其实,这里的 low + high 在整数相当大的时候会产生溢出,从而带来错误。为了避免发生这种情况,我们就有必要做一些边界测试,来考察在极端的情况下函数是不是仍然工作正常。因为函数的声明是:
int binarySearch(int [] array, int target)
所以我们需要构造一些极端的数组情况,比如,空数组,单元素数组,另外,还有很重要的是,极大的数组。
但是在现实中,构造一个极大的数组,并且还能导致 low+high溢出,是很难的。这需要相当大内存的机器才能做到。我们是不是一定需要准备一台超级计算机才能发现这个问题呢?当然不是。
我们可以把这个问题分解来看:为什么当数组极大的时候可能会出错?因为low+high可能会溢出,mid可能是错误的值。于是,我们只要证明2步,就可以证明整个函数是正确的:
- 当mid正确时,函数一定是正确的。
- mid始终是正确的。
第一点,我们可以通过足够多的“普通级别”的测试来验证。第二点呢?在现有的情况下,我们无法验证,因为mid只是整个函数的一句话而已。于是,为了测试mid的正确性,我们就得重构代码,将mid的值改成由函数获取:
int mid = getMidpoint(low, hight)
然后,我们就可以通过测试getMidpoint的正确性从而得知mid的正确性,这里不需要极大的数组,只需要取两个相当大的整数值就行了。在保证了全部的2点之后,我们就可以保证binarySearch函数的正确性了。
在现实中,我们的确会遇到很多“无法测试”的情况。以前很多时候,我们会简单的验证一下在运行环境内可能遇到的极限情况就结束了。这当然是一种办法,但假如这个功能需要被拿到不同的运行环境的时候,作为一个“通用”的功能,我们就需要更严谨的方法来测试。这时,就可能需要对代码进行重构,将“不可测试”的代码转换成“可测试”的。
我想这一点在测试之外的其它地方,也是一个相当不错的思路。
2008年12月03日 22:44
Blog升级成了PivotX,后台干净清爽了很多。看起来跟WordPress很像了。以前版本有一些不舒服的地方,新版中都做了增强和调整。也造成了与以前版本的数据有些不太兼容。晚上花了一些力气,终于把数据都无缝的迁移过来了。
我坚持使用Pivot的理由很简单,免数据库,维护很方便。而且我比较喜欢文件系统这种简单的东西。
某人说新版的界面很挫。我去找了一下,因为是新版的缘故,几乎找不到什么现成的模板。无奈何,只能把他带的一个模板改成了以前的样子,先凑合用着。下次有空再在整理了。
用非主流的系统就是这样,资源难找,什么都得自己动手。唉。有得必有失呀。
以前版本的后台简直可以用一塌糊涂来形容,以至于我一般没什么事都懒得去动他。新版的后台做了很大的改进,从管理角度来说,好多了。
还有以前版本重建索引的时候似乎有bug,有时候数据会扫描不全,现在这个版本好像也解决了。
目前的版本还是beta,不过已经可用了。正式版的时候应该会更好吧。