robbin的博客文章精选 2006年9月-2008年10月

You might also like

Download as pdf or txt
Download as pdf or txt
You are on page 1of 283

http://www.javaeye.

com - 做最棒的软件开发交流社区

robbin的博客文章
作者: robbin http://robbin.javaeye.com

robbin的博客文章精选: 2006年9月 - 2008年10月

第 1 / 283 页 本书由JavaEye提供的电子书DIY功能自动生成于 2008-11-18


http://robbin.javaeye.com

目录

1. Java

1.1 点评Java full-stack框架 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8

1.2 回复ozzzzzz的“Java将死?” . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9

1.3 选择Hibernate还是iBatis? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11

1.4 Spring2.0的新特性点评 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12

1.5 静态类型语言的优势究竟是什么? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15

1.6 应该如何正确使用Quartz . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17

1.7 Java程序员的推荐阅读书籍 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18

1.8 Spring2.0和EJB3.0随谈 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21

1.9 Google Guice - 比Spring快100倍的IoC容器 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24

1.10 可以开始用Struts2.0了 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25

1.11 domain model的延伸讨论 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26

1.12 缓存简述 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33

1.13 为什么ORM性能比iBATIS好? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34

1.14 漫谈应用缓存的命中率问题 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37

1.15 Java开源框架发展的遐想 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39

1.16 Java已经过时了吗? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41

1.17 Google Android会成为手机领域的微软Windows吗? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43

1.18 Warp framework - 一个相当有前途的Java轻量级Web开发框架 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45

1.19 Spring Application Platform - SpringSource的应用服务器发布 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48

1.20 发现JBoss Seam很棒呀!有用Seam做过项目的吗? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50

2. Ruby

2.1 ruby on rails为什么暂时无法成为企业应用开发的主流? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53

第 2 / 283 页
http://robbin.javaeye.com

2.2 通过JavaEye2.0网站看ruby on rails性能 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56

2.3 关于ROR的效率的一个讨论回复 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58

2.4 RoR背后的软件开发方法学思考 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60

2.5 《应用Rails进行敏捷Web开发》中文版书评 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61

2.6 rails作者DHH谈及REST . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63

2.7 在Linux平台上安装和配置Ruby on Rails详解 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64

2.8 在Windows平台使用Apache2.2和Mongrel运行Ruby on Rails . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70

2.9 ruby on rails应用性能优化之道 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72

2.10 rails项目为什么比Java项目好维护? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74

2.11 ActionController::TestSession的bug? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75

2.12 用block简化编程一例 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77

2.13 Windows平台的ruby IDE 点评 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79

2.14 RoR学习书籍推荐 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82

2.15 Robert C. Martin对RoR的高度评价令我吃惊 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83

2.16 ruby的方法调用作用域 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84

2.17 领略一下ruby的DSL能力 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86

2.18 railsconf2007大会介绍 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88

2.19 如何快速统计RoR网站的访问量 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90

2.20 RoR的部署方案选择 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92

2.21 Web开发敏捷之道(第二版) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94

2.22 JavaEye3.0开发手记之一 - 我的开发环境 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96

2.23 JavaEye3.0开发手记之二 - rails的UTF-8支持造成的正则表达式问题 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97

2.24 JavaEye3.0开发手记之三 - 狮身人面 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101

2.25 JavaEye3.0开发手记之四 - ruby的全文检索 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102

2.26 Ruby on Rails 2.0的新特性介绍 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104

第 3 / 283 页
http://robbin.javaeye.com

2.27 Ruby为什么会受程序员的欢迎? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114

2.28 RoR网站如何利用lighttpd的X-sendfile功能提升文件下载性能 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115

2.29 RoR部署方案深度剖析 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119

2.30 JavaEye网站的RoR性能优化经验谈 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125

2.31 Lighttpd和RoR安装配置的疑难解答 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132

2.32 mod_rails尝鲜 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137

2.33 使用libmmseg实现Ruby的中文分词功能 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139

2.34 rmmseg-cpp - 简洁高效的ruby中文分词程序 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143

2.35 Skynet --- ruby的类Google Map/Reduce框架 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145

2.36 Ruby和Rails的缺点 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148

2.37 推荐一篇很好的RoR部署方案性能评测 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149

2.38 对Ruby VM的GC的思考 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151

2.39 征求《Rails锦囊妙计》一书的写作内容建议 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154

3. Tech

3.1 动态脚本语言的部署运行方式介绍 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 156

3.2 lighttpd的tunning tips . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157

3.3 Linux reiserfs文件系统即将陨落 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158

3.4 软件行业2006年终回顾以及2007展望(一)回顾 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159

3.5 软件行业2006年终回顾以及2007展望(二)展望 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161

3.6 从分布式系统的角度看REST . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162

3.7 AJAX与RIA技术之我见 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164

3.8 关系模型和对象模型的究竟匹配还是不匹配? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 166

3.9 豆瓣的程序性能真的很惊人,但... . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168

3.10 memcache_engine + memcachedb = 高性能分布式内存数据库 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169

3.11 用Google的网站流量分析系统来看全球软件行业的分工趋势 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171

第 4 / 283 页
http://robbin.javaeye.com

3.12 贴一段遍历memcached缓存对象的小脚本 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174

3.13 Linux平台gcc和动态共享库的基础知识 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 177

4. 互联网

4.1 中国web2.0前途是什么 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183

4.2 中国互联网需要“费厄泼赖”精神 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 184

4.3 SAAS(软件即服务)的时代即将来临吗? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 186

4.4 iphone敲响了PC时代的丧钟 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 190

4.5 小公司SAAS战略之我见 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 191

4.6 SAAS(软件即服务) 离我们还有多远? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 192

4.7 为什么说OpenSocial只不过是一个公关骗局? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 194

4.8 我为什么鼓吹facebook,为什么唱衰OpenSocial? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197

4.9 关于OpenSocial讨论的总结 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 201

4.10 Facebook的成功秘诀是什么 - SNS之我见(一) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 204

4.11 点评国内Facebook克隆网站 - SNS之我见(二) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 208

4.12 社区网站SNS化的思考 – SNS之我见(三) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 212

4.13 什么样的社区能够成为集大成者?- SNS之我见(四) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 214

4.14 SNS网站的用户流失率怎么会高得如此惊人? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 217

4.15 珍爱创业,远离SNS - SNS之我见(五) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 221

4.16 SNS的工具化思考 - SNS之我见(六) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 222

4.17 SNS的路径选择问题思考 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 224

4.18 社区的多种形态 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 226

4.19 对FriendFeed的一点思考 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 227

4.20 对Friendfriend一点思考之二 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 229

4.21 开心001的Google trends数据一窥 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 231

5. 杂感

第 5 / 283 页
http://robbin.javaeye.com

5.1 程序员到30岁就要转行? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 233

5.2 很多开发人员的毛病 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 235

5.3 继续软件行业部分开发人员毛病的话题 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 236

5.4 2006超女是令人乏味的 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 237

5.5 技术重要还是业务重要(一) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 238

5.6 驳:程序员和建筑工人 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 239

5.7 编程语言进步是解决项目开发问题的最有力工具 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 240

5.8 技术重要还是业务重要(二) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 241

5.9 从京沪列车对比看京沪两地的服务意识 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 242

5.10 小记周末的JavaEye篮球俱乐部活动 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 244

5.11 如何规划你的职业发展道路 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 245

5.12 看了《墨攻》,感觉还不错 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 246

5.13 无责任预测2007年IT行业七大事件(本预测完全胡扯,如有雷同纯属巧合) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 247

5.14 以陈一舟的话自勉 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 249

5.15 TechTarget-值得研究的专业技术网站 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 250

5.16 杭州网侠大会观后感(附演讲ppt) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 251

5.17 从JavaEye网站访问来源看软件公司的区域选择 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 253

5.18 《太阳照常升起》观后感 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 255

5.19 关于技术人员创业入股的问题 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 257

5.20 网络招聘是如何被做烂掉的? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 258

5.21 李刚 Java - 希望电话骚扰事件就此画上一个句号 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 260

5.22 中国行业应用软件领域恶性循环的原因是什么? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 262

5.23 关于刘翔退赛的四个不理解 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 264

6. JavaEye

6.1 JavaEye1.0的老路是行不通的 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 266

第 6 / 283 页
http://robbin.javaeye.com

6.2 绝对不虚此行的活动 - 记Gavin King上海交流研讨会 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 268

6.3 闻之色变的“网站改版”魔咒,从豆瓣改版说起 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 269

6.4 JavaEye新版本上线以后性能还不错 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 271

6.5 关于JavaEye网站未来发展的思考 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 272

6.6 总结一下大家对JavaEye网站发展计划的建议 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 275

6.7 以无法为有法,以无限为有限 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 277

6.8 用全文检索来实现JavaEye的垂直频道 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 278

6.9 用Google的网站流量分析系统来看JavaEye网站 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 280

6.10 JavaEye生物多样性群落的思考 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 282

第 7 / 283 页
http://robbin.javaeye.com 1.1 点评Java full-stack框架

1.1 点评Java full-stack框架

发表时间: 2006-09-11 关键字: full-stack

2005年ruby on rails横空出世般的流行刺激了Java开源框架整合的大趋势,ruby on rails这个号称“full-stack”的框架能做的我们都能做,


它就是整合的更好,省略了配置文件,提供了快速代码生成器,暂且不论ruby on rails本身,但是诸多Java开发人员把目光从只做好一
件事情上面挪到了“提供最方便的full-stack框架”上面,因此我们可以看到整个Java开源社区雨后春笋般的出现了一批又一批的full-stack
框架,Java社区的开源软件哲学已经修改为:“要做最方便好用的full-stack框架”,那么就让我们来一一细数这些full-stack框架吧:

一、RIFE
最老牌的Java full-stack框架,作者Geert Bevin颇为不屑ruby on rails,和ruby on rails作者DHH有过对骂的战斗经验,8月份RIFE发布了
1.5版本,提供了更多更方便的功能和更加简化的开发。RIFE功能相当完善,在Continuations方面颇有独到之处,但是RIFE独辟蹊径,
整个解决方案不与现有任何流行开源框架相同,采用RIFE需要一些勇气。

二、Grails
最像ruby on rails的Java full-stack框架,Grails即Groovy on rails的意思,采用Java动态脚本语言groovy来写程序,底层实现采用
Hibernate/Spring/SpringMVC/JSTL,即groovy的脚本语言在运行期动态生成Hibernate/Spring的Java编译好的字节码。8月份Grails发布
了最新的0.2.1版本,在可用性的道路上又向前进了一步。

三、JBoss Seam
最正宗的Java full-stack框架。JBoss Seam整合了EJB3,Hibernate3,JSF,JBPM等框架,主持大局者是Hibernate作者Gavin King,
Seam提供了一个非常简化的完整框架。说Seam最正宗是因为Seam采用的EJB3,JSF等技术都是Java EE5规范的官方技术,可谓系出
名门。

四、Trails
最强调领域模型驱动的Java full-stack框架。Trails是Hibernate,Spring和Tapestry框架的整合版本,鉴于Tapestry是一个组件驱动的
Web框架。Trails非常强调以领域模型来驱动快速开发。这是一个值得Tapestry爱好者使用的Java full-stack框架。

五、Able
最不甘寂寞的Java full-stack框架。这是8月份刚刚发表的新框架,Able的作者是前Webwork,现Struts2.0的主开发人员Patrick
Lightbody。Pat同学也是一个对ruby on rails颇为不屑的人,曾经和RIFE作者Geert Bevin一唱一和的对战过DHH。Pat一边忙于开发
Struts2.0,一边不甘寂寞的推出了Able框架,这是一个整合了Webwork,Spring和iBATIS的框架,但是对Webwork进行了大幅度简化。

这些成型的full-stack框架,加上最经典的Java full-stack框架……Hibernate/Spring/Struts组合(或者Hibernate/Spring/Webwork组合),
一夜之间,Java开源世界的full-stack框架如千树万树梨花开,让我们这些Java开发人员挑花了眼,有人说,选择太多,即是Java开发人
员之福,也是Java开发人员之痛,如何挑选适合自己需要的框架,则成为Java开发人员必备的能力之一。

第 8 / 283 页
http://robbin.javaeye.com 1.2 回复ozzzzzz的“Java将死?”

1.2 回复ozzzzzz的“Java将死?”

发表时间: 2006-09-15

http://www.javaeye.com/topic/24436

我不想打断ozzzzzz接下去的发言,所以另外开一贴,应和一下ozzzzzz的帖子。

说Java将死,我觉得结论不能下的这么早。虽然外部的商业模式在迅速改变,但是Java本身也在迅速的改变,现在还不能下断言就说
Java一定会在新的商业模式崛起之后就被淘汰,也很有可能Java能够迅速适应新的商业模式,并且找到自己的新的定位和扮演的新角
色。

当前在Java领域有几个值得关注的发展方向:

1、SOA

SOA与其说是一种技术,不如说一个商业词汇。今年初参加BEA SHUG,BEA的consult讲SOA,他自己就很坦白的说,SOA不是讲给技
术人员的,是讲给CIO,企业高层听的,所以很多东西你们就不用听了。

2、full-stack的框架的泛滥

受到ruby on rails的刺激,Java在今年涌现了好多full-stack框架,关于full-stack框架的介绍,请看:
http://robbin.javaeye.com/blog/24162

full-stack的兴起可以在一定程度上满足现在快速开发和快速部署的问题,但是这并不是Java赌博未来的筹码。

3、JDK6.0,7.0引入javascript,ruby,groovy

我和ozzzzzz都认为Sun的管理层和技术层意见是有分歧的。Sun现在的CEO并不是Sun起家的创始人,对Java语言没有那么纯洁的怀旧
感情。因此Sun管理层现在一系列动作都在表明Sun在把Java更加平台化,以提供ruby,groovy,javascript等脚本语言支持。未来Java
会成为一个基础运行平台,上面可以跑各种脚本语言。

我个人认为这是Java在适应新的商业模式的一次漂亮的转身。

4、OSGi标准的普及

IBM在大力推广OSGi标准,而Eclipse正是OSGi标准的最佳案例。我们总是鼓吹组件化开发这么多年了,却从来没有接近过这个目标,
但是OSGi标准有望实现这一理想。最近Spring框架也提供了OSGi的支持,也许不久的将来就会出现一些以OSGi为底层架构的组件化软
件产品涌现出来。

我个人认为这是一个非常值得关注的方向。

说完Java,再谈谈Python和ruby:

第 9 / 283 页
http://robbin.javaeye.com 1.2 回复ozzzzzz的“Java将死?”

JavaEye里面的charon非常了解python,我只算门外汉了,班门弄斧一下。

python和ruby之间,我比较看好ruby,原因是:

1) ruby的语法比python更加自然语言一些,为什么ruby整天嚷嚷DSL,python就没有人提DSL呢?

2) ruby和rails社区比较统一,发展方向明确,而python社区比较类似Java社区,五花八门,各自为政,社区力量一旦分散,会影响未来
的发展

3) rails已经占据了很强的先发优势了,这个优势目前看来起来相当牢固。

第 10 / 283 页
http://robbin.javaeye.com 1.3 选择Hibernate还是iBatis?

1.3 选择Hibernate还是iBatis?

发表时间: 2006-09-18 关键字: hibernate ibatis

选择Hibernate还是iBATIS都有它的道理:

Hibernate功能强大,数据库无关性好,O/R映射能力强,如果你对Hibernate相当精通,而且对Hibernate进行了适当的封装,那么你的
项目整个持久层代码会相当简单,需要写的代码很少,开发速度很快,非常爽。

Hibernate的缺点就是学习门槛不低,要精通门槛更高,而且怎么设计O/R映射,在性能和对象模型之间如何权衡取得平衡,以及怎样
用好Hibernate方面需要你的经验和能力都很强才行。

iBATIS入门简单,即学即用,提供了数据库查询的自动对象绑定功能,而且延续了很好的SQL使用经验,对于没有那么高的对象模型要
求的项目来说,相当完美。

iBATIS的缺点就是框架还是比较简陋,功能尚有缺失,虽然简化了数据绑定代码,但是整个底层数据库查询实际还是要自己写的,工
作量也比较大,而且不太容易适应快速数据库修改。

我的建议就是:

如果你的团队没有Hibernate高手,那么请用iBATIS,要把Hibernate用好,并不容易;否则你应该选择Hibernate,那样你的开发速度和
代码简洁性都相当棒!

BTW:

我觉得rails的ActiveRecord是平衡性做的最好的,避免了Hibernate的复杂性和学习HQL的成本,同时具备iBATIS即学即用的简单性。

第 11 / 283 页
http://robbin.javaeye.com 1.4 Spring2.0的新特性点评

1.4 Spring2.0的新特性点评

发表时间: 2006-10-03 关键字: spring

Spring2.0的发布恐怕算得上2006年Java社区的一件大事了。在Spring2.0发布附带的文档里面对2.0新特性做了概要的介绍,2.0的新
特性是自然是我们最关注的方面:

一、Spring的XML配置引入XML Schema语法简化配置

在Spring1.x系列中,bean的配置文件使用DTD,没有namespace的分隔。2.0的一个非常大的改进是引入了XML Schema的
namespace,因而可以将bean的配置文件做大幅度的简化。这些简化包括了对bean属性的各种简化,AOP配置的简化,事务配置的简
化,JNDI配置的简化等方面。当然,在简化配置的同时,新的XML Schema实际上引入了更多的XML语法,因此使用一个支持XML
Schema的XML Editor就显得非常必要了,例如Eclipse WTP就可以提供Schema的语法自动提示和校验功能。

Spring1.x的bean配置文件逐渐复杂烦琐化,是Spring历来被人所垢病的主要问题之一。在Spring2.0里面XML Schema语法的配置可以
在相当程度上降低配置文件的复杂程度和烦琐程度,可以视为Spring的重大改进之一。但是我们也必须看到XML Schema并没有从根源
上面解决XML配置复杂的问题,而只是减轻。

将所有的bean之间的依赖关系,组装关系统统使用XML来描述,本身就会导致XML阅读和修改一定的困难。并且用XML配置本身无法直
接进行单元测试来验证依赖关系。因此,当bean之间关系越复杂的时候,XML配置文件本身的维护也是一个负担。

我个人比较期待未来的Spring能够使用脚本语言来编写和组装bean之间的关系,这样组装脚本本身也是可测试的,而且脚本的描述能
力要远远好于XML配置文件,同时编写和维护起来也比XML轻松。

二、提供了request和session范围的bean

引入request scope和session scope的bean,我感觉是把双刃剑。对于普通的Java Web框架应用来说,和Servlet容器相关的操作应该


限制在Web层,对于业务层来说,不应该涉及request和session的scope,否则业务层代码无法脱离Servlet容器进行单元测试。对于使
用Webwork/Struts框架的用户来说,恐怕不太会使用该特性,另外根据我的理解,也许request/session scope的bean也是为了提供给
Spring MVC的Controller使用的。

除此之外,对于AJAX Web Service调用来说,这一特性反而是很有用处的。对于这种应用场景,JS通过AJAX调用,抛开Web层框架,直


接访问业务层bean,这个时候就需要提供request/session scope的bean了。

三、集成AspectJ,可以管理容器外对象,提供了领域模型的依赖注入

通常由Hibernate管理的持久化对象PO,并不是由Spring容器初始化的,往往是用户自己new出来,或者通过find,load方法创建的,其
结果就是Spring容器无法对这种容器外创建的对象进行bean依赖关系注入。

在Spring2.0中,可以使用AspectJ对领域模型进行静态织入,这样当该领域模型在容器外被创建的时候,会产生对容器的回调,进行依
赖关系的注入。

第 12 / 283 页
http://robbin.javaeye.com 1.4 Spring2.0的新特性点评

Spring2.0提供的这一特性,确保了Martin Folwer的Rich Domain Object的可行性,这一特性的提供恐怕会对未来很多Java系统的设计产


生相当深远的影响。

其实针对Rich Domain Object更进一步,如果将DAO功能作为Domain Object的抽象父类,那么持久化对象PO就会集PO,DAO,Service


对象于一身,整个业务层,持久层完全合并为一个对象,通过这种方式进行框架简化得到的结果就是,高度类似于ruby on rails的full-
stack的MVC框架。

四、JPA支持

这一点其实没有什么可点评的,提供JPA支持本来就是理所应当之事。

五、JDBC的NamedParameterJdbcTemplate

NamedParameterJdbcTemplate我认为意义非凡,为JDBC查询提供了带命名参数的占位符,而不止是JDBC自己的“?”,这样使用JDBC
的时候,也可以很容易的构造出来带占位符的动态条件查询,而不是参数值带入方式的拼接SQL字符串了。

六、Spring Web MVC功能的大幅度扩充

看的出来,在Spring2.0里面 Web MVC功能大幅度扩充,过去不提供的UI Taglib也终于提供了,配置文件也进行了必要的简化。虽然


Spring MVC从框架设计角度来说远远不如Webwork那么有创意,但是也是一步一个脚印的改进,再配合上各种外围框架例如Spring
Webflow等的支持,可以预见Spring MVC会成长为Webwork的劲敌。

七、支持动态语言ruby,groovy,beanshell

动态语言支持目前看来还比较简单,不够强大,但是表明了Spring的一个态度,其实我个人希望Spring能够加强这方面支持,甚至大胆
一点,提供用动态脚本语言编写的bean组装配置。

八、异步JMS支持,JMX支持,JCA支持的功能完善

Spring2.0自身提供了两类简单的JMS Containter,此外还提供了外部JMS Server的接口,另外JMX功能的支持,JCA功能的支持都在进


一步的完善过程中。

Spring2.0在这几个方面的功能支持不是那么引入注目,毕竟普通Java Web应用很少使用这些方面。但是Spring提供这些功能的完善支
持意义却很深远,因为这些功能都是J2EE规范所要求提供的功能,也是传统应用服务器厂商相对比Java开源框架的传统优势项目。一
旦Spring2.0对这些功能提供了完善的支持,那么将传统的Java企业应用完全迁移到Spring框架上面的技术障碍就一扫而空了。

因此Spring是一个野心很大的框架,从现在状况来看,Spring可以说是Java开源框架之集大成者,从未来来看,Spring将提供J2EE厂商
所能够提供的所有必要的功能,最终Spring将有可能取J2EE规范而代之,成为Java企业开发的事实平台和事实标准。

第 13 / 283 页
http://robbin.javaeye.com 1.4 Spring2.0的新特性点评

总体来说,Spring2.0将向未来的宏大目标又迈进了一大步。不过对于我等普通Java Web项目的开发需求来说,2.0的新特性也没有特
别需要的。

第 14 / 283 页
http://robbin.javaeye.com 1.5 静态类型语言的优势究竟是什么?

1.5 静态类型语言的优势究竟是什么?

发表时间: 2006-11-13 关键字: java ruby

在参与这个讨论的过程中,产生了一个新的话题,很想和大家探讨一下:

http://www.javaeye.com/topic/33890

引用

是像Java或者C#这样强类型的准静态语言在实现复杂的业务逻辑、开发大型商业系统、以及那些生命周期很长的应用中也有着非常
强的优势

这是一个存在于大家心里常识了。我承认我自己在潜意识里面也觉得静态强类型语言适合开发复杂,大型系统。而弱类型脚本语言不
适合开发太复杂,太大型的项目。但是在参与这个讨论过程中,我突然开始置疑这个观点,事实究竟是不是这样的呢?

先定义一下标准:

强类型语言(静态类型语言)是指需要进行变量/对象类型声明的语言,一般情况下需要编译执行。例如C/C++/Java/C#

弱类型语言(动态类型语言)是指不需要进行变量/对象类型声明的语言,一般情况下不需要编译(但也有编译型的)。例如PHP/ASP/
Ruby/Python/Perl/ABAP/SQL/JavaScript/Unix Shell等等。

引用

观点一:静态类型语言因为类型强制声明,所以IDE可以做到很好的代码感知能力,因为有IDE的撑腰,所以开发大型系统,复杂系
统比较有保障。

对于像Java来说,IDEA/Eclipse确实在代码感知能力上面已经非常强了,这无疑能够增加对大型系统复杂系统的掌控能力。但是除了
Java拥有这么强的IDE武器之外,似乎其他语言从来没有这么强的IDE。C#的Visual Studio在GUI开发方面和Wizard方面很强,但是代码
感知能力上和Eclipse差的不是一点半点。至于Visual C++根本就是一个编译器而已,羞于提及Visual这个字眼。更不要说那么多C/C++
开发人员都是操起vi吭哧吭哧写了几十万行代码呢。特别是像Linux Kernel这种几百万行代码,也就是用vi写出来的阿,够复杂,够大
型,够长生命周期的吧。

引用

观点二:静态语言相对比较封闭的特点,使得第三方开发包对代码的侵害性可以降到很低。动态语言在这点上表现的就比较差,我
想大家都有过从网上下载某个JS包,然后放到项目代码里发生冲突的经历

也就是说静态类型语言可以保障package的命名空间分割,从而避免命名冲突,代码的良好隔离性。但是这个观点也缺乏说服力。

第 15 / 283 页
http://robbin.javaeye.com 1.5 静态类型语言的优势究竟是什么?

静态类型语言中C,VB都缺乏良好的命名空间分割,容易产生冲突,但是并没有影响他们做出来的系统就不够大,不够复杂。

而Visual C++开发的DLL版本冲突也是臭名昭著的,似乎C++的命名空间没有给它带来很大的帮助。

而动态类型语言中Ruby/Python/Perl都有比较好的命名空间,特别是Python和Perl,例如CPAN上面的第三方库成吨成吨的,也从来没有
听说什么冲突的问题。

诚然像PHP,JavaScript这样缺乏命名空间的动态语言很容易出现问题,但是这似乎是因为他们缺乏OO机制导致的,而不是因为他们动
态类型导致的吧?

说到大型系统,复杂业务逻辑系统,Google公司很多东西都是用python开发的,这也证明了动态类型语言并非不能做大型的复杂的系
统。其实我个人认为:

动态类型语言,特别是高级动态类型语言,反而能够让人们不需要分心去考虑程序编程问题,而集中精力思考业务逻辑实现,即思考
过程即实现过程,用DSL描述问题的过程就是编程的过程,这方面像Unix Shell,ruby,SQL,甚至PHP都是相应领域当之无愧的DSL语
言。而显然静态类型语言基本都不满足这个要求。

那静态类型语言的优势究竟是什么呢?我认为就是执行效率非常高。所以但凡需要关注执行性能的地方就得用静态类型语言。其他方
面似乎没有什么特别的优势。

第 16 / 283 页
http://robbin.javaeye.com 1.6 应该如何正确使用Quartz

1.6 应该如何正确使用Quartz

发表时间: 2006-12-27 关键字: quartz job

对于Web容器来说,最忌讳应用程序私自启动线程,自行进行线程调度,像Quartz这种在web容器内部默认就自己启动了10个线程进行
异步job调度的框架本身就是很危险的事情,很容易造成servlet线程资源回收不掉,所以我一向排斥使用quartz。

quartz还有一个问题就是不支持cluster。导致使用quartz的应用都没有办法做群集。

那么应该如何正确的使用quartz的同时,又不影响web容器自身的线程调度呢?

办法就是自己单独启动一个Job Server,来quartz跑job,不要部署在web容器中。

其他web节点当需要启动异步任务的时候,可以通过种种方式(DB, JMS, Web Service, etc)通知Job Server,而Job Server收到这个通知


之后,把异步任务加载到自己的任务队列中去。

其实想改造当前已经集成quartz的web应用也不算困难:

例如可以使用数据库的表来记录和维护任务队列和状态,把quartz部分完全从web应用中剥离出去,自己写一个Java Main程序把配置
quartz的spring容器跑起来,这样Job Server就启动了(注意这个Job Server完全脱离tomcat)。此外这个Main程序应该再启动一个子线
程,定期扫描数据库的任务队列表:
有新的任务就加入quartz的任务调度;
把当前任务的执行状态写入任务表;
看到删除任务的表字段状态以后,删除相应的任务。

然后web应用去掉quartz部分配置,把原来的调用quartz任务的代码改写为读写数据库的任务表,这样就把job部分完全从web容器剥离
掉了,甚至web容器做cluster也没有问题了,并且多个web节点在同时读写任务表的时候,还有数据库的事务来确保操作的一致性,实
在是很棒。

另外还可以单独做一个job管理界面,可以通过web界面手工添加任务,查看任务状态,删除任务等等。

第 17 / 283 页
http://robbin.javaeye.com 1.7 Java程序员的推荐阅读书籍

1.7 Java程序员的推荐阅读书籍

发表时间: 2007-02-07 关键字: 读书

《Java程序员的推荐阅读书籍》

JavaEye (http://www.javaeye.com)

范凯(http://robbin.javaeye.com)

作为Java程序员来说,最痛苦的事情莫过于可以选择的范围太广,可以读的书太多,往往容易无所适从。我想就我自己读过的技术书
籍中挑选出来一些,按照学习的先后顺序,推荐给大家,特别是那些想不断提高自己技术水平的Java程序员们。

一、Java编程入门类
对于没有Java编程经验的程序员要入门,随便读什么入门书籍都一样,这个阶段需要你快速的掌握Java基础语法和基本用法,宗旨就
是“囫囵吞枣不求甚解”,先对Java熟悉起来再说。用很短的时间快速过一遍Java语法,连懵带猜多写写代码,要“知其然”。

1、《Java编程思想》

在有了一定的Java编程经验之后,你需要“知其所以然”了。这个时候《Java编程思想》是一本让你知其所以然的好书,它对于基本的面
向对象知识有比较清楚的交待,对Java基本语法,基本类库有比较清楚的讲解,可以帮你打一个良好的Java编程基础。这本书的缺点
是实在太厚,也比较罗嗦,不适合现代人快节奏学习,因此看这本书要懂得取舍,不是每章每节都值得一看的,挑重点的深入看就可
以了。

2、《Agile Java》中文版

这本书是出版社送给我的,我一拿到就束之高阁,放在书柜一页都没有翻过,但是前两天整理书柜的时候,拿出来一翻,竟然发现这
绝对是一本好书!这本书一大特点是以单元测试和TDD来贯穿全书的,在教你Java各种重要的基础知识的过程中,潜移默化的影响你的
编程思维走向敏捷,走向TDD。另外这本书成书很新,以JDK5.0的语法为基础讲解,要学习JDK5.0的新语法也不错。还有这本书对于
内容取舍也非常得当,Java语言毕竟类库庞大,可以讲的内容太多,这本书选择的内容以及内容的多寡都很得当,可以让你以最少的
时间掌握Java最重要的知识,顺便培养出来优秀的编程思路,真是一本不可多得的好书。

虽然作者自己把这本书定位在入门级别,但我不确定这本书用来入门是不是稍微深了点,我自己也准备有空的时候翻翻这本书,学习
学习。

二、Java编程进阶类
打下一个良好的Java基础,还需要更多的实践经验积累,我想没有什么捷径。有两本书值得你在编程生涯的这个阶段阅读,培养良好
的编程习惯,提高你的代码质量。

1、《重构 改善既有代码的设计》

第 18 / 283 页
http://robbin.javaeye.com 1.7 Java程序员的推荐阅读书籍

这本书名气很大,不用多介绍,可以在闲暇的时候多翻翻,多和自己的实践相互印证。这本书对你产生影响是潜移默化的。

2、《测试驱动开发 by Example》

本书最大特点是很薄,看起来没有什么负担。你可以找一个周末的下午,一边看,一边照做,一个下午就把书看完,这本书的所有例
子跑完了。这本书的作用是通过实战让你培养TDD的思路。

三、Java架构师之路
到这个阶段,你应该已经非常娴熟的运用Java编程,而且有了一个良好的编程思路和习惯了,但是你可能还缺乏对应用软件整体架构
的把握,现在就是你迈向架构师的第一步。

1、《Expert One-on-One J2EE Design and Development》

这本书是Rod Johnson的成名著作,非常经典,从这本书中的代码诞生了springframework。但是好像这本书没有中译本。

2、《Expert One-on-One J2EE Development without EJB》

这本书由gigix组织翻译,多位业界专家参与,虽然署名译者是JavaEye,其实JavaEye出力不多,实在是忝居译者之名。

以上两本书都是Rod Johnson的经典名著,Java架构师的必读书籍。在我所推荐的这些书籍当中,是我看过的最仔细,最认真的书,我
当时读这本书几乎是废寝忘食的一气读完的,有小时候挑灯夜读金庸武侠小说的劲头,书中所讲内容和自己的经验知识一一印证,又
被无比精辟的总结出来,读完这本书以后,我有种被打通经脉,功力爆增的感觉。

但是后来我看过一些其他人的评价,似乎阅读体验并没有我那么high,也许是因为每个人的知识积累和经验不同导致的。我那个时候
刚好是经验知识积累已经足够丰富,但是还没有系统的整理成型,让这本书一梳理,立刻形成完整的知识体系了。

3、《企业应用架构模式》

Martin的又一本名著,但这本书我只是泛泛的看了一遍,并没有仔细看。这本书似乎更适合做框架的人去看,例如如果你打算自己写
一个ORM的话,这本书是一定要看的。但是做应用的人,不看貌似也无所谓,但是如果有空,我还是推荐认真看看,会让你知道框架
为什么要这样设计,这样你的层次可以晋升到框架设计者的角度去思考问题。Martin的书我向来都是推崇,但是从来都没有像Rod
Johnson的书那样非常认真去看。

4、《敏捷软件开发 原则、模式与实践》

Uncle Bob的名著,敏捷的经典名著,这本书比较特别,与其说是讲软件开发过程的书,不如说讲软件架构的书,本书用了很大篇幅讲
各种面向对象软件开发的各种模式,个人以为看了这本书,就不必看GoF的《设计模式》了。

四、软件开发过程

第 19 / 283 页
http://robbin.javaeye.com 1.7 Java程序员的推荐阅读书籍

了解软件开发过程不单纯是提高程序员个人的良好编程习惯,也是增强团队协作的基础。

1、《UML精粹》

UML其实和软件开发过程没有什么必然联系,却是软件团队协作沟通,撰写软件文档需要的工具。但是UML真正实用的图不多,看看
这本书已经足够了,完全没有必要去啃《UML用户指南》之类的东西。要提醒大家的是,这本书的中译本翻译的非常之烂,建议有条
件的看英文原版。

2、《解析极限编程 拥抱变化》XP

这是Kent Beck名著的第二版,中英文对照。没什么好说的,必读书籍。

3、《统一软件开发过程》UP

其实UP和敏捷并不一定冲突,UP也非常强调迭代,测试,但是UP强调的文档和过程驱动却是敏捷所不取的。不管怎么说,UP值得你
去读,毕竟在中国真正接受敏捷的企业很少,你还是需要用UP来武装一下自己的,哪怕是披着UP的XP。

4、《敏捷建模》AM

Scott Ambler的名著,这本书非常的progmatic,告诉你怎么既敏捷又UP,把敏捷和UP统一起来了,又提出了很多progmatic的建议和做
法。你可以把《解析极限编程 拥抱变化》、《统一软件开发过程》和《敏捷建模》这三本书放在一起读,看XP和UP的不同点,再看
AM是怎么统一XP和UP的,把这三种理论融为一炉,形成自己的理论体系,那么你也可以去写书了。

五、软件项目管理
如果你突然被领导提拔为项目经理,而你完全没有项目管理经验,你肯定会心里没底;如果你觉得自己管理项目不善,很想改善你的
项目管理能力,那么去考PMP肯定是远水不解近渴的。

1、《快速软件开发》

这也是一本名著。可以这样说,有本书在手,你就有了一个项目管理的高级参谋给你出谋划策,再也不必担心自己不能胜任的问题
了。这本书不是讲管理的理论的,在实际的项目管理中,讲这些理论是不解决问题的,这本书有点类似于“软件项目点子大全”之类的东
西,列举了种种软件项目当中面临的各种问题,以及应该如何解决问题的点子,你只需要稍加变通,找方抓药就行了。

六、总结
在这份推荐阅读书籍的名单中,我没有列举流行的软件框架类学习书籍,例如Struts,Hibernate,Spring之类,也没有列举AJAX方面的
书籍。是因为这类书籍容易过时,而上述的大半书籍的生命周期都足够长,值得你去购买和收藏。

第 20 / 283 页
http://robbin.javaeye.com 1.8 Spring2.0和EJB3.0随谈

1.8 Spring2.0和EJB3.0随谈

发表时间: 2007-02-08

Spring自从2003年发布以来,一直是Java开源框架的奇迹之一。从2000年开始,伴随着B/S架构逐渐引入企业应用软件开发的领域,
Java就逐渐成为企业应用开发的主流技术,一直到2003年,Struts+EJB一直是Java技术架构的不二选择,然而这一切随着2003年
Spring以without EJB的面目出现之后,一切都开始改变。

大概从2003年下半年开始,Spring+Hibernate就开始甚嚣尘上,似乎那时候的Spring和Hibernate尚且不足以动摇J2EE规范以EJB为核
心的领袖地位。但是2004年5月份,吸收了Spring/Hibernate框架优点的EJB3 JCP委员会的成立,事实上宣判了Spring对EJB2的终结,
EJB3则更像是Vendor们的一种自救行为。

2004年到2006这三年时间以来,Spring取得了相当辉煌的成就,不但将EJB2赶进历史,而且牢牢确立了Spring作为Java企业应用开发
的主流地位。而今,甚至对技术比较保守的金融电信行业,也开始言必称Spring,Spring已经成为Java框架的事实标准。

在2004年5月份之后,Hibernate Team开始和Spring公然决裂,这个事情放在两年多以后的今天来看,原因是昭然若揭的,背靠JBoss
的Hibernate Team已经成为EJB3规范的一部分,而JBoss希望力推的以EJB3为核心的Java架构来成为未来的企业应用主流标准,这种
情况演变至今,变成了Springframework和JBoss Seam的两种不同技术架构的竞争关系。

2004年5月份,EJB3规范的起步,对Spring未来其实有很大的威胁,但是EJB3规范历经两年时间的难产,终于在2006年5月正式发布
之时,已经为时过晚了,抬眼望去,已尽是spring的天下。

有意思的是,大致展望一下未来,Java的企业应用开发还能遵循Sun和JCP制订的Java EE规范的道路走下去吗?如果不是这样,那么未
来道路是什么呢?

观察一下Java社区几股大的势力,会发现一些有意思的现象:

IBM和BEA是Java社区的领导者,从2004年开始,IBM和BEA开始大肆宣传SOA,将他们的目光从应用服务器领域挪到了松藕合企业服
务领域,开展SOA商业战略。与此同时,EJB3专家委员会的领导者也悄然变成了JBoss和Oracle,是IBM和BEA无力争取吗?当然不
是。IBM和BEA已经看到了应用服务器市场和底层框架平台即将被开源占领,商业价值萎缩,因而审时度势进行战略转型。一方面押宝
SOA战略,大肆炒热和培育SOA市场,另一方面也积极占领开源市场,IBM放出来WebSphere社区版本-Apache Geronimo,BEA干脆
和Spring的咨询公司interface21合作,提供spring框架在WebLogic上的商业技术支持,如今EJB3对于他们来说已经形同鸡肋,就抛给
别人嚼吧。

将EJB3当块宝的自然是应用服务器市场的跟随者JBoss和Oracle,一方面凭借ORM的先天优势,另一方面有出头机会也不能放过,
EJB3委员会几乎成了JBoss和Oracle的天下。特别是JBoss,更加积极推出JBoss Seam框架,希望确立以JSF+EJB3的架构树立Java开
发的标准,用以取代Struts/Spring/Hibernate的流行组合,因而开启了EJB3和Spring 正面交锋的战争。

Java Vendor中另外一股势力Sun公司这两年则一直自顾不暇,在应用服务器领域几乎退出市场,直到最近才搞出来一个Glassfish,在
开发框架领域也一直毫无建树,推出的JSF至今还很不成熟,难担大任,也许Sun都去忙着开源Solaris和JVM源代码了。

几个大的Vendor或战略转型,或自顾不暇,或忙于收购(Oracle),Java开发领域的主战场被打扫一空,对决的双方换成了Spring和
JBoss。对决的武器则是spring vs Seam。

第 21 / 283 页
http://robbin.javaeye.com 1.8 Spring2.0和EJB3.0随谈

Spring代表了不遵循通用标准,自己制订游戏规则,不依赖容器的一方;JBoss代表了遵循通用标准,但是锁定容器的一方。这场对决
从2004年5月就开始上演,未来很长时间也会继续下去。不过Spring已经站在优势很大的地位上了。

大致对比一下两者:Spring vs EJB3,就会发现Spring从功能上面已经胜出很多了:

1、IoC容器spring胜出

Spring的IoC容器很强大,其bean管理功能超过了目前EJB3容器,配置方面Spring稍微复杂一些。不过对于全局性配置来说,XML要优
于EJB3的annotation。

2、AOP能力Spring胜出

EJB3目前提供的AOP功能非常简单,本来已经无法和Spring相比,至于集成AspectJ的Spring2.0,就更加望尘莫及了。

3、事务管理方面EJB3稍微领先

Spring提供了很棒的本地事务模型,也可以集成JTA,但是不支持分布式事务,当然这种场景也非常罕见。

4、Web框架spring胜出

EJB3标准集成JSF,但是JSF并不成熟,和AJAX配合度也不好。Spring可以灵活集成各种Web框架和模板语言,自身也提供了相当强大
的MVC框架,要是这还觉得不够,那么spring webflow,portlet support都拿出来。

5、远程访问支持,大致持平

EJB3继承了传统的EJB远程访问能力,Web Services支持也不错;不过Spring提供了更多更灵活的选择,Java RPC,HTTP Invoker,


Hessian/Burlap,WebServices。

6、框架集成能力,spring胜出

这是spring的传统优势项目,只要看看spring modules项目,看看n多第三方spring支持,就会发现spring现在的群众基础多么好,集成
工作流,spring modules已经提供了方便的模板类,集成规则引擎,Cache,CMS,脚本语言,异步任务,安全验证框架。。。。。。
EJB3有点望尘莫及的味道

7、JMS,JMX,JCA等,EJB3领先一步

这些传统EJB优势项目往往应用的不太多,EJB3仍然是领先的。不过令人侧目的是,Spring最近几个版本在连续追赶EJB这些传统优势
领域,到Spring2.0为止,其JMS,JMX,JCA支持已经相当不错了,可以说传统EJB能够做的,现在Spring也可以做得到。

这几年除了Spring框架自身不断完善和延伸到传统应用领域,围绕在Spring周围的第三方框架也是越来越丰富,EJB3在annotation方面
有些独到的优势,在一些传统领域,还领先spring,但是总体来说,EJB3为核心的J2EE5.0规范很难和Spring现在的2.0相匹敌,更何况
Java的主力Vendor早已醉翁之意不在这里了,单凭JBoss的Seam,难以战胜spring。

目前JBoss已经开始在国内进行商业上的推广,也希望以其EJB3技术来和Springframework相抗衡,JBoss目前用来说服客户使用EJB3

第 22 / 283 页
http://robbin.javaeye.com 1.8 Spring2.0和EJB3.0随谈

的理由主要有两点:

1、EJB3是一个标准,由多个厂商提供实现
2、JBoss的EJB3由Red Hat公司及其合作伙伴提供技术支持,而springfrmework在国内还没有商业技术支持

第 23 / 283 页
http://robbin.javaeye.com 1.9 Google Guice - 比Spring快100倍的IoC容器

1.9 Google Guice - 比Spring快100倍的IoC容器

发表时间: 2007-02-27 关键字: ioc

http://code.google.com/p/google-guice/

Google公司的Bob lee开发的轻量级IoC容器,其特点是:

1、速度快,号称是spring的100倍速度
2、无配置文件,实用JDK5.0的annotation描述组件依赖,简单,而且有编译器检查和重构支持
3、简单,代码量很少

http://code.google.com/p/google-guice/wiki/SpringComparison

这是Google guice和spring IoC容器的对比

另外xwork2.0已经集成了Google guice容器了。

http://docs.google.com/Doc?id=dd2fhx4z_5df5hw8

这是Google guice的快速入门文档,用起来挺简单的。

第 24 / 283 页
http://robbin.javaeye.com 1.10 可以开始用Struts2.0了

1.10 可以开始用Struts2.0了

发表时间: 2007-02-27 关键字: struts

http://struts.apache.org/

Apache已经发布了Struts2.0的正式版,即2.0.6GA版本。这个版本已经可以在项目中正式使用了。当然大家一定很关心,从
webwork2.2迁移到struts2.0麻烦不麻烦,请看Struts2.0的FAQ:

引用

Essentially, Struts 2.0 is the technical equivalent of WebWork 2.3. Aside from the package and property renaming, it isn't much
different than, say, migrating from WebWork 2.1 to 2.2.

Struts2.0其实就是webwork2.3而已,从webwork2.2迁移到struts2.0不会比从webwork2.1到2.2更麻烦。

webwork2.2和struts2.0差异对比:
http://struts.apache.org/2.x/docs/key-changes-from-webwork-2.html

迁移步骤:
http://struts.apache.org/2.x/docs/webwork-2-migration-strategies.html

总结:

大致来说,struts2.0就是把package和配置文件的名字改了改而已,别的没有做什么改动,所以现在用struts2.0和用webwork2.2没有
多大区别。当然这迁移一迁就是将近两年,还是有点进步的:

1、搭配struts2.0的xwork版本必须使用xwork2.0.1,而xwork2.0.1集成了可选的Google Guice IoC容器


2、Struts2.0弄了一个plugin机制,来适配各种扩展机制
3、全面引入annotation语法,验证,拦截都可以用annotation了。

所以用webwork的同志们,大胆的迁移到struts2.0来吧。

第 25 / 283 页
http://robbin.javaeye.com 1.11 domain model的延伸讨论

1.11 domain model的延伸讨论

发表时间: 2007-03-03 关键字: domain model

domain model,又称为领域模型,是Java企业应用讨论的一个热门话题,JavaEye也曾经多次围绕这个话题讨论,我们来看个简单的例
子:

引用

一个简单的公司工时管理系统,记录员工的个人信息,每个员工的工作任务分配,以及工作所属类别(例如开发,还是测试,还是培
训等等),其中每个员工有n个任务,员工和任务是一对多关系,每个员工也分别隶属于多个不同的工作类别,员工和类型是多对多
关联关系,而每个任务也分别隶属于唯一的工作类别,任务和类别是多对一关系。另外系统不要求对部门信息进行维护,不需要
department表。因此,在这个系统中使用四张数据库表:

users表保存员工信息,有name, password, gender, department, salary


tasks表保存工作任务信息,有name,start_time, end_time
kinds表保存工作所属类别,有name
kinds_users表是一张关联表,保存users表和kinds表的多对多关联外键的

系统的功能需求如下:
1、某部门录用一名新员工
2、某部门员工总薪水总和
3、某员工已经开始但尚未结束的任务
4、给某员工分配一项任务
5、所有用户当前已经开始但尚未结束的任务
6、对某一类别,给所有和此一类别相关的员工,批量新增一批任务
7、针对任务的统计功能,给定某类别,统计当月总的任务数,已完成任务数,未完成任务数

我们先看看用ruby如何实现系统的领域模型:

class User < ActiveRecord::Base


has_and_belongs_to_many :kinds

has_many :tasks, :dependent => :destroy do


def processing_tasks
find :all, :conditions => ["start_time <= ? AND end_time is null", Time.now]
end
end

def apply_task(task_name)
self.tasks << Task.new(:name => task_name, :start_time => Date.today)

第 26 / 283 页
http://robbin.javaeye.com 1.11 domain model的延伸讨论

end

def self.all_processing_tasks
Task.find :all, :conditions => ["start_time <= ? AND end_time is null AND user_id is not null",Time.now]
end
end

class Task < ActiveRecord::Base


belongs_to : owner, :class_name => 'User', :foreign_key => 'user_id'
belongs_to :kind

def self.current_month_tasks(kind)
kind.tasks.current_month_tasks
end
end

class Kind < ActiveRecord::Base


has_and_belongs_to_many :users

has_many :tasks do
def current_month_tasks
month_begin = Date.today - Date.today.mday + 1
month_end = Date.today - Date.today.mday + 30
processing_tasks = find :all, :conditions => ["start_time <= ? AND end_time is null ", month_begin]
processed_tasks = find :all, :conditions => ["end_time >= ? AND end_time <= ? ", month_begin, month_end]
all_tasks = processing_tasks.clone
all_tasks << processed_tasks unless processed_tasks.size == 0
return all_tasks, processed_tasks, processing_tasks
end
end

def add_batch_task_to_users(task_name)
self.users.each do |user|
task = Task.new(:name => task_name, :start_time => Date.today)
user.tasks << task
self.tasks << task
end
end
end

class Department
def self.employee(username, department)

第 27 / 283 页
http://robbin.javaeye.com 1.11 domain model的延伸讨论

User.create(:name => username, :department => department)


end

def self.total_salary(department)
User.sum :salary, :conditions => ["department = ?", department]
end
end

1、某部门录用一名新员工

Department.employee("robbin","开发部")

2、某部门员工总薪水总和

Department.total_salary("开发部")

3、某员工已经开始但尚未结束的任务

user.tasks.processing_tasks

4、给某员工分配一项任务

user.apply_task("学习Java")

5、所有用户当前已经开始但尚未结束的任务

User.all_processing_tasks

6、对某一类别,给所有和此一类别相关的员工,批量新增一批任务

kind.add_batch_task_to_users("学习单元测试")

7、针对任务的统计功能,给定某类别,统计当月总的任务数,已完成任务数,未完成任务数

Task.current_month_tasks(kind)

第 28 / 283 页
http://robbin.javaeye.com 1.11 domain model的延伸讨论

这里值得注意的是,RoR可以很方便的采用充血的领域模型,所有的业务逻辑都可以放在相关的domain model里面。这里的user,
task和kind都是对应于数据库表的领域模型,而department是不对应数据库的纯业务逻辑的domain model。总共4个ruby文件,4个
domain model,55行代码,所有要写的代码都在这里了,代码量确实非常少,每个domain model的颗粒度都比较大。

然后我们再看看如何用Java:

public class User {


private Long id;
private String name;
private String password;
private String gender;
private String department;
private int salary = 0;
private List<Task> tasks = new ArrayList<Task>();
# omit getter/setter methods ......
}

# omit User's ORM Mapping file

public class Task {


private Long id;
private String name;
private int duration = 0;
private User owner;
# omit getter/setter methods ......
}

# omit Task's ORM Mapping file

public class Kind {


......
}

# omit Kind's ORM Mapping file

public interface UserDao {


public void addUser(User user);
public loadUserById(Long id);
# omit CRUD and other persistent methods ......
public List<User> findByDeparment(String department);
}

第 29 / 283 页
http://robbin.javaeye.com 1.11 domain model的延伸讨论

public interface TaskDao {


# omit CRUD and other persistent methods ......
}

public class UserDaoImpl {


# omit implementations ......
}

public class TaskDaoImpl {


# omit implementations ......
}

public class UserService {


private UserDao userDao;
public setUserDao(UserDao userDao) { this.userDao = userDao; }
public int workload(User user) {
int totalDuration = 0;
for (Task task : user.getTasks()) {
totalDuration += task.duration;
}
return totalDuration;
}
public employee(String username, String department) {
User user = new User();
user.setName(username);
user.setDepartment(department);
userDao.addUser(user);
}
}

public class TaskService {


private TaskDao taskDao;
public void setTaskDao(TaskDao taskDao) { this.taskDao = taskDao }
public applyTask(String taskName, User user) {
Task task = new Task();
task.setName(taskName);
task.setUser(user);
taskDao.addTask(task);
}
}

第 30 / 283 页
http://robbin.javaeye.com 1.11 domain model的延伸讨论

public class DepartmentService {


private UserDao userDao;
public void setUserDao(UserDao userDao) { this.userDao = userDao; }
private UserService userService;
public void setUserService(UserService userService) { this.userService = userService; }
public int totalSalary(String department) {
......
}
......
}

# omit IoC Container weaving configuration's file

Java版本的实现代码大家都比较熟悉,因此绝大部分代码都省略了。Java版本需要3个持久对象,3个映射XML文件,3个DAO接口和实
现类,4个Service和实现类,和一个IoC的bean组装文件,总共21个文件,全部逻辑写完整,代码行数至少上千行。

通过对比,我们可以看到Java比较流行的实现是贫血的模型,按照面向对象的基本原则,对象的状态应该和它的行为封装在一起,因
此Java多出来的这些XXXService是一些从纯理论角度而言应该放入其相应的持久对象中去。但是Java实现充血模型从技术上有一定的难
度,如何Service方法挪入到持久对象中呢?如何解决Dao的注入问题?如何解决domain logic方法的事务封装问题?前者可以通过
AspectJ的静态织入来解决,后者也许可以通过织入或者annotation声明来解决。但不管怎么说,Java从技术上很难实现充血模型,而
且即使实现充血模型,也会导致一个Java类好几百行代码的状况,其代码的可阅读性,模块解藕能力都会变得很差,因此我们认为
Java不适合充血模型,在表达复杂的业务逻辑的能力上,Java要比ruby差很多:

结论:
对于Java来说,更加适合采用贫血的模型,Java比较适合于把一个复杂的业务逻辑分离到n个小对象中去,每个小对象描述单一的职
责,n个对象互相协作来表达一个复杂的业务逻辑,这n个对象之间的依赖和协作需要通过外部的容器例如IoC来显式的管理。但对于每
个具体的对象来说,他们毫无疑问是贫血的。

这种贫血的模型好处是:
1、每个贫血对象职责单一,所以模块解藕程度很高,有利于错误的隔离。
2、非常重要的是,这种模型非常适合于软件外包和大规模软件团队的协作。每个编程个体只需要负责单一职责的小对象模块编写,不
会互相影响。

贫血模型的坏处是:
1、由于对象状态和行为分离,所以一个完整的业务逻辑的描述不能够在一个类当中完成,而是一组互相协作的类共同完成的。因此可
复用的颗粒度比较小,代码量膨胀的很厉害,最重要的是业务逻辑的描述能力比较差,一个稍微复杂的业务逻辑,就需要太多类和太
多代码去表达(针对我们假定的这个简单的工时管理系统的业务逻辑实现,ruby使用了50行代码,但Java至少要上千行代码)。
2、对象协作依赖于外部容器的组装,因此裸写代码是不可能的了,必须借助于外部的IoC容器。

第 31 / 283 页
http://robbin.javaeye.com 1.11 domain model的延伸讨论

对于Ruby来说,更加适合充血模型。因为ruby语言的表达能力非常强大,现在用ruby做企业应用的DSL是一个很热门的领域,DSL说白
了就是用来描述某个行业业务逻辑的专用语言。

充血模型的好处是:
1、对象自洽程度很高,表达能力很强,因此非常适合于复杂的企业业务逻辑的实现,以及可复用程度比较高。
2、不必依赖外部容器的组装,所以RoR没有IoC的概念。

充血模型的坏处是:
1、对象高度自洽的结果是不利于大规模团队分工协作。一个编程个体至少要完成一个完整业务逻辑的功能。对于单个完整业务逻辑,
无法再细分下去了。
2、随着业务逻辑的变动,领域模型可能会处于比较频繁的变动状态中,领域模型不够稳定也会带来web层代码频繁变动。

附件是完整的RoR版本的项目示例代码。要运行它,需要安装MySQL数据库(InnoDB表类型),Ruby和Ruby on rails环境。在MySQL数据
库中分别创建demo数据库和demo_test数据库,修改demo\config\database.yml中的MySQL数据库配置,改成你的数据库密码。然后
在项目跟目录下面执行:
rake db:migrate
rake db:test:clone_structure
rake test
即创建开发环境数据库,创建测试环境数据库,和执行所有的单元测试。领域模型代码位于demo\app\models目录下面;单元测试代
码位于demo\test\units目录下面
附件下载:
• demo.zip (80.6 KB)
• http://robbin.javaeye.com/topics/download/12bf5342-03c0-449b-8ae5-1bbfaefed70c
• 描述: 完整的RoR版本的项目示例代码

第 32 / 283 页
http://robbin.javaeye.com 1.12 缓存简述

1.12 缓存简述

发表时间: 2007-03-30 关键字: cache

缓存实现的层面有很多:

1、对象缓存
由ORM框架提供,透明性访问,细颗粒度缓存数据库查询结果,无需业务代码显式编程。当软件结构按照ORM框架的要求进行针对性
设计,使用对象缓存将会极大降低web系统对于数据库的访问请求。因为类似Hibernate这样的ORM,良好的设计数据库结构和利用对
象缓存,在大负载网站,能够提供极高的性能。因为使用对象缓存也无需显式编程,所以适用范围也最广泛。

2、查询缓存
对数据库查询结果行集进行缓存,适用于一些耗时,但是时效性要求比较低的场景。iBATIS就只能使用查询缓存,而无对象缓存。查
询缓存和对象缓存适用的场景不一样,是互为补充的。

3、片断缓存
针对动态页面的局部片断内容进行缓存,适用于一些个性化但不经常更新的页面(例如博客)。OSCache提供了相当简陋的片断缓存,而
RoR则提供了相当好的片断缓存机制。

4、Action缓存
针对URL访问返回的页面结果进行缓存,适用于粗粒度的页面缓存,例如新闻发布。OScache提供了相当简陋的Action缓存(通过
web.xml中的配置),而RoR提供了相当好的Action缓存。

缓存不能一概而论,以上每种缓存分别适用于各自的场景,缓存不同的层面。当然你可以在应用程序当中把4种缓存一起用上。

第 33 / 283 页
http://robbin.javaeye.com 1.13 为什么ORM性能比iBATIS好?

1.13 为什么ORM性能比iBATIS好?

发表时间: 2007-05-06

缓存是有很多层次的,有web server前端缓存,有动态页面静态化,有页面片断缓存,有查询缓存,也有对象缓存。不同层面的缓存适
用于不同的应用场景,作用也各自不同,如果可以,你全部一起用上,他们不矛盾,但这个话题比较大,现在不展开谈。

针对OLTP类型的web应用,只要代码写的质量没有问题,最终的性能瓶颈毫无疑问还是数据库查询。应用服务器层面可以水平扩展,
但是数据库是单点的,很难水平扩展,所以如何有效降低数据库查询频率,减轻数据库压力,是web应用性能问题的根源。

以上所有的缓存方式都可以直接或者间接的降低数据库访问,但缓存是有应用场景的,虽然新闻网站非常适合使用动态页面静态化技
术,但是例如电子商务网站就不适合动态页面静态化,而页面缓存和查询缓存可以使用的场景也不多。但是对象缓存是所有缓存技术
当中适用场景最广泛的,任何OLTP应用,即使实时性要求很高,你也可以使用对象缓存,而且好的ORM实现,对象缓存是完全透明
的,不需要你的程序代码进行硬编码。

用不用对象缓存,怎么用对象缓存,不是一个调优的技巧问题,而是整个应用的架构问题。在你开发一个应用之前,你就要想清楚,
这个应用最终的场景是什么?会有多大的用户量和数据量。你将采用什么方式来架构这个应用:

OK,也许你偏爱SQL,那么你选择iBATIS,数据库设计当中大表有很多冗余字段,会尽量消除大表之间的关联关系,最终用户量和访
问量很高以后,你会选择使用Oracle,雇佣资深的DBA,进行数据库调优和SQL调优,这是大多数公司走的路。

但是我告诉你,你还有另外一条路可以走。你可以选择ORM(不见得一定是Hibernate),数据库设计当中避免出现大表,比较多的表关
联关系,通过ORM以对象化方式操作。当用户量和访问量很高以后,除了数据库端本身的优化,你还有对象缓存这条途径。对象缓存
是怎样提高性能的呢?随便举个例子:

论坛的列表页面,需要显示topic的分页列表,topic作者的名字,topic最后回复帖子的作者,如果是iBATIS,你准备怎么做?

select ... from topic left join user left join post .....

你需要通过join user表来取得topic作者的名字,然后你还需要join post表取得最后回复的帖子,post再join user表取得最后回贴作者名


字。

也许你说,我可以设计表冗余,在topic里面增加username,在post里面增加username,所以通过大表冗余字段,消除了复杂的表关
联:

select ... from topic left join post...

第 34 / 283 页
http://robbin.javaeye.com 1.13 为什么ORM性能比iBATIS好?

OK,且不说冗余字段的维护问题,现在仍然是两张大表的关联查询。然后让我们看看ORM怎么做?

select * from topic where ... --分页条件

就这么一条SQL搞定,比上面的关联查询对数据库的压力小多了。

也许你说,不对阿,作者信息呢?回贴作者信息呢?这些难道不会发送SQL吗?如果发送SQL,这不就是臭名昭著的n+1条问题吗?

你说的对,最坏情况下,会有很多条SQL:

select * from user where id = topic_id...;


....
select * from user where id = topic_id...;

select * from post where id = last_topic_id...;


....
select * from post where id = last_topic_id...;

select * from user where id = post_id...;


....
select * from user where id = post_id...;

事实上何止n+1,根本就是3n+1条SQL了。那你怎么还说ORM性能高呢?

因为对象缓存在起作用,你可以观察到后面的3n条SQL语句全部都是基于主键的单表查询,这3n条语句在理想状况下(比较繁忙的web
网站),全部都可以命中缓存。所以事实上只有一条SQL,就是:

select * from topic where ...--分页条件

这条单表的条件查询和iBATIS通过字段冗余简化过后的大表关联查询相比,当数据量大到一定程度以后(十几万条),查询的速度会差至
少一个数量级,而且对数据库的压力很小,这就是对象缓存的真正威力!

更进一步分析,使用ORM,我们不考虑缓存的情况,那么就是3n+1条SQL。但是这3n+1条SQL的执行速度一定比iBATIS的大表关联查
询慢吗?不一定!因为使用ORM的情况下,第一条SQL是单表的条件查询,在有索引的情况下,速度很快,后面的3n条SQL都是单表
的主键查询,在繁忙的数据库系统当中,3n条SQL几乎可以全部命中数据库的data buffer。但是使用iBATIS的大表关联查询,很可能会
造成全表扫描,这样性能是非常差的。

第 35 / 283 页
http://robbin.javaeye.com 1.13 为什么ORM性能比iBATIS好?

所以结论就是:即使不使用对象缓存,ORM的n+1条SQL性能仍然很有可能超过iBATIS的大表关联查询,而且对数据库造成的压力要小
很多。这个结论貌似令人难以置信,但经过我的实践证明,就是事实。前提是数据量和访问量都要比较大,否则看不出来这种效果

还是拿上面这个例子的应用场景来说,由于JavaEye网站用RoR的ActiveRecord,所以这个场景事实上就会发送3n+1条SQL语句。我从
log里面看到这密密麻麻的SQL,着实非常担忧性能,所以尝试使用了find的:include选项去eager fetch,迫使ActiveRecord发送单条复杂
的关联查询。但非常不幸的是,在网站服务器的production.log里面经过前后对比,发现使用:include以后,单条复杂关联查询耗时更
多,数据库压力更大。

在使用memcached之后,比3n+1条的性能进一步明显提升。所以性能对比就是这样的:

ORM + Cache > ORM n+1 > iBATIS 关联查询

那为什么应用Cache可以进一步提高性能,是因为访问Cache的开销比访问数据库小的得多造成的。

应用程序根据主键key去Cache Server取value,是非常简单的算法,开销极小。
而发送一条主键查询的SQL到数据库,要经过非常复杂的过程,有SQL的解析,执行计划的优化,占位符参数的代入,只读事务的保护
和隔离等等,最终虽然也命中了数据库的data buffer,但是开销确实很大。

BerkeleyDB就是一个极好的证明,它号称其查询速度是Oracle的1000倍,不是因为它做的比Oracle牛,而是因为它本质上就是一个大
Cache,查询没有额外的开销。

第 36 / 283 页
http://robbin.javaeye.com 1.14 漫谈应用缓存的命中率问题

1.14 漫谈应用缓存的命中率问题

发表时间: 2007-05-09

这篇文章源自于:

http://www.javaeye.com/topic/77195

其中很多人谈到了缓存命中率的问题,应用缓存的命中率取决于很多的因素:

1、应用场景
是OLTP还是OLAP应用,即使是OLTP,也要看访问的频度,一个极少被访问到的缓存等于没有什么效果。一般来说,互联网网站是非常
适合缓存应用的场景。

2、缓存的粒度
毫无疑问,缓存的粒度越小,命中率就越高,对象缓存是目前缓存粒度最小的,因此被命中的几率更高。举个例子来说吧:你访问当
前这个页面,浏览帖子,那么对于ORM来说,需要发送n条SQL,取各自帖子user的对象。很显然,如果这个user在其他帖子里面也跟
贴了,那么在访问那个帖子的时候,就可以直接从缓存里面取这个user对象了。

3、架构的设计
架构的设计对于缓存命中率也有至关重要的影响。例如你应该如何去尽量避免缓存失效的问题,如何尽量提供频繁访问数据的缓存问
题,这些都是考验架构师水平的地方。再举个例子来说,对于论坛,需要记录每个topic的浏览次数,所以每次有人访问这个topic,那
么topic表就要update一次,这意味着什么呢?对于topic的对象缓存是无效的,每次访问都要更新缓存。那么可以想一些办法,例如增
加一个中间变量记录点击次数,每累计一定的点击,才更新一次数据库,从而减低缓存失效的频率。

4、缓存的容量和缓存的有效期
缓存太小,造成频繁的LRU,也会降低命中率,缓存的有效期太短也会造成缓存命中率下降。

所以缓存命中率问题不能一概而论,一定说命中率很低或者命中率很高。但是如果你对于缓存的掌握很精通,有意识的去调整应用的
架构,去分解缓存的粒度,总是会带来很高的命中率的。

这里我可以举一个实际的案例,JavaEye2.0网站在使用对象缓存之前,通过MySQL的监控工具进行观察,在连续24小时的平均每秒发
送SQL条数超过了200条,在使用对象缓存之后,连续24小时的平均每秒发送SQL条数下降到了120条左右,几乎下降了一半。

考虑到很多SQL都是分页语句,关联查询,条件查询,集合操作,都是不能被缓存的SQL,而真正能够被缓存的SQL只有根据主键查询
对象和对象关联对象的查询。所以真正能够被缓存的SQL估计最多占所有SQL的60%。所以换算下来,应用缓存的命中率之高,已经相
当惊人了。

不过这里要提醒的一点,有将近一半的SQL都被缓存,不意味着性能可以提升一倍。这是因为能够被缓存的都是按照主键查询单条记
录的SQL,这些SQL本身即使发送到数据库,对数据库造成的压力也没有想像的那么大。真正对数据库造成庞大压力的正是那些没有索
引的大表查询,和造成了全表扫描的关联查询,这些一旦涉及到全表扫描的查询,才是性能的真正杀手。当然了,不管怎么说,通过
使用对象缓存,是毫无疑问可以大幅度降低数据库的负载压力的,有效提升web应用的性能的。

关于这一点,我再给出一组数据来加深大家的印象,通过使用操作系统网络工具进行统计:

第 37 / 283 页
http://robbin.javaeye.com 1.14 漫谈应用缓存的命中率问题

JavaEye网站web server的端口每秒数据流量是2MB;
JavaEye网站的MySQL数据库端口的每秒数据流量是1.2MB;
而网站的memcached的端口每秒的数据流量高达5MB。

第 38 / 283 页
http://robbin.javaeye.com 1.15 Java开源框架发展的遐想

1.15 Java开源框架发展的遐想

发表时间: 2007-05-23

上周末在杭州网侠大会做演讲的时候,我说:Java开源框架的革命浪潮已经结束了,未来几年,将是Java语言级别的革命。说实话,
自从03年Hibernate火爆,04年spring流行之后,Java开源领域实在太缺乏亮点了。但是,Java的主流开源框架真的一点改进的余地都
没有了吗?

先来说说Hibernate吧。Hibernate确实功能强悍,但是Hibernate不够易用,而且有一些明显的缺陷:one-to-one必须通过bytecode
enhancement才能lazy loading;不支持多态关联;怪异的inverse配置和维护;DetachedCriteria有明显的bug;many-to-one的eager
fetch设置不够灵活,让Hibernate的使用者真是又爱又恨,使用起来战战兢兢,如履薄冰阿。Gavin King同学是个很刚愎的人,他似乎
从来不觉得这些问题是问题,而且他已经把自己的主要精力放到JBoss Seam产品上面去了,也许我们只好继续忍受了。那么JPA呢?
JPA标准就像是Hibernate模子里面刻出来的一样。但是为什么人们总是在忍受Hibernate缺陷的同时,却没有去努力改进这些问题呢?

我想,问题的关键在于一些缺陷的改进需要对Hibernate整个源代码架构进行伤筋动骨的改动,但是对于Hiberante今天所取得的垄断地
位来说,显然Hibernate的开发者们已经缺乏足够改进的勇气和魄力了。

Springframework,简直如日中天,定义了轻量级Java企业应用开发的事实标准。但是spring真的很完美吗?我们已经听到太多对于
spring的xml bean配置文件的抱怨。也许配置文件不是太大的问题,spring已经开始尝试引入annotation。但是spring的致命问题是无法
方便的对动态创建的bean进行依赖注入。Google Guice的出现让我们看到了其实prototype的bean和动态创建的bean其实也可以很容易
的管理。spring自身的缺陷事实上造成了很难进行rich domain model架构的实现。

Rod Johnson创办的interface21公司专职从事spring的咨询,最近已经得到了1000万美元的风险投资,是没有足够的资源去改进spring
吗?当然不是。是因为spring今天所取得的垄断地位使得spring的开发者们没用足够的勇气去推翻spring现在的架构,进行重大的改
进。

Java的Web框架领域这两年非常令人失望:Tapestry在升级的过程中不断的迷失自己,丧失用户;webwork和struts合并了两年了,结
果只搞出来一个完全webwork版本的struts2.0.6,毫无改进;JSF叫嚣的厉害,却没有前途;wicket叫好却不叫座;当年令人眼前一亮
的stripes两年来一直小修小补。

web框架没有改进余地了吗?其实我们稍微想一下,就发现web框架大有改进余地。例如以struts2.0为例,完全可以仿照RoR,大量使
用annotation和CoC,完全消除action的配置文件,完全消除validations配置文件,但是struts2.0叫嚣了两年的Zero Configuration,却
干打雷不下雨。

是的,struts2.0有一个叫做restful的actionmapping,但只是徒有其表。我们想一下,只需要稍微修改一下struts2.0的URL Mapping机
制,扩展一下FilterDispatcher,再扩展几个URL的JSP Tag,让Struts2.0完全支持REST架构风格,完全不是什么难事。为什么struts2.0
两年以来毫无动静?实在让人无法理解。

所以Java社区其实有很多事情可以做,而且难度也未必很大,但很奇怪的是,为什么社区显得如此沉寂呢?没有创新性的产品出来
呢?我也想不明白。

第 39 / 283 页
http://robbin.javaeye.com 1.15 Java开源框架发展的遐想

第 40 / 283 页
http://robbin.javaeye.com 1.16 Java已经过时了吗?

1.16 Java已经过时了吗?

发表时间: 2007-07-02

在四年以前,当我开始鼓吹Hibernate,抨击EJB的时候,遭到的是群起而攻之的场面,但是不到一年之后,Hibernate已然得到了普及
和大多数Java开发人员的认可;
在三年以前,当我开始赞誉spring的时候,spring还面临着EJB3的阴影,以及EJB2对其不登大雅之堂的指责,然而不到一年的时间,
spring已经成为绝大多数Java开发人员的首选;
在两年以前,我极力希望宣传webwork,唱衰JSF,时至今日,webwork以Struts2.0的身份容登大雅之堂,而JSF还在靠厂商死挺着;
而当一年之前我开始采用RoR开发JavaEye的时候,RoR的置疑之声还甚嚣尘上,但当我在今年初预言07年下半年RoR在国内会被广泛
接受的时候,很多人已经笑不出来了;
今年我预言些什么呢?我觉得会是AJAX技术走出PC的时代,证据就是iphone,与此相关联的事情就是REST架构的流行。

但是这篇文章里面我想谈的却不是我预言的水平准不准,而是想谈Java真的会因为RoR的流行而过时吗?目前在web开发主要应用在两
个大的领域,互联网和企业应用,我们分别来看一下:

一、互联网领域
互联网领域第一大动态语言是PHP,第二第三分别是ASP和Java。在中小型互联网应用当中,PHP的王者地位不容动摇,但在大型应用
当中,Java是目前主流的选择,特别是电子商务类型的应用,例如阿里巴巴就从早期的PHP转变到Java,从前的eachnet也是如此。造
成这样局面不是没有原因的:

1、中小型互联网网站强调开发速度,维护成本,以及入门快速和部署成本,PHP是最合适的选择;用Java则显得过于笨拙,开发慢,
维护成本高,入门周期长,部署麻烦;RoR开发速度最快,维护成本最低,但是RoR入门速度没有PHP快,部署成本比PHP高。因此中
小型互联网网站主流还是PHP,但RoR能够占据一定的份额。

2、大中型互联网站强调稳定性,性能,大规模代码的组织能力,而开发效率则退居次要地位,有些应用如电子商务对事务有很高的要
求,显然Java是最合适的选择;PHP的代码组织能力最差,RoR次之。

在互联网领域,Java从来就不是主流,并且Java的适用领域和RoR不太重合。我们甚至可以这样说,RoR现在在互联网领域取代的是那
些原本不适合用Java,但是被错误的选择了Java的项目。

二、企业应用领域
目前企业应用领域第一大语言是Java,dotnet其次。企业应用采用的技术和行业有很大关系:例如金融行业,电子政务行业一般只采用
Java。dotnet发展了6年尚且没有进入企业高端的应用,RoR在短期之内也很难取代Java的地位。

在企业应用领域,Java是主流,并且Java的适用领域和RoR也不太重合。我们也可以这样说,RoR将来在企业应用领域要取代的是那些
原本不适合用Java,但是被错误的选择了Java的项目。

至此,我想Java程序员大可以松一口气,RoR目前有哪些不适合的场合呢:

1、对事务要求非常高的场合
RoR还是很简单的单数据库事务控制,缺乏精细的事务控制功能,当然也不支持跨数据库的分布式事务。因此对于事务要求严格的大
型电子商务网站,部署复杂的分布式数据库场景显得力不从心。当然也许有些plugin可以提供这些功能,但是从目前的功能完备性和成
熟度来看,还不够。

第 41 / 283 页
http://robbin.javaeye.com 1.16 Java已经过时了吗?

2、处理大量遗留数据库的场合
ActiveRecord的威力很大程度上来自约定,大量命名糟糕的遗留数据库会对RoR造成比较大的障碍。

3、庞大的项目团队,对开发速度要求低的场合
例如日本外包项目,团队庞大,个体开发速度要求低。但是对于代码规范要求严格的项目。

虽然RoR不会取代Java,但不意味着作为程序员的你可以固步自封。即使在工作当中用不上RoR,多看一点新的技术,对于开阔个人视
野也有很大的好处。

第 42 / 283 页
http://robbin.javaeye.com 1.17 Google Android会成为手机领域的微软Windows吗?

1.17 Google Android会成为手机领域的微软Windows吗?

发表时间: 2007-11-16 关键字: android

Google gPhone手机的传言已经沸沸扬扬好几个月了,然而就像Google其他产品那样出人意料,当Android轰轰烈烈推出的时候,原来
并非手机产品,而是手机操作系统。Google对无线互联网市场垂涎已久,这已经是尽人皆知的事情。在公众场合,无论是Google全球
CEO艾里克施密特博士,还是在中国媒体面前的李开复博士,都毫不掩饰Google对于无线互联网市场的向往。Android的推出就像
Google在无线互联网市场亮出的一把利剑,已经是司马昭之心,路人皆知。

Google Android动了谁的奶酪?是Apple,还是微软?Apple刚刚发布了划时代的iPhone手机,而微软已经在手机操作系统领域耕耘了很
多年。大家可能忽略了一个简单的事实:Google全球CEO艾里克施密特是Apple公司的董事会成员,Google Android实际上也避开了和
iPhone的竞争关系。

互联网时代奇迹般崛起的Google,已经成为微软的心腹大患。然而不论GoogleOS的谣言传得多么活灵活现,业界多么意淫Google直接
挑战微软Windows操作系统,然而Google从来都是按兵不动。Google看得很清楚,桌面操作系统时代快要结束了,现在是掌上操作系
统时代登场了,谁能够先一步占领消费者的手掌,谁才是真正的赢家。这一次,Google终于亮剑了,亮出来的绝对是一把无坚不摧的
利剑 - Android。

Android对于Google未来的无线互联网战略为什么那样重要?Android比其他手机操作系统有什么更牛的地方?

一、Android是开源的

开源社区对于软件行业的推动力已经没有人可以否认了,纵观整个手机操作系统产品,也只有Android的开源力度是如此之大,之强。

二、Android不单纯只是操作系统

Android不只是一个操作系统而已,它包括了:

1、经过Google剪裁和调优的Linux Kernel,对于掌上设备的硬件提供了优秀的支持。Google在Linux方面的应用能力不容置疑,Google
公司所有的几十万台服务器全部都是自己修改过的Linux操作系统。

2、经过Google修改的Java虚拟机Dalvik,请注意这个虚拟机并不是Sun的Hotspot,而是基于Apache Harmony虚拟机版本进行改良而
来,能够提供比Hotspot高得多的执行性能。有了Java虚拟机,大部分Java核心类库都已经可以直接运行。

3、大量立即可用的类库和应用软件,例如浏览器WebKit,数据库SQLite,让你可用轻易开发出来媲美桌面应用复杂度的手机软件。

4、Google已经开发好的大量现成的应用软件,同时可以直接使用Google很多的在线服务。

5、Google提供了基于Eclipse的完整开发环境,模拟器,文档,帮助,示例,当然,还有悬赏1000万美元的花红。

三、围绕Android形成了一个移动手机联盟,主要的手机厂商几乎全部在列,对于已经形成的一个庞大的产业联盟的推动力来说,影响
力是非常惊人的。

事实上,通过Android战略,Google已经开始抢占未来互联网领域的制高点。对于我们程序员来说,有几个非常值得关心的问题:

第 43 / 283 页
http://robbin.javaeye.com 1.17 Google Android会成为手机领域的微软Windows吗?

一、Android是用Java来开发应用的
对于Java程序员,没有比这更令人开心的事情了。的确是这样,打开你的Eclipse,安装上插件,你现在就可以利用你所有的Java编程
经验开发Android应用,而这项应用将在未来几年之后可以运行在绝大部分智能手机之上。Java屹立不倒

二、Java ME前景如何?
事实上,Android是在继续JavaME未竟的事业。JavaME提供了统一的编程平台,但是JavaME不能调用操作系统资源,也没有提供诸多
的应用工具,最终JavaME处在一个非常尴尬的位置上。而Android往下直达操作系统内核,往上直通现成的应用软件,例如联系人,日
历,地图,浏览器,Android就是手机应用的未来。

三、我应该现在开始学习Android吗?
如果你已经是一个熟练的Java程序员,那么你唯一需要做的就是熟悉一下Android类库而已,

无线互联网已经成为未来时代争夺的制高点,Apple iPhone上市,紧接着Google Android一出,你会发现很多传统的无线互联网技术,


例如Java ME,WAP,都将成为过眼云烟,而站在未来时代最前沿的是Google和Apple两个身影。

第 44 / 283 页
http://robbin.javaeye.com 1.18 Warp framework - 一个相当有前途的Java轻量级Web开发框架

1.18 Warp framework - 一个相当有前途的Java轻量级Web开发框架

发表时间: 2008-03-06 关键字: warp

Warp framework 是最近刚刚发布的、基于Google Guice的轻量级Web开发框架,我也是在JavaEye网站的新闻频道看到的这条新闻:


warp-persist 1.0: 为Google Guice专门提供持久层与事务处理的框架,通过这个新闻仔细阅读了Warp网站上面的文档,感觉到很振奋,
Warp是一个相当棒的Java Web框架,而且前景非常看好。

Warp框架充分利用了JDK5.0的Annotation和泛型机制,并且基于Google Guice这个IoC框架,提供了full-stack的Web开发设施,他主要
包含了四个部分:

warp-persist框架:封装Hibernate和JPA,提供事务管理和持久化资源管理
warp-dynamic-finder:提供了基于Annotation的动态查询功能,让数据库查询变得异常简单,不再需要DAO层
warp-mvc:借鉴了Tapestry5,提供了一个基于事件机制和组件化的Web层,并且组件注入方式高度IoC化
warp-servlet: 提供了一些Servlet的封装和附加的高级功能,例如URL过滤,和其他web框架集成等等

这几年来,Java在Web开发框架方面的进步显得很有限,Spring/Hibernate组合对撼JBoss Seam形成两大竞争的主流态势,但是这两个
Web框架在Web快速开发方面的创新还显得不够好:Spring是越来越臃肿了,配置文件也是越来越复杂难懂了;JBoss Seam门槛又过
高,而且集成的JSF一向受人垢病,并非完美的解决方案,特别是在Ruby on Rails横空出世之后,Java社区对于简洁易用的快速web开
发框架的企盼也是一直很高的。

Warp在我看来是这方面做的最好的,它有以下几个鲜明的特点:

一、充分利用JDK5的annotation,简化编程和配置文件

Warp基于Google Guice并且发扬光大,自身无配置文件,所有功能完成均通过annotation,所以编程相当简洁

二、大量使用JDK5的泛型编程,提供强类型安全保证

虽说脚本语言的Duck Typing理念很流行,不过Java的优势也就是类型安全,Spring大量运用反射和XML配置等于是放弃了Java的优势。
Warp在泛型方面做的很好,我相信在IDE的帮助下,Warp编程会更轻松

三、Warp-persist提供了声明式的事务管理,终于可以取代Spring了

Google Guice很好很强大,但是它没有事务管理能力和资源管理能力,所以无法取代spring,但是Warp-persist填补了这一缺憾,注入
和管理Hibernate很容易:

Injector injector = Guice.createInjector(..., PersistenceService


.usingHibernate()
.across(UnitOfWork.TRANSACTION)
.buildModule());

第 45 / 283 页
http://robbin.javaeye.com 1.18 Warp framework - 一个相当有前途的Java轻量级Web开发框架

要声明事务比spring可简单多了:

public class MyService {


@Inject Provider<Session> session;

@Transactional
public void createNewPerson() {
session.get().saveOrUpdate(new Person(...));
}
}

Warp支持Hibernate/JPA的所有事务管理策略,不但注入方式简单,而且声明事务方式更简单,代码看着简洁,写着更省心。

四、Dynamic Finder实在很酷!

还是直接看代码吧:

@Finder(query="from Person")
public List<Person> listAll() { return null; }

用annotation声明一下,一行查询代码都没有,你还要DAO干啥呢?

@Finder(query="from Person where firstName = :firstName")


Person find(@Named("firstName") String name);

带参数的绑定变量查询,还是一行代码不用写,DAO是啥?

@Finder(query="from Person")
List<Person> listAll(@FirstResult int first, @MaxResults int max);

带分页的查询,还是一行代码不用写,谁用DAO我跟谁急 !

五、Web层也极其简单

第 46 / 283 页
http://robbin.javaeye.com 1.18 Warp framework - 一个相当有前途的Java轻量级Web开发框架

Warp-MVC模仿了Tapestry 5的架构,但是作者做了大量的改良和简化,作者解释了一下为什么不直接使用Tapestry,而是自己开发的
理由。

Warp-MVC看起来像一个Tapestry的简化版,有组件的概念,事件响应的方式,但是非常易用,非常简洁,URL映射也通过annotation方
式声明,作者在自己的博客上面提供了相关的简单示例,可以参考:

http://www.jroller.com/dhanji/

Warp框架是最近几年来,我看到的第一个走在正确发展方向上的Java Web框架:结构简单、易用使用、但充分发挥了Java自身的语法
优势,非常值得期待!

目前Warp框架还不是特别成熟,但是Warp-persistent已经相当稳定了,如果你是使用Hibernate/Spring/Struts来开发项目的话,不妨
试试Warp,把spring换掉改成Hibernate/Warp/Struts2.0,也是一个不错的解决方案,全部运用annotation,让你的项目Zero
Configuration。

友情提醒:Warp官方网站无法直接访问,建议在FireFox浏览器上面安装gladder插件,跨越GFW。

Warp Framework - 官方网站

第 47 / 283 页
http://robbin.javaeye.com 1.19 Spring Application Platform - SpringSource的应用服务器发布

1.19 Spring Application Platform - SpringSource的应用服务器发布

发表时间: 2008-05-05

2008年的5.1劳动节,SpringSource发布了策划已久的开源应用服务器-SpringSource Application Platform。JavaEye的新闻频道也有


报道:

SpringSource 宣布发布 SpringSource Application Platform Beta

总体来说,Spring的Application Platform就是一个根据Rod Johnson自己对于Java企业应用开发的理解,自行制订了一套应用服务器的


标准,并且开发了这样一个专用的应用服务器出来。但是Spring的应用服务器也有自己的一些特色,让我们简单看看:

这是Spring应用服务器的结构图。他的底层是用Equinox这个OSGi框架来搭建的,我们知道Equinox为底层框架搭建的应用软件还有
Eclipse,他的特点是高度的模块化,可定制化和在线的部署和卸载,以及模块的版本管理、依赖管理等功能。

Spring在Equinox的基础之上开发了DMK这样一个框架,即动态模块内核(Dynamic Module Kernel),DMK封装了Equinox的很多底层操


作,向上提供了更加方便的API和管理平台。

在DMK之上,所有的功能统统以模块的方式运行在DMK之上,例如Tomcat就是以模块的方式部署在Spring应用服务器上,此外还集成
了应用发布模块、系统管理模块等等。所有的模块都可以以标准的方式部署到Spring应用服务器上面,具体模块的信息,可以看看
Spring应用服务器的repository目录下面的文件。

Spring应用服务器给我的感觉和JBoss应用服务器很像。JBoss也是类似这样的结构,JBoss最核心的底层是JBoss Microkernel,即微内
核,这个MicroKernel提供了JMX的接口,而JBoss应用服务器的所有其他功能,都是通过标准的JMX来插入到MicroKernel之上的,例如
Tomcat、Hibernate3、EJB、Transaction,DB Pool等等,都是标准的SAR模块包。

他们之间比较大的不同在于Spring应用服务器底层使用的是OSGi结构来进行模块化的管理和部署,而JBoss使用的是基于JMX的模块化
管理。使用OSGi的一大好处就是可以在线的热部署和卸载,并且可以提供良好的模块版本管理。

Spring应用服务器我从我初步的接触来看,我觉得有一些比较有特色的地方:

一、轻量级和模块化

Spring应用服务器本质上就是基于Equinox的Spring DMK,这DMK本身是很小的,在DMK上面可以部署各种各样的功能模块来扩展应用
服务器的功能,模块化程度非常高,内核本身是很轻量级的。

看Spring Applicaiton Platform自己的文档上面说,如果去掉Tomcat模块的话,启动应用服务器只占15MB内存(能用来干啥?),其实目


前Spring应用服务器并没有提供很多功能模块上来,只是一个web模块、一个部署模块和一个管理监控模块。但是计划在2.0版本增加
更多的模块、例如群集支持模块、SOA模块等等。

二、在线的热部署和卸载

第 48 / 283 页
http://robbin.javaeye.com 1.19 Spring Application Platform - SpringSource的应用服务器发布

得益于Equinox,可以在服务器运行期增加功能模块、部署新的Web应用,或者更新、卸载Web应用,所有的这些操作都可以Online进
行。这恐怕是比传统的Java应用服务器最领先的特色了。

三、库的版本管理和依赖

jar包的版本冲突和依赖是传统Java应用很头疼的一个方面,Spring应用服务器提出了自己的一套库版本管理和库依赖管理的机制,具
体的原理我还没有仔细的研究,貌似也是利用了OSGi的功能。

总结:

Spring应用服务器和Spring框架并没有什么直接的关系。你用其他框架开发的Web应用也可以部署到spring应用服务器上来,只是
Spring应用服务器提供了很多可能你觉得不错的功能,吸引你使用spring的应用服务器,而不是tomcat或者jboss。但是Spring应用服务
器并不符合Java EE的标准,因此可以看成是一个完全无视JCP的应用服务器,也是Rod Johnson大胆甩开标准进军应用服务器市场的尝
试。

第 49 / 283 页
http://robbin.javaeye.com 1.20 发现JBoss Seam很棒呀!有用Seam做过项目的吗?

1.20 发现JBoss Seam很棒呀!有用Seam做过项目的吗?

发表时间: 2008-07-06 关键字: seam

上周去见了一个朋友Mark,他应邀在Red Hat的研讨会上面介绍他曾经用JBoss Seam做过的一个大的项目。因为听了他的演讲,对


JBoss Seam多了一点认识,有点出乎意料的方便。所以周末在家下载了JBoss Seam摆弄了一下,把Seam自带的examples都浏览了一
遍,也大致看了一下Seam的Reference,感觉挺惊艳的。于是又在JavaEye上面搜索了一下Seam,这才发现自从去年下半年开始,
JavaEye已经有大量关于Seam的讨论了,这都一年多过去了,看来自己对Java社区已经有点孤陋寡闻了。

写这个文章的目的是和大家一起交流一下JBoss Seam,虽然我通过文档和代码,已经对Seam有了不少了解,但是毕竟没有用Seam写
过项目,希望有这方面经验的朋友多谈谈自己的体会。那么作为抛砖引玉,结合与Spring的对比,我先谈谈自己的感觉吧:

一、Seam适应快速开发、简化框架的趋势

在RoR流行之前,Java社区的主流还是非常讲究分层、架构、复用和模式,而比较忽视快速开发和简化架构的,其结果就是代码量大、
开发周期长、架构相当烦琐。以比较常见的Struts/Spring/Hibernate为例,从大的分层来说就有Web层、业务层和持久层,从细的分层
就从前到后有:View(JSP) -> Struts Action -> Spring Business Object Bean -> Spring DAO Bean -> Hibernate Persistent Object。如果
有Remoting调用,那么还需要相应的Service Facade层。每层都是用不同的技术框架或者模式、各层之间整合的方式也是五花八门。把
整个项目的架构搭建起来,已经是非常麻烦的事情了。

Seam给我的感觉像是一个异常简单的MVC框架,他实际上只有两层:JSF View和 Seam Component。而Seam Component有两类:一


类是Entity Bean,另一类就是Session Bean。Entity Bean映射数据库表,Session Bean完成所有的业务逻辑,包括可能的持久化,事
务,响应页面请求、商业逻辑,页面流控制等等。配置文件也不多,除了一堆基础的配置文件,唯一一个需要不断修改的就是
pages.xml了,即配置JSF的view映射。

所以Seam开发项目看起来很简单、很直接,无分层之苦恼。相应的也会让程序员把精力主要放在业务逻辑组件的实现上,而不是把精
力浪费在架构、分层、模式和基础设施搭建的工作上面。

二、Seam的数据绑定做的很出色

由于是一个简单的两层结构,View和Component之间的数据绑定做的很出色,看起来比我欣赏的Webwork的数据绑定方式更胜一筹。
官方的说法叫做双向依赖注入,在component里面可以直接取到页面提交的数据,在页面也可以直接访问component数据。

另外持久化数据的校验也直接集成好了,在EntityBean里面声明数据的约束,在页面就可以直接校验了,和RoR的数据校验方式是一样
的,当然这也得益于Gavin King是Seam和Hibernate两个项目的作者的缘故。

三、Seam的组件机制看起来相当好用

既然Seam简化了分层,实际上把主要的工作都推到组件层去完成了。但是Seam的组件层看起来很简单,这得益于Seam的组件机制设
计了很多的组件状态,根据不同的组件状态,天然的划分了不同组件的功能和逻辑。

第 50 / 283 页
http://robbin.javaeye.com 1.20 发现JBoss Seam很棒呀!有用Seam做过项目的吗?

Seam的组件有点类似于把传统MVC的Action和Spring的Bean合二为一了,但还是不同于传统的MVC框架下面的Action:传统的MVC
Action是基于页面请求的,无法复用,而Seam的组件是事件驱动方式,它只需要捕获和实现事件代码就可以了,至于怎么触发它并不
需要知道,他和Web层可以不绑定,因此理论上面来说是可以实现组件复用的。我个人认为Seam的这个组件机制非常巧妙,既可以用
来实现响应页面事件,绑定页面数据的所谓Web Bean,也可以用来实现和Web没有任何关系的纯业务逻辑组件,一个很漂亮的实现。

另外Seam的组件注入机制看起来也很简单,不像Spring那样麻烦,而且内置了很多现成的组件进来,直接用Annotation声明一下就可
以用了,感觉写组件真的很方便、很灵活、很强大。

四、Seam把数据库资源的管理和事务的封装完全隐藏起来了

Spring的数据库资源管理和事务封装是通过提供了一系列的代理类以及配置文件来实现的,程序员还是要通过配置文件的方式来手工
管理事务,访问数据库也必须通过Template编写匿名内部类来实现,而且在Spring/Hibernate框架下面,OpenSessionInView是一个很
讨厌的问题。

但是Seam已经把数据库资源的管理和事务的封装全部都隐藏起来了,程序员完全不需要知道,也不需要操心这些事情,这真是个大大
的解放。当然Seam可以做到这一点,也无非是因为Seam提供了一套上至View层,下至持久层完整的框架,因此可以把实现细节隐藏
在框架内部,不暴露给程序员。Spring之所以做不到这一点,也因为他只充当了一个黏合剂,不能够直接修改View层和持久层带来的
限制。

五、Seam对第三方框架的整合看起来比Spring更深入

原来印象当中只有Spring才提供了一站式的解决方案,这次一看Seam文档,呵!发现Seam也都齐全了,什么邮件啦、工作流啦、页
面流啦、规则引擎啦、异步任务调度啦、消息系统啦、Web服务啦、远程调用啦、甚至全文检索啦全部都集成了。而且集成的比Spring
更深入一些,例如Java EE本身的JMS,MDB自然是Seam的强项,而JBoss自家的JBPM,JPDL,Rules集成的更加没得说。

从整合角度来说,感觉Spring和Seam的出发点不同:Spring更像一个平台,我提供整合的可能性,然后程序员你自家去整合,我提供
一些写好的整合bean,对于这些你通过XML配置一下就整合进来了,如果我没有提供bean的,那么你也可以自己写bean来整合。而
Seam更像一个完整的框架而不是平台,我这个框架想提供的功能,框架自身就已经整合好了,你直接用就是了,你也可以自己写扩展
来整合,但是这个不是Seam希望程序员做的事情。

因此对于程序员的感觉来说,Spring给你提供了一切的零件和半成品,但你要自己动手来组装,而Seam已经给你装好了一个成品,你
就别自己改装了,直接拿去用吧。

六、Seam提供了方便的代码生成器

和appfuse类似,可以直接用ant task来生成一个完整项目的骨架,以及相应的组件代码生成器,利用seam-gen可以快速生成一个完整
的、带有AJAX功能的CRUD项目,而且还是一个eclipse或者netbeans工程,你可以直接用IDE打开编辑了。这功能虽然不太难做,但是
对于程序员来说,帮助是很大的。Seam做的相当不错。

第 51 / 283 页
http://robbin.javaeye.com 1.20 发现JBoss Seam很棒呀!有用Seam做过项目的吗?

以上是我对Seam的一点小小的赞许,当然我也有一点疑问:

一、Seam的View实现是JSF,看页面代码还是密密麻麻的Tag

我是非常反感JSP Tag的,看看页面密密麻麻的Tag就头皮发麻,能不能弄一个Template呀,例如freemarker啥的?这些Tag既不直观,
也不方便扩展。需要扩展页面组件,总不能让我自定义Tag去干活吧?不清楚这个问题怎么办?像freeamarker还可以方便的自定义页
面宏呢。

二、每次修改都要重新打包发布,太麻烦了吧

就算修改一个页面,也要整个打包deploy成为一个ear去拷贝到jboss的应用目录下面,这个要是改页面,不是得烦死? 我以前都是在
项目里面直接内嵌Jetty,作为一个application启动,修改页面根本无需重起呀,更不要说deploy了。

总体来说,我觉得Seam框架非常出色,尤其是他的组件机制设计的很有匠心,真不愧是Gavin King精心打造的框架了,虽然看起来还
是有些缺陷,但是做企业应用项目的话,Seam是一个很棒的选择,作为程序员来说,要比用Spring/Hibernate/Struts省心的多,更能
够把精力放在业务逻辑的编写上面,开发效率也很不错,可能是Java开源框架里面最优秀的快速开发框架之一了。

第 52 / 283 页
http://robbin.javaeye.com 2.1 ruby on rails为什么暂时无法成为企业应用开发的主流?

2.1 ruby on rails为什么暂时无法成为企业应用开发的主流?

发表时间: 2006-09-17

今天上午和庄表伟在msn上交流了一些看法,下午和JavaEye2.0的主力开发人员jerry讨论了关于ruby on rails在企业应用开发和团队协
作的问题。通过讨论,有了一些初步的想法和观点,虽然还不是很清晰,但是现在总结和记录下来,留待今后的实践来验证。

ozzzzzz在Java将死?中提出了一个衡量未来主流工业语言的标准,其中有一条很有意思:

ozzzzzz 写道

1. 应该能规范书写,而不是像c那样可以造就多种不同的风格。

Java明显是一个编程风格非常容易统一起来的语言,而ruby则很明显是一个难以统一编程风格的语言。JavaEye论坛里面有人曾经说
过:

引用

Java语言,高手和低手写出来的代码都差不多,而ruby则不同,高手和低手的代码,高下立判

Java编程语言的语法非常简单,规范比较严密,这样规范化带来的好处就是,一旦程序员具有比较良好的面向对象编程基础和设计模
式的掌握,那么编写出来的代码几乎是大同小异的。

为什么优秀的Java开源框架的源代码我们读起来都比较容易呢?为什么Java那么容易写出来无二义性,相似度那么高的代码风格呢?
为什么用Java做同样一件事情,往往只有一种最优的写法呢?为什么Java很难搞出来奇技淫巧呢?为什么Java语言一直被人认为是大
巧若拙呢?我们再想想,为什么JDK5.0引入的技巧颇高的泛型编程到现在也有三年,为什么还是没有被广泛采用?再想想Java语言被
设计出来是用在什么场合的呢?

想清楚这些问题,那么我们就会发现Java成为企业应用开发主流的一个内在原因(外因也很多,这里不谈),因为Java语言足够死板!

所以写Java程序没有什么花巧,所以为了弄出来点花巧,逼的Java社区搞出来动态反射,搞出来AOP,抄袭了泛型,其目的都是增加
Java语言的灵活性。

那么Java这种死板而简单的语言有什么好处呢?好处就是适合作为工业语言!

那么我们分析一下工业语言在语法上面有着什么样的要求呢?

1、语法足够简单而且强壮
2、语法足够死板、做同样的事情,只有一种最优解
3、足够的语法障碍,抑制你的随意发挥,给我规规矩矩的编码

第 53 / 283 页
http://robbin.javaeye.com 2.1 ruby on rails为什么暂时无法成为企业应用开发的主流?

工业语言为什么有这种内在的要求呢?

1、团队协作的需要
大规模的项目需要几十人以上的协作,甚至是异地协作。这种大规模的团队协作要求程序员的代码风格必须高度一致,并且代码块之
间的依赖性降到最低。显然死板而容易解藕的Java非常的合格

2、批量生产的需要
现在的软件外包产业体现的尤为明显!不需要你的创意,不需要你的设计,就需要你的coding,而且coding风格,功能已经规定死了。
Java显然又非常合适。

好了,上面分析了从语法特点角度,为什么Java成为了工业语言,那么再分析一下为什么ruby不能成为工业语言:

1、ruby的语法过于灵活,发挥的余地太大,导致每个人的代码风格迥异

我刚开始学习ruby的时候非常不适应,被ruby五花八门的语法糖衣搞晕了,同样的一件事情,你有无数种做法,笨拙的,普通的,聪明
的,天才的,各式各样,甚至有本《ruby quiz》的书专门讲解ruby编程的各种奇技淫巧。ruby这种内在语法特性直接造就了ruby on
rails奇迹。在ruby on rails框架里面,有无数的ruby magic,好用之极又让你惊喜万分,没有ruby这么多灵活的语法支持,rails变不出来
这么多魔术。

但是ruby的语法灵活性恰恰是成为工业语言的一大障碍!Java绝顶高手和Java普通高手的代码在风格上不会有大的差别(我就不觉得Rod
Johnson代码比我高明到哪里去),但是ruby绝顶高手和ruby普通高手的代码简直判若云泥!高下立判!绝顶高手如DHH把ruby用的出神
入化叹服之余,也让你我之辈根本无法写出来符合DHH风格的ruby代码。

在我们JavaEye2.0网站开发中,也出现了这种问题,两个人写的ruby代码,互相之间理解起来存在困难。而由于做一件事情有很多ruby
写法,不同性格的人甚至都会选择不同的实现方法,在一个团队中,要统一编码风格,实在难乎其难!而在Java项目中,基本可以杜
绝此类问题。

由于代码风格难以统一,因此在大规模的团队中使用ruby编程,会造成合作上面的障碍!

2、ruby on rails会导致你的代码藕合度非常高,不利于团队协作开发

由于rails规定死你的代码框架,不论是横向的功能解藕,还是纵向的分层解藕,都比较困难。

首先来说纵向的分层解藕,这是Java大规模项目常用的办法,但是在ruby on rails中基本不可能。因为ruby on rails各层之间的隐式约定


太多了,你不可能分层开发。目前ruby on rails项目都是建议横向功能解藕,不建议纵向分层解藕的。

再说横向功能解藕:首先每个人必须承担足够大颗粒度的功能模块,不能拆分的太细了。因为rails的一个Controller文件就代表一大块
功能了。

例如JavaEye2.0中,整个forum就只有一个controller,整个blog也就只有一个controller。当然你惊叹,整个forum代码就一个文件搞定
了啊,代码太少了!但是反过来,你也可以说,论坛这个功能只能交给一个人来做了,没有办法再拆分功能了。这就带来了一个问

第 54 / 283 页
http://robbin.javaeye.com 2.1 ruby on rails为什么暂时无法成为企业应用开发的主流?

题,团队协作变的困难了,如果两个人同时做论坛模块,就会出现经常性的该controller文件冲突合并。即使妥协一下,每个人只负责
一个大功能块,但是底层的model代码都是互相关联在一起的。又难以避免的并发修改和文件冲突合并。

但是Java不存在这个问题,为什么呢?因为Java把一个Controller分解成为了无数个小Action,把一个Model分解成为了PO,DAO,
Service,进行了充分的功能职责的解藕,每个人的工作基本不会互相干扰,那么团队协作的问题就好办了。

在JavaEye2.0开发过程中,就遇到了这个问题,即使是分出来一小部分任务,也经常性导致文件冲突合并,最后只能把大部分的程序
任务压到了jerry一个人身上。可敬的jerry同学几乎以一人之力编写了整个JavaEye2.0的绝大多数代码。在惊叹jerry以一个人月的高效率
完成整个JavaEye2.0编码工作的同时,我们也不得不反思,为什么ruby on rails这样难以团队协作开发呢?

在我最推崇的《Getting Real》这本书里面建议一个开发团队3个人足够了,一个人设计规划产品功能,一个人设计界面,一个人编写
代码。我们现在也是这样的:robbin设计产品功能,ouspec负责界面,jerry编写代码,然后robbin和ouspec负责测试。但并不是所有的
项目都可以靠3个人搞定的,大规模应用项目团队协作进行开发,我们目前还没有答案。

jerry有个观点我非常赞同,他认为目前我们没有找到合适的团队协作方法是因为现在的软件开发方法都不适合ruby on rails开发团队。
而真正适合ruby on rails的软件开发方法究竟是什么样子,现在还没有出现,恐怕需要人们的探索了。ruby on rails流行必须伴随着适合
ruby on rails的软件开发方法一起出现才行。

因此在人们总结出来这种适合ruby on rails的软件开发方法之前,ruby on rails仍然会被局限在web2.0开发领域,在这个领域,ruby on


rails的所有优点将发挥的淋漓尽致,而缺点将会被回避开。不过一旦涉及到企业应用开发领域,我们将面临这些问题。

因此,我的结论就是ruby on rails目前尚且不适合企业应用项目的开发。当然如果有适合ruby on rails的软件开发指导方法的出现,或者


企业应用本身的定义已经发生了彻底的改变,那么我的结论也就不复存在了。

用一句话来总结就是:

ruby on rails是武林高手的绝世宝剑,却不是两军对垒中士兵使用的常规作战武器(Java却是这种常规武器)。

BTW:我抛出来这个结论,并不代表我的想法已经很成熟了,事实上这也只是我们第一次尝试使用ruby on rails,在不熟悉不了解的情
况下做出结论,未免过于草率,但是我之目的在于抛砖引玉,目前我们在开发中遇到了这些团队协作方面的问题,希望我的抛砖能够
引出来好玉,解决这些我们还没有想到很好解决办法的问题,多谢啦,哈哈!

第 55 / 283 页
http://robbin.javaeye.com 2.2 通过JavaEye2.0网站看ruby on rails性能

2.2 通过JavaEye2.0网站看ruby on rails性能

发表时间: 2006-10-09 关键字: rails performance

ruby on rails作为web开发框架,通常被认为性能很差,并因此被置疑其前景。JavaEye2.0网站使用ruby on rails开发,已经上线运行一


个月了,通过这一个月的运行,我们可以对ruby on rails的性能有一个初步的认识。

JavaEye2.0运行的服务器硬件配置:

引用

HP DL145 G1,两路AMD Operton 2GHz CPU, 4G DDR RAM, 73G SCSI 15k Disk

这是一个标准的低端1U机架式服务器,大概能够以15k价格购买到,可以说是相当便宜的硬件配置了。

JavaEye2.0的软件运行环境:

引用

Linux Kernel-2.6.7,lighttpd-1.4.13,MySQL-5.0,ruby-1.8.4(GC patch)

此外服务器上面还运行了Email Server,Tomcat等服务

在JavaEye2.0刚刚上线的时候,启动了50个FastCGI ruby进程,发现大量空闲FastCGI进程,随后根据运行情况,不断减少进程数量,
目前只启动了20个FastCGI进程,因此负载量还是很轻的。

服务器的平均CPU使用率在繁忙的时候,大概15%左右,MySQL数据库繁忙的时候平均每秒发送超过100条SQL语句,24小时平均每秒
发送45条SQL语句。硬盘IO非常少,每秒读硬盘非常低,每秒写硬盘平均200KB左右(操作系统进行了充分的disk cache,MySQL
Cache使用率也几乎满了)。

通过上面这些服务器运行情况,可以大致得出一个结论,目前JavaEye2.0网站在这种低端硬件上面的负载量非常轻,对硬件消耗不
大。

目前JavaEye2.0网站使用了Google Analytics来统计网站的访问量。根据这一个月的统计量,周一到周五一般每天动态网页PageView超
过5万,周六周日和国庆期间每天动态网页PageView超过2万。但是根据对rails的production.log进行统计,24小时,rails正常处理的、
状态为200 OK的Action动态请求数量有12万多。也就是说网站每天正常处理动态请求超过了12万。

由于网站的访问量大部分集中在早上9.00到晚上9.00这12个小时的范围内。因此可以大致粗略的认为12小时处理12万动态请求,平
均每小时处理1万动态请求,也就是说平均每秒处理3个动态请求。

观察production..0X秒,少量请求是0.X秒,如果我们按照平均每个请求处理时间为0.1秒计算,那么一个FastCGI进程每秒可以处理10
个请求,从目前JavaEye2.0网站的运行状况来看,支撑每天60万动态请求,看来是毫无问题的。所有的这些还是没有对程序进行必要
的Cache优化所取得的,如果对程序进行充分的优化,达到每天支撑100万动态请求也是可以做到的。

如果一个网站能够到达每天50万动态请求,已经是一个相当大的网站了,对于那些企业应用来说,访问量也往往达不到这么大的流
量,因此从JavaEye2.0网站的运行情况来看,ruby on rails在性能方面并不会成为一个问题。

第 56 / 283 页
http://robbin.javaeye.com 2.2 通过JavaEye2.0网站看ruby on rails性能

第 57 / 283 页
http://robbin.javaeye.com 2.3 关于ROR的效率的一个讨论回复

2.3 关于ROR的效率的一个讨论回复

发表时间: 2006-11-06

ozzzzzz 写道

本来这个星期我该开始讨论软件危机的问题了。但是这几天我忽然发现,ROR这个烫手的东西带给我们不可思议的效率,这个提高
的来源究竟是来自何处,是一个目前很少有人讨论过的问题。而如果我们可以搞明白这个原因,我们对于今后技术和方法学发展的
方向将有莫大的好处。
而由于我对于这个问题的结论还没有足够的实际例子做证据,因此我就不着急发言了。

我在2005年4月就听说RoR了,还看了他那个scaffold的例子,本来我对RoR也是持否定态度的,但是2006年在JavaEye有几个讨论打
消了一些我的置疑,后来就开始用RoR了,这些讨论是:

http://www.javaeye.com/topic/18675

http://www.javaeye.com/topic/19534

http://www.javaeye.com/topic/20298

RoR的效率肯定要比Java高一个数量级,这确实是事实,比PHP至少也要高好几倍,这也是事实,这一点在这篇文章中不展开了,但是
为什么开发效率这么高,我也想谈谈我的看法,当然还很不成熟的看法:

一、主要原因是ruby语言的语法非常强大

我记得庄表伟说过一个观点:“框架是强化的语法”,意思就是说语法比较弱,所以才需要n多框架,如果语法很强,框架就很少。这一
点在Java和ruby身上得到了验证。

1、ruby的open class VS Java的AOP,反射、动态代理,字节码增强等技术

JDK1.3开始引入反射,就已经打开了Java这种静态类型语言通往动态类型语法的潘多拉魔盒。随后的动态代理技术,字节码增强技
术,静态和动态的AOP技术开始层出不穷,为什么呢?就是需要在程序运行期动态改变对象的行为。但是对于ruby来说是open class
的,语法级别上就支持程序运行期修改对象行为,所以Java需要很复杂技术才能实现的功能对于ruby来说就是非常简单的搞定了。

2、ruby的duck typing VS Java的IoC,泛型

Java的IoC不用说了,泛型在库级别也开始广泛使用。IoC就是根据对象行为来进行对象组装,泛型就是在不确定对象行为的情况下确
定对象的交互。但是ruby的对象行为是在运行期才确定的,天然就是泛型的,行为不是静态的,所以不需要IoC。

3、ruby的block,closure VS Java的匿名内部类

大家对spring的Template肯定印象很深刻,但是这是ruby标准的用法,所以各种资源释放,异常处理在语法级别上就支持的很好,做起
来很简单。

第 58 / 283 页
http://robbin.javaeye.com 2.3 关于ROR的效率的一个讨论回复

4、ruby的Meta programming VS Java缺乏


method_missing机制大家耳熟能详了,Java没有这么强的Meta programming,很多ruby magic耍不出来。

5、脚本语言 VS 编译语言
这也是一个很大的优势,脚本编程速度确实快。

二、rails框架确实做的很棒

1、full-stack
rails是一个概念一致的fullstack框架,不知道为什么,在Java世界目前只有Rife这一个可以和RoR相提并论的fullstack框架,但是Rife的
实现并不好(作者从PHP转过来的,和DHH爆发过口水战)。

不过因为底层语法支持的不同,用Java是做不出来RoR框架的。因此也有人用Groovy做Grails,不过这帮人不太争气。

2、CoC
这个不用说了,现在很多Java框架开始吸收这一点

3、为web开发良身打造
web开发需要用到各种技术全部提供,绝对的贴心,如果用Java,这些东西都需要自己集成或者自己实现,省了一大堆麻烦事。

4、开发测试部署快速
这个不说了,Java劣势太明显了

暂时想到就这么多吧。

第 59 / 283 页
http://robbin.javaeye.com 2.4 RoR背后的软件开发方法学思考

2.4 RoR背后的软件开发方法学思考

发表时间: 2006-11-07

是的,使用RoR肯定需要新的软件开发方法论来指导,但是这一点尚且需要更多实践项目的探索才能有更进一步的想法。这不像单纯
钻研技术,看看文档,写写code观点就可以出来的。

不过从更加宏观的角度来说,RoR需要你采用一种完全不同的开发软件的思路和方式,也就是ozzzzzz说的方法论吧。例如在我们开发
JavaEye2.0网站之前就确定了一些原则,这些思路和传统软件思路完全不同,例如:

1、传统软件要求明确需求之后再开发,而我们只有一个大致的想法就开始把原型做出来

2、传统软件要做出来之后,内部测试,才会正式发布,用户才会接触到,而我们还没有开始之前,就开始放风说一个月后新网站上
线,把用户参与的时间点提前到了软件开发之前

3、传统软件采用封闭开发,而我们从有想法,到设计原型,一步一步开发,测试,上线所有步骤全程网络直接和用户实时交流

4、传统软件要没有bug才推出,而我们是抢先推出,让用户来反馈bug。

使用RoR是从技术上确保了我们这种开发软件思路能够顺利执行下来,但是这种做软件的思路是从成功的web2.0网站开发和运营的经
验借鉴过来的,具体来说我是受了37signals的《Getting Real》的影响才决定这样去做的。

RoR这两年这么流行,其实也不单纯是技术的原因,更加主要的是RoR顺应了互联网Web2.0软件开发的需要:敏捷,快速反馈,用户
参与。当然我们也有一些创新的做法,例如把用户反馈提前到软件还没有开发之前。

其实企业应用软件开发未来几年的主旋律也无非就是:敏捷,快速开发,用户参与,再加上一个异构系统整合而已。因此RoR的流行
深层次的原因可能是一种应用软件行业开发方法的变迁。

就这个话题我已经准备在12月1日的中国软件大会上讲一个topic了,到时候希望得到更多探讨和交流。

第 60 / 283 页
http://robbin.javaeye.com 2.5 《应用Rails进行敏捷Web开发》中文版书评

2.5 《应用Rails进行敏捷Web开发》中文版书评

发表时间: 2006-11-10 关键字: rails

毫无疑问,ruby on rails这个号称开发速度10倍于Java的快速web开发框架是2005年2006年连续两年web应用开发领域最大的奇迹。自
从2004年7月ruby on rails第一个版本发布以来,ruby on rails以令人惊讶的速度迅速征服了web应用开发领域,在2006年3月毫无悬念
的获得了第16届Jolt大奖的web开发工具奖项;rails的作者DHH(David Heinemeier Hansson)也因此得到了巨大的荣誉,2006年8月
荣获OSCON(全球开源大会)年度最佳黑客;而依靠ruby on rails起家,开发web2.0互联网应用的37signals公司则得到了Amazon创始
人Jeff Bezos的投资,Bezos本人则对ruby on rails相当看好,计划推出基于ruby on rails的Hosting服务。

在2005年和2006年,整个ruby社区和rails社区也呈现出来爆炸性的发展趋势,并且诸多Java社区,敏捷社区的德高望众的人士例如
Andrew Hunt,Bruce Tate,Martin Folwer纷纷投身ruby和rails社区,这恐怕不单单用开发速度快就能够解释的了。

《Agile Web Development with Rails》这本书的名字其实就已经很好的揭示了ruby on rails流行和获得社区认可的一个很重要原因,那


就是“Agile”。随着互联网web2.0时代的来临,对于应用软件行业来说,也越来越需要能够灵活应变需求,能够快速开发,能够迅速提
供用户反馈的软件发展趋势。例如我们可以观察到IBM的企业文化叫做“随需应变”,HP的企业文化叫做“动成长”,而BEA的企业文化叫
做“流体思维”,角度虽然不同,但是无一不是揭示出来软件发展的趋势,即“Agile”,能够灵活应变的本领。而ruby on rails框架正是顺
应了“Agile”的大势,才得以迅速走红的。

ruby on rails在国内一个可以参考的成功案例就是JavaEye2.0网站:
http://www.javaeye.com
三个资深的Java程序员,在没有ruby on rails项目开发经验的情况下,仅仅使用了一个月时间,就完成了包括论坛,博客,招聘等多种
功能融合一体的综合性技术网站的设计,开发,测试,迁移和部署上线运营,在使用其他web开发技术的情况下,这么快的开发速度是
不可想象的。目前JavaEye2.0网站的服务器每天要处理超过15万ruby动态请求,独立访问IP也超过了1万。

如果要学习ruby on rails,《Agile Web Development with Rails》是不容错过的。这本书的作者Dave Thomas也是著名的敏捷宣言成员


之一,在技术出版行业久负盛名,也正是由于Dave Thomas在2000年出版的《Programming ruby》一书,将默默无闻的ruby编程语言
带入到了全球知名的高度。也正是这本经典教材《Agile Web Development with Rails》促进了ruby on rails的普及程度,本书也同时获
得了第16届Jolt大奖的General Technical Book大奖,可谓实至名归。

《Agile Web Development with Rails》前面12章不是按部就班介绍rails框架,而是一上来就开始手把手教你快速开发一个Depot的迷你


购物系统。然后才是rails框架每个部分的详细讲解和剖析,最后两章是web开发的安全性问题和应用部署调优,附录还有一些rails配置
的介绍和ruby编程语言的快速入门。这种行文的结构非常符合初学者的学习习惯,先通过一个案例从整体上快速把握和了解一个技术
的大致情况,然后才是每个部分深入学习,最后的web安全性和应用部署调优的章节特别值得大家仔细去阅读和学习,这部分内容往往
是web开发人员比较薄弱的知识环节,附录的ruby编程语言快速入门可以让你扫平阅读本书的基础知识方面的障碍,因此从本书的目录
结构来看,作者也是匠心独运。

《Agile Web Development with Rails》这本书的中文版《应用Rails进行敏捷Web开发》在2006年8月就已经上市,由林芷薰翻译。译


者到是名不见经传,但是这本书的翻译相当到位,不得不赞一句译者投入的精力和翻译的质量。值得一提的是,中文版的翻译并不完
全按照英文直接字面翻译,很多地方使用了非常中文口语化的意译,让人看起来感觉十分生动有趣,平添几分轻松感。如果想要ruby
on rails快速入门,那么这本书无疑是首选推荐,对于我们JavaEye网站的三个开发人员来说,也是人手一册。如果你没有学习过ruby,
那么建议你先快速看一遍附录ruby入门的章节,然后再大致浏览一遍这本书的主要内容,把Depot案例从头到尾做一遍,就可以用rails
做项目了。在项目开发过程中遇到问题再回过头来查阅本书,查阅最新的rails API文档,或者通过Google搜索。若是没有这本书的帮
助,我们的rails水平进步速度可能也没有这么快吧。

第 61 / 283 页
http://robbin.javaeye.com 2.5 《应用Rails进行敏捷Web开发》中文版书评

目前《Agile Web Development with Rails》的第二版作者还在撰写过程中,可以通过Amazon网站购买第二版beta版的英文电子书。第


二版从我拿到的版本来看,增加了数据库Migration和RJS的章节,其他各个章节也进行了内容的扩充,但是第二版还并没有最后完成,
一些内容还是空着的。所以第二版的英文版正式上市时间还很难说,至于相应的中文版,也要等到英文版推出之后了。

因此对于准备学习和掌握ruby on rails的开发人员来说,现在可以购买《应用Rails进行敏捷Web开发》来学习,如果有条件,可以参考
第二版英文版的相应章节,了解一下哪些内容进行了扩充和增加。

最后,要想掌握一门编程技术,最重要的还是实践,《应用Rails进行敏捷Web开发》可以带领你入门,然后就要靠你自己的了。

第 62 / 283 页
http://robbin.javaeye.com 2.6 rails作者DHH谈及REST

2.6 rails作者DHH谈及REST

发表时间: 2006-12-27 关键字: REST

http://www.loudthinking.com/arc/000602.html

CSDN上面有中文的翻译:

http://blog.csdn.net/dhansson/archive/2006/11/26/1415180.aspx

标题是“死星不可避免的灭亡 ”,引用星球大战的典故,含义是说对于那些庞大商业公司和机构搞出来的貌似威力无比的SOAP和Web
Services就好像星球大战中帝国军队建造的终极武器-死星。

引用

现在感觉起来我们已经到了星球大战-新希望这部电影的最后20分钟。......

而对甲板上的帝国指挥官来说,我敢肯定他们没有什么需要担心的事情标准化过程正在全速前进。我们有委员会来监督委员会。所
以,一小拨叛逆的黑客的咕嘟很难改变什么。难道他们不知道死星很快就要完全投入使用吗?

......我肯定EJB和CORBA的推动者同样认为他们是不可战胜的,......

可能这就是IT业内一个大的运作的方法。我们必须要有一个复杂性深不可测的新的前沿以迷失于中。这个前沿需要工具修整,庞大的
顾问团队,5年的任务计划,和进出的障碍

引用

即将到来的Rails 1.2令我兴奋的就是它全部是关于尽量的让REST成为网络程序员自然的解决方案。肯定有很多人在某个方面根本不
在乎。他们就是那些处于危机的人。但是使REST成为标准根本不难。REST已经很简单了。混合一点帮助,指导,和集成的常规,很
快,程序员对项目经理实现SOAP接口的要求的反应就会是:”你真的想让我这么做?!?!”

DHH认为了SOAP就像帝国军队的死星那样,貌似强大,却终将陨落。而推翻SOAP统治,取代SOAP成为网络web服务的REST虽然看似
不值得一提,却终将获胜。

另外最近Google废除了以前发表的Google SOAP API,改用AJAX来提供Search服务了。

很有意思的事情和趋势,让我们明年好好看看是否REST将掀起真正的web服务革命吧,这是SOAP搞了六年都没有搞成功的事情。

BTW:很可惜这么好的文章在CSDN却没有什么点击和回复,sign~

第 63 / 283 页
http://robbin.javaeye.com 2.7 在Linux平台上安装和配置Ruby on Rails详解

2.7 在Linux平台上安装和配置Ruby on Rails详解

发表时间: 2007-01-05 关键字: lighttpd fcgi

在 Linux 平台上安装和配置 Ruby on Rails 详解

ruby on rails推荐的生产运行环境是Linux/FreeBSD/Unix,即Unix系列的操作系统,采用lighttpd+FCGI的解决方案。以下我将以Linux操
作系统,lighttpd+FCGI,MySQL数据库为例,从源代码编译安装开始讲解。

在安装之前,应该确认Linux操作系统已经安装好gcc编译器,否则请用Linux安装光盘先行安装gcc编译器:
gcc –v
如能返回gcc版本号,则gcc正确安装。

一、安装 Ruby 解析器

一些Linux发行版本,MacOSX操作系统都自带Ruby解析器,但是我仍然建议自行下载ruby源代码编译安装。因为一方面可以自己定制
ruby安装的路径,另一方面可以在编译过程中自行添加更多的特性。

ruby的源代码可以从Ruby官方网站下载:
http://www.ruby-lang.org/en/downloads/

下载源代码包到本地Linux主机,然后解压缩,进入该目录,进行配置,编译和安装:
tar xzvf ruby-1.8.5.tar.gz
cd ruby-1.8.5
./configure –prefix=/usr/local/ruby
make && make install
如果想浏览所有的configure参数,可以:
./configure –help |more
如果不定制安装的目录,默认将安装到/usr/local目录下面。然而我建议自行定制一个ruby的安装目录,例如/usr/local/ruby,这样便
于以后的升级,不会和操作系统其他软件混在一起。

安装好以后,修改操作系统PATH路径,加入/usr/local/ruby/bin:
export PATH=/usr/local/ruby/bin:$PATH
将我们自己安装的ruby放在系统PATH前面,避免操作系统自带的ruby造成的干扰。在Linux上,一般将设置放在/etc/profile中,便于对
全局生效。

二、安装 ruby on rails

在安装rails之前,要先安装rubygems。rubygems是ruby的在线包管理工具,可以从rubyforge下载rubygems:
http://rubyforge.org/projects/rubygems/
下载好源代码包,解压缩,安装:
tar xzvf rubygems-0.9.0.tgz
cd rubygems-0.9.0/
ruby setup.rb

第 64 / 283 页
http://robbin.javaeye.com 2.7 在Linux平台上安装和配置Ruby on Rails详解

然后就可以安装rails了,在确认服务器已经连接互联网的情况下执行:
gem install rails –y
即通过gem从rubyforge网站下载rails所有依赖包安装。

安装好rails以后,可以执行:
rails –v
确认一下rails的版本。

三、安装 ruby 的数据库适配器

rails发行包中已经自带纯ruby的MySQL数据库适配器,然而对于生产环境来说,我们仍然应该下载安装C版本的数据库适配器,以达到
更好的性能。下载mysql-ruby-2.7.3.tar.gz:
http://www.tmtm.org/en/mysql/ruby/
tar xzvf mysql-ruby-2.7.3.tar.gz
cd mysql-ruby-2.7.3
ruby extconf.rb --with-mysql-dir=/opt/mysql5
make && make install
注意--with-mysql-dir应该指向MySQL数据库的安装路径,如果数据库服务器和Web服务器不在同一台机器上,那么Web服务器上也必须
安装MySQL软件,因为ruby的C版本MySQL适配器需要在编译的时候联接MySQL的系统库。

四、安装 Ruby 的 FCGI 支持

由于ruby的fcgi支持库需要在编译的时候联接FCGI的系统库,因此我们需要先安装FCGI库,下载FCGI源代码发行包:
http://www.fastcgi.com/dist/
tar xzvf fcgi-2.4.0.tar.gz
cd fcgi-2.4.0
./configure --prefix=/usr/local/fcgi
make && make install
同样,将fcgi安装在自己指定的目录下,而不是默认的/usr/local,避免多个软件混在一起。

然后就可以安装ruby的fcgi支持库了,下载ruby-fcgi-0.8.7.tar.gz:
http://rubyforge.org/projects/fcgi/
tar xzvf ruby-fcgi-0.8.7.tar.gz
cd ruby-fcgi-0.8.7
ruby install.rb config -- --with-fcgi-include=/usr/local/fcgi/include --with-fcgi-lib=/usr/local/fcgi/lib
ruby install.rb setup
ruby install.rb install

五、安装 lighttpd Web Server

第 65 / 283 页
http://robbin.javaeye.com 2.7 在Linux平台上安装和配置Ruby on Rails详解

安装 Lighttpd

在安装lighttpd之前,应该确认操作系统已经安装pcre,即Perl兼容的规则表达式库:
rpm –qa |grep pcre
如果没有,请从Linux安装光盘里面安装。

然后下载lighttpd:
http://www.lighttpd.net/download/
tar xzvf lighttpd-1.4.13.tar.gz
cd lighttpd-1.4.13
./configure --prefix=/usr/local/lighttpd

configure完毕以后,会给出一个激活的模块和没有激活模块的清单,可以检查一下,是否自己需要的模块都已经激活,在enable的模
块中一定要有“mod_rewrite”这一项,否则重新检查pcre是否安装。然后编译安装:
make && make install

编译后配置:
cp doc/sysconfig.lighttpd /etc/sysconfig/lighttpd
mkdir /etc/lighttpd
cp doc/lighttpd.conf /etc/lighttpd/lighttpd.conf

如果你的Linux是RedHat/CentOS,那么:
cp doc/rc.lighttpd.redhat /etc/init.d/lighttpd
如果你的Linux是SuSE,那么:
cp doc/rc.lighttpd /etc/init.d/lighttpd
如果你的Linux是ubuntu,那么需要自己创建启动脚本,lighttpd官方wiki上面已经给出来该脚本,地址在:
http://redmine.lighttpd.net/wiki/1/ScriptsUbuntu

其他Linux发行版本可以自行参考该文件内容进行修改,或者自己写一个控制脚本,也不过举手之劳:

#!/bin/sh

case "$1" in
start)
/usr/local/lighttpd/sbin/lighttpd -f /etc/lighttpd/lighttpd.conf > /dev/null 2>&1
;;
stop)
killall lighttpd
;;
restart)
$0 stop
sleep 1

第 66 / 283 页
http://robbin.javaeye.com 2.7 在Linux平台上安装和配置Ruby on Rails详解

$0 start
;;
*)
echo "Usage: lighttpd.sh {start|stop|restart}"
;;
esac

exit 0

然后修改/etc/init.d/lighttpd,把
LIGHTTPD_BIN=/usr/sbin/lighttpd
改为
LIGHTTPD_BIN=/usr/local/lighttpd/sbin/lighttpd

此脚本用来控制lighttpd的启动关闭和重起:
/etc/init.d/lighttpd start
/etc/init.d/lighttpd stop
/etc/init.d/lighttpd restart

如果你希望服务器启动的时候就启动lighttpd,那么:
chkconfig lighttpd on

这样lighttpd就安装好了,接下来需要配置lighttpd。

配置 Lighttpd

修改/etc/lighttpd/lighttpd.conf

1)server.modules
取消需要用到模块的注释,mod_rewrite,mod_access,mod_fastcgi,mod_simple_vhost,mod_cgi,mod_compress,
mod_accesslog是一般需要用到的。

2)server.document-root, server.error-log,accesslog.filename需要指定相应的目录

3)用什么权限来运行lighttpd
server.username = "nobody"
server.groupname = "nobody"
从安全角度来说,不建议用root权限运行web server,可以自行指定普通用户权限。

4)静态文件压缩
compress.cache-dir = "/tmp/lighttpd/cache/compress"

第 67 / 283 页
http://robbin.javaeye.com 2.7 在Linux平台上安装和配置Ruby on Rails详解

compress.filetype = ("text/plain", "text/html","text/javascript","text/css")


可以指定某些静态资源类型使用压缩方式传输,节省带宽,对于大量AJAX应用来说,可以极大提高页面加载速度。

5)配置ruby on rails

最简单的配置如下:
$HTTP["host"] == "www.xxx.com" {
server.document-root = "/yourrails/public"
server.error-handler-404 = "/dispatch.fcgi"
fastcgi.server = (".fcgi" =>
("localhost" =>
("min-procs" => 10,
"max-procs" => 10,
"socket" => "/tmp/lighttpd/socket/rails.socket",
"bin-path" => "/yourrails/public/dispatch.fcgi",
"bin-environment" => ("RAILS_ENV" => "production")
)
)
)
}
即由lighttpd启动10个FCGI进程,lighttpd和FCGI之间使用本机Unix Socket通信。

Lighttpd的FAQ:无法启动Ruby on Rails

FastCGI的启动脚本位于Rails应用目录下面public/dispatch.fcgi,如果无法启动Lighttpd,报告FastCGI错误,你可以尝试着手工运行该
脚本cd public && ./dispatch.fcgi,看看是否可以运行。一般来说,很多人都是在Windows下面创建Rails项目,导致dispatch.fcgi脚本的
ruby运行路径指向windows下面的ruby,部署到Linux上面就无法运行了,另外一方面Windows上面创建的Rails项目在Linux上面
dispatch.fcgi没有可执行权限,所以也需要授予可执行权限。

六、安装 ImageMagick 和 RMagic

RMagic是ruby处理图片需要用到的库,很多ruby应用由于都涉及图片处理的功能,往往需要依赖RMagic,但安装ImageMagick和
RMagic相当烦琐,需要特别的说明。

安装 ImageMagick
http://www.imagemagick.org
ImageMagick是用C语言实现的图形处理库,有Unix版本和Windows版本。对于Unix版本来说,安装比较麻烦些,另外不建议安装
ImageMagick二进制版本,往往会导致缺少某些图片处理功能,导致RMagic安装失败。下载ImageMagick源代码,解压缩,配置:
tar xzvf ImageMagick-6.2.9-0.tar.gz
cd tar xzvf ImageMagick-6.2.9
./configure --prefix=/usr/local/ImageMagick

第 68 / 283 页
http://robbin.javaeye.com 2.7 在Linux平台上安装和配置Ruby on Rails详解

观察配置后给出来的支持图形格式,看看该图形格式支持是否是yes,如果不是,那么必须先安装该图形格式的本地库。例如,你应该
检查是否已经安装如下rpm包:
rpm –qa |grep libpng
rpm –qa |grep libpng-devel
rpm –qa |grep libjpeg
rpm –qa |grep gd-devel
如果你希望支持tiff格式,还应该检查
rpm –qa |grep libtiff
如果没有安装,那么在Linux安装光盘找到相应rpm包安装上,再次configure直到确认需要的图形格式全部支持为止,然后编译安装:
make && make install

由于ImageMagic被安装在我们自行指定的/usr/local/ImageMagick,后面安装RMagic会找不到需要用到的ImageMagic的命令和库,因
此需要配置一下操作系统:

编辑/etc/profile里面的PATH环境变量,在最后面加入:
export PATH=/usr/local/ruby/bin:/usr/local/ImageMagick/bin:$PATH

编辑/etc/ld.so.conf,加入:
/usr/local/ImageMagick/lib
执行命令:
ldconfig
将ImageMagick的库加入系统联接库

然后注销当前用户重新登录,便于环境变量修改生效,执行:
convert logo: logo.gif
看是否正确生成一个logo.gif的图片文件。

安装 RMagic
http://rubyforge.org/projects/rmagick/
在rubyfoge上面下载RMagic的源代码发行包,不要下载gem包,然后解压缩编译:
./configure
make && make install

如果配置和编译过程没有报错,即大功告成。

对于MacOSX来说,安装RMagic以上步骤会出错,请参考:
http://rmagick.rubyforge.org/install-osx.html

总体来说,ImageMagick和RMagic的安装很容易出错,安装起来比较困难,如果碰到无法解决的问题,可以通过Google寻求解决办
法。

如果你在安装过程当中,遇到了什么问题,请看:Lighttpd和RoR安装配置的疑难解答

第 69 / 283 页
http://robbin.javaeye.com 2.8 在Windows平台使用Apache2.2和Mongrel运行Ruby on Rails

2.8 在Windows平台使用Apache2.2和Mongrel运行Ruby on Rails

发表时间: 2007-01-05 关键字: apache mongrel

在Windows平台使用Apache2.2和Mongrel运行Ruby on Rails

一、安装Ruby、rails、mongrel和Apache2.2

从rubyforge网站下载One-Click Ruby Install,运行安装程序,就安装好了ruby和rubygems。

运行命令:
gem install rails –y
gem install mongrel –y
gem install mongrel_service -y
安装好了rails和mongrel

从Apache网站下载Windows版本的Apache2.2,运行安装程序,就安装好了Apache2.2。

二、把Mongrel作为Services启动

mongrel_rails service::install -N depot -c d:\Rubyproject\depot -p 3000 –e production


-N指明服务名称,-d指明rails应用的目录,-p是mongrel监听的tcp端口,-e是启动模式为生产模式

这样打开控制面版|管理工具|服务,就可以发现增加了一项名为“depot”的服务,就可以通过控制面版来管理服务了。如果需要命令行启
动和关闭该服务,那么:
mongrel_rails service::start -N depot
mongrel_rails service::stop -N depot

如果需要从服务中注销该项服务,那么:
mongrel_rails service::remove -N depot

如果需要安装多个mongrel实例,那么可以这样:
mongrel_rails service::install -N depot0 -c d:\Rubyproject\depot -p 3000 –e production
mongrel_rails service::install -N depot1 -c d:\Rubyproject\depot -p 3001 –e production
诸如此类。

三、配置Apache2.2

用编辑工具打开Apache2.2目录下面的conf/httpd.conf,需要取消如下模块的注释:
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_balancer_module modules/mod_proxy_balancer.so
LoadModule proxy_http_module modules/mod_proxy_http.so
如果你希望对页面输出使用压缩,也需要取消如下模块的注释:

第 70 / 283 页
http://robbin.javaeye.com 2.8 在Windows平台使用Apache2.2和Mongrel运行Ruby on Rails

LoadModule deflate_module modules/mod_deflate.so

然后按如下内容配置基于HTTP代理的负载均衡:
xml 代码

1. ProxyRequests Off
2. <Proxy balancer://myCluster>
3. BalancerMember http://localhost:3000
4. BalancerMember http://localhost:3001
5. </Proxy>
6.
7. <VirtualHost *:80>
8. ServerName www.xxx.com
9. DocumentRoot d:/rubyproject/depot/public
10. ProxyPass /images !
11. ProxyPass /stylesheets !
12. ProxyPass /javascripts !
13. ProxyPass / balancer://myCluster/
14. ProxyPassReverse / balancer://myCluster/
15. ProxyPreserveHost on
16. </VirtualHost>

myCluster定义了群集中的每个mongrel应用服务器节点。ProxyPass /images !指明该URL开始的请求不代理给Mongrel群集,而由


Apache自己处理。重起Apache,然后打开浏览器访问www.xxx.com,检查配置是否正确。

至此,在Windows Server上面一个具备良好稳定性和性能的Ruby on rails生产环境就搭建好了。

对于页面输出,还可以使用mod_deflate进行输出内容压缩,以提高页面下载速度,这个就留给大家自己配置了。

第 71 / 283 页
http://robbin.javaeye.com 2.9 ruby on rails应用性能优化之道

2.9 ruby on rails应用性能优化之道

发表时间: 2007-02-01 关键字: rails performance

这是一篇我们运营JavaEye网站将近半年时间所得到经验的总结。目前在整个rails社区,都极少有运营rails大访问量网站经验的人详细
的谈这个话题。至于国内,rails应用都停留在学习和尝试阶段,真正投入商业运营的基本找不到,所以谈这个话题为时太早,颇有对
牛弹琴的感觉。所以权当是个人的总结性文章吧,也不会很详细的展开谈论,能对大家有所启发就好。

一、硬件

1、CPU
ruby解析器相对于JVM,PHP解析器来说,比较低效,可能会导致比较多的context switch,因此提高CPU和内存之间的总线带宽和传输
速度会对ruby应用有比较大的性能提升。在目前主流的x86_64 CPU当中,AMD Opteron在CPU芯片内置内存控制器,可以有效提高CPU
和内存数据交换速度,提高context switch能力。所以用AMD Opteron比Intel Xeon EM64T性能要好很多。

2、物理内存
ruby是以进程方式运行的,rails应用的并发响应能力主要取决于ruby进程的数量。一个最简单的rails应用,一个ruby进程占用的物理内
存一般不过30-40MB,但是对于真正复杂的,而且数据库访问频繁,数据量大的rails应用来说,ruby进程稳定的物理内存占用至少100
多MB,经常达到200多MB,甚至300MB。以开10个ruby进程计算,那么物理内存使用上限就是3GB,所以4GB物理内存是起码的。

二、操作系统

1、Linux distro
对于AMD x86_64的CPU来说,SLES要比RHEL有更多的优化。

2、32位版本还是64位版本
应该使用64位版本操作系统,以充分发挥x86_64 CPU的性能,并且x86_64的Linux很多Kernel参数也大很多,代价就是需要更多的物
理内存。所以内存多多益善。

3、文件系统
rails会对每个浏览器会话在硬盘生成session文件,一个繁忙的网站,临时文件目录下面有上万乃至几万个session文件是很常见的现
象。对于这种目录下面几万个小文件的存取,reiserfs要比ext3性能好很多倍。

三、Web Server

主流的选择是apache2.2,lighttpd,litespeed。apache2.2可以首先排除,lighttpd和litespeed都不错,但我会选择开源免费的
lighttpd。至于lighttpd的各种优化参数这里不谈。

四、ruby的部署

1、ruby GC

第 72 / 283 页
http://robbin.javaeye.com 2.9 ruby on rails应用性能优化之道

可以使用railsbench提供的GC patch,以优化ruby内存使用,降低GC频率,提高throughput,代价就是ruby进程的物理内存占用加倍。
所以物理内存越多越好,4G根本不够用,8G,16G绝对不嫌多。

2、FCGI还是mongrel
ruby进程可以以FCGI方式来运行,以FastCGI协议和Web Server通讯,也可以以HTTP Server方式来运行(即Mongrel),以HTTP协议和Web
Server通讯,这两种方式性能上没有什么差异。FCGI方式,在单机上面通过Unix Socket和Web Server通讯,效率比走TCP Port要高。

3、开多少个ruby进程
ruby进程数量和web server的connection数量的比例没有定规,少了多了都会降低性能,要靠实践去摸索,也要参考CPU和内存资源的
使用状况。

五、应用程序

1、避免使用component

2、hash的key使用symbol

3、对于ORM来说,数据库的表设计的原则是颗粒度应该小一些,把常用字段和不常用字段尽量分离到不同表,严重影响性能的大字段
分离到单独的表

4、在不使用对象缓存的情况下,查询方法的:include可以预加载关联对象,避免n+1问题

六、缓存

1、rails的页面缓存,Action缓存和片断缓存
rails提供的缓存方式可以有效降低对应用服务器的负载,但是缓存颗粒度太粗,适应范围比较狭窄,缓存过期的处理比较烦琐。

2、对象缓存
rails应用本身是可以水平扩展的,性能瓶颈往往还是数据库访问,使用CachedModel对象缓存可以有效降低数据库负载,但
CachedModel不像Hibernate二级缓存那么强大,不能够针对非主键查询进行缓存读取,不能针对非主键查询进行缓存填充,和file-
column有冲突,需要自行覆盖model对象的save方法等等。另外在使用对象缓存的情况下,应该把查询方法的:include去掉,避免关联
查询无法利用缓存的现象。

3、查询缓存
对于统计类耗时查询,如果不要求实时性,那么可以使用memcache-client将查询结果缓存到memcached里面。

七、Session的存储方式

由于Linux文件系统的高效性以及操作系统使用内存来做disk cache,因此默认使用硬盘文件保存session,并不会带来性能瓶颈,使用
memcached并不会提高多少IO性能。如果一定要优化session硬盘读取,除了memcached,可以使用RAMDISK。

第 73 / 283 页
http://robbin.javaeye.com 2.10 rails项目为什么比Java项目好维护?

2.10 rails项目为什么比Java项目好维护?

发表时间: 2007-02-09

引用

Java程序你可以生成UML来读,可以很方便地navigate,这些便利在Ruby中享受不到。这是Ruby程序不好维护的一方面。

Java生成UML来读,但凡大一点的框架软件,UML图又大又复杂,根本看不出来头绪,这是不切实际的做法。

引用

另外一方面,由于语言本身的动态性,Ruby没有强大的IDE。这对接手维护的人来说确实是很头疼的一件事。

TextMate,Radrails,VIM对于编程的导航都很不错。但这不是最重要的。最重要的是rails项目的结构非常固定,每个文件也不大,该
写什么不该写什么,框架都框死了。维护的人其实很容易的,他只要熟悉rails,根本不看代码就知道哪部分代码应该在哪里,哪部分
功能在什么地方实现。这是rails相对于Java来说的一个很大的优势。使用Java,倘若你接手的项目使用的框架你没有接触过,那根本无
从下手,即使大家使用同样的框架,但是自己进行了高层的不同方式的封装,你想看出来头绪,仍然要费很大的力气,但对于rails来
说,不存在这些问题。

如果大家不信,我随便举两个例子。首先对比一下Java的开源博客软件roller,这是用struts/hibernate开发的,如果你能在一周之内彻
底搞清楚roller的全部结构,那我得承认你的Java编程水平在我之上;再看看rails的开源博客软件typo,我半天就可以把typo全部代码实
现细节全部都搞得清清楚楚。再来对比Java的开源论坛软件JavaBB,这个简单一些,但是结构也有一定复杂度,然后再对比rails开源
论坛软件rforum,哪个容易阅读,哪个更加容易维护,这是昭然若揭的事实。

所以,rails开发的项目要远比Java开发项目好维护,特别你招聘新员工来进行维护,两者差距拉得更大。

引用

用Java比较容易写得好维护,毕竟这么多年的积累有很多的best practice,甚至还从best practice发展出来工具、框架。而Ruby这方


面的积累还比较少,没有很多清楚的guideline来帮助你,也没有什么工具可以利用,一切都要靠自己

其实你说的正好相反,只要你不要太炫耀ruby的技巧,代码都是很好阅读的。rails编程为什么没有那么多模式和最佳实践,是因为rails
已经把模式和最佳实践做在框架里面了,已经全副武装了,你直接拿来就用了。反而是Java,就算有了Spring/Hibernate/Webwork照
样是在裸奔,没有代码生成机制,没有单元测试框架,没有测试数据设施,没有RESTFul URL机制,没有DB Migration,没有AJAX集
成,没有实现好的分页机制,没有做好的Mock对象,没有现成的页面模板和装饰器,一切都要靠自己。

第 74 / 283 页
http://robbin.javaeye.com 2.11 ActionController::TestSession的bug?

2.11 ActionController::TestSession的bug?

发表时间: 2007-02-12 关键字: rails test

我在看《Agile Web Development with rails》这本书第二版的单元测试这一章,其中在functional test这一部分,rails提供了一些模拟浏


览器请求的get,post等方法,其支持参数格式例如:

get :action, {params}, {session}, {flash}

然后这本书第202页给出一个指定Session的例子为:

def test_index_with_user
get :index, {}, {:user_id => users(:dave).id}
assert_equal(users(:dave).id, session[:user_id])
assert_response :success
assert_template "index"
end

但是实际跑这个测试,却发现程序无论如何拿不到session[:user_id],十分纳闷,在程序里面PP.pp session,发现TestSession对象的
属性@attributes{:user_id => 1}已经有了,但是就是拿不出来,奇怪,实在奇怪。

无奈只得去趴rails的ActionController::TestSession的源代码,终于在test_processor.rb里面找到,第291行:

def [](key)
data[key.to_s]
end

def []=(key, value)


data[key.to_s] = value
end

嗯,用string做key,没有提供用symbol做key的取法,于是把上面测试代码中get这一行修改,原来是:

get :index, {}, {:user_id => users(:dave).id}

现在改为:

get :index, {}, {"user_id" => users(:dave).id}

第 75 / 283 页
http://robbin.javaeye.com 2.11 ActionController::TestSession的bug?

测试程序顺利通过!

问题解决了,不过我不知道这算不算一个bug啊?大家说呢?我是不是应该提交一个issue过去啊?

第 76 / 283 页
http://robbin.javaeye.com 2.12 用block简化编程一例

2.12 用block简化编程一例

发表时间: 2007-02-15 关键字: block

block在ruby中被广泛的使用,即使是Java,spring也大量使用类似的概念来应用于template,但远远没有ruby好用。来看一个简单的应
用实例:

在ruby中自己调用memcache-client对费时的查询进行缓存,也就是自己实现的简单的查询缓存:

if RAILS_ENV == 'test'
@top_topic = TopTopic.get_topic
elsif @top_topic = Cache.get("TopTopic.get_topic")
Cache.put("TopTopic.get_topic",@top_topic, 60*30) if @top_topic = TopTopic.get_topic
end

先判断是否测试环境,如果测试环境,就略过缓存,直接读取数据库,如果不是测试环境,那么先取缓存,如果缓存里面有,就返
回,如果缓存里面没有,去查询数据库,查询数据库后,再判断是否查出来结果,如果没有结果就不填充缓存,如果有结果,就填充
缓存。

逻辑够复杂的,好在ruby语法够简洁,几行就搞定了,但饶是如此,每个QueryCache都这么写,就太难看了,也不符合DRY原则,于
是抽象出来一个QueryCache类:

class QueryCache
# Usage: QueryCache.get(key, timeout) { Model.find_method}
def self.get(key, timeout = 60* 30)
return value = yield if RAILS_ENV == 'test'
unless value = Cache.get(key)
Cache.put(key, value, timeout) if value = yield
end
value
end
end

于是所有的查询缓存可以简化为一行代码:

QueryCache.get("TopTopic.get_topic", 60*30) { TopTopic.get_topic }

第 77 / 283 页
http://robbin.javaeye.com 2.12 用block简化编程一例

这样查询缓存写起来就容易多了,完全屏蔽了复杂的逻辑判断,只要传cache的key,timeout和实际查询语句三个参数就搞定了。

第 78 / 283 页
http://robbin.javaeye.com 2.13 Windows平台的ruby IDE 点评

2.13 Windows平台的ruby IDE 点评

发表时间: 2007-03-05 关键字: IDE

在MacOS平台几乎没有什么争议性,大家都用TextMate。但是Windows平台可供选择和使用的IDE很多,却各有各的长处和短处。基于
我用过的所有ruby IDE点评一下。windows平台的RoR IDE主要分为两类:一类是重量级的全功能IDE,例如Eclipse,Netbeans,IDEA和
jedit,运行起来很耗资源,功能比较齐全;另一类是轻量级的IDE,例如Komodo,RoRed,vim,emacs,E,下面一一点评之:

一、重量级的IDE

1、radrails - 当前最值得推荐的IDE

radrails是基于Eclipse的插件,当前版本0.7.2。radrails继承了Eclipse平台的各种功能,尤其是CVS/SVN集成特别好,和其他ruby IDE
相对比来说,radrails最主要的优点在于bug很少,功能非常齐全。

1) 相对于其他大多数RoR IDE各种各样的bug,radrails在0.7.2版本的表现非常的稳定。在我连续几个月使用下来,基本没有什么大的
bug。

2) 功能齐全,其他IDE或多或少功能都有缺失,但radrails功能非常齐全:内置的server管理,generator,rake task,rdoc检索,plugin
安装,规则表达式校验,tail log,,console调试窗口,debug,代码格式化,代码和模板高亮,ruby代码和rhtml模板的template自动
提示,单元测试支持,代码和测试之间的跳转,代码和模板之间的跳转等等等无所不包。

3) 中文支持非常好,UTF-8编码支持也非常好。中文字体显示也很漂亮,这一点对我们来说很重要。

但是radrails也不是没有缺点,radrails的致命缺点是其RDT功能太弱智。

1) 代码的感知能力很差,连我敲一个def回车都不会自动补齐end。而且也不能够搜索ruby库文件进行语法树分析,所以没有智能提示
功能。

2) 没有像Eclipse的JDT那样的Ctrl+O来快速导航到某个方法的功能,这一点对我开发很重要,否则我就总是需要通过serch "def 方法
名"才能快速找到要修改的方法,非常不方便,这是我非常垢病RDT的一个地方,也没有F3快速导航到类定义文件的功能。

RDT下一个版本0.9.0号称在两周以后就会发布(RDT快两年没有推出新版本了,实在是太迟钝了),貌似对于脚本语言的AST解析能力大
大增强,如果真的是这样,还是很值得期待的,预计RDT0.9.0发布几周之后,radrails就会发布0.8版本。另外值得一提的是radrails得
到了SAP的一些赞助和支持。

2、Netbeans - 最值得期待的IDE

Netbeans6.0M7提供了Generic Language Support Framework,一个很强大的脚本语言框架,在这个框架基础上提供的ruby和ruby on


rails支持表现非凡。可以对ruby语言和库进行良好的语法分析,从而提供智能化的代码提示功能,让ruby程序员也可以享受到敲一个“.”
就能够跳出来详细提示的功能,真正有了写Java程序的安全感。有些优点确实很棒:

1) 代码感知能力超强,不但系统库的API,你自己项目的所有类API都可以根据上下文提示,有了写Java程序那种安全感了,也不用跳

第 79 / 283 页
http://robbin.javaeye.com 2.13 Windows平台的ruby IDE 点评

转来去找类定义文件了。

2) 快捷的打开rails库文件和ruby所有库文件,类似在Eclipse里面打开依赖库的源代码和JDK的源代码的功能,对于学习和熟悉ruby库和
rails非常非常有用。

3) Ctrl+G可以快速定位类定位文件,类似Eclipse的F3的功能。

目前netbeans这些功能领先所有的其他IDE,非常令人期待。但是netbeans也有些明显的缺点,有些东西用起来行为非常古怪,可能是
因为netbeans6.0还是beta版本,bug太多的缘故,而且也不够稳定:

1) 没有类似Eclipse的Ctrl+Shift+R那样的文件快速定位功能,要自己在项目树里面一层层找,这个实在令人难以忍受。一个大项目动不
动几百个文件,不能快速定位,找起来太影响效率。其实netbeans提供了一个Ctrl+Alt+O的快捷定位,但是不起作用,搜索框总是空
的,因此怀疑netbeans有这个功能,目前是bug导致出不来。

2) 没有在文件中快速定位某个方法的功能,这一点和radrails一样令人失望。

3) 在编辑器里面好多顺手的代码编辑的快捷功能都没有,令人很苦恼,这一点显然不如radrails那么方便。

4) 对中文的支持不好

5) 对yml文件没有高亮功能

6) 依赖JDK6.0,在JDK5.0上面跑很不流畅。

总得来说,netbeans还是最值得期待的IDE,等到07年底,netbeans6.0正式发布,ruby插件支持更加成熟以后,我想我会转移到
netbeans上面来。另外非常重要的一点:Sun公司从JDK6以后,致力于JVM平台化发展道路,大力拓展脚本语言在JVM平台的支持力
度,而且Sun给予了JRuby官方支持,所以netbeans平台的脚本框架和RoR支持是有足够的商业推动力的,前景应该是最好的!

3、IDEA - 观望中

貌似前段时间有人撰文推荐IDEA作为首选ruby IDE,我觉得他的理由很奇怪,其实IDEA目前不是好的选择:其ruby代码感知能力和智能
提示能力明显不如netbeans,其功能齐全程度又明显不如radrails,而且最致命的是IDEA竟然不能对rhtml模板高亮和提示,那就宣布了
IDEA的基本不可用,另外yml文件也不能高亮。其插件作者说下一版本会提供rhtml高亮和提示,所以我们对IDEA目前还持观望态度。

但IDEA也有一些明显优点,例如IDEA就有对ruby类和ruby资源进行快速定位的快捷键Ctrl+Alt+N和Alt+N,这明显优于radrails和
netbeans,另外也有在当前文件快速定位方法的快捷键,终于克服了我对radrails的最大怨气。

4、jedit - 貌似没什么理由去用它了

作为一个重量级IDE,却定位在轻量级功能上,要安装一大堆插件才能勉强把功能跑起来,没什么理由去用它。

二、轻量级IDE

1、E - 最值得期待的轻量级IDE

第 80 / 283 页
http://robbin.javaeye.com 2.13 Windows平台的ruby IDE 点评

E现在确实有很多bug,很多功能缺失,例如:我非常在意的对文件进行快速定位的快捷键和在当前文件中快速定位方法的快捷键,目
前E竟然不支持,但是TextMate可是有的;快速删除当前行在TextMate当中是Command+L,但是E貌似没有,诸如此类的功能缺失。所
以E和TextMate还是有很大差距的。

但是E确实在主要方面完全克隆了TextMate,所以这些小功能上面的缺失应该只是时间问题。所以相信给E半年左右的时间,E会成为
Windows平台当之无愧的TextMate。

2、Komodo - 乏善可陈

Komodo是个定位很传统的脚本IDE,对于ruby没有什么特别好的支持,有最基本的语法高亮和简单的代码提示而已,以及一个简陋的
项目树,运行速度还很缓慢,而且还是收费的,实在不值得去用。

3、RoRed - mini ruby IDE

如果你真要去用Komodo,那我建议你改用RoRed,一个专门针对ruby on rails开发的简单编辑器,带有ruby语法高亮,项目树,功能简
单,可能对某些偏爱UltraEdit/Editplus的人来说用RoRed已经够用了,速度也挺快的。

4、vim/emacs - 不适合Windows平台的ruby IDE

vim以及emacs这些源于Unix平台的IDE,我认为不适合在Windows上面用。因为vim/emacs当初被设计成为一个无鼠标支持的编辑环
境,全部依靠键盘命令驱动。当你在Windows下面使用的时候,这种习惯会被打破,从而觉得非常影响效率。

例如在vim里面执行一个generator,Unix上面会在vim窗口中开buffer显示,执行完毕敲一下回车就退出这个buffer了,很方便很快捷。
但在Windows平台,竟然会弹出一个DOS窗口,而且把键盘焦点给转移到这个DOS窗口上去了。这就迫使你不得不动用鼠标去选择这个
DOS窗口,然后关闭它,再把焦点定位回到vim上面来。这就丧失了vim最大的优势了,反而搞的很麻烦。

当然你可以用Alt+Tab键来切换窗口,不必动用鼠标。但遗憾的是Windows操作系统的窗口切换能力很差,一旦你的windows开的窗口
多了,在窗口之间快捷切换是一件很麻烦的事情,还不如鼠标来得快捷。这一点Windows比MacOS有很大的差距。MacOS上面进行多
窗口切换那才叫一个爽字呢!

最后我认为轻量级IDE在windows平台的市场不会很大,即使E的功能能够完善到TextMate的程度,也不会有radrails那么普及。主要还
是和操作系统的支持有关系:

在MacOS上面,你开一个Textmate窗口,一个浏览器窗口,一个tail log窗口,一个命令窗口启动关闭服务器,一个命令窗口进行
console调试,一个命令窗口执行单元测试,还有一个命令窗口连接MySQL数据库看数据。在这些窗口之间仅仅使用快捷键进行来回切
换是很方便很快捷的事情。

但是Windows的窗口切换功能太弱了,一下开了七个窗口,你编程的时候来回切换的工作效率是很低的。所以在Windows上面要提高工
作效率就会倾向于radrails这样的IDE,把所有功能都集成进来了,只要一个radrails窗口,一个浏览器窗口足矣了。这样工作效率才
高。

最后值得一提的是,所有这些IDE的rhtml编辑功能还是不如textmate,一旦在html标签里面嵌入代码段,就不能高亮了。而textmate是
不会这样的。

第 81 / 283 页
http://robbin.javaeye.com 2.14 RoR学习书籍推荐

2.14 RoR学习书籍推荐

发表时间: 2007-03-08

现在学习RoR的人越来越多了,ruby方面的图书也越来越多了,如何挑选合适的书籍,节省必要的学习时间就显得很重要了。可以这样
说,学习RoR编程只看这三本书就足够了,其他别的书统统不要去看了,省得浪费时间。

一、rails编程要看的第一本书《Agile Web Development with Rails第二版》

最经典的rails学习书籍,作者是ruby和rails社区的领导者之一。第二版中文版译者已经翻译好交出版社了,出版社什么时候上市还不清
楚。等不急的自己看英文版也不错,原作者的英文写的很易读。我自己在春节期间就把第二版英文版从头到尾读过了一遍。

二、rails进阶要看的第二本书《ruby for rails》

作者David A Black是ruby社区最资深的大佬之一。这本书的特色是专门针对rails用到的ruby知识进行剖析,很好的rails程序员进阶之
书。让你在了解如何进行RoR编程之后,再进一步搞清楚为什么要这样写,碰到新的需求,你应该怎么充分运用ruby和rails,不过这本
书一个缺点就是太罗嗦了,唯恐读者是白痴,很简单的问题都长篇大论的讲,看得人不耐烦。这本书中文版译者已经翻译好交出版社
了,却不知道为何出版社迟迟没有发行?

三、rails实战要看的第三本书《rails recipes》

作者Chad Fowler也是ruby社区最资深的大佬之一。这本书列举了100多个rails实战的各种问题的解决方案,适合在你用RoR开发项目的
时候,碰到相应问题去寻找相应的最佳实践。这本书还没有被引进国内。

第 82 / 283 页
http://robbin.javaeye.com 2.15 Robert C. Martin对RoR的高度评价令我吃惊

2.15 Robert C. Martin对RoR的高度评价令我吃惊

发表时间: 2007-04-02

先看CSDN上面Robert C. Martin博客中文版:

http://blog.csdn.net/rmartin/archive/2006/08/14/1064049.aspx

引用

从我目前看来,Rails是一个高产的敏捷环境,任何人都应该认真关注它。在我看来,因为Rails具有比Java或是.Net快达五倍甚至更
多的开发效率,一个Rails团队可以远远将Java和.Net团队抛之于后。我知道辩驳方会担心"E"这个词(译注7)。我的回应是:“如果
你不及时跟进,我觉得没什么问题,只要你不妨碍我们把事情搞定。”

作者简介:Robert C. Martin是Object Mentor公司总裁,面向对象设计、模式、UML、敏捷方法学和极限编程领域内的资深顾问。他不


仅是Jolt获奖图书《敏捷软件开发:原则、模式与实践》(中文版)(《敏捷软件开发》(英文影印版))的作者,还是畅销书
Designing Object-Oriented C++ Applications Using the Booch Method的作者。Martin是Pattern Languages of Program Design 3和More
C++ Gems的主编,并与James Newkirk合著了XP in Practice。他是国际程序员大会上著名的发言人,并在C++ Report杂志担任过4年的
编辑。

虽然我已经通过开发JavaEye从RoR得到了很好的回报,但是我仍然吃惊于一个软件行业的泰斗级人物竟然毫不掩饰自己对RoR赤裸裸
的喜爱。

还有这篇文章:

http://blog.csdn.net/rmartin/archive/2007/01/30/1497556.aspx

字里行间都是鼓吹RoR。

第 83 / 283 页
http://robbin.javaeye.com 2.16 ruby的方法调用作用域

2.16 ruby的方法调用作用域

发表时间: 2007-05-03

ruby的method作用域和Java一样,修饰词都有private,protected和public。其中public的含义都是一样的,但是private和protected却完
全不一样。这一点在《Programming ruby》当中语焉不详。今天看了《ruby for rails》第7章才搞明白了。

一、Java当中的含义:
private方法在Java当中的含义是只在当前类范围之内可以调用,当前类的子类也无法访问,但能被同一类别的其他对象实例调用,例
如:

package com.javaeye;

public class C {

private String name;

private String getName() {


return name;
}

public C(String name) {


this.name = name;
}

public boolean compare(C c) {


return this.name == c.getName();
}

protected方法在Java当中的含义是在当前类所在的整个package当中都可见,其他package类则无法访问;

二、Ruby当中的含义:
private在当前类以及子类都可以调用,其他类无法访问,比Java宽松一些,但private方法只能被当前对象隐式调用(self.),不能被同一
类别的其他对象实例调用,这又比Java严格;

protected稍微宽松一些,可以被同一个类别的其他实例调用,例如:

第 84 / 283 页
http://robbin.javaeye.com 2.16 ruby的方法调用作用域

class C
def initialize(name)
@name = name
end

def compare(c)
c.name == @name
end

protected
def name
@name
end
end

class D < C
end

d1 = D.new("fankai")
d2 = D.new("hello")

puts d1.compare(d2)

在类别C当中使用c.name,如果name方法是private的话,只能使用self调用,即只能当前对象实例在当前类范围内调用;如果name方
法是protected的话,那么可以使用同一类的对象实例显式调用,即可以引用其他对象实例的name方法。

因此private和protected的在ruby当前和Java的定义有很大的区别:

1、在不同对象实例当中的作用域不同
Java当中,不管private还是protected的方法,都可以被同一个类别的其他对象实例调用;
Ruby当中,private方法不能被同一个类别的其他对象实例调用;

2、在类继承关系当中的作用域不同
ruby当中,不管private还是protected方法,都可以被子类继承;
Java当中,private方法不能被子类继承;

这种方法调用的差异,也许来自于不同的面向对象理念:Java的面向对象来自C++,强调类继承关系,所以方法调用限定类继承的层次
结构当中的作用域,却不强调对象实例作用域;而ruby的面向对象来自smalltalk,即使是类别也是对象,因此方法调用作用域都是针
对对象实例调用来设置的。

第 85 / 283 页
http://robbin.javaeye.com 2.17 领略一下ruby的DSL能力

2.17 领略一下ruby的DSL能力

发表时间: 2007-05-05

在rails里面,我们可以用很方便的声明方式来定义model之间的关联关系,例如:

class Topic < ActiveRecord::Base


has_many :posts
belongs_to :user
end

那has_many和belongs_to究竟是什么东西呢?其实他们是Topic类的class method,标准写法是:

class Topic < ActiveRecord::Base


Topic.has_many(:posts)
Topic.belongs_to(:user)
end

那么has_many可以给我们带来什么呢?类方法has_many在被执行的时候,给Topic的对象实例添加了一系列方法:posts, posts<<,
orders.push......等等。所以当我们在model里面声明has_many,belongs_to等对象关系的时候,一系列相关的对象方法就被自动添加
进来了。

既然明白了rails的小把戏,让我们来自己试试看吧:

module M
def self.included(c)
c.extend(G)
end
module G
def generate_method(*args)
args.each do |method_name|
define_method(method_name) { puts method_name }
end
end
end
end

class C

第 86 / 283 页
http://robbin.javaeye.com 2.17 领略一下ruby的DSL能力

include M
generate_method :method1, :method2
end

c = C.new
c.method1
c.method2

我们定义了一个声明generate_method,可以接受多个symbol,来动态的创建同名的方法。现在我们在类C里面使用这个声明:
generate_method :method1, :method2,当然我们需要include模块M。为什么rails的model不需要include相关的模块呢?当然是因为
Topic的父类ActiveRecord::Base已经include了模块Associations了。

类C通过include模块M,调用了模块M的一个included回调接口,让类C去extend模块G,换句话来说就是,通过include模块M,来给类
C动态添加一个类方法generate_method。

这个generate_method被定义在模块G当中,它接受一系列参数,来动态创建相关的方法。于是我们就实现了这样的DSL功能:

通过在类C里面声明generate_method :method1, :method2,让类C动态的添加了两个实例方法method1,method2,是不是很有意


思?

实际上rails的对象关联声明也是以同样的方式实现的。

第 87 / 283 页
http://robbin.javaeye.com 2.18 railsconf2007大会介绍

2.18 railsconf2007大会介绍

发表时间: 2007-06-01

5月17日在美国波特兰举行了railsconf2007大会,在本次ruby on rails盛会,一众ruby社区大佬自然纷纷亮相,RoR作者DHH,Dave
Thomas,David A Black, Chad Folwer等等,连Robert C Martin也献身演讲。大会的演讲内容基本上集中在REST,RoR的部署,单元
测试等几个主题上来。大家可以下载大会演讲稿参考:
http://conferences.oreillynet.com/pub/w/51/presentations.html

大会照片:
http://www.flickr.com/photos/x180/sets/72157600225783815/

DHH主题演讲

Uncle Bob大叔也来啦

Dave Thomas

DHH的主题演讲是《A peak at Rails 2.0》,介绍rails2.0版本将要引入的新特性:

一、更好的REST功能支持
1、REST和AJAX更好的整合。可以在respond_to里面直接输出RJS了

2、ActiveResource将正式发布,ActiveReource是用来操纵REST资源的客户端API,可以像操纵本地ActiveReord model那样方便的操纵
远程的REST资源。

3、Action Web Services被拿下,有了ActiveResource和REST,还需要SOAP和Web Services吗?当然不需要了。

4、更强大的根据mime type来自动匹配不同的资源表象

5、HTTP Basic验证支持
可以根据客户端对资源的请求,要求客户端进行HTTP Basic验证,当然也可以进行智能判断,如果是程序或者RSS Reader访问,采用
HTTP Basic验证,如果是用户通过浏览器访问,则返回用户登录页面。

二、断点支持
可以在应用里面设置断点进行调试,还有调试语言。演示文稿里面写的太简略,我还没有搞明白是怎么回事?

三、静态资源的管理
1、在部署的时候,可以自动合并和压缩css文件和js文件,还可以设置cache,提高静态资源下载速度

2、更灵活的图片文件URL设置,把图片访问的URL分离到专门的图片服务器上面。

第 88 / 283 页
http://robbin.javaeye.com 2.18 railsconf2007大会介绍

四、Query Cache
嘿嘿,不用问,这是我非常希望rails添加的功能,rails终于内置缓存了,当然我还希望以后添加对象缓存,而不光是查询缓存。

五、初始化目录config/initializers
如果你现在希望在rails启动的时候执行特定的操作,那么你可以把初始化代码放在config/environments.rb里面,在rails2.0里面你可以
在config/initializers里面任意添加初始化文件。

六、更酷的DB Migration

create_table :people do |t|


t.first_name :type=>:string
...
end

或者

create_table :people do |t|


t.string :first_name
...
end

不用再写t.column.....了。

总的来说,rails2.0没有什么令人激动的新特性,主要的改动都是在rails1.2的REST功能上面的改进和完善。其他方面都是小修小补的
改进。

纵观整个railsconf2007,核心话题还是集中在REST的话题上。REST无疑将是整个RoR社区的热点话题。

第 89 / 283 页
http://robbin.javaeye.com 2.19 如何快速统计RoR网站的访问量

2.19 如何快速统计RoR网站的访问量

发表时间: 2007-07-03

统计网站的访问量有很多专业的第三方工具,例如Google Analytics,提供强大,而且详细的统计功能。当然,也许不是每个人都需要
这么复杂而且操作麻烦的工具,如果你只是需要大概了解一下网站的访问量和访问URL的比例,那么让我们看看最简单最容易的统计
工具:Unix Shell。

一个RoR网站的访问纪录,Web Server(Apache or lighttpd)会记录所有的访问请求,包括动态请求和静态请求,但大量图片,JS,CSS


的请求对我们没有太大的统计价值,因此web server的日志参考价值就不大。

RoR会记录所有动态请求日志到log/production.log里面,我们要做的就是让RoR进行日志交换,每天产生一个新的日志文件。很简单,
修改config/environment.rb

RAILS_DEFAULT_LOGGER = Logger.new("#{RAILS_ROOT}/log/#{RAILS_ENV}.log", "daily")

那么每天就会产生一个诸如production.log.20070702这样的日志文件。

一、统计每日动态请求处理总数

cat production.log.20070702|grep "200 OK"|wc -l

打印日志文件,挑选正确处理的请求行,统计行数,一条shell命令就搞定了网站处理的动态请求数量。虽然动态请求数量不等于网站
访问量,但是可以作为一个重要的参考指标。

二、统计URL的访问频度

网站管理员都很希望知道哪些频道受欢迎被访问的频繁,哪些URL格外受到关注,不必寻求专业的网站流量统计系统,一条shell命令
就搞定了:

cat production.log.20070702 |grep "200 OK" | awk '{print $17}'|sort|uniq -c | sort -r -n > stat.log

打印日志文件,挑选正确处理请求行,把第17列即URL那一列挑出来,排序,统计唯一URL出现的次数,按照URL次数倒序输出到
stat.log文件里面,让我们看看stat.log是什么:

第 90 / 283 页
http://robbin.javaeye.com 2.19 如何快速统计RoR网站的访问量

10096 [http://www.javaeye.com/]
3590 [http://www.javaeye.com/forums/index]
3446 [http://www.javaeye.com/forums/board/Java]
3300 [http://www.javaeye.com/index/rss_index_topics]
2477 [http://www.javaeye.com/forums/board/Life]
1605 [http://www.javaeye.com/forums/board/AJAX]
.........

网站首页被访问了10096次,论坛频道首页被访问了3590次,......

是不是很爽?我们用一条shell命令可以做简单的网站访问统计系统了。那么用Java做的系统,能不能这样统计呢?其实照样可以。你
可以在tomcat的配置文件里面设置输出详细的日志信息,然后照样用shell命令搞定。

第 91 / 283 页
http://robbin.javaeye.com 2.20 RoR的部署方案选择

2.20 RoR的部署方案选择

发表时间: 2007-07-06

RoR的部署方式从架构上来说分为前端和后端:

一、前端
前端的作用就是处理静态资源,将动态请求分发到后端,有时候也带有一些额外的功能,例如对特定URL进行rewrite和redirect,对
HTTP输出进行gzip压缩等等。

前端目前已知的可以选择apache, lighttpd, litespeed, nginx, haproxy

1、apache2.2
apache是全球市场占有率最高的web server,超过全球互联网网站50%的网站都用apache。apache2.2 + mod_proxy_balancer是一个非
常流行,非常稳定的方案。

使用apache2.2唯一的问题就是apache的性能和后面那些轻量级web server相比,差太远了。一方面在处理静态请求方面apache要比
lighttpd慢3-5倍,内存消耗和CPU消耗也高出一个数量级,另一方面mod_proxy_balancer的分发性能也不高,比haproxy差很远。

2、lighttpd
lighttpd是一个轻量级高性能web server,一个在MySQL Inc工作的德国人写的。性能很好,内存和CPU资源消耗很低,支持绝大多数
apache的功能,是apache的绝好替代者。目前lighttpd已经上升到全球互联网第四大web server,市场占有率仅此于apache,IIS和
Sun。

lighttpd唯一的问题是proxy功能不完善,因此不适合搭配mongrel来使用。lighttpd下一个版本1.5.0的proxy模块重写过了,将会解决这
个问题。

3、litespeed
和lighttpd差不多,商业产品,收费的。比lighttpd来说,多一个web管理界面,不用写配置文件了。litespeed专门为单机运行的RoR开
发了一个lsapi协议,号称性能最好,比httpd和fcgi都要好。他的proxy功能比lighttpd完善。

litespeed的缺点我却认为恰恰是这个lsapi。因为lsapi不是web server启动的时候启动固定数目的ruby进程,而是根据请求繁忙程度,动
态创建和销毁ruby进程,貌似节省资源,实则和apache2.2进程模型一样,留下很大的黑客攻击漏洞。只要黑客瞬时发起大量动态请
求,就会让服务器忙于创建ruby进程而导致CPU资源耗尽,失去响应。

当然,litespeed也支持httpd和fcgi,这个和lighttpd用法一样的,到没有这种问题。

4、nginx
一个俄国人开发的轻量级高性能web server,特点是做proxy性能很好,因此被推荐取代apache2.2的mod_proxy_balancer,来和
mongrel cluster搭配。其他方面和lighttpd到差不多。

要说缺点,可能就是发展的时间比较短,至今没有正式版本,还是beta版。没有经过足够网站的验证。

5、haproxy

第 92 / 283 页
http://robbin.javaeye.com 2.20 RoR的部署方案选择

就是一个纯粹的高性能proxy,不处理静态资源的,所有请求统统分发到后端。

二、后端
后端就是跑ruby进程,处理RoR动态请求了。运行后端ruby进程有两种方式:

1、fcgi方式
准确的说,不能叫做fcgi方式,其实就是启动一个ruby进程,让这个ruby进程监听一个tcp/unix socket,以fcgi协议和前端通讯。所以
fcgi不是指ruby进程的运行方式,而是ruby进程使用的通讯协议。这就好比你tomcat可以用http也可以使用ajp通讯一样,tomcat自己的
运行方式都一样的,只是通讯方式不一样。

fcgi方式启动ruby进程,可以使用lighttpd带的一个spawn-fcgi工具来启动(JavaEye目前采用这种方式)。

值得一提的是,apache2.2的mod_fastcgi的方式和上面还不太一样,由apache动态创建fcgi进程和管理fcgi进程,这种方式和litespeed
的lsapi面临的问题是一样的,此外apache的mod_fastcgi自己也有很多严重的bug,是一种很糟糕的部署方式。这种糟糕的部署方式也
败坏了fcgi的名声。

fastcgi只是一种协议,虽然古老,但并不是不好用,http协议也很古老。没有必要因为apache的mod_fastcgi的运行方式的问题而连带
把fastcgi都一同否定了。fastcgi只是一个协议(程序之间的语言),是apache的mod_fastcgi这个模块有问题。打个比方,有个人英语水
平很差,和你用英语对话,总是结结巴巴的,那你说是英语(fastcgi)这种语言有问题呢?还是和你对话的这个人(mod_fastcgi)有问题
呢?

2、http方式
也就是用mongrel去跑ruby进程,由于mongrel实际上已经是一个简单的http server,所以也可以单独作为web server使用。mongrel现在
越来越受欢迎了。

用fcgi方式还是http方式,我个人觉得区别不大,关键还是看应用的场合,一般而言,推荐的搭配是:

lighttpd + fcgi 或者 nginx +mongrel,而apache因为性能差距,而不被推荐。

JavaEye为什么用lighttpd + fcgi呢?原因如下:

1) lighttpd发展了好几年了,市场占有率也相当高,是一个经过实践检验的server,它的文档也很全;而nginx还没有经过足够的市场检
验,文档也很缺乏
2) JavaEye的ruby进程和web server在一台机器上面跑,通过unix socket使用fcgi协议通讯可以避免tcp的网络开销,其通讯速度比使用
tcp socket使用http协议通讯要快一些。

什么场合使用haproxy?

大规模部署,例如你的RoR应用到十几台服务器上面去,你用haproxy会更好,可以方便的添加删除应用服务器节点,proxy性能更好。

第 93 / 283 页
http://robbin.javaeye.com 2.21 Web开发敏捷之道(第二版)

2.21 Web开发敏捷之道(第二版)

发表时间: 2007-08-13

Web开发敏捷之道(第二版)

《Web开发敏捷之道(第二版)-应用Rails进行敏捷Web开发》这本书的中文版已经上市,关于这本书在RoR书籍市场的地位就不用赘
述了。有意思的是,这本经典的Ruby on rails教科书和我们JavaEye网站非常有缘分:

去年8月份,这本书第一版中文版上市的时候,正值我们使用Ruby on rails开发JavaEye2.0的关键时期,所以我毫不犹豫购买了三本,
开发团队人手一册,那个时候,我们开发团队也是刚刚开始学习Ruby on rails,所以的确帮了不少忙。今年8月份,这本书第二版中文
版也上市了,刚巧我们开发团队正在开发JavaEye3.0,这次是完全抛弃掉了JavaEye2.0的代码,彻底重写整个网站的代码,对代码质
量提出了很高的要求,所以也要求我们对Ruby on rails有很好的掌握,不出意外,这次还是人手一册。

这本书的第一版主要是针对rails1.0版本的,第二版是针对rails1.2版本而写,所以新的内容很多,有意思的是,我们JavaEye2.0和
JavaEye3.0的代码变迁也挺符合这本书两个版本之间的内容变动,第二版主要添加的内容有:

一、数据迁移

数据迁移功能是rails1.1版本引入的,非常受程序员的欢迎,去年我们开发JavaEye2.0的时候,rails1.1其实早就发布了,但当时第一版
没有这部分内容,我们也不清楚这个功能。所以数据库的维护都是直接通过数据库工具来修改表结构,但这也造成了一些问题:例如
开发环境添加了字段,但是生产环境忘记修改数据库,造成代码发布以后,网站频频报错的问题出现了好多次。

这次我们开发JavaEye3.0,就是完全使用数据迁移功能来维护数据库,可以杜绝问题的再次发生了,当然数据库的版本跟踪也方便了
很多。

二、REST支持

REST是rails1.2引入的功能,也是rails框架未来的核心功能,这次我们开发JavaEye3.0,就是按照REST的架构风格来设计和开发的。但
是第二版的REST功能介绍显得比较简略,不够详细,如果你的rails项目打算完全基于REST,那么可以参考一下beast开源项目,实际
上我们就是大量参考了beast的代码写法。

三、模型对象的多态关联

多态关联是ORM很有用处而且很有趣的一项功能,第二版详细介绍了rails的多态关联功能,例如JavaEye3.0当中,我们就使用多态关
联特性来实现帖子、博客、站内短信都可以带有附件这样的功能,也使用多态关联特性实现帖子、博客、评论都可以打tag这样的功
能。

四、assert_select和集成测试

我个人觉得assert_select是一项很伟大的功能。我们整天都说TDD、TDD……,但是web应用,你怎么TDD?测试能够覆盖到页面上去
吗?这在其他web开发当中是一个难题,但是assert_select就可以,而且完成的很漂亮,很简单。事实上,有了assert_select和集成测
试,类似selenium之类的外部测试框架完全可以退休了。

第 94 / 283 页
http://robbin.javaeye.com 2.21 Web开发敏捷之道(第二版)

五、其他的一些新内容

例如第二版里面增加了RJS和render :update功能,在JavaEye2.0里面,很多AJAX功能我们也是直接写prototype JS库的调用,现在基本


上都改成了render :update了;
第二版里面增加了发送HTML格式和带附件的email功能,这个也是我们目前很迫切需要的功能;
第二版里面增加了使用mongrel群集部署rails应用的内容,这部分内容恐怕是我们JavaEye3.0唯一不会采用的新内容。

第 95 / 283 页
http://robbin.javaeye.com 2.22 JavaEye3.0开发手记之一 - 我的开发环境

2.22 JavaEye3.0开发手记之一 - 我的开发环境

发表时间: 2007-08-16

JavaEye3.0的开发计划都喊了好久了,现在还刚刚开始,只完成了很少的一部分。为了3.0能够早日上线,我从这周开始把自己的大部
分时间投入了编码工作。借这个机会,我准备边开发JavaEye3.0,边写写心得体会,与大家交流和分享使用RoR开发一个互联网
web2.0网站的点点滴滴。

好了,开工!第一步就是搭建一个趁手的开发环境。我没有MacBook电脑,只有一台三年前买的IBM T40,跑MacOSX很勉强,还是在
WindowsXP上面做开发吧。既然在WindowsXP上面开发,那IDE选什么呢?我选netbeans Ruby IDE:

一、 RoR IDE

http://deadlock.netbeans.org/hudson/job/ruby/

你可以从这个地方下载Ruby IDE专用版本的netbeans,只有30MB大小,速度比RadRails还快!netbeans的RoR支持很强大,但也要注
意两点:
1) 一定要用JDK6.0,否则netbeans会很慢
2) 一定要修改JDK的字体文件,否则中文显示乱码(参考JavaEye论坛的dcaoyuan的帖子)
看我的截图:

第 96 / 283 页
http://robbin.javaeye.com 2.23 JavaEye3.0开发手记之二 - rails的UTF-8支持造成的正则表达式问题

2.23 JavaEye3.0开发手记之二 - rails的UTF-8支持造成的正则表达式问题

发表时间: 2007-08-22

rails的ActionView::Helpers::TextHepler模块提供了很多实用的方法,这些方法对于论坛类应用非常有用,例如auto_link这个方法可以自
动检测传入字符串当中的URL,并将其自动转换为HTML超链接格式,这对于显示帖子的内容来说很不错。

但是在开发JavaEye3.0的时候,却发现auto_link有bug,一旦帖子当中的URL后面紧跟中文的话,auto_link就会把URL后面所有的中文
当做URL的一部分进行格式化,直到碰到空格为止,例如:

引用

http://www.javaeye.com网站很不错

就会被格式化为:

引用

<a href="http://www.javaeye.com网站很不错">http://www.javaeye.com网站很不错</a>

看来得到rails的源代码里找答案了。

打开netbeans,敲快捷键Ctrl+O,在弹出窗口输入:texthelper,回车,netbeans已经帮我打开了text_helper.rb源代码,通过Navigator
窗口,很方便的定位到auto_link方法,仔细看一下,原来主要是这个正则表达式在起作用:

AUTO_LINK_RE = %r{
( # leading text
<\w+.*?>| # leading HTML tag, or
[^=!:'"/]| # leading punctuation, or
^ # beginning of line
)
(
(?:https?://)| # protocol spec, or
(?:www\.) # www.*
)
(
[-\w]+ # subdomain or domain
(?:\.[-\w]+)* # remaining subdomains or domain
(?::\d+)? # port
(?:/(?:(?:[~\w\+%-]|(?:[,.;:][^\s$]))+)?)* # path
(?:\?[\w\+%&=.;-]+)? # query string

第 97 / 283 页
http://robbin.javaeye.com 2.23 JavaEye3.0开发手记之二 - rails的UTF-8支持造成的正则表达式问题

(?:\#[\w\-]*)? # trailing anchor


)
([[:punct:]]|\s|<|$) # trailing text
}x unless const_defined?(:AUTO_LINK_RE)

但这个正则表达式上看下看,左看右看都没有啥问题阿。于是把这个正则表达式拷贝出来,放在一个ruby文件里面test.rb,一点点单独
调试,但怎么调试都正常,即使把上面那个URL放进去,也可以正常截断中文。

难道是因为rails做了手脚?为了验证这一点,在test.rb前面加上如下内容:

ENV["RAILS_ENV"] = "development"
require File.expand_path(File.dirname(__FILE__) + "/../config/environment")

再运行test.rb,果然!中文又被包括进去了,看来就是rails做了手脚。

再回过头仔细看这个正则表达式,只有[\w]和字符串处理有关系,为了验证这一点,我们做如下试验:

创建一个char.rb文件,内容如下:

def name
return "范凯"
end

请注意!该文件保存格式请必须使用UTF-8!!
然后打开irb,进行如下交互:

引用

irb(main):001:0> load "char.rb"


=> true
irb(main):002:0> name
=> "\350\214\203\345\207\257"
irb(main):003:0> name.match /[A-Za-z0-9_]+/
=> nil
irb(main):004:0> name.match /\w+/
=> nil

第 98 / 283 页
http://robbin.javaeye.com 2.23 JavaEye3.0开发手记之二 - rails的UTF-8支持造成的正则表达式问题

请注意标记为红色的行,在ruby的内存中,中文字符串的编码使用的是unicode格式,中文字符串不能够匹配到/[\w]+/上面去,而/[A-
Za-z0-9_]+/与/\w+/是同义词。

好了,现在启动rails的环境:

引用

$ ./script/console
Loading development environment.
>> load "char.rb"
=> []
>> name
=> "鑼冨嚡"
>> name.match /[A-Za-z0-9_]+/
=> nil
>> name.match /\w+/
=> #<MatchData:0x474693c>

哈哈,水落石出了!!由于rails的ActiveSupport的引入,在ruby的内存当中,字符串被转换为UTF-8格式了(显示乱码是因为我的
Windows操作系统是GBK编码),而中文字符串居然可以匹配/\w+/了!

我们可以看到,由于rails在内存当中以UTF-8格式操作中文字符串,而不是ruby默认的unicode格式,这就导致了正则表达式的歧义:/
[A-Za-z0-9_]+/不能匹配中文,但是/\w+/可以匹配中文,但实际上在ruby当中,这两个正则表达式本应该是同义词。

明白了问题的根源,就清楚了如何去解决auto_link的bug,修改正则表达式和相关方法,将\w替换为A-Za-z0-9,并将其放入你的rails项
目的application_helper.rb当中,这样就可以在项目启动以后覆盖rails系统类库的定义:

AUTO_LINK_RE = %r{
( # leading text
<\w+.*?>| # leading HTML tag, or
[^=!:'"/]| # leading punctuation, or
^ # beginning of line
)
(
(?:https?://)| # protocol spec, or
(?:www\.) # www.*
)
(
[-0-9A-Za-z_]+ # subdomain or domain
(?:\.[-0-9A-Za-z_]+)* # remaining subdomains or domain
(?::\d+)? # port

第 99 / 283 页
http://robbin.javaeye.com 2.23 JavaEye3.0开发手记之二 - rails的UTF-8支持造成的正则表达式问题

(?:/(?:(?:[~0-9A-Za-z_\+%-]|(?:[,.;:][^\s$]))+)?)* # path
(?:\?[0-9A-Za-z_\+%&=.;-]+)? # query string
(?:\#[0-9A-Za-z_\-]*)? # trailing anchor
)
}x unless const_defined?(:AUTO_LINK_RE)

def auto_link_urls(text, href_options = {})


extra_options = tag_options(href_options.stringify_keys) || ""
text.gsub(AUTO_LINK_RE) do
all, a, b, c = $&, $1, $2, $3
if a =~ /<a\s/i # don't replace URL's that are already linked
all
else
text = b + c
text = yield(text) if block_given?
%(#{a}<a href="#{b=="www."?"http://www.":b}#{c}"#{extra_options}>#{text}</a>)
end
end
end

OK,搞定了,这下auto_link可以正确截断中文了。

第 100 / 283 页
http://robbin.javaeye.com 2.24 JavaEye3.0开发手记之三 - 狮身人面

2.24 JavaEye3.0开发手记之三 - 狮身人面

发表时间: 2007-09-10

Sphinx的含义是“狮身人面像”,是古埃及的金字塔建筑,传说Sphinx是有翼的狮身女怪,她常叫过路行人猜谜, 猜不出者即遭杀害。

但是我这里说的Sphinx是一个高性能的搜索引擎:

http://www.sphinxsearch.com/

Sphinx是一个俄国人开发的搜索引擎,它的主要特点是:

一、性能非常出色
150万条记录一两分钟就索引完毕,2-4GB以内的文本检索速度不到0.1秒钟。ferret也望尘莫及,更不要说lucene了。

二、和数据库集成性很好
Sphinx通过配置文件可以自行读取数据库信息做索引,不依赖任何外部的应用程序,并且可以作为一个daemon进程启动,支持分布式
检索,并发响应性能很好。因此很多过去使用ferret的人因为并发检索的问题都改用Sphinx了。

三、可以做MySQL的全文检索
MySQL的数据库引擎是可插拔的结构,Sphinx开发了一个SphinxSE数据库引擎,可以在编译MySQL的时候直接编译到MySQL里面去,
这样的话,可以在数据库级别支持高性能的全文检索,那么你可以以如下SQL方式去全文检索了:

select * from xxxx where query='test;sort=attr_asc:group_id' AND ....;

很棒吧。

四、RoR支持也很棒
有一个acts_as_sphinx插件,类似acts_as_ferret,集成到RoR里面很简单。

Sphinx目前可能存在的问题估计还是中文分词问题:

Sphinx支持UTF-8编码的分词,但是他自己的文档上面说仅仅支持英文和俄文的分词,因此我估计对中文分词可能还不能很好的支持。

总之,Sphinx是我们另外一个很棒的选择。

第 101 / 283 页
http://robbin.javaeye.com 2.25 JavaEye3.0开发手记之四 - ruby的全文检索

2.25 JavaEye3.0开发手记之四 - ruby的全文检索

发表时间: 2007-09-28

在Java平台上面,lucene是众望所归的全文检索工具,lucene性能不俗,程序稳定,第三方扩展和分词算法众多,但是在RoR方面,就
没有那么幸运了,JavaEye网站要做全文检索,怎么来解决全文检索的问题呢?

在ruby平台上面,全文检索有三个途径:

1、solr, acts_as_solr

solr是apache开源组织的一个项目,完全基于lucene的最新版本,在lucene的上层提供了一个基于HTTP/XML的Web Services。solr的发
行包自己绑定了jetty6.0应用服务器,可以直接启动,成为一个独立的全文检索的web服务。

由于和solr的通讯方式是标准的基于HTTP的XML,所以你可以使用任何编程语言,Java,C++,Ruby,Python都不在话下。你通过向
solr发送xml查询请求,让solr在后台运行lucene,返回结果也被封装为xml,当然你也可以让solr去做索引。基本上solr就是lucene的一
个Web服务的封装。solr的优势在于为大规模的全文检索做了很多缓存优化,由于采用xml,也不限于客户端的种类。

RoR有一个叫做acts_as_solr的插件,封装了ruby对solr的访问,如果你喜欢用solr作为全文检索,acts_as_solr是一个不错的选择,他
可以很方便的让你的RoR应用添加全文检索功能,考虑到lucene的稳定性,这个方案是一个相当不错的选择。

但是这个方案的缺点也是显而易见的,你的RoR应用所有的全文检索都要依赖后台再次向solr服务器发送web请求来获取结果,单个页
面的执行速度肯定会受限于后台的跨http的web请求,这对于那些对全文检索功能依赖特别多的网站来说,恐怕很难接受。因此
JavaEye3.0不采用solr方案。

2、sphinx

http://robbin.javaeye.com/blog/122696

我已经在上一篇博客当中介绍了sphinx。我个人非常青睐sphinx这种独立的第三方全文检索服务器,而且能够和MySQL结合的很好,更
不用说其优异的性能了。但是sphinx的缺点在于没有很好的分词扩展的接口,它是一个纯C开发的服务。这对于中文分词功能的支持来
说,就很难实现了,因此不得不遗憾的放弃。

3、ferret

ferret是ruby平台模仿lucene的一个移植软件,但是ferret并非纯ruby实现,而是基本上用C编写而成,只有少量面向程序员的接口是ruby
写的。ferret虽然和lucene很像,连API也基本一致,但是ferret的成熟度远远不及lucene,这表现在:

1) ferret不支持中文分词
2) ferret用C编写的,其索引格式和lucene不兼容
3) ferret的索引速度很慢,而且很不稳定
4) windows平台的ferret在search的时候会崩溃

第 102 / 283 页
http://robbin.javaeye.com 2.25 JavaEye3.0开发手记之四 - ruby的全文检索

尽管ferret有上面这些缺点,但是RoR平台可供选择的余地却不大,因此还是决定使用ferret。

------------------------------ ferret 分割线 ------------------------------

1、acts_as_ferret (AAF)

AAF是一个相当不错的RoR插件,封装对ferret的操作,但是经过我的考察,决定弃用AAF。这是因为AAF是直接绑定到model上面的,这
会带来一些问题:

1) 每当model对象被insert/update/delete的时候,AAF会通过model的回调实时更新全文索引。在生产环境这是一个很可怕的事情,多
个ruby进程同时更新索引,就会出问题。所以AAF索性提供一个DRB方式的ferret server让你在生产环境去用。

但即便如此,如果多个ruby进程同时更新索引呢? 考虑到ruby的green thread性能,drb server也很容易就被阻塞住。而且退一步来


说,即便drb性能很好,每个全文检索请求都去发起一次ruby远程调用,恐怕也是很难接受的事实

2) AAF索引每条model记录,但我却不想索引隐藏贴,况且我的索引机制也不想绑定在model上面。

2、中文分词问题

如果只是简单的中文单字拆分,到不难支持,只需要利用RegexpAnalysis写个正则表达式去匹配UTF-8编码的中文就行了,目前JavaEye
的全文检索就是这样处理的,貌似搜索结果还过得去。

但是如果要追求非常精确的搜索结果,则必然需要通过词典的最大匹配算法去进行中文分词。那就只能自己用ruby来写中文分词算法
了,这个是留待我们今后要做的工作。

2、ferret的索引稳定性问题

JavaEye网站有8万topic,30万post,由于ruby本身性能不佳,ferret又不很稳定,在服务器上面直接做index,差点把服务器搞瘫了,所
以此路不通。

由于全文检索并不需要很高的实时性,所以我们的解决办法就是每天晚上把数据库数据下载到本地的台式机上面,然后在本地台式机
上面导入数据库,进行全量索引,然后在压缩打包上传到服务器上面去。这样每天的全文检索结果只会迟后一天的时间,基本上可以
满足需求了。

第 103 / 283 页
http://robbin.javaeye.com 2.26 Ruby on Rails 2.0的新特性介绍

2.26 Ruby on Rails 2.0的新特性介绍

发表时间: 2007-12-10

万众瞩目的Ruby on Rails 2.0已经发布了,Rails框架在2004年诞生以来,一直保持着相当快的版本升级速度:2005年发布了Rails1.0


版本,2006年初发布Rails1.1版本,2007年初发布Rails1.2版本,而还没有等到2008年,在2007年圣诞前夕的12月6日,Rails2.0已
经发布。

Rails框架每个大的版本升级都给我们带来了相当多的新功能,新惊喜。Rails1.0带给我们完善的单元测试和集成测试;Rails1.1带给我
们DataBase Migration和RJS;Rails1.2让我们看到了REST的光明前景,那么Rails2.0又将带给我们什么呢? 我粗略的翻译了一下Rails
框架作者DHH写的Rails2.0框架介绍文章,以下翻译自DHH的文章,原文在:

http://weblog.rubyonrails.org/2007/12/7/rails-2-0-it-s-done

在经过差不多一年的开发之后,Rails2.0终于发布了。这是一个棒极了的Rails版本,包括了大量堪称伟大的新特性,无数的bugfix和大
量功能的打磨。我们花了无数的精力去打造这样一个非常完美合理的软件包。

这也是Rails框架发展历史上的一个里程碑。我个人在Rails框架上面的开发工作已经有四年半的时间了,并且我们现在的贡献者也越来
越多。我对这几年我们所做出的工作和我们一直坚持的信念感到非常的满意。我们一直在坚持这一点并且不断推动它。

在详细的介绍Rails2.0之前,我要向那些为Rails框架做出过贡献的每一个人致以深深的谢意,不论是像一个家庭那样其乐融融的Rails
核心开发团队,还是成千上万的、而且年复一年为Rails提交补丁,积极参与Rails社区人们。Rails2.0也是大规模开源软件开发社区的
一个重大胜利,而你完全可以自豪于你在Rails社区当中扮演的角色和做出的贡献。干杯!

现在让我们简单的窥一斑见全豹的看看Rails的那些闪闪发光的特性:

Action Pack: Resources

Controller里面充斥着大量action方法的时代已经过去了,我们对REST架构的应用进行了大量的改进和提高。首先,我们不再使用分号
来隔离自定义的方法,而是采用斜线,例如原来是 /people/1;edit的URL,现在改成了 /people/1/edit.另外我们还对URL路由资源添加
了命名空间的支持,因此像后台管理的接口你可以像这样非常简单的定义:

map.namespace(:admin) do |admin|
admin.resources :products,
:collection => { :inventory => :get },
:member => { :duplicate => :post },
:has_many => [ :tags, :images, :variants ]
end

第 104 / 283 页
http://robbin.javaeye.com 2.26 Ruby on Rails 2.0的新特性介绍

这种方式可以让你按照如下的方式定义命名路由,例如:inventory_admin_products_url和 admin_product_tags_url等等。为了方便的记
录所有的路由规则,我们添加了一个rake任务叫做“rake routes”,它能够列举出来routes.rb定义的所有命名路由规则。

此外我们还引入了一个新的约定,即所有基于资源的controller默认都是复数形式的。这样即便单个资源在不同的路由规则中被多次引
用,仍然可以指向同一个controller来处理,例如:

# /avatars/45 => AvatarsController#show


map.resources :avatars

# /people/5/avatar => AvatarsController#show


map.resources :people, :has_one => :avatar

Action Pack: Multiview

与资源映射一起进行功能增强的还有MultiView。我们已经有了respond_to方法,但我们可以更进一步,把MultiView控制延伸到模板里
面去。我们现在可以根据模板文件的后缀格式来决定使用什么render机制。因此,show.rhtml你可以写成show.rhtml.erb,这就表明是
一个默认的rhtml模板,和你过去在Action里面使用respond_to声明的format.html是一个意思。此外你还可以使用诸如show.csv.erb,它
表明显示为csv格式的数据,并且使用默认的erb去render它。

所以,新的模板格式是: action.format.renderer。例如:
* show.erb: 不管什么格式的显示方式都使用默认的erb显示show模板
* index.atom.builder: 用Builder库来render XML文件,输出的文件类型为RSS的AOTM类型
* edit.iphone.haml: 使用用户自己定义的HAML render机制来输出模板内容到iPhone手机上面

说到iPhone手机,我们可以自己造一个专用的类型来实现内部路由。当你需要类似iPhone这样的特殊的HTML接口的时候,我们所要做
的就是:

# should go in config/initializers/mime_types.rb
Mime.register_alias "text/html", :iphone

class ApplicationController < ActionController::Base


before_filter :adjust_format_for_iphone

private
def adjust_format_for_iphone
if request.env["HTTP_USER_AGENT"] && request.env["HTTP_USER_AGENT"][/(iPhone|iPod)/]
request.format = :iphone
end
end
end

第 105 / 283 页
http://robbin.javaeye.com 2.26 Ruby on Rails 2.0的新特性介绍

class PostsController < ApplicationController


def index
respond_to do |format|
format.html # renders index.html.erb
format.iphone # renders index.iphone.erb
end
end
end

你完全可以在config/initializers/mime_types.rb里面注册自己的mime type类型的映射,这个文件默认已经提供了。

Action Pack: Record identification

为了驱使你使用基于资源的映射,我们对资源映射的controller和view的URL处理进行了大量的简化。我们添加了大量的命名约定,让你
可以直接把model对象转化为资源映射的路由,例如:

# person is a Person object, which by convention will


# be mapped to person_url for lookup
redirect_to(person)
link_to(person.name, person)
form_for(person)

Action Pack: HTTP Loving

如你所期望的那样,Rails2.0的Action Pack更加贴近HTTP,并且充分利用HTTP协议,例如资源、多种视图,还有更多的呢。我们添加
了一个模块来处理HTTP的Basic验证,它能够让授权的API轻松跨越SSL协议,而且他是如此的简单易用。下面是一个例子(更多的例子
请参考ActionController::HttpAuthentication):

class PostsController < ApplicationController


USER_NAME, PASSWORD = "dhh", "secret"

before_filter :authenticate, :except => [ :index ]

def index

第 106 / 283 页
http://robbin.javaeye.com 2.26 Ruby on Rails 2.0的新特性介绍

render :text => "Everyone can see me!"


end

def edit
render :text => "I'm only accessible if you know the password"
end

private
def authenticate
authenticate_or_request_with_http_basic do |user_name, password|
user_name == USER_NAME && password == PASSWORD
end
end
end

此外,我们也做了很多工作让你把JavaScript和CSS文件组织到一个逻辑单元里面去,而不需要让浏览器发起多次HTTP请求,分别获取
每个JavaScript和CSS文件,以便减少HTTP请求次数。使用javascript_include_tag(:all, :cache => true) 这个helper在生产环境下自动把
public/javascripts/目录下面的所有js文件打包到单个public/javascripts/all.js文件里面,但在开发环境下,仍然保持每个文件独立的修
改。

我们还添加了一些选项让,仅仅几行代码,就能够让浏览器去访问多台服务器上面的资源。如果你添加如下设置:
ActionController::Base.asset_host = “assets%d.example.com”,那么Rails框架就会自动的把静态资源的请求分发到多台物理服务器上
面去,例如分发到assets1.example, assets2.example.com, assets3.example.com等等。这样浏览器可以同时向多台服务器下载资
源,增加你的应用的访问速度。

Action Pack: Security

能够很简单的创建出来安全的应用总是一件令人愉快的事情,而Rails2.0提供了大量先进的功能来达到这一点。非常重要的是我们现在
提供了一种内建的机制来处理CRSF攻击。我们在所有的HTML表单和AJAX请求当中包含了一个特殊的token,而请求来自于其他的应用
的时候,你就可以检测到。所有的这些选项在新创建的Rails2.0项目当中默认就是打开的状态,对于你升级到Rails2.0的项目要打开这
一个选项也很容易,使用ActionController::Base.protect_from_forgery就可以了,详细的说明请看:
ActionController::RequestForgeryProtection。

对于允许用户在应用当中提交HTML代码的情况,防止XSS攻击现在也变得更加简单了。TextHelper#sanitize方法从过滤黑名单变成了
验证白名单。如果你已经使用了sanitize方法,你就会自动获得更好的保护。当然你也可以自行调整默认允许的HTML tag,请看
TextHelper#sanitize获取详情。

最后,我们还添加了“HTTP only cookies”支持,这一特性并不是所有的浏览器都支持,但是对于支持的浏览器你就可以派上用场了。

第 107 / 283 页
http://robbin.javaeye.com 2.26 Ruby on Rails 2.0的新特性介绍

Action Pack: Exception handling

大多数常见的异常都可以统一处理,而不是每个需要单独的处理。通常情况下,你只需要覆盖rescue_action_in_public方法,来进行统
一的异常处理即可。但是你也有可能需要使用自己的case语句来处理特定场合的异常。因此我们现在提供了一个类级别的宏叫做
rescue_from,你可以使用它来声明针对某个特定的Action来捕获异常,例如:

class PostsController < ApplicationController


rescue_from User::NotAuthorized, :with => :deny_access

protected
def deny_access
...
end
end

Action Pack: Cookie store sessions

Rails2.0默认的Session存储机制现在是基于Cookie的方案。Session也可以不必存储在服务器的文件系统或者数据库系统里面,而是以
ruby hash的格式每次作为cookie发送到客户端浏览器来保持。这样做不单单会比传统的服务器端保存Session的方式要快一些,而且完
全不需要维护。你不需要在服务器上面运行cron job任务来清理session文件,也不必担心因为你忘记清理session文件导致你的服务器
/tmp分区下面因为塞满了50万的session文件,从而让你的服务器crash掉。

如果你能够遵循一些最佳实践,保持session最小化,例如只在session里面存放user_id和flash信息,那么这种session机制就会很棒。
但是,如果你打算在session里面保存核弹发射代码的话,这一存储机制就不是一个好主意了。因为它们无法被加密(例如用户伪造
is_admin=true),它们很容易被用户看到。如果对于你的应用程序来说,这是一个必须注意的问题,那么你就应该使用传统的session
存储机制(但你首先应该先做一下调查)。

Action Pack: New request profiler

在一个真实的应用当中找出性能瓶颈是一个艰难的活,但有了我们新的request profiler,工作会变得简单很多。request profiler跟踪一


个完整的执行脚本,报告执行结果,你可以像这样来使用它:

$ cat login_session.rb
get_with_redirect '/'
say "GET / => #{path}"
post_with_redirect '/sessions', :username => 'john', :password => 'doe'
say "POST /sessions => #{path}"
$ ./script/performance/request -n 10 login_session.rb

第 108 / 283 页
http://robbin.javaeye.com 2.26 Ruby on Rails 2.0的新特性介绍

这样你就可以得到一份非常详尽的HTML和text格式的运行报告,每个步骤执行了多少时间,有了这个东西,你就可以很清楚的知道怎
样优化你的应用程序了。

Action Pack: Miscellaneous

还有一个值得一提的是AtomFeedHelper。它可以让你更容易的使用增强的builder格式来创建RSS输出,例如:

# index.atom.builder:
atom_feed do |feed|
feed.title("My great blog!")
feed.updated((@posts.first.created_at))

for post in @posts


feed.entry(post) do |entry|
entry.title(post.title)
entry.content(post.body, :type => 'html')

entry.author do |author|
author.name("DHH")
end
end
end
end

在Rails2.0里面,我们已经进行了大量的性能优化,因此对于helper的调用开销已经变得很小了,而且对于简单的命名路由,我们还使
用了cache,让它们能够执行的更快。

最后我们把in_place_editor和autocomplete_for这两个helper从Rails框架当中挪出去,放到了Rails官方SVN的插件目录下面了。

Active Record: Performance

ActiveRecord进行了无数的bug修复和少量的调整,但是仍然有一些值得一提的亮点。我们添加了一个非常简单的查询缓存,它能够在
同一个请求的过程当中记录相似的SQL调用,并且缓存查询结果。查询缓存对于那些很难用:include来解决的N+1次查询问题会非常有
帮助。另外我们也彻底提高了fixtures的性能,对于大多数常规的测试套件,性能提高了50-100%。

Active Record: Sexy migrations

现在我们有一种新的migration文件中声明的格式。以前我们是这样写的:

第 109 / 283 页
http://robbin.javaeye.com 2.26 Ruby on Rails 2.0的新特性介绍

create_table :people do |t|


t.column, "account_id", :integer
t.column, "first_name", :string, :null => false
t.column, "last_name", :string, :null => false
t.column, "description", :text
t.column, "created_at", :datetime
t.column, "updated_at", :datetime
end

而现在,我们可以这样写:

create_table :people do |t|


t.integer :account_id
t.string :first_name, :last_name, :null => false
t.text :description
t.timestamps
end

Active Record: Foxy fixtures

近来fixtures功能受到了很多抨击,对于fixtures的批评主要集中在fixtures之间声明的依赖关系上。在fixtures里面通过声明id属性来作为
主键,从而构造fixtures之间的关联关系是个郁闷的活。现在你可以通过这种方式声明和编写fixtures:

# sellers.yml
shopify:
name: Shopify

# products.yml
pimp_cup:
seller: shopify
name: Pimp cup

如上面所示,不再需要定义id属性,通过id来关联fixtures了,你现在可以直接使用fixtures的名字来建立关联关系。

Active Record: XML in, JSON out

第 110 / 283 页
http://robbin.javaeye.com 2.26 Ruby on Rails 2.0的新特性介绍

ActiveRecord支持XML的序列化已经有一段时间了。在Rails2.0当中,我们还添加了XML的反序列化功能,所以你现在可以这样用
Person.new.from_xml(“David“) 来获取person对象。当然我们也添加了序列化到JSON格式的功能,它和XML序列化的支持是一样的,还
可以支持关联关系的抓取,只需要写person.to_json就可以了。

Active Record: Shedding some weight

为了让ActiveRecord更加简洁和通用,我们把acts_as_list,acts_as_tree等acts_as_xxx功能挪出了Rails,放在了Rails官方的SVN插件
里面。如果你需要用到诸如acts_as_list的话,那么你需要安装这个插件,你可以./script/plugin install acts_as_list 来安装,安装好以
后,acts_as_list功能又回来了,用法没有任何区别。

更加激进一点的改动是我们把所有的商业数据库驱动全部挪到了外部的gem包里面。因此Rails2.0仅仅自带MySQL、SQLite和
PostgreSQL数据库驱动。这三个数据库是我们更加积极测试和支持的数据库。当然,这并非意味着我们排斥商业数据库,我们只是希
望它们能够在Rails发行版本之外保持自己独立的开发和发布计划。对于商业数据库来说,这其实是一件好事情,让厂商可以在基础版
本上面添加更多的异常和处理机制,使它们工作的更好。

所有的商业数据库驱动现在都放在gems包里面,符合如下命名规则:activerecord-XYZ-adapter。所以如果你安装了activerecord-
oracle-adapter包,那么这台机器上面所有的各种版本的Rails应用程序都可以访问Oracle数据库了,你却无需修改任何一行应用的代
码。

这种方式对于新的数据库驱动来说在Rails社区也可以更加方便的获得支持。只要你把数据库驱动安装命名规范打包成为gem,用户就
可以安装这个gem,立刻在Rails程序当中使用到它们了。

Active Record: with_scope with a dash of syntactic vinegar

ActiveRecord::Base.with_scope被劝阻使用以避免用户在controoler,特别是filter里面误用。现在我们鼓励用户仅仅在model里面使用这
种格式,这也是当初我们设计这项功能的初衷和保持一个良好实践的需要。当然,这仅仅只是鼓励和劝阻,如果你在衡量得失之后,
非要坚持在model之外使用with_scope的话,你尽管可以用这种方式来调用:.send(:with_scope)。

ActionWebService out, ActiveResource in

在SOAP和REST的争论当中,Rails选择坚定的站在REST这一边似乎不出人意料。如果你并没有集成其他异构系统需求的话,那么我们
强烈劝阻你使用SOAP。作为很自然的选择,ActionWebService现在并不在Rails框架的依赖当中,gem包仍然保留,但是这是一个重要
的信息,建议你尽量不用它。

与此同时,我们把新的ActiveResource包从beta版本升级挪入Rails框架之内。ActiveResource很像ActiveRecord,只不过面向的不是
model,而是资源。它有和ActiveRecord非常相似的API,并且可以和基于资源的Rails应用良好的整合。例如,ActiveResource提供了一
个vanilla scaffold,你可以参考。

ActiveSupport

ActiveSupport没有多少新东西,我们只是添加了大量新的方法,例如Array#rand可以随机取得集合的元素,Hash#except可以过滤掉不
想要的key和其他大量的Date类型的扩展。另外单元测试增加了一个assert_difference的便利方法。简而言之,仅仅是bugfix和调整。

Action Mailer

第 111 / 283 页
http://robbin.javaeye.com 2.26 Ruby on Rails 2.0的新特性介绍

Action Mailer有不少更新,除了一大堆bugfix之外,我们添加了一个选项可以注册可选的模板渲染机制,此外还给email的单元测试添加
一套assert_emails,例如验证邮件投递的数量:

assert_emails 1 do post :signup, :name => ‘Jonathan’ end

Rails: The debugger is back

为了更好的整合调试器,我们对Rails框架整体进行了一系列的改进。我最得意之作就是调试器的断点功能回来了,这不仅仅只是一个
类似irb dump那样的断点数据观测,而是一个真正的调试器。你可以单步前进、单步后退、列举当前位置等等。这完全得益于ruby-
debug这个gem包,所以我们推荐你安装这个gem包,然后Rails新的调试器就可以工作了。

如果你想使用调试器,那么首先安装ruby-debug这个gem包,然后把“debugger”命令写在你的应用程序当中,接着用-debugger或者-u参
数启动服务器,当代码执行到debugger命令的地方,你就可以在运行服务器的终端上面直接操纵应用了,完全不需要使用script/
breakpointer或者其他的什么东西。当然你还可以在单元测试当中使用调试器。

Rails: Clean up your environment

在Rails2.0之前的版本,config/environment.rb当中塞满了各种各样的启动配置信息和代码。现在你可以把这些东西分门别类的放在独
立的文件当中,然后把文件放在config/initializers目录下面,当Rails应用启动的时候,它们就会被自动的加载。新的Rails2.0应用自带
了两个这样的例子,分别是inflections.rb(定义你自己的单复数规则)和mime_types.rb(定义你自己的扩展类型)。我们鼓励你把启动配置
信息放在独立的文件里面,而不要去改动environment.rb文件。

Rails: Easier plugin order

现在我们开始把很多功能从Rails剥离出来放到插件里面去了,你也许有可能有一些其他依赖这些功能的插件。例如在你自己的
acts_as_extra_cool_list插件被加载之前,需要首先加载acts_as_list插件,因为acts_as_extra_cool_list扩展了acts_as_list。

在Rails2.0之前,设定插件的加载次序需要你在config.plugins里面列举所有的插件。这种做法主要的问题是当你仅仅需要acts_as_list
插件加载次序在前,而不关心其他插件加载次序的时候,未免需要多写太多东西。而现在你仅仅这样写就可以了:config.plugins = [
:acts_as_list, :all ]。

And hundreds upon hundreds of other improvements

上面我提到的这么多特性也仅仅只是Rails2.0的冰山一角。我们可以列举出来成千上万的bug修复、功能调优、新功能的添加。许许多
多的热情的贡献者不知疲倦的在各个细节上面改进Rails框架,但是这些工作都是非常重要的。

我希望你能够不介意麻烦去阅读Rails的CHANGELOG,了解更多的Rails2.0的改进。

第 112 / 283 页
http://robbin.javaeye.com 2.26 Ruby on Rails 2.0的新特性介绍

So how do I upgrade?

如果你希望升级到Rails2.0,那么你应该首先升级到Rails 1.2.6版本。它对于所有在Rails2.0当中被挪出去的功能给出了警告信息。如
果你的应用程序在Rails 1.2.6上面良好的运行,并且没有任何警告信息,那么你就可以升级到Rails 2.0了。当然如果你用到了Rails的
分页的话,你需要安装classic_pagination这个插件。如果你需要使用Oracle数据库,那么你需要安装activerecord-oracle-adapter这个
gem包,诸如此类等等等等。

第 113 / 283 页
http://robbin.javaeye.com 2.27 Ruby为什么会受程序员的欢迎?

2.27 Ruby为什么会受程序员的欢迎?

发表时间: 2008-01-07

孟岩最近写了一篇博客:

Ruby 1.9不会杀死Python

这篇文章很有点标题党的意思,所以在JavaEye论坛很快被水掉了,只好锁贴:

http://www.javaeye.com/topic/153651

但我个人对于孟岩的观点是不敢苟同的。首先我并不同意所谓魔幻语言和简约语言的分类。其实Martin Flower论述过这个问题,他是
用“人性化接口”和“最小接口”来区分编程语言的风格化差异的,请看这篇文章:

http://martinfowler.com/bliki/HumaneInterface.html

其实不用我多说,Martin论述的挺充分了。强把Ruby和C++归为魔幻一类,其实并不准确,因为Ruby的魔幻语法和C++相比,最大区别
在于:

C++的魔幻语法会导致代码的可读性变差,而Ruby的魔幻语法会导致代码的可读性大大提高。

不论是matz本人,还是整个Ruby社区,Rails社区诸多开源项目的作者,抑或整个Ruby和Rails开发者社区,在一个编程哲学问题上是高
度统一的,这就是:

强调程序员的快乐编程,追求人性化编程,在代码的可读性上面有偏执的追求,拒绝难以阅读的代码和难用的API。也就是所谓的
coding for fun!

所以你看无论是Rails,rake,rspec,甚至移植自lucene的ferret,都鲜明的体现出来这种特点,就是API简单好用,让你写的代码像英
文文章,自然流畅,轻松愉快。要是哪个Ruby框架的API复杂晦涩,在Ruby社区简直没法混,大家根本不买他的帐,这也是为什么Ruby
应用于DSL领域这么热的根本原因。

对于ruby程序员来说,这种追求编程人性化的哲学理念会潜移默化影响程序员,让他不知不觉把代码的可读性越写越好。对于程序员
来说,谁不想coding for fun呢? 而当你品尝到了coding for fun的乐趣,又怎么会轻易抛弃?

所以Ruby受程序员欢迎的根本原因还是在于它是一种能给你带来编程乐趣的语言。

第 114 / 283 页
http://robbin.javaeye.com 2.28 RoR网站如何利用lighttpd的X-sendfile功能提升文件下载性能

2.28 RoR网站如何利用lighttpd的X-sendfile功能提升文件下载性能

发表时间: 2008-01-12 关键字: x-sendfile

传统的Web服务器在处理文件下载的时候,总是先读入文件内容到应用程序内存,然后再把内存当中的内容发送给客户端浏览器。这
种方式在应付当今大负载网站,音频视频网站力不从心。sendfile是现代操作系统支持的一种高性能网络IO方式,操作系统内核的
sendfile调用可以将文件内容直接推送到网卡的buffer当中,从而避免了Web服务器读写文件的开销,实现了“零拷贝”模式。

作为最流行的轻量级Web服务器的翘楚,lighttpd提供了良好的sendfile支持,JavaEye网站服务器使用的就是lighttpd。在Linux操作系统
上面,只需要在lighttpd.conf配置文件如下配置,lighttpd就会使用sendfile方式处理静态资源的下载,效率非常高:

引用

server.network-backend = "linux-sendfile"

但是在某些情况下,我们却无法直接让lighttpd处理文件的下载,比方说JavaEye网站需要统计帖子附件的下载次数,博客相册的点击次
数,比方说需要对下载的文件进行权限的控制,特别是对于一些多用户系统,你不能让用户上传的私密文件被其他用户随便下载到,
例如JavaEye圈子的共享文件不能够对圈子外的用户开放下载。因此,文件下载目录千万不能放到public目录下,不能让用户直接通过
浏览器的URL地址访问到。在这种情况下,文件下载必须由服务器端应用程序来处理。

在RoR应用当中,我们可以在controller中使用send_file方法来控制文件的下载。send_file方法将下载的文件以4KB为单位写到一个输出
流去。如果我们使用mongrel应用服务器的话,mongrel会在内存当中创建一个StringIO对象,把整个下载文件完整的读入内存,然后再
向客户端或者前端的Web服务器写出。如果我们使用fcgi来运行RoR的话,fcgi会直接把输出流的内容向前端的Web服务器写出。

毫无疑问,我们可以看到这种下载处理方式有很大的性能缺陷:

1、当使用mongrel的时候,如果下载文件很大,会导致mongrel内存暴涨!

mongrel创建一个StringIO对象缓存整个输出内容,我们假设用户下载的是一个100MB的文件,该用户又很喜欢用多线程下载工具,他
开了10个线程并发下载,那么mongrel的内存占用会暴涨1GB以上。而且最可怕的是,即使当用户下载结束以后,mongrel的内存都不
会迅速回落,而是一直保持如此高的内存占用。这个缺陷非常容易被别有用心的黑客利用,攻击网站。这也是JavaEye网站为什么始终
不用mongrel的原因之一。

2、当使用fcgi的时候,如果前端Web服务器没有足够大buffer,会导致fcgi进程被挂住

fcgi自己不开output buffer,而是实时写出输出内容,如果前端Web服务器用的是lighttpd,那么你很幸运,lighttpd会照单全收,一个字
节都不拉下;如果前端Web服务器用的是nginx/apache,那么你很不幸,nginx/apache默认只开8K的buffer,收不下的那就对不起了,
您慢点嘞,fcgi进程就被挂住了,只要客户端浏览器下载不结束,fcgi进程就被一直占用。

3、即使使用lighttpd+fcgi,也会对服务器造成不小的性能开销

lighttpd+fcgi是最理想的Rails部署环境,JavaEye网站使用的就是lighttpd+fcgi。当ruby程序执行send_file开始下载的时候,fcgi会以4KB

第 115 / 283 页
http://robbin.javaeye.com 2.28 RoR网站如何利用lighttpd的X-sendfile功能提升文件下载性能

为单位读入文件内容,然后立刻写出到lighttpd去,而lighttpd照单全收。因此当下载文件被完整的通过fcgi被flush到lighttpd的内存里面
去以后,即使你杀掉fcgi进程,都丝毫不会影响文件下载。

也许你会问,lighttpd都吃下来文件内容,内存会不会暴涨?会的,我们假设同样的用户场景,某用户启动10个线程下载100MB的文
件,fcgi进程内存不会发生变化,但是lighttpd会暴涨1GB。但所幸的是lighttpd的内存管理的不错,一旦用户取消下载,或者下载完
毕,lighttpd立刻释放掉1GB的内存。

但是无论怎么说,ruby还是需要完整的读取下载文件,而lighttpd也需要开辟足够大的内存,处理整个文件的下载过程,对服务器开销
还是很大的。我们的问题是,能不能让带权限控制的文件下载像lighttpd下载静态资源文件那样快,开销那样小呢?答案就是X-
sendfile!

使用X-sendfile方式,服务器端应用程序不需要读取下载文件了,只需要设置response的header信息就足够了,此外还要附加一个信息
“X-LIGHTTPD-send-file”信息给lighttpd,告诉lighttpd,文件下载我就不管了,你自己看着办吧:

response.headers['Content-Type'] = @attachment.content_type
response.headers['Content-Disposition'] = "attachment; filename=\"#{URI.encode(@attachment.filename)}\""
response.headers['Content-Length'] = @attachment.size
response.headers["X-LIGHTTPD-send-file"] = @attachment.public_filename
render :nothing => true

X-LIGHTTPD-send-file告诉lighttpd,去硬盘的哪个路径找要下载的文件,最后一行啥都不输出了,下载不用ruby来管了。

而lighttpd收到X-LIGHTTPD-send-file信息以后,就会找到硬盘该文件,以静态资源文件的下载方式处理,丝毫不消耗lighttpd的内存。还
是以某用户启动10个线程下载100MB文件为例,10个fcgi进程发送了response信息就处理完毕了,而lighttpd知道下载的是硬盘的静态
文件,会以sendfile方式下载,文件内容就会被操作系统内核直接送到网卡的buffer里面,既不消耗ruby进程,也不消耗lighttpd,皆大
欢喜。

在lighttpd-1.4.18版本里面,fastcgi方式已经内置X-sendfile支持,仅仅需要你在配置文件打开就可以了:

引用

"allow-x-send-file"="enable"

这样我们就可以在RoR应用中使用X-sendfile飞速的下载文件了。但是慢着,免费的午餐有这么容易享用吗? 如果你已经按照我的介绍
进行了相关的配置,那么你会失望的发现,下载文件会出问题,无论多大的文件,下载到本地都只有1KB,怎么回事? 这是Rails一个
可耻的bug!经过我们努力的摸索和钻研,终于搞清楚的原因以及fix bug的方法,目前好像在互联网上面还搜索不到任何解决相关问题
的办法,那么我们提出的解决方案看来是首开先河了。

Rails的render机制在输出页面之前,会根据输出内容的长度来设置response信息的Content-Length,如果输出的内容是页面,这一步是
必须的操作。但如果是X-sendfile的话,我们在程序当中 render :nothing => true了,于是Rails就会错误的设置Content-Length为1KB

第 116 / 283 页
http://robbin.javaeye.com 2.28 RoR网站如何利用lighttpd的X-sendfile功能提升文件下载性能

(为什么不是0KB呢?这是因为render :nothing实际上输出一个空白或者回车之类的字符,又是一个可耻的问题!), 覆盖掉我们在程序


当中设置的Content-Length。而lighttpd在处理X-sendfile的时候也明显大脑进水,它不会根据硬盘文件的实际长度来确定Content-
Length,而是顽固的相信Rails告诉他的Content-Length就是1KB,最后我们会悲哀的发现下载文件只有1KB,而且是下载文件的第一个
字符。

为什么说这是Rails一个可耻的bug呢?因为这个bug已经被多次报告到Rails的Trac上面,但是直至最新的Rails2.0的SVN,仍然拒绝被
修复。所以这个世界没有无缘无故的爱,也没有无缘无故的恨,Mongrel作者Zed Shaw造反Rails社区是有原因滴。没有办法啦,我们
只好自己动手修复:

在我们的Rails项目的lib目录下面创建子目录action_controller,然后在这个子目录下面创建文件cgi_response.rb,文件内容如下:

module ActionController # fix rails X-sendfile bug!


class CgiResponse
def set_content_length!
@headers["Content-Length"] = @body.size unless @body.respond_to?(:call) || @headers["X-LIGHTTPD-send-file"]
end
end
end

打开了ActionController::CgiResponse类,覆盖掉set_content_length!方法,当reponse的信息当中包含X-LIGHTTPD-send-file的时候,避
免Rails覆盖我们的Content-Length设置。这样X-sendfile功能就可以正常使用了。然后在app/controllers/application.rb里面引入这个文
件:

require 'action_controller/cgi_response'

JavaEye网站在使用了X-sendfile功能之后,lighttpd的内存占用有明显的下降。未使用X-sendfile之前,lighttpd有时候内存占用会到
200MB以上(有用户多线程下载附件),在使用X-sendfile之后,lighttpd的内存占用还从未突破20MB。

最后要提醒大家几个问题:

1、lighttpd-1.4.18不认X-sendfile这个header,只认X-LIGHTTPD-send-file

按照lighttpd网站自己的文档,以及各种各样流行的X-sendfile文档,设置的header都是X-sendfile,但是经过我们n次失败的摸索,才发
现原来必须使用X-LIGHTTPD-send-file,这一点请不要被文档迷惑,目前好像也只有我们提出这个解决办法,互联网上面尚未看到其他
人提出过,看来我们又首开先河了。用RoR就是这点好,你动不动就得自己先去当尝螃蟹的那个人。

2、lighttpd-1.5.0版本的X-sendfile设置有所改变

第 117 / 283 页
http://robbin.javaeye.com 2.28 RoR网站如何利用lighttpd的X-sendfile功能提升文件下载性能

lighttpd-1.5.0版本还未发布正式版本,据说1.5.0已经认识X-sendfile这个header了,这个大家有兴趣自己测试吧。

3、Rails2.0版本仍然存在这个X-sendfile的bug

我们的fix方法目前是在Rails1.2.6上面编写的,针对Rails2.0版本应该也是有效的,但是我们还没有测试过,有兴趣的同学自己测试一
下吧。

第 118 / 283 页
http://robbin.javaeye.com 2.29 RoR部署方案深度剖析

2.29 RoR部署方案深度剖析

发表时间: 2008-01-14 关键字: deployment

RoR的部署方案可谓五花八门,有Apache/Fastcgi方式的,有Nginx/Mongrel方式的,还有lighttpd/Fastcgi方式,也有人使用HAProxy/
Mongrel,各种部署方式都是众说纷纭,让人搞不清楚哪种方式更好一些。我的这篇文章就是希望结合我们运营JavaEye网站一年多以
来的经验(通过统计Rails的production.log,JavaEye网站目前每天处理超过70万200 OK状态的Ruby动态请求,应该是国内目前负载量
最大的RoR应用了),为大家剖析RoR部署方案的优劣,帮助大家选择适合自己生产环境的RoR部署方式。

在讨论部署方案之前,先让我们看一下RoR网站部署的简单架构:

浏览器的HTTP访问请求首先达到Web服务器,充当Web服务器的一般是Lighttpd/Apache/Nginx,如果访问请求包含静态资源,那么
Web服务器就会直接从本地硬盘读取静态资源文件,例如图片,JavaScript,CSS等等,返回给客户端浏览器;如果访问请求是动态请
求,那么Web服务器把URL请求转发到后端的FastCGI/Mongrel来处理,等到FastCGI/Mongrel处理完请求,将生成的页面数据返回给
Web服务器,最后Web服务器把页面数据发送到客户端的浏览器。

从RoR的部署方式来看,主要由前端的Web服务器和后端的应用服务器构成:前端的Web服务器可以使用Apache,Lighttpd,Nginx和
Litespeed,后端的应用服务器可以使用FastCGI和Mongrel,下面我们分门别类的介绍和剖析:

一、介绍Web服务器
Web服务器的主要作用有两点:一是处理静态资源,二是将动态请求分发到后端应用服务器,然后接收后端应用服务器生成的页面数
据,将其返回浏览器,充当了一个信息沟通的桥梁作用,在本文当中我们重点分析后者的作用。

1、Apache 2.2

Apache是全球互联网使用最广泛的Web服务器,但在处理静态资源文件上却不是性能最优秀的Web服务器,不过一般情况下,静态资
源的访问并不是RoR网站的瓶颈,因此也不必过于在意这一点。

第 119 / 283 页
http://robbin.javaeye.com 2.29 RoR部署方案深度剖析

Apache 2.2既支持HTTP Proxy方式连接后端的Mongrel应用服务器,也可以通过mod_fastcgi/mod_fcgid来连接FastCGI应用服务器:当


以HTTP Proxy方式连接Mongrel的时候,Apache接收Mongrel返回的页面数据的buffer size最大只能开到8KB(默认是4KB或者8KB),因此
当页面数据超过8KB的时候,可能需要Apache和Mongrel之间发生多次交互;当以mod_fastcgi方式连接FastCGI应用服务器的时候,接
收返回数据的Buffer size仍然只有8KB而已,如果使用mod_fcgid,那么buffer size为64KB,有了很大的改善。

2、Nginx

Nginx是俄国人出品的轻量级Web服务器,在处理静态资源方面,据说性能还略微超过Lighttpd的10%,而且资源消耗更小。

Nginx内置了良好的HTTP Proxy和FastCGI支持,因此即可以连接Mongrel,也可以连接FastCGI服务器,在这两种情况下,Nginx默认的
接收应用服务器返回数据的Buffer Size也只有区区的8KB,但是你可以自行设置更大Buffer Size。

3、Lighttpd

Lighttpd是全球互联网排名第五的Web服务器,也是近两年来上升最快的Web服务器,特别是很受一些著名Web 2.0大网站的欢迎,例
如wikipedia的某些服务器,youtube的视频服务器,在国内,豆瓣网站和JavaEye网站都是Lighttpd的绝对拥护者。在处理静态资源方
面,Lighttpd性能远远超过Apache。

Lighttpd既支持HTTP Proxy连接Mongrel,也支持FastCGI方式,但是Lighttpd的FastCGI支持在所有流行的Web服务器当中可能是最优秀
的,所以用FastCGI的网站都很喜欢Lighttpd。Lighttpd在接收后端应用服务器返回数据的方式上和Apache/Nginx有非常大的区别:

Apache/Nginx是针对每个应用服务器连接分配固定Size的Buffer,而且默认只开8KB,这个Size对于现在网页动辄50-100KB的情况来
说,显得过于保守,如果应用服务器的返回数据无法一次填满Web服务器的Buffer,那么就会导致应用服务器和Web服务器之间多次数
据传输,这对于RoR网站的性能会造成一些相关的影响,我们在后面会详细的分析。

Lighttpd并不针对应用服务器的每个连接分配固定的Buffer,而是尽可能的把应用服务器返回的数据一次性接收下来,因此无论应用服
务器返回多大的数据量,Lighttpd都是照单全收,胃口非常惊人。

4、Litespeed

Litespeed是一个商业收费的Web服务器,静态资源处理能力据它自己的评测数据比Lighttpd略高。Litespeed也同时支持HTTP Proxy连接
Mongrel和FastCGI连接应用服务器。此外Litespeed专门为单机运行的RoR开发了一个lsapi协议,号称性能最好的RoR通讯协议,比
HTTP Proxy和FastCGI都要好。但是lsapi的运行方式有很大缺陷:因为lsapi不是web server启动的时候启动固定数目的ruby进程,而是
根据请求繁忙程度,动态创建和销毁ruby进程,貌似节省资源,实则留下很大的黑客攻击漏洞。只要黑客瞬时发起大量动态请求,就
会让服务器忙于创建ruby进程而导致CPU资源耗尽,失去响应。

由于Litespeed在运行RoR方面并没有表现出比Lighttpd优越之处,而且还是收费软件,企业版本售价在双核CPU上面每年收费499美
元,并且也不开源,因此我们就不再把关注点放在Litespeed上面。当然Litespeed收费也不是白收的,它提供了非常好用的基于Web的
服务器管理界面,以及非常多的安全性方面的设置参数。

5、HAProxy

HAProxy并不是一个Web服务器,他既不能处理静态资源,也不能充当浏览器和应用服务器之间的缓冲桥梁,他只是充当了一个请求分

第 120 / 283 页
http://robbin.javaeye.com 2.29 RoR部署方案深度剖析

发的软件网关作用。ThoughtWorks公司的RubyWorks选择使用HAProxy + Mongrel Cluster的方式来部署RoR应用,不能不说是一个愚蠢


的方案。这种方案其实相当于把n个Mongrel应用服务器捆绑起来,直接充当Web服务器,而Mongrel毕竟是一个Ruby写的服务器,无论
是网络IO能力,还是静态资源的处理速度,无法和真正的Web服务器相提并论,让Mongrel直接处理静态资源和调度网络IO,会造成服
务器资源毫无必要的极大开销,因此HAProxy也不在我们的考虑之列。

二、分析应用服务器的处理方式

无论是Mongrel还是FastCGI,都能够良好的运行Rails服务器,但是他们在和Web服务器之间的数据传输方式上存在一些差别,而正是
这些差别,对部署方式有重大的影响:

1、Mongrel

Mongrel本身可以直接充当Web服务器,但在这种情况下性能并不会好。因为Mongrel只有HTTP协议的解析部分是用C语言编写的,其余
所有代码都是纯Ruby的。在处理静态资源下载上面,Mongrel的实现方式非常低效率,他只是简单的以16KB为单位,依次读入文件内
容,再写出到网络Socket端口,其性能远远比不上传统的Web服务器调用操作系统的read()和write()库实现的静态文件下载速度,如果
和现代Web服务器实现的sendfile方式的“零拷贝”下载相比,简直就是望尘莫及。

Mongrel使用了Ruby的用户线程机制来实现多线程并发,并且使用了一个fastthread补丁,改善了Ruby用户线程的同步互斥锁问题。但
是Ruby并不是本地线程,我们也不要对Mongrel的网络IO负载能力抱有什么不切实际的幻想。同时Rails本身也不是线程安全的,因此
Mongrel在执行Rails代码的过程中,完全是加锁的状态,那和单进程其实也没有太大差别。

因此,当我们使用Mongrel的时候,一般会在前端放置Web服务器,通过HTTP Proxy方式把请求转发给后端的Mongrel应用服务器。在这
种情况下,Mongrel只处理动态请求,在运行Rails框架生成页面数据之后,把数据返回给Web服务器就可以了。但是在这种部署方案
下,有一个很重要的细节被我们忽视了,Mongrel运行Rails生成的页面数据是怎么返回给Web服务器的呢?通过仔细钻研源代码我们可
以搞清楚Mongrel处理Rails请求的细节:

1) Mongrel接收到请求以后,启动一个ruby线程解析请求信息
2) 加锁,调用Rails Dispatcher启动Rails框架
3) Rails处理完毕,创建一个StringIO对象,把Rails生成的页面数据写入到StringIO中
4) 解锁,把StringIO的数据flush到Web服务器

这个StringIO对象其实很重要!它充当了一个输出缓冲区的作用,我们设想一下,当Mongrel作为独立的Web服务器的时候,如果Rails
生成的页面比较大,而客户端浏览器下载页面的速度又比较慢,假设没有这个StringIO对象,会发生什么问题? Rails线程在执行render
方法的时候就会被挂住!同步互斥锁没有解锁,Mongrel再也无法处理下一个动态请求了。

当Mongrel仅仅作为应用服务器的时候,这个StringIO仍然很重要,为什么?我们前面提到过了,Apache/Nginx的接收缓冲区都只开了
8KB,如果页面比较大,Mongrel就没有办法一次性把数据全部推给Web服务器,必须等到Web服务器把接收缓冲区的8K数据推到客户
浏览器端以后,清空缓冲区,才能接收下一个8KB的数据。这种情况下,Mongrel必须和Web服务器之间进行多次数据传输,才能完成
整个Web响应的过程,显然没有一次性把页面数据全部推给Web服务器快。如果Web服务器使用Lighttpd的话,情况会不一样。当
Mongrel把StringIO的数据flush出去的时候,Lighttpd是一次性全部接收下来了,不需要多次交互,因此Lighttpd+Mongrel的RoR网站的
实际速度要快于Apache/Nginx+Mongel。

Mongrel使用StringIO对象缓存输出结果,在某些特殊的情况下会带来很大的安全隐忧。我们假设使用服务器端程序控制带权限的文件

第 121 / 283 页
http://robbin.javaeye.com 2.29 RoR部署方案深度剖析

下载,某用户下载的是一个100MB的文件,该用户使用了多线程下载工具,他开了10个线程并发下载,那么每个线程Mongrel在响应
之后,都会把整个文件读入到内存的StringIO对象当中,所以总共会创建出来10个StringIO对象保存10份文件内容,所以Mongrel的内
存会一下暴涨到1GB以上。而且最可怕的是,即使当用户下载结束以后,Mongrel的内存都不会迅速回落,而是一直保持如此高的内存
占用,这是因为Ruby的GC机制不好,不能够及时进行垃圾回收。

也许你会觉得不太可能下载100MB那么大的附件,但是以JavaEye网站为例,圈子的共享文件最大允许10MB,只要用户在多台机器上
面,每台机器开100个线程下载圈子共享文件,每个Mongrel的内存占用都会立刻超过1GB,用不了几分钟,服务器的物理内存就会被
耗尽,网站失去响应。这个缺陷非常容易被别有用心的黑客利用,攻击网站。这也是JavaEye网站为什么始终不用mongrel的原因之
一。

通过上面的剖析,我们知道Mongrel在使用Lighttpd的时候,可以达到最快的RoR执行速度,但是Lighttpd当前的1.4.18版本的HTTP
Proxy的负载均衡和故障切换功能有一些bug,因此一般很少有人会使用这种方式。大多数人都会采用Mongrel搭配Apache2.2或者
Nginx,但是正如我们上面做分析的那样,Apache/Nginx的Buffer Size实在是一个很讨厌的限制,特别是Apache只能最大开8KB的
Buffer,因此我建议使用Nginx搭配Mongrel,并且把Nginx的Proxy Buffer Size设置的大一些,比如说设置为64KB,以保证大多数页面输
出结果可以一次性flush到Web服务器去。

2、FastCGI

很多人对FastCGI谈虎色变,仿佛FastCGI就是内存泄漏,性能故障的罪魁祸首,又或者嫌弃FastCGI太古老了,已经被淘汰掉的技术
了,其实这是一个很大的误解。FastCGI本质上只是一种进程间通讯的协议,虽然是一个比较古老的协议,但是还是比HTTP协议年轻多
了,HTTP协议不是照样现在很流行吗?

在PHP/ASP/JSP流行之前,FastCGI曾经非常普及,只不过那个时代的FastCGI程序是用C语言编写的,写起来太费劲,而PHP/ASP/JSP
相比之下,写起来就太简单了,所以FastCGI就渐渐被丢到了历史的故纸堆里面。但是最近两年来,由于Ruby和Python的快速Web开发
框架的强势崛起,FastCGI仿佛又咸鱼翻身了。

当我们以FastCGI方式运行Rails应用服务器的时候,每个FastCGI进程都是单线程运行的,考虑到Rails本身不是线程安全的,所以和
Mongrel运行Rails的实际效果是一样的,都是每个进程只能跑一个Rails实例。但是FastCGI在Rails生成页面数据返回给Web服务器的方
式和Mongrel截然不同:

前面我们说到Mongrel自己开了输出缓冲区,而FastCGI则完全不开任何缓冲区,当Rails执行render方法的时候,FastCGI实际执行的是
FCGI::Stream.write方法调用,直接把数据写给Web服务器了。此时如果Web服务器是Apache/Nginx,会发生什么?

如果我们使用mod_fastcgi模块,那么Apache的接收缓冲区就是8KB;
如果我们使用mod_fcgid模块,那么Apache的接收缓冲区就是64KB;(mod_fcgid是中国人开发的取代mod_fastcgi的开源项目,在
Apache社区很受欢迎,谁敢说中国人只是开源“消费”国?)
如果我们使用Nginx服务器,那么默认的接收缓冲区就是8KB,但是可以改得更大;

如果页面数据比较大,超过8KB,会怎么样? FastCGI进程被挂在render方法上!必须等到Web服务器的缓冲区清空,把页面数据全部
接收下来以后,FastCGI进程才能结束本次Rails调用,处理下一个请求!所以千万别用Apache/Nginx搭配FastCGI应用服务器,否则你
的RoR应用会死的很难看。根据我个人的测试数据表明,同样的测试负载,Apache搭配70个FastCGI进程挂掉,但是Lighttpd搭配30个
FastCGI进程轻松跑完!

当FastCGI搭配Lighttpd的时候,我们知道Lighttpd会一次性照单全收FastCGI送过来的页面数据,所以FastCGI进程并不会被挂住。如果

第 122 / 283 页
http://robbin.javaeye.com 2.29 RoR部署方案深度剖析

我们对比一下Lighttpd搭配Mongrel和FastCGI会发现,Lighttpd搭配FastCGI性能最好,为什么呢?

Mongrel首先自己会用StringIO缓冲页面数据,然后推送给Lighttpd以后,Lighttpd也在内存当中缓冲了一份页面数据,造成了毫无必要
的double buffer的开销。这自然不如FastCGI不做任何缓冲,直接推给Lighttpd性能来得高,内存消耗少了。

我们的方案分析到这里,大家应该自己心里有结论了,Lighttpd+FastCGI是性能最佳,服务器资源消耗最少的RoR部署方案,事实上目
前RoR网站部署使用最多最流行的也是Lighttpd+FastCGI方式,而JavaEye网站,自然也是这种方式的部署。因此我们可以对各种方案进
行一个性能优劣的排队:

引用

Lighttpd+FastCGI > Lighttpd+Mongrel > Nginx+Mongrel > Apache+Mongrel > Ngignx+FastCGI > Apache+FastCGI

其中Lighttpd+FastCGI是性能最佳方案,而Apache+FastCGI是性能最差方案。

有些细心的同学可能会产生一个新的疑问?你说到底,之所以Lighttpd跑RoR性能最好,还是在于Lighttpd接收数据不限定缓冲区的大
小,而Apache/Nginx限定了缓冲区大小所至。那为什么Nginx要限制呢?Lighttpd如果不限制的话,会不会导致Lighttpd内存爆掉?

Nginx限制Proxy Buffer Size其实也有道理,因为Nginx并不是为RoR量身打造的Web服务器,Nginx最广泛的用途还是高负载大访问量的


代理服务器,在Nginx主要的应用场合,如果不做这样的限制,那Nginx端的资源消耗就相当高了,有可能会拖累所代理的服务速度。

Lighttpd主要用途之一就是提供高性能的FastCGI支持的Web服务器,所以必须为FastCGI量身打造。Lighttpd端承担的负载越高,就越能
有效的加快FastCGI执行速度。其实我们稍微心算一下,假设Lighttpd后面挂1000个FastCGI进程,每个FastCGI进程同时送过来50KB的
页面数据,Lighttpd就是全部吃下来,也不过只消耗50MB的内存而已,而事实上1000个FastCGI进程足以支撑每日上千万的大网站
了。

只有当我们使用服务器端程序控制大文件下载的时候,有可能造成Lighttpd内存暴涨,例如某个用户使用100个线程并发下载JavaEye圈
子的共享文件,在没有特殊处理的情况下,Lighttpd将全部吃下100个FastCGI进程送过来的10MB数据,就会立刻暴涨1GB的内存。这
种情况怎么办呢?其实我们也有办法让Lighttpd一点内存都不吃, 请看我写的另外一篇文章:RoR网站如何利用lighttpd的X-sendfile功
能提升文件下载性能

可能很多人看了我的文章,对结论觉得很诧异,既然Lighttpd+FastCGI这样好,为什么那么多人都推崇Mongrel,否定FastCGI呢?我
想,不外乎几个原因:

一、Lighttpd+FastCGI配置起来比较专业,而Mongrel配置简单

尽管我当初第一次搭建Lighttpd+FastCGI环境没费什么周折,但是我观察到非常多的Ruby程序员很难成功搭建一个Lighttpd+FastCGI的
环境出来,很多人连Lighttpd都无法独立的运行起来。这也许是因为很多程序员习惯了Windows开发环境,对于Unix上面通过源代码编
译安装的方式过于陌生造成的。而我从97年开始使用Unix,至今已有10年历史,因此搭建这样简单的系统,对我来说不造成什么障
碍。

而Mongrel就简单了,gem install mongrel安装完毕,mongrel_rails start启动,哪个人不会?毕竟绝大多数开发人员和部署人员不是高

第 123 / 283 页
http://robbin.javaeye.com 2.29 RoR部署方案深度剖析

手,他们熟悉哪种方式,自然就会推崇哪种方式。

二、Mongrel可以独立作为Web服务器运行,开发环境和部署环境统一

一般来说,程序员肯定是尽量保持开发环境和部署环境的一致性,避免部署到生产环境出现不测的后果。既然在开发环境熟悉了
Mongrel,当然更加愿意在生产环境使用Mongrel,而不愿意碰没有接触过的Lighttpd。

三、Mongrel支持HTTP协议,因此不论监控还是集成其他服务都比较简单,容易玩出更多的花活。

HTTP协议要比FastCGI协议普及的多,因此通过HTTP方式的监控工具,群集管理工具,集成其他服务的工具都是一抓一大把。而支持
FastCGI的第三方工具就少得可怜了。你要玩很多花活出来,用FastCGI的话,就难免得自己开发相应的工具,那当然不如使用Mongrel
方便啦。

最后,如果你看了这篇文章,想摩拳擦掌的安装一把Lighttpd+FastCGI的话,那么我的这篇文章就是最好的安装指南:

在Linux平台上安装和配置Ruby on Rails详解

第 124 / 283 页
http://robbin.javaeye.com 2.30 JavaEye网站的RoR性能优化经验谈

2.30 JavaEye网站的RoR性能优化经验谈

发表时间: 2008-01-20

JavaEye网站从2006年9月11日上线基于RoR的2.0版本开始,到现在已经运行了将近一年半了。在这一年半的时间里,JavaEye网站的
每日PV从最开始的5万,缓慢增长到了现在的60万。随着网站负载的不断增加,我们也在不断尝试和调整网站的性能,积累了不少第
一手RoR应用性能优化的实战经验。虽然我们并不是RoR性能优化的权威专家,我们所积累的经验也许并不是最优实践,但是作为国内
最早涉足RoR商业运营的互联网网站之一,我们非常乐意分享和交流我们的实战经验,以帮助后来者节省必要的摸索时间。

RoR惊人的开发速度恐怕是每个互联网创业者都梦寐以求的,但是随着网站流量的不断增大,可能大多数采用RoR的网站或迟或早会遇
到RoR的性能瓶颈,我的一个朋友capitian说过一句很有意思的话:“RoR应用做到后来,总有自己修改底层的冲动”。就我所了解和掌握
的情况来看,很多RoR网站都过早的遇到了性能瓶颈,一个很普遍的现象就是:RoR应用的CPU负载要远远高于数据库的负载。这是一
个有点违背常理的现象,因为我们知道,硬盘IO速度要比内存慢得多,所以一般Web应用的性能瓶颈往往会出现在数据库IO上,因此优
化数据库访问,进行对象缓存是非常有效的性能优化手段。但是一旦应用服务器负载比数据库还高的话,单纯的对象缓存就无用武之
地了。下面我们从几个方面分别谈一谈如何进行RoR的性能优化:

应用的部署
RoR应用的部署包括操作系统,Web服务器,应用服务器和数据库四个方面:

一、操作系统

1、发行版本

RoR适合于部署在Unix类操作系统上面,通常比较多的人使用RHEL/CentOS/Ubuntu,我们比较偏爱SuSE Linux,对于我们服务器使用
的AMD Opteron x86_64的CPU来说,SLES要比RHEL有更多的优化。另外应该尽量使用64位版本操作系统,以充分发挥x86_64 CPU的
性能,并且x86_64的Linux很多Kernel参数也大很多,代价就是需要更多的物理内存。

2、文件系统

Linux最常用的文件系统是ext3,但我们使用的是Reiserfs文件系统。Reiserfs在读写大量小文件的目录性能非常高,即使处理目录下面
直接存放10万个文件,性能仍然不会下降。我们知道默认情况Rails会对每个浏览器会话在硬盘生成session文件,一个繁忙的网站,
临时文件目录下面有上万乃至几万个session文件是很常见的现象。对于这种目录下面几万个小文件的存取,reiserfs要比ext3性能高一
个数量级。如果希望对session文件有更好的存取性能,可以把临时目录链接到Linux的内存文件系统/dev/shm目录下面,这样实际上
session文件的存取都是直接内存操作了,这种方式唯一的问题在于不能支持群集部署。如果你已经升级到了Rails2.0,可以采取把
session保存到Cookie里面的方式,既可以避免服务器处理session的开销,而且还支持群集部署,是大规模网站部署的首选方式。

3、内核的网络参数调整

对于流量很大的网站来说,默认的Linux内核网络参数偏小,因此如果你的网站流量非常大,或者上传下载大文件比较多,可以针对性
的调整内核网络参数,扩大内核的TCP接收数据和发送数据的Buffer缓冲区大小,比方说:

引用

第 125 / 283 页
http://robbin.javaeye.com 2.30 JavaEye网站的RoR性能优化经验谈

net.core.rmem_default=262144
net.core.wmem_default=262144
net.core.rmem_max=262144
net.core.wmem_max=262144
net.ipv4.tcp_rmem=4096 65536 524288
net.ipv4.tcp_wmem=4096 65536 524288

参数具体调整,可以Google相关的Linux内核参数的文档,这里不展开详谈。

二、Web服务器

Web服务器首选Lighttpd,因为Lighttpd在和后端的应用服务器通讯方式上做了足够的优化:当POST大数据量的时候,Lighttpd在完整的
接收客户端浏览器的数据之后,才会一次性发送给应用服务器;同样的,Lighttpd也是一次性把应用服务器处理的页面数据全部接收,
不设置Buffer Size的限制。因此Lighttpd能够尽最大可能的减轻应用服务器的负担,减少应用服务器用于处理数据传输的延迟,更加有
效的利用应用服务器资源。这方面的详细的论述请看:RoR部署方案深度剖析。

关于Lighttpd的安装可以参考在Linux平台上安装和配置Ruby on Rails详解,这里仅谈Lighttpd的性能优化的几个要点:

1、网络IO调度方式
Linux Kernel 2.6支持sysepoll方式调度网络IO,能够处理极高的并发连接请求,Lighttpd可以通过配置文件打开sysepoll支持:

引用

server.event-handler = "linux-sysepoll"

2、网络IO传输方式
Linux Kernel 2.6支持sendfile方式传输数据,Lighttpd可以通过配置文件打开sendfile支持:

引用

server.network-backend = "linux-sendfile"

此外Lighttpd还支持应用服务器参与的文件下载控制X-sendfile,详细的论述请看:RoR网站如何利用lighttpd的X-sendfile功能提升文件
下载性能

3、文件状态缓存
Lighttpd通过stat()调用获得文件被修改的信息,来决定当请求同一个静态文件资源的时候,是否需要再次读取硬盘文件。但是每次
stat()调用也有一定的开销,Lighttpd支持通过Fam Server来减少stat调用。即每次当文件被修改之后,Kernel会发送一个消息通知Fam
Server,而Lighttpd会通过进程间通讯连接Fam Server,可以知道文件是否被修改的信息,不必再每次调用stat()。

引用

server.stat-cache-engine = "fam"

第 126 / 283 页
http://robbin.javaeye.com 2.30 JavaEye网站的RoR性能优化经验谈

4、限定POST Size
为了避免黑客恶意的攻击服务器,伪造超大Post数据包轰炸Web服务器和应用服务器,可以限制Request请求的大小,例如限制为
10MB:

引用

server.max-request-size = 10240

5、日志文件
Lighttpd是单进程单线程的服务器,调度网络IO性能是极高的,但是在某些极端情况下,单进程服务器也有风险,即一旦被某操作系统
调用挂住,整个服务器就没有办法响应请求了。比方说服务器其他进程导致的IO WAIT很高,操作系统的buffer又不够的时候,Lighttpd
在大量的写access log就有被挂住的可能性。因此如果Lighttpd日志对你的参考价值不大,可以考虑关闭掉。像JavaEye网站每天
Lighttpd产生430万条log,对硬盘IO也是一个不小的负担,既然已经开着Rais的production.log,那么Lighttpd的access log没什么参考价
值了,那就关掉它。

Lighttpd的性能优化请看其作者写的文章:
http://trac.lighttpd.net/trac/wiki/Docs%3APerformance

三、应用服务器

Ruby的应用服务器可以使用FastCGI,或者Mongrel,如果我们使用Lighttpd的话,FastCGI是最好的搭配。

1、FastCGI和Lighttpd的通讯方式

如果FastCGI和Lighttpd是在同一台服务器,那么建议采用Unix Socket通讯,这种通讯方式比TCP要快一些,FastCGI可以通过Lighttpd自
带的spawn-fcgi命令行工具启动,创建socket文件,而Lighttpd监听socket文件。如果两者不在同一台服务器,需要群集部署,那就必
须采用TCP Socket通讯,方式是一样的。

2、FastCGI进程应该开多少个合适?

Rails是单进程方式运行的,理论上来说,开几个FastCGI进程,就只能并发响应几个请求。对于繁忙的网站来说,峰值期间每秒有几十
个动态请求是很正常的事情,但实际上FastCGI进程并不需要开那么多。这是因为前端的Web服务器在处理用户浏览器连接,发送
Request请求需要相当长的时间,在FastCGI处理完请求释放该连接以后,Web服务器还需要相当长的时间才能把页面数据完整的发送
到客户端浏览器。用户在点击一个链接以后,等待1-2秒,页面内容就显示出来,这对用户的感觉来说已经是非常快的了,而FastCGI
用于处理该请求可能只需要0.1秒,那么一个FastCGI进程虽然并不能够真正的并发运行,但实际上的效果是他可以在1秒之内处理10个
请求,让10个用户在同时访问网站的过程当中感觉不到明显的延迟。

因此FastCGI需要开多少个,取决于你的网站峰值期间每秒有多少个用户请求过来,而你的FastCGI又能够以多快的速度处理请求。比
方说你的网站峰值期间每秒有50个动态请求,FastCGI在峰值期间处理每个请求需要0.2秒,那么实际上你只需要开10个FastCGI进程就
足够了,为了应付突发的峰值请求,你可以在这个计算量上面增加一些余量,比方说15-20个进程,肯定是绰绰有余了。

第 127 / 283 页
http://robbin.javaeye.com 2.30 JavaEye网站的RoR性能优化经验谈

关于FastCGI的性能优化,可以参考Lighttpd作者的文章,虽然他是针对PHP跑FastCGI写的,但对RoR也有参考价值:
http://trac.lighttpd.net/trac/wiki/Docs%3APerformanceFastCGI

四、数据库

JavaEye网站使用MySQL5.0.XX版本,数据库引擎是InnoDB。关于MySQL数据库的调优,推荐大家看MySQL Performance Blog,作者是


一个MySQL性能调优方面的专家,并且提供MySQL咨询服务。他的博客上面有很丰富的关于MySQL调优的文章和演讲文稿,特别是关
于InnoDB方面,非常深入。JavaEye的数据库调优就是根据他的InnoDB演讲文稿来调整的,一般说来,有几个需要调整的参数:

innodb_buffer_pool_size
这个参数很重要,越大越好,对于专用的数据库服务器一般建议开服务器内存的50%以上。

query_cache_size
查询缓存,对于查询的性能提高有很大帮助,但不宜开得过大,查询缓存的过期可能很频繁,过大查询缓存反而降低性能,增加服务
器开销

innodb_flush_method = O_DIRECT
针对InnoDB的数据文件,关闭操作系统的文件缓冲,由于InnoDB自己有巨大的Buffer Pool,操作系统对文件的读写缓冲功能反而会降
低MySQL的InnoDB的IO性能。

最后针对数据库的SQL优化来说有两点原则:

1、对数据库表要适当的创建索引
特别是出现在where查询条件当中字段,和关联查询当中的外键,要高度注意。

2、尽量避免大表的全表扫描和数据库的硬盘IO
查询比较慢的SQL要explain一下,看看是否发生了全表扫描,采取各种措施减少或者避免大表的全表扫描问题,例如拆分表等等。

最后针对MySQL数据库运行情况,我们可以用show status; 和 show innodb status\G 来监测。

Rails应用程序的优化
Rails应用程序优化包括ruby解析器的优化,缓存的使用,以及应用代码级别的优化。Stefans Kaes曾经在Railsconf 2006有一个Rails应
用程序优化的演讲,他的演讲PPT是极好的Rails性能优化指南,可以在这里下载:http://www.javaeye.com/topic/24508。他还编写了
一个用于Rails性能测试的软件包RailsBench,大家可以参考。由于Stefans Kaes的代码优化文档已经写的非常详细了,因此我就不在
一一复述,只提出几点对性能影响比较大的方面:

一、ruby解析器的优化

第 128 / 283 页
http://robbin.javaeye.com 2.30 JavaEye网站的RoR性能优化经验谈

ruby的解析器性能是很糟糕的,ruby早期的主要用途是取代perl写批量处理的脚本的,并不是为服务器应用编写的,因此在内存分配策
略上非常不适合服务器应用。Stefans Kaes编写了一个ruby GC的补丁文件,在railsbench下载包里面提供了。虽然当前Railsbench提供
的GC补丁只有针对ruby 1.8.4和1.8.5版本的,但是在ruby 18,6上面使用1.8.5的GC补丁也完全没有问题。GC补丁的作用主要是针对
Rails应用开大了ruby的内存堆,可以有效提高内存堆的利用率,降低GC的频率。根据Stefans Kaes提供的测试数据,打补丁并且调整
参数以后,GC的频率下降到只有原来的1/10还不到。降低GC频率尽管并不能够提高单个请求的执行速度,但是可以增加整体应用的
负载能力。

我们在JavaEye的服务器上也使用了GC补丁,并且根据推荐参数进行了调整。在使用GC补丁之后,Web服务器的CPU负载下降了大概
15%左右,效果非常显著。当然开大内存堆的代价就是ruby进程会多消耗内存,在我们的服务器上,ruby打补丁之后多消耗了50%左右
的物理内存。

二、缓存的使用

1、对象缓存
JavaEye上面关于对象缓存的讨论很多,我们也提供了JavaEye这方面很多数据,因此不展开了。RoR可以使用两个对象缓存,一个是
CachedModel,类似Hibernate,比较简单,对Model的CRUD操作自动进行缓存;另外一个是cache_fu,需要自己编码来添加对象缓
存,但提供了更多高级机制,目前我们使用的是cache_fu。在使用对象缓存的情况下,应该把查询方法的:include去掉,避免关联查询
无法利用缓存的现象。

2、查询缓存
对于统计类耗时查询,如果不要求实时性,那么可以使用memcache-client将查询结果缓存到memcached里面,例如博客排行榜之类。

3、页面局部缓存
对象缓存和查询缓存都是降低数据库访问负载的,但如果RoR的负载很高,那么只能依靠页面局部缓存了。传统的互联网web1.0网站
很流行采用动态页面静态化技术来提高网站的负载,但是对于web2.0网站来说,每个页面都带有登陆用户的个人信息,页面的很多部
分需要实时更新,例如投票,点击统计,digg,显示用户在线状态等等,动态页面静态化非常困难。当然如果你非要采用动态页面静
态化,技术上也不是实现不了,可以通过AJAX请求来处理静态页面的动态部分,但是这种解决方案的开发成本过高,而且性能未必会
有明显的改善,大家看看新浪和搜狐博客就知道这种技术被应用的有多糟糕了。

web2.0网站比较常用使用页面局部缓存,一种情况是页面不需要实时更新的,那么只需要设置一个合理的过期时间就行了,这种情况
我们目前使用的比较多;另外一种情况是虽然不需要实时更新,但是会在用户执行某些操作后需要缓存过期,比方说博客个人主页的
很多页面,这种情况下缓存过期策略会比较复杂,考虑到合理的开发成本,我们尚未对这样的页面使用局部缓存。

此外,Rails的页面局部缓存有一个缺点,就是和页面查询结果对应的Action当中的查询语句要放在View里面,否则每次action里面的查
询还是会被执行,但是这样做会破坏程序代码良好的MVC结构。这种情况下,也可以采用另外一个Cache插件: better rails caching,在
缓存页面的同时可以缓存Action当中的查询语句。

三、应用代码的优化

Stefans Kaes的文档里面对应用代码的优化进行了非常详细的介绍,因此我这里只提两个比较重要的注意事项:

第 129 / 283 页
http://robbin.javaeye.com 2.30 JavaEye网站的RoR性能优化经验谈

1、link_to
Rails的link_to是非常慢的,它的代码实现过于复杂,特别是Rails1.2引入了REST以后,大量的命名路由被使用,这些命名路由还需要
通过一次method_missing,那就更加缓慢了。因此对于被频繁使用的内部URL地址,一定要自己用字符串拼接方式改写,可以很明显
提高View的render性能。此外类似的helper还有很多,例如button_tag,image_tag啥啥的,如非必要,尽量不用他的helper

2、正则表达式
ruby的正则表达式也是极慢,例如auto_fix这个helper的正则表达式就比较复杂,造成的结果就是一但大量使用auto_fix,View的render
就明显变慢,类似依赖正则表达式进行字符串过滤的helper有很多,如果需要频繁大量使用,请先自行做benchmark。

Rails应用程序的内存泄漏问题和解决
内存泄漏是服务器端程序经常遇到的,有时候内存泄漏问题会让人很头疼,总体来说,Rails的内存泄漏问题比Java要少得多,这是因
为Java内存泄漏最常见的三种情况在Rails当中不存在:

1、HttpSession导致的内存泄漏
Java程序员喜欢往session里面丢很多东西,最糟糕的是竟然有很多框架软件也肆无忌惮往session里面丢状态数据,但Rails的session
是不放在内存里面的,所以无此烦恼。

2、数据库连接释放不彻底
Java的数据库连接池释放不彻底,以及查询游标释放不彻底,都必然导致内存泄漏。Rails没有数据库连接池,而是每个进程持有一个
长连接,因此不存在这个问题,而且由于持有长连接,也不存在Java里面的OpenSessionInView的烦恼。

3、用静态变量持有全局共享数据
Java程序员很喜欢通过静态全局变量来持有共享数据,但共享数据忘记清理的话,也很容易导致内存泄漏,Ruby是SNA架构,多进程
服务器模式,进程间无法共享数据,反而避免了全局共享数据带来的麻烦。

但是Rails应用有一种情况:在Ruby代码中调用C写的第三方ruby类库的时候,很容易导致内存泄漏,但这种内存泄漏反而在Java中极其
罕见。Ruby本身有GC来管理内存堆,但是代码一旦调用C写的第三方ruby类库,内存堆的分配权就掌握在第三方C库的实现上面了,如
果这个C库的代码质量不够好,内存泄漏就不可避免。由于ruby本身性能很差,因此计算量大的功能往往依赖底层的C库来实现,这下
内存泄漏的潘多拉魔盒就打开了!而Java性能比较好,功能都是纯Java编写,基本上看不到需要依赖第三方C库的情况,因此比较安
全。

JavaEye也面临着内存泄漏的困扰,这方面困扰主要来自于Rmagic。Rmagick调用ImageMagick的C库来完成图片的操作,从我们的监测
来看,RMagick大多数情况下会缓慢的泄漏内存,在某些特定的图片操作上会急剧的泄漏内存。解决办法就是用mini_magick替代
Rmagick,mini_magick是直接调用ImageMagick的mogrify命令,另起一个进程来操作图片,操作完进程就结束了,绝无后患,由于
Linux的fork进程开销不大,因此也不必担心性能问题。

此外,调用第三方C库的ruby代码编写都需要高度小心,比方说JavaEye使用ferret实现全文检索,根据应用的需要调用ferret的API来编
写自己的analyzer,其中在实现token_stream方法上面使用了XXXAnalyzer.new和XXXToken.new,XXXFilter.new,结果内存急剧泄漏,
经过检查发现是Analyzer对象不能被反复创建,改成创建后缓存该对象就好了,但是Filter和Token对象却必须每次创建,此外ferret的
PerAnalyzerFilter也有内存泄漏问题。由于类库是用C编写的,单纯看API文档或者看源代码片断一般无法判断出里面的内存泄漏陷阱

第 130 / 283 页
http://robbin.javaeye.com 2.30 JavaEye网站的RoR性能优化经验谈

的。

当遇到了难以解决和定位的内存泄漏问题,Ruby也有类似Java的内存Profiler工具:

1、Memory Profiler
一个纯ruby编写的内存探测器,原理很简单,就是用ruby的对象引用计数器ObjectSpace.each_object去遍历内存堆中的每个ruby对象,
进行统计和分析。用起来很简单,非常适合于开发环境下侦测内存泄漏问题,但不能用在生产环境下,极度影响Rails性能。

2、Bleak_house
Bleak_house给Ruby解析器打了补丁,插入相关的指令,可以从底层探测整个ruby内存堆中对象的情况,然后你可以定期dump出来完
整的内存堆里面的所有对象,再用bleak工具去分析dump文件,他比上面的工具分析的信息要全面,可以在测试环境和预发布环境下
使用,但在生产环境下,也会对应用的性能产生很大的影响,要慎用。

JavaEye网站在RoR性能方面的经验就全部分享给大家了,也希望做RoR的朋友都拿出来自己的经验和大家分享,共同学习和促进RoR
的应用和普及。

第 131 / 283 页
http://robbin.javaeye.com 2.31 Lighttpd和RoR安装配置的疑难解答

2.31 Lighttpd和RoR安装配置的疑难解答

发表时间: 2008-03-07 关键字: lighttpd

之前写过一篇在Linux平台上安装和配置Ruby on Rails详解,可能是有点高估了Linux的普及和应用程度,无数安装和配置的问题都以各
种方式向我涌过来。这里集中的提供一下疑难解答:

一、到底我应该用Lighttpd,还是Nginx/Mongrel?

现在Nginx/Mongrel的部署方式越来越受欢迎了,很多人置疑Lighttpd/FastCGI,并且现在也涌现了一些比Mongrel性能更好的例如
Thin,ebb等ruby应用服务器,那Lighttpd/FastCGI真的过时了吗?

大家有兴趣可以看一下我这篇文章:RoR部署方案深度剖析,Lighttpd提供了很多其他Web服务器不具备的优势,可以最大化FastCGI的
性能。现在Mongrel/Thin/ebb都利用了一些多线程或者事件IO机制来提供并发性能,这是FastCGI所不具备的,但遗憾的是Rails框架是
单线程的,最终还是必须单进程单线程来执行Rails请求,所以这些并发优势无用武之地。但一些其他Ruby的Web框架例如camping,
weavers已经开始支持ruby多线程,提供了比Rails好得多的性能,mongrel/ebb只有在这些web框架上面才能发挥其性能优势。

所以只要你还是用Rails框架,Lighttpd/FastCGI就是性能最好的部署方案。

二、ubuntu Linux安装ruby碰到的缺少readline,zlib库的问题?

有些人的ubuntu安装的库不全,比方说缺少readline库,缺少zlib库,可能会导致自己手工编译安装ruby的失败,那么就用apt-get先把
库安装好。

三、Lighttpd安装遇到的缺少pcre库的问题?

RHEL/CentOS用户可能要用yum安装一下pcre/pcre-devel这两个库,ubuntu用户用apt-get安装一下,Linux熟手也可以自己下载源代码
编译安装,Pcre是Perl兼容的正则表达式库,Lighttpd的Rewrite功能需要它。

四、Lighttpd配置过程当中遇到的种种问题?

1、我用的是ubuntu,你说的控制脚本rc.lighttpd我跑不了,执行就会报错

如果你的Linux是ubuntu,那么需要自己创建启动脚本,lighttpd官方wiki上面已经给出来该脚本,地址在:
http://redmine.lighttpd.net/wiki/1/ScriptsUbuntu

rc.lighttpd这个脚本是针对SuSE Linux写的,此外还提供了一个rc.lighttpd.redhat是针对RedHat Linux写的,你自己写一个控制脚本,也


不过是举手之劳:

#!/bin/sh

case "$1" in

第 132 / 283 页
http://robbin.javaeye.com 2.31 Lighttpd和RoR安装配置的疑难解答

start)
/usr/local/lighttpd/sbin/lighttpd -f /etc/lighttpd/lighttpd.conf > /dev/null 2>&1
;;
stop)
killall lighttpd
;;
restart)
$0 stop
sleep 1
$0 start
;;
*)
echo "Usage: lighttpd.sh {start|stop|restart}"
;;
esac

exit 0

创建一个shell脚本,内容如上,chmod u+x lighttpd.sh,这个脚本就可以用来启动关闭和重起lighttpd了

2、启动Lighttpd的时候报错,说XXX目录找不到

Lighttpd启动之后默认情况下会写access log,error log,如果你启动了压缩过程,还会把文件压缩过的版本放在压缩目录下面,所以


检查一下你的lighttpd.conf配置文件,是不是这些目录还没有,或者路径不对。

3、启动lighttpd可以访问,但如果配置了Rails,就无法启动

如果无法启动,要学会自己看Lighttpd的error log和Rails项目的log目录下面的fastcgi crash log,在这两个log文件当中可以找到出错原


因。其中一种常犯的错误是:Rails项目在Windows上面创建和开发,最后部署到Linux Server上面。这种情况下dispatch.fcgi这个脚本
的ruby解析器路径是 #!c:/ruby/bin/ruby.exe 这个路径在Linux上面肯定是错误的,你可以改成#!/usr/bin/env ruby,或者干脆在Linux上
面创建该Rails项目。此外在windows上面创建的Rails项目,dispatch.fcgi没有可执行权限,这也需要你在Linux上面先赋予可执行权限
才行。你可以尝试着手工运行该脚本cd public && ./dispatch.fcgi,看看是否可以运行。

4、启动lighttpd报错,说找不到socket路径

我在前面安装文档中给出来的配置内容如下:

$HTTP["host"] == "www.xxx.com" {
server.document-root = "/yourrails/public"

第 133 / 283 页
http://robbin.javaeye.com 2.31 Lighttpd和RoR安装配置的疑难解答

server.error-handler-404 = "/dispatch.fcgi"
fastcgi.server = (".fcgi" =>
("localhost" =>
("min-procs" => 10,
"max-procs" => 10,
"socket" => "/tmp/lighttpd/socket/rails.socket",
"bin-path" => "/yourrails/public/dispatch.fcgi",
"bin-environment" => ("RAILS_ENV" => "production")
)
)
)
}

就算照抄你要改改路径吧?这个demo当中的socket路径是/tmp/lighttpd/socket/rails.socket,那你要照抄,先检查一下有没有/tmp/
lighttpd/sock目录总是应该的吧?其实用啥路径都无妨,关键就是别照抄,领会原理,根据自己的环境做相应的调整。

5、lighttpd可以启动,但是访问Rails应用出现404错误,找不到页面

在lighttpd的虚拟域配置里面有一项

server.error-handler-404 = "/dispatch.fcgi"

意思是当lighttpd找不到URL对应的硬盘文件,就会调用Rails的dispatch.fcgi去处理该URL请求,这也是lighttpd访问Rails的主要方式,
其性能比URL转发要快。如果你在配置文件里面忽略了这一行,lighttpd就会直接返回404错误,而不是交给Rails处理。

6、重起lighttpd以后,fastcgi进程不关闭,导致多次重起lighttpd之后,fastcgi进程堆积越来越
多?

正常情况下,关闭Lighttpd以后,dispatch进程就会销毁,但是在dispatch进程处理请求的时候关闭lighttpd,dispatch进程并不会马上
关闭,而是处理完毕当前请求,才会关闭掉。一些极端情况下,可能会导致dispatch进程一直不关闭,dispatch进程就会越来越多。解
决办法很简单 killall -9 dispatch.fcgi,只管杀进程就好了。

7、我的lighttpd和FastCGI部署在不同的服务器,怎么配置呢?

这种情况下,Lighttpd只是连接远程服务器的TCP端口,而不负责启动dispatch.fcgi进程,因此需要自己写脚本启动关闭dispatch.fcgi进
程。lighttpd提供了一个spawn-fcgi的程序,可以用来启动dispatch.fcgi进程,监听TCP端口,你可以自己写一个shell脚本来完成这个工
作。另外spawn-fcgi还可以启动dispatch.fcgi进程,创建本机的unix socket端口,和本机lighttpd通讯,例如:

例如:

第 134 / 283 页
http://robbin.javaeye.com 2.31 Lighttpd和RoR安装配置的疑难解答

#!/bin/sh

DISPATCH_PATH=/yourrailsapp/public/dispatch.fcgi
SOCKET_PATH=/tmp/lighttpd/socket
RAILS_ENV=production
export RAILS_ENV

case "$1" in

start)
for num in 0 1 2 3 4 5 6 7 8 9
do
/usr/local/lighttpd/bin/spawn-fcgi -f $DISPATCH_PATH -s $SOCKET_PATH/rails.socket-$num
done
;;

stop)
killall -9 dispatch.fcgi
;;

restart)
$0 stop
$0 start
;;

*)
echo "Usage: dispatch.sh {start|stop|restart}"
;;

esac

exit 0

执行 ./dispatch.sh start 将启动10个dispatch.fcgi进程,在/tmp/lighttpd/sock目录下面创建了10个unix socket文件,然后配置lighttpd


去连接这10个socket文件:

$HTTP["host"] =~ "www.xxx.com$" {
server.document-root = "/yourrails/public"
server.error-handler-404 = "/dispatch.fcgi"
fastcgi.server = (".fcgi" =>

第 135 / 283 页
http://robbin.javaeye.com 2.31 Lighttpd和RoR安装配置的疑难解答

(
("socket"=>"/tmp/lighttpd/socket/rails.socket-0"),
("socket"=>"/tmp/lighttpd/socket/rails.socket-1"),
("socket"=>"/tmp/lighttpd/socket/rails.socket-2"),
("socket"=>"/tmp/lighttpd/socket/rails.socket-3"),
("socket"=>"/tmp/lighttpd/socket/rails.socket-4"),
("socket"=>"/tmp/lighttpd/socket/rails.socket-5"),
("socket"=>"/tmp/lighttpd/socket/rails.socket-6"),
("socket"=>"/tmp/lighttpd/socket/rails.socket-7"),
("socket"=>"/tmp/lighttpd/socket/rails.socket-8"),
("socket"=>"/tmp/lighttpd/socket/rails.socket-9")
)
)
}

这样做的好处是,每次重新部署应用,就不需要重起lighttpd了,只需要执行自己的dispatch.sh来重起dispatch.fcgi进程就可以了。同
时也可以很好的解决上一个fastcgi进程堆积的问题。

如果远程部署,配置方式是一样的,就是lighttp连接的端口改为:

("host"=>"192.168.0.1, "port"=>3001),
("host"=>"192.168.0.1, "port"=>3002),
......

dispatch.sh创建dispatch.fcgi进程的时候,使用 -t 参数创建tcp端口,而不是 -s 创建unix socket文件即可。

8、我的rails应用不是在根目录下面,是在子目录下面怎么配置呢?

例如你的rails应用必须使用某个网站的子目录,如:http://www.xxx.com/myapp,那么只需要在lighttpd增加一项目录别名映射就可以
了,例如:

server.document-root = "/yourwebsite/myapp/public"
alias.url = ("/myapp" => "/yourwebsite/myapp/public")

第 136 / 283 页
http://robbin.javaeye.com 2.32 mod_rails尝鲜

2.32 mod_rails尝鲜

发表时间: 2008-04-13 关键字: mod_rails

Passenger(俗称mod_rails)是最近刚刚发布的Apache module项目,刚一出来就得到了诸多好评,JavaEye新闻也有两篇报道:

Rails部署也可以简单得像PHP一样
Passenger(mod_rails)新的RoR部署方式

其中性能评测更加令人印象深刻

好像还有人称,未来RoR的主流部署方式将是mod_rails,而且这个项目的作者还貌似一个华人,叫做“赖洪礼”,所有的这一切都让人挺
有兴趣,于是我在周末也简单的安装和测试了一把。

如果已经安装好Apache和Ruby on Rails的环境,并且把Apache的bin目录和ruby的bin目录配置到PATH环境变量下面,那么安装
Passenger倒也很简单:

gem install passenger


passenger-install-apache2-module

安装好以后,他会提示你如下配置Apache(具体环境可能稍有不同):

LoadModule passenger_module /usr/local/ruby/lib/ruby/gems/1.8/gems/passenger-1.0.1/ext/apache2/mod_passenger.so


RailsSpawnServer /usr/local/ruby/lib/ruby/gems/1.8/gems/passenger-1.0.1/bin/passenger-spawn-server
RailsRuby /usr/local/ruby/bin/ruby

NameVirtualHost *:80

<VirtualHost *:80>
DocumentRoot "/home/webroot/demo/public"
ServerName 192.168.0.3
ErrorLog "logs/rails-error_log"
CustomLog "logs/rails-access_log" common
</VirtualHost>

前面三行是注册Apache的module,以及该module的相关启动脚本,后面就是标准的Apache虚拟主机配置方法了,指明rails项目的
public路径就可以了。

第 137 / 283 页
http://robbin.javaeye.com 2.32 mod_rails尝鲜

在Apache运行起来之后,Apache启动了一个Rails的Passenger进程,该进程是用来管理ruby进程的启动关闭以及响应请求的,如果访
问量比较大,该进程还会陆续启动子进程,来提高更多的ruby进程管理,如下所示:

root 5981 5980 0 13:37 ? 00:00:00 Passenger spawn server


root 6086 5981 0 13:40 ? 00:00:01 Passenger FrameworkSpawner: 2.0.2
daemon 6350 6086 0 13:54 ? 00:00:00 Passenger ApplicationSpawner: /home/webroot/demo

以上的3个ruby进程是控制进程,此外,还会根据web请求的数量,启动相应数量的Ruby进程来处理Rails请求。这些ruby进程在控制进
程的控制下,当web请求负载高的时候,会动态创建更多进程,当web请求负载低的时候,就会动态销毁,以节省内存。控制进程和
Rails进程之间使用Unix Socket来通讯。

mod_rails的大致原理就是这样的。这种运行方式有点类似Apache以mod_fastcgi方式来运行Rails,但因为通讯方式和控制进程都要好
得多,因此不会出现mod_fastcgi的好多问题。

mod_rails提供了apache上面另外一种可以选择的Rails部署方式,但是这种部署运行方式也不可避免的带有致命缺陷。正因为ruby进程
是动态创建,而我们知道Rails进程启动的时候是非常消耗CPU的操作,因此黑客可以很容易的通过瞬时发起数量巨大的并发web动态请
求让服务器因为忙于创建大量的Rails进程而陷于瘫痪。

另外对于虚拟主机提供商来说,ruby进程的数量是根据请求量动态调整的,因此无法根据付费用户来分配限制相应的资源,这不像
mongrel那样好控制用户使用的资源数量。因此预期Rails虚拟主机提供商也不会采用mod_rails。

最后我个人觉得,随着Lighttpd和nginx的崛起,Apache真的已经可以淘汰了,Apache这种多进程web服务器实在太消耗服务器资源,
也太容易被DOS攻击了,任何依赖Apache的部署方案都有点过时了。

如果说要我推荐的话,Rails部署的性能首选还是Lighttpd+FastCGI,次选则可以考虑 nginx + thin/mongrel

第 138 / 283 页
http://robbin.javaeye.com 2.33 使用libmmseg实现Ruby的中文分词功能

2.33 使用libmmseg实现Ruby的中文分词功能

发表时间: 2008-05-24 关键字: libmmseg

用Ruby on Rails开发web2.0网站的人都知道,ruby的全文检索功能不像Java支持的那样好,要提供中文的全文检索功能是一件很困难
的事情,而偏偏全文检索是web2.0网站绕不过去的一道坎。虽然ruby也有类似lucene的全文检索软件ferret,但是ferret本身并没有提供
中文分词功能,必须自己另行扩展中文分词功能。因此攻克ruby中文全文检索功能的瓶颈在于提供ruby的中文分词功能。

Java的lucene虽然也没有中文分词功能,但是现在有很多第三方开源的Java中文分词项目,因此Java的中文分词并不是一个难以解决的
问题。但对于ruby来说,由于ruby的性能相当差,因此中文分词这种需要大量的、密集的字符串运算,ruby编写的中文分词代码性能根
本无法接受,唯一的办法就是用C/C++编写分词算法,用ruby去调用。

libmmseg是李沫南用C++编写的开源的中文分词软件,libmmseg的分词算法采用的是“基于词库的最大匹配算法”,分词速度为每秒
300KB左右。

libmmseg主要被作者用来实现Sphinx全文检索软件的中文分词功能,因此作者给Sphinx提供了一个补丁文件,可以让Sphinx集成
libmmseg,从而支持对于中文文章的全文检索功能,关于这一点可以看:http://www.coreseek.cn/index.php?page=Sphinx的介绍。

libmmseg从0.7.2版本开始,作者提供了ruby调用的接口,所以我们可以直接在ruby程序里面调用libmmseg进行分词了。特别是我们可
以用ferret去调用libmmseg分词功能,从而让ruby原生支持中文的全文检索,这无疑是一个好消息。然而libmmseg和ruby的集成颇有些
麻烦,因此希望这篇文章可以提供一点点指导。

一、下载libmmseg

首先是到作者的网站下面最新版本的libmmseg http://www.coreseek.cn/opensource/mmseg/,但libmmseg 0.7.3作者还没有在网站


上面更新,因此可以从本文附件下载。

二、安装libmmseg

解压缩以后,标准的Unix源代码编译安装流程:

unzip mmseg-0.7.3.zip
cd mmseg-0.7.3
chmod a+x configure
./configure
make && make install

顺利的话libmmseg被安装到/usr/local相应的目录下面,建议再执行一下 ldconfig 命令,更新链接库缓存。

提示:编译libmmseg,gcc的版本必须是4.0以上。我的Linux是gcc 3.3.3编译失败,解决办法是注释掉src/css/
UnigramCorpusReader.cpp这个文件的int UnigramCorpusReader::open(const char* filename, const char* type)方法里面的所有内容,
让这个方法为空方法,这样就可以编译通过了。但是mmseg命令行工具就无法使用了。

第 139 / 283 页
http://robbin.javaeye.com 2.33 使用libmmseg实现Ruby的中文分词功能

三、安装ruby扩展

libmmseg软件包下面有一个ruby目录,进入该目录编译ruby。这里作者没有把相应的h文件依赖关系写好,因此需要我们手工把所有相
关h文件拷贝到当前目录,确保编译的通过,详细操作如下:

cd ruby
cp /usr/local/include/mmseg/*.h .
cp ../src/*.h .
cp ../src/css/*.h .
ruby extconf.lin.rb
make && make install

顺利的话,编译好的mmseg.so就会被拷贝到ruby的系统库扩展目录下面。你可以简单的测试一下,进入irb,尝试load一下mmseg,看
能否成功:

irb
require 'mmseg'

四、创建词典文件

进入libmmseg软件包的data目录下面,执行如下命令:

mmseg -u unigram.txt

把生成的文件改名为uni.lib,拷贝到ruby目录下面,然后执行测试:ruby test.rb,如果一切都顺利的话,你可以看到test.rb测试是通过
的。

提示:如果你的gcc版本低于4.0,则无法编译libmmseg,如果你按照前面的提示编译通过了,那么这里无法使用mmseg生成词典文
件。解决办法就是另外找台机器安装gcc4.0编译,生成字典文件。

五、编写ferret的Analyzer,封装一个可以处理中文的分词器

我们知道ferret的StandardAnalyzer是不支持中文分词的,因此我们要自己封装一个Analyzer,用mmseg来分词。然后在我们自己的
Rails项目目录下面,我们把前面创建好的词典文件uni.lib放在项目的dict/uni.lib位置(可以自己创建一个dict目录),记得在程序里面正确
的加载词典文件:

require 'ferret'
require 'mmseg'

第 140 / 283 页
http://robbin.javaeye.com 2.33 使用libmmseg实现Ruby的中文分词功能

class ChineseAnalyzer < Ferret::Analysis::Analyzer


def initialize
@mmseg = Mmseg.createSeg("#{RAILS_ROOT}/dict", "")
end

def token_stream(field, text)


Ferret::Analysis::LowerCaseFilter.new(Tokenizer.new(@mmseg, text))
end
end

class Tokenizer < Ferret::Analysis::TokenStream


def initialize(mmseg, text)
@mmseg = mmseg
self.text = text
end

def next
if @mmseg.next
@token.text = @text[@mmseg.start...@mmseg.end]
@token.start = @mmseg.start
@token.end = @mmseg.end
@token
end
end

def text
@text
end

def text=(text)
@text = text
@mmseg.setText(text)
@token = Ferret::Analysis::Token.new("", 0, 0)
end
end

有了这个ChineseAnalyzer,我们就可以方便的在Rails程序里面进行中文分词和全文检索了。根据我的实际测试,在ruby代码中调用
libmmseg,性能相当不错,而且内存消耗比较低,完全可以放心的在生产环境使用,作为Rails网站的中文全文检索功能的支撑。

附件下载:

第 141 / 283 页
http://robbin.javaeye.com 2.33 使用libmmseg实现Ruby的中文分词功能
• mmseg-0.7.3.zip (2.6 MB)
• http://robbin.javaeye.com/topics/download/77d22314-209a-361d-b072-c4c40a6d4d82
• 描述: libmmseg 0.7.3

第 142 / 283 页
http://robbin.javaeye.com 2.34 rmmseg-cpp - 简洁高效的ruby中文分词程序

2.34 rmmseg-cpp - 简洁高效的ruby中文分词程序

发表时间: 2008-05-27 关键字: rmmseg

我在前一篇文章向大家介绍了libmmseg实现ruby的中文分词,在这篇文章当中向大家介绍另外一个优秀的ruby中文分词程序rmmseg-
cpp。

rmmseg是浙江大学的学生pluskid开发的纯ruby版本的中文分词程序,采用的也是“基于词典的最大匹配算法”,rmmseg的相关介绍请
看:http://www.javaeye.com/news/1380。

rmmseg的主要问题是性能和内存消耗。用纯ruby编写的rmmseg分词的速度非常慢,而且内存消耗非常惊人,当使用复杂分词算法的
时候,内存呈线性上升的现象,在我作的大量索引测试程序中曾经上升到了900MB以上。

为此rmmseg的作者pluskid再接再厉用C++重写了一遍rmmseg项目,这就是rmmseg-cpp。根据作者自己的简单测试表明:rmmseg-cpp
的性能是rmmseg的400倍之多。下面简单介绍rmmseg-cpp的安装和使用:

1、安装
rmmseg-cpp目前只支持Unix操作系统,不支持Windows

gem install pluskid-rmmseg-cpp --source=http://gems.github.com

2、使用

require 'ferret'
require 'rmmseg'
analyzer = RMMSeg::Ferret::Analyzer.new do |tokenizer|
Ferret::Analysis::LowerCaseFilter.new(tokenizer)
end

就可以了,然后就可以使用analyzer进行分词索引和查询了。

rmmseg-cpp和libmmseg目前都可以作为比较好的ruby中文分词程序来使用,他们的性能和内存管理都相当不错,经过我们测试和使用
的情况来看,都可以放心在生产环境当中使用。不过他们也有一些区别和各自的特点:

1、rmmseg-cpp的分词速度比libmmseg快一倍左右

rmmseg-cpp是专门为ruby的ferret编写的中文分词接口,代码十分简练,和ruby结合的很好;libmmseg主要是用来和sphinx配合的,并
不是为ruby而写,他仅仅提供了一个非常简陋的ruby调用接口,在ruby程序当中使用中文分词的时候,rmmseg-cpp的性能明显胜出一
筹。

2、rmmseg-cpp的内存管理似乎不如libmmseg稳定

第 143 / 283 页
http://robbin.javaeye.com 2.34 rmmseg-cpp - 简洁高效的ruby中文分词程序

Ruby本身是带有GC功能的脚本语言,用C/C++编写Ruby扩展本身是一件很麻烦的事情,因为C/C++自身是需要手工分配内存的,但是
如果程序员对于Ruby的GC机制没有足够的了解,会带来很多麻烦,弄不好就可能内存泄漏,或者发生不期望的被使用中的对象被Ruby
GC掉的问题。

rmmseg-cpp已经在GC方面下了很大的功夫,因此内存管理相当不错,但是我曾在一次数据量非常大量的全文索引过程当中观察到内存
短时间内快速上升了几十MB的现象(但这种现象不常见)。

而libmmseg没有对ruby的依赖,仅仅提供一个简陋的接口,因此在数次测试当中,已经程序长时间运行观察下来,内存管理比
rmmseg-cpp显得更加平稳一点,没有出现过一次内存快速上升的现象。

3、rmmseg-cpp目前没有Windows版本,而libmmseg支持windows版本

4、rmmseg-cpp安装配置很简单,不像libmmseg那么麻烦

总得来说,rmmseg-cpp和libmmseg都是用C++编写的优秀的中文分词程序,并且都可以支持在ruby当中实现全文检索的中文分词功
能。如果不是特殊的需要,仅仅只是在ruby当中使用中文分词功能,那么推荐使用rmmseg-cpp。目前JavaEye网站的中文分词算法已经
采用rmmseg-cpp,效果还不错。

第 144 / 283 页
http://robbin.javaeye.com 2.35 Skynet --- ruby的类Google Map/Reduce框架

2.35 Skynet --- ruby的类Google Map/Reduce框架

发表时间: 2008-06-02 关键字: skynet, mapreduce

Skynet是一个很响亮的名字,因为它是阿诺施瓦辛格主演的经典系列电影《终结者》里面的统治人类的超级计算机网络。不过本文的
Skynet没这么恐怖,它是一个ruby版本的Google Map/Reduce框架的名字而已。

Google的Map/Reduce框架实在太有名气了,他可以把一个任务切分为很多份,交给n台计算机并行执行,返回的结果再并行的归并,
最后得到运算的结果。据说Google一个搜索结果会Map到7000台服务器并行执行,这么多么可怕的分布式运算能力阿!有了Map/
Reduce,程序员就可以在无需关注分布式框架的情况下,用简单的代码写出来健壮、并行的分布式应用程序,并且可以充分发挥计算
机群集运算的能力。

如今能够实现Map/Reduce算法的框架已经有好几个了,其中最有名气的可能就是Yahoo发起的开源项目Hadoop,不过Hadoop并不是
用ruby编写的,但在ruby的世界,Adam Pisoni已经开发出来了ruby版本的Map/Reduce框架,这就是Skynet。

Adam Pisoni开发Skynet的初衷是因为Adam Pisoni的公司Geni.com是一家定位于家族SNS的互联网网站。网站提供的新闻推送功能要求


能够从大量的用户产生的信息当中提取特定用户感兴趣的内容,推送给用户。这实际上是一个分布式运算模型,要能够把任务分布到
多台服务器上面执行,最后把任务归并回来。Adam Pisoni没有找到合适的框架,最终自己开发了Skynet,运用Map/Reduce算法来提
供这个分布式运算平台。

用Skynet开发Map/Reduce的分布式应用程序非常简单,让我们举一个简单的例子看看吧:假设有一个1GB的文本文件,我们的任务是
要统计该文件当中每个单词出现的次数统计。传统的做法当然很简单,顺序读入文件内容,进行单词统计就行了,但是毫无疑问,执
行速度会很慢。如果我们有一个1000台服务器的运算群集,我们可以如何利用Skeynet来并发执行这个程序,从而缩短统计时间呢?

Map/Reduce算法的过程是:

1、Partition(划分数据)
把数据划分为1000份,这个过程由Skynet自动完成

2、Map
除了划分数据,还需要把运算该数据的代码也Map到每个运算节点上面去并发执行。这1000个节点各自执行自己的任务,执行完毕以
后把执行结果返回

3、Partition
这1000分执行结果需要归并,于是我们再次划分数据,比方说划分为10份,这个过程也是Skynet自动完成的

4、Reduce
把Reduce代码和Reduce数据分发到10个节点执行,每个节点执行完毕返回数据。如果需要再次Reduce可以再次执行。最终Reduce为
一个总共的结果。

其实Map/Reduce算法的原理是很简单的,好了,看看Skynet下面,我们怎么实现呢?其实我们需要编写的代码只有两个方法:一个
map方法,告诉skynet如何执行每份数据,一个reduce方法,告诉skynet如何归并每份数据,所以这个并行算法最终用Skynet来写的
话,也非常简单:

第 145 / 283 页
http://robbin.javaeye.com 2.35 Skynet --- ruby的类Google Map/Reduce框架

class MapreduceTest
include SkynetDebugger

def self.map(datas)
results = {}
datas.each do |data|
results[data] ||= 0
results[data] += 1
end
[results]
end

def self.reduce(datas)
results = {}
datas.each do |hashes|
hashes.each do |key,value|
results[key] ||= 0
results[key] += value
end
end
results
end
end

这个就是一个最简单、但是完整ruby版本的Map/Reduce代码了。我们需要编写一个map方法,告诉skynet去统计每个单词的出现次
数,我们还需要编写一个reduce方法告诉skynet去归并每个map的统计结果。好了,剩下所有的工作都归Skeynet接管了,是不是很简
单!

当然要让这个Map/Reduce跑起来我们还需要做一些工作,比方说安装skynet,配置skynet的并行节点等等,这些琐碎的工作可以看看
skynet自己的文档:http://skynet.rubyforge.org/doc/index.html,就不详述了。

值得一提的是Skynet可以和Rails框架良好的整合起来工作,你可以把Rails当中一些非常耗时、可以Map/Reduce的工作丢给Skynet去
异步后台执行,比方说:

MyModel.distributed_find(:all, :conditions => “created_on < ’#{3.days.ago}’”).each(:some_method)

把最近3天以来所有的model查询处理以后要执行的耗时操作some_method交给Skynet,让Skynet动用他强大的运算网络去执行。

还可以异步执行:

第 146 / 283 页
http://robbin.javaeye.com 2.35 Skynet --- ruby的类Google Map/Reduce框架

model_object.send_later(:method, options, :save)

把耗时的任务交给Skynet去异步执行。

对于拥有强大运算网络、并且需要进行大量耗时运算的web2.0网站来说,Skynet真是一个很棒的工具,他可以让程序员很简单的编写
处理健壮而高效的分布式应用程序!

第 147 / 283 页
http://robbin.javaeye.com 2.36 Ruby和Rails的缺点

2.36 Ruby和Rails的缺点

发表时间: 2008-06-25

有人说,robbin你说了那么多RoR的优点,你啥时候说说RoR的缺点阿?你说的缺点肯定比别人说的更客观。没办法,为了表现出来我
不是一个RoR粉,只好总结点缺点,以飨RoR黑子们:

Ruby和Rails的一些缺点的总结:

ruby的问题我觉得主要是:

1、ruby本身的性能是比较差的,无法直接做一些计算密集型的任务

比方说大量的分词运算、语料训练什么的,用ruby写是不行的

2、ruby的C扩展很难写

正因为ruby性能差,所以很多情况下要依赖C写的底层库,但是写ruby的扩展C库是很困难的事情。一方面没有特别多的资料介绍,你
能参考的只有《Ruby Hacking Guide》,另外一方面Ruby是带有GC的语言,C又是没有GC的,所以如果你对ruby的GC机制没有特别清
楚的了解情况下,写C扩展会出现意想不到的问题:比方说你写的程序逻辑没有任何问题,但是和ruby配合起来就会不定期的出现错
误,这就是你C程序的某个赋值变量可能会被ruby GC以你意想不到的方式销毁。

3、ruby的C扩展库质量不高,容易出现内存泄漏问题

正因为上面的原因,很多第三方的C扩展库质量不好,很容易出现内存泄漏问题,这是一个很头疼的问题,你很难定位,也很难解决,
只能尽量避免使用第三方扩展C库。

Rails的问题我觉得主要是:

1、特别容易出现命名冲突

你自己写的代码里面给类增加的方法,动不动就和Rails给类扩展的方法名称冲突了。这种错误很隐蔽,很难发现。这也是ruby语言动
态性带来的一个负面影响

2、Rails每次升级API变动都比较大

Rails升级是不太考虑向下兼容性的,所以每次升级的话,可能你很多代码都要改,更糟糕的是很多Rails插件特别喜欢以hack rails的方
式来扩展Rails功能,那么Rails一升级,插件的兼容性几乎肯定是不行的,这个是比较痛苦的事情。

3、Rails的view方面还是比较原始的erb拼接字符串方式,像JSP那样原始,没有一个类似Java的velocity/freemarker那样的页面模版
库,所以写helper动不动要用字符串去拼html片断,如果是特别复杂的view需要拼的话,代码就会写的很丑陋。

当然总体来说,RoR还是让我感觉非常满意的,特别适合互联网应用。

第 148 / 283 页
http://robbin.javaeye.com 2.37 推荐一篇很好的RoR部署方案性能评测

2.37 推荐一篇很好的RoR部署方案性能评测

发表时间: 2008-07-08

今年年初的时候,我写了一篇RoR部署方案深度剖析的文章,分析了Rails的进程运行方式下各种部署方案的优缺点,以及采用什么部
署方案最优的话题。当时我没有给出具体的性能评测数据,因为我觉得运行的机制原理很清楚的情况下,没有做评测的必要性。但不
管怎么说,一份详细的性能评测数据还是更有说服力,因此我很欣喜的看到ShiningRay的这份评测报告有多么宝贵的价值。

浅析Ruby on Rails部署方案

ShiningRay的博客文章

在这份评测报告当中,ShiningRay给出了更多的主流部署方案、详细的分析和丰富的测试数据,可以算是RoR部署方案性能测试之集大
成者了。所以没什么好说的,强烈推荐阅读!当然我会建议你在阅读该文档之前,不妨先阅读我在年初写的RoR部署方案深度剖析,

会更加有助于你了解ShinningRay的评测报告。

引用一下评测的结论部分:

ShiningRay 写道

Lighttpd的三种方案占据了前三位,Lighttpd+FastCGI是性能最高的部署方式。这种方式比另一种流行方案Nginx+Mongrel的方式性能
提升了高达50%!FastCGI的好处在此体现出来:

• 二进制协议,无需HTTP的解析

• 与前端可以建立持久链接

• 没有锁和上下文切换的开销

另外Lighttpd相对于Nginx的优势在于请求和响应的接收缓冲区很大,省去多次接收和发送的开销。

Lighttpd+Thin的方式的性能列第三位,这点似乎出乎意料之外,但实际上是因为Lighttpd 1.5支持对HTTP后端建立HTTP KeepAlive链


接。在对后端单独的测试中,小并发下的Thin的KeepAlive测试性能并不比FastCGI差,同时Thin实现了非阻塞 IO,而FastCGI则是阻
塞式的。相反,HAproxy和Nginx则都不支持HTTP KeepAlive。

而Swiftiply的方式也显示出了强劲的性能,应该是得益于它的“让后端主动连接到Swiftiply”的这种特殊的结构。

当前备受关注的Passenger的部署方式在本案中并没有显示出特别的性能上的优势,不过如果将并发链接数放在300以内,则
Apache2.2/Prefork + Passenger的部署方式的平均每秒响应数上升为204.03,这样看来,倘若为Apache进行一些优化配置,依然不
失为一种高效的部署方案。而同时Passenger又是最容易配置的一种方案,能达到这种效果已经非常令人满意。

HAproxy + Mongrel并限制链接数为1,则是一种稳定、保守的部署方式,虽然在这里性能不出众,但是稳定性非常好。

第 149 / 283 页
http://robbin.javaeye.com 2.37 推荐一篇很好的RoR部署方案性能评测

最后,与Nginx相关的三种方案都排在了该榜的末尾,由于Nginx的反向代理负载均衡缺少一些高级的特性以及Rails本身的特性而导
致其不适合单独应用在Rails程序的部署上:

• 缺少到后台服务器端的链接数限制的能力,这导致了Mongrel在接受大量请求时将时间消耗在上下文切换和锁的争用上。

• 缺乏建立到后台服务器端的持久链接的能力,这导致了在链接的打开、建立、关闭上花费了额外的开销。

第 150 / 283 页
http://robbin.javaeye.com 2.38 对Ruby VM的GC的思考

2.38 对Ruby VM的GC的思考

发表时间: 2008-09-02 关键字: gc

Ruby虽然是动态脚本语言,但是和Java一样,带有VM,有自己的内存堆,创建对象的时候在堆里面分配内存,对象使用完毕由GC进行
回收。但是通过我们运营Rails网站两年多的实践来看,Ruby VM的GC还是存在很大的问题。简单的来说,就是GC之后,尽管对象已经
完全回收,但是物理内存释放不够充分,有泄漏的现象。通过pmap来dump ruby进程物理内存地址映射表进行分析,观察到ruby的内
存堆总是在不停的扩张,GC之后回收不干净。而我对比观察Java VM,其Full GC之后,物理内存释放的非常干净。所以用Ruby做服务
器长期的跑,就会发现Ruby进程没有理由的缓慢泄漏内存,内存堆缓慢增长,貌似没有上限。

由于pmap命令可以dump进程的内存映射表,因此我们可以对比RubyVM和JVM在GC前后的内存映射情况。比方说Ruby的内存状况大概
是这样的:

下图是一个Ruby进程的物理内存映射表,堆内存占据的空间是我抽取出来的三行:

00000000005d4000 125260K rwx-- [ anon ]


0000002a95c23000 23456K rw--- [ anon ]
0000002a99186000 50980K rw--- [ anon ]

0000000000400000 760K r-x-- /usr/local/ruby/bin/ruby


00000000005bd000 92K rw--- /usr/local/ruby/bin/ruby
00000000005d4000 125260K rwx-- [ anon ]
0000002a95556000 84K r-x-- /lib64/ld-2.3.3.so
0000002a9556b000 12K rw--- [ anon ]
0000002a9556e000 24K r--s- /usr/lib64/gconv/gconv-modules.cache
0000002a95574000 4K rw--- [ anon ]
0000002a95577000 12K rw--- [ anon ]
0000002a9557a000 204K r---- /usr/lib/locale/en_US.utf8/LC_CTYPE
0000002a9566a000 12K rw--- /lib64/ld-2.3.3.so
0000002a9566d000 8K r-x-- /lib64/libdl.so.2
0000002a9566f000 1024K ----- /lib64/libdl.so.2
0000002a9576f000 4K rw--- /lib64/libdl.so.2
......

可以看出来Ruby的堆内存分配比较连续,分段不多。而JVM的堆内存分配段就很多了,由于堆地址段太多,我就不贴出来了,大家可
以自己观察。

由于Ruby的内存分配算法和回收算法还是比较原始的,因此在进行多次回收之后,内存堆很容易出现大量的内存碎片,很多内存碎片

第 151 / 283 页
http://robbin.javaeye.com 2.38 对Ruby VM的GC的思考

并不能够被有效的利用,并且ruby没有好的碎片归并压缩算法,因此碎片造成的内存堆地址空间浪费就会越来越大。其结果就是Ruby
进程在长期高负载运行之下,表现出缓慢的内存泄漏现象!

对比JVM的堆分配,他分配了很多的段,每个段的内存存活期不一样,根据分代算法,可以把不同存活期的对象在堆之间移动,堆内
部则进行碎片归并。比方说我对一个Tomcat应用服务器的实际应用先pmap记录内存映射,然后GC,再pmap记录内存映射,两者diff一
下,就可以发现某些堆在收缩,但是某些堆甚至在GC后扩张了,这便是对象在堆之间进行移动的现象。因此我不得不赞赏一下JVM的
内存分配。

话说回来,由于Ruby的VM内存分配的碎片问题,导致Ruby进程几乎无可避免的内存泄漏。其结果就是你必须实时监控Ruby进程的运行
情况,一旦发现内存使用超过限额,则必须果断的杀掉进程重起。比方说现在很多流行的Rails网站都是用monit去监控mongrel实例,
一旦发现内存使用超过限额就杀掉重起。这种监控方式虽然可以有效的解决ruby的内存泄漏问题,但是太过简单粗暴,如果杀掉进程
重起的时候,Ruby进程正好在处理请求,那么该请求是肯定会失败掉的,对于一些极端的情况,似乎很难令人接受这种现象的存在。
我现在没有用monit,而是自己写shell脚本来监控(写几行shell就可以搞定的事情没必要那么麻烦搞什么monit),每天大概能出现两三次
这种需要杀掉重起的情况,对比每天要处理将近100 万动态请求来说,可靠性还是达到了99.999%,还算可以。

那么将于今年年底发布的ruby 1.9.1能够解决这个问题吗? 答案是悲观的,1.9的GC并没有本质的提高,可以预见还是会出现无可避免


的内存泄漏问题。但是1.9的内存泄漏会比现在的1.8要轻微一些,原因是1.9会对堆空间的内存碎片从小到大进行排序,因此对于内存
碎片的利用率要高一些,再加上1.9的GC相对来说更积极主动一些,因此在一定程度上可以减轻内存碎片问题。

但不管怎么说,在可以预见的未来,Ruby的内存泄漏问题无可避免,我们还是要做好动不动杀掉ruby进程重起的准备。所以你要好好
操练一下monit,或者像我一样,写个shell脚本进行监控,用crontab每隔几分钟跑一下。

我们的Rails部署方式是lighttpd+fcgi,用Unix Socket通信,监控脚本示例如下:

#!/bin/sh

. /etc/profile.local

RUBY_HEAP_MIN_SLOTS=600000
RUBY_HEAP_SLOTS_INCREMENT=600000
RUBY_HEAP_FREE_MIN=100000
RUBY_GC_MALLOC_LIMIT=60000000
RAILS_ENV=production
export RUBY_HEAP_MIN_SLOTS RUBY_HEAP_SLOTS_INCREMENT RUBY_GC_MALLOC_LIMIT RUBY_HEAP_FREE_MIN RAILS_ENV

SPAWN=/usr/local/lighttpd/bin/spawn-fcgi
DISPATCH_PATH=/.../yourrailsapp/public/dispatch.fcgi
SOCKET_PATH=/yourlighttpd/socket
PID_PATH=/yourlighttpd/pids

RSS_MAX=307200

第 152 / 283 页
http://robbin.javaeye.com 2.38 对Ruby VM的GC的思考

for PSDATA in `ps -e v | grep dispatch.fcgi | awk '{print $1 ":" $8 }'`


do
RSS=${PSDATA#*:}
PID=${PSDATA%:*}
if [ $RSS -ge $RSS_MAX ]; then
echo
echo `date`
echo "----------------------------------------"
echo "PID["$PID"]: RSS="$RSS"KB is too big!"
for num in 0 1 2 3 4 5 6 7 8 9
do
if [ $PID -eq `cat $PID_PATH/javaeye.pid-$num` ]; then
echo "PID["$PID"] using socket: "$num
kill -9 $PID
rm -rf $SOCKET_PATH/javaeye.socket-$num
$SPAWN -f $DISPATCH_PATH -s $SOCKET_PATH/javaeye.socket-$num -P $PID_PATH/javaeye.pid-$num
fi
done
fi
done

sleep 10

for num in 0 1 2 3 4 5 6 7 8 9
do
if [ ! -d /proc/`cat $PID_PATH/javaeye.pid-$num` ]; then
echo
echo "Ruby Server using socket: "$num" had been crashed, need to be starting..."
rm -rf $SOCKET_PATH/javaeye.socket-$num
$SPAWN -f $DISPATCH_PATH -s $SOCKET_PATH/javaeye.socket-$num -P $PID_PATH/javaeye.pid-$num
fi
done

第 153 / 283 页
http://robbin.javaeye.com 2.39 征求《Rails锦囊妙计》一书的写作内容建议

2.39 征求《Rails锦囊妙计》一书的写作内容建议

发表时间: 2008-10-31

《Rails锦囊妙计》这本书是dlee发起的,旨在面向Rails中高阶开发人员、指导实战的Rails书籍。这本书现在参与编写的人员是dlee,
Quake Wang,liusong111,骆古道和我。dlee主要介绍REST方面的编程,Quake写的是ActiveRecord的编程技巧,liusong111介绍
Controller和View方面的实战技巧,骆老师写的是jQuery on Rails和ActionMailer,而我主要负责性能和部署方面的内容。其他同志的进
度情况请咨询dlee。

我拟定了一下我负责内容的章节,总共三章内容,列举如下,请大家提提建议,看看需要删除哪些内容,需要补充哪些内容,谢谢!
然后我会根据这个目录开始写。

《Rails生产环境的安装和部署章节》

一、介绍和分析主流的Rails部署运行环境

1、Rails部署运行方式介绍
2、操作系统的选择:Red Hat Linux, CentOS, SuSE Linux,Ubuntu Linux,以及Windows
3、Rails运行服务器的选择:FastCGI,Passenger,Mongrel,Thin
4、Rails可选的Web服务器介绍:Lighttpd,Nginx,Apache
5、Rails部署运行主流方式介绍

二、Lighttpd/FastCGI部署运行环境的安装和配置
1、编译安装Lighttpd
2、配置Lighttpd/FastCGI
3、监控和调优Lighttpd

三、Nginx/Mongrel部署运行环境的安装和配置
四、Apache/Passenger部署运行环境的安装和配置
五、Apache/Mongrel部署运行环境的安装和配置

《Rails的性能调优和架构设计章节》

一、Rails部署运行环境的性能调优
1、操作系统的性能调优
2、数据库的性能调优
3、文件系统的选择

二、Ruby应用代码的性能调优

三、缓存策略和实战

第 154 / 283 页
http://robbin.javaeye.com 2.39 征求《Rails锦囊妙计》一书的写作内容建议

1、对象缓存策略
2、页面片断缓存策略
3、动态页面静态化
4、基于REST资源的缓存策略
5、Memcached介绍
1)memcached安装和配置
2)memcached监测
3)memcached原理探讨

四、和内存泄漏问题的斗争
1、Ruby VM内存分配策略分析
2、内存泄漏原因分析
3、内存泄漏监测工具介绍
4、Ruby进程的监控

5、Session问题的讨论
1)选择Session存储策略
2)基于Cookie的Session策略介绍

6、设计Rails应用的系统架构
1)多进程和多线程之争
2)如何安排合理的进程数量
3)设计可扩展性的系统架构

《Ruby on Rails实战解决方案点滴章节》

一、如何实现泛域名解析和多域名博客网站开发
二、如何集成全文检索功能
三、如何实时记录用户的在线状态
四、如何管理大量附件的下载和同步
五、如何利用好Rails的production.log
六、JavaEye网站的架构演进过程

第 155 / 283 页
http://robbin.javaeye.com 3.1 动态脚本语言的部署运行方式介绍

3.1 动态脚本语言的部署运行方式介绍

发表时间: 2006-09-18 关键字: Python ruby php perl

现在这类脚本语言的运行方式基本上有三种:

1、Apache Module方式

由Apache进程用module方式来管理,web请求的静态页面和动态请求都是由apache进程内部直接处理掉了。典型的如mod_php,
mod_ruby,mod_perl,mod_python。这种方式目前PHP和Perl比较多的采用。这种方式其实还是非常成熟的,apache对于内存管理已
经很好,运行效率各方面都很不错。当然apache进程之间也是SNA。

但是ruby和python一般不建议用这种方式,这是因为PHP和Perl解析器的开销非常小,以Apache Module方式跑很灵活而且不怎么消耗
资源;而ruby和python的解析器开销非常大,用这种方式,很浪费资源。例如一个PHP解析器跑起来才消耗2MB内存,一般也就
7-8MB。但是ruby解析器跑起来就是30MB内存,消耗多的时候高达200多MB。由于很多apache进程只是在处理静态资源,完全没有
必要带着一个庞大的ruby在跑,因此就显得过于浪费了。

2、FastCGI/SCGI

ruby on rails很流行使用FastCGI,Python则流行SCGI,也是SNA,比上面的方案在部署和cluster方面要灵活的多。这种方式下,web
server处理静态资源,将动态请求通过Unix Socket/TCP端口发送给后面的ruby/python进程来处理。一般来说,页面带有很多静态资
源,因此一次用户的动态请求实际上对应了web server的好几个连接去处理静态资源,和一个后台ruby进程去处理动态资源。因为把静
态资源和动态请求分开了,所以不再需要那么多的ruby进程来跑。据说一般经验公式是:apache进程数量如果是70个的话,那么
FastCGI方式的ruby进程只需要开10个,7:1的比例。另外每个ruby进程再执行一次之后就会hold住这个数据库连接,以后就会直接使用
了,避免了数据库连接的开销,已经类似Java的数据库连接池的作用了。

JavaEye2.0现在开了30个FastCGI的ruby进程,但是据我观察,大部分繁忙的时候,真正被用到的ruby进程也只有十几个而已。

3、ServerVM

Java和Zope都是这种方式,一个单一进程在跑,里面很多线程分别处理不同的动态请求,shared memory方式。有时候也会在前面放
一个web server提高静态资源的处理能力。这种方式大家都很熟悉了,不用多说。

第 156 / 283 页
http://robbin.javaeye.com 3.2 lighttpd的tunning tips

3.2 lighttpd的tunning tips

发表时间: 2006-09-21

http://trac.lighttpd.net/trac/wiki/Docs%3APerformanceFastCGI

lighttpd作者写的tunning tips,很值得看一看

lighttpd目前的开发十分活跃,我在期待1.4.12或者1.5.10的发布。

第 157 / 283 页
http://robbin.javaeye.com 3.3 Linux reiserfs文件系统即将陨落

3.3 Linux reiserfs文件系统即将陨落

发表时间: 2006-10-12 关键字: reiserfs hans

Linux著名的高性能文件系统reiserfs向来是Linux fans眼中的挚爱,但是reiserfs即将陨落。

前段时间已经风传Linux Kernel拒绝将reiserfs4加入kernel source,随后SuSE,这个reiserfs最大的赞助商也准备在下一个版本的SuSE


Linux中不再将reiserfs作为默认文件系统。

如果说由于政治原因导致reiserfs文件系统被排斥在Linux主流之外的话,Hans Reiser则亲手埋葬了自己和自己的作品:

最近Hans Reiser因为谋杀妻子的罪名被警方逮捕,而且警方拒绝辩护律师,估计证据已经确凿。Hans同学就算不是死刑,估计也得在
监狱里面度过余生了。Reiserfs文件系统,即将陨落。

http://www.idiom.com/~beverly/hans_resume.html

http://www.linuxeden.com/doc/24610.html

第 158 / 283 页
http://robbin.javaeye.com 3.4 软件行业2006年终回顾以及2007展望(一)回顾

3.4 软件行业2006年终回顾以及2007展望(一)回顾

发表时间: 2006-12-11 关键字: 年终总结

http://www.javaeye.com/topic/17785

buaawhl同学在2005年底发起了这个针对2006年的软件行业大预测。此时此刻2006年将近尾声了,那么这一年当中究竟在我们的行
业当中发生了些什么呢?有哪些预测已经应验,又有哪些预测将在未来一年当中发生呢?先让我们来回顾一下吧:

一、Red Hat收购了JBoss

这是三四月份发生的事情,收购对于JBoss来说是件好事情,傍上了一颗大树,可以借助Red Hat的力量把JBoss的服务拓展到全球,而
这对于只有几十个人的小公司JBoss来说是无能为力的。

对于Red Hat来说,喜忧掺半,喜则产品线齐全,忧则Oracle成了对手。这不,不久前Oracle就推出基于Red Hat Linux的Unbrekable


Linux以打击Red Hat。

二、EJB3.0规范正式推出

在五月的JavaOne,EJB3.0规范正式推出。到年底之前完整通过EJB3.0认证的Hibernate3.2已经推出,包括Spring2.0提供的标准JPA支
持,EJB3.0已经不存在技术上的推广障碍。但是似乎姗姗来迟了些。

三、Spring2.0的发布

Spring2.0的发布也算千呼万唤使出来了,功能继续增强,产品线继续完善,大有一统J2EE江湖,吞噬EJB3.0之势。当然不出意外的
是,配置文件继续复杂化,产品整体越来越庞大和臃肿,也开始让越来越多人垢病。

四、Java彻底开源

Java开源是Sun在2006年抛出的重磅炸弹,其影响之深远,要到数年之后才能下定论。可以预见的是在未来两三年中,Java行业会出
现很多令人惊奇的开源产品。

五、ruby on rails继续独领风骚

在2006年,忽如一夜春风来,各种快速开发框架如千树万树梨花开。不用问,这都是被rails刺激。Groovy,Django,Able,Seam,
Rife,Stripes,数不胜数。不过rails能够领先的秘诀其实是其设计思想的领先。在年初rails1.1版本推出,RJS,DB Migration功能的引
入让rails耳目一新。年底rails1.2RC版本推出,REST架构更让其他框架望尘莫及。

总结陈词:

第 159 / 283 页
http://robbin.javaeye.com 3.4 软件行业2006年终回顾以及2007展望(一)回顾

在Java领域,2006年是富有转折性意义的一年:
Java开源给未来带来很多有趣的不确定性;
Spring2.0在事实标准方面继续领跑EJB3.0,社区力量战胜了厂商意志,另外值得一提的是厂商一直吹捧的JSF仍旧一副阿斗的样子;
Java领域受rails刺激开始走向full-stack的快速开发道路,并且积极吸纳脚本语言,而JVM开始走向平台化。

ruby on rails在2006年在国外的社区当中呈现火爆的态势,并且开始在国内慢慢普及。

接下来我们回顾一下那些曾经被吹捧的技术,如今的情况如何:

1、JSF,EJB3
JSF是厂商大力吹捧了n年的web框架,到现在还扶不上墙;EJB3比较特殊,刚刚推出还不好下断言,其中的JPA部分也是被大家所相当
看好的。但不管怎么说并没有厂商期望般火爆。

2、AOP
AOP在2006年始终不温不火,不过AOP的应用确实越来越普及了。

3、SOA
在2006年有一个现象,“咸与SOA”,是个人都会去讨论一下SOA,搞构件的普元也开始SOA了,SOA是一个2006年彻底被用烂的词
汇,而真正的SOA大家还都没有接触到。

4、AJAX
AJAX在2005年就开始火爆了,在2006年一直表现平稳,规规矩矩。

5、Spring
Spring是2005年大红大紫的Java框架软件,在2006年毫无疑问更上层楼了,当然在未来几年似乎仍旧成为Java主流开发框架,但是
Spring的弱点似乎也越来越被大家所讨论了。

至于那些2005年曾经被唱衰的技术呢?

1、ruby语言和rails框架

不错,2005年底,ruby语言和rails框架还处在被主流开发社区所排斥的地位,也有很多人预测rails将昙花一现,不过如今rails越活越
红火了。

2、Struts1.x

Strutx被唱衰也不是一年两年,竟然还能挺到现在,证明了Struts顽强的生命力。

第 160 / 283 页
http://robbin.javaeye.com 3.5 软件行业2006年终回顾以及2007展望(二)展望

3.5 软件行业2006年终回顾以及2007展望(二)展望

发表时间: 2006-12-11 关键字: 年终总结

http://www.javaeye.com/topic/17785

buaawhl同学在2005年底发起了这个针对2006年的软件行业大预测。此时此刻2006年将近尾声了,那么这一年当中究竟在我们的行
业当中发生了些什么呢?有哪些预测已经应验,又有哪些预测将在未来一年当中发生呢?让我们大胆的预测一下2007吧:

一、Java开源会带来什么?

Java开源的意义非常深远,仿佛解除了套在Java身上的枷锁,任何厂商都可以在遵循GPL的前提下自行改造Java和JDK。在未来的一年
当中,我们必将看到很多基于Java的有趣的产品和创意诞生。事实上我认为07年对Java来说,是至关重要的一年,这一年将奠定Java
开源今后的发展方向,也许今后我们不再期待Sun的JDK版本升级,而是其他厂商或者社区的JDK版本升级。

二、Ruby语言和Rails框架会更加普及

在2005年rails尚且只是被少数人接受,在2006年国外的rails社区已经是火爆一片,国内的rails应用也开始呈现星星之火,2007年我
们将可以看到更多的rails应用出现。

三、AJAX屹立不倒

Windows Vista携带dotnet3.0 framework就要发布了,仿佛Microsoft要改变浏览器统治桌面历史的序幕就要拉开了。但是我的预测却是


AJAX不但是一种过渡技术,也将成为长期存在的技术。XAML无法改变互联网HTML的实质-超联接,就无法改变浏览器统治桌面的局
面。

第 161 / 283 页
http://robbin.javaeye.com 3.6 从分布式系统的角度看REST

3.6 从分布式系统的角度看REST

发表时间: 2007-05-23 关键字: rest

上周末在杭州网侠大会做了关于REST的演讲。会后经过一些交流,特别是今天在msn上面和dlee的交流,感觉自己对于REST的理解更
深入了一层。

我们说REST架构风格,从REST具备的内在特征来说,它包括了这些特征:

1、基于HTTP的资源
2、以HTTP协议去操作
3、数据和表象分离

但是如果我们换一个角度,即分布式应用系统的角度来看,我们会有一些更有意思的结论:

分布式应用系统的架构,经历了好几代的变迁,我们来简单回顾一下:

1、基于CORBA协议的C++中间件时代
CORBA时代我还在上学,基本上没有怎么接触过Corba编程。曾经有一次我提供EJB培训的客户,正在进行传统Corba架构向EJB2架构
迁移,通过和他们的交流,对Corba多了一些了解。当时就感叹,和EJB2相比,Corba实在太难用了。Corba时代在1998年EJB1.0发布
以后,就逐渐淡出历史舞台了。

2、基于RMI/IIOP协议的EJB时代
这个时代开始于1998年,到现在基本上已经划上了句号。其实在EJB出现以前,在1996年Microsoft发布WindowsNT4.0以后,
Microsoft当时也提出了自己的分布式架构,即MTS,但是MTS的光辉被随后出现的伟大的EJB技术彻底击败,此后,就拉开了Java的应
用服务器时代,BEA也是在这个时代的转折点成长起来的。

不管是Corba,还是EJB,都有一些共同点:
1) 通过专有的网络协议通讯
2) 不能跨平台调用
3) 通过分布式对象调用来实现分布式架构,换句话来说就是,分布式架构是绑定在面向对象的机制上的

分布式对象架构的缺陷在EJB2时代被充分暴露了出来,乃至于Martin Folwer在《企业应用架构模式》当中强调,分布式调用的第一原
则就是不要分布式。更多关于EJB2分布式对象架构的缺陷在Rod Johnson的《J2EE without EJB》当中被剖析的更加清楚。

3、基于SOAP协议的Web Services时代
这个时代始于2001年Microsoft公司推出dotnet平台,整个行业开始鼓吹Web Services。中间经历了一次低潮之后,在IBM,BEA成功的
联手炒作SOA之后,再次王者归来。

web services有一些明显不同于Corba和EJB分布式对象架构的特征:
1) 通过标准SOAP协议通讯,一般走HTTP通道
2) 能够跨平台调用
3) 通讯格式是xml文本,而不是二进制数据格式
4) 通过RPC机制来实现分布式调用,而不是通过面向对象机制实现分布式调用

第 162 / 283 页
http://robbin.javaeye.com 3.6 从分布式系统的角度看REST

web services的优点和缺点都非常突出,这个不是本文的要点,不做具体分析。这里唯一要强调的是SOAP协议并不依赖于HTTP。事实
上SOAP协议可以走很多底层协议,例如SMTP协议,Jabber协议等等。

REST也是一种分布式系统的架构风格,那么REST和上面这些分布式架构有哪些明显的区别呢?
1) REST走的是HTTP协议,并且充分利用或者说极端依赖HTTP协议
Corba和EJB是采用专有的二进制协议,SOAP可以但不依赖HTTP,并且仅仅使用HTTP POST。
2) REST是基于HTTP抽象资源的分布式调用,换句话来说,就是分布式调用是绑定在资源的操作上面的。

通过上面的总结,我们可以做一个直观的对比表格:

分布式架构 协议 调用方式
-------------------------------------------------------
Corba架构 专有二进制协议 对象的CRUD操作
EJB架构 专有二进制协议 对象的CRUD操作
Web Services SOAP协议 RPC方式
REST HTTP协议 对资源的CRUD操作
--------------------------------------------------------

REST最大的特点是什么呢?REST是为通过HTTP协议来进行分布式调用量身定造的架构

传统上,我们开发一个非分布式的软件系统,使用OO进行建模和架构,无往而不利。但是分布式对象却显得不那么有效。对于跨进程
的调用,也许我们需要探索更好的面向对象的分布式调用架构。

REST是专门为分布式调用设计的架构,在REST里面,分布式是通过对资源的操作来实现的,不是像EJB那样通过对象的方法调用来实
现的。资源是一种抽象的概念,资源被映射到相应的一套URL规则上面了。所以资源只和URL相关,而与具体实现无关,因此REST具
有更好的解藕性。在RoR的实现当中,你可以把一些资源直接映射到model对象上面去,也可以不映射到model上面,而完全是由业务
逻辑组合的抽象资源。

第 163 / 283 页
http://robbin.javaeye.com 3.7 AJAX与RIA技术之我见

3.7 AJAX与RIA技术之我见

发表时间: 2007-08-02 关键字: ajax flex

DHH于6月底曾经发表过一篇文章,名为《我就喜欢HTML/CSS/JavaScript,那又怎么样!》,大意是说,目前热炒的RIA技术并不能
够取代AJAX技术,而事实上我们还没有发挥出HTML的全部潜力,我本人很享受HTML/CSS/JS给给我的开发体验云云。

我比较赞成DHH的观点,从另外一些角度谈谈我对RIA技术,主要是Flex的看法。

我在2004年曾经指导一个企业应用系统的开发,这个系统提出了比较高的实时反馈和交互式要求。由于同时有两个flash高手加盟,我
们决定采取基于flash的RIA技术:

对于交互要求非常高的部分使用flash开发,flash通过AMF协议和服务器端通讯,服务器端使用了OpenAMF这个开源框架,可以解析
AMF请求,转化为对Spring bean的调用,这个架构是一个标准的分布式系统调用:

flash <-----AMF-----> OpenAMF网关 <--> Spring Ioc

和现在很多人普遍采用的AJAX DWR框架是一个道理:

IE <-----XHR-----> DWR <--> Spring Ioc

客户端的flash是先用Flash IDE画好界面元素,保存为fla文件,然后程序员使用ActionScript编写代码,和服务器端进行交互。这是一个
标准的基于Flash的RIA方案,但是项目最终放弃了Flash RIA。

时至今日,REST+Flex又被作为一个非常热门的方案被提出来了,那么REST+Flex比2004年我们采用的AMF+Flash方案有什么区别呢?

一、服务器端和客户端交换数据的方式不同

1、AMF+Flash采用的是标准的RPC方式,这种方式的被广泛的使用在EJB,XML-RPC,DWR等等,这种方式的缺点这里不赘述了,
JavaEye以前有大量的讨论

2、REST+Flex采用的是REST方法,这种方式是现在非常热门的轻量级分布式系统解决方案之一,优点也不赘述了,JavaEye也有大量
讨论

二、客户端描述界面的方式不同

1、AMF+Flash采用标准的Flash IDE来画界面,保存为fla后缀的二进制文件,界面文件不可直接用文本编辑器编辑,一般程序员很难使
用。

2、REST+Flex采用Flex Builder来画界面,或者用文本编辑器手工编写MXML,这是一种带有namespace的XML的文件,程序员比较容
易使用。

通过比较我们可以发现,REST+Flex的方案已经前进了一大步,但是我还没有提到为什么2004年那个Flash RIA方案会失败,为什么
呢?失败的最重大的原因在于开发成本!

第 164 / 283 页
http://robbin.javaeye.com 3.7 AJAX与RIA技术之我见

你会说,我们用AJAX开发成本也很高阿,HTML/CSS/JS跨浏览器兼容性的成本非常高。Flash不用考虑跨浏览器,界面还可以用IDE直
接画,AS代码和MXML界面彻底分离,多棒的MVC,开发效率怎么想都比AJAX低很多。不错,Flash没有跨浏览器开发成本,但是Flash
有一个巨大的和网页交互的成本。

这又牵扯出来一个更深层次的问题:互联网传播的主要载体是什么?文本?图片?视频?还是其他的什么?

HTML的诞生是适应于互联网大量文本内容的传播的,只要你的web应用还是以文本为主,就必须以HTML为主,这一点无法改变。那么
就意味着你的Flash RIA必须要大量的和HTML页面进行交互。(也有一些纯网络游戏或者休闲游戏网站是纯flash的,几乎没有HTML,但
这不是我们讨论之列)

所以问题就在于Flash和网页的大量交互,但很遗憾的是Flash操纵网页DOM的能力很弱,与传统的JavaScript无法相提并论!所以你会
遇到各种意想不到的问题,而这些问题原本用JavaScript却是很简单的事情,例如驱动网页导航,刷新,打开关闭窗口,DIV隐藏显示
等等,开发成本就是这么不知不觉升上来的。最终你会发现Flash的开发成本太高!

其实这不能怪Flash,根源在于:你开发的web应用最终还是一个基于文本形式的,所以你就无法使用纯Flash应用(Flash对于文本支持
能力又很弱),必须大量依赖HTML;而要大量操纵HTML,最趁手的工具就是JavaScript,而Flash就是一个很蹩脚的工具,无论它的多
媒体表现能力多么强大。

SilverLight能改变这一点吗?不能!Microsoft发明XMLHTTP绝对是天才的创意,XMLHTTP之所以成功根本原因在于它和HTML的良好交
互性,而且使用JS操纵。SilverLight只是Flash的一个模仿品,却完全没有看到Flash的局限性在哪里?所以SilverLight完全继承了Flash
的致命缺点。这也只能说明SilverLight是Microsoft商业竞争的一种手段,而不是本着创新精神去做的东西。

现在开发AJAX的确有其痛苦之处,跨浏览器兼容性是最让人头疼的。但是我们应该清楚,只要web应该是基于文本形式这一点不改
变,那么HTML/JS的地位就不会改变,那么AJAX无论如果都是web开发之首选技术。

第 165 / 283 页
http://robbin.javaeye.com 3.8 关系模型和对象模型的究竟匹配还是不匹配?

3.8 关系模型和对象模型的究竟匹配还是不匹配?

发表时间: 2007-12-27

在过去的很多年,我以为关系模型就是传统的企业应用当中DBA设计的那些无数冗余字段,多个模型合并到一个表里面的数据库设计
方式,这种数据库设计非常适合复杂的OLAP类型的查询,他可以有效的消除多表联合查询,而我们大家都知道,大表的复杂关联查询
是性能杀手,一旦无法有效利用索引,导致了全表扫描,等待你的只有数据库服务器硬盘灯的狂闪不止,和无数进程阻塞在IO WAIT状
态的无奈。

我前几个月订购了一本人邮图灵出版的《MySQL 5 权威指南》第三版中文版,买这本书只是因为有人送我China-Pub的优惠券,我就顺
手买本MySQL的书,用来管理JavaEye服务器的时候备查的。其实这本书内容很一般,他说的东西我都知道了,所以这本书我拿过来随
手翻了翻就感觉到买的不值得。但是当我随手翻到第8章第5节第138页介绍什么是三大范式的时候,我终于知道我错了。

从138页到142页,作者深入浅出举例说明了三大范式,我被震了,就这几页让我觉得买这本书值了。对于我这个不是计算机科班出身
的人来说,到现在才知道什么是三大范式不算可耻。我震惊的只是三大范式和我们现在遵循ORM的原则去设计数据库的方式如出一
辙!我简单摘要书中内容如下:

引用

第一范式:
1、内容相似的数据列必须消除(消除的办法就是再创建一个数据表来存放他们,建立关联关系)
2、必须为每一组相关数据分别创建一个表
3、每条数据记录必须用一个主键来标示

第二范式:
1、只要数据列里面的内容出现重复,就意味着应该把表拆分为多个表
2、拆分形成的表必须用外键关联起来。

第三范式:
1、与主键没有直接关系的数据列必须消除(消除的办法就是再创建一个表来存放他们)

这三大范式就像给ORM的人如何设计数据库写的指南:

引用

第一范式:
1、每个持久对象映射一张表
2、每个持久对象必须有一个主键

第二范式:
1、持久对象要有内聚性,冗余的内容拿出去,单独创建持久对象
2、持久对象之间的关系用外键关联

第 166 / 283 页
http://robbin.javaeye.com 3.8 关系模型和对象模型的究竟匹配还是不匹配?

第三范式:
1、持久对象要有内聚性,无关的内容拿出去,单独创建持久对象

关系模型和对象模型是不是在存储概念上一致,就不用多说废话了。

说关系模型和对象模型“阻抗不匹配”,当然是有不匹配的地方,比方说对象模型当中特有的“继承”,“组合”,“聚合”,“依赖”的概念在关
系模型当中是不存在的,但是这种模型的“阻抗不匹配”最终在存储模型是还是能够统一起来的,这就是ORM的作用:

1、对象的继承关系可以表达为三种不同的关系存储模型:整个继承数一张表;每个继承层次一张表;每个对象一张表

2、对象的组合和聚合可以用主外键关联的表来存储,它可以表达1:n,n:1和n:m的关系

3、对象的依赖关系和存储无关,所以不需要ORM做什么。

所以结论就是这样:

关系模型和对象模型存在概念上的阻抗不匹配,但是在关系数据库的存储模型上是一致的,无论你从关系模型的三大范式理论出发,
还是从对象模型的ORM理论出发,最终一定会得到一致的数据库表设计。

这里值得我们反思的一个问题是:为什么传统的数据库应用人们这样漠视和违反三大范式?在很多所谓的金融、电信等超级大项目当
中,连主键都没有的表比比皆是,一张表上百个字段,字段之间没有什么逻辑关系的情况比比皆是?

我想答案在于:传统的数据库应用软件开发,程序员很难从符合三大范式的数据模型当中获得有效的查询性能。符合三大范式就意味
着数据库表会拆分的很细,表间关联很多,统计分析查询就不可避免的导致n张表的联合查询,在没有有效的应用层缓存的情况下,这
种查询无可避免的性能低下。这使得程序员宁肯违背三大范式,而选择查询性能优先的数据库设计。

但是我们现在不一样了,有了良好的ORM框架和应用层的对象缓存机制,我们可以做到:让比较简单的查询根本不打扰数据库,让比
较复杂的查询尽量少的扫描表记录,其最终达到的效果在OLTP类型的应用上面效果远远超过传统的方式。

以JavaEye网站为例:JavaEye使用了Rails的ActiveRecord ORM,表设计符合三大范式,所有页面都是动态页面,要对数据库发送大量
查询,很多Web页面至少要向数据库发送50条以上的SQL语句。根据对数据库和Memcached Server的统计数据表明:JavaEye网站平均
每秒向数据库发送140条SQL语句,平均每秒向Memcached Server发送250次缓存查询,缓存命中率大概为85%,也就是说缓存服务器
要比数据库服务器繁忙将近一倍,而Ruby应用程序的数据有60%是来自Memcached Server,而只有40%是直接来自MySQL的。

为了加深大家印象,再给大家一个数据,目前JavaEye的Web服务器CPU负载在40-60%左右,而JavaEye的数据库服务器CPU负载只有
20%-30%,IO WAIT几乎没有。所以良好的遵循三大范式,利用好ORM和对象缓存,可以取得非常棒的应用性能,还可以让你的数据库
更加轻松。
最后,我的结论就是对象模型和关系模型在数据库存储上不存在阻抗不匹配,面向对象的程序设计和面向数据库的程序设计应该是一
致的,而不应该是对立和冲突的,请不要把面向对象和面向数据库对立起来,不是他们对立,而是你不了解什么才是真正良好的设
计。

第 167 / 283 页
http://robbin.javaeye.com 3.9 豆瓣的程序性能真的很惊人,但...

3.9 豆瓣的程序性能真的很惊人,但...

发表时间: 2008-01-17

http://www.dbanotes.net/arch/douban_web_server.html

在老冯同学的博客上看到的文章。里面介绍说豆瓣网站的情况如下:

一台Web服务器运行Lighttpd,每天处理2500万个request,峰值每秒处理1000个request;
一台应用服务器运行Python,每天处理500万PV;
数据库服务器运行MySQL,负载情况没有介绍。

我对比了一下JavaEye网站的服务器运行情况,我们是一台Web+应用服务器,一台数据库服务器,如下:

Web服务器运行Lighttpd,每天处理430万个request,峰值每秒处理150个request,平均每秒处理50个request;
Web服务器运行Ruby 1.8.6 + Rails 1.2.6,每天处理70万动态请求(去掉404,301状态的请求,只统计200的),如果算PV的话,去掉
RSS订阅请求,AJAX请求,估计PV在60万左右;
数据库服务器运行MySQL,CPU负载不高,在5%-30%之间波动。

豆瓣的Lighttpd峰值每秒处理1000个request,到不让人觉得意外,因为Lighttpd本身就是设计能够并发处理上万个request的。但是豆
瓣用单台服务器支撑500万动态请求,确实是很惊人的数据!看阿北介绍说,豆瓣的应用服务器是一台单颗双核AMD Opteron,
JavaEye的Web服务器是两路老的单核的AMD Opteron,主频是2GHz,豆瓣的应用服务器是新的单颗双核AMD Opteron,主频不详。

目前JavaEye的Web服务器运行Lighttpd,Memcached,Email Server和Ruby的FastCGI,除了ruby之外,其他应用消耗的CPU资源都极
少,Web服务器在峰值期间的CPU负载在35-50%之间波动,非峰值期间回落到20-30%。假设应用程序不做针对性优化,我估计这台服
务器可以支撑到100万到120万PV,但要更高就很困难了。不过JavaEye要达到这样的访问量,估计还得一年时间。到那个时候再想办
法也不迟。不过设想到这样的程度,我到宁愿加一台服务器立马解决问题,而不是投入人力去费时耗力的优化程序代码。

豆瓣使用的Python性能要比Ruby好很多,但即便如此,在同样硬件条件下,用Python支撑到500万以上,也是非常困难的,可以想像
的是大量运用了页面的局部缓存,以及对程序和框架的优化达到了极致,这一点,不得不佩服豆瓣的技术人员的性能优化水准和所下
的功夫。

不过,对于豆瓣只用一台应用服务器支撑500万PV,我觉得没有必要。豆瓣有2000万人民币的投资,增加一台服务器一次性开支不超
过1.5万,每年托管费多支出0.5万而已,九牛一毛。但在今天一个资深程序员月薪都要超过1.5万的情况下,为了节省这点钱而需要对
应用程序进行深度优化而投入的人力成本,远远超过2万元。豆瓣新版本刚上线的一段时间之内,网站访问速度非常缓慢,最近速度慢
慢的提升上来了,似乎也从侧面证明了这一点。干吗不多部署几台应用服务器,让用户从一开始就享受良好的速度体验呢?而用一台
应用服务器支撑,等着优化程序代码来提升访问速度呢?CSDN网站每天有600多万访问量,比豆瓣的访问量略高一些,CSDN有30多
台服务器,其实服务器少不见得就有多好,服务器多也不见得就是什么坏事。用投入硬件的方式可以解决的性能问题,总是会比软件
优化方式来得成本低。

第 168 / 283 页
http://robbin.javaeye.com 3.10 memcache_engine + memcachedb = 高性能分布式内存数据库

3.10 memcache_engine + memcachedb = 高性能分布式内存数据库

发表时间: 2008-01-22 关键字: memcachedb

memcachedb是一个由新浪网的开发人员开放出来的开源项目,给memcached分布式缓存服务器添加了Berkeley DB的持久化存储机制
和异步主辅复制机制,让memcached具备了事务恢复能力、持久化能力和分布式复制能力,非常适合于需要超高性能读写速度,但是
不需要严格事务约束,能够被持久化保存的应用场景,例如memcachedb被应用在新浪博客上面。

memcachedb给memcached添加了一些数据库才具备的特性,但是我们还不能说memcachedb已经是一个数据库了,这是因为
memcached不支持内存对象的遍历操作,当然更加不能支持复杂的查询操作,只能支持根据已知的key去查询对应的value。因此如果
想把memcachedb当成一个高性能的分布式内存数据库来使用的话,查询的问题就没有办法解决,只能在应用程序里面配合其他方案
做一些折衷。

然而memcached的另外一个开源项目完美的填补了这一个缺陷,就是memcache_engine。

memcache_engine是一个MySQL数据库的存储引擎,目前只支持MySQL5.1数据库,他能够把memcachedb作为MySQL数据库的一个存
储引擎和MySQL集成起来,让用户通过标准的SQL查询语句访问memcachedb中存放的数据,请看如下示例:

CREATE TABLE `a` (


`a` int(11) NOT NULL DEFAULT '0',
`b` int(11) DEFAULT NULL,
`c` int(11) DEFAULT NULL,
PRIMARY KEY (`a`)
) ENGINE=MEMCACHE DEFAULT CHARSET=latin1
CONNECTION='localhost:6666\;localhost:6688';

创建表a,存放在分布式memcached server:localhost:6666和localhost:6688当中。然后我们就可以使用标准的SQL语句随意的进行
CRUD操作去使用memcachedb了,这实在是太酷了!有了memcache_engine,我们就可以用SQL去访问memcached,有了
memcachedb,我们就不必担心数据丢失问题,事务恢复问题了,简直是绝配,让memcached真正成为了一个高性能的分布式数据库
系统了。目前memcache_engine项目还是早期试验阶段,让我们期待memcache_engine项目早日发布正式版本吧!

顺便多说几句:最近一年来,特别是最近一个月以来,围绕memcached的开源项目发展的非常非常活跃:

1、最近刚刚发布了memcached的新的高性能C客户端接口: libmemcached

2、由于有了libmemcached,该组织又发布了memcache_engine存储引擎,cool!

3、由于libmemcached的发布,不到一周时间,ruby的两个崭新的memcache client就问世了,他们是Caffeine和New memcache-


client,让ruby访问memcached的速度大幅度提高,请看:libmemcached发布了,ruby访问memcached提速20倍

4、memcachedb发布了,这是中国的互联网公司贡献的开源项目

第 169 / 283 页
http://robbin.javaeye.com 3.10 memcache_engine + memcachedb = 高性能分布式内存数据库

以上几个项目都是在2008年1月发布的,真的不是一般的繁荣阿。再加上之前发布的新的支持异步访问的Java Memcached API和C#接


口,可以说除了Python,其他主流非主流编程语言都可以使用memcached了。其实即便是Python还没有公布出来的开源接口,我们也
知道国内的web2.0网站豆瓣就是使用Python访问memcached,并且支持了极大的访问量,因此目前围绕memcached的开源项目发展的
情况非常的繁荣。

memcached最近两年这么受欢迎,其实和互联网web2.0的流行有很大的关系,web2.0网站通常需要个性化页面,依赖于页面局部和
数据细颗粒度的缓存来提升性能,并且web2.0网站流量都很大,因此memcached这种高性能分布式缓存服务器就大行其道了。

当然我觉得最具有革命意义的还是memcache_engine和memcachedb这两个项目的发布,他们能够让memcached的用途不仅仅限于缓
存服务器而已,而是能够真正充当分布式数据库来使用了,这无异是诸多大流量web2.0网站和开发人员的福音阿。

第 170 / 283 页
http://robbin.javaeye.com 3.11 用Google的网站流量分析系统来看全球软件行业的分工趋势

3.11 用Google的网站流量分析系统来看全球软件行业的分工趋势

发表时间: 2008-06-25

用Google的网站流量分析系统来看JavaEye网站介绍用了Google Trends来分析互联网网站的用户构成比例,通过参考网站的用户还搜索
了什么关键字,我们可以窥视一下这个网站的用户究竟都是干吗的。接着我们还可以用Google Trends来分析编程语言在全球软件行业
的分工趋势。

先分析一下Java编程语言在全球软件行业的分工情况

我们可以用Google Trends来搜索如下网站:

看Sun网站的趋势

看Apache开源网站的趋势

看JBoss网站的趋势

看Hibernate网站的趋势

看Springframework网站的趋势

看TSS网站的趋势

看OnJava网站的趋势

大家还可以不厌其烦的列举下去,不过所有这些全球主流的Java相关的网站都有一个明显的趋势,请大家点击链接以后看趋势图左下
角的国家和地区排名:

1、来自印度的流量遥遥领先于美国
2、一般都是印度流量第一、美国流量第二、日本流量第三、中国流量第四
3、欧洲的流量很小

这说明了什么?印度竟然全面领先美国?

接着看.NET编程语言在全球软件行业的分工情况

看MSDN网站的趋势

看codeplex网站的趋势

看Microsoft网站的趋势

第 171 / 283 页
http://robbin.javaeye.com 3.11 用Google的网站流量分析系统来看全球软件行业的分工趋势

1、美国的流量超过了印度,印度流量大幅度下降
2、日本的流量明显下降,中国和日本非常接近

好的,然后我们看看PHP编程语言吧

看PHP.net网站的趋势

看Zend网站的趋势

看PHPBuilder网站的趋势

1、印度流量排名第一、美国排名第二
2、中国和日本流量明显下降,而欧洲流量明显上升

然后我们再看ruby

看Rails官方网站的趋势

看rubyforge.org网站的趋势

1、美国夺回流量第一的宝座,印度流量大幅度下降
2、中国和日本的流量上升明显,欧洲流量也在上升

最后我们看看Python

看Python官方网站的趋势

看django网站的趋势

1、美国流量遥遥领先,印度大幅度下降
2、中国流量上升非常明显,而日本流量有小幅度下降,欧洲流量上升明显

好了,现在我们总结一把吧!

我们现在总结一下趋势:

1、Java是企业应用开发的主流编程语言,印度作为全球软件外包第一大国,当仁不让的夺取了Java流量排名第一的位置,当然我们也
可以看到,印度和中国这两个致力于发展软件外包的国家在Java的流量上面是非常高的。而美国在Java方面的流量却非常逊色于印
度,美国人都去研究什么去了?

第 172 / 283 页
http://robbin.javaeye.com 3.11 用Google的网站流量分析系统来看全球软件行业的分工趋势

2、.NET方面,美国领先于印度,中国的流量也不少,日本不算多。看起来美国人更倾向于把Java项目外包到印度,而公司内部项目自
己用.NET去做,而日本明显对.NET不太感冒。

3、PHP是互联网第一大web编程语言,印度又超过美国了,美国人的兴趣究竟在什么地方?值得注意的是,中国流量很小,看起来
PHP在中国程序员接受度并不高。

4、Ruby和Python方面,美国开始遥遥领先,答案揭晓了,美国人都跑去钻研Ruby和Python去了,而中国在这方面看起来关注度也不
错。

基于这个趋势,我们可以分析一下:

1、美国作为全球软件行业的领导者,目前的关注点更多的放在了新兴技术上面,比方说.NET比Java要晚五年出现,于是美国人更关
注.NET,而动态脚本语言方面Ruby和Python更加是美国人关注的焦点内容。

2、印度作为软件外包大国,焦点在Java和PHP上面,做外包项目嘛。

3、日本对.NET和Python不太感冒,而对Java和Ruby的关注度很高。

4、欧洲对Java和.NET都不太感冒,而对PHP/Ruby/Python等脚本语言关注度很高。

5、中国的情况看起来最复杂,无论哪个方面排名都不是非常靠前,但无论哪个方面排名都不是特别靠后,几乎所有的主流技术都会被
关注。

我个人的感觉是美国人还是很聪明的,把产业链下游的成熟技术都弄到印度去做,自己钻研产业链上游的创新技术;
而日本和欧洲显得非常有自己的主张,不会受别人影响,清楚自己需要的是什么;
而印度不用说了,庞大的外包市场,跟着外包走的;
至于中国的情况很复杂,既有外包的盲从一面,也有追逐创新技术的一面。

第 173 / 283 页
http://robbin.javaeye.com 3.12 贴一段遍历memcached缓存对象的小脚本

3.12 贴一段遍历memcached缓存对象的小脚本

发表时间: 2008-10-13 关键字: memcached

memcached因为性能的缘故,没有提供遍历整个缓存当中对象的功能,不过memcached也提供了很多命令来监控memcached的状
态,例如stats命令就有:

stats
stats reset
stats malloc
stats maps
stats sizes
stats slabs
stats items
stats cachedump slab_id limit_num
stats detail [on|off|dump]

不一一详细解释了,比较有价值的是stats items和stats cachedump,以及stats detail dump这几个命令,用前两条命令,实际上我们


可以遍历整个memcached缓存(尽管效率低下),后一条命令则可以显示最近memcached当中对缓存对象的详细操作情况。

因为我想详细了解一下JavaEye在线运行的memcached服务器当中缓存对象的详细情况,所以花了几十分钟用ruby写了一个小脚本,用
来方便的统计缓存对象,此外它还可以让你方便的发送stats命令。用法很简单:

1、统计memcached server当中的对象:

./memcached.rb

输出的结果大致是这样的:

Problem : 4564
GroupPost : 5643
User : 27133
Group : 144
...
Post : 44442
PostText : 255286
......
views : 36260
Forum : 27
Category : 15065

第 174 / 283 页
http://robbin.javaeye.com 3.12 贴一段遍历memcached缓存对象的小脚本

可以告诉你每个对象缓存的确切数量,比方说PostText被缓存了25万个对象,页面被缓存了3.6万个。这个统计方法是根据Rails内置的
Cache生成的key做的解析,也许你要根据自己的应用调整一下解析代码。

2、统计memcached的对象和对象的大小

./memcached.rb stats sizes

3、监控memcached的缓存操作情况
./memcached.rb stats detail on
./memcached.rb stats detail dump
./memcached.rb stats detail off

以下是该脚本的源代码,写的很粗糙。

#!/usr/bin/env ruby
require 'socket'

# stats
# stats reset
# stats malloc
# stats maps
# stats sizes
# stats slabs
# stats items
# stats cachedump slab_id limit_num
# stats detail [on|off|dump]

class Memcache
class << self
def open(host, port)
s = TCPSocket.open(host, port)
yield s if block_given?
ensure
s.close if s
end

def command(command_string, s)
s.send(command_string + "\r\n", 0)
buff = []
until ["END", "OK", "DELETE", "ERROR"].include?(line = s.gets.strip) do
buff << line

第 175 / 283 页
http://robbin.javaeye.com 3.12 贴一段遍历memcached缓存对象的小脚本

end
buff
end

def exec(command_string, host = "javaeye", port = 11211)


open(host, port) { |socket| command(command_string, socket).each {|line| puts line } }
end

def cache_stats(host = "javaeye", port = 11211)


cache_objects = {}
open(host, port) do |socket|
slabs = []
command("stats items", socket).each do |line|
slab_id = line.split[1].split(":")[1].to_i
slabs << slab_id unless slabs.include?(slab_id)
end
slabs.each do |slab_id|
puts "browse slab #{slab_id}..."
command("stats cachedump #{slab_id} 0", socket).each do |item|
key = item.split[1].split("/")[0].to_s
cache_objects.include?(key) ? cache_objects[key] += 1 : cache_objects[key] = 1
end
end
end
cache_objects.each_pair {|key, value| puts "#{key} : #{value}"}
end
end
end

if ARGV.size == 0
Memcache.cache_stats
else
Memcache.exec(ARGV.join(" "))
end

第 176 / 283 页
http://robbin.javaeye.com 3.13 Linux平台gcc和动态共享库的基础知识

3.13 Linux平台gcc和动态共享库的基础知识

发表时间: 2008-11-02 关键字: gcc

对大多数不从事Linux平台C语言开发的人来说,GNU gcc的一套工具和Linux平台的共享库的使用还是十分陌生的,其实我也不太熟
悉,姑且写点基础知识,权当做备忘吧。

一、GNU gcc的编译工具用法

我们先来写一个简单的C程序:hello.c

#include <stdio.h>

void print_hello() {
printf("Hello World\n");
}

int main(int argc, char argv[]) {


print_hello();
return 0;
}

定义了一个print_hello函数,调用main函数打印Hello World。

如何编译它呢?

gcc -o hello -O2 hello.c

-o参数指定生成的可执行程序的文件名, -O2是优化级别。该命令会编译生成hello可执行程序,看看这个文件:ls -l hello

-rwxr-xr-x 1 robbin users 11939 2008-11-02 13:48 hello

有11KB大小。

看看他链接了哪些系统动态链接库,用ldd命令:

ldd hello

输出信息为:

第 177 / 283 页
http://robbin.javaeye.com 3.13 Linux平台gcc和动态共享库的基础知识

libc.so.6 => /lib64/tls/libc.so.6 (0x0000002a9566d000)


/lib64/ld-linux-x86-64.so.2 (0x0000002a95556000)

libc是C语言标准函数库,ld是动态链接器。

接着我们看看hello这个程序里面有哪些符号,用nm命令:

nm hello

输出:

00000000005008f8 A __bss_start
000000000040043c t call_gmon_start
......
00000000004004f0 T main
0000000000500658 d p.0
00000000004004e0 T print_hello
U puts@@GLIBC_2.2.5
0000000000400410 T _start

中间省略了一些,不过我们还是可以在符号表里面找到函数定义。

hello有11KB,体积偏大,去处符号表可以给它瘦身,我们用strip命令:

strip hello

然后再ls -l hello,输出为:

-rwxr-xr-x 1 webuser users 4464 2008-11-02 13:56 hello

只有4.4KB了,瘦身效果明显! 不过这次符号表再也看不到了,nm hello,输出为:nm: hello: no symbols。

最后如果我们想从可执行程序里面提取出来一点什么文本信息的话,还可以用strings命令:

strings hello

输出信息为:

第 178 / 283 页
http://robbin.javaeye.com 3.13 Linux平台gcc和动态共享库的基础知识

/lib64/ld-linux-x86-64.so.2
SuSE
libc.so.6
puts
__libc_start_main
__gmon_start__
GLIBC_2.2.5
t fff
Hello World

友情提醒一下,如果你用Java写一个HelloWorld.java,编译以后你也可以用strings窥探一番。

二、动态共享库怎么使用

这次我们把hello.c拆开成为两个文件:hello.c和main.c。hello.c的代码是:

#include <stdio.h>

void print_hello() {
printf("Hello World\n");
}

而main.c的代码是:

int main(int argc, char argv[]) {


print_hello();
return 0;
}

hello.c是我们的动态共享库,在hello.c里面我们声明和实现了各种公用的函数,最后main.c可以去调用这些公用函数。首先我们要把
hello.c编译成为动态共享库:

gcc -o libhello.so -O2 -fPIC -shared hello.c

-fPIC参数声明链接库的代码段是可以共享的,-shared参数声明编译为共享库。请注意这次我们编译的共享库的名字叫做libhello.so,
这也是Linux共享库的一个命名的惯例了:后缀使用so,而名称使用libxxxx格式。

然后编译main.c的时候,我们需要更多的参数让gcc知道如何寻找共享库:

第 179 / 283 页
http://robbin.javaeye.com 3.13 Linux平台gcc和动态共享库的基础知识

gcc -o main -O2 -L. -lhello main.c

-L参数指定到哪个附加路径下面去寻找共享库,现在我们指定在当前目录下面寻找;
-l参数指定链接到哪个共享库上面,我们传的参数hello,那么gcc就会自动链接到libhello.so这个共享库上面(注意我们上面说的
libXXXX.so命名规则);
-I参数指定到哪个附加路径下面去寻找h文件,这个我们没有使用。

最后我们成功编译好了main,执行一下,报错:

引用

./main: error while loading shared libraries: libhello.so: cannot open shared object file: No such file or directory

找不到libhello.so这个共享库,怎么回事?这是因为libhello.so并不在操作系统默认的共享库的路径下面,我们可以临时指定一下链接
路径:

export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH

这样就成功了。我们用ldd main看一下:

libhello.so => ./libhello.so (0x0000002a9566d000)


libc.so.6 => /lib64/tls/libc.so.6 (0x0000002a9576e000)
/lib64/ld-linux-x86-64.so.2 (0x0000002a95556000)

这次main程序链接到了libhello.so这个共享库上面。

三、关于Linux的动态共享库的设置

可执行程序找不到要链接的动态共享库,这是Linux上面编译和运行程序很容易碰到的问题,通过上面的小例子,我们已经大致了解共
享库的一点基本原理,接下来我们要探讨一下怎么设置程序寻找动态共享库的行为。

Linux操作系统上面的动态共享库大致分为三类:

1、操作系统级别的共享库和基础的系统工具库

比方说libc.so, libz.so, libpthread.so等等,这些系统库会被放在/lib和/usr/lib目录下面,如果是64位操作系统,还会有/lib64和/usr/


lib64目录。如果操作系统带有图形界面,那么还会有/usr/X11R6/lib目录,如果是64位操作系统,还有/usr/X11R6/lib64目录。此外
还可能有其他特定Linux版本的系统库目录。

这些系统库文件的完整和版本的正确,确保了Linux上面各种程序能够正常的运行。

第 180 / 283 页
http://robbin.javaeye.com 3.13 Linux平台gcc和动态共享库的基础知识

2、应用程序级别的系统共享库

并非操作系统自带,但是可能被很多应用程序所共享的库,一般会被放在/usr/local/lib和/usr/local/lib64这两个目录下面。很多你自
行编译安装的程序都会在编译的时候自动把/usr/local/lib加入gcc的-L参数,而在运行的时候自动到/usr/local/lib下面去寻找共享库。

以上两类的动态共享库,应用程序会自动寻找到他们,并不需要你额外的设置和担心。这是为什么呢? 因为以上这些目录默认就被加
入到动态链接程序的搜索路径里面了。Linux的系统共享库搜索路径定义在/etc/ld.so.conf这个配置文件里面。这个文件的内容格式大
致如下:

/usr/X11R6/lib64
/usr/X11R6/lib
/usr/local/lib
/lib64
/lib
/usr/lib64
/usr/lib
/usr/local/lib64
/usr/local/ImageMagick/lib

假设我们自己编译安装的ImageMagick图形库在/usr/local/ImageMagick目录下面,并且希望其他应用程序都可以使用ImageMagick的
动态共享库,那么我们只需要把/usr/local/ImageMagick/lib目录加入/etc/ld.so.conf文件里面,然后执行:ldconfig 命令即可。

ldcofig将搜索以上所有的目录,为共享库建立一个缓存文件/etc/ld.so.cache。为了确认ldconfig已经搜索到ImageMagick的库,我们可
以用上面介绍的strings命令从ld.so.cache里面抽取文本信息来检查一下:

strings /etc/ld.so.cache | grep ImageMagick

输出结果为:

/usr/local/ImageMagick/lib/libWand.so.10
/usr/local/ImageMagick/lib/libWand.so
/usr/local/ImageMagick/lib/libMagick.so.10
/usr/local/ImageMagick/lib/libMagick.so
/usr/local/ImageMagick/lib/libMagick++.so.10
/usr/local/ImageMagick/lib/libMagick++.so

已经成功了!

第 181 / 283 页
http://robbin.javaeye.com 3.13 Linux平台gcc和动态共享库的基础知识

3、应用程序独享的动态共享库

有很多共享库只被特定的应用程序使用,那么就没有必要加入系统库路径,以免应用程序的共享库之间发生版本冲突。因此Linux还可
以通过设置环境变量LD_LIBRARY_PATH来临时指定应用程序的共享库搜索路径,就像我们上面举的那个例子一样,我们可以在应用程
序的启动脚本里面预先设置LD_LIBRARY_PATH,指定本应用程序附加的共享库搜索路径,从而让应用程序找到它。

第 182 / 283 页
http://robbin.javaeye.com 4.1 中国web2.0前途是什么

4.1 中国web2.0前途是什么

发表时间: 2006-12-13 关键字: web2.0

http://www.uuzone.com/blog/mao/149664.htm

今天在我的RSS Reader里面看到uuzone的CEO老冒的一篇告别uuzone的博客。背后的故事大致可以猜到:VC不满意uuzone糟糕的业绩
和遥遥无期的商业前景,于是换人,准备对uuzone下手了。

对这个结果并不感觉意外,因为uuzone一直以来网站流量就不大,网站的目标用户群体定位不够清晰,网站缺乏特色,网站经营始终
看不到什么起色,而且就是uuzone新版本的页面透明效果也运用的很不好,总之,这是一个必然的结果。经营三年而无任何起色的网
站,VC也不可能再沉得住气了。接下来的故事自然很好想像:裁员收缩开支,网站大幅改版谋求广告收益,基本上没有什么太大的起
色了。

06年下半年基本上是国内web2.0网站处于紧缩的状态之中,预计未来一两年中会有大批网站关闭或者撤资,能够真正活下来的web2.0
网站可能很少。不过话说回来,国内真正设计和运营的好的web2.0网站本来就寥寥无几,在我看来无非就是豆瓣,点评网而已,当然
连他们都不温不火,其他各种跟风的网站更加毫无价值可言,倒闭也在情理之中。

互联网web2.0网站的兴衰有时候和社会经济的大环境,以及文化都有非常紧密的关联关系。例如国内很火的视频分享网站在国内就很
难有生存的空间,毕竟国内的摄像器材本身就没有普及,搞视频分享网站无异空中楼阁;再例如国内一些颇为高雅的web2.0网站在国
内也难觅生机,作为一个上网网民群体普遍文化素质低下的国家来说,高雅意味着过于小众的需求了。web2.0和中国互联网根本就不
match,中国的社会政治,经济和文化条件决定了只有服务于最大众的低素质网民群体,网站才有非常好的商业前景,例如为什么像
mop,天涯之类社区在国内这么受欢迎,为什么baidu的贴吧这么受欢迎,都是是这些原因有紧密关系的。

我相信web2.0这种以用户需求为导向强调用户反馈和内容建设的网站在未来的某天会在中国成功的,但是需要一段漫长的等待,等待
中国的政治经济和文化条件具备的那一天。

最后说到JavaEye网站,我觉得JavaEye2.0是一个非常web2.0化的网站,而且还固执的定位于高雅,分众化,看起来没有什么大的商业
前景。但是所不同的是,我们不会去找投资,从某种意义上来说,我们也不需要找投资。因为我们本来就不期望JavaEye网站很赚钱,
很成功,这也是一种不切实际的幻想。

我希望JavaEye网站始终成为一个注重高品质的精品技术社区,不需要很赚钱,能够通过招聘业务和网站广告赚一点点钱就足够了,我
能够做自己感兴趣的事情,然后赚一点点钱糊口已经很满足了。

第 183 / 283 页
http://robbin.javaeye.com 4.2 中国互联网需要“费厄泼赖”精神

4.2 中国互联网需要“费厄泼赖”精神

发表时间: 2007-05-09

“费厄泼赖”,即fair play,公平竞争。产生这篇文章想法是来自于庄表伟想我推荐了王建硕的一篇文章:《用户贡献内容还是竞争对手
贡献内容》。

王建硕这篇文章的大概意思就是说:国内的互联网没有版权意识,文章都是互相抄来抄去,通过内容的建设,不能够形成竞争壁垒,
不像国外有版权意识保护,可以通过建设良好的内容来形成壁垒。所以不如建设用户体验壁垒,而不是内容壁垒。

对于现象的分析,说的比较对,但是对于观点,我却完全不同意。

两年之前,有一次聚会的饭局上,我向gigix谈起来我对于JavaEye的未来发展的想法,是希望努力建设成为一个高质量的,整合了
forum,blog和wiki的技术社区。gigix当时轻轻一笑,他说你的想法已经落伍了,你建设内容是没有用的,人家网站随便RSS一扒就给扒
走了,很轻松搞出来一个和你一样的网站。这个想法可以说和两年以后的王建硕的观点不谋而合。

不得不承认,国内的互联网环境是非常糟糕的。这种糟糕的状况是来源于什么原因,这里我还不想深究,但是没有版权意识,随便抄
袭肯定是中国互联网的一大毒瘤。看看中国互联网公司面临的状况吧:

全球网站流量排名前10名的网站当中,中国就占了三家,分别是百度,腾迅和新浪,除此之外,就是Google(google, youbute, orkut),


Microsoft(msn,live),Yahoo,以及myspace。

也就是说全球最大的10家网站,被7家公司占据,其中三家是中国互联网公司。但是我们再看看这三家公司网站的收益情况和四家美
国公司收益情况的对比,我们就可以发现,简直不成比例,和网站流量的地位完全不成比例!

TSS,即www.theserverside.com,号称全球最大的Java社区,其流量还不如JavaEye网站高。CSDN网站的流量放在国外,已经是一个
很赚钱的互联网上市公司了,但是在国内,他刚刚扭亏为盈。

英语为母语的上网群体远远高于中文阿?中国现在才1亿互联网用户阿?全球英语互联网用户多少亿?我们只需要简单的分析一下,就
会发现中国互联网网站在同等流量下价值非常低。造成这种问题的原因,从宏观上来说无非就是三点:

1、中国经济容量不能和美国比
2、中国互联网用户的价值比美国低
3、中国的网站自身内容价值低

前两点不是我们做网站的人能够控制的,但是我们可以控制第三点,怎样提高自身网站的价值,增加网站的核心竞争力。

那么对于一个做内容的网站来说,核心价值在什么地方?内容?流量?用户体验?还是别的什么?

王建硕,gigix都认为内容已经不能成为网站的核心竞争力了,因为它无法树立竞争壁垒。但是真实的情况是这样吗?

JavaEye网站的内容被随便抄袭,随便转载,已经泛滥到了何等程度?那为什么JavaEye到今天都没有一个直接的竞争对手?

新浪新闻是另外一个典型的例子,它的用户体验很差,广告到处漂,他的很多新闻内容用google一搜,n个网站都在转载抄袭,为什么

第 184 / 283 页
http://robbin.javaeye.com 4.2 中国互联网需要“费厄泼赖”精神

还有这么多人去看新浪,sohu和网易都抢不走它的流量?

问题的根源在哪里?在于中国互联网的原创内容不是太多,而是太少,而且少的可怜!只要用Google搜索一下就知道了,你搜索一个
英文关键词,搜索结果很少有重复的,但是搜索中文关键词,超过60%的内容都是重复搜索结果,没有办法,太多网站转载,抄袭。

所以整个中国互联网的信息泡沫太泛滥了,真正有价值的信息太少了。作为一个中国的用户,即使你的网站用户体验再好,但是这个
网站没有什么内容,也无法吸引他。就好像你装修了很好的一个餐厅,结果菜谱上面没有几个菜?你让顾客怎么吃?

所以建立用户体验壁垒并不是具有决定意义的,具有决定的意义的还是在于你的网站能不能真正提供有价值的原创内容。OK,你可以
去转载,去抄袭,但是这些内容,用户可以自己通过Google获取阿?他的获取途径并不是只有你一家网站,那么你这些转载的内容对
于他来说,怎么可能有价值?进而,你的网站怎么可能有价值?特别是,如果你开始抄袭别人的内容,那么你有什么资格指责别人抄
袭你的内容?

原创内容如何建立内容壁垒呢?其实这是很简单的事情,别人抄袭你的内容是需要时间差的,你的原创内容比别人早出来,这就是时
间壁垒;别人抄袭你的内容,但是抄袭不走你的网站氛围,你的创作氛围就是氛围壁垒;别人抄袭你的内容,但是抄袭不走你的原创
网站风格,你的原创风格就是风格壁垒;当然你还有法律武器,可以通过法律手段树立壁垒,前提是你自己要干净,如果你自己都不
干净,有什么资格指责别人?

所以归根结底,我们需要“费厄泼赖”精神,埋头做好自己的原创内容,不要总想着抄袭,转载,走捷径,你如果不“费厄泼赖”,你的网
站也是没有价值的网站,最终损害的还是自身的利益。如果你坚持“费厄泼赖”,在当前这么险恶的互联网江湖,你一定有自己的立足之
处。

第 185 / 283 页
http://robbin.javaeye.com 4.3 SAAS(软件即服务)的时代即将来临吗?

4.3 SAAS(软件即服务)的时代即将来临吗?

发表时间: 2007-05-29

在详细展开本文讨论之前,我们先来介绍两家公司:

1、37signals

http://www.37signals.com/

只要是RoR的fans没有不知道37signals的。这是一家位于芝加哥的创业型小公司,公司小到只有8个员工,但在业界享有盛誉。在芝加
哥办公室上班的有4个人,其余4个人分别在纽约,波特兰等城市soho办公。但是37signals公司基于web的小型商业软件产品的注册用
户却超过了100万。下图是该公司全部员工的合影(RoR作者DHH是左边稍靠后的那个人,貌似姿势挺猥琐):

37signals公司出版了一本名为《Getting Real》的书(中文名称《把握现实》),充分阐述了基于互联网web2.0商业创业的经验,可谓
web2.0创业的圣经。

美国时代周刊记者采访了37signals公司,专门写了一篇稿件《Small Is Essential》,揭示了该公司的主要商业模式。

37signals公司主要提供基于互联网的小型商业软件租用服务:有提供项目管理和团队写作的BaseCamp(这也是导致RoR诞生的产品);
有小型客户关系管理系统Highrise;有即时团队在线交流系统Campfire;有信息组织,日历,工作安排软件Backpack等等。

用户在线注册37signals的系统,在线使用,每个月交纳12美元到149美元不等的月租费。37signals的在线软件租用服务对于小型商业

第 186 / 283 页
http://robbin.javaeye.com 4.3 SAAS(软件即服务)的时代即将来临吗?

公司具有很大的吸引力,功能好用,操作简单,价格便宜,无需维护,注册即可以使用。

2、salesforce

http://www.salesforce.com/

salesforce是业界赫赫有名的一家在线CRM厂商,其创始人来自前Oracle公司的高管。公司在2004年就上市了。salesforce这两年处于
一个飞速发展的阶段:2004年7月,Salesforce刚上市时,股票交易价为11美元。到2006年,它的股价到达在40美元。成立7年多的
Salesforce.com在全世界的2.48万个公司拥有超过50.1万个用户,并以每年80%的速度增长,客户满意度高达97%。Salesforce在
2006年二季度的收益从7190万美元增加到1.181亿美元左右。如今salesforce已经进入中国,提供在线CRM系统。提供每人每年888
元人民币软件租用服务费。

看完上面两家公司的介绍,你一定会说,他们做的不就是ASP(应用服务提供商)吗?是的,从某种程度上来说,他们就是ASP。其实
ASP早就伴随第一次互联网浪潮的时候已经唱了一出狼来了的故事,但是现在ASP会卷土重来吗?让我们再来看看大公司的反映:

1、Google Apps

http://www.google.com/a/

不用多说了,Google Apps是google将其强大的互联网服务伸向企业应用领域的重要尝试之一。

2、Microsoft

Microsoft是典型的传统套装软件生产商,但是不意味着Microsoft不重视SAAS领域。附件是Microsoft的一系列关于SAAS文章当中的一
篇。

Bill Gates今年访问中国之行,其中有一项重要的成果,就是和阿里巴巴达成的合作的协议。而这项合作的内容就是和阿里软件公司共
同构建基于微软技术的SAAS平台战略。这项合作的意义可以说相当深远。

关于SAAS更多深入探讨,推荐大家看一下这篇文章:

http://www.donews.com/Content/200611/f4c23d1d6dc745f483df8e787ca0251d.shtm

SAAS的商业模式相比传统的套装软件有什么优势呢?对于软件供应商来说:

1、短开发周期,低成本,快速用户反馈
看看37signals就知道了,不再需要漫长的开发周期,可以尽快提供用户使用,搜集用户反馈,大大压缩软件开发成本,降低软件的市
场风险,而且可以提高软件的市场需求适应程度的敏捷性。

2、相比卖套装软件来说,无需建设庞大的销售渠道,可以充分利用互联网长尾效应
这是一个伟大的进步,诞生于互联网的长尾效应真正要在企业应用领域发挥作用了。看看37signals和salesforce,数量庞大的中小企
业购买他们的在线企业服务。这些中小企业在传统的软件营销渠道来说,都是处于被放弃的状态。

第 187 / 283 页
http://robbin.javaeye.com 4.3 SAAS(软件即服务)的时代即将来临吗?

对于传统套装软件的销售来说,不管是Oracle,SAP还是RedHat,他们往往集中销售资源去攻克传统大客户,例如四大银行,电信,创
造公司超过一半的销售利润,另外通过合作伙伴建设销售渠道以分销的方式面向中小型客户。越是小型客户,越得不到重视,长尾末
端的客户完全被放弃。

根据长尾效应我们知道,传统销售被放弃的那条长长的尾巴加起来其总市场价值等价于传统销售的市场价值。这也是Google赖以创造
惊人利润的主要原因。但是传统销售资源的有限性不允许他们对于尾巴用户投入资源。但是SAAS这种在线电子商务解除了资源限制。
可以让长尾充分发挥了。

3、软件技术支持的成本大幅度降低
看看37signals,根本没有技术支持人员。互联网AJAX技术的兴起,使得基于浏览器的应用完全可以轻松处理复杂的企业应用操作。集
中式的服务器使得软件在线升级几乎0成本。你还需要庞大的call center吗?你还需要庞大的技术工程师队伍吗?

对于客户来说,SAAS也带来了很多优势:

1、购买软件的风险大大降低了
你不用再担心花几十万购买的套装软件根本不合适,或者花几十万外包的项目开发出来的软件根本不符合需求。简单的注册流程之
后,立刻开始使用,在试用期你就知道这个软件你应该不应该花钱购买了。

2、购买软件的成本大大降低了
不需要一次性付款,每个月按功能,按注册人数付费,就像分期付款一样,不会有浪费。如果你什么时候觉得软件不合适了,随时可
以中止付费。

3、立即可用的软件
你不需要花很多时间去考察,去开发,去部署,当你需要,你就可以立刻使用,为你的公司争取了宝贵的时间。

但是SAAS没有一点问题吗?ASP是怎么倒下的?如果我们提供SAAS服务,那么会面临怎样的问题呢?

1、公司的信誉度的问题
如果你的公司明天就会倒闭的话,哪个客户敢用你的服务?如果你不是一个行业知名的大公司的话,很多客户不敢购买和使用你的服
务,把自己公司业务押在你的身上。

2、安全和保密的问题
你怎么保证客户的资料不被外泄?你怎么保证你不会利用客户资料进行非法的勾当?客户为什么要信任你?

3、网络服务质量的问题
中国的电信运营商的网络安全保护水平实在令人担忧,如果你提供互联网服务,因为网络问题导致网站不能访问,网民最多诅咒几
句,如果是你的客户把自己公司业务放在你的服务器上面,那么倒霉的就是客户了。

所以SAAS其实是很有高的门槛了,因为你必须有知名的品牌来让客户信任你,你必须有强大的资源来提供安全和可靠的服务。

salesforce是目前进入国内做SAAS服务比较早的一个,随后还有阿里软件。这里不得不提一句阿里软件,因为阿里软件有很大的优
势:通过阿里巴巴网站聚敛了几百万中小型商户;多年互联网经营建立的品牌信誉度;和Microsoft合作强强联合以求强大的技术支

第 188 / 283 页
http://robbin.javaeye.com 4.3 SAAS(软件即服务)的时代即将来临吗?

撑;全国部署的上万台服务器提供了充分安全的网络质量和故障转移方案。可以说阿里软件想不成功都很困难,这里不得不佩服马
云。当然除了阿里巴巴以外,国内的金蝶,用友,金算盘,800CRM都盯着这个市场,我相信在未来的几年,SAAS会成为一股潮流。

作为技术人员的角度来看待SAAS,我觉得有两点值得一提:

1、互联网应用和企业应用的界限会越来越模糊
很多开发人员言必称超级复杂的企业应用,动辄分布式事务,消息中间件。确实,在传统的大客户大项目当中,这些超级复杂的企业
应用还会长期存在。但是不可否认的一个事实就是,企业应用的开发人员会越来越多被要求从事SAAS类型应用的开发当中来。在这个
领域,不是超级复杂的企业应用游戏规则,而是互联网游戏规则:快速开发,快速反馈,简单架构,小团队,随需应变。因此解决传
统超级复杂问题的编程工具利器也许不那么有效了,在这个新的领域,需要的是轻量级的超级快速编程工具利器。

2、你想做中国的37signals吗?
如果你可以开发出很酷很好用,而且市场很需要的在线软件产品,就去做吧,不论是面向小型企业,还是面向消费者个人群体,我都
相信这种在线软件消费模式在未来会广阔的市场前景。

附件下载:
• zzcwscjgzl.rar (450.1 KB)
• http://robbin.javaeye.com/topics/download/c0adb574-34c7-4301-b9e0-ee785c1c0ecd
• 描述: 《抓住长尾市场的架构战略》

第 189 / 283 页
http://robbin.javaeye.com 4.4 iphone敲响了PC时代的丧钟

4.4 iphone敲响了PC时代的丧钟

发表时间: 2007-06-19

2007年6月29日,美国旧金山,这是一个即将载入史册的日子。这一天,Apple将发布跨越时代的产品-iphone手机。

PC时代开端于1974年,自从Apple的Macintash图形操作系统,特别是Microsoft Windows推出以后,得到了极大的繁荣。最近几年以
来,虽然PDA,手机,各种手持式上网设备层出不穷,但是都没有能够改变图形操作系统的基本操作方式:WIMP,Windows,Icon,
Menu和Ponter。

WIMP方式适合于固定场所,有足够空间,比较大的键盘、鼠标和显示器。但是不适合手持式设备,没有固定使用场所,没有足够空间
的输入输出设备,不固定。这决定了PC的使用方式并不适合手持式设备。

但是我们可以看到目前的所有手持式设备还是沿袭了PC的使用方式和界面风格,要求使用者用纤细的笔小心翼翼的在位置不固定的手
机上面寻找细小的点进行定位;或者要求使用者按手机上面纤细的小键盘来操作。

这种不适合的使用方式决定了手持式设备不可能被广泛使用,特别是广泛使用在传统PC使用的场合。但是iphone改变了这一切。

iphone开创了手持式设备界面交互的一个新的时代:不再使用键盘和触笔,而是人的手指;不再沿用PC时代的图形WIMP风格,而是虚
拟现实的操作方式:

手指滑动就可以拖动界面翻页,手指并拢就可以缩小,手指分开就可以放大图像,转动手机的方向就可以转动视频观看的角度......

当我观看了Apple网站的iphone操作视频之后,我意识到自从图形操作系统GUI诞生以来的又一次重大突破产生了。iphone的人机交互
方式彻底颠覆了传统的键盘鼠标触笔的交互方式,将会引爆手持式设备普及使用时代的来临。

现在的iphone,你可以比PC更方便的上网浏览,收发Email,观看视频,播放音乐,编辑相册,地图查询,浏览电子书籍。普通消费者
在PC上面要做的绝大多数事情可以在iphone方面更方便更快捷的完成,那么你还会选择用PC吗?

iphone将引爆手持式设备的革命,未来的10年之内,将是手持式设备取代PC的时代。当然这不意味着PC将被淘汰,而是意味着人们会
更加普及使用手持式设备,更倾向于在手持式设备上面完成常规的工作。而这将意味着一个新的IT时代的来临。

在20多年以前,苹果公司的Macintash引爆了GUI时代的来临,20多年以后,iphone将引爆手持式设备时代的来临。

第 190 / 283 页
http://robbin.javaeye.com 4.5 小公司SAAS战略之我见

4.5 小公司SAAS战略之我见

发表时间: 2007-07-06

SAAS毫无疑问是软件行业的未来趋势,大部分意见认为只有巨头的名气和信誉才能很大程度上消除客户使用SAAS的信用和安全方面的
担忧,因此SAAS可能没有小公司的份。但我到不认为只有巨头才能做SAAS,JavaEye也会在未来合适的时机结合自身的优势,尝试性
的做一点点SAAS的服务。

小公司做SAAS,我认为必须做好三点:

1、产品定位
简单模仿国外成功的产品或者国内巨头的产品肯定是行不通的,寻找一个巧妙的产品定位是成功的关键。如何寻找到一个客户覆盖面
非常广泛,市场足够大,同时又不需要过高的安全信用,门槛比较低的产品定位,至关重要。更重要的是这个产品的门槛这么低,那
么竞争壁垒你怎么建立?

2、电话服务
37signals可以凭借超级简单的UI操作而完全不需要服务部门,但是在中国不可以。中国的企业用户还没有达到那么高的电脑操作素
质,有一个call center会让你的客户吃一颗定心丸,让他们有足够的信心去使用你的产品。当然你仍然需要不遗余力的改进UI操作,以
降低用户操作成本和电话服务成本。

3、网站运营
互联网产品的推广要靠有创意的运营,产品推广不能光靠免费注册免费使用,到处发小广告,花钱去其他网站打广告。Gmail就是一个
成功运营的典范,在互联网webmail已经泛滥的今天,Gmail的邀请制和1GB的惊人空间让它变成的稀缺资源,反而名声大噪。

JavaEye将来要做哪方面的SAAS服务,我暂且卖个关子。通过对于JavaEye网站的运营,我们也积累了一点点互联网产品运营和推广的
经验,对于SAAS产品的定位通过JavaEye网站自身功能的探索也渐露端倪。也许这个产品今年都不会面世,但是我们计划用两年的时
间去培育它。

第 191 / 283 页
http://robbin.javaeye.com 4.6 SAAS(软件即服务) 离我们还有多远?

4.6 SAAS(软件即服务) 离我们还有多远?

发表时间: 2008-03-06 关键字: saas

最近在新闻上面看到了这样一条:Google公司的在线软件服务包Google Apps 2007年营业收入达到了4亿美元,然后在方军博客上面


看到这样一段评论:

http://www.mindmeters.com/showlog.asp?log_id=6942

方军博客 写道

有消息说,“Google Apps生成的营收在谷歌总营收中占到2%到3%的比例,2007年约为4亿美元,相当于2006年4000万美元的10
倍。……假设Google Apps由一家独立的公司提供,按照Salesforce.com 10倍的市值营收比,这家独立公司的市值至少将达到40亿
美元。”

在我周围,Google Apps的用户并不多。我想,由于中国互联网用户仍处于接受信息的阶段、且免费的盗版软件四处可用,Google
Apps在中国的总体用户量并不大。这可能是我们忽视Google Apps的原因,这可能是个很大的错误。

在一年前,访问哈佛商学院创新教授克里斯滕森时,他认为Google Apps是他的理论中所分析的新市场创新,当时他说:“我在哈佛商
学院的学生做文字处理时,他们用Google的Word,他们将文件存储在Google 的服务器上,而不是他们自己的电脑上。这是一个典型
的新市场破坏,当互联网变得越来越快和更可依赖,用户正从桌面电脑上的软件应用转向基于互联网的应用。”

克里斯滕森这段理论分析并不是印象最深刻的,印象最深刻的是他开玩笑说自己老了,不会采用Google Apps,但新一代学生们早已
经把一切都放在网上。我也时时体会到,虽然信任别的备份方式,但实际上资料备份一份在Gmail里面是最方便的,几年以后要找资
料的时候,那些在Gmail里面的最容易找出来。

最令我动容的是最后这句话,你是信任自己电脑硬盘的备份呢?还是信任Gmail给你的备份呢?你是在自己电脑上面查找资料方便呢?
还是在Gmail里面查找资料方便呢?更进一步,你觉得用outlook收公司的邮件放心呢?还是用Gmail收那些已经被Google扫描查过毒的
邮件放心呢?

当我问了自己上面这些问题以后,我发现至少在互联网消费领域,SAAS面临的最大障碍……信任问题已经悄悄发生了逆转:

一、你信任桌面邮件软件还是Web邮件系统?

记得多年前我还一直使用Foxmail的时候,整理和备份邮件对我来说是一件负担很重的事情,重新安装软件或者操作系统都意味着大批
邮件内容的丢失,大批邮件地址的丢失,当然你还需要防备时不时不期而止的垃圾邮件和病毒附件。但自从我使用Gmail之后,所有的
烦恼全部消失,想不起来某件事情,用Gmail一搜就搞定了,我已经离不开Gmail了。

二、你信任自己的本地备份还是网络备份?

我家里的台式机四年之内坏了四块硬盘:一块IBM,一块Maxtor,两块Seagate,备份光盘也有很多已经无法读出来了。但我在Gmail
里面的文档随时随地都可以打开看,完全不用担心丢失问题。

第 192 / 283 页
http://robbin.javaeye.com 4.6 SAAS(软件即服务) 离我们还有多远?

三、你觉得Microsoft Office方便还是Google Docs方便?

不知道别人的方式是什么,我是定期整理自己的电脑硬盘,把文档进行分门别类的整理,存放,很麻烦,而且文档一多,实际上也很
不好管理和查找。特别是需要和别人进行共享和编辑的文档,有n个版本,经常发生混乱的现象。但是一旦开始使用Google Docs,这
些烦恼统统退散,备份、整理、查找、共享和版本管理变得异乎寻常的简单。

四、你使用桌面便笺还是网络便笺?

我曾经安装和试用了n个桌面便笺软件,没有找到一个令我觉得满意的,最后我发现了37sinals的Backpack在线个人日程管理软件,现
在我已经把免费账号下面所有的Page都用光了。

五、你还在电脑上面安装金山词霸吗?

其实你可以随时使用金山的在线词霸查词了。

这个列表还可以无休无止的列举下去,在我们不经意之间,网络已经是一个比我们桌面PC更加可靠、更加值得信赖的NPC,SAAS离我
们还远吗?

第 193 / 283 页
http://robbin.javaeye.com 4.7 为什么说OpenSocial只不过是一个公关骗局?

4.7 为什么说OpenSocial只不过是一个公关骗局?

发表时间: 2008-06-17

最近几天以来,Google OpenSocial可谓国内互联网媒体的焦点:谷歌中国公司高调宣布国内10家著名的社区网站加入OpenSocial联
盟,将各自推出支持OpenSocial的平台,如MySpace中国、天涯社区、校内网、豆瓣等等;并且谷歌高调举办开发者大赛,征集优秀
的OpenSocial作品;此外谷歌还不遗余力在行业内和社区内对OpenSocial进行大肆宣传,真可谓全方位的轰炸式推广了。

在谷歌的大力推广之下,国内很多网站已经蠢蠢欲动,摩拳擦掌准备支持OpenSocial,生怕落于人后,错过一次千载难逢的互联网机
遇。我的一位在某互联网公司的高层朋友对OpenSocial颇为心动,勾起了我对OpenSocial了解的欲望。但是经过一个晚上的学习和了
解,感到非常失望,借用Valleywag的博客文章标题来形容就是:OpenSocial只不过是Google的公关骗局。为什么我会有这样的感觉
呢?

一、OpenSocial只不过是一个widget,离app还差10万8千里

OpenSocial和Facebook的f8虽然都可以称之为平台,但实际上的差异非常巨大。f8是真正的App platform,而OpenSocial仅仅只是一个
widget容器而已。打个比方来说,Facebook平台就好像一个功能很强劲的Java应用服务器,你可以在上面开发各种各样的程序,而
OpenSocial平台就好像一个简单的个人主页服务器,你只能在上面发布一下个人主页而已。

Facebook自己并不托管你开发的代码,你需要自己找服务器来运行你的应用程序,从这一点上面来说,Facebook上面的app实际上是
独立的第三方网站,因此你可以做你想做的任何事情,你可以安装自己的Oracle数据库,跑自己的Tomcat应用服务器,本来就是你自
己的网站,和Facebook没任何关系。

好了,突然有这么一天,你眼红Facebook 7000万注册用户的资源,你想把自己的网站和facebook集成起来,于是你研究了一下
Facebook开放出来的REST接口,你根据他的接口,实现了登陆验证,然后在facebook上面注册了你的网站入口页面,好了,一切搞
定!等着Facebook给你带流量和用户吧。我不是开玩笑,Friends for Sale这个网站通过和Facebook的整合,在三个月时间内流量从零
增加到每天1000万访问量,注册用户增加60万。

那么OpenSocial是怎么回事呢? OpenSocial仅仅是一个xml文件而已!这个xml你既可以上传到提供OpenSocial容器的SNS网站上面,
你也可以放在自己的网站上面。当然你也需要到这个SNS网站上面去注册一下xml文件的URL地址。于是这个SNS网站就会在显示指定
的页面的时候,读取这个xml文件进行解析执行,把结果嵌入进来。如果你还没有明白这是怎么回事的话,你可以跟着我的步骤往下
走:

1、复制我写的xml文件的URL地址:http://ftp.javaeye.com/download/my-helloworld.xml

2、打开iGoogle主页(我假定你在Google注册过账户,并且此时已经登陆):http://www.google.com/ig?hl=zh-CN,点击导航条最右边的
链接“添加内容”

3、在添加内容页面的左下角有一个类似RSS订阅的链接,叫做“添加供稿源或小工具”,点击它

4、在弹出的框里面把前面的xml文件的URL地址粘贴进去,确认,然后关闭这个对话框,最后返回iGoogle主页。

现在你看到了什么? 是不是一个页面框里面显示“Hello,JavaEye!”,恭喜你!你已经开发了第一个OpenSocial应用了。

第 194 / 283 页
http://robbin.javaeye.com 4.7 为什么说OpenSocial只不过是一个公关骗局?

当然OpenSocial的这个xml没有那么简单,你可以在这个xml里面写html,javascript,引用图片,JavaScript库,CSS样式文件,甚至可
以引用flash,你当然也可以通过OpenSocial提供的JS库通过AJAX调用来访问SNS网站给你暴露出来的API,但是它终究只是一个xml文
件,终究只能访问SNS网站的资源,而不是一个独立的网站:他本质上是JavaScript,他本质上是在用户的浏览器端执行的(服务器端有
一个简单的xml解析操作,但没有业务逻辑),因此没有任何服务器端运算能力,也没有能力充分利用服务器资源进行复杂的操作。

说到这里你应该明白了吧,facebook的app是在app作者自己的服务器上面运行的,而OpenSocial的widget是在浏览者的浏览器里面运
行的,facebook就好像用Java来做一个全功能的web应用,而OpenSocial则好像用html/javascript写一个纯静态web应用。

因此OpenSocial根本就没有办法做复杂的应用,他顶多只算是一个可以嵌入页面的widget,可以搞点花哨的页面效果,可以用AJAX方
式抓点数据来显示,或者增加点锦上添花的AJAX搜索什么的小功能,但你想用OpenSocial来做类似Friends for Sale那样复杂度的应用
的话,没门!除非你有用JavaScript开发星际争霸的高超JS编程水准,否则只能干瞪眼。

二、OpenSocial仅仅只是一个接口规范,提供OpenSocial的SNS网站不知道在什么地方飘呀飘

OpenSocial让我无可避免的联想起来臭名昭著的JCP以及Java EE专家委员会。JCP是一个很有意思的组织,专门负责制订标准,然后让
厂商们根据标准来写自己的实现。就拿应用服务器来说吧:Glassfish,Tomcat,Resin,Jetty,WebLogic,WebSphere一大串号称符
合某些标准的应用服务器实现,但是你绝对无法把一个war随意部署,这是因为:

1、应用服务器厂商总会因为自己的某些需要提供一些标准之外的东西,或者有些标准就是总支持不好,比如说WebSphere
2、有些应用服务器厂商没有能力提供全部标准的实现,只能打个折扣,比如说Tomcat就不支持EJB
3、Java EE标准也是有版本区别滴!不同的应用服务器分别支持的标准版本也各自不同。

所以Java EE标准当初也想的很好,让大家开发Java项目,一次开发,处处部署嘛,应该没麻烦的,但是做Java企业应用的人都知道,
迁移应用服务器绝对是一个体力活。遗憾的是所有这些曾经在Java EE领域出现的问题,现在在OpenSocial这里照样的重复着历史:

1、大的SNS会不会出于自己的商业利益,往里面添加私货,就像WebSphere那样,这几乎是必然的。

2、iGoogle虽然号称支持OpenSocial v0.7,但是很多地方的功能已经打了折扣,我们可以联想一下,国内的小SNS们,都有能力实现
全部的功能吗?

3、目前号称支持OpenSocial的这些网站列表,支持的标准是各自不同的,有支持v0.5的,有支持v0.6的,也有支持v0.7的。你当网站
是搞企业开发阿,你Google升级一个版本,我们一定能很快的升级代码,支持上去吗?万一我平台上面好多老版本的widget已经在跑
了,我一升级不兼容咋办?

三、这也是最关键的问题:OpenSocial能给SNS网站带来什么好处?能给开发者带来什么好
处?

facebook的f8推出一年多来,已经涌现了24000多个第三方app,为什么这么多公司和开发者这样踊跃开发app,踊跃的把自己的网站
和facebook集成? 无它,唯钞票尔!我集成了facebook可以给我带来流量,我在app里面可以加广告,流量大广告点击多,钞票哗哗
的来,谁不干劲十足阿。

第 195 / 283 页
http://robbin.javaeye.com 4.7 为什么说OpenSocial只不过是一个公关骗局?

那么开发者开发OpenSocial的widget有什么好处?现在Google只是告诉你,你开发一次,可以处处部署!但是我上面已经告诉过你了,
这句话是狗屁!就好像Java一次编译,处处部署那样扯淡。而且更扯的是,就算我处处部署,我真能赚钱吗? 基本没戏!因为widget
太简单,难以开发高交互性的应用,因此无法粘住用户和病毒式推广用户,而且widget本身往往是页面的一个小小的frame框,你还能
有啥地方加广告?

开发facebook的app也不见得只能通过广告赚钱,通过facebook给自己网站带来大量的注册用户,基于这些注册用户本身就可以挖掘商
业模式了。但是OpenSocial widget是静态页面阿,你自己没有服务器没有后台程序,widget只能给OpenSocial提供者带流量,无法给
你带来注册用户阿!

所以开发者你从头到尾就是白忙活一场,捞不着一点钞票,当然也许SNS网站看在你贡献了这么多OpenSocial widget的面子上,给你
点啥纪念品也说不定。

然后我们反过来说提供OpenSocial的SNS网站能得到啥好处呢?答案是nothing but cost!你开发OpenSocial的容器要投入大量开发力


量吧? Google升级版本了,你要跟着改代码吧? 弄了一个平台出来,不像网页,人家要写程序攻击是不是太容易了点?安全性要考虑
吧?你的OpenSocial平台推出以后,怎么也得推广一下吧?所以这钞票就哗哗的出去了。但问题是我们前面说过了OpenSocial根本不
能给开发者带来利益,因此无法像facebook平台那样涌现那么多app出来,那么零星三五个,甚至要SNS网站自己开发widget,这种模
式你能运营的起来吗?

而且还有一个特别容易被忽视的关键问题:你的网站究竟是做什么的?你是做平台的?还是做社区的?

facebook网站压根就是一个做平台的网站,他的网站架构全部都是为了app服务的,除了app它啥都没有了,就连facebook自己网站提
供的所有功能也全部是以app形式出现的。也正因为如此,facebook做平台才能成功。

现在这些号称支持OpenSocial的网站全部都是做社区起家的网站,社区是他们的老本行,而开放平台对他们来说,只不过是一个锦上
添花的东西,有固然好,起码卡一个领先的身位,但是没有对我来说也不是灭顶之灾。

因此这些网站断然不会扔掉目前网站积累的所有社区资源,孤注一掷的做平台。也正因为没有这样和facebook一样的决心,网站开发
和运营的中心还是必然围绕社区展开,其结果就是开放平台永远不会成为他们网站的核心,永远只是锦上添花的功能。因此也就注定
了他们的开放平台不会成功。

总之,OpenSocial就是一个Google的公关骗局,是Google为了抵抗facebook推出的一个防御性策略,一个从技术层面,从商业层面完
全经不起推敲的坏主意,OpenSocial目前和Facebook之间的差距完全不在一个层面上。有空的话多研究研究facebook,比浪费钱在
OpenSocial上划得来。

补充:有人说我给facebook写软文,我就觉得好笑,照这么说,那我已经不知道给Sun公司写了多少年的软文了,好吧,现在就给大家
看看真正的软文要怎么写的:我为什么鼓吹facebook,为什么唱衰OpenSocial?

第 196 / 283 页
http://robbin.javaeye.com 4.8 我为什么鼓吹facebook,为什么唱衰OpenSocial?

4.8 我为什么鼓吹facebook,为什么唱衰OpenSocial?

发表时间: 2008-06-20

OpenSocial只不过是Google的公关骗局发布以后,好像捅了马蜂窝,我看有人说我在给facebook写软文;有人说我在扯淡,有人说我
根本不懂OpenSocial,不一而足。总的感觉是国内开发人员对facebook的了解太少,对Google又崇拜的丧失了起码的判断能力和怀疑
精神,其实我自己也算是一个G粉,用Google Search,Gmail,Google Docs,Google Reader。

我为什么鼓吹facebook?

经常关注我的人应该知道,我从去年下半年就开始推崇facebook,时不时发表一些关于facebook的评论,到现在也快一年了。在这么
长的时间里面,我断断续续花了不少时间了解facebook网站和facebook平台。但是我发现一个奇怪的现象:虽然这一年来facebook经
常是互联网媒体上面的焦点,但是似乎国内的开发人员从来没有想过要去研究一下它,以致于我现在发现很多拉着我和我争辩
OpenSocial的人,对facebook都缺乏起码的认识。我觉得对于那些ruby on rails程序员来说尤其不可以原谅,因为facebook平台支持的
所有API当中,用RoR去开发facebook app是最简单的事情,有现成的插件做了良好的封装,你只需要处理一下登陆验证,注册一下api
key和callback URL就全部弄好了。

1、从网站运营的角度来看,facebook是网站成长的翅膀

一个网站站长运营网站最困难的问题是什么?是推广!特别是在网站刚刚成立不久的时期,你怎么让更多人了解你的网站使用你的网
站这是一个非常困难的事情。即便是很多已经很成功的网站,在早期的推广过程当中也是很幸运的遇到了非常好的机遇,才得以迅速
成长起来的。推广是网站早期发展最大的瓶颈。但是由于有了facebook,你的网站推广就迎刃而解了。我来举个例子:

http://friendfeed.com

friendfeed是现在国外非常火爆的一个网站,可以订阅朋友的最新消息和动态。那么你说friendfeed当初是怎么推广的呢?怎么才能迅
速积累这么多用户的呢?其实很简单,就是去注册成为一个facebook app就行了。所需要的额外开发工作量只是简单的登陆验证,用
以和facebook实现统一认证而已,极少的代码量,如果在RoR里面,只是几十行代码的工作量。

好了,当friendfeed把自身的网站注册成为一个facebook app以后,在facebook里面的7000万注册用户就可以在facebook里面添加这个
app,成为自己在facebook里面的一个tool来使用了。也就是说作为一个用户,你既可以在facebook里面使用friendfeed,你也可以直接
访问friendfeed网站。例如我就是通过facebook才知道friendfeed,进而在facebook里面添加了friendfeed的账户,现在我往往直接访问
friendfeed,而不见得每次都通过facebook访问friendfeed。

我们想想看,如果friendfeed不借助facebook平台的威力,他自己一个用户一个用户的去推广,他需要花多少推广的费用,需要发展多
少年的时间?而通过facebook平台的威力,你就可以迅速成长为一个大网站。friendfeed具体的用户数字我不知道,facebook平台上面
的Friend for Sale这个app的数字是三个月时间从零增长到每天1000万PV,60万注册用户,而仅仅是两个人在业余时间开发出来的网
站。作为一个对比,JavaEye网站用了5年时间发展了15万注册用户,每天80万PV。这就是自己积累用户,和借助平台发展网站的巨大
差别。

有了facebook,你做网站根本就不需要操心网站推广的问题,你只需要下功夫把网站功能做好就行了,插上了这样的翅膀你还担心网
站发展不起来吗?

第 197 / 283 页
http://robbin.javaeye.com 4.8 我为什么鼓吹facebook,为什么唱衰OpenSocial?

2、从商业回报角度看,facebook让你创业赢利变得很容易

前面提到了Friend For Sale这个app,两个人业余开发的,但是为了支撑每天1000万PV的访问量,他们买了12台服务器,请了DBA顾


问,租用了一个机柜和100MB独享带宽,然后他们两个人辞职自己成立了公司。这些钱都从哪里来?很简单,就是广告费!他们在
friends for sals里面嵌入了banner广告,访问量越大,点击量越大,赚钱越多。1000万PV是什么概念?在中国的网站里面差不多可以
排进前50名的网站。

facebook开放平台以后,到现在一年多涌现了24000个app,这就相当于有24000个网站把他们的访问入口点注册到了facebook这里,
从facebook这里分享网站流量、用户和广告,也就是说facebook现在养活了24000个网站,这24000个网站要依靠facebook来混口饭
吃。这一成就是Google,Microsoft到现在都没有做到的,Google赚钱也只是自己一个公司赚到了钱,而facebook赚钱,则是让一整个
网站产业链都赚到了钱。这就是为什么有那么多网站要到facebook去注册app,为什么有那么多公司要专门给facebook开放app的根本
原因。在这一点上面,只有阿里巴巴有点像,他也是和很多很多网商的切身利益捆绑在了一起,我觉得这种制造一个产业链的网站才
是真的很难被击败的,因为你要击败的不是一个网站,而是千万万万个利益绑定在一起的网站。

我们试想一下,如果全球有几十万个网站都注册了facebook app,从facebook那里分享流量、用户和广告的话,这个互联网究竟是谁
说了算? 当然谁是衣食父母谁说了算。即便facebook崛起之前,Google也没有统治互联网,网站并不受Google的直接威胁,但是
facebook对网站的控制力要超过Google,这一点很好理解:用户通过Google搜索快速进入网站就脱离了Google的控制范围,但是通过
facebook访问app,则一直在facebook的控制之下。

从今年年初开始,我就一直在说,现在最好的互联网创业就是开发facebook app,特别是开发一些web game类型的app,很容易就积


累大批用户了,你有一个好的创意和好的开发执行力,已经可以成功了,大伙看看现在facebook上面火爆的火炬接力这个app就可以明
白。

我为什么唱衰OpenSocial?

有人说我只研究了一个晚上的OpenSocial,没资格否定OpenSocial,说我根本不了解OpenSocial可以跨域进行AJAX调用,胡乱下结
论。

1、从技术角度来说,OpenSocial限制的太死

其实我不需要学习OpenSocial一个月才能下结论,我只需要确定一点,即OpenSocial本质上是在用户的浏览器端通过JavaScript来运
行,这就足够了。那些做过复杂企业应用,特别是用EXT/dojo做过One Page One Application应用的人,应该比我更清楚用纯AJAX做网
站,和传统的服务器端web方式究竟有什么不同吧。

理论上来说,AJAX调用可以完成大多数网站服务器端同样的功能,如果开发商自己架设服务器,在widget的JS里面调用自己服务器暴
露出来的服务的话,也可以做很多事情。但问题是成本不一样,用户体验不一样。

打个比方来说吧:eBay网站扔掉全部的JSP页面和Web框架,全部都改成静态页面,只在服务器端通过DWR提供AJAX调用接口,然后
静态页面里面的 JS在浏览器端执行,通过DWR调用服务器端的服务,全部页面渲染都在浏览器端完成。最后做成一个One Page One
Applicaion的网站。

你说从程序角度有没有实现的可能性呢?答案当然是可以,但问题是eBay不会这样去做,任何一个成功的互联网网站都不会这样去
做,因为这样做其开发成本太高,其用户体验太差,只有一些操作非常复杂的企业应用才会采用这种OPOA方式。

第 198 / 283 页
http://robbin.javaeye.com 4.8 我为什么鼓吹facebook,为什么唱衰OpenSocial?

OpenSocial 要做复杂的交互性应用,他也只能通过这种One Page Oone Application方式,这种方式是非常受限的。如果说Facebook给


了开发人员无限的可能性,仅仅要求你实现登陆验证的话,那么OpenSocial则个开发人员施加了强大的限制,逼你只能在JavaScript里
面翻筋斗,练梅花桩,其结果就是很多创造性的应用无法实现或者很难实现。事实上我现在看到的稍微复杂的高交互式OpenSocial应
用示例都是用flash做出来的。你都被逼得用flash的时候,那就已经是另外一回事了,和OpenSocial没啥球关系了。你不用你
OpenSocial,我一个flash也可以随便哪个网站去部署没一点问题。就是JavaEye的发贴也可以嵌入flash,是不是也可以算一个
OpenSocial容器阿?

2、从网站运营角度来说,OpenSocial不能给开发商带来推广效应

还是拿friendfeed举例,我们设想一下,friendfeed怎么去使用OpenSocial才能带来同样的好处呢,答案是impossible!

friendfeed 必须按照OpenSocial的规范去写这样一个XML文件,把这个XML文件发布到某个OpenSocial容器网站,例如MySpace上面
去。好了,现在问题来了,MySpace的用户能不能仅仅通过MySpace页面嵌入的这个friendfeed的widget来使用friendfeed网站的全部功
能呢?答案当然是不可能,除非Friendfeed的开发人员在这个xml里面用JavaScript来重写一遍整个friendfeed网站的功能,嘿嘿,用一
句通俗的话来说就是: 你必须把一头大象给我装进冰箱里面去。

3、从商业利益角度来说,OpenSocial无法保护开发商的利益,代码剽窃没有任何障碍

OpenSocial开发出来的gadget是在XML里面写JS和HTML,而这个XML还是一个在互联网上面可以访问到的URL,不需要任何授权就可
以访问,这等于是代码完全暴露在光天化日之下。我们可以假设一下,某个公司投入研发力量开发出来的一个优秀的gadget很受欢
迎,在很多OpenSocial容器网站都有很多人使用,那么一个很可能出现的后果就是别人可以把你的源代码直接拿过来,稍微改改,也
发布为一个gadget去赚钱,而你没有任何办法去阻止他。

有人会说,我的gadget会通过AJAX调用我自己服务器的资源,你抄走了gadget,抄不走我服务器提供的Web服务,那我就要说了,如
果你的gadget真的有商业价值,别人直接拿走你的gadget代码,然后自己架一个服务器,把你提供Web服务的接口也实现一遍,这并
不什么困难的事情,而我相信一个有商业价值的gadget,在gadget本身的研发投入已经非常巨大了,这些投入被别人白白的拿走,毫
无障碍的利用OpenSocial网络到处发布,一定会对你造成巨大的商业损失。

所以一个稍微有点理智的开发商,都必须慎重考虑投入到OpenSocial是不是值得的问题。

4、从商业模式的角度来说,OpenSocial无法形成一个简单有效的价值链,忽视了app开发商
的利益

facebook的商业模式是简单而清晰的,参与商业博弈的就是facebook和app网站,1:n的关系,而且是利益共同体,互相依存。但是
OpenSocial的商业模式参与博弈的关系过于复杂,是一个m:1:n的网状关系,m彼此之间还有强烈的竞争关系,而n和m的对应关系还不
是线性的,你需要针对不同的m开发不同版本的gadget,而这个1是Google,他还分别和两边发生关系。我们知道商业模式越简单越有
效,这个商业模式当中环节实在太多,而且彼此相互制约,哪一个环节出了问题,整个商业模式就走不下去。这一点在前面文章当中
已经分析过了,不详细剖析了。总之关于这个问题我只想强调一点:

别看facebook平台上面有那么多活跃的开发商贡献app好像花团锦簇的样子,你深入研究一下facebook的app就会发现,facebook上面
真正火爆的app根本就不是程序爱好者写的,全部都是专门的公司开发出来的。

第 199 / 283 页
http://robbin.javaeye.com 4.8 我为什么鼓吹facebook,为什么唱衰OpenSocial?

你做开放平台,永远也不要指望软件开发人员作为业余爱好给你开发app,指望像开源社区那样踊跃的程序员贡献者,这些东西根本就
不靠谱。真正靠谱的就是你的开放平台本身是具有商业价值的,能够给开发商带来商业利益,那么自然就会吸引大批的公司、网站和
创业者专门给你开发app。而facebook之所以能够有今天,也就是因为这个原因。

Facebook战略之所以正确,是因为他从一开始就是立足于让app开发商赚到钱,所以app开发商就会趋之若鹜、前仆后继;而
OpenSocial战略从一开始就是错误的,是因为Google搞OpenSocial的出发点不是让app开发商赚钱,而是让app开发商可以实现:“开发
一次,处处部署”。

OpenSocial这个出发点就错了:只要能让我赚到钱,别说开发一次了,让我开发n次都愿意;但是赚不到钱的事,你就别指望我白白给
你开发了,所以说程序员开发量多大根本就不重要,重要的是你Google有没有为app开发商设计有效的赚钱方式。而遗憾的是
OpenSocial整个战略的侧重点都在拉拢SNS网站对抗Facebook上面,根本就没有关注app开发商的利益。所以现在的OpenSocial对于开
发商来说,没有任何商业吸引力,你光指望在程序员社区推广推广,搞搞编程大赛,拉几个程序员作为兴趣爱好给你开发gadget,不
如趁早洗洗睡了吧。

第 200 / 283 页
http://robbin.javaeye.com 4.9 关于OpenSocial讨论的总结

4.9 关于OpenSocial讨论的总结

发表时间: 2008-06-23

最近我写了两篇关于Google OpenSocial的文章,分别是:为什么说OpenSocial只不过是一个公关骗局?和我为什么鼓吹facebook,为
什么唱衰OpenSocial?,出乎我自己的意料,这两篇文章得到了异乎寻常的关注,有赞成我的观点,也有反对我的观点,当然也有谩
骂的。其中非常感谢那些对OpenSocial很了解的人热情的回复我的文章,指出我文章的错误之处。我今天看了一遍OpenSocial v0.8的
文档,想就前面的文章和讨论做一个简单的总结:

Google OpenSocial v0.8增加了REST API,支持服务器端的扩展

之前我看OpenSocial的项目文档,是直接访问到了OpenSocial的中文官方网站(也许是因为我的Google账号设置为默认中文版的缘故),
中文网站至今没有发布v0.8版本,因此我没有注意到REST的支持。今天仔细看了一遍OpenSocial英文官方网站,v0.8版本正式提供了
REST支持。准确的来说就是:OpenSocial v0.8支持两种方式的访问:

1、使用gadget访问OpenSocial,本质上是在浏览器端运行的JavaScript,这就是我在前面文章当中一直大力批评的方式。gadget如何
发布,官方文档没有明确说明,只是说容器应该提供功能让开发者可以发布,gadget应该运行在containing page里面。

2、v0.8正式公布的REST方式访问OpenSocial,这也是f8平台早就支持的方式,你可以在自己的服务器上面编写程序去远程调用
OpenSocial的REST API。至于通过这种方式开发的应用,应该如何发布在容器网站上面,官方文档没有任何说明。

我想从技术角度分别谈谈这两种方式:

1、gadget方式调用OpenSocial

gadget方式其实就是一个页面里面嵌入的widget应用,用AJAX开发出来的。这种方式我否定它的重要原因就是这种方式难以开发高交
互式的复杂应用,而SNS的应用要火爆要推广出去,必须是那种交互式很强,越多人参与越有意思的应用,比方说看一下facebook上
面那些很火爆的app,都是交互式特别强的app。

gadget方式还有另外一个可能的隐忧:大量AJAX的应用可能会拖慢浏览器的速度,特别是一些mashup的应用,如果gadget开发者无节
制的使用JS,很可能导致一进入该containing页面,浏览器就假死。

当然gadget还有一个问题就是源代码泄漏问题了,使得拷贝没有任何成本,这一点前面文章提过,他和网站AJAX应用的JS源代码泄漏
其严重程度是不一样的。因为网站的核心竞争力往往并不在那点AJAX效果上面,而gadget的主要竞争力就靠这个了。

不过我看很多朋友在回复我的文章当中,反而更加看好这种“轻”应用的方式,比方说:

ScorpioX 写道

你有空可以研究一下Netvibes的结构,他们刚刚开源了。我个人认为一个显示空间和数据操作功能都有很大限制的Widget适合做一些
简单的信息发布,例如RSS或邮件。太复杂的交互,Widget就捉襟见肘了。但这并不妨碍我们可以利用Widget来做一些事情,例如我
刚给你的Feed在 Netvibes做了一个Widget,呵呵。http://eco.netvibes.com/widgets/241588/javaeye

Netvibes自己也做Social功能,而且也开发了Facebook的Widget,当然不可能把FB的全部功能搬进来,但进行一些短平快的查询还是

第 201 / 283 页
http://robbin.javaeye.com 4.9 关于OpenSocial讨论的总结

很不错的。http://eco.netvibes.com/widgets/206745/facebook
Netvibes为什么要这么搞,当然是通过自己平台的能力把FB边缘化,让Netvibes成为你每日必上的网站。所以,从根本上讲,清楚自
己的目的最重要。而手段可以层出不穷。

其实我觉得Netvibes现在混的一点都不好,iGoogle也没有怎么火起来,这种mashup也很难看到什么商业前景,我也不看好“轻”widget
应用,当然关于这个问题见人见智。大家可以多多发表见解。

2、远程调用OpenSocial的REST API

我个人是非常推崇这种方式的开放平台的,对于开发者来说没有任何限制,可以做任何事情。因此如果OpenSocial的开发商都倾向于
采用这种方式,那么我前面文章当中对于OpenSocial的一些论断是错误的,请大家不要被我前面的言论误导。

但是OpenSocial文档没有说明app开发商开发的REST应用究竟应该以何种方式呈现在OpenSocial容器网站上面,而我却认为这是至关
重要的地方。比方说facebook网站是把自己定位成为一个纯粹的平台网站的,他开放任何数据给app开发商,他把app作为网站的核心
价值展现出来,给app开发商最大的利益。

但是作为一个社区网站来说,如果提供这种REST API,就面临一个两难的抉择:如果把app作为网站的重要功能集成进来的话,那么
app开发商事实上就在和网站自身争夺用户,网站为了保护自身的利益,就会限制app访问的数据;如果不作为网站重要功能集成的
话,app开发商没有动力给你开发app。关于这一点,我在前面文章提到过:

robbin 写道

而且还有一个特别容易被忽视的关键问题:你的网站究竟是做什么的?你是做平台的?还是做社区的?

facebook网站压根就是一个做平台的网站,他的网站架构全部都是为了app服务的,除了app它啥都没有了,就连facebook自己网站
提供的所有功能也全部是以app形式出现的。也正因为如此,facebook做平台才能成功。

因此这些网站断然不会扔掉目前网站积累的所有社区资源,孤注一掷的做平台。也正因为没有这样和facebook一样的决心,网站开
发和运营的中心还是必然围绕社区展开,其结果就是开放平台永远不会成为他们网站的核心,永远只是锦上添花的功能。因此也就
注定了他们的开放平台不会成功。

根据我了解到的一些信息来看,国内目前宣布支持OpenSocial的网站当中确实有这种担忧在内,并且开放的并不彻底。

事实上如果SNS网站虽然提供了完整的REST API支持,但是对于app应用的集成方面做的不够,或者说不热心积极整合的话,那么
REST API的意义也就不大了。因为对于app开发商来说,开发app的目的是希望利用你SNS网站的平台给我带来流量和用户,如果你不
提供整合手段,或者提供整合手段但是不提供良好的app推广方式的话,那我app开发商想要达到的目的根本就没有达到。

而gadget整合进来和app整合进来是不太一样的两回事:整合gadget无非就是在页面里面嵌入一个iframe,在页面开一个小天窗,增加
点页面功能而已,对SNS网站本身不会形成什么冲击,有益无害,但是对开发商没有什么利益;而整合app就不一样了,需要你对自己
网站本身做很大的改动,能够适应app顺利的整合进来,成为网站功能的一部分,帮助app开发商达到推广他应用和分享利益的目的。

第 202 / 283 页
http://robbin.javaeye.com 4.9 关于OpenSocial讨论的总结

因此指望在网站现有基础上增加点OpenSocial,然后很多app就自己来了,这是不可能出现的。天上没有掉馅饼的好事。

探讨一下OpenSocial的前景

尽管OpenSocial规范支持了REST,我前面文章批评OpenSocial的很多理由可以被推翻了,但是OpenSocial的隐忧还是有很多:

1、OpenSocial的版本不一致的问题,这个问题包含两个意思:

1) OpenSocial规范自身一个版本一个版本的升级,网站不可能整齐划一的都支持到最新版本,有的支持v0.5,有的支持v0.6,有的支
持v0.7。让开放者开发的应用失去了处处部署的可能性

2) 即使都支持OpenSocial的同一个版本,不同的容器网站支持的功能也各有多少,处处部署是不可能的

2、即使OpenSocial从代码上可以处处部署,但从用户角度也未必可以处处部署

毕竟不同的SNS网站侧重点是不一样的,你在一个SNS网站上面非常受欢迎的app,原封不动挪到另外一个SNS网站就未必会受到这个
网站用户的欢迎。特别是国内的社区网站,都会形成一种内在的、独特的、甚至有些排外的社区文化,不同网站的社区文化是不一样
的,同样的app不可能到处都吃香,成功的app必然是为这个社区用户和社区文化定制的app。

3、OpenSocial怎么鼓励app开发商?

这个问题我在前面文章详细谈过了,从OpenSocial整个战略来看,并没有考虑到app开发商的利益,而OpenSocial的不可移植性又大大
增加了开发的成本,再上了SNS网站自身对于app开发商的利益争夺还是有戒备心理的,那么怎么来形成一个健康的商业生态链呢?我
想这个问题我们得拭目以待了,就我个人来说,并不是那么看好。

第 203 / 283 页
http://robbin.javaeye.com 4.10 Facebook的成功秘诀是什么 - SNS之我见(一)

4.10 Facebook的成功秘诀是什么 - SNS之我见(一)

发表时间: 2008-07-11 关键字: sns, facebook

SNS是2008年中国互联网最火爆的现象了,无数的SNS网站一夜之间纷纷涌现,前仆后继,慰为壮观:校内、海内、开心、一起、蚂
蚁以及无数的Facebook克隆SNS网站陷入了一场空前惨烈的厮杀当中,每个人都生怕错过互联网下一个the big thing的机会,一波接一
波的抄袭、炒做和竞争令人应接不暇、眼花缭乱。我也未能免俗,从2006年就一直关注SNS网站的发展,在2007年下半年就开始用
Facebook,也一直在不断思索:究竟SNS网站的未来是什么呢?这场空前混乱的SNS大战会有什么样的结果呢?在中国,一个成功的
SNS模式应该是什么样的呢?

一、引子

早在博客概念还如日中天的2005年,国内就已经有一大批克隆MySpace的SNS网站了,比方说uuzone,圈网等等,当2006年MySpace
以5.8亿美元的高价被新闻集团收购之后,国内的Myspace克隆网站达到了一个高潮。但是这种类型的SNS网站模式在国内一直不太成
功,难以病毒式传播,需要依靠大规模用户推广和不断的线下活动组织,所以逐渐式微了。除了已经关门的之外,其他的已经无一例
外的改头换面克隆Facebook了。此时当其他网站还在盯着博客概念和MySpace的时候,王兴已经全盘克隆Facebook推出了校内网,眼
光很独到。

但是直到2007年微软以2.4亿美元购买了Facebook的1.5%股份,这才真正引爆了国内的Facebook热潮,此前言必称MySpace的谢文也
从此改口,言必称Facebook了。从2007到现在一年时间不到,国内的Facebook克隆SNS网站已经是忽如一夜VC来,千万SNS缤纷开
了。这些众多的SNS网站当中,除了51.com和豆瓣之外,几乎无一例外的先后抄袭MySpace和Facebook。

现在的SNS都长着一副Facebook的嘴脸,这真的十分无趣,国外的Web2.0网站类型非常丰富,光是SNS类型的还有twitter,
friendfeed,friendster,ning等等,干吗光盯着Facebook抄阿?所以我的第一个话题是:

二、Facebook的成功秘诀是什么?

这几年时不时有人问我:JavaEye的成功秘诀是什么?也有很多人告诉我他们发现了JavaEye成功的秘密是XXX,在他们看来,只要按照
这个XXX去做,也可以创办一个成功的技术网站,但我没有发现有人成功过:这不是因为他们找错了秘诀,而是因为网站的成功并不是
光靠一个秘诀。

JavaEye的发展历史分为几个阶段:从2003年9月创立到2006年8月是第一个阶段,这个阶段的JavaEye靠的是个人铁腕管理;从2006
年9月到2007年9月是第二个阶段,这个阶段的JavaEye靠的是web2.0概念的社区改造;从2007年10月开始是第三个阶段,这个阶段
的JavaEye靠的是不断精益求精的功能和品质服务。以后JavaEye还会有很多发展阶段,跨越每个不同的发展阶段都需要独特的核心竞
争力(或者说秘诀)。

现在国内克隆Facebook的一些SNS网站就犯了上面同样的问题:王兴认为Facebook的成功秘诀是发展大学生用户市场,所以他搞了校
内网;当王兴卖掉校内创办海内的时候,他又认为Facebook的成功秘诀是真人社区,这一点也被谢文反复的吹捧;而戴志康显然认为
Facebook的成功秘诀是去中心化的社区形态,所以他搞了一个UCenter Home出来;而从开心网开始,大家又突然发现Facebook的成功
秘诀原来是上面的Web小游戏,于是一窝蜂的抄袭Facebook的热门小游戏;当然还有很多人认为Facebook的成功秘诀在于开放平台。
所以不同的人看Facebook,会得出不同的结论,所谓:“横看成岭侧成峰,远近高低各不同”。

第 204 / 283 页
http://robbin.javaeye.com 4.10 Facebook的成功秘诀是什么 - SNS之我见(一)

其实这些看法都对,但是又都不准确:Facebook在每个发展阶段都有导致他成功的原因:在Facebook发展的第一个阶段,面向校园市
场和实名注册是他成功的原因;在Facebook发展的第二个阶段,采用去中心化的封闭式设计又能够很好的隔离不同类型的用户;在
Facebook发展的第三个阶段,是开放平台推动了他的腾飞,是web小游戏让他的用户群迅速的扩大。因此就算要抄袭Facebook,也应
该认识到Facebook成功的每个阶段,要抄就抄得全面点。

三、Facebook究竟是什么?

那么Facebook本质上是什么东西呢?现在的Facebook对用户来说是一个社交工具,而不是一个社区;如果我们抛开用户的身份,从互
联网网站类型去看,Facebook是一个应用平台,而不是一个社区网站。因此目前国内的SNS网站当中,只有开心网最接近Facebook,
只有开心和海内没有企图去成为一个社区网站,其他所有的SNS网站都背离了这一点。

我在2007年下半年,总是不断的收到一些朋友的Facebook邮件邀请,一开始不为所动,到后来开始不胜其扰,最后注册了一个账号。
但是注册账号以后发现Facebook就是一个空白的网站,根本不知道可以干吗,于是又是长期的不登陆,直到一个朋友给我发来了
Facebook上面的Vampire的app邀请,Vampire是一个吸血鬼的小游戏,你可以咬别人组建你的吸血鬼军队,还可以和别的军队作战。
就这么一个小游戏,立马让我明白了Facebook是怎么个玩法,马上促使你把自己的MSN/Gtalk的朋友都拉过来玩,于是一个你熟识朋
友的在线圈子很快就组成了。

现在很多的开心网用户看到上面这一段,肯定觉得似曾相识,他们就是这样开始用开心的,这里的互动关键点是什么呢?是作为一个
网站,用户为什么会来你的网站?

因为你的网站有大牛?还是因为你的网站有高质量的文章和讨论?还是因为你的网站提供了很多吸引他的机会和资源?

如果用户是因为这样的理由来你的网站,那你抄袭Facebook就太失败了。因为你的网站核心竞争力还是在于“内容”,还是要依靠UGC。
那么一个封闭的社区、一个去中心化隔离用户的社区要创造高质量的UGC就太难了。
Facebook靠的是你的朋友在上面活动,你可以参与他们的活动,这就是全部的理由。至于搞什么活动不重要,写不写什么文字也不重
要,唯一重要的是你需要Facebook这样一个tool来保持和你朋友之间的关系。

虽然Facebook不仅仅限于认识的朋友,但是其主要目的就是提供给熟识的朋友进行交流之用,因此Facebook本身并不提供任何全站的
公共信息广播,也不开放匿名访问,你和自己认识的朋友之间的交流本来就是私密性的,这些信息本来就是被保护起来的。

而且尤其重要的一点就是Facebook并不鼓励UGC(用户创造内容),这是和其他web2.0网站的本质区别。Facebook真正鼓励是你和你
的朋友在Facebook上面“发生了互动的行为”,而不是“互动的所创造的内容”。

用这个标准你去衡量一下,就会发现开心网是唯一神似Facebook的网站,而其他网站,特别是UCenter Home简直就是拙劣的Facebook
模仿者,他完全没有领会Facebook的本质,完全用自己做社区软件的思路去套Facebook,搞出来的UCHome压根就是一个社区网站,
这一点大家看看5GSNS:

1、你为什么去5GSNS,因为你想看keso或者其他大牛写的文章
2、你为什么去5GSNS,因为你知道keso或者其他大牛现在在干吗
3、你为什么去5GSNS,因为上面有互联网行业的招聘信息

说白了就是一句话:高质量的内容和资源在吸引你,所以要保持高质量的内容和资源,你必须依靠高质量的会员持续的UGC,那么我

第 205 / 283 页
http://robbin.javaeye.com 4.10 Facebook的成功秘诀是什么 - SNS之我见(一)

请问你,这和一个BBS有本质区别吗?或者我这样问你,keso不用UCHome,而是discuz!,会妨碍你访问5GSNS吗?会妨碍你泡在这
个网站上面并且发贴吗?所以小戴同学换汤不换药呀。

四、Facebook怎么赚钱?

据说Facebook现在全球注册会员有6000多万了吧,网站流量也排名全球前10了,这样的网站赚钱是不难的,难的是用简单的商业模
式持续的赚大钱。无论是Facebook在网站上面搞搞电子商务卖卖商品也好,搞搞网络招聘卖卖人头也好,搞搞游戏卖卖道具也好,都
能赚钱,但是这些商业模式有问题:

1、无论是电子商务、网络招聘、网络游戏或者其他的什么商业模式,都是划分具体的用户群体去赚特定人群的钱,无形之中,潜在客
户就少了一大半,Facebook坐拥6000万会员,商业模式的覆盖面必须广,去赚小众的钱就是个失败的商业模式。

2、进入特定的分众领域,以Facebook这样的通用SNS网站来说,竞争力根本不及专业的垂直网站,你做电子商务做不过ebay,做网络
招聘做不过monster,做网络游戏做不过爆雪,都只能吃点残羹冷炙。而且这种专业领域,你Facebook根本没有积累,你需要花多么
大的代价才能摸清楚这里面的水有多深呀。

3、你做这些垂直领域的生意,其实就是和Facebook平台上面的开发商在抢生意,这是一个大忌,会破坏整个Facebook平台的商业生
态链条。而这个大忌,校内网正在不遗余力的去犯。

那Facebook怎么办?靠广告吗?广告是一条路,但光靠广告不行。Facebook在2007年广告收入是1.45亿美元。这个收入水平和Yahoo
这样的门户网站无法相提并论,也远远不足以盈利和上市。

其实在网络广告市场,已经被证明的广告模式只有两种:搜索引擎的关键字广告和媒体网站的媒体广告,也就是Google模式和Yahoo模
式,或者说国内的百度模式和新浪模式。前者依靠拍卖广告关键字赚钱,后者依靠网络媒体内容平台传播影响力。

而Facebook的精准广告投放只能依靠CPC(每点击成本)来计费,而我们知道Google的adsense收入是非常可怜的,他的主要广告收入
来自竞价排名。Facebook的非UGC特性决定了他是一个没有内容的网站,无法像媒体网站那样卖内容广告,作为一个对比,开放式的
SNS网站MySpace就不同了,他的网站互动产生了巨大的UGC,所以他的广告收入是Facebook的3倍以上。因此光靠广告收入,对于
Facebook来说非常的不够。

那么Facebook的钱途在哪里?

Facebook的真正钱途在于从app开发商身上赚钱!我们看看淘宝网是怎么赚钱的就知道了:淘宝网开店不收费,但是你想成为诚信商
家,你想进驻淘宝商城,你想在淘宝的搜索上面靠前,你想获得淘宝的高级服务,那么请乖乖交钱。而淘宝上面的大商家是很愿意掏
这笔钱的,因为淘宝这个平台可以让他赚到更多的钱。

Facebook现在就是一门心思做平台,不做应用,尽量能开放的数据全部开放出去,不遗余力的培养app开发商,为app开放商创造最好
的赚钱途径。Facebook就是一个巨大的网店,而app开发商就是上面免费租赁店面的商家,兜售自己的玩具,吸引用户来玩。app开发
商可以去做网络招聘、app开发商可以去做机票预定、app开发商可以去做电子商务,现在Facebook上面已经有几万个app了,其中真
正赚钱的app还不是特别丰富。等到Facebook平台上面有100万个赚钱的app商家的时候,Facebook再面向app商家推出增值服务,你
可以想像一下到时候Facebook赚钱是多么容易的事情。

第 206 / 283 页
http://robbin.javaeye.com 4.10 Facebook的成功秘诀是什么 - SNS之我见(一)

所以Facebook并不需要直接从注册用户身上赚钱,而是把面向用户的细分垂直领域的赚钱机会统统留给app商家,同时也把这些细分
领域的成本、风险和时间统统节省了,Facebook只要把自己的平台做的足够好,给app商家提供足够好的免费服务和增值服务,就可
以坐在家里收钱了,压根不需要自己亲自一个细分领域一个细分领域辛苦的开拓。从这一点来看,校内是多么的愚蠢和短视。为什么
现在Facebook这么全心全意的伺候app开发商,当然是因为app开发商将来就是Facebook的衣食父母呀。

第 207 / 283 页
http://robbin.javaeye.com 4.11 点评国内Facebook克隆网站 - SNS之我见(二)

4.11 点评国内Facebook克隆网站 - SNS之我见(二)

发表时间: 2008-07-11 关键字: sns, clone

点评国内SNS网站

1、小富即安、目光短浅的校内网

在校内开放API之前,我看错了两件事情:一个是低估了国内web2.0小网站开发app的热情;一个是高估了国内SNS网站商业眼光。

校内网在国内能够成功,我觉得机遇是主要的原因:王兴搞校内网的时候,国家教委开始管制各大高校的BBS,在校学生们无处可
去,校内网刚好补上,而那些离校的学生面对ChinaRen和5460两个烂得不能再烂的同学录,也只能选择校内网。因此校内网的成功与
其说是真人网络和定位大学生市场的成功,还不如说是国家教委和清华师兄张朝阳给了王兴这个机会。而王兴离开校内创办海内至今
没有起色,也很说明了这个问题,校内的成功不是网站模式的拷贝成功,而是机遇的成功。

BTW:我个人觉得互联网创业当中的机遇是很重要的,王志东离开新浪以后至今没有翻身已经很说明问题了。互联网成功的创业人士
离开原来公司独自创业失败的例子我手里还有两个,因为认识就不方便点名了。总之,成功的人不要觉得自己很了不起,你的成功多
半是走了狗屎运。我到很佩服马化腾和丁磊,从不讳言自己成功有运气的成分。

校内网本质不是Facebook模式,而是社区网站,虽然他也做了必要的隔离,但是总体而已,UGC在校内还是占了很重要的部分,特别
是校内和mop整合的很紧密。我看过王兴创办海内的一个采访:记者问他为什么创办海内,他说校内网虽然抄袭Facebook,但是本质
上还是抄袭MySpace的,而他更看好Facebook,所以创办海内,真正抄袭Facebook。这段话我当时不理解,但是后来我明白了,你仔
细研究校内网,他的确是一个披了Facebook皮的MySpace网站,他的社区性质很明显。

校内的社区性质决定了他绝不会走Facebook的商业模式,为什么呢?如果你像我一样自己辛辛苦苦创办了一个社区网站,积累了这么
多会员出来,那么你绝对没有开放网站、开放用户的决心。因为这样一个社区已经可以让你真金白银的赚很多钱了,如果你现在彻彻
底底的转型搞应用平台,等于是放弃了现在可以触手可及的利益,而去博一个更伟大的赌注,除非逼到绝路,谁会愿意冒这个险?

不过坦白说,校内现在的条件很好,积累了足够多的用户,又融了4.5亿美元的资金,完全有资格去做平台,而不必担心什么风险,更
何况国内web2.0小网站空前高涨的app开发热情和淘宝网的经验也证明了Facebook的商业战略在中国完全有实现的可能性。但是以陈
一舟的性格和现在校内网的做法,我可以断定校内会亲自切入若干垂直领域,例如电子商务,旅游,网络招聘,web网游,在赚那么丁
点小钱的同时,放弃了成为真正的中国Facebook的可能性。我想,如果把陈一舟换成了马云,马云一定会选择走平台的道路,所以说
性格决定命运呀。

2、命运难测的开心网

前面说了开心网是真正气质上符合Facebook克隆的网站,实际上开心网成功的唯一秘诀就是抄袭Facebook抄的最谦虚,最真诚,抄到
了位。开心网最火的买卖朋友和争车位这两个应用都是抄袭自Facebook的“Friends for sale”和“Parking War”,号称开心网贴心的注册后
提示邮箱登录链接,其实也是原封不动的抄了Facebook。而开心网不过是忠实的抄袭了Facebook就已经惊人的成功了,由此可见国内
互联网的作弊家们,给点专业精神好不好,你抄也得抄像点嘛。

开心网唯一的问题就是商业模式,CPC广告在国内更加行不通,如果说Facebook还能用CPC赚到1.45亿的话,那么开心压根就不用指

第 208 / 283 页
http://robbin.javaeye.com 4.11 点评国内Facebook克隆网站 - SNS之我见(二)

望广告费。如果走Facebook的平台战略,构建一个巨大的应用平台,通过app商家来收费的话,这条路太长了,需要的投资太大。马
云的成功毕竟也有孙正义和Yahoo累计十多亿美元的砸钱。孙正义已经给陈一舟砸了4.5亿了,不可能再给开心网了。

所以我猜测开心网的商业模式会走第三条路,就是自己做web小游戏,最终转型成为一个SNS型的休闲web网络游戏网站。但是这条路
会走的很累:一是web网游市场竞争的激烈程度完全不低于SNS网站;二是纯做小游戏的开发成本很高。

目前开心网的小游戏都是自己开发的,但是这种小游戏是有一个新鲜期的,用户一开始玩活跃度很高,但是过了新鲜期,就逐渐觉得
没有意思了,用户经过了一段时间的活跃期,就会逐渐消沉下去,开心网现在已经开始出现这种问题了。所以传统网游的生命周期即
便不断更新也不过3-5年而已,这种web小游戏的生命周期就更短了,不过1-3个月而已。你要保持网站用户的活跃度,就要不停的开发
下去,因此开发成本会越来越高。

Facebook最聪明的地方就是他自己不开发app,只鼓励app开发商去开发,因此Facebook没有这个开发成本的巨大负担。开心网要想摆
脱这个困境,还是必须走Facebook平台战略,可以说开心不走平台战略就没有大的前途,但是开心要走平台战略,这个目标就太大,
实现难度过高。所以Facebook的模式不是那么容易抄的,你真想做Facebook的话,你不开放平台是根本玩不下去的,但你开放平台你
没有足够的资金支撑,你也玩不下去。

3、有点尴尬的海内网

王兴创办海内网的时候,已经意识到要避免成为一个社区网站了,但是由于他一开始没有从app切入,导致了海内以他不期望的方式成
为了一个IT同人社区了。但是他又非常不愿意接受这一点,极力摆脱。不过他不做IT同人社区,有的是人做,于是5GSNS出来了,海内
上面的大批IT大牛都跑了。不知道现在王兴究竟是高兴多一点,还是失落多一点呢。

海内网和下面要提到的所有SNS克隆网站相比,有一个本质不同:海内不提供网站公共信息的广播,你看不到朋友之外的信息,他还
是以Facebook那种模式,引导你去和自己熟人去社交。但不幸的是海内的用户们毕竟是在中国BBS泡大的一代,你不用app去勾引他
们,他们在海内只想着卧底发文搞UGC,而不是拉自己的哥们上来虚情假意的社交。

4、画虎类犬的UCHome、一起、5GSNS等等

这些网站都是披了Facebook外衣的MySpace克隆产品,加上海内这个本来想克隆Facebook但是无奈的成为MySpace克隆的产品。对于
这些网站来说,他们本质上并不是Facebook社交工具,他们本质上是web2.0社区。这些web2.0社区如果老老实实走克隆MySpace的路
也许还有点前途,但是非要披着Facebook的皮去克隆MySpace,怎么看怎么别扭。

别看现在UCHome搞了那么多功能,那么多插件,还开放了平台出来,但是他还是一个社区软件,不是社交工具。开心网出来已经3个
月了,这些网站也很迅速的把开心网的热门app应用抄过来了,但是他们的流量有起色吗?和开心的距离拉近了吗?为什么这几个网站
抄了开心网的必杀app应用,流量仍然没有起色呢?这是因为他们做的是社区网站陌生人交往,不是社交工具熟人交往。必杀app应用
只有在熟人之间才能用起来,你和陌生人之间买来买去的,谁会答理你?

大家可以自己去看看alexa,我发现一个特别有意思的现象:海内、一起和5GSNS这3个网站的独立IP和UV都几乎一模一样,这3个网站
的会员都似曾相识,一母四胞胎。这说明了什么?说明了用Facebook之皮做社区网站并不会迅速把流量拉起来了,除了开心网是真正
流量爆增以外,其他的3个网站现在支撑那点可怜流量的都是IT业的卧底们。

第 209 / 283 页
http://robbin.javaeye.com 4.11 点评国内Facebook克隆网站 - SNS之我见(二)

所以我的结论就是:无论你是用Facebook之皮做社区网站也罢,还是照抄Facebook的必杀app也罢,并不真正能够达到类似开心网这
种病毒式传销和流量爆增的效果。其原因就在于你就是做陌生人社区网站,而不是做熟人社交工具,所以这些app对你的网站用户扩展
无效。因此UCHome花团锦簇的推出那么多功能一点都不可怕,这些东西根本就不对路。

我的建议是,要想做社区就好好的从BBS起家,这是一条被证明成功的社区发展道路。但为什么这么多人都不愿意这样做,非要走一
条未来不确定的路呢?一言以蔽之,这些网站的创始人心里都有一个执念:“BBS是可耻的,BBS是没有商业价值的,BBS是没品的,
我作为一个有品的互联网资深人士,我得创造有品的互联网生活方式”

小戴同学在discuz!论坛上面写了很长的一篇帖子(不过比我这篇文章短),讲他为什么要开发UCHome,中心思想就是BBS过时了,
BBS缺点太大,我发现Facebook做社区比BBS更优越,所以我现在开发了UCHome。

谢文一直鼓吹三个代表精神:代表互联网的物质生活,代表互联网的精神生活,代表互联网的社会生活的一个超级web2.0社区?总之
谢文老师明枪明棒的要搞社区,结果却套了一个Facebook的皮上来。其实您大可不必,你要是不抄Facebook的皮,我就把你和豆瓣、
51.com放在一起看了。

5GSNS这个就不说,还不如用discuz!得了。

那么他们为什么要用Facebook的皮来做社区呢?

1、BBS的确有很大的缺陷
凡是运营过BBS的人都知道BBS的“劣币驱逐良币”的问题,低手充斥会导致高手的离开、社区的衰落。用Facebook的皮可以很大程度上
隔离用户,解决BBS最大的痼疾。

2、可以改进很多BBS没有做好的功能
比方说集中的信息更新通知功能,个性化推荐,更好的社区好友互动功能等等。

这些好处都是看得见的,再加上很多人本身对BBS的强烈排斥,更加倾向于用Facebook之皮来做社区网站了。我得必须承认,虽然
UCHome这个克隆完全曲解了Facebook之本意,但是UCHome也不失为一个不错的改良版本的社区软件。但是我得说,作为一个非盈
利性质的社区来说,用UCHome可能比BBS更好,但是对于一个有商业期望的网站来说,用UCHome做社区,无疑于自杀。为什么呢?
因为Facebook之皮本身是用来实现熟人之间的社交的,因此他是一个封闭的工具,非常不利于信息的传播!

传统的BBS要盈利,已经有两条被证明过康庄大道:

1、BBS转型做网络媒体,以BBS为基础成为网络媒体的成功案例简直多得数不过来:
新浪网的前身就是一个四通利方体育沙龙BBS;
网易的前身也是一个大BBS,我在98年还注册过账号灌水;
IT媒体类的网站,最近被收购的IT168,PCPOP哪个不是靠BBS起家的?太平洋电脑网也是BBS起家;
CSDN也是BBS起家,一开始是程序员大本营光盘的技术支持论坛;
被IT168买过去的ITPUB,ChinaUnix也是BBS;
JavaEye也是BBS起家;

2、BBS转型做电子商务
阿里巴巴网站一开始就是一个BBS,是马云亲自敲定要做BBS的;
篱笆网也是BBS,不用说了;

第 210 / 283 页
http://robbin.javaeye.com 4.11 点评国内Facebook克隆网站 - SNS之我见(二)

搜房网也是BBS起家

BBS起家的互联网网站太多了,这本来就是一条光明的大道。为什么这些互联网资深人士畏之如虎呢?

1、BBS的运营难度和成本都比较高
要运营好一个BBS,站长需要非常高超的平衡能力,以及一个得力的运营团队,能把一个BBS运营好是极难的事情,这里面的门槛非常
高,太多人想回避这个难度走捷径,造假,灌水,吵做,流量是上来了,社区的商业价值没有了。而且BBS需要持续不断的投入,一
旦运营投入不足,BBS的人气就难以为继。

2、越是互联网资深人士越希望用网站独特的功能取胜,不战而屈人之兵,越想避免商业上的短兵相接和踏实的运营。
对互联网特别有感觉的人,往往希望用自己的长处作为核心竞争力,希望用卓越的网站功能和体验去吸引用户,战胜对手,而不屑于
没有技术含量的日常运营工作和类似传统销售的营销方式。我感觉自己身上就存在这样的毛病,而且我也从上述很多人的言论当中感
受到了这一点。网站毕竟是公司,要遵守商业规则,踏踏实实的运营和赚钱比整天想着用杀手锏网站功能去击败对手更重要。

而且我也强烈的感觉到一点:走捷径成功的网站往往商业模式会难产,一点一点打拼上来的网站商业模式都是顺理成章的。上面提到
这么多从BBS起家的网站哪个不是踏踏实实运营了五六年以后成功的?而2005年风光无限的博客网站现在纷纷倒闭,博客网站的运营
难度太小,根本无法和BBS相比,因此无法像BBS那样容易催生商业模式。

用Facebook之皮运营的社区网站,其用户创造内容的传播途径是受阻的,因此无法成功的转型成为一个网络媒体,这BBS第一条商业
模式就堵死了;其做电子商务网站其用户传播的途径又受限于朋友之内,传播范围太小,无法形成有效营销,这BBS第二条商业模式
也堵死了。5GSNS要搞网络招聘,但是网络招聘市场的水非常深,我可以告诉大家的就是:截止目前为止,所有的垂直招聘社区无一
成功的,5GSNS在走一条没有商业前途的路,真要搞招聘,不能按照5GSNS现在这种搞法,所以这条也基本堵死了。

社区网站做SNS

另外还有一个有意思的趋势:一些以BBS起家的社区网站也开始SNS化,开始引入Facebook模式:一个是TechWeb用UCHome架设了一
个社区,这个我就觉得很搞笑了,明明有自己的BBS,还搞UCHome自己抢自己的用户?另外一个稍微高明一点,CSDN把个人空间和
个人博客改用Facebook之皮来实现了。其实这层皮并不重要,重要的是你怎么给社区的用户提供好的个性化推荐、好的个人信息聚
合、好的朋友交流工具,这些我在CSDN个人空间尚未看到。

本质上来说Facebook的社交工具和传统社区网站是冲突的,但是把Facebook某些好的功能元素融入社区网站,以改良BBS社区的弊
端,创造一个更加活跃的社区网站,并不是不可能。不过这里还是需要你有自己创新的思路,而不是照搬Facebook或者UCHome。

第 211 / 283 页
http://robbin.javaeye.com 4.12 社区网站SNS化的思考 – SNS之我见(三)

4.12 社区网站SNS化的思考 – SNS之我见(三)

发表时间: 2008-07-12 关键字: sns, community

一、 SNS工具还是社区网站?

Facebook的创始人马克扎克博格在多次接受采访的时候都强调过:Facebook是一个社交工具,在前面两篇文章我也阐示了这一点。因
此SNS网站在我看来分为两大类:

1、Facebook类的SNS,他只是一个社交工具,他不是社区,没有UGC,没有社区文化。Facebook是封闭性质的网站,未注册用户什么
都看不到,即使是注册用户也只能看到自己和好友的状态。

我想强调的是:Facebook的封闭性是由于他的工具属性决定的,我们假设Facebook完全开放出来,你说你能看到什么:由于Facebook
根本就没有内容,你能看到的也只是用户的状态而已,但是对于你不熟悉的人来说,他的状态对你是没有意义的,你也只会关注你的
熟人的状态而已。因此Facebook的封闭性只不过是Facebook工具属性带来的现象而已。

国内属于这一类性质的SNS网站只有开心网一例。这类SNS网站具有真正的病毒式营销能力,从开心网恐怖的Alexa曲线就可以一窥端
倪,从拉用户和创造流量的角度来说,这种网站模式无疑是成功的,当然人品守恒定理告诉我们:走捷径的网站商业模式是难产的,
开心要想成功,还有太长的路要走。

2、MySpace类的SNS,他是一个社区,有社区文化,有UGC,但具有SNS的某些属性。他是半开放性质的网站,未注册用户可以看到
注册用户创造出来的UGC,但是看不到注册用户的状态。

除了开心网之外所有的Facebook克隆网站和豆瓣都属于这一类。至于腾迅和51.com我就不分析了,像我这种平生没进过网吧,没打过
网游,不用QQ的人来说,他们已经超出了我的认知能力了。

在这些社区网站当中,我尤其反感披着Facebook皮的MySpace克隆们,以UCHome为甚。以我使用Facebook的经验来说,如果是你自
己主动注册SNS,而不是熟人邀请你加入,那么这个SNS网站对你基本就是摸不着门道的。但我惊奇的发现,事实却不是这样,为什
么呢?

因为UCHome们已经为你提供了贴心的全站信息广播功能了,你一注册上去,在你个人profile页面下面就有整个网站陌生人的各种状
态,发布的文章,评论等等。当然由于社区大牛肯定很活跃,所以映入你眼帘的一定是他的文章和他的状态。于是你很快就在这个社
区找到自己可干的事情了。

从新手切入社区的角度来看,UCHome和传统的BBS社区没有本质区别,甚至会造成新手更多的进入障碍和使用习惯上面的挑战。从整
个社区的角度来说,由于社区的封闭性,也非常不利于网站的推广,更加由于社区的封闭性,导致社区本来应该有的媒体广告价值也
被阉割了。

至于这些克隆网站幻想的电子商务模式,也基本属于不靠谱。因为任何商业模式的临界点都需要足够规模的用户量,而这一关他们就
过不去。在这些网站当中,除了校内网由于历史机遇的原因、也由于整合猫扑的拉动作用,已经成功的把规模发展壮大之外,其他网
站现在规模都还在极低的水平徘徊,即便迅速抄袭、全部配备了开心网赖以成功的app游戏,仍然没有任何起色。从拉用户的角度来
说,这些网站甚至不如传统的BBS更加有效。所以这些网站就不多提了,我在前一篇文章已经分析过了。

二、豆瓣和一起的网络虚拟城市构想
第 212 / 283 页
http://robbin.javaeye.com 4.12 社区网站SNS化的思考 – SNS之我见(三)

虽然我在上一篇文章当中揶揄了谢文老师,但是我得承认谢文和其他几个Facebook克隆者相比,是有着本质区别的。虽然谢文流俗的
抄了Facebook的皮,但不像其他几个根本就不知道自己要做什么的克隆网站,谢文很清楚自己要做的是社区而不是SNS,或者更准确
的说,谢文要做的是一个网络虚拟城市。豆瓣的构想在自己的官方博客当中已经很鲜明的阐示了:豆瓣是一座仁者见仁、智者见智的
城市。

构建一个网络虚拟城市,将人们的现实生活映射到虚拟社区当中,满足人们在网络空间和现实空间的各种需求,将提供给社区里面人
们的服务外包给各个提供服务的网站,和各个提供现实服务的厂商。这就是谢文构想的宏大计划。豆瓣的计划未必有这么宏大,但是
豆瓣想要构建网络虚拟城市的目标和谢文是一致的。从这一点来看,一起和豆瓣是具有原创精神的中国web2.0社区网站,值得大家长
期关注。

但是当我们仔细审视这样一个宏大的目标,我有两个疑问盘旋在脑海当中:

1、要构建一个成功的网络虚拟城市,需要极其庞大的用户量,至少需要上千万规模的真实有效用户,否则虚拟城市的环境难以有效运
作。但问题是你能够积累出来这么多真实有效的用户吗?一起和豆瓣这样的社区网站定位还是比较高雅的,起码相比腾迅和51.com要
高雅的多,迄今为止51.com也不过2400万注册会员(其中真实有效会员比例就不清楚了),以大中城市的白领为主的社区网站,潜在
用户能有1000万吗?即使把所有潜在用户都拉过来,也未必能够达到商业模式的临界点。

2、网络虚拟城市的需求是多种多样的,单纯依靠网站自己的开发力量,随着用户量的增长,肯定会越来越不足,所以必须开放平台,
推动第三方app开发商来满足日益增长的用户服务需求。如果沿着这条路走下去,最终还是会变成一个巨大的应用平台,而不是一个社
区网站,其商业模式也最终会走向Facebook模式。那么为什么不更加直接一点,直接走Facebook的路呢?

我看alexa的曲线,开心网已经逐渐逼近豆瓣了,照这种趋势发展下去,用不了三个月,开心的流量就要超过豆瓣了,而现在一起的流
量还在非常低的水平徘徊。从网站发展只争朝夕的角度来看,豆瓣和一起的模式未免发展的太过缓慢。

因此我的结论就是:无论选择的路径是什么,如果你的终极定位是SNS的话,那么或迟或早的要走向Facebook的社交工具和应用平台
模式。

第 213 / 283 页
http://robbin.javaeye.com 4.13 什么样的社区能够成为集大成者?- SNS之我见(四)

4.13 什么样的社区能够成为集大成者?- SNS之我见(四)

发表时间: 2008-07-13 关键字: sns, javaeye

一、题外话

最近我的博客文章被广泛转载,在互联网圈中引起一阵阵涟漪,这已经远远超出了我的本意。我写博客文章的本意只不过是整理自己
的思路,我既非互联网圈内人,也没有兴趣混这个圈子,我写文章也不是为了给互联网圈内人看的。我关注互联网发展趋势,并且分
析互联网热门题材的目的很明确:就是希望从中获得一些有价值的启发,从而更好的发展JavaEye( http://www.javaeye.com )这个技
术社区网站而已。

因此互联网界的人士们实在没有必要因为我这个圈外人说了几句讽刺的话而感到不爽,更没有必要一本正经的分析我的文章。如果一
个非技术人员写了一篇分析软件行业的文章,我就只当他扯淡,连看他文章的兴趣都没有,所以你们没必要看我的文章,更没必要当
回事。

很多互联网圈内人看不惯我的文章也不奇怪。我分析网站的思路只看最本质的唯一特征,其他枝节都不看,化繁为简,直接定性。我
习惯形成自己的思维方式,然后运用这种思维方式去观察和分析事物,总结出自己的理论体系和实践指导方针。别人的思维方式和观
点是什么样的,我并不关心,我只关心在我自己的思维方式体系之下,SNS会被归纳成什么,然后我怎么来指导我自己的行动。

很多人不同意我的观点,纠住细节不放,非要用细节经不起推敲来论证我的观点是错的,或者非要我给出什么数据来论证我的观点不
可。但我真的没什么兴趣非要说服别人不可,特别是没什么兴趣用别人认可的思维方式去论证。我并不需要向别人证明什么,也不需
要通过别人的认可来肯定自己的价值,我只在乎自己长期以来形成的思维价值观是否有效:我的思维方式体系能不能从眼花缭乱、茫
然无措的现象当中归纳和总结出本质,给我自己指明行动方向,以及如果我的思维方式体系出现了偏差,我应该怎么修正和完善它。

二、中国互联网社区运营方式的探索

我是1998年开始上网,算而今也有10年上网历史了。在网络社区的形态上,中国互联网经历了:BBS -> 博客 -> SNS这样一个缓慢的


变迁过程。回顾过去的10年:

1、BBS经久不衰,商业模式也久经考验
这个不用多说了,前面文章我已经阐述过了。从BBS起家转型成为门户网站,或者垂直门户网站,是第一代互联网成功的典范。

2、博客的冰火两重天
2006年是BSP的滑铁卢,新浪博客的推出标志着BSP的末路,到现在BSP硕果仅存的也开始纷纷转型SNS了。这里面有两个非常值得玩
味的地方:

1)新浪博客指明了博客作为一种网站形态存在的商业价值
到现在为止,新浪博客已经成为新浪访问量最大的频道,并且成为新浪网新闻内容的主要来源之一。传统的新闻门户依靠编辑采编内
容的模式的高昂成本,被博客源源不断的UGC供给大幅度降低了。所以博客成为了廉价的新闻编辑和内容来源。这就是博客对于媒体
网站的主要商业价值。

可以说凡是具有媒体性质的社区网站,都可以把博客这一属性玩活。比方说CSDN的博客活脱脱就是照搬新浪博客的模式,而且效果非
常好。JavaEye也是这样的,博客频道成为网站高质量内容来源的一个重要组成部分。但是传统的BSP难以转型成为博客媒体,这是因

第 214 / 283 页
http://robbin.javaeye.com 4.13 什么样的社区能够成为集大成者?- SNS之我见(四)

为他们既没有BBS,也没有新闻采编队伍,没有办法树立一个网络媒体的形象定位, 博客人群又过于松散,没有定位在垂直领域里
面,因而无法把博客的媒体属性价值最大化利用起来。

2)UCHome和蚂蚁尝试挖掘博客的SNS价值
既然博客的媒体价值无法挖掘,那么能不能用SNS的形式去组织博客,加强博客的互动性,以博客为个人中心,组织一个SNS社区
呢?目前看来用UCHome的5GSNS和蚂蚁社区有这方面的尝试。

3、SNS的变迁

第一代模仿MySpace的SNS已经式微,第二代模仿Facebook的SNS只有开心网我相对比较看好,目前其他SNS主要还是社区形态,但
是和第一代所不同的是,稍微有所创新,开始尝试融合博客进来了。

康盛创想在两年多以前就推出了整合BBS和博客功能的SuperSite,但是一直很不成功,博客特性没有发挥出来,对此小戴认为是真正
能持续贡献博客文章的人太少,但我不这样看,SuperSite失败的主要原因在于没有强调博客的独立性,博客成为了BBS的附庸。没有
一个人愿意自己的博客成为某个网站的某个功能的附属品,而希望博客是相对独立的。

JavaEye网站在两年前开发JavaEye2.0版本的时候,也开始进行BBS和博客的整合,发展到今天来看,虽然没有达到预期的全部效果,
但是也相当成功,根本原因在于尊重了BBS和博客的不同使用习惯,仅仅在底层数据存储进行了统一,在页面操作还是完全分离开
的,既不至于让用户觉得自己的博客是BBS的附庸,也可以方便用户文章在博客和帖子之间任意转换。

康盛创想在SuperSite失败之后,再接再厉推出的UCHome可以视为针对博客和社区整合的创新努力,但是这一次不是博客和BBS整
合,改成了博客和SNS整合了。但是在我看来,无论是SuperSite还是UCHome,都没有改变一点:博客的附庸地位!现在的UCHome
还是一个SNS框架,博客是SNS框架里面的节点。针对UCHome里面的个人博客访问是相当受限的,而且个人博客和个人Profile完全混
为一谈了!

个人博客应该存在两张皮:一张皮是公开出来的,作为blogger的对外公开形象存在的,是个人的网络名片;另外一张皮是博客管理界
面,类似Facebook的profile页面,blogger可以浏览博客的状态,管理博客和评论,跟踪访客的状态的。但是UCHome把Facebook的
profile当做了博客对外的那张皮,这就让我感觉有种超人的内裤外穿了,无论我想暴露还是不想暴露的内容统统一股脑暴露了。 固然
这样做可以加强交流不假,但是其结果就是并不会有人真正用这个来写博客,也不会把自己在UCHome里面的profile页面当做个人的公
开网络名片。换了是我做UCHome的话,我会把博客和个人Profile 页面分开来,而不是合并在一起。

总之从社区形态来说,目前国内互联网的社区有大致这样一些类型:

1、BBS为基础的,例如天涯、猫扑、西祠、搜房、篱笆等等,这些活的都很好。
2、 Blog为基础的,例如博客网,blogbus等,这些都要转型做SNS了,或者所谓的blogsphere了。
3、从SNS切入,融合Blog形态的,例如5GSNS(UCHome)、蚂蚁等等。
4、想做网络虚拟城市的SNS,例如豆瓣,一起等等。
5、其他各种类型杂交的,很多。

每个做社区的网站都在尝试解决BBS和Blog的弊病,都在尝试新的社区模式:

1、BBS是以话题为中心组织的,不利于个人的信息组织;
2、Blog是以个人为中心组织的,不利于信息的流动和分享;
3、第一代SNS是以兴趣小组为中心组织的,不利于个人信息组织,也不利于个人信息流动;

第 215 / 283 页
http://robbin.javaeye.com 4.13 什么样的社区能够成为集大成者?- SNS之我见(四)

4、第二代SNS是以关系为中心组织的,能解决所有的问题吗?

三、我心中理想的社区形态是什么样的?

我写整个系列的四篇文章的过程,也是我整理自己思路的过程,希望在自己的脑海当中勾勒出一个比较清晰的理想化社区的蓝图,我
心中理想的社区应该具备如下的特征:

1、社区应该是公开性质的,但具有三层不同的属性:针对未注册用户,他是一个具有媒体性质的社区门户网站;针对注册用户,他是
一个有高度定制能力的个性化web2.0网站;针对核心用户,他是一个熟人社交工具。我希望针对不同层次的用户,展现出来网站的不
同层面的属性。既不应该是完全排斥未注册用户的封闭社区,也不应该是注册不注册都一个样的BBS,也不希望他仅仅只是单薄的熟
人社交游戏网站。

2、BBS和Blog分别作为独立的社区形态存在,Blog作为个人网络名片,应该具备独立性,但是底层是统一为一体的。目前JavaEye已经
很好解决了这个问题。

3、社区应该提供Blog之外的个人信息聚合中心,并且允许用户对个人的信息聚合中心进行充分的定制,比方说我不想看网站的千人一
面的首页,我可以订阅我关注的板块内容,把我的profile设置为网站首页,那么以后我一登录网站看到的就是我自己定制的网站,我看
到的内容都是我关注的内容了。

4、社区应该在个人信息聚合中心提供个性化推荐,根据用户的行为,推荐他可能感兴趣的人和内容。

5、提供把陌生人转化为熟人的工具,想想看Facebook是怎么定义熟人的,你就知道我指什么了。此外要为熟人社交提供必要的道
具。

第 216 / 283 页
http://robbin.javaeye.com 4.14 SNS网站的用户流失率怎么会高得如此惊人?

4.14 SNS网站的用户流失率怎么会高得如此惊人?

发表时间: 2008-07-15 关键字: sns

平生第一次博客转载别人的文章,原文作者是51.com的高管黄绍麟
---------------------------------------------------------

作者:黄绍麟

◎用户典型的SNS体验

甲先生是个普通白领,白天工作使用互联网找资料连络客户,下班后回家偶而会上网闲逛。互联网是他日常接触的媒介,但是在他生
命中这个东西并不显得特别重要,至少他不是天天泡在网上的人。然而最近几个月来,他老是收到一堆电子邮件,标题大部分写著
「某某人加你为好友」之类的。顺著连接过去看,是自己MSN 上面的朋友。既然是朋友的邀请,总是不怎么好意思拒绝,想想也就注
册加入。于是,甲先生先后加入Facebook,MySpace ,Friendster,LinkedIn ,还有一堆中文的本地网站。而注册这些网站总是十分痛
苦,每个网站都叫他填写过去经历,上传照片,还要贡献MSN 上的好友清单。

刚开始他担心这些朋友是不是会常来拜访他的个人空间,而他如果不知情,没回访,是很不礼貌的。这种来自人际关系的压力颇大,
搞得他有段时间下班后天天上网回覆这些朋友的消息,一耗就是两小时。(妙的是,他其实不知道这些朋友也是碍于类似压力而耗在
上面)
一开始是熟人,后来一堆陌生人也把他加为好友。天天跟这些人在网上「搞关系」,刚开始还颇觉得有些意思。看看好友又更新了照
片,又写了新的Blog,彼此间留留言打招呼,似乎也颇惬意。

然而大约三个月后,甲先生开始觉得乏味。跟一堆人在网上Social来 Social去,实在挺无聊。随著朋友越来越多,不得不耗在上面更多
时间。更痛苦的是,每个网站他都得去照顾,每天两小时已然不够。终于,他决定戒掉。这类让他一度上瘾到无可自拔的互联网服
务,在精神压力达到临界点后,终于被他废弃。花大量时间搞这些关系到底什么意思?生活不该是如此的,他要拿回主控权。

◎SNS经营者的典型经验

所有的SNS网站经营者都困惑,用户流失率怎么会高得如此惊人,而且找不到方法可以根治问题,似乎这本来就是SNS网站的天性。
靠著人际网络的压力而驱动的事业,也因压力解除而退散。过去的SNS网站像一个大筛子一样,一瓢子捞下去,看似捞到大量用户,
然而经过三个月的时间,总是仅剩下不到一半的有效用户,其馀的用户根本不再来了。用户量看似很大,其实很虚。而一个SNS网站
之所以能够急速成长,主因是透过人际关系鍊拉动的增长,其速度远大于用户的流失速度。当增加多而流失少,看起来整体就是增加
的。然而,当用户的增长慢下来的时候呢?

MySpace ,Facebook如日中天。若以全世界为市场范围,这些网站确实还没碰触到天花板。因此,向其他国家扩张看似是维持增长的
解决方案。然而,本质的问题没有解决。SNS网站还有一个也是很奇特的惊人现象。就是一旦成为网站的活跃用户,这个用户就会非
常活跃,而且维持非常长的存活周期。几乎可以说是以此为家,天天报到,赖著不走。

从注册用户到有效用户到活跃用户,这条路上有大量的人脱队。这个现象是不正常的吗?非也,这完全是网络社区的正常现象。笔者
多年前就说过,网络社区是「性质相同的一群人,聚在一起互相取暖」。这群人的名字,叫Heavy User。简言之,活跃的Blogger 属于
这群人。SNS的特性是高度互动,而互动本来就很累人。愿意跟别人大量互动天天写博客的当然不是常人。他们的表现欲,成就动

第 217 / 283 页
http://robbin.javaeye.com 4.14 SNS网站的用户流失率怎么会高得如此惊人?

机,都高于一般人,并且最终在某个社区网站里找到舞台与归属感。问题是当这群人玩得很开心的时候,一般网民在干什么?

◎SNS是会玩腻的

那些抛弃某个SNS网站而去的人,是不是跑去玩其他竞争网站的同类型服务了?有小部分人是的(嗯,就是Heavy User),但大部分
离开的人不是,他们是从此不玩这类型服务了。玩腻了Facebook之后转而去玩MySpace 的人是少数人,大部分的人是从此离开SNS 这
类型服务。写博客也是一样的,从某大博客平台换到另一个博客平台继续写作的是少数人,大部分的人是停笔。

离开一个网站跟离开一个服务,完全是两种概念。举个例子来说,「看厌了新浪新闻而转看搜狐新闻」,跟「从此不看网络新闻」,
我们很明白的知道差异在哪。真糟糕!原来SNS服务是一种会玩腻的服务!真糟糕!当所有网民都已成为我SNS网站用户,再来该怎
么办?如果把市场发展比喻成下棋,那么过去几年红透半边天的SNS概念网站,已经走入了残局阶段。网站经营者表面看似风光,心
底下却打鼓。摆脱这些本质上的宿命,成为不得不然的工作。令人意外的是,解决之道居然在于Web 1.0 。

SNS网站的用户数多寡,完全看它占领那个社会阶层(或者文化阶层)而定。

◎社会阶层决定网站用户数

SNS发展至今吸引了大批创业者加入,然而时局已经不再大好,很多网站走入关门边缘,在求发展与求获利中挣扎。想要再融资是不
太可能,因为亚洲地区的创投界已经不像以前这么看好这个领域。市场局面大势底定。在中国大陆,用户达到数千万级别的,可期望
藉第三轮融资发展,但面对大型 1.0网站也进入市场的挑战;用户数仅数百万级别的,用户数也不会再快速增加,必须自己想办法营
利。

在台湾,由于有雅虎台湾这个市场独大的门户网站,再加上原本就狭小的市场,小型SNS网站积弱不振,距离营利之路很远。但与此
同时却有一些老牌社区网站存活很好,获利颇佳。为什么会造成这种市场局面?笔者以前说过,SNS的发展基础是社会学,因此一个
SNS网站的用户数多寡,完全看它占领了那个社会阶层(或者文化阶层)而定,那个阶层直接决定了用户数的上限。

因为SNS网站几乎是靠著人拉人发展起来。每个用户会拉动的人都是他生活上熟悉的圈子,不管陌生人或熟人。当同一种阶层的人在
这个网站越积越多的时候,其他阶层的人也越难以加入到这里。等到网站有第一批用户,为了牢牢抓住他们,及利用他们带更多用户
进来,必须更加揣摩他们的心思甚或社交习惯。结果更深化了这样的发展,更加走向某一种文化氛围或者社会阶层,再也无法回头。

◎经营团队本身的社会阶层决定用户多寡

要观察一个SNS网站发展,看它第一批用户是甚么人就知道了。 Google的 SNS网站Orkut 一开始无心插柳在巴西大受欢迎,其他国家


用户从此很难加入。我们身旁几乎没人用Orkut ,尽管我们用Google。韩国最大社区网站Cyworld 先前进军美国,当然想吸引欧系美国
人来用,没想到却吸引到一堆亚裔小男生小女生。为什么?因为网站功能设计甚至文化氛围始终比较接近亚洲人户习惯。而交友网站
Friendster自从积累大量菲律宾用户后,其他国家的人也很难融入那个圈子。这就是文化界线。纵然跨国SNS网站能吸引到全世界用
户,仔细观察这些人,会发现都是性质靠近的一群。

反观国内,51.com的用户一开始从二线城市网吧发展起来,现在很难拓展用户群到一线城市的白领。反之其它SNS网站也打不进二线
城市市场。文化的氛围以及实体世界的社会阶层,就是这么影响著。占有「上层社会」(指白领)的SNS网站,用户数发展注定受

第 218 / 283 页
http://robbin.javaeye.com 4.14 SNS网站的用户流失率怎么会高得如此惊人?

限。特别在中国大陆,白领是占总人口比例极少的一群,大部分生活在沿海。以这个群体为目标的SNS网站用户数很难上到千万。

至于台湾的共享书签网站黑米与推推王,使用族群的文化氛围便明显不同。前者要更加精英一些,后者要更加普罗大众一些。然而两
者都不脱白领的社会阶层,因此不如老牌的草根社区高流量或赚钱。

再往前一点看,要观察一个SNS网站发展,看它的创业团队是属于甚么样的社会阶层就知道了。因为这群人会把自己的思维放进到社
群的经营上,而这些思维绝对受到这些人本身所处社会阶层的制约。

◎有文化的东西做不大

有的SNS网站或者社区网站并不是占领某一种社会阶层,而是占领某种文化团体或者兴趣团体,例如以动漫为主题,以运动为主题,
以文学为主题,以书评为主题,或者以美食为主题的社区。这些社区一定都受到社会群体的大小制约。例如,喜欢动漫的人在中国大
陆市场有多少?喜欢美食的人在台湾市场有多少?在中国大陆这样的市场可能让网站经营者足以养活自己,在台湾可能就很艰难。

SNS网站或者社区网站为什么做不大?除了社会阶层的制约外,也因为「有文化的东西本来就做不大」。只要一个社区网站你能清楚
说出它是属于一种甚么样的文化氛围,他就是做不大的。难道「没文化」就能做大?要弄清楚这里的「没文化」不是指低俗文化,而
是指「讲不出来是什么文化」。只要能讲出这个网站属于哪种文化,就一定有人讨厌这种文化。无法讨好所有人的结果就是做不大。

然而这太强人所难了!社区正因其文化氛围吸引兴趣相投的人靠近并留下,怎么可能没有文化?然而也正是如此,不喜欢这种氛围的
人也都不来。很多老牌社区网站多少年过去了,也就那个样子没有大发展。令人意外的是,解决之道居然在于Web 1.0 。

◎SNS就是直销

在传统商务世界里,创业者要创新或生产好产品或许不难,但是要寻找渠道让商品到达终端用户却困难得多。或许寻找渠道也不难,
但可能因此付出高昂代价。拥有渠道的资本家,并不是容易被扳倒的对象。10年前互联网兴起,第一次打破这个现象。对创业者来
说,商品就是网站,提供的服务可直达终端用户,不再经过其他渠道。过去资本密集的报业所拥有的渠道优势被瓦解,成就了 1.0的
网络世界。这种新渠道除了冲击传统媒体也冲击传统商务,当然更冲击传统的通信方式。总结来说,过去 1.0之所以能有这么多小本
创业的人,可看成是创业家们找到了低成本的营销渠道,避开了传统资本家的封锁。

然而,Yahoo!之类的创业者,10年后却成了新资本家,他们掌握渠道让新兴互联网创业者难以出头。创业家必须花钱到传统渠道(也
就是 1.0网站)买所费不赀的广告,否则自己的网站就一个访客都没有。在传统商务世界里,许多年前有人发明一种新的渠道,透过
人际网络可以避开传统渠道的困局而达到销售目的,称为直销。而当互联网上已经有这么多巨头存在的时候,要怎么样避开而进行低
成本推广?答案就是人际网络。SNS创业家精巧的利用人际网络达成「以人带人」的低成本营销。如果不是这玩意儿,这些新网站的
用户数和流量都不会起来的。我们应当对透过人际网络的推广手段予以高度肯定。

◎回归基本才能做大

很多人买过直销商品,却觉得从这管道买东西很不牢靠。参与直销体系的人流动率高,本身就不是稳定的销售体系,SNS靠关系链吸
收新用户也一样。况且,推广方式再厉害也解决不了产品的本质问题。

第 219 / 283 页
http://robbin.javaeye.com 4.14 SNS网站的用户流失率怎么会高得如此惊人?

本系列第一篇文章提到,SNS网站的用户流失率极高,这是第一个问题;用户流失后不是流向竞争对手,而是不再玩同类型的网站,
这是第二个问题。对经营者来说,这延伸出两个思考:首先,别人流失的用户也不会是你的用户,结论是必须抢夺用户的第一次。想
想还有哪些用户没被染指过的,产品就往哪里做。

其次,用户终归要流失,因此最重要的是抢夺活跃用户。只有活跃用户可能会在同类型的SNS网站之间到处迁移,也会尝试新的网
站。牢牢抓住这群用户,网站经营至少就先立于不败之地。

掌握某一个层面的活跃用户,网站大概就可以开始谈营利,也能小而美活得过去,以往成功的社区网站莫不如此。但是对于那些怀抱
大企图想把用户群体扩增到没那么活跃的用户去,又该怎么办?摆脱掉太过强烈的社区气息吧!摆脱掉太过强烈的文化氛围吧!越是
接近人们基本需求的东西,越是不带有上述的气息。这样的东西有三个,存储(Storage ),工具(Tools ),以及内容(Content
)。简单来说,就是 1.0时代的产物。

◎下一步:存储,工具,与内容

Facebook创办人Mark Zuckerbery 说,Facebook不是一个社交网络,而是一个社交工具。由于其开放 API的关系,外界对于这句话的解


读是朝向「Facebook变成一个操作系统或平台的可能性」上去讨论。这句话之所以经典,正在于他精要的点出一个道理:只有做「平
台」才能大。笔者的解读是,只有工具才能够维持一个人的使用习惯,而且最重要的是,平台与工具本身都是跟文化无关的东西,人
人能用。

你用Gmail 写信用MSN 发讯息,这些工具跟文化的关系并不大(至少不像社区网站那样强烈)。过去做惯了炒热社区气氛以巩固活跃


用户的经营者,现在要开始来想想有哪些工具是比较冷的,人人都能用的。

也正因此,与社交高度相关的工具,实时通讯软件IM,看似在过去10 年已经定型的市场,台面下却翻滚著一股暗潮。拥有几亿用户的
SNS 社交网络服务经营者,推出来的新IM工具有可能扰动一池春水。

此外,人人都有不想社交的时候。 SNS网站可不可以只要简单的让我存放自己的照片,文件,收藏的网址就好,我的个人首页最好都
没人知道,也不要老拿别人最近的活动来烦我?
存储(Storage )就是这种最底层的需求。相较于活跃用户一天到晚四处Social,更多人是只需要这样子的服务就好。当用户玩腻了社
交,还有什么会让他还常来?或许就是放放照片而已。活跃用户来,是因为关系在这里;其他用户来,是因为家当在这里。

◎SNS进化即将完成

第三样东西是内容,这个部分比较容易理解,也很多SNS网站在做。对于Social不那么热衷的人,弄一些内容给他看看。当然,使用标
签等功能进行内容的聚合是常见的方法。
谈到这里,会发现SNS走到头来,还是没离开笔者多年以前说过的,互联网的四根柱子:内容(Content ),社区(Community ),
通讯(Communication ),商务(Commerce)。

只是 1.0时代我们从内容起步开始经营网站,逐步让网站具有社区,通讯及商务功能。SNS时代,我们从社区开始起步,逐渐往内容以
及通讯工具走,最后必然也走进商务。我们终于看清SNS的时代意义,他是全球网站的大进化。所造成的结果并非新的取代旧的,而
是新的逐渐混入旧的,而旧的逐渐融入新的。因为不管是几点零,都是人在用。而人,使用习惯没有改变。

第 220 / 283 页
http://robbin.javaeye.com 4.15 珍爱创业,远离SNS - SNS之我见(五)

4.15 珍爱创业,远离SNS - SNS之我见(五)

发表时间: 2008-07-15 关键字: sns

我泡5G这个SNS只有三天,但是三天来的感觉就是两个词:上瘾!非常上瘾!在你的关系网络当中,任何一个朋友的一举一动都会迅
速广播到网络的每个节点,而每个节点受到这个扰动以后,就会有相应的反应,于是这个反应又立刻广播到关系网络的每个节点,产
生连锁反应,在很短时间内,所有的节点之间互相影响,互相叠加,以类似核弹爆炸的链式反应一般指数级增长,最终造成了信息大
爆炸!

其实SNS里面真正创造的单位信息并不多,但是在关系网络这个异常敏感的链式反应堆上面,哪怕增加一丁点核燃料,都会引起整个
反应堆的核裂变过程。作为关系网络节点的用户来说,不管你愿意还是不愿意,都主动或者被动的参与制作了整个反应堆的裂变过
程。你越活跃,你的信息就越多,你的信息越多,就刺激你越活跃,所有人都像打了鸡血,拼命互动,拼命的制造信息,想停也停不
下来。大量的信息一晃而过,没什么留存,泡过以后除了兴奋感和疲惫感,什么都没有留下,这种感觉很像史玉柱的网游:很快让你
上瘾,牢牢的抓住你,刺激你的肾上腺素,不把你泡的精疲力尽不算完。

因此SNS是一种很廉价的拉动用户和PV的网络模式,可以说拉流量的确很有效,但是负作用太大,是一种竭泽而渔的做法,用户一旦
厌倦,就真的对所有SNS网站产生排斥感了。并不是所有的用户心甘情愿的沉迷进去,并不是所有的用户都希望黏性越大互动越频繁
越好:很多用户并不希望社区的侵入性太大,一个健康的社区软件要有高超的平衡性,不能对用户产生太大的侵入性,特别是不能影
响到用户的正常生活。或者说至少我不会去做这种社区,这种模式除了获得单纯的PV之外,对客户无法产生商业价值,对用户也会造
成潜在的伤害。好的社区要给用户选择权,如果有些用户只是希望在这个社区安安静静的呆着就好,你应该给他创造这个空间,而不
是有意无意的引诱他一起陷入疯狂。

所以用贾志新的话来说:“对于要做内容的站,碰不得SNS,更碰不得UCHome。很多web2.0网站的创业者创业的初衷就不是web2.0能
带来新的价值,而是想用web2.0绕过 web1.0的积累,走捷径,但是产品也好网站也好,没有长时间积累,转眼之间爆发的东西很容
易迅速降温”

其实我写这篇日志的时候,已经发现自己对UCHome的论断是错误的了。从5G来看,我这个不是互联网圈内人,也不怎么认识,不怎
么和圈内人来往的技术人员尚且有上瘾的感觉,就足以说明,用户注册5G或许是因为keso,但是用户泡5G,绝对是因为UCHome的产
品设计让用户上了瘾,在这种情况下,一些产品设计上的缺陷就显得无足轻重了。所以我删除了《SNS之我见》后面两篇讨论
UCHome的内容。

但是作为我来说,不可以用这种办法去做技术社区,因为技术社区的商业价值在于他对于软件公司和软件厂商的影响力。现在很多软
件公司的老板默许开发部员工上班泡JavaEye,是因为他明白员工泡JavaEye对工作有好处,他招聘员工也信任JavaEye,他相信好的开
发人员肯定泡JavaEye。而软件厂商要做广告或者活动,去找开发者做调查,问他们去什么社区交流技术,他们都说JavaEye,这样客
户已经接受了我们网站。如果JavaEye做交友SNS,程序员整天泡在上面风花雪月,固然是皆大欢喜,但是软件公司老板会封杀
JavaEye网站,软件厂商也不会认可JavaEye的价值,最终就是死路一条。所以做内容的网站,如果有自己明确的商业价值定位,就应
该远离SNS,远离UCHome,基于这种判断,我也不太看好5G,特别是不看好5G搞网络招聘的想法。

总之,我还是那句话:珍爱创业,远离SNS。

第 221 / 283 页
http://robbin.javaeye.com 4.16 SNS的工具化思考 - SNS之我见(六)

4.16 SNS的工具化思考 - SNS之我见(六)

发表时间: 2008-07-17 关键字: sns, tool

我上一篇文章的标题是“珍爱创业,远离SNS”,很多人说你太极端了,不能片面的否定所有的SNS。其实我这个口号是有上下文的,准
确的说,应该是“如果你希望做一个以内容为主的web2.0网站,那么千万不要搞成陌生人SNS交友社区”。

从我写的这个系列第一篇文章开始,我就区分了两类SNS网站:一类熟人社交工具网站,例如Facebook和开心网;另外一类是陌生人
交友社区网站,国内其他的SNS都是这种网站。

前一篇文章我主要谈的是陌生人交友社区的问题,这类网站往往通过刺激用户的持续高潮来透支用户,达到短时间内流量激增的效
果,当然负面影响也很大。针对这类网站我觉得最重要的改良方向是把双向反馈的好友关系拆开,拆为两类:一是单向的订阅关系;
一是双向的熟人关系。单向的订阅关系只是我关注别人,我的动作不会对我关注的人产生影响,这样就可以有效打断泛滥的信息爆增
问题。

这篇文章我想探讨的问题是熟人社交工具,我观察了一下开心网,开心网的熟人社交特色体现的很鲜明:

1、开心网很注意提醒,甚至用很多手段限制用户不要随便加入不认识的人为熟人
2、每个会员的好友数量都不是特别的多,大致平均在30个左右,这和那些陌生交友SNS网站上来一加几百上前的陌生好友截然不同
3、开心网的很多应用有意无意的引导用户删除掉那些不认识的好友,比方说你对好友的第一印象这个应用,你如果不认识这个好友你
根本无从评价。开心上面很多应用只有熟人之间才能互动起来,陌生人没有办法玩。
4、由于熟人数量有限,而开心的应用都比较轻巧,比较傻瓜化的,所以交互起来不会对用户产生太大的负担和压迫感。不像社区型
SNS,逼迫你看贴回贴,要知道看长贴回长贴都是很累人的事情。因此不会对用户产生过分的沉迷感,算是比较健康的。

总之,这类SNS总结起来就是两点:熟人、休闲社交工具。

但是开心网的问题我在前面也说过了,休闲社交工具总有玩腻的一天,你不得不马不停蹄的一直开发新应用,推出新应用,来推动用
户不停的社交,这不是一个终究解决方案,要么你做平台,把开发应用的工作交给第三方,走facebook的路,要么,你就要想清楚,
怎样提供那些最基本的,但是熟人社交却必需的工具,这样才能长久的留住用户。

我们把思路放在更大的范围来看,有哪些工具型应用是互联网用户之间交流所必需的呢?

1、Email,这个是熟人社交用到的最基本的交流工具了,而且也是必需的,经久不衰;
2、IM,这个也是熟人社交用到的,几乎是必需的交流工具了;
3、通讯录,这个更加是商务人士必备的工具;
4、相册,这个也是比较常见的,但不是必需的;
5、休闲游戏

我暂时想到的只有这些了。然后我们看看熟人社交工具能够提供些什么?

1、Email,这个显然SNS无法提供;
2、IM,虽然用户更习惯用MSN,但是Web IM也有他的长处,看来是一个可以提供的基础工具;
3、通讯录,实际上很多通讯录是和Email整合在一起的,但是似乎SNS也可以提供通讯录功能,和SNS里面对用户的管理整合起来,
可能是个不错的想法;

第 222 / 283 页
http://robbin.javaeye.com 4.16 SNS的工具化思考 - SNS之我见(六)

4、相册,这个好像已经是SNS的标准配置了;
5、休闲游戏,好像也是标配了

其实除了这些之外,还有很多对社交有用的工具,例如投票,送礼物,音乐推荐等等。但是这些似乎又不足以成为基础型的熟人社交
工具,那么对于熟人社交来说,什么类型的工具才是用户必需的呢?

第 223 / 283 页
http://robbin.javaeye.com 4.17 SNS的路径选择问题思考

4.17 SNS的路径选择问题思考

发表时间: 2008-07-31

SNS和UGC的关系

UGC和交互一定是相互依存的,UGC必然推动交互,而交互一定产生UGC,这两者不可能割裂。但一个SNS网站究竟侧重点和围绕的核
心究竟是高质量的内容,还是围绕用户交互的行为?

用户之间如果根本就是陌生人,他们怎么会交互的起来呢?必须依靠高质量的内容!越是陌生人交往越需要高质量内容。而实际上熟
人交往并不那么依赖高质量的内容,比方说我和我邻居之间,我所关心的无非就是你今天小孩啥啥了,明天你去哪里玩啥啥了这些琐
碎的事情而已,你非要和我讨论严肃的互联网商业模式问题,我压根不感兴趣。

因此人际关系的亲疏程度,和他们之间交流内容的质量水平是成反比的。对于熟人交流,你不需要多么高质量的内容,设计一些轻巧
的社交工具就很好了,但是对于陌生人交流,你没有一个产生高质量内容的机制,根本交流不起来。

社区其实也有SNS

社区网站天然有SNS的需求,而且社区网站的SNS需求实际上是分为两类的:

1) 新手崇拜牛人,想了解牛人动态。我和你不熟,你是牛人,我关注你的高质量UGC,但对你的生活琐事完全没兴趣。这是单向的订
阅关系。

2)我们两个人已经很熟了,甚至在生活当中认识,你的生活琐事我会很感兴趣,比方说你啥时候结婚呀,老婆漂亮不?JavaEye很多
私下的聚会就是吃吃喝喝,绝口不谈技术,只谈风月。这是双向的熟人关系。

当然有时候这两类关系之间的界限往往很模糊,并不那么泾渭分明。

从熟人SNS关系切入

Facebook和开心的切入点就是熟人社交,通过MSN拉来一堆熟人开练。熟人社交并不强调UGC,也不靠UGC来拉人,以用户交互动作
为核心,靠的就是轻巧的交流工具:poke,web game,vote,IM等等。熟人社交SNS的发展瓶颈是轻巧的社交工具不产生持久的黏
性,也难以刺激高质量UGC的产出,因此持久性不强。解决路径可能是:

1、开放平台刺激app的极大繁荣,以数量换取持久的黏性。

2、给用户提供互联网基础工具,例如日历、相册、邮箱、IM、RSS Reader等等,类似于Google现在的做法。实际上我在Facebook的
一些朋友就是拿Facebook来安排日历、组织活动、接收新闻等等。

熟人SNS网站也可以逐渐扩展到陌生人社交模式去,Facebook已经是这样了,开心网正在进化过程中。如果做纯SNS网站,我认为从
熟人关系切入是唯一正确的选择。只有这种模式才不会在一开始就设定一个天花板,网站发展的潜力才会更大。

第 224 / 283 页
http://robbin.javaeye.com 4.17 SNS的路径选择问题思考

从陌生人SNS关系切入

现在很多SNS网站都是陌生人社交,实际上社区网站也可以归入此类,比方说豆瓣,当然JavaEye也算。陌生人社交要依靠高质量的
UGC建立人际关系。但是任何牛人都不是所有领域的牛人,他只在自己擅长的几个领域有生产高质量UGC的本领。所以社区网站也
好,陌生人SNS也好,天然就是垂直的。

垂直网站在成立之初就设定了天花板,要突破天花板单纯依靠网站的功能引导几乎不可能,只能依靠网站的运营团队去做传统的运
营。比方说天涯从人文和体育起步,现在扩展到了方方面面,依靠的就是运营团队去做内容。定位在垂直领域的社区不应该搞成SNS
网站,否则无法提供一个高质量UGC环境。

SNS的熟人关系也有不同

熟人关系,仔细区分的话,也有两类:

1、你生活当中就认识的人:你的同事,你的发小,你的亲戚,你的客户,熟人关系的建立与维系完全不需要通过互联网,SNS熟人社
交网站很适合这类用户。你并不是通过互联网建立这种熟人关系的。对于这种熟人关系,开心网有致命的吸引力。为什么呢?因为你
可以通过网络的交互发掘出来身边的熟人竟然还有你不熟悉的另外一面,这简直太好玩了。开心网就是靠拉这种熟人起家的。但开心
的问题在于,我不玩开心,仍然可以维系熟人关系,开心对我可有可无。所以开心必须拿出来其他的本领来黏住用户。

2、你通过网络社区,因为共同的兴趣爱好认识的熟人:你需要通过互联网建立和维系熟人关系,社区网站应该提供这种熟人关系的交
流工具。这种熟人关系是通过互联网高质量UGC逐渐建立起来的。但是见过面喝过酒,成为熟人以后。高质量UGC对你们的维系作用
已经极大的降低了,你们现在需要适合熟人社交的工具了。

结论

1、社区和SNS是密不可分的,社区一定会产生SNS。
2、社区的核心必须是UGC,但可以提供SNS功能提高社区的黏性
3、纯SNS只有熟人社交这一条路可走
4、垂直SNS是扯淡,只不过是批了SNS皮的社区

第 225 / 283 页
http://robbin.javaeye.com 4.18 社区的多种形态

4.18 社区的多种形态

发表时间: 2008-08-04

回复:精英还是草根?这是一个问题!

以社区作为基础运营的垂直网站,这个“社区”的概念一般泛指由用户贡献主要内容为驱动,毫无疑问,BBS是一种典型的社区形态。也
有很多网站用单一BBS 形态就已经做到了足够大,比方说篱笆网。但是我在2006年已经选择了放弃单一BBS形态。我觉得你的观点对
我最大的冲击就是,单纯BBS作为社区基础也可以做大,关于这一点,我没有这么强烈的信心。

目前JavaEye实际上存在四个社区形态:BBS,问答,Blog+Digg,圈子频道

1、 BBS -以帖子最后回复时间倒排序的方式组织内容。我觉得这种内容组织方式是有缺陷的,间接鼓励和放大了灌水者的声音,整
个生物多样性群落难以在BBS中共存。最后往往导致低端用户驱逐中高端用户。JavaEye的做法是在BBS当中驱逐低端用户,保护中端
用户和高端用户。

2、问答 - 以提问的悬赏分和提问时间倒排序的方式组织内容,特别适合低端用户的需求。这也是一种社区的形态,可以形成社区文
化的。JavaEye目前的做法就是鼓励低端用户提问,然后定期搞活动,鼓励中高端用户去回答问题。目前解答问题成功的比例是33%左
右,算上很多人提一个问题就走,可能很长时间不回来看,这个比例已经非常高了。

3、Blog + Digg - 以Digg方式组织博客文章,这是我自己想出来的博客社区组织方式(不知道是不是首创)。目前从JavaEye的博客频


道看来,已经形成了一种不同于BBS的社区氛围,不论高、中、低端用户都相处和谐的社区。而且在流量的贡献上面来看也非常高,
可以算是我的成功之作。

4、圈子 - 圈子频道相比上面三个社区不算成功,以上三种社区形态都是聚中心化的,作为一个规模比较小的垂直网站来说,圈子的
去中心化难以聚集足够的人气形成良好的互动。

作为我来说,解决生物多样性共存问题,我的想法就是给不同的人提供适合他们需求的不同服务形式。

>> 你对金字塔顶端的人的要求是什么?

就像你上面说的,我希望高端用户关注JavaEye网站,偶尔贡献一点点内容。然后问题就是,怎么留住高端用户?我的想法是两点:

1、网站提供他想看到的高质量内容,比方说新闻算是一个吧,高质量博客也算是一个,今后我们还会编辑更多精华的内容。

2、熟人之间情感的联系,让熟人之间的交流更通畅些,让这些高端用户因为熟人情感的纽带,更无法割舍这个网站

第 226 / 283 页
http://robbin.javaeye.com 4.19 对FriendFeed的一点思考

4.19 对FriendFeed的一点思考

发表时间: 2008-10-21

本来想写一篇博客展开探讨一下,但是今天时间很晚了,不想太晚睡觉,简单写写,以后有空再修改这篇文章。

一、SNS的魅力在什么地方?

1、FriendFeed,或者通俗点说:好友动态的信息推送。

比方说Facebook登录以后的默认个人首页就是好友动态页面。每个人都有关注别人动态和阅读别人信息的需求,特别是对于本行业名
人,以及和生活密切相关的人的信息关注度非常高。这便是我一直强调的用户订阅关系。

2、解决用户的孤独感。

一个用户在网站没有融入社区、没有融入一个小圈子,那么这个网站对他的黏性是非常小的,当用户的动态快速激发大面积反馈的时
候,会高度激励用户。当然解决用户孤独感也要靠FriendFeed机制有效建立起来才行,但是网站有一些其他的辅助手段可以采用。

3、熟人社交的需求。简单的来说,假设哪个网站上面有我大批的高中同班同学每天出没的话,那我一定是这个网站的铁杆用户。

二、网站怎么有效发挥这些SNS的魅力?

1、很多人都认为:就像现在社区网站标配博客一样,以后社区网站也会标配SNS。这种观点其实偏了,社区网站其实真正需要标配的
是FriendFeed(关注者动态的信息推送),而不是全套SNS。

2、社区怎么解决用户的孤独感?办法有很多,社区网站的方方面面的细节都可以去解决这个问题,当然提供了FriendFeed一定会强化
这个效果。

3、如何构建熟人社交环境? 开心001是一个很好的榜样了。

三、引申下去,该向哪个方向下功夫?

1、看看现在的这几个网站:

1) Facebook是三者兼而有之的一个SNS网站,所以他很成功
2) FriendFeed.com,我非常欣赏的一个网站,把Feed功能扩展到整个互联网,把一个用户的所有动态进行整合,然后推送给你,他
满足了功能1
3) 51.com,没太研究过,他满足了2
4) xiaonei.com,没太研究过,满足了1+2,也有一部分3
5) kaixin001,满足了2+3

2、FriendFeed方向如何?

第 227 / 283 页
http://robbin.javaeye.com 4.19 对FriendFeed的一点思考

本质上来说,SNS网站很大一部分价值在于FriendFeed,但是仅仅提供站内feed,无疑是远远不够的,哪个SNS能够率先整合整个互联
网该用户的feed,就相当于这个网站的注册用户在无形当中被放大了不知道多少倍,多订阅一个用户,哪怕他并不注册该网站,也相
当于该用户已经注册了你的网站,甚至是一个比注册用户还要活跃的核心用户。

基于这样的原因,我觉得FriendFeed很有战略价值,事实上在国外FriendFeed.com也很火爆。但是我比较看淡国内FriendFeed的前景,
原因在于:“除了写博客、泡论坛发贴、网络聊天之外,一个中国互联网用户基本没有其他动态可以feed了!”

网络聊天涉及隐私,不会feed给你,那你能够抓取到的用户feed无非就是博客和帖子,因此只需要通过RSS就可以了。也就是说你一个
网站,在构建本站用户FriendFeed之外,RSS Reader做的越强越好用,意味者给你贡献内容的活跃用户越多。这里引申出来一个问
题,独立的RSS Reader网站如抓虾、鲜果在干吗呢?他们的网站架构天然是最适合做大SNS网站的。这个问题我也不知道,也许他们
没有意识到FriendFeed的价值,也许他们有不为人知的其他计划。

JavaEye以后一定会做RSS Reader,但是RSS Reader仅仅是底层驱动器,不会直接暴露RSS概念给初级用户。用户仅仅是通过站内


FriendFeed网络,去扩张到站外FriendFeed网络,从而网站通过FriendFeed站内外网络,把站外的用户通过RSS机制整合进来,这里的
关键在于SNS关系网络驱动的RSS Feed,从而利用站内外的Feed,把互联网资源和用户整合到网站内部,这样的网站才可以立于不败
之地。

3、熟人社交呢?

FriendFeed有价值,但是价值没有熟人社交更高。如何构建一个适合熟人社交的环境、提供轻便的社交工具、还有待于探索,开心001
仅仅只是开了一个头,并且他自身也有很多有待解决的问题。

四、总结陈词

1、FriendFeed很好很强大

2、但是国内互联网应用比较滞后、FriendFeed退化到RSS Feed即可

3、RSS Feed+SNS 才是网站整合资源和用户的法宝,社区网站单纯整合SNS没有太大价值

4、总体来说,FriendFeed的价值在国内仅仅只能发挥到第3条这样的作用了,无法更进一步。

5、SNS有很大的前途,还是要看熟人社交+休闲游戏这条路

第 228 / 283 页
http://robbin.javaeye.com 4.20 对Friendfriend一点思考之二

4.20 对Friendfriend一点思考之二

发表时间: 2008-10-21

这是接上一篇文章对Friendfriend一点思考的继续思考。在中国互联网的特定环境下,做什么有前途?在国内的SNS类型网站里面,大
致有以下3类不同侧重点的网站:

1、侧重Friend Feed类型,比方说所有的抄袭Facebook架构的网站,以校内为首

2、侧重个人空间类型,比方说腾迅的Qzone,51.com

3、侧重熟人社交休闲游戏类型,比方说开心001

简单分析一下:

1、侧重Friend Feed类型的网站扩张前景比较小。即便按照我前面文章所述把Friend Feed做到很理想的程度,效果相对来说有限。因


为:

1) 国外web2.0类型网站已经都成了流量最大的网站了,用户已经非常习惯在web2.0网站上面活动,产生动态,这为friend feed提供了
基础。比如youtube、facebook、myspace、flickr、twitter等等。但国内web2.0网站其实并没有真正起来,即便流量有起色的web2.0网
站也非常封闭。因此没有多少friend feed可以抓取。

2) 中国互联网用户在web2.0方面培养出来的普遍使用习惯仅仅限于:发帖子、写博客和网络聊天。但是只有网络聊天才是真正的全民
普及。发帖子和写博客的网络用户仅仅占聊天用户不到1/10的比例。因此腾迅掐住了中国web2.0最大的咽喉。

3) 通过JavaEye网站的统计可以看出来,每天登录的注册用户大约1.5万,但是每天匿名浏览者超过15万以上,大约将近20万。登录用
户每天产生feed的用户最多5000人。也就是说创造内容的用户和浏览用户比例在1:40左右。如果不能够有效发动那39倍的人群,让他
们产生信息,留下足迹,显然扩张的余地很有限。

2、侧重个人空间类型的Qzone很成功,51.com也不错。基本上是利用SNS关系给个人空间带流量,解决用户孤独感的问题。面向低年
龄用户收取虚拟网络服务费用。但这种类型网站的扩张仍然受限于1:40的问题,当然腾迅稍微特殊一点,Qzone某种程度上可以看成
是QQ的延伸和补充。51.com也走向了融合网游的路,其他网站不见得可以模仿这条路。

3、熟人社交的休闲型社区,相对来说,扩张的可能性更高。原因在于1:40的那另外39个人,也许不会发贴,不会写博客,但是不会
拒绝熟人邀请下去点点鼠标。问题在于以下几个方面:

1) 网站的用户导入期怎么操作?
2) 导入进来的用户,以提供什么样的服务进行商业价值转换?
3) 适合于这种特征的应用是什么?

解决好这3个问题,那么网站我相信就会做的不错。另外有一个伪问题是:“这种网站本质上是web game,用户玩一下就腻了,不来
了,网站没前途。”

第 229 / 283 页
http://robbin.javaeye.com 4.20 对Friendfriend一点思考之二

其实,网站不一定非要多高的用户黏性不可,网站流失用户也不是灭顶之灾。你已经把40倍的用户都拉来了,即使跑掉30个,那剩下
的10个还是比原来的1个多10倍。最重要的在于网站要拥有把用户点击快速变现的能力,那么你根本不恐惧流失用户,用户已经给你
带来现金了,你还要怎样,非绑死他不可?

总结陈词:

1、friendfeed好是好,做好了friendfeed,会成为一个很有价值的网站,但不意味着你的网站能成为暴发户。

2、不论用户学历高低,收入高低,互联网95%以上的用户都是鼠标型用户,不是键盘型用户。你要明白你花了95%的精力提供的功能
仅仅是为5%的用户服务的。

3、键盘型用户才是你网站的忠实会员,有黏性的会员,能够feed出来信息的用户;而鼠标型用户离你的网站若即若离,你不要企图把
所有的鼠标型用户统统转化为键盘型用户

4、为键盘型用户提供核心功能,他们决定了你网站的性质;为鼠标型用户提供转化为键盘型用户的机制

5、对于不太可能转换为键盘型用户的鼠标型用户,应该专门为他们开发网站功能,确保他们能够快进快出,不必有太大的心理压力,
在保持和网站继续若即若离关系的同时,争取把他们的鼠标点击转化为商业价值。

第 230 / 283 页
http://robbin.javaeye.com 4.21 开心001的Google trends数据一窥

4.21 开心001的Google trends数据一窥

发表时间: 2008-10-23 关键字: google trends

今天看了一下开心001网站的Google Trends数据: http://trends.google.com/websites?q=kaixin001.com,其中“Also visited”这一项表


明用户还访问了其他哪些网站。或者我们也许可以通过这一项数据窥视一下哪些用户更喜欢使用开心网。以下是截图:

在“Also visited”列出的10个网站当中可以划分为几类:

1、李鬼类网站

比方说kaixin.com,kxlive.cn,顶着开心的名字,以假乱真,以博取开心001的流量,而且看起来这种策略还非常成功。

2、白领生活类网站

比方篱笆网、大众点评网、丁丁地图、北京公交网,这也似乎说明了开心001的用户以北京、上海等大城市白领为主的用户构成,像
篱笆、大众点评、丁丁都是上海的网站。

3、IT专业类网站

比方海内、5G、cnbeta和JavaEye。也许王兴不希望海内定位在IT行业人士的用户构成上,但是目前看来海内还没有摆脱这个定位;5G
是互联网研究方面的SNS,cnbeta则是互联网草根媒体资讯网站。看来IT专业人士都还是挺认真的卧底开心001的。

最后我非常惊讶的发现JavaEye网站也赫然在列,JavaEye是一个专业软件开发者社区,怎么会出现在这里? 难道JavaEye的用户很喜欢
开心001这种模式?

第 231 / 283 页
http://robbin.javaeye.com 4.21 开心001的Google trends数据一窥

BTW: 以同样的方式看看xiaonei.com和51.com也挺有分析价值的,可以很清楚的看出来网站的用户构成。校内的用户还是集中在学生
群体,而51的用户主要和QQ重叠。
附件下载:
• kaixin001.jpg (17.7 KB)
• http://robbin.javaeye.com/topics/download/24b17d3f-d954-38bf-853e-0033d9d36c19

第 232 / 283 页
http://robbin.javaeye.com 5.1 程序员到30岁就要转行?

5.1 程序员到30岁就要转行?

发表时间: 2006-09-14

已经迈过了30岁人生大关了,这个时候很适合谈谈这个话题。目前我自己还奋战在程序代码的第一线,我熟识的同年龄段的一些程序
员朋友也无不如此,其中很多人已经在公司担任非常重要的职位了,有些已经到了公司的最高管理层,这些人中基本上至少都在中层
管理的位置上。

随着年龄的增长和阅历的增加,一个具有良好工作习惯的程序员,在多年的团队开发过程中,不可避免的培养了自己管理团队的能力
和沟通表达的能力,如果到30岁都做不到这一点,那只能说你这么多年来就根本没有好好做过项目。当然很重要的一点是,做管理层
不意味着你要脱离开发实践,特别是对于软件行业来说更是如此。一个技术问题卡壳了,你管理水平再高也无济于事阿!这个时候就
看你能不能奋战在第一线,成为大家的主心骨了。《功夫》里面有句台词说得很好,“能力越大,责任越大”,我觉得一个程序员也应该
具备这种意识,除了不断提高自己的技术水平,同时也应该主动承担更多的责任,你的责任心越大,就能够做更重要的事情,让周围
的人越对你产生心理依赖感,时间久了,你自然而然就成了开发团队的Leader,几年下来,成为公司技术方面的顶梁柱或者成为公司
高管,并不是什么难事。至少从我身边这么多朋友看过来,就是这样。所以,我很反感什么30岁就不能做程序员,30岁就要转行的悲
观论调,有这样想法的人根本就不适合做程序员,转行还是趁早的好。

一个有美好前途的程序员,应该具备如下的素质:

1、对技术始终保持浓厚的兴趣,不抱残守缺,要“喜新厌旧”!

这一点直接决定了一个程序员能不能成为高手,有没有前途。我认识的坚持做技术的朋友中间,处在最高位置的那些人都是那种兴趣
及其广泛,知识面及其广博的,而且对新的技术保持足够的敏感度,并且绝不吝惜自己赖以成名的技术,该抛弃的时候绝不会犹豫和
可惜。简单来说就是既要“喜新”,又要“厌旧”。

我自己不是科班出身的,只因为98年毕业的时候互联网最热,就投身进来做技术了。如果那个年代互联网不热门,我也很有可能就做
证券行业了。我觉得自己只所以能够比很多技术人员水平更高,原因也就不外上面这几点:对技术保持浓厚的兴趣;孜孜不倦的学习
新技术;喜新,而又毫不吝惜的厌旧。

很多开发人员很害怕自己辛辛苦苦学习掌握的技术过时,很像守财奴,其实软件行业唯一不变的就是变化,你守是守不住的,必须积
极主动的进攻,主动掌握新技术,而不是被动的等待新技术把你给淘汰掉。而且长期坚持不懈的学习会提高你的学习能力,开阔你的
视野,培养一个良好的学习习惯,而同时这些方面又会反过来使你学习新技术的速度越来越快。

我自己现在就有这种感觉,当你对某些知识领域一无所知的时候,如果你总是躲避,不去接触,那么你永远站在门外,而如果你坚持
不懈的学习下去,你会发现你懂得越多就学得越快,到后来,你甚至可以培养出很敏锐的技术直觉,一种新技术好与不好,有没有前
途,你只要花很少的时间就可以自己判断的出来。所以虽然框架满天飞,我觉得我自己从来没有出现过无所适从的感觉,如果不知道
这个框架好,还是那个框架好,那就花点时间都去学习一下,很快就知道哪个好哪个不好,判断的标准自己心里早就有数。

到了30岁,在技术方面我对自己很欣慰的一点是我发现自己的学习能力完全没有下降,甚至越来越强,有些新的东西花很少的时间学
习,就可以取得比很多人花很久时间都要好的效果,甚至能够立刻结合以前的经验,看出来这种新东西存在的缺陷和未来的发展方
向。

2、要有强烈的责任感
这一点上面已经提到了,一个有责任感的程序员,他到了30岁一定会成为一个好的技术管理者,就算他曾经有管理和交流能力方面的

第 233 / 283 页
http://robbin.javaeye.com 5.1 程序员到30岁就要转行?

缺陷,他以后也会做的很好。

那些说什么30岁就得转行的人在我看来就是软件行业的逃兵,他根本就进错了这一行。

第 234 / 283 页
http://robbin.javaeye.com 5.2 很多开发人员的毛病

5.2 很多开发人员的毛病

发表时间: 2006-09-25

很多开发人员老是说管理层轻视技术人员,可你们有没有想过管理层为什么要轻视技术呢?很多软件公司老板能自己身家千万以上,
个个都精明过人,如果技术人员真的像你们说的那么有价值,老板会想不到吗,会冒着放弃长期利益的风险,仅仅就不肯尊重开发人
员,给予开发人员高的待遇,这些人要是目光这么短浅,怎么可能赚到那么多钱呢?是的,确实很多软件公司老板目光短浅,为人苛
刻,待人刻薄,但是开发人员自己就完全没有问题了?

开发人员老是说自己待遇低,压力大,30岁就必须转行了,从来都是埋怨环境,从来不去反思一下自己有什么问题!

一些大公司招聘核心技术人员,上来就要求八年十年工作经验,那就意味着他们招的就是30岁以上的资深开发人员,30岁以上的程序
员真的没有好机会吗?恐怕是你们自己就放弃了。

待遇低,你们见过待遇低的工作吗? 软件开发行业几乎是平均工资最高的行业了,一个程序员工作两年以上,轻松拿到6k以上的月
薪,水平更好的,四年以上就可以拿到10k,你们去看看那些传统行业,一个经理级别的人才能拿到6k,能拿到10k以上的凤毛麟角。

压力大,你们见过压力大的工作?当你们吹着空调喝着咖啡,一边和mm网络聊天,一边敲敲代码的时候,那些销售人员顶着烈日酷暑
白天黑夜的跑客户,还要交际应酬,为了抢到一个单子,绞尽脑汁,为了赔客户喝酒,身体都搞坏了。一个月不出单子,就愁得晚上
睡不着觉;两个月不出单子,不用公司赶你,你自己就得灰溜溜辞职。你开发人员项目延期两个月,小公司资金周转都困难,老板会
因为项目延期开除你吗?

不客气的说,有相当那么一批开发人员,从小就是聪明的孩子,成绩好的学生,家长溺爱,老师护着,自以为自己多了不起。进入社
会以后,觉得自己是精英,这看不惯,那瞧不上,眼高手低。让他做点事情做不来,稍微得罪一下,就把你当仇人。这些个人从小就
没有吃过什么苦,不知道社会是什么样子,自大,幼稚,狭隘。取得一点点成绩就觉得老子天下第一,遇到点挫折,就埋天怨地,从
来不觉得自己错了。

有这么多埋怨,不如改行做销售,让你们去跑三个月销售,一个个嘴巴都闭上了。

第 235 / 283 页
http://robbin.javaeye.com 5.3 继续软件行业部分开发人员毛病的话题

5.3 继续软件行业部分开发人员毛病的话题

发表时间: 2006-09-30

我是做软件咨询的,这些年接触的各种各样软件公司老板,软件公司高层中层,软件公司底层开发人员,软件客户方,我自己都记不
清楚究竟有多少了,不至于被几个老板请顿饭就飘飘然,就是被别人请吃饭我自己都记不清楚有多少回了。

中国整个大的经济环境下劳动者的普遍待遇就不算好,不光IT行业如此。其实相对而言,在IT行业劳动者是普通受到重视的,一个核心
开发人员就有能力威胁老板,这不是地位重要是什么?

前年我和朋友自己研发备份软件去各个行业推销,去那些上海大的单位,企业,跨国公司推销,感触很深。那些机械行业,化工行
业,汽车行业,医药行业,最最重要的公司资产是那些厂房,设备,那动辄都是几亿几十亿的投资,相比之下,劳动者的价值算什
么?连根毛都不算!这些行业的高级技术人员工资还不如一个毕业一两年的软件开发人员。公司随时都可以弃你如敝徙。

IT行业特别是软件行业则不然,公司没有什么固定资产投资,公司唯一有价值的资产就是人,是开发人员。所以软件行业的从业劳动
者的地位相比其他很多行业是很高的。特别是高水平的核心开发人员,几乎是每个软件公司都很稀缺,可遇不可求的,这些人几乎有
和老板叫板的资本。这在传统行业是不可想像的。

大学毕业之后那几年我也曾经愤青过,这也瞧不起,那也看不上,总觉得时不我予,天妒英才。但是有过创业的经历,有过各行各业
销售跑单的经历,有过几年软件咨询的经历之后,在接触了社会各个阶层之后,在了解了社会各行各业之后,我越来越反感我自己以
前那种少不更事的愤青。

每个人都有过自己的青涩期,这没有什么,最可怕的就是一叶障目,在没有什么社会经验,完全不了解其他行业的情况下,轻率的把
自己扮成苦大仇深的样子,自大的愤青着,这样的开发人员非常普遍,我接触过太多了,所以非常有感触,他们的缺点集中体现在:
自大,幼稚,狭隘上。

软件行业从资本方来说,问题也同样多,传统行业投资数额巨大,不是每个人都玩的起的。但是软件行业拿几个单子,拉几个人就可
以干了,门槛低了,也鱼龙混杂了。软件行业能够经营十数年的公司,更加少见。整个行业积累不够导致各种各样问题的爆发。不过
这不是我这篇博客想探讨的话题,我这里不想展开。

第 236 / 283 页
http://robbin.javaeye.com 5.4 2006超女是令人乏味的

5.4 2006超女是令人乏味的

发表时间: 2006-09-30

昨天晚上超级女生决赛,我打开电视一边随便听听,一边在房间里面打扫卫生。

05年超级女生我算看的比较多了,大概总共看了三四期的样子,后来还看了好几次精彩集锦什么的,对于前五名可谓非常了解了。06
年超级女生总共看了两期,对这些人完全没有深刻印象。最后冠军亚军投票数量统计,一个510万,一个480万,超过去年很多,去年
冠军亚军都是300多万票,但是无疑06年超级女生严重走了下坡路。

其中根本原因在于05超女每个人的个性都特别鲜明,而且截然不同,06超女,你找不出来什么个性,特别独特之处。

05李宇春一个中性人,被戏称春哥,不管怎么说,其形象之独特,似乎中国以前还从未有过;
05周笔畅的R&B,不论蹩脚不蹩脚,国内还没有人能像她这样把任何歌曲到她嘴里都给R&B的;
05张靓影,一开口唱歌,水准就直逼中文歌坛大姐大,实力之强悍,令人叹服;
05何洁,一个媚你到媚到呕吐的,充满动感的女孩,你可以不喜欢她,但是你无法忽视她;
05纪敏佳,糟糕的外形加上出众的实力唱将,坎坷的超女之路,当她唱《The Power of Love》的时候,我诧异国内还能有人唱到这种
水平的。

06年的超女,唯一给我留下独特印象的是沈阳超女第二名的张楚格,顶着硕士高学历的超女,音乐学院的专业出身,鹤立鸡群的身
高,落落寡欢孤寂的神情却搭配一张令人亲近的娃娃脸,形象反差的很厉害,我只看过她唱了一首歌,但给我印象非常深刻。

06超女不但候选人失色,连评委都没有05那么个性鲜明的,唯独出了一个美女评委朱桦,吸引了不少眼球。

至于06超女前五名,没有一个有自己独特鲜明的,令人难忘的个性和形象的,这届超女甚至没有能够超过04超女张含韵的,06超女是
失败的,一个闹哄哄的舞台就快要谢幕了。

第 237 / 283 页
http://robbin.javaeye.com 5.5 技术重要还是业务重要(一)

5.5 技术重要还是业务重要(一)

发表时间: 2006-10-06

技术重要还是业务重要,这是萦绕在软件开发者头上一个很难做出选择的问题。见过很多很多人说,技术不重要,技术很快就被淘汰
了,业务才重要,业务精通了,你才有前途。这是一个很难回答的问题,我想分几次谈谈这个话题:

一个标准的答案就是:技术重要,业务也重要,哪个方面最缺,哪个方面就更重要。那么对于比较普遍的中国的行业软件公司来说,
究竟是技术方面缺,还是业务方面缺,如果是两方面都缺,哪方面更缺呢?

我举两个例子发生在我身上的例子:

1、曾经替某行业公司找人才,项目经理,高级开发人员都需要。我问,是否需要行业背景经验,对方老板答曰:不需要,我们培训一
个月业务就够了,关键是技术水平要过硬。

2、做一个金融方面的项目,我问:我对该业务完全不了解,对方老板答曰:没有关系,我们派一个人帮你就好了,业务这些东西很快
就可以掌握,我们现在的问题就是项目拿下来做不好,没有好的软件开发团队。

规模稍微大一些的软件公司,有些项目经理可能职能上完全就是业务人员,开发是由Team Lead负责的。那么软件开发人员应该走哪
条路?技术重要还是业务重要呢?

第 238 / 283 页
http://robbin.javaeye.com 5.6 驳:程序员和建筑工人

5.6 驳:程序员和建筑工人

发表时间: 2006-10-16 关键字: 软件工程

number017 写道

不知哪时在哪里看到一个软件工程和建筑工程的对比...

前日吃饭的时候无聊,便提到这个:"你看,对面那栋漂亮的楼房。把他们建起来的是一群建筑工人,有些甚至被我们称为民工(这里,无
歧视);而我们做软件的,大多受过高等教育,甚至很多被成为精英,为什么还把软件搞得这么糟糕。自从1968年软件危机第一次被提出
以来,还长期存在。这是为什么呢?"

旁边的JJ说话了:"因为建筑师叫那些民工怎么做,他们就怎么做。而大多数软件开发人员都很有个性、很有想法,所以困难重重。"

偶抬杠:"这么说,去招一批民工来做软件,就可以解决这个问题?"

JJ无语,但还是很坚持。

旁边的猥琐男见状,正是提出自己高论的好时机:"这说明了建筑工程发展得很好了,而软件工程还没到达那个境界。这是一个长期、持
续、抗争的过程,不过有一天会好起来的。"

嗯...科学的乐观主义者,他还在想着银弹。

偶想想,一位大师上课的时候说过:"软件本身是技术,但带着与生俱来的艺术性。"很多东西具有两面性,可以拿摄影来对比:一般人认为
摄影是艺术,但它带有与生俱来的技术性。这大概不算矛盾,但却是统一体。

大师的回答着实很能回到这个问题:艺术能有完美的吗?所以软件也不能。你可以把软件的一面--技术做得很好,用很合理的技术,高超
的算法;但是你永远不能把软件的另外一面--艺术做到极致。难道这就是传说中的哲学?

Oh,My God!!!我怎么会提起哲学?

这种类比没有什么意思。

你怎么知道一个外表看起来很漂亮的building,里面就不是充满各种各样问题的呢?现在豆腐渣工程,盖的很糟糕的小区比比皆是。买
房子一不小心买到质量残次的楼盘,然后打官司的,你随便找到房产论坛去看看吧,多到令你吃惊的地步。

开发软件也是一样的,你让美工做个漂亮的首页,然后给客户demo一下,唬的客户眼花缭乱的,那还不是小意思的事情吗?他怎么可
能知道你里面的代码全部都是垃圾?

楼房,你不搬到里面住个几年,就光在外面看着光鲜,贸贸然下定论,说这个building有多好多好,就和你给客户demo一下,那都是
一个意思。所不同的地方在于,楼房要盖好了才能demo,但是软件只要美工做几个页面就可以demo了,所以楼房不会离谱的太狠而
已。

第 239 / 283 页
http://robbin.javaeye.com 5.7 编程语言进步是解决项目开发问题的最有力工具

5.7 编程语言进步是解决项目开发问题的最有力工具

发表时间: 2006-10-23

Godlikeme 写道

我从没有对Ruby有过负面评价,我的出发点是不要把开发语言的优点、缺点看得如此的重,他们本身是同质的,真正能够给开发效
率带来的提高并不大。我在这里强调了算法,是想强调软件开发的难点是现实问题的复杂性,这些才是软件开发中最大的障碍,任
何开发语言遇到这个问题都无能为力。我不想比较什么优缺点,ruby我了解一点点,耳濡目染,但至少对我现在所了解的情况来说,
还没有什么让我觉得ruby较其他语言有本质上的进步,大同小异罢了。我相信语言还会不断进步...,但它还仅仅是语言,是表达形
式,内容才是最重要的。

ruby和其他web开发语言最大的本质不同就是开发速度了,比J2EE快5-10倍,这难道不算本质上的进步吗?

现在的商业社会,就是拼速度的时代,你的速度比别人快,你就赢了,就是这么个游戏规则。

说到web开发涉及到的企业应用业务逻辑,绝大部分没有什么算法上的难度,业务逻辑的抽象也不至于难到令程序员根本无法抽象的地
步,绝大部分你只要对相关业务进行一段时间的培训,都不成问题,你能做别人也能做,但是同样的人力,人家做10个月,你1个月
就搞定了,所以你成本低,你又赢定了。

现在的应用软件开发中最大的障碍根本就不是什么现实问题复杂性,应用软件开发的最大障碍就是开发速度和开发成本问题,还有需
求变更响应能力上。

客户希望3个月上线,结果你拖拖拉拉搞了一年才上线测试;老板希望投入10个月,结果实际投入30个人月项目还遥遥无期;客户需
求朝令夕改,几次反复的折腾就把软件改的面目全非,什么架构,什么模式,什么bad smell统统被迫抛到爪哇国,只求早点结束这噩
梦。这些现实项目遇到的最大难题,难道不是通过语言的进步来解决的吗?你对现实问题的复杂性搞的再清楚,你能架得住客户的折
腾?你能搞的定项目开发的延期?

采用了先进的开发语言,投入高水平的开发人员,我现在2个人月项目上线,客户需求只要不太离谱,他上午提出,我下午就改好,这
样去做项目才有竞争力。

第 240 / 283 页
http://robbin.javaeye.com 5.8 技术重要还是业务重要(二)

5.8 技术重要还是业务重要(二)

发表时间: 2006-10-24

Godlikeme 写道

我没有体验过,不知道ruby的速度,但我比较悲观,就假设是5倍好了。
把项目的开发和测试时间定为整个项目的40%好了,那么一个j2ee项目应该在100%,而ruby是68%,也就是ruby比java项目的整个周
期快了1/3,我不认为开发速度加快会带来真个项目的进度加快那么多,如果是10倍这样,Ruby is a silver bullet。不管怎样,开发
效率的提高是一件好事。

现在的应用软件开发中最大的障碍根本就不是什么现实问题复杂性,应用软件开发的最大障碍就是开发速度和开发成本问题,还有
需求变更响应能力上。

对于这句话,我只想引用人月神话序中的一句话“Jackson指出软件行业人员/方法学大师们只是简单地模仿、照搬其他学科的方法,
却将最重要的方面--问题域给忽略了。他指出,面向对象方法和结构化方法对问题域的处理没有什么大的区别,却被人们过分地用美
好的词汇给美化了。”

因此,我只能认为,robbin认为Ruby是一颗银弹,到底是不是,只能拭目以待。

这是另外一个问题了,而且还是比较大的问题。我到是经常看见别人说业务重要,技术不重要什么的论调,要说我都重要,哪个缺少
哪个更重要。

不过从我个人项目经历来说,我主持、参与和咨询过n多行业项目,涉及了医药、机械、广告、化工、航空、银行、教育、电子政务等
行业项目,这些行业的业务知识我都不懂,但是我没有发现这些行业的业务知识,或者说问题域成为项目的最大障碍。

其实这个道理很容易想通的,搞编程的人都比较聪明的,那些行业知识你没有理由比掌握一门编程语言困难啊?再说也不需要你成为
行业专家你才能进行业务逻辑抽象啊。而且搞编程的人,他们的逻辑思维能力都被训练的很好了,对于普通的业务逻辑抽象和归纳,
根本就是小儿科的事情啊,为啥会成为障碍呢?哪些地方你不知道,你随时去问客户的业务专家不就好了吗?

项目成败的因素有很多,如果抛开外部因素的话,一般来说项目成败往往取决于Team Lead的个人能力:包括他的技术能力、管理能
力、组织协调能力,但无论如何行业知识的问题域不是什么障碍,如果你们做项目在这方面被卡住了,就要想想看老板是通过什么手
段拿到项目的了。

第 241 / 283 页
http://robbin.javaeye.com 5.9 从京沪列车对比看京沪两地的服务意识

5.9 从京沪列车对比看京沪两地的服务意识

发表时间: 2006-11-22 关键字: 北京 上海

从京沪列车对比看京沪两地的服务意识

因为工作关系,我时不时乘京沪列车往来于两地之间。京沪列车,号称可以媲美飞机服务的,舒适乘车体验的软卧列车,全程12小
时,票价500元左右,每天晚上7.00到7.35分之间,每间隔7分钟连续发车5趟,号称追尾列车,第二天早上7.00到7.35分之间,5趟
列车每间隔7分钟陆续抵达目的地。因为夕发朝至,两边都不占用白天工作时间,因此每次去北京我总是乘京沪列车,而不是坐飞机。

这5趟列车中,其中两趟1/2,21/22次是北京铁路局的,另外三趟5/6,7/8,13/14是上海铁路局的,虽然列车都是同样的,但是乘
坐次数多了以后,发现乘坐体验差异很大,而经常往来两地的人都是首选上海铁路局的列车,实在买不到票才选择北京铁路局的列
车,怎么会有这么大差别呢?仔细比较一下服务的细节,答案浮出水面:

一、乘车积分卡
上海铁路局列车可以办理积分卡,类似各大航空公司的积分卡,每次乘坐上海铁路局列车从上海到北京区间,列车员会到车厢给每个
有积分卡的乘客刷卡,累积刷卡10次,免费赠送一次上海铁路局的京沪列车车票;
北京铁路局的列车没有这项服务;

二、免费餐
上海铁路局列车赠送免费餐,类似飞机赠送的那种免费餐,量不太大,不过作为晚餐也够填饱肚子了,另外你还可以订第二天的早
餐;
北京铁路局列车没有免费餐,列车员也不会推着小车卖盒饭,你要在列车上吃饭,请到餐车,早餐也不供应;

三、牙刷牙膏
上海铁路局列车赠送免费的牙刷牙膏,虽然不那么好用,不过还可以凑合用用;
北京铁路局列车没有;

四、叫早和锁厕所
上海铁路局列车的列车员在列车到站前不叫早,只在列车到站前30分钟开始列车广播,提醒你该起床了,直到列车快进站的时候才锁
厕所;
北京铁路局列车的列车员在列车到站前一小时就哐哐哐敲门,叫醒每个乘客,说要打扫卫生,要大家起床,拜托!才6.00,就要我们
起床!眼睛还没有睁开呢!而且列车到站前半小时就锁厕所,可怜刚刚起来的乘客们排着长队等厕所;

五、小桌板
上海铁路局列车里面的小桌板很长,可以放很多东西;
北京铁路局列车里面的小桌板很短,放不下多少东西;

六、被罩和枕头
上海铁路局列车的被罩质地不错,比较厚实,里面的被芯不会露出来;枕头是一个大软枕头;
北京铁路局列车的被罩好像是劣质产品,被芯总是露出来,塞不回去;一个小硬枕头,一个小软枕头;

七、列车员

第 242 / 283 页
http://robbin.javaeye.com 5.9 从京沪列车对比看京沪两地的服务意识

上海铁路局列车员都是上海的女孩,服务意识很好。有次我晚上起来肚子不舒服,列车员还很关心的嘘寒问暖,对了,长的都很漂
亮;
北京铁路局的列车员都是天津的女孩,说话嗓门比较大,而且奇怪的是为什么没有北京本地人做列车员?

八、留言簿
上海铁路局列车上面的留言簿上面都写满了,绝大多数都是赞誉的,每个评论下面,列车长都写了回复;
北京铁路局列车上面的留言簿都是空空的,没有什么留言;

这些细节其实都不算什么,但是累积起来就会让乘客的感受有非常大的不同,所以大家都对上海铁路局列车趋之若鹜,对北京铁路局
列车避之不及。当然这只是冰山一角,但是已经足够体现出来两个城市服务意识的巨大差距了。

第 243 / 283 页
http://robbin.javaeye.com 5.10 小记周末的JavaEye篮球俱乐部活动

5.10 小记周末的JavaEye篮球俱乐部活动

发表时间: 2006-11-27 关键字: 篮球

11月26日周日下午,天公做美,连绵的阴雨竟然停了下来。于是赶紧出门,看看时间还来得及,做上公交车就到了上海师大。等到师
大篮球场,看见ouspec一个人抱着篮球idle中。一问,说大家会陆续过来,要等一会。于是在旁边空闲场地练习投篮。

过了不一会,大家陆续过来了,有flhs,HLTB,还有两个没有报id的会员,于是大家分为两组打对抗赛。打了有半个小时,eyejava和她
女朋友来了,于是分了三组,两组对抗,一组休息。这样从下午2.00一直打到4.00左右,中间歇歇打打。

本来我球技很差,不过当天发挥的还不错,除了中投不太准之外,上篮,背框还都像模像样,印象当中也投进了不少球。一个没有报
id的在群硕上班的会员发挥很好,篮下技术很棒,HLTB也不错,eyejava刚上来手很冷,不过后来投篮神准,怎么打怎么有,ouspec投
篮姿势不标准,不过命中率很高。

等大家都打累了,一商量时间还早,出了师大校门有一个避风塘,于是又在避风塘喝茶聊天。flhs抢着买了单,还买了两副扑克(可惜
没有用上),大家一边吃零食喝茶,一边闲聊。一直聊到晚上6.00,于是做鸟兽散。

个人觉得这是一次成功的活动,以后应该经常举办,周末打打球,锻炼锻炼,打累了就到避风塘聊天杀人。下次可以稍微准备一下,
这次没有把杀人活动组织起来,有点遗憾。

BTW:最近琐碎事情实在太多,很多想写的文章都没有时间去写,学习学习庄表伟,预报一下:

一、rails1.2的REST,理念领先的革命性web设计思想
二、Java开源,潘多拉魔盒已被打开
三、社区2.0的探索和思考
四、如何构建Java群集,以及群集编程

第 244 / 283 页
http://robbin.javaeye.com 5.11 如何规划你的职业发展道路

5.11 如何规划你的职业发展道路

发表时间: 2006-11-28 关键字: 职业

这是2004年JavaEye杭州活动我的演讲稿,当时演讲的主题是《如何规划你的职业发展道路》,演讲当时的反响不错。后来2005年在
上海交通大学闵行校区又应交大之请再次演讲这个主题,反响也很好。

后来很多朋友曾经多次向我要这个演讲的ppt,今天突然想起来,就把ppt转换为pdf,提供给大家参考,希望对于大家的职业发展道路
有所启发。

附件下载:
• 如何规划职业发展道路.zip (281.8 KB)
• http://robbin.javaeye.com/topics/download/a81d2d5c-27f5-4a44-820e-82420ad50c90
• 描述: 如何规划你的职业发展道路

第 245 / 283 页
http://robbin.javaeye.com 5.12 看了《墨攻》,感觉还不错

5.12 看了《墨攻》,感觉还不错

发表时间: 2006-12-25 关键字: 影视

昨天去家乐福超市的时候,看到旁边的电影院中正在放映《黄金甲》,而刘德华的《墨攻》已经下了档期,然后在超市里面就看到了
《墨攻》的DVD,于是顺手买了一张,带回来看了。

电影里面当革离第一次出现在梁城,摘下斗蓬的时候,让我想到了《星球大战》里面的绝地武士,《墨攻》的情节有点像《特洛
依》,好多地方可以看出来有借鉴《特洛依》的地方。就战争场面而言,当然与好莱坞大片有非常大的差距。不过整个影片看下来,
却感觉很好,你能够感觉到影片有种诚意,感觉到导演在用心。也许场面不华丽,也许故事很一般,但是影片很鲜明的向观众传达了
它希望传达的思想,而观众也能够有所感受,有所触动。

不得不说,在当前所谓的古装大片满天飞,众多大导演不知所云,让观众云山雾罩的时候,一部很有古装大片气质的《墨攻》显得尤
其优秀,同样是古装大片,同样是大陆港台韩日影星加盟,《墨攻》,就能够很好的驾驭体裁,讲好故事,传达思想,捏合演员,怎
么《十面埋伏》、《无极)、《夜宴》统统不及格呢?

答案就是导演的诚意!特别是在看过《夜宴》之后,这种感觉很强烈。也不妄我花了15.9元钱。

演员的表演也值得称道:

刘德华很好表现出来一个墨者在墨家理想主义思想和战争爱情现实面前冲突的困惑,可怜他在《十面埋伏》中被张艺谋给毁的;
王志文把一个阴险,卑鄙,狡猾,无能的大王表现的淋漓尽致,,可怜他在《无极》中被陈凯歌给毁的;
安圣基演的巷淹中将军很有古代军人的气质,很棒!可怜他的韩国同胞张东健在《无极》中被陈凯歌给毁的;

第 246 / 283 页
http://robbin.javaeye.com 5.13 无责任预测2007年IT行业七大事件(本预测完全胡扯,如有雷同纯属巧合)

5.13 无责任预测2007年IT行业七大事件(本预测完全胡扯,如有雷同纯属巧合)

发表时间: 2006-12-28 关键字: 技术预测

本来老老实实写了两篇博客,总结2006,展望2007年软件行业技术发展的,结果反响比较小:

http://robbin.javaeye.com/blog/38560

http://robbin.javaeye.com/blog/38593

看来大家还是喜欢八卦,那么我只好无责任的八一八了:

本预测完全胡扯,如有雷同纯属巧合

一、REST击败SOAP,Google开始抢夺IBM的市场

在rails1.2迅速普及,以及业界巨头Google,Amazon的不遗余力的推动下,REST+AJAX SOA架构广泛流行,SOAP和重型Web Services


被淘汰,Google携REST+AJAX开始抢夺IBM的SOA市场份额。然后IBM开始在WebSphere平台提供RoR支持。

二、无数个开源Java版本将出现

除了Sun的JavaSE,还有Apache的JavaSE,Microsoft的JavaSE版本Mava,Java一下跑出来好多孪生兄弟,此外ruby团队发布Rava,即
在JVM上面直接跑Ruby的版本,此外Python团队也不甘示弱的推出了Pava RC版。

三、Red Hat收购MySQL,与Oracle正面开战

Red Hat继收购JBoss之后,继续收购了MySQL,于是两大巨头开始全面绞杀,从操作系统到数据库,从数据库到应用服务器。

四、ruby on rails在国内开始迅速普及

RoR在国内迅速普及,击败了PHP,Java和dotnet,成为国内最流行的应用软件开发技术。失业的PHP,Java和dotnet程序员们开始纷
纷上街游行,高呼打倒小日本,抵制ruby,抵制日货。

五、“今天你自拍了吗?”

各地电视台纷纷加入视频网站大战,推出宣传口号为:“今天你自拍了吗?”,同时DV开始大降价,厂家开始免费促销,只要你自拍上
传到我的网站,我就免费赠送DV给你。

六、google离职员工创业开始搞web3.0

第 247 / 283 页
http://robbin.javaeye.com 5.13 无责任预测2007年IT行业七大事件(本预测完全胡扯,如有雷同纯属巧合)

由于Google已经变成大公司,股票激励机制逐渐失效。开始有员工离职创业,研究下一代智能互联网web3.0

七、中国软件程序员工会成立

由某知名程序员发起,成立中国软件程序员工会,下辖一个律师团。程序员工会专门受理程序员对所在公司的投诉,保护程序员合法
权利,例如:要求公司给员工提供全面的福利保障,不允许加班,最低工资保障。程序员工会也负责成立委员会进行考核,只有通过
考核的人颁发证书才允许进入软件开发行业。并且工会通过组织第一次程序员罢工取得了阶段性胜利。

第 248 / 283 页
http://robbin.javaeye.com 5.14 以陈一舟的话自勉

5.14 以陈一舟的话自勉

发表时间: 2007-04-22

引用

  千橡学到了少既是多,欲速则不达,因为任何好的东西,比如昨天晚上我看到Hao123的站长说,好的品牌,包括猫扑、
DoNews,都是一个站长在没有任何回报想法的时候,踏踏实实的做了五六年,在做的时候没有想到回报,就是非常喜欢这个事情,
觉得有用户需要,做了五六年以后,价值是在五六年以后才爆发的,因为品牌积累到一定程度以后,每天所增加的用户不是花钱拉
过来的,而是你的品牌本身积累以后,口口相传,口碑是非常重要的,我觉得做互联网产品的话,一定要有口碑,所以做网站还是
做公司,都要做自有的IP,自有的PV,不花钱,能够自动到你这来。而且只要做出自有的PV,经济价值可以上升,因为愿意看你PV
的网民会越来越多。我们在座的各位一定要做自有的PV。

  我提醒自己比较多的是,做事情保持饥渴,虽然很饥渴、很执著,但是现在发现对于大公司来说,这件事情并不是最难的,因
为公司有这么多钱肯定是很执著,但实际上最困难的事情就是怎么样保持少既是多和欲速则不达,一定要有足够的时间给自己考
虑。对于个人站长来说,要做一个真正的好的事情,需要时间,我们去年的心态一定要放慢,互联网做出一个好东西真是要时间。
比如在投资行业里面有一个概念叫做复合增长率,每年成长30%,去年中国的股市上涨100%以上,和30%没有什么了不起,但是全
世界第二富的人巴非特就是在30年的时间从一个很下的基数夺到全世界第二富,他也没有特别的事,每一年投一两个公司,他们忙
的时候他休假,股市跳楼的时候他忙,30年如一日,每年增长30%,如果基数是1的话,涨20-30年左右是1万倍。所以在座的各
位,你手上的网站价值1万元人民币的话,如果是夫妻老婆店,不一定要卖掉,但是可以找到办法,可以让你网站自有PV和价值每年
涨的不多,和中国互联网一起涨,涨30%,退休的时候是1个亿,符合增长率非常关键。互联网行业有一个通病,都想挣快钱,我觉
得挣快钱有一个过程,现在是拼耐心,这个事情怎么能够长远,怎么样把自己的心态、泡沫的心态放下去,去踏踏实实的做事情,
每年不要涨多,只涨30%就够了,到十年以后可能翻了100倍左右。

  最后把我去年的一句话送给大家,保持饥渴、保持执著,只要保持饥渴和执著,十年以后大家都可以成功。

我特别同意其中这句话:

引用

好的品牌,包括猫扑、DoNews,都是一个站长在没有任何回报想法的时候,踏踏实实的做了五六年,在做的时候没有想到回报,就
是非常喜欢这个事情,觉得有用户需要,做了五六年以后,价值是在五六年以后才爆发的

引用

实际上最困难的事情就是怎么样保持少既是多和欲速则不达,一定要有足够的时间给自己考虑。对于个人站长来说,要做一个真正
的好的事情,需要时间,我们去年的心态一定要放慢,互联网做出一个好东西真是要时间

第 249 / 283 页
http://robbin.javaeye.com 5.15 TechTarget-值得研究的专业技术网站

5.15 TechTarget-值得研究的专业技术网站

发表时间: 2007-05-18

http://blog.chinabyte.com/blog/yj123456789/archive/2007/05/17/15191.html

引用

TechTarget在美国时间5月17日上午10点上市,融资一亿美金。

TechTarget是美国一个IT专业网站,其服务的人群主要是高级技术人员,发表的文章也多趋向于技术性。与美国传统的IT专业网站
CNET相比,TechTarget更加细分化,用户也更加有针对性。这也让TechTarget的用户粘性远远大于一般IT专业网站。

在TechTarget之前上市的IT专业网站还有一个,就是鼎鼎大名的CNET,不过最近几年CNET已经在走下坡路,并有淡出美国主流网站
的危险,原因之一就是粘性不够。由于CNET需要顾及自己的所有用户,这就造成了它的内容一定要简单、明了,不能太专业,也不
能太不专业。平衡中往往造成顾此失彼。于是,专业的用户被一些更专业的网站分流,而普通用户也倾向于去信息更加丰富的雅虎
等门户。IT专业的定位在现在的CNET而言,更像是枷锁,而不是优势。

TechTarget就属于分流专业人士的网站,它的定位更加明确,就是高端技术人群,所以他的粘性也更加好。一些非常技术性的文章往
往在CNET关注程度非常小,而在TechTarget却非常热门。

TechTarget的上市说明现在投资人对大而杂的网站前景并不看好,而细分化、精准定位的网站往往可以获得青睐。

http://www.techtarget.com/

TechTarget网站全球Alexa网站流量排名是2900名,只和国内的ChinaUnix社区流量相当,但是他的价值,明显超过了CSDN( 注:CSDN
Alexa排名是600多名)

http://www.techtarget.com.cn/

TechTarget中文网站全球Alexa网站流量排名是27000名,比JavaEye流量差得很远,JavaEye现在是12000名。

这说明了一个事实,全球互联网行业不再那么看重PageView,而是网站的内在价值。专注于行业细分的网站也会有一个好的前景。值
得研究一下TechTarget全球网站的运营方式和盈利模式。至于TechTarget中文网站,没有什么价值。

第 250 / 283 页
http://robbin.javaeye.com 5.16 杭州网侠大会观后感(附演讲ppt)

5.16 杭州网侠大会观后感(附演讲ppt)

发表时间: 2007-05-21

上周末刚刚参加杭州的网络工程师侠客行大会,有不少感想。

一、认识了很多高手,请教了很多问题

1、章文嵩博士
最荣幸的是认识LVS(Linux Virtual Server)的作者章文嵩博士。章文嵩博士的大名已经久仰了很多年了。LVS也是我很感兴趣的一种做大
规模网络部署的软件load balancer方案之一。借这个机会,我专门向章博士请教了LVS如何处理HTTP Session Sticky的问题,很有收
获。章博士说有任何问题,都可以给他发Email来问,章博士很谦虚,和他交流感觉很开心。

2、张华平博士
在休息室,餐桌上好几次和张博士聊天,结果聊的都是JavaEye社区的事情。直到我离开杭州前听张博士的topic,才知道他是中文分词
方面的知名专家,而且是大名鼎鼎的ICTCLAS项目的负责人,几个月前我还下载了ICTCLAS钻研,这次碰到了作者了,很可惜没有早点
知道,否则就有充分的时间向他请教了。好在交换了名片,还有交流的机会。

3、IBM的罗学聪先生
罗学聪说他原来是Rational公司的,后来因为并购进入IBM,现在做SOA的咨询。SOA是个很热门的领域,罗先生给我介绍了很多
IBMSOA产品线的知识。

4、博客堂的开心就好(王洪超)
这也是一个如雷贯耳的名字,向他和其他微软同事,请教了很多围绕silverlight的问题,可惜交流时间很短,他们就走了,关于
silverlight我还会另外写文章和大家探讨。

二、对阿里巴巴公司的认识

外界对阿里巴巴公司的争议很多,褒贬不一。最近连续多次去杭州和阿里巴巴公司接触,阿里巴巴给我留下最深刻印象的还是公司的
企业文化。

1、阿里的员工入职培训令人印象深刻
阿里的入职培训号称“洗脑”,对员工进行阿里文化的灌输。员工就像上小学一样,每天上课,下课,一起搞活动,唱歌,组织团队进行
小红旗评比。恍惚间好像回到了小学时代很单纯的生活。

2、阿里的员工精神面貌特别的好
每个人很勤奋,很敬业,工作的责任心非常高,而且都是带着很高的热情投入自己的工作当中。这样一个团结的,敬业的,勤奋的,
士气高昂的团队其战斗力是相当可怕的。马云是他们绝对的精神领袖,可以鼓舞每个阿里的员工奋不顾身。

说到这里,我有点明白马云为什么会成功了。其实中国人都是很聪明,很有能力的,但是中国人很难能够团结起来,上下一心去做一
件事情。但是一旦能够把一群中国人团结在一起,为着一个共同的目标,以宗教狂热般的精神去奋斗,那没有什么事情不可能成功
的。

第 251 / 283 页
http://robbin.javaeye.com 5.16 杭州网侠大会观后感(附演讲ppt)

在解放战争时期,我党的军队装备能力很差,人员素质很低,但是有一个像神一般的精神领袖毛主席,有一个高度组织起来的人员洗
脑机制:把党支部建在连上。就这样奇迹般战胜了国民党。在建国以后,一穷二白,之所以能够创造经济奇迹,两弹一星,靠的还是
毛主席的精神领袖能力和党的洗脑机制来保证全国人民上下一心,共同创造奇迹。

华为公司也好,阿里巴巴也好,给人强烈的团队战斗精神。事实上,一直到现在,我们都没有看到马云在公司经营上面,公司产品上
面有什么生花的妙笔,但是他可以如此的成功。不得不说他最厉害的一点就在于能够团结一群聪明的中国人以宗教狂热般的心态去做
事情。有了这种精神,没有什么奇迹不可以创造。雅虎中国至今经营不好,我想最根本的原因也在于人员的文化整合上没有达到阿里
的程度导致的。

另外,这也是一种启示,中国本土的软件公司如何克服人员流失问题,如何把一件事情做成功?我想最终并不需要你有多么高明的经
营手段,多么厉害的商业头脑,只要团结一批人以宗教狂热般的心态一起奋斗,无论干什么都会成功。

三、一些遗憾

感觉最遗憾的是出席的社区方面的嘉宾太少了,阿里自身的网站全部都是用Java开发的,但是似乎没有什么在Java社区方面有号召力
的人,他们在DBA方面到是一批itpub的社区高手。所以我没有找到什么可以直接交流技术环节的嘉宾。

另外阿里组织的本次活动我看他们工作人员已经非常用心去做好了,但是明显缺乏经验,各个环节都有不足之处。

四、小花絮

我讲完Java的topic之后,鼠标忘记拿走了。第二天对阿里的工作人员说,能不能帮我问一下会场工作人员,看有没有见到我的鼠标。
毕竟这个鼠标我用了三年多了,很有感情。

在我走之前,阿里的人说找到了,塞给我一只IBM鼠标,我很高兴,也没有细看,塞进包里面就走了。等晚上回家打开电脑,才发现鼠
标不是我原来那只,而且是一只用过一段时间的鼠标。很明显,阿里的工作人员把他们自己公司的鼠标赔给我了。

其实我有不只一个鼠标,而且他们赔给我的鼠标我也用不惯,丢在抽屉里面了。但他们对待工作的态度确实让人觉得挺敬佩的。

附件下载:
• Java软件技术发展趋势探讨.rar (637.2 KB)
• http://robbin.javaeye.com/topics/download/35c334de-7f13-41d9-bbab-61f8aca4cd8b
• 描述: 《Java软件技术发展趋势探讨》
• 使用rails编写REST风格的web应用.rar (585.4 KB)
• http://robbin.javaeye.com/topics/download/6a8dc869-a346-4d10-b3d5-06237c036079
• 描述: 《使用RoR开发REST》风格的web应用

第 252 / 283 页
http://robbin.javaeye.com 5.17 从JavaEye网站访问来源看软件公司的区域选择

5.17 从JavaEye网站访问来源看软件公司的区域选择

发表时间: 2007-08-27

JavaEye网站是国内比较高端的软件开发社区,通过对JavaEye网站的访问数据做一些分析,我们可以得出一些有价值的数据。

从上图可以看出,在国内一线城市北京、上海、广州和深圳四个城市,软件人才的储备北京遥遥领先,上海和广州居中,差不多是北
京的一半,而深圳则落入二线城市的行列。另外值得注意的是杭州的人才储备也非常丰富,虽然没有办法和周边城市上海相比,但是
也远远超过了深圳。

北京、上海、广州,深圳和杭州五城市的分析:

1、北京是软件公司首选的落户城市,人才储备异常丰富,占据了1/4的全国高端软件人才,同时北京也是软件人才找工作首选的城
市。

2、深圳的人才储备落入二线城市行列,尽管有华为,中兴,金蝶等国内软件领头羊,但软件人才在深圳似乎很不活跃。

3、在上面图表中排名前五的城市也是国内房价和生活成本最高的五个城市,已经不适合规模化软件公司的发展。

武汉、南京、成都和沈阳四城市的分析:

第 253 / 283 页
http://robbin.javaeye.com 5.17 从JavaEye网站访问来源看软件公司的区域选择

1、这四个二线城市当中的武汉,南京和成都人才储备基本相当,而远高于沈阳。这和城市拥有密集的高校有很大的关系。

2、规模化软件公司比较适合的城市是武汉和成都。这两个城市拥有密集的高校,人才后备充足;地理位置距离一线中心城市非常远,
不会发生人才争夺问题;生活成本比较低,有利于公司降低运营成本,人才安居乐业。

总结:

1、需要比较多高端人才的公司首选城市是北京,同样的,高端人才就业机会最多的城市也是北京。

2、长三角上海、杭州、南京三城市人才加起来可以和北京等量齐观,但不如北京密集,但总体来说也是比较好的选择。而广州深圳在
一线城市当中落在最后面。

2、需要比较多中低端人才,规模化发展的公司可以考虑武汉和成都。综合了人才后备足、生活成本低,离中心城市远等优势。

第 254 / 283 页
http://robbin.javaeye.com 5.18 《太阳照常升起》观后感

5.18 《太阳照常升起》观后感

发表时间: 2007-09-15

周五晚上到影院看了《太阳照常升起》的晚场半价场。电影开场前很吃惊,周末的半价晚场一般都会爆满的,例如我看《变形金
钢》,《加勒比海盗》都是如此,但是今天里面只有十几个人,看来《太阳照常升起》的票房好不了。

看完以后觉得《太阳照常升起》是一个非常纯粹的文艺片,只不过不那么沉闷,今天看电影之前也看了一些影评,很多人说看不懂,
说不明白黄秋生为什么自杀。我是看懂了,故事不复杂,人物的命运也很合逻辑。但是《太阳照常升起》不是娱乐片,没有足够生活
体验和人生感悟的年轻人肯定会看不懂,所以我建议30岁以下的就不必看了。

故事的脉络大致是这样的:

1958年的某一天,周韵在怀孕的时候去新疆找自己的志愿军丈夫,在沙漠里面同行的一个女人是南洋华侨孔维,孔维是去找自己的未
婚夫姜文结婚去的。孔维独自走在连绵山脉一个刻着“尽头”的碑前停下来碰到姜文,这是一个很浪漫的场景。然后在一个篝火晚会上面
他们结婚,狂欢,抢新娘,男人摸女人屁股,风俗很开放。

周韵见到的是自己丈夫的遗物,有三个洞的军装,三条俄国女人的辫子,还有一包他丈夫和外国女人写的情书。他丈夫牺牲了,但因
为生活作风问题,不能成为烈士。周韵对他丈夫的死和他丈夫对她感情的背叛很伤心,并且由此开始精神不正常。在姜文和孔维结婚
那天,周韵在铁路上生下了孩子,她抱着孩子千里迢迢到了他丈夫的家乡,定居了下来。

在后来的20年当中,周韵始终生活在对丈夫的缅怀和感情背叛痛恨的矛盾心理当中,这表现在她剪了他丈夫的照片,后来还烧了他丈
夫的书信上面。20年后某天,周韵因为碰到一只鸟刁走了她的鞋,彻底诱发了她的精神失常。动不动上树大喊,或者挖坑盖屋子。但
其实她并没有真的精神病,从某种意义上来说,这是一种身体的自我保护机制,让压抑了20年的矛盾心理的得以宣泄和缓和。在1976
年夏天的某一天,当她盖好了石屋子之后,她压抑20年的矛盾心理得以释放,她终于想开了,所以又回复了正常。

一个长期压抑了20年的人终于想开了,她的精神解脱了,所以她的死是一种很自然的选择,其实她死不死都不重要,在那个时刻,人
需要的是彻底的解脱。

同样在1976年夏天,姜文在一所学校当老师,他的老婆孔维和他两地分居,他和学校医务室的陈冲勾搭上了。姜文的同事黄秋生也是
南洋华侨,是一个比较洁身自好,生活讲究和举止优雅的人,在某天晚上放露天电影,他去摸了一个学校食堂女工的屁股,这个女工
本来就很仰慕他,反而想过来抱他,他一惊,转身就跑,此时有人大喊“抓流氓”,于是就把他当流氓穷追不舍。黄秋生逃进姜文的房
间,跳窗,去撞破了姜文和陈冲的奸情。陈冲为避免奸情泄漏,骗黄秋生跳楼摔断了腿,被42只手电筒照着,被众人殴打,颜面尽
丧。

最后黄秋生洗脱了罪名,他却在第二天自杀了。他为什么自杀,他当被42只手电筒照着,被众人殴打的时候,被陈冲设套出卖的时
候,这个很有尊严的男人已经像条狗一样没有尊严了,他之所以没有自杀是因为不想屈辱的死,所以当他罪名洗脱的时候,就是他含
笑自杀的时候。

1976年秋天,姜文和陈冲的奸情被最终暴露,于是姜文被下放到周韵的儿子房祖名的村子。姜文整天打猎冷落自己的妻子,而他的妻
子孔维本来就是一个风流的女人,于是勾搭上了房祖名。姜文发现以后准备打死房祖名,因为房祖名说没有见过天鹅绒,于是跑到北
京找崔健帮忙。崔健给他分析错不在别人,在他自己。于是姜文打消年头回到村子,准备放过房祖名,和自己老婆好好过下去。那边
厢,单纯的房祖名找到了天鹅绒,傻乎乎的用话刺激了姜文男人的尊严。姜文恼火之下枪杀了房祖名。

第 255 / 283 页
http://robbin.javaeye.com 5.18 《太阳照常升起》观后感

整个电影就是这么一回事不难看懂。但要说电影想表达什么,那么我觉得姜文表达的是在种种压抑环境下的人性。每个人都活在社会
大环境、生活小环境,以及亲人的压抑之下表现出来的原始的人性。

从电影的艺术性来说,我觉得它很棒,是一个开了先河的大师级作品,但是要说故事性,娱乐性,那真的没什么可值得一题的,相信
年轻的80后会喜欢变形金刚之类,不会对这部电影感兴趣。

如果以后什么时候有空,我到打算再看一遍这部电影,搞搞清楚那么多符号性的场景和镜头究竟是什么意思。

第 256 / 283 页
http://robbin.javaeye.com 5.19 关于技术人员创业入股的问题

5.19 关于技术人员创业入股的问题

发表时间: 2008-04-13

投资方原打算在前两年投入300万研发产品,如果算上后期的维护和市场推广,估计投资方在这个公司的投资预算大概在500万人民币
左右。好了,那么楼主一不打算实际出资占有股份,二没有现成的产品折算成现金入股(X产品产权不是你的,Y产品不是这个行业的产
品),也就是说你现在只能以技术入股,即所谓的干股。

干股意味着你没有实际的投入,也无需承担任何风险,随时都可以撤退,而且干股获得的股份实际上是对你未来创业期投入的预先支
付,激励你在未来创业期发挥其应得股份的作用的,而不意味着你加入公司的第一天,就应该拿到这么多股份。记住一点:你应该占
多少股份,取决于你付出了什么,而不是你预期对公司发挥多大作用。人家实际注资几百万,就该占有多少股份,而你干股入股的方
式,人家就算只给你10%,也是合情合理。

虽然楼主口口声声说不想再打工,只想有自己的事业云云。但我不得不打击你一下,无论最终你在这家公司拿到多少股份,即使你最
终拿到自己期望的25%,也不意味着这个公司是你的事业。实际上由于你干股的身份、加上你完全对运作公司,市场推广、公司财务
等方面一无所知,因此你在公司的地位是被动的,实际身份介于股东和打工者之间的形态,你以后会发现,就算你是股东,你实际出
资的那个大股东仍然是你的老板,这一点无法改变,除非你也出资一二百万。

至于薪水方面,你期望税后25万年薪,就一下暴露了自己抱定打工的心态,而不是创业心态。这个年薪在上海算很高了,现在即便外
企都不见得能够给到你这个数字,更不要说创业公司,没有一家会给你这个数字。既然你是创业,就要记住一点:创业是要冒很大风
险的,你拿这么高工资,一点收入的损失都没有,完全没有风险?就算你一分股份都不占,你也不吃亏阿,我看前面说到,好像你现
在也无法立刻找到这么高的收入吧?想要在创业公司获得高收入,要靠你对公司业绩贡献特别大,而公司盈利情况非常好,那么年终
奖你可以一下拿到十几万。任何公司的CEO/CTO的年收入主要都是靠业绩激励的奖金,而不是靠工资获得的,如果公司还在投入期,
根本不赚钱,你作为股东为什么不能和公司共患难呢?

我也不了解你的合作方,因此不清楚人家会怎么想。如果换了是我的话,我投资500万成立这样一家公司,我给你开的条件,年薪方
面我只能给到税后10-15万,股份在10-20%之间,如果年薪要得高,股份就相应的低一些,反之依然。另外我会要求你做到两点:你
需要实际出资10万现金入股,购买5%的股份,剩下的股份也不是一次性给予的,会分三年36个月,做满一个月,获得一个月的,干满
三年,并且尽职完成自己的工作,才能拿到所有的股份,如果干不满36个月,干几个月就拿几个月的股份。

你们现在的情况并不是大家都白手创业,而是有资本进来的,那就是资本说话,你干股的身份其实就是给资本打工。

第 257 / 283 页
http://robbin.javaeye.com 5.20 网络招聘是如何被做烂掉的?

5.20 网络招聘是如何被做烂掉的?

发表时间: 2008-07-31

回复谢震文章http://zhenxie.javaeye.com/blog/189138

目前网络招聘面临的这种状况,我个人觉得是这些网站把市场给做烂掉了。

前面你提到的普遍现象是招聘公司收到太多无用简历,需要花太多时间在筛选工作上面。问题的核心在于为什么会收到这么多无用简
历?难道单单是因为投递简历成本太低的缘故吗?

从JavaEye网站招聘的简历投递来看,不存在这种问题,基本上投递简历的人目的性很强,不会满天撒网。之所以51job等网站出现这
样的现象,实际上离不开51job网站自身在鼓励这样做。

原因其实很简单,hr衡量投入产出比就是投入一块钱能够收到多少份简历,收到的简历越多,说明效果越好。一个网站你花了500块
钱,收到了上千封简历,另外一个网站你花了2000块钱,只收到20封简历,尽管最终你招聘的人员都来自后者,作为hr来说,她一定
会把主要预算安排在前面那个网站。

作为51job来说,和同类其他招聘网站的早期竞争就是通过降低招聘费用,鼓励简历的疯狂发送的手段来建立市场竞争优势的。最终造
成了这样的局面,培养了大批的hr以简历的单位成本来衡量招聘效果(hr也没有办法从专业技术能力来衡量简历质量)。

而正是由于造成了这样的局面,导致了投递简历泛滥的恶化。作为应聘者来说,虽然投递简历没有成本,但是他有接电话和约面试的
成本,他也不希望自己正在和领导开会的时候,接到别的公司面试通知的电话,投递简历投多了是有风险的。而且投多了以后,他自
己都不记得自己投过哪些公司的哪些职位,真有面试的时候,他都不知道怎么回事,懵懵懂懂的就去面试了,这样的效果肯定不好。
所以投递简历成本低,不一定会造成投递的泛滥。

问题的核心在于应聘者发现投递了10份简历竟然石沉大海。这里我们理解为什么会石沉大海,因为招聘公司一收上千份简历,hr晕掉
了,很多合适的简历很容易就被淘汰掉了(这个后面再谈),因此中签率非常低。这个时候应聘者能够采取的唯一办法就是多发猛发疯狂
的发,反正发简历成本低,怕啥,发吧。于是他完全可以无成本的一周发1000 封简历出去,同一个职位,他反复的发,骚扰hr。

最终三方共同推动,造成了目前的结果:网站培养了hr衡量单位简历成本的习惯,hr只看简历数量而不是质量,网站鼓励简历的烂发;
hr收到太多简历无法处理;简历投递效果下降,应聘者开始疯狂发简历,hr更加无法处理简历,如此往复。

这个时候hr开始抱怨了,网站想了一招,我给你开发简历过滤器,让你按照关键词筛选,这样上千份简历你不就可以轻松筛选了吗?hr
说好吧。从此hr不再一份一份看那上千份简历,只搜关键字。如果应聘者很不幸,简历当中没有这个关键字,你简历再好,也会被第
一时间过滤掉。这应聘者就开始不服气,我明明实力很强,职位很合适阿,我那就猛发吧,一个职位我隔三差五的骚扰你,而且大面
积撒网,广种薄收嘛。于是继续恶性循环。

那你会问,网站既然可以开发筛选器,为什么不在应聘者投递简历的时候就筛选呢,让hr收到简历的数量少一些,有效一些呢?其实
你现在可以明白,网站打死也不会这样干,因为这样干的后果是hr发现收到的简历数量大幅度下降,她会觉得单位简历的成本太高,
认为这个网站不值得投放招聘广告了。

作为网站来说他宁愿你hr收到无穷无尽的简历,让hr相信这个网站就是最好的招聘网站,人才资源是极大丰富的,然后再提供附加的收
费服务,来帮助你从这些垃圾简历当中来招聘。这样网站可以达到他的商业目的,用及其低廉的招聘包月服务费用,和大量的垃圾简

第 258 / 283 页
http://robbin.javaeye.com 5.20 网络招聘是如何被做烂掉的?

历吸引公司成为包月甚至包年的会员,然后再提供附加的增值服务来实现真正的利润增长。

现在51job的企业招聘费用非常低,一个企业一个月招聘广告才500元,你想他怎么赚钱?压根就是赔本赚吆喝。但他根本不靠这个赚
钱,靠的是用海量的简历砸晕你,然后要你乖乖的掏钱买服务,赚的是这个钱。

我个人观察下来网络招聘网站就是这样,靠大企业的大单子,和大量中小会员的增值服务来赚钱,压根不靠会员费和招聘广告费。所
以这些网站的商业模式决定了他不会按照你建议的方向去走。这个市场就是这样被做烂掉的。

直接招聘者自己看简历往往是小公司才这样,对于大公司来说,没有这个时间和精力这样做,所以HR是必须的环节。但是客户细分来
说,大公司才能给招聘网站带来营收的大部分,而小公司只占很小的比例。

对于HR来说,他需要一个数据来量化招聘广告的投放效果,所以简历数量就是这个量化的指标,直接决定了他这笔钱花的值得还是不
值得。过滤简历是他的日常工作的一部分,他自然也需要一些工具辅助他减轻工作量,这两者并不矛盾。

目前招聘市场的确存在你说的现象,对51job很不满意,但你要找其他招聘网站可能效果更差,两害相权取其轻也,还是用51job。

第 259 / 283 页
http://robbin.javaeye.com 5.21 李刚 Java - 希望电话骚扰事件就此画上一个句号

5.21 李刚 Java - 希望电话骚扰事件就此画上一个句号

发表时间: 2008-08-02 关键字: 李刚 java j2ee

8月2日晚上7点,我在上海市公安局某分局里,听着王警官在电话里面和13312871616手机号码的主人进行沟通,王警官希望我们双
方进行调解。为此,我愿意做出我的让步,不再追究打骚扰电话者的法律责任,并且非常希望把这件事情画上一个句号,大家都把精
力放在自己的工作上面来,不要为这种无聊的事情浪费精力。

电话骚扰事件的经过是这样的:

8月1日中午,我公司接到广州打来的一个电话,来电显示为13312871616,一个中年男子声音的人说:“JavaEye网站诋毁李刚”,要
求我们立刻删除一篇ID为“都别装了”的会员发表的文章,该文章对李刚使用了不雅词汇,怀疑李刚学生有书托嫌疑。他指责JavaEye网
站把该贴置为精华贴,是纵容行为(实际上该贴是会员投票的结果)。于是我们要求对方证明自己的身份,并且给出合理的删贴依
据。对方威胁着说:我还用证明?你要是不删,我就举报你们,我们回答:你完全有权利举报JavaEye网站。然后对方情绪失控,我们
挂断电话。从此时开始,此人不停的拨打我公司电话,导致我公司无法正常办公,只能暂时拔掉电话线。

拔掉电话线以后,此人开始拨打我本人的手机,有以下截图为证,来自上海移动手机帐务查询系统的网页显示此人的手机号码和打电
话的时间。

在我不胜其扰,关闭手机之后,以为摆脱了此人的骚扰,谁知道当我下班回家,此人不知从什么地方探听到了我的家庭电话,继续开
始打我家庭电话骚扰。我接听以后,对方说:你删不删那个帖子,我说如果不删呢,对方说那我就继续打下去,直到你删了为止。此
后我们双方进行了多次对话,但是沟通没有效果,期间此人还说了很多不着边际的话,不一一复述。

我实在不堪其扰,只好告诉对方,你如果继续骚扰我和我的家人,我只能把这件事情在网络上面公布出来,我希望你马上停止骚扰行
为,否则后果自负,对方不听,继续不断拨打骚扰电话。于是我把这件事情在JavaEye网站上面发贴公布。

在我发贴公布之后大约15分钟,骚扰电话暂时停止,时间大概在晚上10.00左右。随后李刚登录JavaEye网站,在JavaEye网站上面发
贴澄清自己,请看这篇帖子的讨论:http://www.javaeye.com/topic/223273。李刚声明,他没有指示任何人打骚扰电话。

8月2日早上8.35分,我再次被13312871616打来的电话吵醒。等我上网之后看到了李刚最新的回贴,要求JavaEye网站删除“都别装
了”的那个帖子。根据李刚本人的要求,我删除了“都别装了”的主贴。之后我和李刚通过站内短信进行了良好的沟通,双方达成了如下
共识:

1、骚扰电话不是李刚指使的
2、有人在JavaEye和李刚之间挑拨离间,想造成我们之间的冲突,达到他不可告人之目的
3、必须揪出打骚扰电话这个人,还李刚一个清白

于是我公布了骚扰电话号码13312871616,通过百度搜索确认,电话号码的主人叫田江东,和李刚在同一所培训学校就职,是李刚的
顶头上司。

第 260 / 283 页
http://robbin.javaeye.com 5.21 李刚 Java - 希望电话骚扰事件就此画上一个句号

为了搞清楚事实的真相,我向上海市公安局某分局报案,要求协助解决该骚扰电话背后的真正主使者。在录口供期间,13312871616
再次拨打我的手机号码,于是我让王警官接听了电话。王警官让此人打上海市公安局某分局的办公电话(可能被录音),双方进行了
电话沟通:打电话的人承认自己就是田江东,这些电话都是他打的。

我向王警官反映,田江东要求我们删除的帖子已经删除了,我希望他不要再打骚扰电话。据王警官转述,田江东认为后面发的帖子更
恶心(我不清楚这个后面的帖子指的是什么?),必须删除之。王警官在电话里面和田江东进行了长时间的沟通,希望田江东和我进
行和解,并且希望田江东采取合法的诉讼手段解决问题,不要采取电话骚扰的手段。

经过王警官的调解,我不再追究田江东对我公司,我本人和我家庭的电话骚扰行为,也希望田江东不要再使用电话骚扰的手段,因为
电话骚扰并不能够解决问题,只会激化矛盾。如果田江东对我所发的帖子有任何不满,欢迎到JavaEye网站来发贴沟通,大家都可以做
见证人,就像李刚和我发贴进行的沟通一样,问题很快就可以解决。我相信,只要双方在网站上面沟通清楚,这件事情就可以画上一
个句号了。

恳请大家回贴的时候不要再攻击别人,攻击别人无助于解决问题,谢谢。

第 261 / 283 页
http://robbin.javaeye.com 5.22 中国行业应用软件领域恶性循环的原因是什么?

5.22 中国行业应用软件领域恶性循环的原因是什么?

发表时间: 2008-08-06

我对该问题的看法:

中国的企业应用软件领域恶性循环的根源是什么? 是中国经济领域的国有企业寡头垄断,挤压民营企业生存空间,国进民退造成的。

1、软件公司要赚钱,也遵循2-8原则,20%的大客户大项目赚公司80%的利润,而80%的小客户小项目只不过是给程序员练手,培养
技能,积累公司研发实力的。

2、企业应用软件领域的大客户除了几个民营巨头如华为、联想之外,99%的都是国有寡头企业,例如:金融行业的四大商业银行;电
信行业的电信、网通,移动;电子政务行业的国家各级单位和地方各级单位;航空领域的三大航空公司;石油领域的中海油、中石
油;钢铁行业的宝钢;教育行业的国家、地方各级教育部门;医药行业的国有各大医院;还有很多,不一一列举。政府所谓的扶持软
件行业,本质上也是通过政府机构的软件采购来实现的,所以也算这一类里面。

3、做这些大客户的生意,你的公司靠的不是软件研发实力,靠的不是行业软件经验积累,而是靠你有没有该行业的人脉,有没有官商
撑腰。

4、有人脉的官商公司接下这些大项目,然后自己剥削大部分利润,再转外包给那些有规模有实力的软件公司,于是这些有规模有实力
的公司只能赚个辛苦钱,而无法积累资本,无法扩大公司规模。

5、大部分有实力的软件公司接到官商转外包,并不会自己做,而是继续转外包给下面的虾米软件公司做,自己做地分钱而已。所以既
无技术积累,又无资本积累。

6、虾米公司拿到项目已经不赚钱了,于是再次转外包给soho的程序员去做,自己做地分钱。所以只是一个老鸨的角色。

7、因此,各级企业应用软件公司规模越到下面,越赚不到大客户的钱,他们只能去接民营企业的软件项目的单子。

8、有IT需求的民营企业现在活的都很惨,被国有企业挤压的太狠,哪有钱可以大笔采购软件项目,只能精打细算,能省则省,越低的
报价越心动。

9、有质量的软件公司不能赔本赚吆喝,报价不低,野鸡软件公司报价低,于是抢了好的软件公司的单。

10、野鸡公司转外包给soho程序员写代码,自己赚了一票就走人,赚钱没有可持续性。

11、所以我现在非常反对程序员接私活,JavaEye坚决不做软件项目外包交易功能。

12、做过企业应用项目的人知道这里水太深,都转型了。我好几个朋友,本来自己开软件公司做企业应用项目的,现在公司转型做
web game,说想不到赚钱这么轻松。

13、但是有更多不知道水有深的人,前仆后继的做企业应用软件,这是一个博傻的行业。

第 262 / 283 页
http://robbin.javaeye.com 5.22 中国行业应用软件领域恶性循环的原因是什么?

14、我不做企业应用软件项目,因为我知道这里的水很深;我不做web game,因为我不喜欢玩游戏;我做JavaEye,是因为做技术社
区是一件健康有益身心的事情。

第 263 / 283 页
http://robbin.javaeye.com 5.23 关于刘翔退赛的四个不理解

5.23 关于刘翔退赛的四个不理解

发表时间: 2008-08-19

第一个不解:

从半年前刘翔美国热身赛伤病退赛开始,他的状态就一直不好,而这段时间罗伯斯破了世界记录。恐怕在奥运会之前,已经没有多少
人看好刘翔能拿金牌了吧?固然刘翔退赛,观众可能是不爽,但是当天的预赛也是大牌云集呀?罗伯斯,杜库雷,特拉梅尔都来了,
中国的史冬鹏也过了第一轮了。观众买的票看到了这么多高手的比赛,哪里亏了?如果说就看刘翔一个人跑,就他一个人值票价,其
他人都是垃圾,没有票价,那是不是对其他高手太不尊重了?如果说就看刘翔一个人跑,干吗还比赛呀?让刘翔一个人跑,大家看就
不行了吗?

第二个不解:

引用

今天中途退出比赛的还有特拉梅尔,他比刘翔早一组或两组。特拉梅尔在过了第一个栏架以后就不行了,摔在地上,他是被搀扶过
终点的。

好奇的问一句:特拉梅尔在别人搀扶下,怎么跨过后面的9个栏架的?莫非是别人把他举过栏架的,还是他自己从栏架下面钻过去的?

BTW:我当时在上班,没有看过电视。

第三个不解:

引用

纳税人就不能为自己的纳税说点想法吗?刘翔训练是国家给的钱,钱哪里来,是不是纳税人,雇员没做好工作,老板说两句怎么
了,还不能说吗?你们怎么管理企业,雇员完不成任务就是一个更高境界的伟大转型吗?

刘翔赚的比赛奖金和广告费用,国家体育总局都有高额抽成的。国家在刘翔身上投的钱,早就百倍千倍的赚回来了。也许你们小区的
体育设施建设资金里面就有刘翔的一份功劳。他不欠你一分钱。我就不理解,怎么刘翔一退赛,好像他欠了你们祖宗十八代的债一
样。

我看的最绝的评价是:

引用

刘翔的确不懂事,大家买了豁贵的票来干嘛地?不就是来单捧你的场嘛,谁要看你跑了,大伙都说了你哪怕出来走一圈都可以。伤
了不能跑就拿话筒献唱一首嘛,实在不行拿个大顶说不定也能逗众位爷一乐,今儿个算是亲眼见到刘翔用手跨栏了。

第 264 / 283 页
http://robbin.javaeye.com 5.23 关于刘翔退赛的四个不理解

刘翔退赛只是运动员个人的一个行为而已,没必要大惊小怪的,怎么一个运动员退赛搞出来这么大动静?

第四个不解:

刘翔赛前虽然也一直说有伤,但是都是说大腿拉伤,已经差不多好了。新闻媒体从来没有透露他的跟腱有这么严重的伤病,即使到赛
前三天突然严重了,以致于无法完成训练这种程度。那么我觉得新闻媒体有责任披露出来。现在的问题就是:当时为什么没有披露?
这么严重的伤病,为什么赛前要封锁消息?为什么不让公众有知情权? 是谁决定要封锁这个消息的?是孙海平,是田管中心,还是中
国奥运代表团?

第 265 / 283 页
http://robbin.javaeye.com 6.1 JavaEye1.0的老路是行不通的

6.1 JavaEye1.0的老路是行不通的

发表时间: 2007-02-27

JavaEye1.0时代就只有论坛这一种形式,每天手工删除和程序自动删除超过一半的帖子,那剩下来的自然质量要高很多。当时我写的
程序设定的标准是超过7天的主贴跟贴不到4个,点击不足200个的非精华贴非高级会员发贴统统删除,但是这种方式人道吗?

过去每天发贴量只有100-200,现在每天发贴量达到1000贴,从高质量帖子的数量来看,显然是现在比过去多得多,只不过没有自动
删贴制度,比例下降了而已。现在如果想看那些质量高的文章,应该去文集频道,专栏频道,这些都是挑选出来的高质量文章。相当
于过去自动删除帖子之后剩下的文章。如果还拿过去的标准要求现在的论坛,是不合适的。

JavaEye在04年05年确实有一些比较火爆的帖子,但是要看到当时的时代背景:EJB2逐渐被人唾弃,Hibernate/Spring强势崛起,
CMM开始被骂,敏捷开发在国内悄悄普及,AJAX技术也在Google推动下一夜成名。从整个Java行业来说,那几年可以炒作的体裁很
多,可以争论的话题很多,观点的冲突很多。这在客观上造就了论坛的火爆。

但是进入05年底以后,整个Java行业特别是Java开源社区就陷入了沉寂,近两年以来都没有什么足够的兴奋点,再加上原来那些观点
该讨论的早就讨论清楚了,实在没有什么可争论的地方了,论坛的争论话题陷入枯竭。

其实JavaEye老论坛在进入2006年以后,已经大幅度下滑、越来越衰落了。靠严格版规,铁腕删贴,和屈指可数的几个牛人撑门面的
网站运营方式在JavaEye起步阶段可谓屡试不爽,非常有效。但是到了后期已经越来越跟不上形势了。

因为这个时期Java整个社区已经沉寂很久了,客观上没有多少值得讨论的话题,而主观上JavaEye上面活跃的那些牛人经过一段很短时
间的磨合,就迅速在所有的主要观点上达成了一致,再也没有什么可争论的地方了。这种情况下话题本来就枯竭了。而且这些活跃
的、在所有主要观点达成一致的人们在客观上又形成了一种话语霸权,使得论坛无法存在不同的声音,无法容纳新来的会员发表不同
的见解。使得论坛也很难吸收新鲜血液,越来越死气沉沉。

任何网站都是这样的,想靠一招鲜就吃遍天是不可能的。JavaEye如果沿着老路走下去,到2006年底就得完蛋!所以开发JavaEye2.0
从很大程度上来说是一种自救的行为。如果再不思变,JavaEye只有死路一条。于是我下定决心开始动手开发JavaEye2.0版本。

另外,即使是JavaEye的活跃老会员,也未必对我的独裁删贴制度就没有积怨。在我们埋头开发JavaEye2.0的时候,这些矛盾终于集中
爆发出来。某个JavaEye老会员连续多次在JavaEye论坛发表对XX公司的不当言论,激起了公愤,于是我删除了这些帖子。随后这个老
会员在另外两个对我独裁删贴制度积怨已久的老会员的挑拨下,误会我是为了讨好XX公司才删他的帖子,终于和JavaEye反目成仇,并
且他们联合起来,以我长期施行的独裁删贴制度为攻击口实,不断私下拉拢其他JavaEye老会员。还炮制出来XX公司要收购JavaEye的
谣言。好在这个时候JavaEye2.0就上线了,否则后果不堪设想。

这些事情说明了什么?虽然大家还在津津乐道以前的独裁删贴制度,津津乐道以前某几个高手激烈辩论的场景。但是铁的事实证明了
JavaEye那套老办法已经维持不下去了,甚至连一些核心的老会员都已经对这套管理制度积怨甚久,而这些老会员之间观点太统一了,
实在也争论不起来什么话题了。

时代总是在进步的,网站也罢,会员也罢,制度也罢都要与时俱进,老办法已经行不通了,就只能求变。从JavaEye2.0网站一开始起
步,我就在有意识淡化个人的影响力,淡化牛人特权,引进民主,鼓励所有人共建。

我选择走这条路一点都不后悔,虽然现在网站特别突出的牛人少了,但是一批有一定影响力积极贡献的牛人们却成倍增多了;虽然激
烈的观点争论少了,但是踏实务实的技术文章却成倍增多了;虽然我个人影响力越来越小了,但是群体的影响力越来越大了。

第 266 / 283 页
http://robbin.javaeye.com 6.1 JavaEye1.0的老路是行不通的

长尾的头部不应该是少数几个牛人,而应该是技术水平中等偏上的一大批人,如果把网站的长尾头部定位在某几个牛人身上,那网站
本身生存危机就太大了。

其实过去那些貌似精彩的辩论真的那么有实用价值吗?十几人几十人撸起袖子纷纷参战,刀光剑影的场面确实令人兴奋,也很吸引眼
球,但是你现在再回过头去看那些文章,你还能有当时的感觉吗?出于想要整理精华文集的目的,我曾经大致浏览了很多当时的精彩
辩论,老实话,现在再看过去,很多文章现在看来都挺幼稚的,包括我自己的文章。不是因为自己水平怎么提高了,实在是口水太
多,干货太少。

第 267 / 283 页
http://robbin.javaeye.com 6.2 绝对不虚此行的活动 - 记Gavin King上海交流研讨会

6.2 绝对不虚此行的活动 - 记Gavin King上海交流研讨会

发表时间: 2007-04-19

本次活动举办的两天前,我突然接到Red Hat通知,Gavin King由于身体不适,在北京演讲状态不佳,将取消上海的演讲,只回答听众


的提问。随后将Gavin King自己写的请求取消演讲的Email转发给我看了。我心里这一沉,又是周四下午的活动,Gavin King又取消演
讲,这次完蛋了,所以随后的会务筹备工作,我基本上也没有怎么去做,预计能来50个人就不错了。

事实上今天下午最终来的人也不多,以我目测来看,可能也就100人上下。然而令我意外的是,下午1.30 Gavin King到达现场的时


候,身体状态显得非常不错,而且要求主动进行演讲,这令我和晓钢赶紧商议更改预定的流程。

以前在TSS的视频里面看过Gavin的演讲,紧张,语速快,表达能力差。但今天现场演讲大家都看到了,演讲能力非常棒!现场反应也
够灵敏,估计这哥们也是这两年到处演讲给练出来了,确实让人刮目相看。

Gavin的演讲当中也不忘抨击了两句springframework,当然问题也说到了点子上,spring不使用OpenSessionInView的时候,确实处理
lazy集合初始化在session关闭以后的问题很棘手。Gavin说EJB3没有这个问题,这引起我想试试EJB3的兴趣。

随后的提问环节,JavaEye的Allen Young小朋友抛出来一个尖锐的问题,直接问Gavin怎么看RoR的AR的CoC?Gavin同学的反应意料之
中也意料之外。说意料之中是Gavin同学强烈的表达对RoR的鄙视,说意料之外是Gavin立刻演示了一下annotation在默认配置情况下简
短写法,以证明Hibernate已经CoC了。虽然这个问题值得商榷,但现场Gavin的回答和表现绝对一流,让我这个会议组织者非常满意。

也许是因为Gavin的高水平表现让我原来预期砸锅的会议相当的精彩,导致我在自己的演讲环节有点心不在焉,大失水准。头一次在演
讲当中拖了后腿。

晓钢演讲过程中,我抽空让Gavin把书全部签了名。晓钢演讲之后,Gavin的现场抽奖环节也非常棒,看的出来,很多中奖者相当兴
奋,得到Gavin亲笔签名的书,还现场在讲台和Gavin搂搂抱抱的合影。最后会议结束后,很多人依然冲上去和Gavin同学搂搂抱抱,亲
密无间的合影。

不得不说,不是每个来到中国的外国专家都这么平易近人的,至少多次来中国的Martin Folwer是一个相当严肃的英国人,想和他合影
是很困难的,至于搂搂抱抱根本没有可能。我想,也许是因为Gavin本来就很年轻,和我们很多人同龄的缘故吧。当然,以Gavin在社
区闻名的火爆脾气,现场如此平易近人,笑容可鞠,令我很感到非常意外。

因为我晚上还要到外地出差,会议结束后就立刻离开了。现在在宾馆写这篇报道。今天拍照的曹晓钢,刘江大概还在陪Gavin吃饭呢
吧,你们等他们明天把照片贴出来吧。
附件下载:
• Hibernate性能调优.zip (148.4 KB)
• http://robbin.javaeye.com/topics/download/bd89c12e-df37-4185-8ebf-c35db63a886c
• 描述: 我的演讲内容

第 268 / 283 页
http://robbin.javaeye.com 6.3 闻之色变的“网站改版”魔咒,从豆瓣改版说起

6.3 闻之色变的“网站改版”魔咒,从豆瓣改版说起

发表时间: 2007-11-19 关键字: 网站改版

话说这网站改版就像站长的“滑铁卢”一样,无论网站多有名气,站长多么英明,倒在“网站改版”魔咒之下的,还真是不计其数。

2006年5月,老冒领导的uuzone改版。uuzone是国内做的最早的,最web2.0化的SNS网站了,改版之后网站访问量急剧下跌,
uuzone只得让新旧两个网站版本并行使用,然而并没有挽回网站下跌的颓势。

2007年9月,横戈领导的blogbus改版。blogbus是国内最早的博客网站之一,改版之后,用户批评意见四起,横戈在博客里面深刻检
讨。

2007年11月,豆瓣改版,这次阿北也未能免俗,一样中招。豆瓣的用户在改版之后民怨沸腾,甚至开始纠集起来倒版,威胁网站把导
航方式改回原来的样式。由于豆瓣在互联网的知名度,顿时沸沸扬扬起来:有铁杆支持阿北者如和菜头,破头大骂倒版的“垃圾用户”;
有幸灾乐祸者如麦田,推断豆瓣越来越天涯化,真可谓一地鸡毛。

“网站改版”就像站长的梦靥一般,不改版迟早是个死,改版那死的更快。作为JavaEye网站的站长,我确实有点感同身受,改版被用户
骂还真是很委屈的一件事情:费了老鼻子劲,冒了多大风险,付出多大代价,千辛万苦把网站改了一遍,运行速度更快了,代码更干
净,bug都修复的差不多了,网站布局更加合理了,页面更加美观了,功能更加强大了,咋用户就是不买账呢?辛辛苦苦的劳动白费了
不说,还被人骂,我委屈大了我。

换个角度,作为一个普通的网站用户来说,对于网站改版予以抵制,很可以理解,很大程度上出于用户养成的使用习惯问题。拿我来
说吧,经常看新浪网的NBA专题,这前几周NBA专题改版了,我一下就懵了,懵了好几天才适应新的版本。再说Google Analytics也是
我常用的Google服务之一,Analytics改版之后长达三个月之内我还一直使用老的版本,迟迟不愿使用新版本。所以说,改变用户的使
用习惯,对于网站来说,是非常忌讳的一件事情,但是改版还是得改呀,怎么办?

最近我们JavaEye网站也在面临着改版,从JavaEye2.0改版到JavaEye3.0,鉴于这么多英明神武的前辈都中了招,小弟我也是万分惶
恐,日夜惴惴,唯恐中招。如何避免网站改版带来的负面影响,我觉得横戈总结的四条可谓金玉良言:

1、升级或新产品上线之前,不仅仅要做好充分的内测,有条件的话要搭建系统进行公测;
2、任何时候,都应该重视用户的使用体验,而不应完全从技术角度考虑;
3、新功能推出之前,应做好充分的说明,否则会让用户无所适从;
4、不要同时推出太多改动,分阶段推出产品的改进效果会更好;

其实大部分网站改版都是败在忽视这几条之下的。JavaEye网站在2006年9月也进行了一次成功的改版,回顾这次改版,我觉得成功的
原因在于以下两条:

1、JavaEye1.0只是一个论坛,而JavaEye2.0变成了一个综合性社区网站,只要JavaEye2.0的论坛部分保持和1.0一致,改版就不会遭
到用户强烈的反弹。在JavaEye2.0的开发早期,我们的程序员曾经想按照功能更加合理的discuz!的样式开发2.0的论坛,但是被我阻
止,我要求程序员必须原样复制phpBB样式的论坛,确保用户使用习惯的一致性。最终JavaEye2.0上线的时候,尽管网站代码是全部
使用RoR重写的,但是论坛完全可以和原来的phpBB以假乱真,连我自己都难以分辨。这样用户对于改版很自然就接受了。

2、在JavaEye2.0的开发过程当中,我们是把2.0放在网站上面一直公测的,让用户提前接触和使用JavaEye2.0,这样在真正上线的时
候,就不再有特别陌生的感觉,对于改版就不会过分抵制。

第 269 / 283 页
http://robbin.javaeye.com 6.3 闻之色变的“网站改版”魔咒,从豆瓣改版说起

然而对于我们目前从JavaEye2.0到JavaEye3.0的改版来说,同样的成功经验是不可复制的。2.0已经是一个综合性、比较完善的网站
了,无论怎么改,都会让用户产生不适应的感觉,而不可能像1.0到2.0那样从无到有的方式。另外对于一个JavaEye3.0的公测版本,
由于2.0本身有着丰富的内容,除了少量用户之外,大部分用户并没有兴趣经常去访问3.0的公测版本,那么怎么成功改版,避免改版
魔咒呢?

Google analytics是新旧两个版本并行,但是这个方式并不能够完全消除用户的不适应感,我的灵感来自于横戈提到的第四条:

4、不要同时推出太多改动,分阶段推出产品的改进效果会更好;

对,分阶段推出产品的改进,一点一点的改进网站,而不是从2.0一下跳跃到3.0。在2.0网站的基础上面一点一点改版,一点一点加功
能,让用户在不知不觉的过程当中实现了从2.0到3.0的改版迁移过程。如果说传统的网站改版,是让用户在一夜之间适应新版本的
话,那么分阶段改进就是用户在长达两三个月的时间内一点一点适应新版本。

因此从10月份开始,我就拟定了新的网站改版计划,JavaEye2.0的改版和JavaEye3.0的开发计划同时并行:JavaEye2.0现在的网站功
能一点一点的改进,不断向JavaEye3.0的功能和界面靠拢:在已经过去的一个多月时间里面,我们已经上线了原来3.0的新闻频道,改
进了网站的一级导航,和新闻频道的二级导航,发布了第一个新闻频道的专题栏目,论坛的回贴投票机制进行修改,接下去我们的博
客功能还要大幅度扩充,博客频道还要彻底改版,一点一点,在我们JavaEye2.0的代码基础上,让功能和界面一点一点往3.0的目标上
面靠近。

与此同时JavaEye3.0根据原定的目标来开发,但是同时根据JavaEye2.0改进的用户反馈情况不断进行相应的调整。最终我们希望做
到,除了知识库频道是在3.0才上线之外的绝大部分功能在2.0的代码基础上全部修改到位,最终到明年春节真正把代码迁移到3.0的时
候,让用户感觉不到网站发生了改版。这样做的好处,除了保证了改版的成功,也可以提前几个月把新版本的功能让用户使用,在用
户使用的过程当中,你才能发现你设计的新版本功能究竟是不是用户需要的功能,如果不是,那么通过你的投石问路,你也能够清楚
的把握用户的需求,从而做出适当的调整。

这是一个非常稳妥的网站改版方案,也许有人会说,那你2.0一点一点改完之后,你开发3.0还有什么意义呢?工作不是重复了吗?其
实工作并不重复,因为在我们2.0的改版过程当中,也不断把3.0实现的新功能迁移到2.0上面来,例如接下来的编辑器切换和自动保
存、重写的博客导入功能。当然最重要的在于,3.0的代码是在一个新的架构上进行设计和开发的干净的代码项目,可以提供更高的性
能,更好的代码维护性,未来更好的功能扩充性。

JavaEye2.0改版到JavaEye3.0的成败我觉得系于两点:

1、JavaEye2.0能在多大程度上实现3.0的既定功能和界面改进
2、JavaEye3.0能在多大程度上保持和2.0一致的界面和用户操作方式

我相信,只要把这两点把握好,我们会再一次迎来成功的JavaEye网站改版。

第 270 / 283 页
http://robbin.javaeye.com 6.4 JavaEye新版本上线以后性能还不错

6.4 JavaEye新版本上线以后性能还不错

发表时间: 2008-01-09

在08年元旦新版本上线以后,我们一直忙着修改bug,调整功能和UI,这个版本真正要达到令用户满意的程度,估计要到春节的时候
了。

新版本的性能还不错,目前网站访问量也一直在缓慢上升。查看了一下昨天的访问日志,Ruby处理的200 OK的动态请求有71万多,排
除5万的RSS订阅请求,和一些搜索引擎的请求,估计昨天真实的用户访问量也应该差不多达到了60万PV了,当然这还没有计算有可
能被缓存掉的静态页面。整个网站有95%以上的动态请求处理时间都在0.5秒以下,还不错,挺满意的。

另外统计下来数据库平均每秒发送SQL为103条,这比JavaEye2.0平均140条下降了不少,也证明我们目前代码的缓存效率更好了。从
memcached的统计来看,缓存命中率为87%,相当不错,比JavaEye2.0的将近80%的缓存命中率又提高了不少。平均每秒发送338次
缓存查询,比数据库还频繁3倍多,缓存顶上一个数据库了。

lighttpd统计出来的traffic来看有所下降,JavaEye2.0的时候,平均每天web端口流量超过了23GB,现在网站web端口平均每天流量下降
到19GB。这主要是因为新版本的页面代码全部使用div+css布局,页面大小减少了很多,另外JS和CSS也进行了必要的瘦身。因此整个
网站的traffic下降了20%左右。

第 271 / 283 页
http://robbin.javaeye.com 6.5 关于JavaEye网站未来发展的思考

6.5 关于JavaEye网站未来发展的思考

发表时间: 2008-03-21

曾经有好几次用户发贴调查软件开发者经常访问的网站,每次调查的结果都大同小异,绝大部分用户平常只访问两到三个网站而已,
多的也不超过五个网站。我觉得这是一个很有意思的现象:

一般说来,软件开发者平时上网的时间都极长,除了上班8小时上网以外,晚上在家也经常泡在网络上面,很多人一天上网超过12小
时也不算奇怪;更有甚者,很多人一天到晚都需要泡在网上,如果不能上网,简直就无法正常工作了,比方说我就是这样的典型。

但是对于这样一个每天泡网时间这么长的用户群体来说,为什么访问的网站这样少呢?以我自己为例,除了工具性质的Google以外,
我每天上的网站也仅仅只有JavaEye和新浪而已,其他网站都仅仅在需要的时候用一下而已,像我这样的典型用户在软件开发者群体当
中普遍存在。

原因我觉得是因为人的精力是有限的,网络生活的展开不是发散型,而是逐渐趋于收敛的。虽然整个互联网网站的数量不断在稳步增
加当中,但是作为一个用户个体,他每天访问的网站并不会同步增加,而是始终收敛于二三个网站当中。但作为他经常访问的那几个
网站,他对网站的需求是逐渐趋于多样化的,希望网站不断能够提供更多的功能来满足他网络生活的多种需要。

现在JavaEye网站已经成为很多软件开发者平时网络生活所依赖的网站,为什么我们不把它做得更好,让用户用的更爽呢,牢牢的粘下
去呢? 因此我觉得JavaEye网站应该成为为软件开发者提供全方位服务的网站,或者用一句庸俗的话来说:软件开发者的网络家园。

就我自己的感觉来说,每天用Gmail收发邮件,用Google Reader阅读RSS,上新浪看一下时政要闻和体育新闻(曾经订阅新浪新闻
RSS,结果被信息轰炸的无法阅读),然后就是泡JavaEye了,但问题是JavaEye无法给我提供每天超过10小时的网络消磨方式,换句话
来说就是:JavaEye还不足以承担网络生活家园这样一个目标。那么JavaEye要如何去做才能够达到这样的目标呢?我觉得需要分三个
阶段来达到:

第一阶段:以提供内容为主、扩大网站内容的来源和方式

无论web1.0还是web2.0,只要不是Google那样的工具型应用、facebook那样的SNS应用、以及网络游戏,那么高质量的内容永远都是
网站的核心吸引力,别人到你这个网站来就是因为有他需要的内容。因此需要解决的问题无非是:

1、如何产生高质量的内容
2、如何有效的整理和展示这些内容

目前JavaEye网站提供了“新闻”、“论坛”、“博客”和“圈子”这四种内容展示的方式,并且通过博客、论坛以及圈子的融合来打通应用之间
的隔离,此外还通过全文检索来实现内容之间的关联性。但是我觉得这还远远不够,因此在JavaEye3.0的版本当中我们还将提供另外
四种内容展示的方式:

1、知识库
知识库可以提供真正结构化的内容、可以有效的归纳和整理知识、提高信息阅读的质量和有效性,知识库也是可以在很大程度上弥补
论坛信息杂乱的一种很好的内容展示方式。当然我们仍然会通过全文检索的机制,让知识库的内容和其他类型的内容形成有效的关
联,而不是割裂开来。

2、招聘频道

第 272 / 283 页
http://robbin.javaeye.com 6.5 关于JavaEye网站未来发展的思考

招聘的内涵其实非常丰富,比方说如何进行职业生涯的规划、如果进行面试和笔试、常见的各种面试试题、应聘技巧这些知识性的招
聘内容既是知识库的内容,同时也是招聘相关的内容。此外针对招聘者来说,公司黄页可以帮助他们了解公司的信息、个人简历展示
可以帮助公司了解人才的信息。招聘内容的建设可以极大的丰富JavaEye网站的内容吸引力。

3、问答频道
论坛并不是一个很好的提问解答途径,特别是JavaEye网站的论坛定位在交流为主,版规严格的情况下,并不利于提问解答这一基本需
求的满足。因此,在保持论坛高质量的前提下,为了鼓励用户使用JavaEye网站,我们将提供另外一种形式的内容,即类似百度知道的
问答频道,并且和知识库结合起来,专门面向求解答案的用户。

4、精华频道
网站的核心竞争力在于高质量的内容、其实还有一个潜在的台词:高质量内容可以有效的树立一个网站的品牌和形象。随着2006年9
月JavaEye2.0的上线,精华内容的产生渠道就已经相当分散了,用户不能够快速有效的从JavaEye整个网站每天的新闻、论坛、博客、
圈子、以至于知识库、招聘和问答当中挑选出来真正的精华内容。于是对精华内容有偏执癖好的人来说,我们需要这一个精华频道,
不求内容丰富,但求内容篇篇精华,可以咀嚼良久,余音绕梁。

JavaEye3.0版本要完成的使命就是实现第一阶段的目标,建设完善的以内容为核心的综合性技术网站。今年上半年JavaEye的开发任务
就是上面这四个新的频道上线,以及现有功能的不断完善和优化。并且希望JavaEye网站的页面访问量可以从目前的每天70万,提高到
至少每天100万以上。

第二阶段:以用户交互为主、提高用户交流的质量和频率

实现第一阶段的目标也只是成为一个不错的技术网站而已,并不能成为软件开发者的网络家园。许多人之所以愿意整天泡在一个网
站,并不单纯因为内容吸引人,从深层次的原因来说,是他熟悉了这个网站上面的人,他有和这些人进行交流的实际需要。

用户之间交流的信息质量是和用户之间的熟悉程度成反比:如果两个人之间很陌生,一定是通过他写的高质量文章吸引了你,让你对
他有所了解,产生了和他交流的话题和欲望;但是如果两个人之间很熟悉的话,交流的内容往往不是什么高深的技术话题,而是拉拉
家常。所以高质量的内容仅仅是把软件开发者们拉到一起来进行有效交流的纽带,而一旦用户之间建立了密切的关系之后,维系他们
的主要不是高质量内容,而是交流的场所和交流的形式。

所以我们看到一种奇怪的现象,很多老会员可能平时并不经常发言,但是他会经常泡在JavaEye的海阔天空版,因为对他们来说,高质
量的文章不是最吸引他们的地方,而是活跃在JavaEye的这些id和他们进行交流,这才是驱使他们泡JavaEye的理由。但很遗憾的是,除
了在海阔天空交流场所进行灌水的交流形式之外,会员们找不到其他更加有效的交流场所和交流形式了。因此JavaEye第二个阶段的主
要目标是提供丰富的用户交流场所和交流方式。因此JavaEye需要借鉴facebook网站,开发更好的用户交流功能:

1、提供用户个性化信息聚合页面
类似用户一登陆facebook就可以看到各种和他有关的信息的profile页面,那么我们能不能够做到,用户点击页面右上角的“我的个性化
网站”链接以后,看到用户自定义的各种信息的聚合呢?比方说哪些人回了他的帖子、他关注的哪些高手发表了什么新的言论、他的某
某好友推荐了什么内容等等,一目了然。

2、休闲交友的小应用
平常好友之间交流缺少的不是话题,而是一个“引题”,不在乎交流的内容,但是需要有个东西来引导大家进入交流的场景。所以你如果
想和某个久不大招呼的朋友聊天,上来说“Hi,你吃了吗?”,其实你并不关心他吃没吃,只是你需要一个“引题”而已。制造引题的小应
用有很多很多方式,只要看看facebook上面很受欢迎的小应用,就知道应该怎么做了。比方说facebook上面有一个小游戏是吸血鬼游

第 273 / 283 页
http://robbin.javaeye.com 6.5 关于JavaEye网站未来发展的思考

戏,你咬更多的人你的等级就越高,高等级的吸血鬼还可以组织自己的军队,和朋友进行战斗,很简单的互动就可以让你和朋友保持
不间断的联系。

3、提供更加多样的交流方式
可以不仅仅局限于网页上面的交流,开发好友之间的基于IM、浏览器插件、AIR甚至IDE插件,把用户关心的信息直接推送到用户的桌
面。

第二个阶段的功能开发和运营则是今年下半年的主要目标。只有达到了这一目标,JavaEye网站才能真正具备足够的吸引力和强大的竞
争力,才能真正发展成为一个规模足够大、能够支撑起来商业模式的技术网站。

第三阶段:以开放性为主、提供API,增加网站向外的信息整合能力

互联网未来的发展趋势一定是网站之间的互相共享资源与合作,而不是像国内目前这样大家死把着自己的用户和内容,唯恐被别人偷
去了。我相信JavaEye如果能够实现第二阶段目标,并且成长为行业内数一数二的大网站以后,就应该有一个更高的目标:整合行业网
站资源,引领网站开放和合作的潮流,事实上facebook已经给所有人树立了一个高大的榜样。

这第三个阶段则是JavaEye明年以后要努力的方向了,粗略的展望一下,我觉得应该做到这样两点:

1、网站平台化,向外开放API
让用户能够自行开发应用扩充网站的功能,特别是面向软件开发者的网站,技术门槛并不是问题。如果网站只能够是用户提出需求,
然后站方开发功能,实在有些无趣。想像一下用户自己开发应用,给网站添加功能,自己改造自己的个人空间是多么有意思的事情。

2、网站聚合化,把外面信息聚合进来
这包括两个方面:聚合个人博客,聚合小型网站。比方说很多人更喜欢自己购买域名租赁空间架博客,但是他的博客流量很低,不能
参与到一个大的技术交流圈子里面来。那么我们能不能够通过API接口,让用户自行编程把自己的博客以某种形式聚合到JavaEye网站
上面来呢?对于小型网站也是这样,能不能让小型网站以某种方式整合到JavaEye网站的平台上来呢?双方合作的好处就是小网站可以
获得大网站的平台资源,可以获得流量,而大网站更加平台化,能够整合更多的资源,变得更加强大。

如果能够最终实现第三个阶段的目标,JavaEye会具备滚雪球般的自我发展能力,能够真正的在竞争当中立于不败之地,能够真正成为
令软件开发者所每天依赖的那个网络家园。

第 274 / 283 页
http://robbin.javaeye.com 6.6 总结一下大家对JavaEye网站发展计划的建议

6.6 总结一下大家对JavaEye网站发展计划的建议

发表时间: 2008-03-25

前面一篇博客文章,我谈了一下JavaEye网站今明两年的发展战略,其实写这篇博客文章的主要目的其一是整理并且系统化自己考虑了
很久的想法,并且将其记录下来;其二是将这个战略构思分享给我的两位partner,因为我觉得写下来会比我空对空说话印象更加深
刻;其三就是把这个战略构思分享给大家,看看大家会有什么反应。

有点出乎意料,大家对于这篇文章的反应很热烈,也提了很多好的建议和想法,我试着总结和归纳一下,作为勉励我们继续把JavaEye
网站做好的鞭策,同时也回答一下大家的一些问题:

一、JavaEye网站的商业模式是广告和招聘

很多人关心JavaEye网站靠什么赚钱呢?其实在过去四年多时间里面我也在一直摸索,但是现在我可以回答大家,就是广告和招聘。能
够把这两项业务同时做好,对于我们这样一个小网站小公司来说,已经非常赚钱了,我并不指望融资和上市,这不是我能力之所及
的。

一些朋友建议我们推出软件外包频道,并且认为这是一个很有前途的商业模式。的确现在有很多威客模式的网站,但是软件行业有其
特殊性,在线外包在这里几乎走不通,有兴趣的可以看看JavaEye的两个接私活的讨论,所谓“珍惜生命,远离外包”,即便从软件开发
人员的职业生涯角度来说,我也不建议大家接私活,更不要说JavaEye做这种连我自己都不认可的事情了。

私活就那么难搞定吗?
都别装了,难道你们不想拉私活?

二、网站要在产品细节方面多下功夫、努力提高网站的易用性,追求更好的用户体验

比方说JavaEye博客还有进一步改进的余地、论坛的规则也可以增加一些人性化的提示、以及网站每个角落的功能点都应该精益求精的
改进,突出三个要点:简洁、易用、人性化。

从JavaEye2.0版本开始,我们一直朝着这个目标在努力,并且到目前为止还取得了不错的效果。特别是今年元旦新的版本上线以后,
大家一致好评,网站的流量也在稳步上升,到最近两周,JavaEye网站每天页面访问量已经突破80万(周末50-60万)。因此产品改进是
我们不断追求的目标,我们希望JavaEye最终不要像传统的门户网站那样用户体验糟糕,广告满天飞,而是一个偏web2.0风格的、清新
自然、简洁易用、让人有亲近感的网站。

三、追求高质量的专业内容是JavaEye永远的核心竞争力

我看有些人表达了这方面的担忧,不过好在我们头脑很清醒,不会犯这种错误。精华频道和知识库频道就是我们隆重推出,突出强调
专业内容、高质量内容的功能,坚持精品战略是JavaEye的核心竞争力。

即便有了这两个频道,我们也不会丝毫放松对论坛发贴回贴质量的要求,而是一如既往的坚守论坛高质量讨论的底线。也许有些朋友
对严格的要求有些丧气,不过问答频道就是为入门级别的朋友准备的,我们希望有效的分流一部分这方面的需求,以保证各种层次的
用户和谐共处。

第 275 / 283 页
http://robbin.javaeye.com 6.6 总结一下大家对JavaEye网站发展计划的建议

四、回答一些相关的问题

1、JavaEye不打算发起开源项目、不打算提供SVN托管

我们目前只有三个全职的创业人员,其中全职写代码的只有一人,没有这个精力做这件事情。但我们会利用JavaEye这个平台帮助优秀
的开源项目作者宣传他的项目,提供在线资源,比方说GT-Grid、庖丁分词等等。至于SVN,为什么不在Google Code,Java.net,
Sourceforge上面开呢?有生命力的开源项目一定要融入全球开源社区,局限在国内的开源项目不会有前途。至于说到组合流行的框
架、提供整合的解决方案,其实并不需要发起啥开源项目、只要在知识库里面提供丰富的框架指导性文档和示例代码就已经足够了。

2、JavaEye扩展内容需要循序渐进

JavaEye网站要成为全面的软件开发者社区,从目前来说在移动平台开发、数据库开发、操作系统和底层开发方面存在不足。我们也希
望能够面面俱到,但是需要时间的积累和内容的积累,慢慢来吧,总会有那么一天的。

3、JavaEye会逐渐增加一些个性化和SNS的东西

我在战略里面不止一次提到了facebook,到不是说JavaEye要转型搞SNS,而是facebook这种以人际关系组织的网站功能很值得我们借
鉴,他的一些工具恰好可以弥补JavaEye网站在交流方面存在的不足。我们希望做到的三步是:第一步个人信息聚合、第二步是通过应
用来实现交友互动、第三步是个性化的推荐。

4、开发API是一个远期目标

关于开发API,看来大家都有不少创意。但这是JavaEye的远期目标,因此我没有特别清晰的路线图,而只是一个模糊的想法,这要随
着JavaEye网站顺利完成前两个阶段的任务以后,根据到时候的形势来随机应变了,当然大家也可以随时贡献一些创意。

第 276 / 283 页
http://robbin.javaeye.com 6.7 以无法为有法,以无限为有限

6.7 以无法为有法,以无限为有限

发表时间: 2008-03-28

以无法为有法,以无限为有限 --- by 李小龙

关于JavaEye网站未来发展的思考当中分析了一种现象:用户经常泡的网站会逐渐收敛到两三个,不会超过五个。如果深层次的探究下
来,即便在一个网站内部,用户经常泡的功能也会逐渐收敛到两三个,不会超过五个。虽然在战略方面来说,JavaEye以后会做很多很
多功能,但基本原则就是:功能可以五花八门,但是所有的功能都是为同一个目标服务的,目标不能多,不能发散。

我每次看CSDN网站就觉得心浮气燥,很有挫折感,望而生畏,为什么呢?其中一个原因就是CSDN提供了太多功能了,想要实现的目
标实在太多了。他要做下载、他要做开源、他要做项目外包、他要做视频远程教育、他还要做图书评论、他还要做招聘,他还要做
SNS,如此多的目标导致了纷繁复杂、并且彼此独立的功能点。让你面对这样一个庞然大物产生了心理压迫感和畏惧,没有信心去掌
握这个网站的使用方法。

JavaEye的目标简单而清晰,对于非登陆会员来说,就是提供高质量内容,形式可以多样化,但是目标单一;对于长时间泡在网站上面
的登陆用户,我们是提供加强的用户交流功能;最后对于资深用户和重度用户,我们会开放API,让他们自己DIY。这样非登陆会员他
只看到技术文章就好了,不给他增加心理负担;登陆用户想多消磨时间的时候,给他更高级的应用,但不需要他自己开发那么麻烦;
最后重度用户连网站所有功能都不满足的时候,就自己动手来干,给他足够的灵活性。

总之,一个网站不应该越做越复杂,越做越分散;而应该越做越简约,越做越收敛。JavaEye网站为什么大家觉得用起来还比较舒适,
一个很重要的原因在于:JavaEye网站是收敛的,整个网站虽然功能已经挺多的了,但是整个网站是浑然一体的,所以不会给用户压迫
感。即便我们要做的知识库、精华频道也都是围绕同一个目标展开的不同形式,因此不会破坏网站的整体感。

像项目外包、开源项目托管、图书评论这些功能,每个功能都有他自己独立的目标,而且和我们网站现在的目标是不同的。因此这些
功能上线以后网站的整体感就被破坏了,网站的目标分散为好几个,用户就会立刻感觉到网站功能很复杂、网站不同频道的使用方式
不一致、使用起来有压迫感。

比方说豆瓣就是一个典型的例子,现在的豆瓣改版越改越让人看不清楚面目,越改越让人觉得网站复杂、庞大,难以亲近。究其原因
在于豆瓣要实现好几个不同的目标:既要做书评影评乐评,又要做SNS,还要做同城交友,还想做城市娱乐生活向导,想做的事情太
多了,就让用户无所适从了。

facebook又是一个特别典型的例子,他唯一的目标就是提供交流工具的平台,自身提供的功能极度的少,但是平台容纳能力又极度的
大,这才是网站的至高境界:化繁为简,以无招胜有招。

第 277 / 283 页
http://robbin.javaeye.com 6.8 用全文检索来实现JavaEye的垂直频道

6.8 用全文检索来实现JavaEye的垂直频道

发表时间: 2008-05-27 关键字: 全文检索

JavaEye网站给大家提供了多种多样的交流方式:新闻、论坛、博客、问答和知识库等等,但是如果你只对Java感兴趣,或者只对
Python感兴趣的话,却找不到相应的Java专区或者Python专区,不得不自己浏览网站的每个频道去寻找相关内容。这说明:除了用交
流形式来横向组织网站内容以外,JavaEye还应该提供一种按照技术门类纵向组织内容的方式:这就是JavaEye的垂直频道。

目前,JavaEye的垂直频道beta版本已经上线公测了,大家有兴趣的话可以访问:

http://java.javaeye.com

现在我们只是提供了Java、Ruby、AJAX和Agile等几个垂直频道,这些垂直频道的内容都是从网站各个频道自动提取出来的。也许大家
会问,JavaEye的垂直频道是怎么实现的呢?答案就是全文检索。

全文检索在web2.0网站中起到的作用非常大,除了大家都知道的全站搜索功能之外,全文检索在很多方面都可以发挥巨大的作用:

一、全文检索可以用来实现相关文章推荐

比方说JavaEye新闻就有相关文章推荐,JavaEye论坛帖子也有相关文章推荐,此外JavaEye问答频道问题也有相关问题,也许你提问一
个问题以后,并不需要别人回答,已经从相关文章当中获得了想要的答案了。

二、全文检索可以用来实现内容自动分类

比方说JavaEye博客频道首页的的内容分类,如果要求用户发表博客文章的时候手工指定自己文章的分类固然可以,但是会增加发贴功
能的复杂度,让用户选择一大堆框框才能发贴实在不是很好的用户体验。利用技术手段来改善用户体验正是优秀程序员的价值体现,
于是我们就是用全文检索来实现内容的自动分类。而这一点也被用在我们即将推出的JavaEye垂直频道上。

三、全文检索可以用来实现寻找好友功能

JavaEye上面的每个会员都会留下自己的轨迹:发贴,写博客,评论,对不同新闻和博客的投票,所有这些行为都可以用全文检索来建
立相关度,从而系统可以得知哪些JavaEye用户可能和你有相似的行为,而这正是SNS的基础功能之一。

JavaEye的垂直频道正是利用全文检索来内容自动分类的。具体做法如下:

我们可以根据一篇文章当中的索引词汇通过TF/IDF算法,查找这篇文章相关性最高的其他文章,这就是相关文章推荐的实现方式。基
于TF/IDF算法我们可以更进一步,用已知分类的文章作为语料库进行训练,提取该分类当中最重要的关键词汇,并且给每个词汇标记
不同的权重。建立这个关键词汇分类表以后,我们就可以用它来作为内容自动分类的标准,从而让程序可以自动挑选不同分类的文
章,就这样,JavaEye垂直频道就做好了。

第 278 / 283 页
http://robbin.javaeye.com 6.8 用全文检索来实现JavaEye的垂直频道

第 279 / 283 页
http://robbin.javaeye.com 6.9 用Google的网站流量分析系统来看JavaEye网站

6.9 用Google的网站流量分析系统来看JavaEye网站

发表时间: 2008-06-24

最近Google Trends提供了一项很有意思的功能:就是提供互联网网站的流量分析和趋势统计。它的功能有点类似Alexa网站的作用,但
是目前他提供的数据还比较简单,而且我们还不清楚Google Trends统计出来的网站流量数据究竟是怎么算出来的,当然我简单猜测一
下有可能来自Google Analytics,Google Adsense,Google Search以及其他第三方数据的修正。但不管怎么说,在alexa作弊盛行的今
天,多一个Google Trends肯定是更客观公正的评价系统,而且Google Trends提供了一些看起来很有意思的数据,让我们来看看
JavaEye的Trends吧:

JavaEye网站的流量分析

访问:http://trends.google.com/websites?q=javaeye.com&geo=all&date=all&sort=0

itpub是国内最大的数据库社区,不过被it168收购以后也有很多Java开发方面的内容。从图中来看,itpub这一年来的流量是明显下降
的,日访问者从超过3万下降到如今2万多一点,在2008年春节以后被JavaEye网站超过了。

第 280 / 283 页
http://robbin.javaeye.com 6.9 用Google的网站流量分析系统来看JavaEye网站

而访问itpub的人也经常访问oracle和bea的网站,这和itpub的数据库社区属性还是挺吻合的。而访问的关键词最多的是Oracle、tomcat
和eclipse,则说明社区的人主要是Oracle和Java的开发人员,不过“招商银行”这个关键词真有点怪?莫非说明itpub的人都喜欢用招行网
银吗?而看看CSDN则有民生银行和建设银行,莫非csdn的人更喜欢用这两个银行的网银?

不过对比几个国内的软件社区,JavaEye的访问者搜索关键词密度还是高度集中在技术词汇上面的,这也许说明上JavaEye网站的人还
是以比较严肃的交流技术为主的人群构成。

大家都可以试试看自己关心的网站,特别是看看访问这个网站的人还会上什么网站,以及这个网站的人都在关心什么内容。

第 281 / 283 页
http://robbin.javaeye.com 6.10 JavaEye生物多样性群落的思考

6.10 JavaEye生物多样性群落的思考

发表时间: 2008-08-02

robbin关于“劣币驱良币”观点的误区

这篇文章讲的很棒,是丁香园创始人之一写的,看了他的文章以后,我的一点点想法:

我非常同意你对我观点的批评,我们不应该不尊重入门会员,不应该把他们归为劣币这样一个词汇,我非常同意你的“生物多样性群落”
这样一个概念。但对如何构建这样一个多样性的群落,我有如下看法:

1、有一些论坛的坏习惯是必须进行严厉打击的,不管他是什么级别的会员,比方用故意吸引眼球的惊人标题党,比方说用自卑自残自
我可怜的词汇发贴,比方说为了顶自己的帖子拼命灌水。这样的行为会破坏论坛的整体的技术讨论氛围,不论任何人,一律严惩不
怠。当然由于高级别会员往往会比较自觉维护论坛气氛,很少违反这样的规则,因此看起来貌似对新手打压多一些,但实际上我们并
不会偏袒高级会员。

2、JavaEye实际上的确是定位于中高端技术人员的网站,因此从网站宗旨来说,并不是为初学者服务的,在这种情况下,过于初级的
问题在论坛遭到鄙视我觉得很难避免。但是我们已经在论坛开设了入门版,并且专门开发了问答频道,就是专门为这些入门级别的会
员提供的服务。我们希望这些会员可以更多的使用这些服务来满足自己的需要。目前我们的问答频道效果很不错,初步达到了预期的
目的。

3、对于一些老会员抱成一圈,比较排斥不同意见这种现象JavaEye是有的。特别是在2007年以前是相当明显的,但是自从2006年9月
我们网站改版并且扩大网站群体之后,特别是随着博客和圈子的访问量占据网站访问比例的逐渐提高,这种现象在逐渐的改善。我虽
然不敢说已经完全杜绝,但是我自己很少看到这种现象了。

4、现在JavaEye论坛频道占整个网站PV的比例已经下降到了30%不到一点。新闻频道、问答频道和博客频道的影响力都在不断扩大,
这是我现在不那么单纯只关注论坛的主要原因。

不过就像你说的,像我们这样的垂直社区最终要解决好生物多样性共存的问题,丁香园在这方面走在JavaEye的前面。所以我也特别期
待你的下一篇博客文章出来。对于这个问题,我经历过这样的探索过程:

1、 2006年的时候,我觉得要解决这个问题,应该提供多种服务,并不是每个人都喜欢泡论坛的,那些不喜欢泡论坛的人,我们要提
供他们感兴趣的服务,所以 JavaEye后来推出了博客、新闻、圈子、问答等等新的服务形式。从现在来看,效果还不错,因为论坛流量
下降到整个网站30%还不到。

2、 2007年的时候,我觉得要继续解决好这个问题,圈子可能是一个突破,对感兴趣的话题自己组织小圈子进行讨论,去中心化,就
像豆瓣小组一样,最终这方面的尝试效果不太明显。有可能是论坛的存在导致了难以去中心化。但是圈子频道在和厂商、出版社合作
方面现在发挥了意想不到的作用。

3、 2008年以后,JavaEye除了不断推出形式更加多样化的服务例如问答频道、知识库频道,以及将要改版的招聘频道、精华频道之
外,我觉得 JavaEye面临的问题稍微有所不同: JavaEye想占领的中高端软件开发人员市场基本上已经占领的差不多了,网站的成长遇
到了一个台阶需要跨越,经过我的思考,我认为需要从两个方面下手:

第 282 / 283 页
http://robbin.javaeye.com 6.10 JavaEye生物多样性群落的思考

1) 网站运营,这是最传统的手段,也是最有效的手段,随着我们招聘频道和精华频道的推出,网站运营的工作会全面铺开。

2) 适当的加强一点点用户交互方面的功能,在会员之间建立起来感情的纽带。

第 283 / 283 页

You might also like