Lion经验两则

No Comments

最近经历的Lion下比较想记一笔的经验,凑个数吧。

  1. 无厘头的DNS无法解析问题。

    不知道为什么我总是碰见这个问题… 网上搜了搜似乎也不是很常见。

    症状很简单:DNS无法解析,重设DNS服务器地址、DHCP的话重新续租等等都没法解决。

    解决方法:重启mDNSResponder服务。

    似乎有些简单粗暴了,不过确实没找到其他方法。记得Lion之前,这个mDNSResponder服务就总给我找事儿,不过那时的症状很明显,一般是从休眠唤醒之后,mDNSResponder进程的CPU使用率异常高,占满一个CPU核心;升级到Lion之后就再也没遇到这个问题,当时还觉得这个升级的钱花的值得。结果,后来就时不时地遇见DNS无法解析的问题了,无论怎么修改DNS相关设置都没法解决,syslog、dmesg输出也没有任何异常信息。后来想起来mDNSResponder最近很是消停,就上网搜了搜,才知道原来这个服务不像名字暗示的那样只负责mDNS,而是负责所有解析了。也许咱家接触Mac太晚了,不知道这个服务的渊源,我只记得Ubuntu下关掉Avahi是不影响其他DNS解析的。

    于是老方法重启了mDNSResponder服务,问题解决。

    
    launchctl stop com.apple.mDNSResponder
    launchctl start com.apple.mDNSResponder
    

    果然咬人的狗不叫。

  2. 把用户追加到其他组。

    各种userxxx命令在Lion下都是没有地,只有万能的dscl。简短截说,一个例子:

    
    dscl localhost -append /Local/Default/Groups/wheel GroupMembership iusr
    

    其实刚开始也就是知道dscl这么个东西而已,不过好在有-list命令可以去遍历“/”下的各个节点,然后就比较简单了。需要注意的也就是不同版本的Mac OS X的本地目录(此目录非彼目录哇~)下的用户组的路径不太相同,本地目录作为数据源的名称也不同,这些不同之处基本上不带参数跑一下dscl也就看出来了,就不废话了。

    哦,网上有人说用水果官方的Server Admin Tools来做这个事儿,不过我试验了一下,类似wheel这种组是看不到的,dscl下反正是可以看见,命令行也简单直白,所以就不纠结Server Admin Tools了。

以上~自行su/sudo。

安装gevent,Lion上

No Comments

不出所料,凡是带本地绑定的Python库,在Mac上多多少少都别扭一些。

今天是pip install gevent的时候出错:

In file included from gevent/core.c:225:
gevent/libevent.h:9:19: error: event.h: No such file or directory
gevent/libevent.h:38:20: error: evhttp.h: No such file or directory
gevent/libevent.h:39:19: error: evdns.h: No such file or directory

……

gevent/core.c: At top level:
gevent/core.c:21272: error: expected ‘)’ before ‘val’
lipo: can’t figure out the architecture type of: /var/tmp//cceaLjtd.out
error: Setup script exited with error: command ‘gcc-4.2′ failed with exit status 1

没仔细看pip怎么传-I、-L的参数去,环境变量也烦得慌,反正直接python setup.py可以接受这两个参数就好了。

直接下载gevent的源代码包,然后

sudo python setup.py install -I /usr/local/include/ -L /usr/local/lib

即可。因为/usr/local 是给brew指定的默认PREFIX,libevent也是通过brew安装来的。

 

有关并发

4 Comments

最近那个靠谱的小朋友开始看OpenJDK 6的源代码,相比之下真是让我汗颜,我机器里的代码都扔在那儿很久了。

不知道这个小朋友是不是也从main()开始看,还是为了搞明白一些问题而有针对性地去看。反正最近跟我讨论了一些并发、多线程方面的事情,很多概念和算法都是上学时就学了的,但是不出意料我也已经都忘了。于是,呃,现在看来最方便的查资料方式莫过于wikipedia.org了,也不知道会不会出些纰漏,不过英文版比中文版要好很多,内容多,引用和批注看起来也比较充实,暂且相信这么多人的劳动成果吧。摘录一些基本概念:

Critical Section:

临界区。本质上是段代码,其中包含一定需要确保同时只能被一个执行这段代码的线程访问的资源。临界区本身来说并不是实现对资源互斥访问的算法或者机制,一般都需要借用互斥量、信号量之类的结构来确保这种多个线程对这个资源的互斥访问。

Mutex:

mutual exclusion,互斥量,互斥体,互斥锁,whatever,基本带上“互斥”就行,也很常见。最简单的用来确保临街区并发安全的算法或者机制,同时也是用来指代负责在多个线程中协调互斥操作的那个数据结构,我想后面这个用途应该更常见,一般说进入了某个mutex保护的临界区以内为 “持有/获得了某个mutex” 。

Mutex有硬件和软件的实现。硬件实现方面,单处理器机器上一般就是临时禁掉中断和上下文切换,多处理器机上一般用原子的test-and-set操作让几个线程通过一个共享的标志变量做busy-wait,也叫做“自旋锁”(spinlock);软件实现就太多了:Dekker算法,Peterson算法,还有发明Paxos的大神Lamport的面包店算法,以及最近才知道的一个Szymanski算法。这几个算法应该都是lock-free的 (???)。

Semaphore:

信号量有一个初始值用来控制进入临界区的进程/线程数量,从而将并发访问的进程/线程数目控制在初始值限定的数量以下。说到信号量,其实这倒是一个可以从互斥量延展开的概念:互斥量可以看做初始值为1的信号量,而且有些实现里信号量和互斥量的也很类似。信号量有两种操作:P和V,P操作用来将限制并发访问的数值减1,V操作相反。所以一般情况下使用信号量访问共享的资源/数据的时候以P操作开始而以V操作结束,而进行P操作的时候如果信号量的用来控制并发访问的值已经降为0的话,调用P操作的进程/线程就没办法进入临界区而要等待其他进程/线程做完V操作。有的情景中也会把P操作叫做wait,V操作叫做signal。

Monitor:

监视器,对于Java程序员来说这是最熟悉的并发控制单元和概念。简单来说,监视器类似mutex加上wait+signal操作:排他,而且支持不同的线程彼此通过wait和signal操作进行通信。多个线程彼此之间需要协作和某种意义上的通信也算是个可以理解的需求,而无论是获取mutex还是semaphore的P/V操作,都没办法满足多个线程在临界区以内互相协调,所以如果真的遇到了这种需求,只好想方法变通去。监视器正是可以支持多个线程在临界区内进行一些更细粒度的协作——通过wait和signal操作,而且必须保证多个线程在临界区内执行的排他特性。

和信号量的P/V操作——有些时候也会被叫做wait/signal——不同,监视器的wait和signal操作可以让当前线程暂时释放掉已经持有的监视器,当然,因为这个时候当前线程已经进入临界区,所以暂时释放掉监视器以后就不能再继续执行了;然后在其他线程执行同一监视器上的signal方法后,这个暂时释放掉监视器的线程就可以在调用signal的线程离开临界区以后继续从上次调用wait的地方执行。其实对于signal调用后具体应该要决定哪个线程该继续执行也是有两种争论:一是把调用signal的线程挂起,把原来在wait的线程唤起;另一种正相反,调用完signal的线程继续跑,离开临界区之后才轮到原来在wait的线程继续执行。Java应该是后面一种。

 

基本上应该就这些了吧,没涉及到分布式条件下的互斥和同步。没有太仔细看所以出错了的话还望斧正。

解决一个JCC编译构建问题

2 Comments

首先是环境:


iusr-mbp:~ iusr$ uname -a
Darwin iusr-mbp 10.7.0 Darwin Kernel Version 10.7.0: Sat Jan 29 15:17:16 PST 2011; root:xnu-1504.9.37~1/RELEASE_I386 i386

iusr-mbp:~ iusr$ python -V
Python 2.7

JCC是最新的pylucene-3.1.0-1里面的那份儿。

起因是想做个小东西,预计要用到Lucene。别看我不怎么用它,可我还真嫌java干起来太麻烦…虽然做这个也想为了方便工作时用,可也算业余时间折腾吧,实在懒得一本正经地Java。所以选择了PyLucene,自然,以前也没接触过。

按照http://lucene.apache.org/pylucene/jcc/documentation/install.html上的说明,看起来不难,可惜,果不其然,到了我这里就出问题了,诶。

出问题时的输出:


iusr-mbp:jcc iusr$ python setup.py build
running build
running build_py
writing /private/tmp/pylucene-3.1.0-1/jcc/jcc/config.py
copying jcc/config.py -> build/lib.macosx-10.5-fat3-2.7/jcc
copying jcc/classes/org/apache/jcc/PythonVM.class -> build/lib.macosx-10.5-fat3-2.7/jcc/classes/org/apache/jcc
copying jcc/classes/org/apache/jcc/PythonException.class -> build/lib.macosx-10.5-fat3-2.7/jcc/classes/org/apache/jcc
running build_ext
building 'jcc' extension
gcc-4.0 -fno-strict-aliasing -fno-common -dynamic -arch i386 -arch ppc -arch x86_64 -g -O2 -DNDEBUG -g -O3 -dynamiclib -D_jcc_lib -DJCC_VER="2.8" -I/System/Library/Frameworks/JavaVM.framework/Headers -I_jcc -Ijcc/sources -I/Library/Frameworks/Python.framework/Versions/2.7/include/python2.7 -c jcc/sources/jcc.cpp -o build/temp.macosx-10.5-fat3-2.7/jcc/sources/jcc.o -DPYTHON -fno-strict-aliasing -Wno-write-strings
/usr/libexec/gcc/powerpc-apple-darwin10/4.0.1/as: assembler (/usr/bin/../libexec/gcc/darwin/ppc/as or /usr/bin/../local/libexec/gcc/darwin/ppc/as) for architecture ppc not installed
Installed assemblers are:
/usr/bin/../libexec/gcc/darwin/x86_64/as for architecture x86_64
/usr/bin/../libexec/gcc/darwin/i386/as for architecture i386
lipo: can't open input file: /var/folders/Gy/Gyqx+dxCGlGc5LULCWn6Zk+++TI/-Tmp-//ccr6jC50.out (No such file or directory)
error: command 'gcc-4.0' failed with exit status 1

也不知道是不是因为XCode刚更新过,给PPC的as明明是在 /usr/libexec/gcc/powerpc-apple-darwin10/4.0.1/as ,好吧,ln -s 一下到/usr/local/libexec/gcc/darwin/ppc/as 下面。结果还是不行…换了个错误:


iusr-mbp:jcc iusr$ python setup.py build
running build
running build_py
writing /private/tmp/pylucene-3.1.0-1/jcc/jcc/config.py
copying jcc/config.py -> build/lib.macosx-10.5-fat3-2.7/jcc
copying jcc/classes/org/apache/jcc/PythonVM.class -> build/lib.macosx-10.5-fat3-2.7/jcc/classes/org/apache/jcc
copying jcc/classes/org/apache/jcc/PythonException.class -> build/lib.macosx-10.5-fat3-2.7/jcc/classes/org/apache/jcc
running build_ext
building 'jcc' extension
gcc-4.0 -fno-strict-aliasing -fno-common -dynamic -arch i386 -arch ppc -arch x86_64 -g -O2 -DNDEBUG -g -O3 -dynamiclib -D_jcc_lib -DJCC_VER="2.8" -I/System/Library/Frameworks/JavaVM.framework/Headers -I_jcc -Ijcc/sources -I/Library/Frameworks/Python.framework/Versions/2.7/include/python2.7 -c jcc/sources/jcc.cpp -o build/temp.macosx-10.5-fat3-2.7/jcc/sources/jcc.o -DPYTHON -fno-strict-aliasing -Wno-write-strings
/usr/bin/../local/libexec/gcc/darwin/ppc/as: can't fork a new process to execute: /usr/bin/../local/libexec/gcc/darwin/ppc/as (Resource temporarily unavailable)
lipo: can't open input file: /var/folders/Gy/Gyqx+dxCGlGc5LULCWn6Zk+++TI/-Tmp-//ccNXEZps.out (No such file or directory)
error: command 'gcc-4.0' failed with exit status 1

郁闷了。折腾来折腾去都不行,直接cp过去给PPC的as也是不行,而且,真想不通为啥去为PPC编译,反正只是本地自己用。然后只好用python -v setup.py build 看了下输出,查到了编译前要调到distutils.unixcompiler.py,于是看了看源代码,看到有个_darwin_compiler_fixup方法很是可疑——敢情,这方法是会考虑ARCHFLAGS这个环境变量的——是啊!当初折腾编译、make时要折腾的若干叉叉叉FLAGS环境变量之一啊!看来后来一直都是被各种自动化工具养得白痴了,看来生命还是在于折腾。

于是乎,


iusr-mbp:jcc iusr$ export ARCHFLAGS="-arch x86_64 -arch i386"

x86_64和i386怎么都够我用了~然后再python setup.py build以及python setup.py install,成功。这一来就不用考虑诸如Xapian这样的东西了,长的跟“下片儿”似的。

P.S.,distutils.unixcompiler._darwin_compiler_fixup前面的一段注释挺好玩,as usual。

QCon Beijing 2011 Day 1

7 Comments

继续。对今天的讲座多少有些失望,同去的同事们也这么说。也算说明一个问题:别以为站在台上的就都是无比牛气的。我看着失望还无所谓,一牛人同事也觉得今天的session比较失望,那就是问题了。

今天的选择:

09:00
10:00
百度离线集群整合之道
(幻灯片下载)
讲师:吴波
大宴会厅(设同声传译)
11:10
13:00
“稳定压倒一切”——银行应用中的稳定性考量(幻灯片下载)
讲师:周伟然
大宴会厅
14:20
淘宝前台系统优化实践 (幻灯片下载)

讲师:蒋江伟

大宴会厅

15:50
在云中操控Netflix
(幻灯片下载)
讲师:Adrian Crockcroft
第六会议室(同声传译)
17:10
网游服务器性能优化

(幻灯片下载)

讲师:谢廷宝

第一会议室

想去而没法去的是:淘宝网线上线下性能跟踪体系和容量规划(幻灯片下载) ,讲师:吴毓雄基于Spring 3.1的现代组件设计(幻灯片下载),讲师:Juergen Hoeller艺龙旅行网架构案例分享(幻灯片下载),讲师:贾志峰企业级软件的组件化和动态化开发实践(幻灯片下载) ,讲师:池建强

今天的内容感觉没啥意思,所以也不想太多点评了,诶。

  1. 2011年的企业级Java和超越:从JavaEE 6到云计算:本来人家名字是Jürgen Höller,结果被替成了Juergen Hoeller,怪不得一直没认出来这是谁是干啥的呢(呃,我承认没仔细看QCon的讲师介绍材料)。直到幻灯片一开始,看到了名字,才想起来,SpringSource的。这个session整体来说,比昨天Oracle的Chuk Munn的演讲要“亲切”得多。都是讨论Java EE和云计算,Oracle一副一家独大不容置疑的样子,发明出来那一堆乱七八糟的东西(虽然Chuk Munn强调过那些小发明只是目前的状态,以后完全可能改变),而这位出身SpringSource的大叔对各种业界已经在用的云计算平台起码表示一种承认和尊重,虽然也没忘了给Spring框架做广告。总的来说是对现有很多和话题相关的技术的一个不错的覆盖和介绍。哦,让我比较高兴的是老大预料太依靠状态的范式应该会逐渐减少直至消失,至于JSF这种强烈依赖状态的东西八成就要消失——但愿,一直觉得JSF麻烦得要命,IDE支持又比不了ASP.NET,真白搭。
    值得一说的是幻灯片里特别提到了新的ForkJoinPool,也就是执行fork-join风格任务的线程池。这应该是Java 7会装备的特性,看上去是并发的map/filter & reduce,诶,Java总算也有这么个东西了。不过就像java.util.concurrent第一次引入一样,不涉及任何语言变化,纯粹是为了提升开发效率。不知道新的ParallelArray类能不能解决好诸如locality的问题——诶,跟神人习得的词汇,现趸现卖了 :D
    还提了一个问题:假如在服务的低谷时段,在线用户数量比CPU核心数量还少得时候,应用该怎么办?噻,我从来没想过这个问题,总之服务器是不会因为买卖儿不好就想不开自尽的吧。
  2. 百度离线集群整合之道:这个算是今天觉得比较不错的一个session。内容讲的是BVC——Baidu Volunteer Computing——这一系统,试图利用现有服务器的剩余计算能力为其他应用服务。Volunteer Computing不是啥新鲜事物了,我也是SETI@home和BOINC项目的N多年的资深计算节点老板了。BVC挺有想法的,不过不怎么明白的是怎么会有那么多剩余资源,多到需要建这么一个系统来统一管理?没规划好么?会后和公司的牛人讨论这个话题,还是觉得,涉及到分布式解决方案的设计的时候,明显感觉很多系统有同质化的趋势,听多了就没什么惊喜了。也没办法,就那些算法和范式。
  3. 基于云计算架构构建Netflix:见到了Adrian Crockcroft,所以很激动来着,然后发现这个session基本是Amazon的云计算产品展示会… 好在下午的内容没让人失望。此处省略好几百字。
  4. “稳定压倒一切”——银行应用中的稳定性考量:呃,这个吧,听上去还是以前企业应用的那些东西呃,顺便说了说ESB和SOA神马的。整体来说没什么感觉。
  5. 淘宝前台系统优化实践:说实话抱着很大希望来听的!结果好像此前台非彼前台啊。想必淘宝整体架构太庞大了,所以前台就是他们的web页面服务,不是折腾浏览器这头儿的东西。总的来说,这个session是多半场Java培训,至少我表示没有压力啊没有压力。后面的性能对比部分里的经验分享算是比较多的,不过很多背景、配置、步骤什么的都没有说,我觉着这些都不提,直接上来就做对比,有点儿不太严谨。至少,列一下JVM参数,做没做适当的预热,etc.,都要介绍一下吧,结果是都没有说。感觉做这个session的淘宝的小朋友可能是个比较嫩的孩纸 :D 换做JavaEye上的某些资深牛人来做,应该会很严谨的吧。
    幻灯片刚讲到前几张执行时间对比的饼图里,我眼还算比较尖,看到了Velocity的身影,所以在微博上感慨淘宝还算有眼光。Velocity我自己因为实习的关系接触得比较早,也还算比较深刻,喜欢它的简单,所以当时火爆的FreeMarker我根本一点都看不进去。我想淘宝的Java团队之所以能顺利地把Velocity的模板引擎从解释性改造为编译性,Velocity本身的简单应该也有些好处的吧——不过说这个编译化改动做了2、3个月,有点儿吓人呢,回来研究一下以现在的可用工具能用多久改造完毕。不太喜欢JSP。
  6. 在云中操控Netflix:这次Adrian Crockcroft总是讲到了些经验分享的东西。一上来还是些Amazon WS的产品展示… 然后逐渐有了些和开发相关的经验分享,比如很多anti-patterns,还有一些比较详细的中间层的设计——感觉这一点有些想东家的企业产品线里的设计和实现:由专门的team以库的方式提供这个封装好的中间层,然后底层服务是轻易不会被允许直接访问的。
    Netflix服务器的部署和升级,都是用一些自动化工具去完成,用版本控制工具管理的,而且基本没有针对机器上老版本服务器应用的升级,而是直接创建新的AWS节点部署新版本的应用,逐渐使其上线,测试OK以后直接把运行老版本的节点摘下线,最终完全销毁——比较灵活和经济的方法,而且借助了AWS的一些API,也减轻了很多重复的人力劳动,避免因为重复导致人为失误。这个幻灯片一定要再看一次,里面有不少Java开发方面的内容。
  7. 网游服务器性能优化:这个还是因为公司牛人想听这个我才后来改变主意的。感觉讲师应该有很多想要和大家分享的,不过一是时间不够,二是…有些优化和问题听上去有些…弱了… 演讲做的还是很真诚的,容量很大,不过也许我真该按原计划去池建强的业级软件的组件化和动态化开发实践,毕竟这是今天“设计优良的架构”系列的主持人啊!

今天主要的感受就是对大部分sessions比较失望,而且似乎其他来参加QCon的人也是这样的感觉,很多人频繁地来回穿梭,我就当作是在找好session听吧。一个session讲好了能让人坐下听完不走,真是不易。很多做技术出身的人都缺乏这个能力。有时我会觉得听讲座的人不该坐下后听5分钟就觉得无聊走人,也许后面的很精彩呢;另一方面也觉得做讲演的人开篇5分钟没法吸引到别人的话,水平还真的有待提高,毕竟一共就只有1个小时而已,大家都不想耽误不想花冤枉钱来听些讲的不太好的内容。

明天最后一天了,感觉大会故意安排了几个不错的来压轴吧,诶。下次中国再有QCon的话就要斟酌一下了,都是这样的session的话真不如去JavaONE了。

QCon Beijing 2011 Day 0

No Comments

标题显得很NB吧?哇哈哈…

难得这次东家能应允让我这么个打杂的来参加这么高端的集会啊,感谢感谢。

结果今天的选择是:

09:00

支撑Facebook消息处理的HBase存储系统 (幻灯片下载)

讲师:Nicolas Spiegelberg

大宴会厅(设同声传译)

10:00

Java EE 7平台:走进云计算 (幻灯片下载)

讲师:Lee Chuk Munn

地点:大宴会厅(设同声传译)

13:00

Web开发的新势力——服务端JavaScript开发(幻灯片下载)

讲师:廖恺

第七会议室

14:20

MongoDB开发应用实践(幻灯片下载)

讲师:潘凡

第一会议室

15:50

Remote Object、SOA和REST(幻灯片下载)

讲师:徐昊

第七会议室

17:10

淘宝商品库优化实践解析(幻灯片下载)

讲师:余锋

大宴会厅

 

其实还有几个很想去的但是因为安排没办法只好放弃掉:为速度而生——百姓网如何优化网速 (幻灯片下载),讲师:潘晓良QQ邮箱存储平台(幻灯片下载),讲师:胡戊构建高性能的微博系统——再谈新浪微博架构(幻灯片下载),讲师:杨卫华BeansDB的设计与实现(幻灯片下载),讲师:刘洪清一种基于服务器,集群存储和虚拟机的实现(幻灯片下载),讲师:王劲凯。Gavin King折腾了下他session的安排也比较让人不爽。

简单出于个人主观评论一下今天参加的内容:

  1. 支撑Facebook消息处理的HBase存储系统:太in-a-nutshell了,一看幻灯风格就能估计出来大概是要照本宣科了。很多事情去HBase老家和Facebook的haystack什么的地方看看就大概知道了;私以为不用太诧异于Facebook不用自己发明的Cassandara;同声传译很扯,后面不知道是不是有人把传译的耳机放了很大的音量,搞的我基本上是左耳英语右耳隐约地听中文,左耳是男声右耳隐约地听女声,真ft。私以为这种级别的演讲混外企的应该不用别人给翻译才对,旁边几个XXX公司的员工人手一个传译终端,诶,还没活明白呢。
  2. Java EE 7平台:走进云计算:这就是一个纯粹的传统商业公司能看到的云计算了。不想多说什么。module-info.java、jmod什么的真是弱爆了…新浪微博的#QCon#话题里也都有人说为什么不直接纳了OSGi什么的。没办法,看着jigsaw吧。我觉着无论基于Maven还是OSGi,基本都能自己搭一个出来了。JEE 7,掺和进来云计算,诶,不定整出来一个多复杂的规范了;有本地代码依赖的就找msi、deb、rpm,太扯了,用source tarball的可以去死了么?Oracle要自己提供一些apt、yum源神马的来定义这些deb、rpm之间的依赖不?
  3. Web开发的新势力——服务端JavaScript开发:光看标题就知道Node.js肯定占绝大部分份额了。整体来说比较充实,但是还是介绍性质的居多,真共享性质的内容偏少。没办法,这东西兴起也没多久,现在基本还不算太成熟的东西,虽然npm都出来了。后来碰见了@qinyf小朋友,也说了说寥恺,因为他以前也在饭否和海内团队呆过一段时间。这老大给我的第一印象就是绝对的脑子快反应也快,好像确实是这样,说话连珠炮一样很是痛快。我本身对Node.js这个东西也很感兴趣,真稍微突破些皮毛搞过javascript的人应该都多多少少觉得这个语言有些可把玩的地方,愿意用它干点什么。最后被广告了cnodejs.org ,回来逛逛。
  4. MongoDB开发应用实践:这个一上来以为也会是很水的介绍性质的session,结果真是比较出乎我的意料,看到了很多真实案例,感觉比较痛快,经验之谈真的是很宝贵。演讲的潘凡不紧不慢地聊着以往的经验,听起来也挺有意思的。幻灯片值得以后借鉴一下,至少很多教训知道了可以少走些弯路吧。等这个session开始的时候在场外被@qinyf小朋友当场揪了出来,我嘞个去,我还以为我一直是站在暗处的只有我认识他他不会认识我的。总上各种SNS真的很容易暴露自己啊。然后这个session是和@qinyf还有@hill两位年轻有为型牛人听的,噻,小激动了一把,都不会坐着了。期间@qinyf不动声色地考察了我对一些技术名词、项目名字的了解程度。我忐忑了。好像还称赞我算是我这个年纪的人群里面比较刻苦学习的,擦,顿时有种半截入了土的感觉。
  5. Remote Object、SOA和REST:最大的感触就是专业讲师/咨询师就是不一样啊,连续一个小时,期间几秒钟都没有停嘴啊真的。不过有些观点在我看来有些主观。最起码,简单是好事没错,不过也并不见得说一个东西复杂了就一定不好的,比如SOA。没错,WS-*、WSS-*家族太不讲求计划生育了,协议规范跟OO类型爆炸一样,我以前曾经打了一大摞协议文档只为了了解一个很简单的和T-Mobile Germany的系统对接的任务,但是实际上T-Mobile Germany也算是SOA实施比较成功的范例了,小公司上SOA实在是找死,但是很大规模的有很多员工很多需要彼此协调的部门的公司里,SOA为各个部门之间的自治和业务设计师/架构师的统一设计提供了一个可行的架构,否则还真的难以协调起那么多个部门的已经存在了的服务资源。而且,CORBA臃肿收场,EJB2臃肿收场,SOAP、Web Service、SOA臃肿收场,说不定哪天REST也是一个下场,反正看看各种为了REST而REST的应用和人们我觉得就心里没底。另外语义和ATOM(以及APP/AtomPub),我还是觉得有些摇摆不定,不知道它们以后究竟会不会得到广泛的应用。
  6. 淘宝商品库优化实践解析:某神人建议我去听的,我就不抱怨这神人太揠苗助长了 :D 这个session涉及到的领域是我一直超级感兴趣的,不过无奈实际经验和知识实在欠缺得不少。之前也遇到过很多相关的文章和话题神马的,神人都和我念叨过,我也顺藤摸瓜看了些资料,知道些皮毛不过内里显然还是不明。收获是那一大堆各种参数…sysctl的,mysql的,innodb的,天,当时场上闪光灯此起彼伏的估计也都是想记下来那些参数的吧?不知道QCon每次都会发布这些幻灯片么?此外描述的一些方法论也还不错。照例,下载幻灯片留作参考。这个我不评论了,等那神人逐个地点批吧,哇哈哈!

睡~明天第一个session就是JEE 6和云计算(之于强扭的瓜、强迫的幸福),我主观上都有些不安了…

[浅读openjdk7] 1. 构建openjdk7 @Mac

6 Comments

我这么寻思啊,在各种伟大的Linux这种对开发人员这么友好的OS们里面,一切构建方面的问题都是纸老虎。也因为目前手里没方便的Linux机器(其实公司里有一台,外加跑着blog的VPS,就是嫌麻烦…),所以怎么在Linux上面折腾build openjdk7就不废话了,应该比起openjdk6来说不会复杂太多的吧,参考 [浅读openjdk6] 1. 构建openjdk6 。在Windows上嘛,谁乐意折腾谁折腾去吧…反正build完了debug时也不是很爽。

其实今时今日Mac用户也算赶上好时候了,因为Oracle和Apple关于OpenJDK项目合作的事情似乎进行还不错,所以Oracle这边厢似乎也投入了不少,最明显的,NND终于看到像样的官方指导了!—— Mac OS X Port。这么一来build完全不构成任何问题了,ALLOW_DOWNLOADS=true 了以后连一些依赖项都会被自动下载了…

但是,我还是碰见了一个问题:那是编译corba子项目下自动生成的代码的时候,因为文件编码的问题会失败——就这么一个问题,也在 OpenJDK for Mac OS X 这篇日本语blog里描述并解决了,而且还被人在 Mac OS X Port 这篇wiki上主动留了下链接…就是那个通过设置环境变量 _JAVA_OPTIONS=-Dfile.encoding=ASCII 搞定的那部分。至于这位 dolduke 提到的其他几个问题我反正还没遇到。

感慨现在命真好的同时也确实没神马成就感了。

P.S.,春天晚上还是比较冷啊,build一下openjdk有助于取暖。

[浅读openjdk7] 0. 获取openjdk7源代码

1 Comment

呃,我自己都觉得很惭愧… 距离那篇 [浅读openjdk6] 0. 获取openjdk6源代码 过去了要2年了吧,期间总算不出意外地没有怎么继续那个系列。草稿箱里累积了大概5篇,顺着main函数开始的一些理解,结果还是没能坚持下来,哪天都删掉好了…

最近身边一个小朋友也开始看openjdk6了,加上网上某些著名人士年前也都零零散散地开始看代码并且发布了些blog,各种奋发图强人士让我感觉真是情何以堪。想了想,不行我也继续看吧,只不过目标换到了openjdk7,不是为了别人看6我看7显得多牛逼,而是对project coin那些小改动比较感兴趣。

结果,因为现在换了MacBook Pro了,不再频繁用Linux,照着自己以前在Linux下的方法做果然没能成功(呃,简直是一定的吧,尤其我也不是MacPorts用户),上网搜了搜,发现一篇 Build OpenJDK Java 1.7.0 on Mac OS X 10.5,已经装过MacPorts的权当参考吧,其实和Linux下差不多了。不过我不老喜欢MacPorts那样的东西,原先也许会喜欢吧,原汁原味的感觉,但是到了要决定是不是真要搞到自己机器上来的那一霎那,就觉得它太过臃肿了,转去用Homebrew了,虽然我也不是ruby用户…

继续搜,然后发现,好像年初的时候openjdk在BSD port的基础之上有了专门的mac os x port项目,见 http://mail.openjdk.java.net/pipermail/macosx-port-dev/2011-January/000007.html ,Apple员工发的,也算是Oracle宣称的和Apple合作提高OpenJDK在Mac机器上的覆盖面吧——这点来说Oracle至少及格了,借用开源的openjdk和Apple这样的商业公司达成了某些协议,阻止乔不死大爷试图在Mac上扼杀Java的企图。

所以现在如果在Mac OS X上想要拿到openjdk7的代码,需要clone专门的那个mac os x port项目的代码库:


hg clone http://hg.openjdk.java.net/macosx-port/macosx-port
cd macosx-port
chmod a+x get_source.sh
./get_source.sh

这样这个脚本会自动去clone位于macosx-port项目下的corba,jaxp,jaxws,langtools,jdk和hotspot这些子项目,和标准的其他平台上的openjdk7是一样的。看脚本的代码应该是不再需要mercurial的forest那个插件了,不过里面也写到了fclone分支,不知道到底什么动机,所以为求保险,建议还是安装forest插件,但是最开始的老版的forest插件已经不维护了,更新的在 http://hg.akoha.org/hgforest/,github上也看到过一个fork,说是提供了一些bug fix,不过我没试过。对于Linux和Windows来说,hg fclone依旧,顶层库的URL为http://hg.openjdk.java.net/jdk7/jdk7/

此外,Mac上XCode据说也要安装,最低要3.2.x。不知道对于拿代码来说是不是必需的,不过后期做build肯定是必备无疑。

最后,以./get_source.sh运行输出结尾。


iusr-mbp:macosx-port iusr$ ./get_source.sh
# Repos:  corba jaxp jaxws langtools jdk hotspot
Starting on corba
Starting on jaxp
Starting on jaxws
Starting on langtools
Starting on jdk
Starting on hotspo
t# hg clone http://hg.openjdk.java.net/macosx-port/macosx-port/corba corba
requesting all changes
adding changesets
adding manifests
adding file changes
added 333 changesets with 3221 changes to 1379 files
updating to branch default
1357 files updated, 0 files merged, 0 files removed, 0 files unresolved
# exit code 0
# hg clone http://hg.openjdk.java.net/macosx-port/macosx-port/jaxp jaxp
requesting all changes
adding changesets
adding manifests
adding file changes
added 252 changesets with 2188 changes to 1984 files
updating to branch default
18 files updated, 0 files merged, 0 files removed, 0 files unresolved
# exit code 0
# hg clone http://hg.openjdk.java.net/macosx-port/macosx-port/jaxws jaxws
requesting all changes
adding changesets
adding manifests
adding file changes
added 242 changesets with 6427 changes to 3002 files
updating to branch default
18 files updated, 0 files merged, 0 files removed, 0 files unresolved
# exit code 0
# hg clone http://hg.openjdk.java.net/macosx-port/macosx-port/langtools langtools
requesting all changes
adding changesets
adding manifests
adding file changes
added 945 changesets with 12323 changes to 4546 files
updating to branch default
4225 files updated, 0 files merged, 0 files removed, 0 files unresolved
# exit code 0
# hg clone http://hg.openjdk.java.net/macosx-port/macosx-port/hotspot hotspot
requesting all changes
adding changesets
adding manifests
adding file changes
added 2287 changesets with 20293 changes to 4202 files
updating to branch default
3903 files updated, 0 files merged, 0 files removed, 0 files unresolved
# exit code 0
# hg clone http://hg.openjdk.java.net/macosx-port/macosx-port/jdk jdk
requesting all changes
adding changesets
adding manifests
adding file changes
added 3767 changesets with 54877 changes to 20574 files
updating to branch default
19580 files updated, 0 files merged, 0 files removed, 0 files unresolved
# exit code 0
# Repos:  . ./corba ./hotspot ./jaxp ./jaxws ./jdk ./langtools
Starting on .
Starting on ./corba
Starting on ./hotspot
Starting on ./jaxp
Starting on ./jaxws
Starting on ./jdk
Starting on ./langtools
# cd . && hg pull -u
pulling from http://hg.openjdk.java.net/macosx-port/macosx-port
searching for changes
no changes found
# exit code 0
# cd ./hotspot && hg pull -u
pulling from http://hg.openjdk.java.net/macosx-port/macosx-port/hotspot
searching for changes
no changes found
# exit code 0
# cd ./corba && hg pull -u
pulling from http://hg.openjdk.java.net/macosx-port/macosx-port/corba
searching for changes
no changes found
# exit code 0
# cd ./langtools && hg pull -u
pulling from http://hg.openjdk.java.net/macosx-port/macosx-port/langtools
searching for changes
no changes found
# exit code 0
# cd ./jaxws && hg pull -u
pulling from http://hg.openjdk.java.net/macosx-port/macosx-port/jaxws
searching for changes
no changes found
# exit code 0
# cd ./jaxp && hg pull -u
pulling from http://hg.openjdk.java.net/macosx-port/macosx-port/jaxp
searching for changes
no changes found
# exit code 0
# cd ./jdk && hg pull -u
pulling from http://hg.openjdk.java.net/macosx-port/macosx-port/jdk
searching for changes
no changes found
# exit code 0

解决django runserver发送静态文件的一个配置问题

4 Comments

首先,不管常识也好,django自己的文档也罢,用应用服务器发送静态资源文件一直就不是什么好办法,尤其用python、java这种东西做的应用服务器,几乎没什么可能达到apache、lighttpdcherokeenginx之流的性能——当然有人说nginx是web应用平台,换而言之,应用服务器,这个我也没话说。

有关配置django通过runserver方式启动的开发测试用服务器处理用来发送静态文件的文档在:http://docs.djangoproject.com/en/1.2/howto/static-files/ ,也是警告了无数次这样做不好,只限于开发目的。

近来和几个同学做个练手的小东西,基本上就我还算知道一些web方面的事儿,大伙都是传统软件开发行业出身,nginx这种看起来很geeky的东西,八成下意识都觉得离远点儿好(这也是当初为啥我看了一阵子cherokee,毕竟管理UI太Q太省心了…),所以和哥儿几个白话了会儿选型,就有人问,诶,能让django直接管HTTP服务嘛?想想也可以理解,nginx那东西,win下还不知道啥德行了,反正我没碰过,出什么问题真耽误人家时间啊。遂折腾了一下,照文档配的,也很简单,可最后静态资源怎么都是找不到,怎么看配置都没问题的啊…

后来问题解决了,其实可能也就是个比较不常见的配置问题,原因是我把admin和site的media目录配成同一个了…当初就是觉得一是省事,二是看了看admin里的js和css,有一些东西很有重用的价值。没想到给后来埋下这么个麻烦。

怎么改配置文件都没法解决问题,直接看代码吧。

调用流程是:

manage.py -> django.core.management.execute_manager()
-> django.core.management.ManagementUtility.execute()
-> django.core.management.commands.runserver.Command.handle()
-> django.core.servers.basehttp.run()
-> django.core.servers.basehttp.WSGIRequestHandler.handle()
-> django.core.servers.basehttp.ServerHandler.run()
-> django.core.servers.basehttp.AdminMediaHandler.()

让我最开始很迷惑的就是runserver.Command里面直接诡异地传了AdminMediaHandler去后续处理请求,刚开始看代码的时候总觉得是不是哪里看错了,让个这么霸道的名字唬住了。后来一通traceback.print_stack()才敢确信,配好的django.views.static.serve()根本就没调到。

因为,AdminMediaHandler()中有这么一段判断:

if self.media_url.startswith('http://') or self.media_url.startswith('https://') \
or not environ['PATH_INFO'].startswith(self.media_url):
return self.application(environ, start_response)

因为配置里的ADMIN_MEDIA_PREFIX和MEDIA_URL都是/media/,就会导致这个条件判断为False无法进到application(),which会辗转进入后面的django.views.static.serve(),而是在admin应用的media里寻找文件,最后因为找不到返回HTTP 404。

解决方法嘛,也没啥太好的方法,不值得因为这么个破事儿去hack配置文件,把开发环境和部署环境搞的差异很大,所以就把admin用到的静态文件挪了挪窝 :D

至于为啥要打开admin嘛…我就是觉得admin挺好玩的…

设计模式培训,第0天

No Comments

其实一共也就才2天。

还是头儿一直张罗着要做一个设计模式的培训,因为连续2次公司技术考试里大部分人对设计模式的试题回答得都比较业余。我一直觉得这种东西是很虚的那种技术,所以一直以来不是太感冒:曾经有过N次都是看了设计模式的书就发现自己前几天在干的东西就是某模式,总觉得一帮人吹的那么神乎其神干什么。今天讲师也正好提到了Joshua Bloch大爷也有这种经历。所以说,自然而然地在不了解模式的情况下就应用了一种或N种模式也不是什么稀奇的事情,更不值得沾沾自喜,只不过不学习设计模式就能自己总结出目前流行的所有这些设计模式,那就真是神一般的存在了。

今天想记一笔,主要是因为有一个题目有点儿意思,直接就和讲师想到一起去了(过分低调了,否则可以拿个小奖品),而且应该比他想的还多一丁点。

题目很简单,设计一个logging框架,要求主要是:

  1. 支持同一笔log记录到不同的目的媒体,比如文件、数据库,或者通过socket传输字节流;
  2. 支持同一笔log记录到不同目的媒体时使用不同的格式;
  3. 支持log分级;
  4. 除了将log级别作为是否记录log的判别标准以外,要允许用户创建自己的算法逻辑决定log是否记录。

大概就是这个意思了,细节记不太清。

很多人的第一印象是:这不就是一个设计log4j么?!不过仔细考虑的话,1和4都是log4j不能直接支持的;第1个要求可以通过log4j.xml配置方式通过AsyncAppender搞定,但显然这是具体实现类的行为,没法体现框架的设计思路。

类图,草稿,而且不规范

类图,草稿,而且不规范

上面是草草画的一个类图,很草,而且也不规范,箭头的实虚都是后来看了UML类图规范又改的。

在大部分人都直接认为这就是个log4j的设计的时候,我和组里的几个哥们儿还是识别出来明显的差异,然后开始了我们自己的设计,目的很朴素:一定要和log4j不同,否则就不去演示了。

不过log4j在大部分java开发人员思维方式里的先入为主的地位还是很严重的,几个接口方法定义过来一看,还是那么地log4j。这可不行。于是先来统一一下中心思想,直接套一个大概还靠谱的模式:chain of responsibility。其实我心里完全想的是另外一个模式:J2EE核心模式里的intercepting filter。主要因为似乎chain of responsibility最原始的定义是最终链中只有一个节点被执行,而我的想法是把输出log的对象做成chain,这样肯定需要链中有0到N个对象能被执行,虽然可以说是种扩展,不过还是别在讨论严肃话题的时候捣浆糊的好,再者,借助filter就可以很容易地针对log级别和用户自定义逻辑进行过滤,只让满足所有条件的log被最终记录下来。

这个时候log4j给我们的先入为主的印象又作祟了一小下;控制输出log的被定义为类似log4j的Logger——姑且也叫做Logger吧,然后向log4j看齐一下,每个Logger都有一个名字,名字的命名规范和java的包及类名的命名规范类似,做成了树状的实现了继承的结构。这时我和另外一个老哥就有一点儿傻眼了:这成了树了,怎么搞链式调用啊?马上我想到一个补丁:生成一个广度优先遍历,哇,这样似乎又和iterator拉上关系了;并且然后允许客户代码获取没有预先配置好的Logger,默认的log行为是继承父节点的行为,这也比较类似Log4j,然后每一次客户代码获取没有预先配置好的Logger的时候,框架就在其父节点下挂接上这个新的Logger,更新广度有限遍历的iterator,etc.。如此这般,折腾了一会儿以后,我失望地发现,哎,这不还是log4j么,核心的部分基本是换汤不换药的。

好在随即马上又想到一个补丁。以上的思路的中心都是Logger们用命名规范生成出来的一个树状结构,痛苦也来源于此,但是现在已经有了filter的定义,不如换个思路,把记log时所用的Logger的名字一起作为参数传到filter中,然后做一个根据Logger名字来决定是否过滤Log消息的filter。这样一来,让我头疼的树状结构终于被干掉了,对框架来说偷了些巧,而且实现这样一个拿到Logger名字然后做一下字符串操作的filter也远比遍历、维护树状结构容易很多。至少针对这个题目看来,树状的结构没有带来更多的好处。

于是我们team就产生出了2种设计:一种是之前最终演化成和log4j基本差不多的设计,一种是我更喜欢的剥离出Logger名字管理的使用了intercepting filter模式的设计。后者明显更简单一些,没有不必要的处理。事后才反应过来,那个树状组织Logger的方式完全不是必需的,题目也根本没提到,只是作为一个需求更改验证了一下我的想法能处理这种组织方式。

讲师在看了其他team的设计之后也公布了一下他的设计,据他说那是97、98年左右的事情了,那个时候他也是刚毕业,和项目经历一起花了一个晚上重构他之前的臭代码到这个设计。98年左右,国内是肯定没有引进设计模式这本书的了。

之后也有其他很多同事“攻击”了chain of responsibility,指出这个模式和这个题目的要求似乎不太搭调,毕竟没人要求必须按照某个顺序记录同一笔log,而observer模式应该更适合一些。其实这个问题用observer的缺陷是很明显的了,filter逻辑完全要再借助其他类实现。无所谓了,好在我提到是用intercepting filter,而不是chain of responsibility,如果照讲师的说法,chain of responsibility带个filter,那observer带个filter不也可以解决同样的问题么。

是以为记。比较意识流了一些,嗯。想想这样一个logging框架,做出来应该也是有一定用途的吧。

作业是一个异常处理框架。实在有些想用上AOP,不知对付OO设计模式的题目算不算作弊乜?

Older Entries