部署应用前,必须对即将部署的动作进行recipe配置。例如,官网例子,recipe依赖单一的MongoDB服务实例和Tomcat服务实例;由于例子已做好配置,该recipe可以不做任何修改也可以进行下一步操作。当然,也可以对一些可选项修改,比如,recipe中配置的服务实例数量。
Anatomy(剖析) of a Recipe
Recipes是在不修改应用代码和架构的同时,对应用程序栈安装、启动、协调、监控的执行计划。部署文件和文件夹位于应用的recipe文件夹中,例如:<cloudifyRoot>/recipes/apps/petclinic-simple. 下面是例子PetClinic应用的recipe文件和文件夹目录列表:
运行MongoDB和Tomcat所需要的文件,可以在对应的mongod和tomcat子文件夹中找到。下图是PetClinic application的recipe文件和文件夹目录结构:
图中表明, mongod service继承了mongod service in ../../../services/mongodb/mongod, 而 tomcatservice 继承了the tomcat service in ../../../services/mongodb/tomcat.The Application Recipe
每一份recipe必须包括一个描述文件,用于描述它所需要的的服务(层)及其依赖关系。
例子PetClinic application包含两种services, 每项service包含了单一的service实例:
以下为PetClinic application的应用描述文件的内容:
application
{ name="petclinic"
service {
name = "mongod"
}
service {
name = "tomcat"
dependsOn = ["mongod"]
}
}
从该文件中可发现以下信息:
每一项服务受制于其自己的service recipe,该recipe通常基于一个recipe 结构。每一个service文件夹包含服务需要的所有信息。以下为service recipe的文件和文件夹:
在tomcat recipe文件夹的Groovy脚本中,你可以发现它们基本上都是是可以由任何的groovy或java代码编写的普通脚本。唯一不同的是Cloudify API((ServiceContext API)的使用。). API暴露了service运行的细节,因此一个服务可以定位并使用同一个应用中的其它服务的细节。例如,PetClinic application通过API将mongodservice 实例的端口暴露给应用的其它所用服务。
服务的二进制文件(执行程序文件),例子中的Tomcat和MongoDB发布版上传到为服务实例提供的machines中是相当大的。因此,当提供machines时,recipes通过一个指定的repository(可能是任一的Http、Ftp或本地文件系统)获取,并不从recipe中上传。那样可提高Cloudify环境的性能和反应。在Groovy中内置了支持Apache Ant的AntBuilder,通过Antgettask获取程序二进制文件。
MongoDB (mongod) Recipe 执行下步骤:
Themongodservice 的描述在<cloudify root>/recipes/apps/petclinic/mongod/mongod-service.groovy.
Tomcat Recipe执行下步骤:
The tomcat service 描述文件是<cloudify root>/recipes/apps/petclinic/tomcat/tomcat-service.groovy.
在例子中,我们使用ServiceContext API 和其 k/v 存储机制,用于分享mongod服务实例 (host address and port) 细节给tomcat服务实例。
首先, MongoDB recipe 暴露mongod服务实例细节如下:
// In <cloudify root>/recipes/apps/petclinic/mongod/mongod_install.groovy
import com.gigaspaces.cloudify.dsl.context.ServiceContextFactory
// ...
// Getting the mongod service instance ID
instanceID = serviceContext.getInstanceId()
// Calculating the mongod port and storing it in the serviceContext for later use
// (by the service and by other services).
serviceContext.attributes.thisInstance["port"] = config.basePort+instanceID
// ...
然后,Tomcat recipe 检索这些细节如下:
import com.gigaspaces.cloudify.dsl.context.ServiceContextFactory
// ...
// Waiting for the mongos service for 20 seconds
mongoService = serviceContext.waitForService(config.mongoService, 20, TimeUnit.SECONDS)
// Waiting for the mongod service instance for 60 seconds (In this case,
mongoInstances = mongoService.waitForInstances(mongoService.numberOfPlannedInstances, 60, TimeUnit.SECONDS)
// Retrieving the mongod host address.
// Note that the mongoInstances array is zero based.
def mongoServiceHost = mongoInstances[0].hostAddress
// Retrieving the mongod port
// Note that the mongoServiceInstances array is one based.
def mongoServiceInstances=serviceContext.attributes.mongod.instances
mongoServicePort=mongoServiceInstances[1].port
这个工作完成后,tomcat服务实例知道了mongod服务实例的主机地址和端口,即可以与之通信了。