关于cloud foundry 的源码解析的文章很多,最近我也在研究这个东西,感觉内容比较多,也相对比较复杂,我在这里做一个整合,方便大家了解。
1.CloudController
了解整个Cloud Foundry需要熟悉的内容很多,但最核心的东西是nats和event-machine. 关于nats上一篇已经做了介绍,大家可参考基于Cloud Foundry的PaaS实践(二) Cloud Foundry集群部署 ,安装一下执行个小示例程序便可一目了然。关于event-machine,大家可参考EventMachine-scalable-non-blocking-i-o-in-ruby 和 eventmachine_introduction_10.pdf 。简而言之,就是一个用很牛的算法(reactor)写的一个非阻塞的socket通信框架,有多种语言的实现,nats也用到。同样的,照着上面资料中的示例执行一下,就明白了。
有了以上的基础,我们可以开始共同看一下Cloud Foundry的核心,cloud_controller.
Cloud_Controller负责整个Cloud Foundry的用户管理/应用管理/服务管理,基于rails框架对外提供RESTFUL接口服务。我们可以通过分析一般rails应用的方法加以分析。rails应用的掌握个人喜欢通过MVC框架和RESTFUL接口把握。
首先,看一下cloud_controller/config/routes.rb:
按列从左至右依次为:http方法/访问路径/代码文件和函数信息/略。以第一行为例,如果cloud_controller接收到http get请求info路径信息,将使用cloud_controller/app/default_controller.rb文件中的info函数响应。以上供刚刚接触rails的同学参考。
了解了routers.rb的路由方法后,还可以使用wireshark工具,安装vmc(安装ruby后执行gem install vmc),通过vmc help帮助执行vmc 命令的同时,用wireshark抓取http包,刚cloud_controller RESTFUL接口可完全把握。下面使用LINUX的curl工具,显示示例包如下:
当然,这个应答信息显示的不够全面,大家还是wireshark,我这台电脑没装,暂时就不能截图了。另外,大家也可以使用Advance RESTclient,示例:
到此,我们已经可以把握全部restful接口,以及每个接口执行的路径,再列一下cloud_controller/app目录下的文件,一目了然。
在看代码之前,最好再看一下数据模型。我曾经画了个模型图,可惜暂时找不到了,先做个文字介绍吧。
cloud_controller的主要数据模型包括:
(临时画的简表,抱歉未添加表关系和示例数据,过两天要是翻到我写的手册就补上)。
表的内容不难,此处列出的只是比较主要的,可能会有变化,但相信这里的大部分东西不会大变。特别说明,service在Cloud Foundry中指的是System Service,比如Cloud Foundry会根据用户的需要,由用户执行vmc create-server mysql后,为用户创建一个mysql,然后执行vmc bind-service mysql-name app-name后,就将此服务和应用绑定,即应用可以访问VCAP_SERVICES环境变量,得到这个mysql实例的连接信息,包括用户名/密码/IP/端口啥的。这块目前Cloud Foundry支持API,用法更加简单,但原理如是。实现的信息会保存在services表中,连接信息会保存在binding_tokens表中,服务绑定信息会放在service_bindings表中,服务版本信息会保存service_configs中。大家可以执行一下命令,看看表中数据的变化即可顿悟。
2.dea
上一篇文章分析了router的运行原理,在这一篇开始分析dea组件的运行。。。,记得以前自己刚刚开始接触cloud foundry的时候就会觉得dea是最神奇的一个模块,不过看了它的代码之后它的神秘感也就渐渐的消失了。。
首先来看启动的代码:
- EM.run {
- agent = DEA::Agent.new(config)
- agent.run()
- }
agent类的构造函数主要是进行一些基本信息的配置,例如app目录的路径,总共可用的内存大小等。。。这里就不一看他的代码了。。主要是来看run函数中的代码,因为重要的部分都在这个里面。。。
- begin #用于创建文件夹
- FileUtils.mkdir_p(@droplet_dir)
- FileUtils.mkdir_p(@staged_dir)
- FileUtils.mkdir_p(@apps_dir)
- FileUtils.mkdir_p(@db_dir)
- if @secure # Allow traversal by secure users
- FileUtils.chmod(0711, @apps_dir)
- FileUtils.chmod(0711, @droplet_dir)
- end
- rescue => e
- @logger.fatal("Can't create support directories: #{e}")
- exit 1
- end