• 25 十一 2009 /  互联网技术

    昨天花了一下午的时间测试一个程序的执行效率,该程序是一个后台日志分析的程序,犯懒用php写的,毕竟php对文本处理效率很高(编写&执行),一开始担心php的数组按照键值查询效率低,所以使用memcache作为内存缓存来用。

    程序编写好后执行正常,当处理数据量上来以后,发现执行很慢。其它的项目中我也发现在压力测试时memcache会是瓶颈并导致很高的cpu占用,因此怀疑是否自己编译的php+memcached有问题,或者是其它问题。于是做了下面的测试。

    Trace for /logprocess/process_sessiontime_memcached.php
    Total Elapsed Time = 767.74
    Total System Time = 19.15
    Total User Time = 742.67

    Real User System secs/ cumm
    %Time (excl/cumm) (excl/cumm) (excl/cumm) Calls call s/call Memory Usage Name
    --------------------------------------------------------------------------------------
    69.2 531.12 531.12 520.74 520.74 6.94 6.94 92646 0.0057 0.0057 0 Memcached->set
    21.4 164.18 164.18 157.25 157.25 4.85 4.85 92646 0.0018 0.0018 0 Memcached->get

    从上面的数据能看出,这个程序php执行的瓶颈在memcache,而set操作更加有问题,接近70%的时间都在做set操作,难道真是使用的模块有问题嘛?我查过php的memcached模块,代码基本上就是一个连接,实质使用的还是libmemcached这个库的内容,所以如果要是有问题的话也肯定在libmemcached这个上面。但网上搜索后,无果,没有人说它有问题。

    后来细想,按照上面的数据折算,读写平均的话122.22次/秒,读单独是564.30次/秒,写单独是174.47次/秒,数据表现也算不错了。写慢是memcache以及被测试的程序逻辑有矛盾,我了解了一下,memcache会使用item(key+value)的长度做前期的定位,试想如果程序使得value长度不断变化,是否set会不断移动item所在的slab位置呢(将旧的变成过期,再按照新写入数据的流程写入新的item)?没有深度考究,但觉得值得怀疑;如果写操作所占用的cpu释放出来的话,读的效率应该可以更高,回头可以测试一下,估计能超过1千次/秒。

    总结上述,memcache使用要被仔细的规划,取长补短,如果随意使用的话未必能有好的效果。上面的程序其实就不应该用memcache,频繁的写不是memcache的强项,而分布式、多点频繁读取才是强项。

    说道缓存,所以我顺便又测试了Alternative PHP Cache(APC)的模式,还是刚才的程序,出来的结果是读写平均392.57次/秒,比memcache快3倍多,我没有出读写分离的数据,估计如果单读的话,应该还能再快一些,毕竟APC是本地缓存。因此,如果你的应用不需要分布式的话,APC是一个很好的选择,它能帮你在一台机器的情况下,保持并缓存每次php请求之间的数据。其次,它还是一个类似eAccelerator的代码opcode缓存模块,可以提高php代码执行速度。

    最后,回到我一开始没有考虑的解决方案,因为我不需要跟其它进程或者服务器共享我的数据,所以直接用php的数组,处理速度是多少呢?15,441次/秒!当然啦,内部就是一堆指针指来指去而已,我没有想到的是数组在很多无序的key中找value还是很快的,所以以后大家可以放心这么使用,只是注意配置文件中允许的php运行时占用的内存再调大点就好了。

    总结,任何设计要根据具体的应用需求来选择解决方案,选择时要考虑所选技术本身的特性,取其优点避其缺点。Memcache不适合做数据频繁变化的内存共享,一次写入多次读取的模式会更适合一些。Tokyo Tyrant / Tokyo Cabinet / Redis也许能用于频繁读写的情况,我还没有时间去评测;BTW,以前还使用Mysql内存表做这类事情多一点,希望能构建一个数据写入缓存机制,但是实际使用时还是有一些问题,所以有空再找找新的解决方案吧。

    最后说一句,就一句:在Memcache盛行的当今,Memcache不可滥用。

    Tags: , ,

  • 23 十一 2009 /  互联网技术

    脑子不好使,只能记录下来以后备用

    首先python有几个版本,我现在选择的是2.5版,版本越低,可选择的第三方支持包就越多,当然也要平衡,低版本也会有性能问题,或者小bug。2.6是3.0的过度版本,有很多新的特性但又兼容老的版本(3.0有些老版本的语法、特性就不支持了),所以权衡选择了2.5版。

    python自身的安装比较简单,在linux下就是通过源码编译就可以了,需要注意的是,python在linux系统下作为很底层的语言支持,通常系统会有一个版本默认已经安装了,如果你觉得那个版本够用就直接用,如果安装新的版本,最好不要改动或者覆盖那个版本。我一般都在/usr/local/python2.5目录下安装一个新的,然后ln -s /usr/local/python2.5/bin/python2.5 /usr/bin/python2.5,这样原有的版本和新的版本互不干扰。

    python的扩展包很多,一般分成两类,两种方法来安装
    1、扩展包是直接的源码包
    通常这种包解开后会有一个setup.py的文件,使用你希望安装这个扩展包的python版本来运行python setup.py install就可以完成安装,当然你也可以先python setup.py make再install,意思和linux下编译源代码的流程是类似的。

    2、.egg文件
    这种类似jar的代码包是一个叫easy_install的项目产生的,首先你可以下载并安装easy_install;如果你的easy_install是.egg结尾的,可以使用sh easy_install.egg来安装。如果是普通源码包就参考上面第一种方法安装。
    安装后会在 /bin/目录下多出来一个叫easy_install的脚本。你下载的.egg包就可以运行./easy_install xxx.egg来安装了。
    当然还有一个更简单的方法,就是./easy_install module_name,这样它就会在网上找到适当的模块进行自动安装并且保持模块之间的关联。
    easy_install除了网上查询包自动下载,后续的工作就是在 /lib/python2.5/site-packages/目录下的easy_install.pth文件中加入了.egg文件的关联而已,并且将.egg文件拷入上述这个目录,这样python在寻找软件包的时候就能找到并自动装载。

    BTW:有关Python MySQLdb模块
    上述安装方法很自然就可以将这个模块安装好,但是我的习惯不喜欢将mysql客户端的库放在默认的位置,导致实际python导入模块的时候会报错,这时候只需要将你的库文件路径加入/etc/ld.so.conf中,并且执行ldconfg -v就可以了。

    Tags:

  • 27 十 2009 /  互联网技术

    原文链接:Nginx & Comet: Low Latency Server Push

    作者:Ilya Grigorik

    翻译:孙绍轩

    服务器推送(Server Push)是高效的、延迟低的数据交换方式。如果数据发送端与接收端都在互联网中公开可见,可以使用PubSubHubbubsimpler Webhook等方法完成任务。但是如果数据接收方在防火墙内、在内网或它只是一个浏览器(只可以向外发送数据请求,无法处理传入的数据),则实现服务器推送就更难了。如果你有冒险精神,你可以建立一个反向HTTP服务器。如果你寻求可靠的解决方案,也许你要等待HTML5的WebSocket’s API特性了。但如果你需要即刻可以实现的解决方案,你可以妥协一下,使用异步推送模式来代替,你可以使用Comet,也被称为反向Ajax、HTTP服务器推送或HTTP流。

    早在2006年Alex Russel提出了一个不坏的技术思路,那就是长连接(Comet)概念:从客户端发起并保持一个连接直到数据出现并传送(long polling),或者永远保持一个连接,通过它推送数据到客户端(streaming)。这两种方法的好处是数据传送非常及时。因此长连接技术广泛用于聊天应用(Facebook, Google, Meebo等)以及实现即时触发的机制。

    Nginx变成一个长连接服务器

    实现长连接服务比较大的问题是特殊的隐形需求以及事件驱动web服务器能否高效处理众多的长连接。Friendfeed的Tornado服务器是一个标准应用级服务器的好例子。另外,感谢Leo Ponomarev的努力,你现在可以用nginx_http_push_module插件使你的Nginx服务器变身成为一台完全功能的长连接服务器。

    使用自定义的一套框架结构,Leo的插件只提供两个对外的接口:一个是订阅者,一个是发布者。客户端连接Nginx服务器,创建针对一个频道的long-polling长连接并等待数据。同时,发布者只是简单的将数据使用POST方法提交给Nginx,插件收到数据后将它一个个发给等待的客户端。这表明发布者不需要直接传递数据,它只是一个简单的事件产生器!没有比这个更简单的方法了。

    还有更高的功能是,客户端和发布端可以建立任意的频道,并且插件也提供消息队列功能,这表明Nginx服务器会在客户端断线的情况下临时保存消息。队列消息可以按照时间、等待列表长度或内存限制大小来失效释放。

    NginxRuby配置例子

    一开始,你需要从源代码编译一个Nginx。解压源代码包,从GitHub获取插件的源码并放入Nginx的源码目录,然后使用下面的参数编译(./configure –add-module=/path/to/plugin && make && make install)。下一步,参考readme文件和协议文件,了解所有的参数选项。一个多客户端接收信息的配置例子如下:

    > nginx-push.conf

    # 内部发布点(保证私有或不对外公开)

    location /publish {

    set $push_channel_id $arg_id;      #/?id=239aff3 或类似的文本标示

    push_sender;

    push_store_messages on;            # 打开消息队列

    push_message_timeout 2h;           # 2小时后消息失效

    push_max_message_buffer_length 10; # 保存10条消息

    push_min_message_recipients 0;     # 清除前最小接收人数目

    }

    # 公开的长连接接收点

    location /activity {

    push_listener;

    # 一个频道编号能有多少客户端同时连接

    # – last: 只有最频繁请求的客户端能保持,其它连接返回409

    # – first: 只有最早连接的那个客户端可以保持,其它连接返回409

    # – broadcast: 任何数量的客户端连接都会是长连接

    push_listener_concurrency broadcast;

    set $push_channel_id $arg_id;

    default_type  text/plain;

    }

    当你编译配置好你的Nginx服务器,并且启动它,我们可以建立一个简单的广播场景,一个数据发送广播方,几个订阅信息接收方来测试我们的长连接服务器。

    > comet-push-consume.rb

    require ‘rubygems’

    require ‘em-http’

    def subscribe(opts)

    listener = EventMachine::HttpRequest.new(‘http://127.0.0.1/activity?id=’+ opts[:channel]).get :head => opts[:head]

    listener.callback {

    # 打印所获取的内容,并重新订阅这个频道

    # 使用last-modified头去忽略之前已经获取的数据。

    puts “Listener recieved: ” + listener.response + “\\n”

    modified = listener.response_header['LAST_MODIFIED']

    subscribe({:channel => opts[:channel], :head => {‘If-Modified-Since’ => modified}})

    }

    end

    EventMachine.run {

    channel = “pub”

    # 每5秒钟发布一个新的消息

    EM.add_periodic_timer(5) do

    time = Time.now

    publisher = EventMachine::HttpRequest.new(‘http://127.0.0.1/publish?id=’+channel).post :body => “Hello @ #{time}”

    publisher.callback {

    puts “Published message @ #{time}”

    puts “Response code: ” + publisher.response_header.status.to_s

    puts “Headers: ” + publisher.response_header.inspect

    puts “Body: \\n” + publisher.response

    puts “\\n”

    }

    end

    # 打开两个客户端

    subscribe(:channel => channel)

    subscribe(:channel => channel)

    }

    nginx-push.zip (完整的Nginx配置和Ruby代码)

    在上面的代码中,每5秒钟数据发布端向Nginx服务器发出新的事件,服务器将数据通过长连接转发给两个订阅的客户端。当消息发送到客户端,服务器会断开他们的连接,客户端会立即重连并等待下一次数据的到来。结果就是使用Nginx实现了一个数据发布端到客户端的实时消息推送机制!

    期待生产环境下的长连接服务

    Leo的模块还在开发期,还需要时间来稳定下来,但它是一个需要关注的项目。最近的更新计划都着重于bug修复,未来的计划里有描述要加入流的模式:代替现在每次数据获取后都要重连的情况(long polling),Nginx会保持连接,将数据一段段的实时传送给客户端。拥有这个功能后你能很方便的部署你自己的信息触发式API(例如:Twitter流)。

    最后,不要忘记数字不断增长的其它Nginx模块,或者如果你感兴趣的话,可以参考Evan Miller编写的指引来开发自己的Nginx模块。

    Tags: ,

  • 26 十 2009 /  互联网技术

    Software Developer 2.0 2009会议上以及之前参加的一些会议上看到一个现象,大厂商都开始敏捷了,如果你现在还徘徊是否要敏捷,我觉得可能为时已晚,你要立刻敏捷起来!

    SD2.0 2009上微软给大家介绍了Visual Studio 2010,从界面上来看沿袭了Office 2007的风格,工具条排列很花哨,也有一大堆微软经典的wizards,利用这些向导可以很方便的完成开发工作。一个被我关注的重点是VS2010整合了开发流程中除了编码以外的东西,比如版本控制、缺陷管理、UML建模等都融合进入这个集成开发环境,并且它还拥有敏捷开发的一些特性模板,单元测试模板用于测试驱动开发。不难看出微软为了方便开发者,将最近开发管理所需的功能都列入到它的VS2010里面去了,而且是全网络化的解决方案,开发人员之间是可以很方面的共享信息的。相信在微软内部也有团队在实施敏捷。

    IBM的一场演讲中也透露出,IBM内部软件开发也在实施敏捷,而讲演者Robert Degg来自Rational,他主要的工作就是在IBM内部帮助各个软件开发部门实施敏捷。

    通过网上的一些文档介绍,Google, Yahoo!, Facebook, Twitter, eBay等大型互联网公司都在实施敏捷开发并有些成效。敏捷已经不是两三年前大家都在观望的局面了,已经不是只有创业团队敢于尝试的一种开发方法了,渐渐的你会发现身边的软件公司都多少的运用敏捷开发的方法,你还犹豫什么?

    忽悠大家半天再来说说如何实施敏捷

    也许敏捷方法并不和你现在使用的方法有太大的差异,我认为我们要从小事出发,用敏捷方法解决我们现在特定的问题,这样才能积累所有人的信心继续朝着更高的方向改进。毕竟老板只会看效果,如果不能在短时间内达到效果,说到天花乱坠也没有用。下面列举一些可以注意的小点,你可以按照你具体的情况来选择实施。

    • 对待需求按照重要程度排序,一段时间内只完成确认的最终要的任务

    其实很多开发团队也是这么做的,只是敏捷方法提出频繁迭代的概念,让完成需求有一个特定的周期,并且这个周期要尽可能频繁的迭代。每个周期完成的是完整的事情,没有完成的百分之多少的概念,只有完成和没有完成。这样保证每个迭代有工作的产物,保证下一个迭代万一出现问题我也能拿出上一个迭代的成功产物。

    另外重要程度排序也会使得最重要的业务需求最先完成,不至于做的半天都是无用功。

    迭代周期中不加入其它新的变化导致在一段时间内足够的清净让开发人员来完成工作。

    • 测试驱动

    也许这个题目太大,你可以缩小化成自动单元测试,因为要自动测试所以你要写测试脚本,也许你会在写完程序后懒得写测试脚本所以把测试脚本编写在程序开发前面。选择一个适合的测试框架,你会很快达到这个目标。你会发现不必为了找一个bug花费很多的时间,如果你要查问题,就给自己一个假设,用这个假设实现一个测试来验证吧,逐渐的你的测试脚本会限制你,一有bug测试就无法通过了,你就不需要找而是直接修复发现bug。

    对于小团队,这里其实更重要的是让单元测试从无到有。

    • 配对编程

    也许你会对这个很怀疑,但我能说的是,这只是一个形式,如果你仔细观察,在你公司内部,也会经常因为某一个人解决不了一个问题而抓住另外一个人,两个人一弄就是一下午,也许问题已经解决了,两个人也会继续一段时间。配对本来就是一个很自然的事情。

    配对根本解决什么呢?

    1、人的经验问题,不可能都是全才,配对有利于带新人,或者让两个不同领域的开发人员能互相熟悉或产生升华。这点通常在配对前两个人一起设计而体现。

    2、代码复查;首先我相信大部分开发团队是没有这个独立的工作内容的,但它真的很重要,代码复查可以让所有人在一个编码标准下开发,复查可以让一些有问题的设计思路更早被发现,因为一个不好的设计并不会产生bug,但也许它影响了后续的性能或者灵活的可扩展性。因此如何引入代码复查而又不增加而外的开发负担呢?配对编程是个很好的方法。

    3、形成通才而不是很多专才;通常我们担心某些点没了某些人就不转了这种情况,一个是不利于公司管理,二来也不利于那个人发展(我因为精通某一个方面就弄要负责那个方面,也许我都已经厌倦了,但无法自拔,解脱只有辞职换工作了),配对编程的经验共享使得可以弱化上述问题,并且所有人被灌输的是你感兴趣的部分你都可以了解,不是对每个开发人员发展都有激励作用嘛?

    • 任务管理或缺陷管理

    也许这不算敏捷里面的东西,但它和敏捷开发密不可分,例如Scrum里面的burndown chart就是代表bug被解决的趋势。老外讲究的一个思路是:你如果想优化一个事情,就首先要弄清楚如何度量这个事情,只有度量的结果才能反馈你的改进是否有效。因此无处不在的数据会很直接的体现项目的状况。

    现成的有很多系统可以辅助你进行任务管理和缺陷管理,我推荐Trac,一个使用Python编写的集成系统,用于开发中知识共享,围绕它也可以找到很多第三方的插件来满足你的需求。

    ok,对比一下你的现状,也许你离敏捷并不遥远,只需要参考一下将好的东西吸取到你现在的过程中,就这么简单,开始行动吧,也许未来你也能创造出一个什么敏捷方法!

    Tags:

  • 26 十 2009 /  互联网技术

    上个星期参加为期三天的Software Developer 2.0 2009大会,我了解到各个手机系统平台提供商的现状,现归纳总结一下。

    Android

    Google推出的东西总是可以在那个领域溅起巨浪,Android以免费开放的原则推出,引起了众多人的关注,发布了两年后这个东西逐渐成熟起来,支持的手机也越来越多了。总体都往好的方面发展,中国地区的开发者可能更加关注,希望这个年轻的项目可以尽快开花结果。

    SymbianOS

    老牌智能手机操作系统大哥,被Nokia收购了以后沉默了一小段时间,变身成Symbian Foundation出现在我们面前,给大家的惊喜是,免费、开放,果真是被Google挤兑的不行了。计划明年2010年全部开放所有的系统代码和授权,个人估计山寨机又会更火,因为又有一个好用的系统平台可以选择了。BTW:Nokia最近出的手机真是没有什么新意,gphone和iphone两面夹击,够它受的了,祈祷吧。

    iPhone下的Coco touch

    苹果是相对封闭的,我们只能去写iphone或者ipod touch上面的应用,平台就看着眼馋吧,个人觉得这种封闭的、控制力很强的软硬结合物才能做出精品。

    Windows Mobile 6.5

    如果你是微软的崇拜者,你可以继续关注,不过总觉得PC上的一个概念移植到手机而不用手机的思路来设计一个系统的话,不会太好用。不过这个开发会是很简单,强大的Visual Studio永远是开发利器。这次开会也有幸看到Visual Studio 2010,大厂也开始敏捷了,呵呵。

    WebOS

    Palm借助WebOS推出Palm Pre新一代手机系统,一个巨人倒下了,如果能再次站起来的话,那会是非常强大。希望能看到这一天,因为Palm是最能体会移动设备操作的厂商,现在其它平台下很多操作都有palm的影子。期待它再次回到主力。

    BlackBerry

    封闭的软硬系统以及特定的应用场景,如果不是针对商业应用开发的开发者就不用太关注它了。

    总结

    平台还是很多的嘛,作为开发者的你也不能三心二意,专注在一个平台上先做大是我的忠告。至于选择哪个平台,那就要看自己的情况了。Android借助中国移动Ophone的力量蓄势待发,强烈的建议重点关注。iPhone如果你是做国外业务也可以关注,如果是关注国内市场就可以稍微晚一点再说,因为从联通对iphone的定价,我十分怀疑它有足够的运营能力能将这个优秀的平台在国内搞好(苹果也不是吃素的,一向会很强硬)。Symbian有足够的有开发经验的开发人员,想做应用找现成的人就好了,无需再自己研究,所以这个平台关注就好,只要你的应用有竞争力,补充上Symbian平台可以说是小菜一碟。

    让暴风雨来得更猛烈些吧,只有平台竞争更激烈,运营商竞争更激烈,才会有更多的好处落在用户和开发者身上,我们期待这一天早一些来临吧!

    Tags: , ,

  • 10 十 2009 /  互联网技术

    写在前面:

    总觉得学习英语要实践点什么,计划作为毕业印证我要翻译一本技术书籍。现在我还没有毕业,所以接下来的日子里,尝试翻译一些短文,热热身先。

    ———————华丽的分割线———————————-

    Python内建异常清单

    by Al Lukaszewski for About.com

    翻译:Yorgo Sun

    原文:http://python.about.com/od/pythonstandardlibrary/a/lib_exceptions.htm

    下面是一个完整的Python运行时会抛出的错误列表。大部分错误都可以一目了然,我添加了一些注释来使得它们更加清晰。这参考并扩展了Python 2.5文档中“内建异常”的章节。

    • BaseException: 所有内建异常的基础类。
    • Exception: 所有的内建的、非系统预置的异常均继承这个类,所有用户定义的异常也应该继承这个类。
    • StandardError: 所有内建异常的基础类,除了StopIteration,GeneratorExitKeyboardInterruptSystemExit StandardError 是继承Exception而来的。
    • ArithmeticError: 一些内建算术错误异常的基类,如: OverflowErrorZeroDivisionError,FloatingPointError.
    • LookupError: 当一个键值或索引在数组或序列中无效时所触发的所有异常的基类: IndexError,KeyError. 它也会由sys.setdefaultencoding()直接触发。
    • EnvironmentError: 所有能发生在Python系统之外的异常的基类:IOErrorOSError.
    • AssertionError: 当判定条件失败时,触发此异常。
    • AttributeError: 当一个属性被引用或赋值时出现错误会引发此异常(当一个对象不支持属性被引用或赋值时,会触发TypeError异常)
    • EOFError: 当内建函数(input() 或 raw_input())达到文件尾时触发此异常。(注意:文件对象的read() 和 readline()方法处理方法不同,当遇到到达文件尾部的情况时会返回空字符串)
    • FloatingPointError: 浮点操作失败时触发此异常。
    • GeneratorExit: 当调用生成器的close() 方法时,触发此异常。它直接继承了Exception 用于替代 StandardError ,毕竟这是一个技术手段并不是一个错误异常。 2.5版本新加特性。
    • IOError: 当I/O操作(如一个 print 语句、内建 open()函数或调用文件对象的某个方法)因为I/O相关的问题而失败时触发此异常,例如:“无此文件”或“没有足够的磁盘空间”。这个类继承于EnvironmentError
    • ImportError: 当 import 语句无法找到对应的模块定义或 from…import 无法找到对应名字的内容时触发此异常。
    • IndexError: 当一个序列子集超出范围时触发此异常。(索引会被截取以保证在合理的范围内; 如果索引x不是一个整数, TypeError 异常会被触发)
    • KeyError: 当键值并不存在于图(字典)中,会触发此异常。
    • KeyboardInterrupt: 当用户按下终止键时触发此异常(通常是Ctrl+C或者Delete键)。
    • MemoryError: 当某些操作导致内存耗尽但应能恢复的情况下(通过删除一些对象来释放内存),触发此异常。
    • NameError: 当无法找到对应名字的本地变量或全局变量时,触发此异常。这只针对无效的名字。 附带参数是包含了无法找到的名字的错误信息。
    • NotImplementedError: 这个异常继承于 RuntimeError. 用户定义基类后,抽象方法可以触发这个异常来要求派生类必须实现该抽象方法。
    • OSError: 这个类继承于 EnvironmentError ,主要用于os模块的os.error异常。
    • OverflowError: 当一个算术运算太大导致数值溢出时触发此异常。
    • ReferenceError: weakref.proxy()函数产生一个弱引用代理时,此异常被触发。弱引用代理通常访问一个被引用对象的属性,但这个对象已经被垃圾回收。更多的弱引用信息,请参考weakref模块。
    • RuntimeError: 当一个无法分类的错误发生时,触发该异常。
    • StopIteration: 当一个迭代器的 next() 方法无法获得更多的值时,触发该异常。
    • SyntaxError: 当语法解析器遇到语法错误时触发此异常。
    • SystemError: 当解释程序遇到一个内部错误,但是情况看来可以纠正,不需要放弃退出。辅助参数是一个字符串,标明在更顶层什么出错了。
    • SystemExit: 这个异常被 sys.exit() 函数触发。当这个异常没有被有效处理,Python终止程序并退出;没有堆栈信息打印。如果辅助参数是整数,它表示系统退出状态(和C语言的exit()函数类似);如果它是空则退出状态为0;如果它是其它类型(例如字符串),这个对象会被打印输出,并且退出状态为1。
    • TypeError: 当一个操作或函数调用一个不恰当的对象类型时,触发此异常。附带参数是一个字符串,表明具体的不匹配的类型。
    • UnboundLocalError: 当在一个函数或方法内引用本地变量但变量并没有赋值时,触发此异常。
    • UnicodeDecodeError: 当一个Unicode相关的编码、解码错误发生时,触发此异常。它是ValueError的子类。
    • UnicodeEncodeError: 在文字编码时发生一个Unicode相关的错误则触发此异常。它是UnicodeError的子类。
    • UnicodeError: 在文字解码时发生一个Unicode相关的错误则触发此异常。它是UnicodeError的子类。
    • UnicodeTranslateError: 在转换文字编码时,当一个Unicode相关的错误发生,触发此异常。它是UnicodeError的子类。
    • ValueError: 当一个内建操作或函数接收了参数,参数的类型是对的但值并不符合并且无法匹配一个更加精准的异常(例如:IndexError),触发此异常。
    • WindowsError: 当Windows系统下特定的错误发生或当错误编号无法映射 errno值时,触发此异常。
    • ZeroDivisionError: 当除法或取余操作分母为0时,触发此异常。附带的参数是一个文字信息,标明了运算类型和具体运算数据。

    Tags: ,

  • 12 六 2009 /  互联网技术

    通常长连接应用的结构思路网上都有很多介绍,但是很多细节并没有透露。最近实现具体的应用时探索了几点细节,记录下来。主要的问题是客户端浏览器要有实时的消息返回,但通常整个链路上都会出现一些设置问题导致的无法实时返回的情况。

    1、nginx服务器代理模式不会实时返回数据

    因为现在主流的web服务器还没有特别适合事件驱动的,所以长连接部分需要单独写server程序,但我们又希望用统一的80端口来做服务端口,所以我用nignx做了前面的代理,根据规则转发长连接请求到后台的独立服务器上。

    于是问题来了,通过nginx转发并不直接回复给客户端,需要数据传输后断开连接,客户端才能收到返回的所有内容。这是后需要将默认的proxy_pass的buffer关掉,有一个属性是proxy_buffering off;关掉以后nignx会直接返回结果而没有缓存等待所有内容都从后台服务器传送完成才返回给客户端。

    2、Chrome浏览器的实时处理数据机制

    Chrome和其他浏览器不一样,如果你一开始返回一个http头,里面表明有很长的数据需要下载,Chrome没有收到一定量数据前,是不会在浏览器中渲染或者执行这些已经下载的数据的,所以导致你无法通过长连接触发你想触发的javascript或一些你想做的操作。

    解决方案是在后台的服务器上判断如果是Chrome来访则要在内容body里面先输出标准的html头部head和body标签,然后后面跟随至少2048个字节的字符,可以随意,我用点符号来填充,然后才是正式的我要输出的内容。这样Chrome收够了2048字节的内容后就会触发对代码的处理工作,后续的代码也就变成实时触发的效果了。这算是一个针对Chrome的hack吧。

    Tags: , ,

  • 11 六 2009 /  互联网技术

    flash客户端程序能同时保持多少个socket链接?偶然的机会我调试一个程序发现了flash貌似对socket有数字限制。实际测试结果是最大20个连接,如果超过,它就会将最早的一个socket断掉,并且不触发任何的事件。个人认为这是非常变态的,客户端无法得知这些连接出现问题了,并且如果要限制也应该是将新建的socket抛出超过最大限制的异常这样好让人家去处理。

    当然,也许没人在flash用这么多socket链接,我也是在写得不好的程序里发现的这个问题而已。也许flash有默认的处理机制而我发现的是一个bug。总之概率比较小,但是除虫比较烦人,所以如果你看到这个文章解决了你的问题,只能说明你比我幸运,能找到一个比你更早发现并记录这个问题的人了。

    Tags:

  • 08 六 2009 /  互联网技术

    上周末参加了Google在中国的开发者日,印象中比去年人少了,印象中学生比去年少了。这是好事儿,可以安心听课不需要抢座位了。

    开复兄介绍了在过去的一年中google推广的技术的使用情况,然后搬出来刚刚在美国发布的热乎乎的Google Wave给大家尝鲜,的确产品做得很牛,现场掌声不断,相比微软感觉M$真是老了。

    Wave很好很强大,具体的介绍在网上google一下就好了,我这里也不多废话。但是我的体会是,如果你做一个产品或者想尝试复制一个已有的产品来经营的话,如果你在制作过程中没有新的创意或者改进,那就干脆不要做好了。创新才是关键,我愿意为创新而冒着项目有可能会失败的风险,但是值得。试想你就平平淡淡的做一个东西出来,有什么用,都是垃圾,是100%的失败。但是我有创新,那就是50%的概率可以成功,起码有50%的概率,比100%失败强多了。

    Google在很多产品上都有这样的特性,要不就不做,要做就要做得有新意,这样才能真正黏住用户。Wave是一个更大更好的例子。如果40年前没有发明email这个最伟大的互联网应用的话,如果现在用当前的互联网技术来做一个email的话,该是什么样子呢?Wave就是朝着这个目标来前进的,几乎摆脱了所有的当前的技术观念,以一种崭新的思想实现了,结果当然是振奋人心。

    另外一个热词是HTML 5,列表中没有IE,但其它的浏览器在未来的测试版中通通都开始支持HTML 5的草案了。HTML 5计划能在2010年发布,这次人们希望根据实际的需求而推出标准,而不是跟产业脱节的标准出台后4-5年才能被广泛引用,因此Google在努力。

    HTML 5的几个特性让我感到害怕

    1、canvas 能实现2维空间下的绘图

    2、location 能定位用户的位置

    3、video 多媒体标签

    4、本地缓存功能

    感觉Adobe Flash在跟M$的silverlight pk完胜,但是却直接被HTML5吞了,有了HTML5这些东西,要flash干啥?真是可怕。

    Tags: , ,

  • 06 六 2009 /  互联网技术

    首先,探索新鲜事物是有风险的;一个下午时间,工作用的SVN库内容被我搞乱了一点,我本机的代码被误删,这些血的代价换回的是一个整合的开发体验。我将我在开发中用到的几乎所有的内容都整合到Eclipse中了,有点爽。

    先介绍我开发时会用什么,php、python、actionscript、javascript是最近常用的几种语言,用SVN做代码库,Trac进行文档编写和bug管理以及任务分配。因为主要是Web应用,所以nginx做为web server通过fastcgi连接php和python,基本上调试是在开发服务器上完成的,本机也可,但是我的确比较烦windows下这些环境的配置。所以时不时要通过ssh来传送文件到远程的开发服务器上。

    再来讲讲Eclipse,这厮也不是什么新鲜东西了,n年前就听说几大巨头共同投资开发了这样的一个开源的集成开发环境(IDE),当年初次体验时没有什么感觉,那时候还主要用于java或者C/C++的开发,附带的插件还很少。也许Java的fans追捧的比较多。我长时间开始使用Eclipse是因为做一些Flex的项目,Flex Builder本身就是一个Eclipse的变种,被Adobe公司优化后,在那个时候相比直接下载的Eclipse来讲,好用很多,毕竟这个东西是卖钱的,不好用能行嘛。Flex项目完成后对Eclipse的感觉也加深了,总想将php开发的环境也迁移过来,我印象中触动我的新闻消息是Zend Studio也做了Eclipse的版本。但是直到今天前,我还觉得整合不是很完善,也许是没有踏实下来用,也许是插件发展还没有跟上我的要求。

    于是今天,我再次弄了一下这个东西,发现最近一段时间它的插件跟进速度很快,基本上可以满足我上述所有的要求,当然也许是我终于踏实下来研究了一下。下面是配置的一些流程以及一些配置注意项,正常情况下,如果没有什么异常,Eclipse配置好后就可以在windows、linux、mac下完成主流语言的开发、调试工作,并且可以将项目代码通过SVN来共享,并且可以管理自己的Todo list以及Trac上的ticket。怎么样,听起来是不是很爽?ok,如果你不想在试验体验时有血的代价,听好我的流程和注意项,Let’s go!

    访问http://www.eclipse.org/downloads/下载Java Developers版本,这个版本相对比较小一点,预装的东西少一点,后续按需自己安装插件嘛。一开始我选择了Classic版本,也没有什么问题,但是因为增加了所有功能的源代码以及Eclipse开发文档、插件开发库等东西,导致这个软件包比较大,大的坏处是下载很慢并且程序启动的时候因为加载很多无谓的东西导致很慢。所以一切你自己需要来选择初始版本。

    下载后解压到你希望它存在的目录就可以了,然后进入目录,运行eclipse.exe,如果你是其它操作系统的,就照着类似的方法安装启动就可以了。第一次启动会让你选择默认的项目工作目录(workspace),你可以每次都选择来切换不同的工作目录,也可以默认死一个,一个工作目录可以包含多个项目。这里要注意的是未来工作目录下的项目目录是会在建立或者导入项目时清空目录中的内容的,所以未来设置项目路径或者选择工作目录都要小心,我的文件就是这么被误删的,呜呜~~~~

    启动界面如图,默认是一个欢迎界面

    eclipse welcome windows

    可以关闭这个欢迎界面,以后要再想看的话,在目录help->welcome中激活,先不要研究这个,直接切入主题。我们先安装php的开发插件。

    访问这个地址http://www.phpeclipse.com/wiki/Installation,选择你所需要的update源,复制地址,例如我选择的是http://update.phpeclipse.net/update/stable/1.2.x,然后回到Eclipse中,选择目录help->Software Updates,如下图所示将update源地址添加进入更新列表中,然后就可以在列表中选择新安装或者更新的软件包了。

    eclipse add update site

    点击列表左侧每一项前面的加号,就可以展开看到可以安装的软件包,勾选你需要的,对于php来讲,选择全部,然后选择右面的install按钮,等待一会儿会再跟你确认是新装还是update,再次确认后就开始实际的下载安装了。这里我没有考虑网络太慢的原因,如果你实在受不了的话,可以找个地方先下载好软件包,然后还是在这个add site的地方加入,只是选择右面的local按钮选择本地文件罢了。

    好,在建议下重启eclipse以后,你会发现多了一些小东西,首先可以new php的project了,如果你在菜单file->new下无法看到默认的php project不要紧张,直接选择new project也可以,这时候创建项目的向导程序可以允许你选PHP目录下的php project,接下来的事情跟着向导程序一步步走就可以了,你就可以轻松建立一个php的项目了。

    php项目会进入php视图,如果没有的话,可以在菜单windows->open perspective->other里面选到,选好以后应该能发现菜单下多了一排小图标。这里用到的是一个开发环境简化安装的项目XAMPP。phpeclipse可以和xampp联动,做到在开发界面中重启例如apache、mysql等相关的服务,十分方便。不过,我不用XAMPP所以暂时没有研究它怎么调用我自己配置的开发环境。

    同样道理,我们参考上面的流程来安装python的开发插件。我选择的是PyDev,访问http://pydev.sourceforge.net/download.html页面来选择合适的update节点地址,拷贝下来还是到添加站点的地方添加,并且选择安装软件包,稍等片刻后就会安装好。重启后需要做一个配置来映射系统的python解析器,访问菜单Windows->Perferences->Pydev->Interpreter下,如图所示:

    eclipse config pydev

    选择右上角new一个新的python interpreter,起一个名字并且指定python.exe所在的路径,确认后就和上面的截图效果一样,会配置好所有的python库的路径,如果你要添加额外的库,也可以在下面这个框里面添加。至此pydev的设置也都ok了,创建项目和php的那个流程一样。我想其它语言你只要能找到它的插件,按照这个流程安装都应该可以支持。下面我们来说一些辅助的功能,eclipse与svn结合。

    Eclipse默认只有CVS的支持,svn毕竟是一个新东西,但是它的确比cvs好用,所以一直期待这个插件,这次我能完美的安装并使用这个插件了,安装流程和上述的流程都是一样的,非常简单,只是有一个概念要搞清楚。eclipse网站展示的只是svn插件的部分,让它顺利运行还需要安装一个第三方的svn connector接口以及选择一个connector实现。下面两个连接分别是插件和connector的update地址。

    http://download.eclipse.org/technology/subversive/0.7/update-site/

    http://community.polarion.com/projects/subversive/download/eclipse/2.0/update-site/

    安装好重启后可以在新建项目的时候选择Project from svn,这样就可以从svn直接checkout出来一个项目来开发程序了。需要特别注意的是,如果你不选择默认项目work space,你一定要自己制定项目的子目录,如果你选择了一个workspace但并没有选择子目录的话,它会在建立项目时将选择的目录内的所有内容都删除了!我就被删了我所有的开发代码。

    还有要注意的是,如果你直接将你现在的项目import到svn,它会将你当前项目当做目录import进去,所以不要而外再起一个svn的子目录名字了,不然就会多了一层,很乱。

    Eclipse默认还安装了 Mylyn的模块,它基本上是一个开发时的任务管理器,它可以和代码相关,比如你在代码注释里填写TODO:xxxx,它就会自动提取这个把它变成一个todolist。更加增强的是,如果你选择安装mylyn的trac插件,你还可以随时调用trac里面的ticket来做bug或者任务管理。因为目前跟trac 0.11.3的配合还不是太好,需要下载一些patch才能work,所以这部分我打算日后单独写一篇文档来描述,下面只是列出Mylyn的trac插件update地址。

    http://download.eclipse.org/tools/mylyn/update/extras

    总结:Eclipse是名副其实的综合IDE工具,因为它开源的特性导致会有更多的人提供基于它的开发工具特性,它也就会支持更多的开发语言或者开发领域。熟悉这个工具非常值得,因此希望大家玩得开心,happy coding!

    Tags: , , , ,