Brad Fitzpatrick 是所有受访者中最年轻的一位,也是其中唯一一位从未在没有因特网或个人电脑的世界里生活过的。他出生于
1980 年,很早就开始了自己的程序员生涯, 5 岁时就在一台自制的 Apple II
克隆机上学习编程。在十几岁时,正好赶上因特网革命的大潮,他一头扎入其中,在高中时就建立了自己的第一个商业网站,在进入大学前的那个夏天创立了著名社
区 LiveJournal 。
LiveJournal 的日渐流行迫使 Fitzpatrick 走上了学习构建可伸缩网站的艰难之旅,期间他和他创办的 Danga
交互技术公司里的程序员们开发了几个开源软件,其中包括 memcached 、 Perlbal 和 MogileFS
,现在被用于很多世界上最繁忙的网站的服务器上。
Fitzpatrick 是个典型的极有才华的世纪之交的 Web 程序员,他的主要编程语言是 Perl 和 C ,需要时也会用 Java 、
C++ 、 Python 、 JavaScript 和 C#
。他做的所有编程工作基本都与网络相关,比如为网站构建更好的后端基础设施,设计协议和软件来让博客阅读软件获知博客更新,甚至为他的手机编写代码以便在
摩托车上就能自动打开车库门。
我们将谈到他在读著名儿童系列丛书 Clifford the Big Red Dog 的年龄就开始学习编程,为什么能够很高兴地一边念大学,一边运行 LiveJournal ,以及他是如何学会不惧怕去阅读他人的代码的。
Seibel
:
你是怎么成为一个程序员的?
Fitzpatrick
:我父亲曾在
Mostek
工作。这个公司是制造内存的,他对电脑很感兴趣。他做了台
Apple II
电脑,材料几乎都是多余的废弃部件。他和我母亲坐在电视机旁把部件焊起来,这个工作花了他们好几个月,只是把它们焊起来而已。然后我父亲从公司里拿了些不能卖的
ROM
,这些
ROM
有一位或几位不能用,有的在高位,有的在低位。后来不知怎么着他们弄到了
Apple II ROM
,接着就不停地将
ROM
烧到无法工作的芯片上,直到找到一块能用的为止,损坏的那位正巧是好的。最终,他和他的一帮同事终于做成了自制
Apple II
。我差不多从两岁起就在上面玩或者看他编程。
Seibel
:
他是个程序员还是个硬件工程师?
Fitzpatrick
:他是个电气工程师,偶尔也写写程序。我五岁时他就教我编程,搞笑的是我六七岁时就超过他了。我母亲说我是一边读
Clifford the Big Red Dog
,
一边读从图书馆借来的
Apple II
程序员手册。我会把
“
变量”念成
“
贝量”。我早期的一些记忆就是和父亲一起编程。比如他把我拖进厨房,在纸上写下一段程序,问我:
“
你觉得这段程序是什么意思?”我记得那程序好像是
“
10 PRINT HELLO,
20 GOTO 10”
。
Seibel
:
那么说你是从
BASIC
开始的?
Fitzpatrick
:是的,就是
BASIC
。我当时还不能使用鼠标、高级图形模式和彩色,直到我们家的一个朋友向我介绍了
C
并给了我
Turbo C
。那年我大概八岁或者十岁。我父亲在
1984
年去了
Intel
,我们就搬去了波特兰。他帮助设计了
386
和
486
,现在仍在
Intel
。我们总是能有新的有趣的电脑。
Seibel
:
那你有没有试过汇编语言呢?
Fitzpatrick
:我在计算器上做过些汇编,比如
TI
计算器上的
Z80
,但仅此而已。
Seibel
:
你还记得是什么吸引你开始编程的吗?
Fitzpatrick
:我不记得了,只是好玩吧。我母亲不得不限制我使用电脑,好让我出去和朋友们一起玩。我的朋友们会跑过来说:
“
Brad
又在玩电脑。他太无聊了。”我母亲则会对我说:
“
到外面去玩吧。”
Seibel
:
你还记得写的第一个比较有意思的程序吗?
Fitzpatrick
:我们以前有台
Epson
打印机,它配有几本又大又厚的手册,手册最后是程序员指南。我就在
Apple
上写了点东西,我可以在高级图形模式下画些东西,当程序完成绘制(线段、图案或别的什么)之后,按下
Control C
,在后台一个不会显示的帧缓冲区里键入一段内容,加载另一个程序,它会读取屏幕并打印出来。
在那之前,我记得还写过一个程序,每当我敲击一个键,它就移动稿面,我按退格稿面会向回退,这样打字时就感觉像是在用打字机一样了。
这是我的第一个程序,好比方
K
是抓取的下一个字符,如果
K
等于
a
,打印
a
;如果
K
等于
b
,打印
b
。我几乎处理了每个字母、数字和一些标点。后来一个念头一闪而过:
“
等等,我可以说‘打印一个变量!’”然后用
1
行代码替换掉了
40
行。
“
天啊,这太棒了!”对一个六岁的孩子来说,这已经是抽象能力的极限了。
那些都是比较有意思的早期作品。到了中学,我开始开发游戏,为朋友们制作图形编辑器和关卡编辑器,他们会把图形做进关卡中,随后我们再把它卖给其他同学。我记得我不得不检测
EGA
和
VGA
。如果
VGA
跑不了,就退回到
EGA
模式,使用另一组适合当前屏幕的贴图,为此我们必须为所有的东西做两组图形。学校的人会出大概
5
美元买它,然后安装,接着发现它不能用,他们的家长就会给我爸妈打电话大喊:
“
你儿子拿那没用的东西从我孩子那里骗了
5
美元。”我母亲就开车带我过去,坐在死胡同里等我进同学家调试并修复我的程序。
Seibel
:
那段日子里你有没有上过关于编程的课?
Fitzpatrick
:没有。就是从图书馆里借了一两本书,然后随便玩玩。当时没有真正的论坛或因特网。后来我连上了一个
BBS
,但上面并没什么内容,它没有联上因特网,只是一群人在玩棋类游戏而已。
Seibel
:
你的学校有
AP
C.S.
(计算机科学)或类似的课程么?
Fitzpatrick
:呃,我们没有
AP C.S.
课程,但我们有计算机程序设计课。有一个老师在上这门课,不过我都可以在教室后面讲高级课程了。他们还在用我写的图形编辑器和图形库,他们要做的项目是开发一个游戏。我偶尔还会碰到那个计算机老师,他是我家的一个朋友,我会在我哥哥的足球比赛上看到他,他会说:
“
是啊,我们还在用你的库呢。”
我的确参加了
AP C.S.
考试,那是在考试从
Pascal
换成
C
语言前的最后一年,一年后又从
C
换到了
Java
之类的语言。我不懂
Pascal
,所以去附近有
AP C.S.
课程的高中上了一些夜间班,大概三四次吧。后来我找了本书来学
Pascal
,我把大多数时间花在用
Pascal
画星形线上,因为那时我刚学三角学。我会说:
“
哇哦,正弦和余弦太有趣了。我又可以一显身手了。”
Seibel
:
那你考得怎么样?
Fitzpatrick
:我得了
5
分
。考试内容是写一个大整数类。现在这是我招聘人员的一道面试题:
“
写一个能够进行任意大整数乘法及除法的类。”既然我能在高中的一次
AP
考试中做出这道题,那么他们在这儿应该也能做得出来。
Seibel
:
你大学第一年的夏天在
Intel
工作,那在高中时期有没有做过程序员的工作呢?
Fitzpatrick
:是的,我在
Tektronix[4]
工作过一段时间。在正式工作之前,我有几个主机账号。我写了些机器人程序,往聊天室里灌水,把
AOL
惹翻了,这么做确实让人讨厌。我在另一个
Windows
程序中编写
AOL
客户端脚本,还写机器人程序猛提交
AOL
的线上表单,获赠
CD
。因为不想让他们发现这是重复表单而只寄一张
CD
,我用了自己名字的各种变体。这些账户有
100
个免费小时,或者是
5000
个免费小时。在这几千次表单提交后,整整一个星期,邮递员会天天带着很多
CD
过来。
我妈妈说:
“
见鬼,
Brad
,你会有麻烦的。”我回答:
“
呃,这是他们的错,对吗?”后来有一天,有一个找我的电话,我接了(通常我不去接电话),电话那头是一个
AOL
的人,他对我大叫:
“
别再向我们提交表单了!”我平时的反应并不敏捷,但这次我立刻回敬了他:
“
为什么你们会寄给我这些废物?每天都有邮递员过来,扔下这些
CD
!”他说:
“
对不起,先生。不会再发生这样的事情了。”然后我把这些
CD
都用来布置大学宿舍了,它们现在还放在我家车库的一个盒子里呢。我记得它们曾是很好的装饰品,所以没有扔掉。
恶搞完
AOL
后,我得到了一个当地
ISP
的
shell
账号。大概上我就是在那时学的
Unix
。虽然不能运行
CGI
脚本,但我可以用
FTP
上传东西,所以我就在家里的台式机上运行
Perl
程序来生成整个
Web
站点,接着再上传到服务器上。后来我在
Tektronix
得到了一份工作,类似暑期实习。当时我已经很懂
Perl
和
Web
了,但还没有做过动态
Web
。在
1994
年、
1995
年时,
Web
还是个很新的东西。
我去
Tektronix
上班的第一天,他们给我介绍我的办公用品:
“
这是你的电脑。”那是一台大的
SPARC
工作站,也可能是别的什么运行了
X
和
Motif
的机器。
“
这是你的浏览器。”可能是
Netscape 2
,我记不清了。
“
如果你有
CGI
的东西,放到这个目录里。”我记得那天晚上我写了个最基本的
Hello World
的
CGI
程序,大约就三行吧,我感叹道:
“
天哪,这太有意思了。”第二天早上六点我就来工作了,继续疯狂地写
CGI
。
后来我开始自己做动态
Web
编程。当时我找了台支持
CGI
的
Windows Web
服务器。我最终说服了我的
ISP
(也许是和他们交情不错,或者之前给了他们不少帮助让他们信任我):
“
OK
,我们会运行你的
CGI
,但开始前会对它们做审核。”他们仔细查看了代码,然后把那些代码扔到他们的目录里。那是一个投票站的脚本,你可以用它来创建投票程序,例如:
“
你最喜欢的电影是哪部?”添加完选项后就能开始投票了。后来的几年里它变得越来越流行了。
Seibel
:
是
FreeVote
吗?
Fitzpatrick
:是的,在弄爆我的主机后它变成了
FreeVote
。那时
Banner
广告真的很流行,也许就是那段时间开始流行起来的,我通过它赚到了越来越多的钱,得到越来越好的合同,每次点击的收益也越来越高。最高时每点击一次广告我就能赚到
27
美分,就算是按今天的标准,我觉得也是相当夸张的。有了它,我每个月在
Banner
广告点击方面能有
2.5
万~
2.7
万美元的收入。
这些都是在高中时做的,我整个高中时期都在私下做这事。我还在
Intel
做了两个夏天,随后在进入大学前的最后一个夏天,我办起了
LiveJournal
。为此,在进入大学的第一年,我卖了
FreeVote
,基本上算是送给一个朋友的,大概只要了
1.1
万美元,因为我想摆脱它,还有相应的法律责任。
Seibel
:
你有了
ISP
并开始使用
Unix
,这有没有对你编程带来什么变化?
Fitzpatrick
:
Unix
并没让我抓狂。我没办法理解
Windows
上都发生了什么,也许你看过
Windows API
—
—每个函数都有差不多
20
个参数,它们都是标志位,而且一半都赋了
0
值。完全不知道发生了什么。当有东西无法正常工作时,你根本没办法知道究竟是怎么回事。
Seibel
:
你早期的编程方法或编程风格和你现在所想的有什么明显的不同之处吗?
Fitzpatrick
:我用过很多种编程风格,面向对象的、函数式的,现在用的这种有点怪异,混合了面向对象和函数式编程。这是我热爱
Perl
的原因,虽然语法很丑陋,有很多历史包袱和瑕疵,但它从不限制我写代码的风格。用你喜欢的风格去写就是了。你能让代码优雅一致,却没有和特定语言相关的风格。直到我进入
,我写的
Perl
代码才慢慢少了下来。
运营
LiveJournal
后,我也做了很多测试工作。尤其是当我开始和他人共事时,我意识到永远也甩不掉自己写的代码,要一辈子维护它们时,我开始写测试了。在十年前的博客文章上,我收到了这样的评论:
“
嘿,我看到这段代码,发现了一个问题。”然后我立刻着手维护代码。
我现在维护着很多代码,还有其他很多人在和它们打交
道,如果有什么地方不清楚,我会假设有人理解不了我写的某些不变式。因此,当我要搞些小聪明时,通常我都会保证在代码出现问题时有测试及时跳出来。我也强
迫其他人写测试,他们基本上都为我工作。我会为自己的代码写测试,当别人写代码时我会告诉他们:
“
你确定这段代码能工作吗?写个测试证明给我看。”有时,他们会意识到
“
天哪,这么做太有用了”,尤其是在后期维护的时候。
Seibel
:
你是从什么时候开始和他人一同共事的?
Fitzpatrick
:差不多是在大学结束的时候,我开始雇用其他人,尤其是毕业搬回波特兰后。
早期的雇员是客户支持,所以他们不用写任何代码。慢慢地,我开始雇用程序员。我雇佣的第一个人是我的一个网友,他的名字是
Brad Whitaker
,我们都有名为
BradleyLand
或
BradleyWorld
的网站,因此我们找到了对方的网站。我比他早几年开始
Web
编程,也可能是早一年,他问我:
“
嘿,你的网站是怎么做的?”就是说它到底是
HTML
、
Frame
、
CGI
还是
Perl
的。后来我开始接很多合同项目,我就把一些我不做的项目给他。有一次我们有个大项目,谁都没有办法独自完成,我找到他说:
“
这个项目需要两个人来做。”他让我飞去宾夕法尼亚,也许是匹兹堡?我对东海岸完全没概念,我是个生活在西海岸的人。也许是费城?有牛肉奶酪三明治
的地方。
Seibel
:
是费城。
Fitzpatrick
:是的,我们第一次见面是在一家便宜的旅馆里,我感觉好像早就认识他一样。他和我打招呼:
“
嘿,最近怎么样?”他走了进来,在我旅馆的卫生间里上了个厕所,当时我就站在那儿,可他连门都不关。我回答道:
“
还不错。你还真惬意。”虽然我们从未谋面,可就像认识了四五年一样。然后,我们就开始干活了。
他住到我空余的一间卧室里,我们差不多把厨房给搬空了,架起几张桌子,放上电脑就开工了。我们通常
10
点或
11
点起床,干到中午,看会儿电视(穿着短裤坐着看电视),然后不间断地工作到早上三四点钟。后来,我的另一个朋友从华盛顿大学过来度暑假。他是我大学一年级后认识的,我们三个在一起忙碌着。这个朋友住在市区,早上坐轻轨过来,然后滑滑板到我家。他就坐在外面用
Wi-Fi
上网、写程序,直到我们醒过来去给他开门,让他进来。
一起有了三个人,房子就有点挤了,我就说:
“
哦,好吧,我们搞间办公室吧。”于是我们弄了间办公室,
“
我们既然有了这些空间,不如再雇点人吧!”在随后的两年里,我们慢慢扩大到了
12
个人,而
LiveJournal
也逐渐流行了起来,当然压力也更大了,因为我还得处理人事问题。
后来,我妈妈来处理人事,随后我们的关系就有点紧张了,因为她为我工作。我给她定了几条规矩:
“
如果你给我打电话,要分清楚是私事还是公事。要么只谈私事,要么只谈公事。你不能在工作与私人问题间换来换去的。”如果她转变话题,我就会挂电话。然后她再打回来,我会说
“
你搞混了”。这真的搞得很紧张,当我把公司卖掉时她真的很高兴,她不用再为我工作了,我们也不用争吵了。
Seibel
:
那时你的公司还接合同工项目吗,还是说这就是整个
LiveJournal
了?
Fitzpatrick
:差不多这就是整个
LiveJournal
了。我们还打算开个照片托管服务,这方面
Flickr
做的比我们好,我们的那个有些过度设计了:漂亮的抽象,能结合到任何东西中。为
LiveJournal
做的每个新的基础设施,我们都会问自己:
“
它怎么和
FotoBilder
结合到一起?”为此,我们把每样东西都抽象出来。
Memcached
是抽象的,因为没有必要把它和
LiveJournal
绑在一起。随后我们还做了个类似
GFS
的文件系统,还有一个任务队列。为了提高可扩展性,我们不停地开发基础设施组件,它们能被应用于我们的各项产品之中,由于没有复杂的依赖关系,它们的维护也更方便了。虽然可能会增加一些工作量,但如果能减少依赖,那还是很值得的,所以我们开发了所有这些通用基础设施。
Seibel
:
我对于你扩展
LiveJournal
的过程有些好奇,你是从什么地方开始的,一路上又是怎么学到你需要的东西的?
Fitzpatrick
:我们和其他客户共享一个
Unix
主机,差点把它搞挂了。
Seibel
:
以
CGI
的方式运行的吗?
Fitzpatrick
:是的。我想从严格意义上来说那应该是个
CGI
,派生出所有的东西然后终止掉。
ISP
分配给我一个家伙。我的服务器当时总是死机,我对他说:
“
我每月为这台服务器付
10
美元,它为什么不能工作?”他告诉我:
“
哦,你该这么做。”很快我就学会了
Unix
,知道正在发生的事情。
我从
CGI
转到
FastCGI
,调整了
Apache
,关闭反向
DNS
查询功能。经过了这些步骤,性能有了好转。最终,我遇到了
IO
和
CPU
的瓶颈,我买了自己专用的服务器,但那也只是一台机器,它经常死机,而且我的硬
盘快没有空间了。起先这台服务器只对我的朋友开放,我没有取消注册页面。他们邀请了他们的朋友,而这些朋友又邀请了其他朋友,但我并没想过把这个站点变成
公开网站。它只是正好有个开放的注册页面。于是,我在
LiveJournal
的新闻页面里写了点东西:
“
我们需要大家的帮助,我们需要购买服务器。”
我记得那次大概募集了六七千美金,我买了两台大的
Dell
服务器,托管在西雅图市区的
Speakeasy[6]
里。有人推荐了一些
Dell
服务器,这些
6U
的大家伙差不多有
90
磅
一台。数据库服务器和
Web
服务器从逻辑上是独立的。因为我运行了一个
MySQL
进程和一个
Apache
进程,所以我只知道这样去分离。
就这样过了一阵子。
Web
服务器直接面向大众,服务器上有两块网卡,通过交叉线缆(
crossover cable
)连接数据库服务器。后来
Web
服务器过载了,但那还比较好对付,那时我有了几台
1U
的服务器。之后我们有了
3
台
Web
服务器和
1
台数据库服务器。这时我先后用了三四个
HTTP
负载均衡器—
—
mod_bachhand
、
mod_proxy
和
Squid
。这些我一个都不喜欢,我就是从这时开始讨厌
HTTP
负载均衡器的。
接下来过载的就是数据库,那时我抱怨道:
“
哦,见鬼。”
Web
服务器可以很好地扩展,它们都是无状态的,只要投入更多的机器,分散负载就可以了。那段时间很难熬,
“
我可以优化查询来应付一下,”但那只能坚持一周,一周后它又会过载。那时我就开始思考一个独立的请求到底需要什么。
那时我认为自己是世界上第一个想到这个方法的人,我们可以切分数据库,将它分区存放。我画了几张图来做设计文档,简单说明我们的代码会是如何工作的。
“
我们的主数据库只存放全局相关的元数据,这些是低流量的。各个博客和评论相关的东西会分别存放到每个用户的数据库集群里。每个分区都有自己的用户
ID
。”现在看来,每个人都会这么做。但那时候在不间断服务的情况下迁移代码
着实是件很费力的事。
Seibel
:
在你迁移时有没有暂停服务?
Fitzpatrick
:没有。每个用户都一个标志位,标明他在哪个集群上。如果标志位是
0
,说明他在主数据库上;如果非零,则说明他已经被分区了。有个版本号是
“
你的账号正被锁定”。这时该账号处于锁定状态,尝试迁移数据,如果在这时你做了什么变更则需要重试。基本上在我们完成迁移前你在主库上不能进行写操作,迁移完成后声明:
“
OK
,现在你的账号可以使用了。”
迁移程序在后台运行了两个月。我们计算过,如果只是把数据导出来,写点程序拆分
SQL
文件随后重新加载,可能要花一周左右。摆在我们面前有两个选择——停机一周或者缓慢迁移两个月。我们先迁
10%