Cloud Foundry是一个开源的平台即服务产品,它提供开发者自由度去选择云平台,开发框架和应用服务。而Cloud Foundry中,服务则是体现了应用程序的高级功能,正是由于服务Service的存在,用户得以加速应用部署和简化应用管理。首先,还是简要的介绍一下Cloud Foundry的Service。
目前Cloud Foundry的Service主要包括三方面:1.数据库服务(nosql以及relation),比如:Redis,MondoDB,Neo4j,CouchDB,Mysql,Postgres等;2.存储类服务,比如:Vblob,Filesystem等;3.其他类型服务,比如:RabbitMQ消息队列系统,Memcached分布式内存对象缓存服务等。在Cloud Foundry中,从组件的角度来看,service主要包括两部分:service gateway与service node。从工作流程来看,service有以下两个最为主要的功能:创建service实例和为运行的app绑定一个或若干个service实例,当然还有一些其他重要的功能,比如为service创建snapshot等,但这些不在本文源码探讨的范畴之内。
个人觉得研究分析Cloud Foundry的某个组件,应该从两个方面入手:第一,研究组件启动的过程;第二,研究在与用户交互时的运作流程。关于Cloud Foundry的service gateway,源码也是如此。
关于源码,在github上的Cloud Foundry板块都有,主要有:vcap-service-base,vcap-services以及cloud-controller,其中cloud-controller作为一个控制组件,很多关于service的信息都会通过http的形式转发给service gateway,所以cloud-controller和gateway在通信上戚戚相关。
前期的准备工作准备好了,那就开始来分析一下源码吧。还是从启动和运行两个方面来理解。
1.gateway的启动
关于gateway启动的代码,在cloudfoundry-vcap-services-base\lib\base目录下的asynchronous_service_gateway.rb中,这也是研究gateway的最主要ruby文件之一。其实gateway启动的代码很清晰,如下:
def initialize(opts)
super
setup(opts)
end
大家都知道initialize方法会在每次生成该类的一个新实例时被执行。所以在启动gatweway的时候,首先执行initialize方法,然后再去调用setup方法。setup方法顾名思义,主要是gateway启动设置的事情。可以看到在同一ruby文件中,setup方法就在initialize方法之下,该函方法以下几部分组成:实例变量的赋值,设置heartbeat以及终止处理方法,添加未知handles,注册反馈handles。
1.1设置heartbeat以及终止处理方法
setup方法的代码很清晰,关于实例变量的赋值,这里不作赘述。所谓heartbeat,即是心跳,意味着人的心脏每过不到一秒,它就会跳一下,如果不跳的话,那说人出现假死状态或者已经死亡。这样的概念对于一个gateway节点来说,同样成立,主要功能告诉他人本节点活着,而且发给那个人可以找到自己的url等。而gateway的heartbeat则是向cloud controller发送的,如下:
EM.add_periodic_timer(@hb_interval) { send_heartbeat }
EM.next_tick { send_heartbeat }
可以看到gateway是循环向cloud controller发送heartbeat的。而EM和add_periodic_timer是EventMachine的相关内容,具体可以参考实验室大牛的博文Research on EventMachine。以下是send_heartbeat方法的定义:
def send_heartbeat
@logger.info("Sending info to cloud controller: #{@offering_uri}")
req = create_http_request(
:head => @cc_req_hdrs,
:body => @svc_json
)
http = EM::HttpRequest.new(@offering_uri).post(req)
http.callback do
if http.response_header.status == 200
@logger.info("Successfully registered with cloud controller")
else
@logger.error("Failed registering with cloud controller, status=#{http.response_header.status}")
end
end
http.errback do
@logger.error("Failed registering with cloud controller: #{http.error}")
end
end
这些源码很清晰,首先是打出Sending info to cloud controller:#{@offering_uri}的的log,然后是创建一个http请求的req,然后通过新建一个HttpRequest类的实例,做post一个req的操作,一旦回复信息中status为200,则表示成功注册。这里关键部分就在http=EM::HttpRequest.new(@offering_uri).post(req)这行代码处。关于HttpRequest的代码实现是通过Gem包的形式被下载到安装gateway节点上的,主要就是通过http的方式向cloud controller发送Rest请求。
cloud controller收到的所有Rest请求,都会被转发到cloud_controller/cloud_controller/config/route.rb文件下,而send_heartbeat方法发来的Rest请求会被映射到该文件中的post'services/v1/offerings'=>'services#create',:as=>:service_create这行代码,从而将映射到service_controller.rb文件中的create方法。以下是create方法的具体实现