产品库
随着手机行情系统的顺利上线并平稳运行,导购频道开始酝酿一个更大的计划:准备一个更完整的 3C 产品库。
这件事比手机报价复杂不少。手机至少还是同一类产品,参数结构完全一样;但将庞杂的 3C 产品放在一起,情况就完全不同。显卡有显存、核心频率和接口类型,显示器有尺寸、分辨率和响应时间,换成打印机,又是另一套参数。
如果每增加一种产品,就重新设计数据表、修改后台页面,产品类别一多,系统很快就会变得难以维护。
那段时间,我其实还同时在另一家软件公司实习,刚好接触到 MDA(Model Driven Architecture)的一些概念。这个思路放到产品库里,刚好可以解决一个问题:不要把每一种产品的结构写死,而是通过一个“元模型”描述不同产品类型有哪些属性,再根据这些定义维护具体产品信息。
简单来说,就是新增一种产品类型时,尽量做到零代码修改,而是通过配置来扩展系统。这个想法确定以后,产品库的开发才正式开始。
2000 年初的 Web 开发
这个产品库的开发过程,其实也体现了 2000 年初 Web 开发的一些特点。
那时的网易,主要还是一家门户网站。导购频道虽然关注 3C 产品,但核心业务依然是内容:编辑整理信息,网站负责展示内容,让用户查询和浏览。所以这个产品库本质上也是一个典型的信息发布系统。
这种系统本身比较简单,主要围绕信息展示、数据查询和基础交互展开,并不需要今天这么细的角色分工。
当时,业务需求通常直接来自编辑。比如在这个项目里,Eric 提出需求和想法,跟团队里的美工荣仔沟通好页面和交互,荣仔负责出设计稿和切图。而我拿到这些静态文件后,便接手了后续所有的代码开发。
当时主流的做法,是把 HTML 等页面代码与服务器端程序混写在一起,动态输出页面内容。所以那时并没有今天意义上的前后端分工,我一个人需要同时包揽页面最终呈现、后台业务逻辑以及数据处理。
按照这种协作方式,产品库的开发很快完成。放到今天来看,这种开发方式已经很难适应复杂互联网产品的需求。但在 2003 年,它和当时 Web 系统的复杂度是匹配的。
不过,系统开发完成以后,一个最现实的问题摆在了面前。
不够优雅
产品库覆盖大量 3C 产品,每个品类下面都有很多品牌和型号,每个型号又包含大量参数。如果完全依靠人工录入,工作量非常大。
Eric 正准备招几个兼职,专门负责数据录入。这很理所当然。
然而,我并不这么认为。看到团队准备安排几个人长期重复录入数据,我当时想的不是怎么去增加人手,而是本能地觉得这种解决方式不够优雅。
既然这些产品资料已经存在于其他网站上,为什么不能让程序帮我们完成这件事?
我跟 Eric 说,先别急着招人,我想想办法。
接下来,我写了一套爬虫程序,把相关产品页面批量抓下来,再从页面中提取品牌、型号和各种参数。真正麻烦的是不同产品的参数体系完全不同,页面结构也并不统一,我最后做了一套基于正则表达式的解析机制,并把不同产品类型的解析规则做成配置。

支持多层正则逐步抽取数据:先定位候选区域,再逐层提取目标字段;
支持枚举值映射,把网页原始内容转换成系统需要的标准值。
大概一个星期以后,我又去了好世界广场。Eric 问起数据录入的事情,我很平静地告诉他,数据已经初始化完成。
Eric 原本以为我说的“初始化完成”,只是开始了一部分工作,后来才发现整个过程其实已经结束了。
数据初始化完成以后,产品库终于可以真正投入使用。很快,Eric 又有了一个新的想法。
DPSHOW
这个想法,就是做一个面向摄影爱好者的社区,名叫 DPSHOW。具体负责牵头这个项目的,是团队里的编辑阿进。
2003 年前后,数码相机开始逐渐普及,网上已经出现了不少摄影论坛。摄影爱好者会在论坛里分享作品、交流器材和拍摄技巧。虽然 DPSHOW 的思路和当时的论坛有些相似,但核心焦点并不完全一样:论坛的核心是帖子,而 DPSHOW 关注的则是用户上传的摄影作品——大家发布的不再只是一段文字,而是一张张真实的照片。
如果用今天的产品语言描述,DPSHOW 已经有了一些 UGC 的影子:普通用户可以上传自己的作品;同时,一些摄影师也会持续产出更高质量的内容。也是在那几年,模特约拍开始在圈子里流行。摄影师约模特拍摄作品后,再上传到网站交流,这类图文逐渐成了摄影社区里极具分量的内容。
和前面的产品库不同,DPSHOW 不再只是一个服务编辑和运营的后台系统,而是一个直接面对用户的网站。从技术上看,它的用户体系、内容发布和评论互动与论坛颇为相似,这些常规模块我之前已经做过不少。真正带来全新挑战的,是图片本身。
文字内容主要是数据展示,而图片除了存储和展示,还需要进行处理。例如用户上传作品以后,系统需要生成缩略图,并进行一些图片优化处理,比如锐化。
解决了图片处理的技术细节后,DPSHOW 很快便正式上线。上线以后,凭借“模特约拍”这类极具吸引力的题材,这个摄影社区也无意中找到了当年的“流量密码”。而随着用户数量增加,它很快给我带来了一个以前没有遇到过的问题。

200 万 PV 的考验
DPSHOW 上线以后,访问量增长得非常快,后来很快到了每天大约 200 万 PV。
对今天的大型互联网系统来说,这个数字可能不算惊人。但放在 2003 年,而且还是一个以图片为核心的摄影社区,这已经给系统带来了不小的压力。
很快,系统开始出现瓶颈。最先扛不住的不是代码,也不是数据库,而是带宽。
普通网页主要是文字内容,而摄影作品一张图片的大小,可能就超过很多普通页面。用户浏览作品,本质上就是不断下载图片。大量请求集中到同一台服务器以后,出口带宽很快成为瓶颈。
当时还没有今天这样成熟的 CDN 服务。遇到这个问题后,Eric 也找运维沟通过,但在现有条件下并没有什么现成方案可以直接解决。既然单台服务器已经成为瓶颈,那就只能增加服务器,把压力横向分散出去。
我让运维增加了几台服务器,并通过 NFS 让图片在这些服务器之间保持同步。然后在页面渲染图片路径时,我增加了一层简单的路由逻辑,根据图片信息动态选择不同服务器的地址,让图片请求分散到多台机器。
这样,原本集中在一台服务器上的图片访问,就被拆分到了多台服务器。
当时我还没有“分布式”这个概念。对我来说,这只是一个很具体的问题:单台服务器扛不住,那就让多台服务器一起承担压力。
现在想来,这套实现其实已经具备了一些水平扩展的思路。
好世界的天台
DPSHOW 稳定下来以后,我和 Eric 之间已经形成了一种比较稳定的合作方式。
其实最开始,我还是会定期去好世界广场办公。但后来随着几个系统陆续上线,很多事情已经可以远程完成。平时有新的需求,Eric 和阿进就通过 POPO 跟我沟通,需要当面把事情理清楚的时候,我再过去一趟。
2003 年最后一个月的一天,Eric 突然联系我,让我去一趟好世界广场,说有些事情想当面聊。
地点不是办公室,也不是那个十平方米左右的小房间,而是好世界广场的天台。
站在天台吹着风,我脑子里很自然地想到了《无间道》里的经典场景。其实还没开始聊,我就隐约感觉到,这次应该不是普通的需求沟通。
毕竟,一个开发需求,没必要特意跑到天台去说。
