一、那些云概念
一图胜千言,最近这两年大肆炒作的云计算本质上就是下面这张图。基础设施即服务(IaaS),平台即服务(PaaS)和软件即服务(SaaS)。
他们之间的区别和联系从下图的“食物链”上可以看出来,本质上都是对资源的管理和使其可供消费。
二、我对云计算的理解
先讲个段子,一位中国留学生去美国打工时当过报童,不带计算器,习惯动作抬头望天时心算找零。顾客大为惊讶,纷纷掏出计算器验证,皆无误,也抬头望天,惊恐问:云计算?该留学生茫然。有一天,一位面熟的老外向他打招呼,他望着天想了一会才叫出老外的名字,众人大惊:云存储?
上面这个段子,也从一定层面上反映出云这个概念的炒作性,以至于很多人忽略了本质,被各个厂商的口号忽悠过去,现在任何服务都想和云沾边。
再贴一个微博上的对联,@云计算风云:上联:云计算、云手机、云存储、云服务器、云杀毒、云办公、云优盘、云打印、云邮件、云输入法、云播放器、云游戏—云里雾里;下联:谷歌云、微软云、苹果云、脸谱云、亚马逊云、IBM云、百度云、阿里云、腾讯云、360云、搜狗云、华为云—不知所云;横批:神马都是浮云!
我对云计算的理解就是:平台开发商出售计算能力,且想方设法让这些计算资源可以方便的取得和管理;应用开发者按需消费所需要的资源/服务,架构于这样的平台上的应用也可以获得高可用高扩展的特性。
下面摘自wikipedia,列举了这三种类型的服务各自比较有标志性的厂商或产品
IaaS: Amazon CloudFormation (and underlying services such as Amazon EC2), Rackspace Cloud, Terremark, Windows Azure Virtual Machines,Google Compute Engine. and Joyent.
PaaS: Amazon Elastic Beanstalk, Cloud Foundry, Heroku, Force.com, EngineYard, Mendix, Google App Engine, Windows Azure Compute and OrangeScape.
SaaS: Google Apps, innkeypos, Quickbooks Online, Successfactors Bizx, Limelight Video Platform, Salesforce.com, Microsoft Office 365 and Onlive.
三、有人应该要问了我们在玩的OpenStack是什么?
OpenStack是为搭建IaaS平台服务的开源软件,让任何人都可以自行建立和提供云端运算服务,在我们这的作用是建立企业内部的私有云。如果我不关机OpenStack用到的技术细节的话,看上去就是虚拟化和装机。这步走出去成功以后,对我们的好处就是以后可以很方便的拿到一套产品的开发或运行环境。
四、技术层面的那些云计算资源
无论如何,下面这些服务都值得你点开链接,了解一下: Amazon EC2,Amazon S3,Google App Engine,appfog,engineyard,Heroku
五、使用Parse云环境编程
5.1 为什么选Parse这个平台呢?
1. 因为它是Gigaom网站评出来的2012年最值得关注的云计算新兴公司之一,他的模式和appfog比较类似,但是专注移动应用领域,除了Rest API还提供了Android和iOS平台的API,相对来说上手更简单,更适合我们这个Demo
2. 一个web应用除了部署环境之外,还有不得不解决的就是数据库存储的问题,这里我们想使用Parse做云端数据存储。
5.2 构建数据模型
理论结束,正式开始,在这里我想演示怎么做一个基于Cloud在线地址簿(with scalable possibility)
需求有两点: 1. 支持在线存储我自己的通讯录 2. 支持多用户注册登录,可以让别人也在线存储他们的通讯录
5.2.1 首先,需要在parse.com注册一个帐号,或者直接用你的Github帐号登录。
5.2.2 然后,登录后会定向到这个页面,https://parse.com/apps,选择”+Create New App”,填一个名字然后确定你的应用就创建成功了。
有了这个Application ID和 Rest Key其实就可以在线创建和存储数据了,Rest API 可以参考 https://parse.com/docs/rest#objects
这里很值得夸赞的是,示例代码里已经直接填好了你的app的ApplicationID和Rest API Key,基本上你就是拷贝下来,粘帖到命令行就可以尝试了。
5.2.3 考虑第一个需求,创建单用户版本的地址簿。

Note:请使用自己的ID和Key来执行下面的命令,这样才能在你刚才创建的应用的Dashboard里看到你的执行效果。
curl -X POST
-H "X-Parse-Application-Id: 5o93Gh8W63z2npIUErJvwwYz2IkpJIba6eL1ROAa" \
-H "X-Parse-REST-API-Key: E7Xg39e89nYjGhc1V0fXeukHMXOAo5SCkrQAgiKM" \
-H "Content-Type: application/json"
-d '{"name":"demo","cellphone":"13799998888","address":"No.1068"}' https://api.parse.com/1/classes/AddressBook
然后我们在网页上的管理界面的Data Browser里面可以看到刚刚通过Rest API创建的数据了

上面是创建数据的例子,下面列出增加,查找,删除,更新的全部代码
curl -X POST \
-H "X-Parse-Application-Id: 5o93Gh8W63z2npIUErJvwwYz2IkpJIba6eL1ROAa" \
-H "X-Parse-REST-API-Key: E7Xg39e89nYjGhc1V0fXeukHMXOAo5SCkrQAgiKM" \
-H "Content-Type: application/json" \
-d '{"name":"tomcat","cellphone":"13788889999","address":"No.1068"}' https://api.parse.com/1/classes/AddressBook
{
"createdAt": "2012-10-30T07:53:36.824Z",
"objectId": "8weFDfQ343"
}
curl -X GET \
-H "X-Parse-Application-Id: 5o93Gh8W63z2npIUErJvwwYz2IkpJIba6eL1ROAa" \
-H "X-Parse-REST-API-Key: E7Xg39e89nYjGhc1V0fXeukHMXOAo5SCkrQAgiKM" https://api.parse.com/1/classes/AddressBook/8weFDfQ343
{"name":"tomcat","cellphone":"13788889999","address":"No.1068", "createdAt":"2012-10-30T07:53:36.824Z","updatedAt":"2012-10-30T07:53:36.824Z","objectId":"8weFDfQ343"}
curl -X PUT \
-H "X-Parse-Application-Id: 5o93Gh8W63z2npIUErJvwwYz2IkpJIba6eL1ROAa" \
-H "X-Parse-REST-API-Key: E7Xg39e89nYjGhc1V0fXeukHMXOAo5SCkrQAgiKM" \
-H "Content-Type: application/json" \
-d '{"address":"No.1068 Tianshan Road West"}' https://api.parse.com/1/classes/AddressBook/8weFDfQ343
{"updatedAt":"2012-10-30T09:00:33.314Z"}
curl -X GET \
-H "X-Parse-Application-Id: 5o93Gh8W63z2npIUErJvwwYz2IkpJIba6eL1ROAa" \
-H "X-Parse-REST-API-Key: E7Xg39e89nYjGhc1V0fXeukHMXOAo5SCkrQAgiKM" https://api.parse.com/1/classes/AddressBook/8weFDfQ343
{"name":"tomcat","cellphone":"13788889999","address":"No.1068 Tianshan Road West","createdAt":"2012-10-30T07:53:36.824Z","updatedAt":"2012-10-30T09:00:33.314Z","objectId":"8weFDfQ343"}
curl -X DELETE \
-H "X-Parse-Application-Id: 5o93Gh8W63z2npIUErJvwwYz2IkpJIba6eL1ROAa" \
-H "X-Parse-REST-API-Key: E7Xg39e89nYjGhc1V0fXeukHMXOAo5SCkrQAgiKM" https://api.parse.com/1/classes/AddressBook/8weFDfQ343
5.2.4 考虑第二个需求,创建多用户版本的地址簿,对于用户注册,登录,验证邮箱,重置密码等的基本需求Parse已经帮我们解决了,左边是User相关API文档的截图。
5.2.4.1 注册用户
curl -X POST -H "X-Parse-Application-Id: 5o93Gh8W63z2npIUErJvwwYz2IkpJIba6eL1ROAa" \
-H "X-Parse-REST-API-Key: E7Xg39e89nYjGhc1V0fXeukHMXOAo5SCkrQAgiKM" \
-H "Content-Type: application/json" \
-d '{"username":"test","password":"test","phone":"415-392-0202"}' https://api.parse.com/1/users
{"createdAt":"2012-10-31T02:45:10.402Z","objectId":"EXmRl19aJq","sessionToken":"3cbkov9ol4o1iaungkmni0ssc"}
5.2.4.2 创建关联
下面这条是更新命令,有两处值得一提,1. 8weFDfQ343 是刚才第一条AddressBook记录的ID 2. “__op”:”AddRelation” 是Parse为我们提供的做关联的内置命令,相当于数据库的外键关联。
curl -X PUT \
-H "X-Parse-Application-Id: 5o93Gh8W63z2npIUErJvwwYz2IkpJIba6eL1ROAa" \
-H "X-Parse-REST-API-Key: E7Xg39e89nYjGhc1V0fXeukHMXOAo5SCkrQAgiKM" \
-H "Content-Type: application/json" \
-d '{"owner":{"__op":"AddRelation","objects":[{"__type":"Pointer","className":"_User","objectId":"EXmRl19aJq"}]}}' https://api.parse.com/1/classes/AddressBook/8weFDfQ343
{"updatedAt":"2012-10-31T02:56:40.557Z"}
5.2.4.3 使用一条命令创建地址簿联系人记录并且关联到这个用户
如果创建地址簿记录和关联到用户需要两个命令,就难免显得麻烦了,一般情况下的用例是:用户登录,添加他的地址簿记录,这个关联是可以一步做到的。
curl -X POST \
-H "X-Parse-Application-Id: 5o93Gh8W63z2npIUErJvwwYz2IkpJIba6eL1ROAa" \
-H "X-Parse-REST-API-Key: E7Xg39e89nYjGhc1V0fXeukHMXOAo5SCkrQAgiKM" \
-H "Content-Type: application/json" \
-d '{"name":"tim","cellphone":"13799998888","address":"No.1068 Tianshan Road West","cheatMode":false, "owner":{"__op":"AddRelation","objects":[{"__type":"Pointer","className":"_User","objectId":"EXmRl19aJq"}]}}' \
https://api.parse.com/1/classes/AddressBook
{"createdAt":"2012-10-31T02:59:44.762Z","objectId":"Yb7TdS01Mn"}
这个在Dashboard中的效果也非常直观
5.3 创建用户界面
技术上使用Bootstrap+Sinatra搭建,程序源码可以在这里找到 https://github.com/jihao/ab-parse-demo,你可以clone下来使用ruby ab.rb就能在本机跑了,当然你需要有ruby的运行环境。
这里大概解释一下结构,不太讨论技术细节,毕竟了解ruby的应该可以很容易看懂源码,如果觉得这100来行代码很酷,很简洁,立刻可以online,很想知道实现细节的同学们欢迎来找我讨论。
- Gemfile是用bundle init创建出来的,这个文件定义了程序依赖的其他gem
- views目录定义了所有的视图模板
- ab.rb是程序的核心controller
Sinatra是基于Ruby语言的非常简单的web框架,号称以最小精力为代价快速创建web应用为目的的DSL。
我们看一段代码ab.rb里处理用户注册的代码来感受一下氛围,前面几行是简单的参数校验,第15行是使用RestClient访问parse api创建用户,创建成功后重定向用户到登录界面。
post '/signup' do
name = email = params[:email]
password = params[:password]
confirm_password = params[:confirm_password]
if name.empty? || password.empty? || confirm_password.empty?
flash[:notice] = "Should not be empty"
return erb :signup
end
if password != confirm_password
flash[:notice] = "2 fields does not match"
return erb :signup
end
headers = AUTH_HASH.merge({:content_type=>:json, :accept=>:json})
result = RestClient.post "https://api.parse.com/1/users",
{"username"=>name,"password"=>password,"email"=>email}.to_json,
headers
@result = JSON.parse result
flash[:notice] = "Succeed (ObjectId=%s)" % @result["objectId"]
redirect "/signin"
end
5.4 部署应用
我选择使用上文中提到的Heroku来部署这个Sinatra应用,从头开始到部署完成非常简单
5.4.1 打开这个页面 https://toolbelt.heroku.com,选择你的平台安装
hao@ab-parse-demo$ heroku login
5.4.2 在ab-parse-demo的git repository下面,执行如下命令
hao@ab-parse-demo$ heroku create ab-parse-demo
5.4.3 然后就可以通过git push来部署了,这里给不想亲自尝试的同学们show下这条命令的log。
可以看到,首先代码被提交到Heroku上,然后它根据Gemfile自动安装了gem依赖,然后应用被编译部署到 http://ab-parse-demo.herokuapp.com
hao@ab-parse-demo$ git push heroku master
Warning: Permanently added the RSA host key for IP address '50.19.85.154' to the list of known hosts.
Counting objects: 15, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (8/8), done.
Writing objects: 100% (8/8), 1.30 KiB, done.
Total 8 (delta 7), reused 0 (delta 0)
-----> Heroku receiving push
-----> Ruby/Rack app detected
-----> Installing dependencies using Bundler version 1.2.1
Running: bundle install --without development:test --path vendor/bundle --binstubs bin/
Fetching gem metadata from http://ruby.taobao.org/.
Fetching full source index from http://ruby.taobao.org/
Using mime-types (1.19)
Using rack (1.4.1)
Using rack-flash3 (1.0.1)
Using rack-protection (1.2.0)
Using rest-client (1.6.7)
Using tilt (1.3.3)
Using sinatra (1.3.3)
Using bundler (1.2.1)
Your bundle is complete! It was installed into ./vendor/bundle
Cleaning up the bundler cache.
-----> Discovering process types
Procfile declares types -> (none)
Default types for Ruby/Rack -> console, rake, web
-----> Compiled slug size: 892K
-----> Launching... done, v7
http://ab-parse-demo.herokuapp.com deployed to Heroku
To git@heroku.com:ab-parse-demo.git
981fb68..30889ab master -> master
hao@ab-parse-demo$ heroku ps
=== web: `bundle exec rackup config.ru -p $PORT`
web.1: up 2012/11/01 22:54:42 (~ 10m ago)
5.4.4 最终效果
5.4 水平扩展应用
这是heroku管理这个应用的后台,Dynos默认是1,1个节点是免费的,然后这个蓝色条是可以拖动的,如果我要这个应用水平扩展到10个节点以支持更多的用户的话,可以拖动以预览相对应的费用。
六、小结
综上所述,这就是我们触手可及的云计算,对于程序员来说是相当不错的一件事情。










