Cloud Foundry中Service Gateway功能以及通信机制

本报告从两个方面讲述Cloud Foundry中的组件Service Gateway:Service Gateway的功能和Service Gateway的通信机制。

 

1. Service Gateway的功能

Service Gateway 在CloudFoundry中的作用主要是:接收Cloud Foundry中的控制器Cloud Controller发来的请求,并根据请求类型,对Service Node上的service instance作相应的管理。

在CloudFoundry中,Cloud Controller 会向ServiceGateway发送20种管理请求。以下是这些请求具体的描述:

 

1.1. Provision a service

功能:为用户创建一个新的服务实例。

函数调用:@provisioner.provision_service(req)

参数解析:

    req:CloudController发送的请求到达后,经Service Gateway译码后的信息,在ruby中的数据类型为hash;在provision_service(req)函数中,主要用到其中的属性的label,plan,version;

    label:需要创建服务实例的类型,比如:mysql-5.1,mysql-5.0等;

    plan:需要创建服务实例的计划,主要是限制创建服务实例的大小等;

    version:需要创建服务实例的版本,比如在MySQL的版本号5.1。

 

1.2.   Unprovision  a service

功能:为用户清除一个已经创建完毕的服务实例。

函数调用:@provisioner.unprovision_service(params['service_id'])

参数解析:

params['service_id']:Cloud Controller发送的请求中,属性为'service_id'的值;由于清除一个已经创建完毕的服务实例,只需要知道这个服务实例的ID,所以传给unprovision_service()函数的参数只需要一个服务实例的ID。

 

1.3.   Bind a service

功能:为用户的一个应用程序绑定一个服务实例

函数调用:@provisioner.bind_instance(req.service_id,req.binding_options)

参数解析:

req.service_id:CloudController需要给应用程序绑定的服务实例ID;

req.binding_options:CloudController需要给应用程序绑定服务实例时的绑定选项,在目前Cloud Foundry的运行中,该参数值为空,另外在源程序中该参数值的作用只限于存储与查看,并不影响程序的运行,可以认为是绑定的备注信息。

备注:由于在CloudFoundry中,绑定一个服务实例,只是为特定服务实例创建credential信息,随后将这些信息返回给Cloud Controller,由Cloud Controller将这些信息重新打包入应用程序,所以在该过程中,Service Gateway涉及的只有相应的service_id,而不需要具体的应用程序ID。

 

 

1.4.   Unbind a service

功能:为用户一个绑定服务实例的应用程序解除绑定。

函数调用: @provisioner.unbind_instance(req.service_id, req.handle_id,req.binding_options)

参数解析:

req.service_id:需要解除绑定的服务实例的ID;

req.handle_id:需要解除绑定的服务实例的认证信息所在记录的ID;

req.binding_options:服务实例在绑定时的绑定选项,该参数在函数引用参数中出现,但是在函数具体实现中却没有使用到。

 

1.5.   Createa snapshot

功能:为一个服务实例创建一个快照文件

    函数调用:@provisioner.create_snapshot(service_id)

    参数解析:

    service_id:需要创建快照的服务实例ID。

 

1.6.   Get snapshot details

功能:获取一个服务实例快照的具体信息

    函数调用:@provisioner.get_snapshot(service_id, snapshot_id)

    参数解析:

    service_id:需要获取具体信息的快照对应的服务实例ID;

    snapshot_id:需要获取具体信息的快照ID。

 

1.7.   Update snapshot name

功能:为一个已经创建完毕的快照更新名称

    函数调用:@provisioner.update_snapshot_name(service_id, snapshot_id, req.name)

    参数解析:

    service_id:需要更新名称的快照对应的服务实例ID;

    snapshot_id:需要更新名称的快照ID;

    req.name:最终用来更新快照的名称。

 

1.8.   Get all snapshots related to an instance

功能:列举一个服务实例的所有快照

    函数调用:snapshots = service_snapshots(service_id)

    参数解析:

    service_id:需要列举所有快照的服务实例ID。

     

1.9.   Roll back to a snapshot

功能:将以个服务实例回滚到某个指定的快照

    函数调用:@provisioner.rollback_snapshot(service_id, snapshot_id)

    参数解析:

    service_id:需要回滚的服务实例的ID;

    snapshot_id:需要将该服务实例回滚到指定版本的快照ID。

 

1.10.  Delete a snapshot

功能:删除一个服务实例的某个快照

    函数调用:@provisioner.delete_snapshot(service_id, snapshot_id)

    参数解析:

    service_id:需要删除快照的服务实例ID;

    snapshot_id:需要删除的快照ID。

     

1.11.  Create a serialized URL

功能:为一个服务实例创建一个串行化的URL

    函数调用:@provisioner.create_serialized_url(service_id, snapshot_id)

    参数解析:

    service_id:需要创建串行化URL的服务实例ID;

    snapshot_id:需要创建串行化URL的快照ID。

     

1.12.  Get a serialized URL

功能:获取指定服务实例的指定快照的串行化URL

    函数调用:@provisioner.get_serialized_url(service_id, snapshot_id)

    参数解析:

    service_id:需要获取串行化URL的服务实例ID;

    snapshot_id:需要获取串行化URL的服务实例中的快照ID。

 

1.13.  Import serialized data fromURL

    功能:为指定服务实例导入串行化URL

    函数调用:@provisioner.import_from_url(service_id, req.url)

    参数解析:

    service_id:需要导入串行化URL的服务实例ID;

    req.url:需要为服务实例导入的具体串行化URL。

 

1.14.  Get job details

    功能:获取指定服务实例的指定任务信息

    函数调用: @provisioner.job_details(service_id, job_id)

    参数解析:

    service_id:需要获取任务信息的服务实例ID;

    job_id:服务实例的具体任务的ID。

 

1.15.  Restore a service

    功能:备份指定服务实例

    函数调用:@provisioner.restore_instance(req['instance_id'],req['backup_path'])

    参数解析:

    req['instance_id']:需要备份的服务实例的ID;

    req['backup_path']:备份服务实例的备份路径。

 

1.16.  Recovery an instance

    功能:恢复一个服务实例,如果一个Service Node已经崩溃的话

    函数调用:@provisioner.recover(instance_id, backup_path, resp.handles)

    参数调用:

    instance_id:需要恢复的服务实例ID;

    backup_path:该服务实例的备份路径。

    备注:在Cloud Foundry中,为服务实例创建一个快照与存储一个服务实例是不一样的效果。快照的意义是记录服务实例的某个时间情况,可以将服务实例回滚后某个时间点,而回滚的前提是该服务实例还存在;当服务实例不存在时(比如Service  Node崩溃),那么只能从存储的备份服务实例中找到相应的服务实例,并做到恢复。

   

1.17.  Check orphans

    功能:查找orphan

    函数调用:check_orphan(resp.handles,)

    参数解析:

    resp.handles:所有创建完毕的服务实例。

    备注:orphan的意思是孤儿,在Cloud Foundry中代表那些在Service Node中已经创建完毕,而且已经在Service Gateway中有记录信息,但是在Cloud Controller中却没有记录信息的服务实例。这些服务实例的存在只会浪费ServiceNode的资源,而在实际Cloud Foundry运行的过程中,它们是不会被用户使用到(因为在Cloud Controller中不存在它们的记录)。而作为“orphan”的这些服务实例的存在是不合理的,需要被清除,而清除的第一步就是查看是否存在这样的“orphan”。

   

1.18.  Purge orphans

    功能:挖除orphan

    函数调用:@provisioner.purge_orphan(orphan_ins_hash,orphan_binding_hash)

    参数调用:

    orphan_ins_hash:确认为orphan的所有服务实例的ID,数据类型为hash类型;

    orphan_binding_hash:确认为orphan的,在Service Gateway看来已经被绑定,但是Cloud Controller却不知道的服务实例ID,数据类型为hash类型。

 

1.19.  Migrate a service

    功能:为特定Service Node上的服务实例进行迁移

    函数调用:@provisioner.migrate_instance(params["node_id"], params["instance_id"],params["action"])

    参数解析:

    params["node_id"]:需要迁移服务实例所在的Service Node ID;

    params["instance_id"]:需要被迁移的服务实例ID;

    params["action"]:迁移的具体操作类型。

 

1.20.  Get services on a node

    功能:获取某个Service Node上所有的服务实例

    函数调用:@provisioner.get_instance_id_list(params["node_id"])

    参数解析:

    params["node_id"]:需要获取的所有服务实例所在的Service Node ID。


 

2.ServiceGateway的通信机制

    由CloudFoundry的平台框架可知,对于Service Gateway来说,需要通信的平台组件只有两个,分别是:Cloud Controller和Service Node。其中Service Gateway与Cloud Controller的通信是通过相互发送HTTP请求的形式来完成的。另外,Service Gateway与Service Node的通信是通过Cloud Foundry的消息中间件NATS来完成的。以下是对这两种通信方式的分析:

  

2.1. HTTP通信

在Service Gateway中,它总是通过HTTP的方式建立与Cloud Controller的通信。

这样的通信可以分为两类:

(1).Service Gateway从CloudController处获取HTTP请求,并作出相应的处理。

在第一部分讲述Service Gateway的功能时,涉及的20种功能,都是Cloud Controller的发送来管理请求,而他们都是通过HTTP的形式完成的。首先Service Gateway先对这些HTTP请求进行路由,然后将这些请求分发到相应的处理函数出进行处理,最后返回相应的结果。

(2).Service Gateway向CloudController发送HTTP请求,发送的HTTP请求的函数主要有send_heartbeat,send_deactivation_notice,fetch_handles, 以下将更深入的分析这些方法的功能与实现。

 

2.1.1. send_heartbeat

功能:Service Gateway向CloudController发送心跳信息,表示该Service Gateway存活,可以接收管理请求。

主要方法实现:

http =EM::HttpRequest.new(@offering_url).post(req)

   方法分析:Service Gateway通过HTTP方式向Cloud Controller发送一个post请求,其中Cloud Controller的URL为@offering_url,具体的请求信息被打包在req对象中。以下为req内容:

      req=create_http_request(

      :head => @cc_req_hdrs,

      :body => @svc_json

      )

备注:其中发送的heartbeat中。内容包括:该Service Gateway的服务类型,URL(IP和port),描述等。

 

2.1.2.send_deactivation_notice

功能:Service Gateway向Cloud Controller发送停止信息,表示该Service Gateway已停止工作。

    主要方法实现:

    http = EM::HttpRequest.new(@offering_url).post(req)

    方法分析:Service Gateway通过HTTP方式向Cloud Controller发送一个post请求,其中Cloud Controller的URL为@offering_url,具体的请求信息被打包在req对象中。以下为req内容:    req=create_http_request(

       :head => @cc_req_hdrs,

       :body => @svc_json

    )

 

2.1.3.fetch_handles

功能:Service Gateway向Cloud Foundry发送获取已有服务实例信息的请求(包括创建信息,绑定信息等)。

主要方法实现:

    Http =EM::HttpRequest.new(@offering_url).get(req)

    方法分析:Service Gateway通过HTTP方式向Cloud Controller发送一个post请求,其中Cloud Controller的URL为@offering_url,具体的请求信息被打包在req对象中。以下为req内容:req=create_http_request :head =>@cc_req_hdrs

 

2.1.4.update_service_handle

功能:Service Gateway向Cloud Controller发送更新已有服务实例信息的请求(包括创建信息,绑定信息等)。

    主要方法实现:

    http =EM::HttpRequest.new(@offering_url).get(req)

    方法分析:Service Gateway通过HTTP方式向Cloud Controller发送一个get请求,其中Cloud Controller的URL为@offering_url,具体的请求信息被打包在req对象中。以下为req内容:    req=create_http_request(

       :head => @cc_req_hdrs,

       :body => handle_json

    )

 

2.2.   NATS通信

在Service Gateway中,NATS通信主要存在于Service Gateway和Service Node的通信中。

NATS是一个基于事件驱动的轻量级,支持订阅和发布的消息中间件系统。作为Cloud Foundry的神经中枢,NATS负责组件之间的通信和交互工作。

NATS在ServiceGateway中的使用主要是创建连接,发送订阅和发布消息。以下是具体实现。

 

2.2.1.创建NATS连接

Service Gateway具体使用到NATS来订阅和发布消息的程序代码位于provision.rb文件中,而其中Provisioner这个类则是继承于Base这个类。

Service Gateway具体与NATS建立连接的过程则在于Base这个类中。具体代码实现为:

@node_nats= NATS.connect(:uri => options[:mbus])

其中options[:mbus]为NATS server端所在节点的URL。而代码中的NATS是一个程序包,是通过gem包的形式安装在Service Gateway节点处,在程序中是通过require的方式进行引用,引用完毕后就可以使用该gem包中的方法。@node_nats为ServiceGateway与NATS server端创建连接时产生的一个对象,而后续的一些订阅和发布的实现都是通过这个对象来完成的。

 

2.2.2.发送订阅和发布消息

Service Gateway通过NATS来发送订阅和发布消息,由于在创建与NATS连接的时候,已经产生了一个与NATS server端进行通信的对象@node_nats,所以在每次需要订阅和发布消息的时候,都是引用这个对象进行相应的操作。

关于消息的操作类型主要有以下几种:publish, subscribe, unsubscribe。

Publish主要是某一个组件发布一个消息,这个消息可以被其他组件订阅。

Subscribe主要是某一个组件订阅一个消息,一旦有这样的消息被发布以后,NATS就会将这样的信息分发给订阅者。

Unsubscribe主要是某一个组件不再订阅某一个消息。

在第一章中涉及的ServiceGateway功能中,只要这些功能中会需要Service Gateway和Service Node建立通信,则具体的代码实现中,都需要@node_nats这个对象来实现通信。

以下是在ServiceGateway中需要使用NATS建立通信的地方:

 

方法check_orphan中:

    @node_nats.publish("#{service_name}.check_orphan","SendMe Handles")

    主要实现:Service Gateway向NATS发布一个消息,消息的内容为指定类型的Service Node向该Service Gateway发送服务实例的具体信息。

 

    方法purge_orphan中:

    @node_nats.publish("#{service_name}.purge_orphan.#{node_id}", req.encode)

    主要实现:Service Gateway向NATS发布一个消息,消息的内容为指定类型的Service Node需要挖除指定ID的服务实例。

 

    方法unprovision_service中:

    timer =EM.add_timer(@node_timeout) {

 @node_nats.unsubscribe(subscription)

blk.call(timeout_fail)

}

    主要实现:查看Service Gateway向NATS发送关于Service Node的请求,Service Node是否超时。

    @node_nats.request("#{service_name}.unprovision.#{node_id}", request.encode)

    主要实现:Service Gateway向NATS发送一个请求信息,这个请求信息主要让NATS负责找到相应的Service Node来删除某一个具体的服务实例。

 

     方法provision_service, bind_instance, unbind_uinstance中的分别有@node_nats.request("#{service_name}.provision.#{best_node}",prov_req.encode),

    @node_nats.request( "#{service_name}.bind.#{node_id}",request.encode)和

    @node_nats.request( "#{service_name}.unbind.#{node_id}",request.encode)。

    这三处的主要实现与unprovision_service的实现原理相同,具体功能略有区别。

 

    方法restore_instance中:

    @node_nats.request( "#{service_name}.restore.#{node_id}",request.encode)

    主要实现:Service Gateway向NATS发送一个请求信息,这个请求信息让NATS负责找到相应的Service Node来为某一个服务实例创建一个备份。

 

    方法migrate_instance中:

   @node_nats.request(channel, message)

    主要实现:Service Gateway向NATS发送一个请求信息,该请求让NATS负责找到相应的Service Node来实现服务的迁移。

你可能感兴趣的:(Cloud Foundry中Service Gateway功能以及通信机制)