生命周期事件——Lifecycle Events

2021-02-20 07:47发布

Lifecycle Events Overview

Cloudify支持以下类型的生命周期事件:

  • Application events — 内置events,在Cloudify shell提示符输入命令来调用。 
  • Service events —在service recipe中定义的事件,由ESM调用。
  • Service instance events — 在service recipe中定义的最后要的生命周期事件,由ESM调用。

当一个生命周期事件被触发,事件需要的动作发生对应的事件处理脚本会运行。例如一个安装事件被ESM调用,对应的安装事件处理(定义在服务描述文件中)会执行。

已知的限制: 当start 事件反回,Cloudify将认为service 实例已经停止并且会试图重试。为了避免该行为,确保start脚本永久睡眠。 

Application Events

Application events 是Cloudify内置的,当前不能在应用recipe中自定义。它们是由Cloudify shell提示符输入命令来调用的。通常用于执行各各任务,如,将recipes拷贝到管理machines中,然后触发相应的内置应用事件。

存在两种application events:

  • Application install –用于安装应用,在 Cloudify shell prompt中输入: install-application<applicationName>。这个命令提供应用所需要的服务,启动服务以满足应用的依赖关系,然后安装这个应用。
  • Application uninstall – 卸载应用,在Cloudify shell prompt, 输入: uninstall-application <applicationName>。 这个命令用于停止和移除应用、应用依赖的所有服务、Cloudify agents,并关闭服务所运行的machine。

Service Events

服务事件在服务recipe中自定义。它们被ESM触发。这些事件对于服务实例启动前,或者在移除最后一项服务实例后关闭集群前,执行任务是非常有用的。它们能够运行在所有的或指定的服务实例上。

下图为服务事件图:

Service Instance Events

服务实例事件可以在服务recipe中自定义。他们被ESM触发。

下图为主要的服务实例事件生命周期。

Lifecycle Event Handlers(生命周期事件处理程序)

生命周期事件处理程序被定义在服务描述文件的lifecycle section。他们可以被定义在一个与服务recipe同文件夹的外部文件中(支持的格式包括:Groovy scripts, Windows batch files, or *nix shell scripts),或者是一个内敛闭包(当代码很短的时候非常有用)。可以使用通过一个外部脚本文件来运行其它语言来编写脚本,并通过环境变量来提供其上下文。以下是一个事件处理程序可以分配的完整生命周期事件的序列:

  • preServiceStart
  • init
  • preInstall
  • install
  • postInstall
  • preStart
  • start
  • startDetection
  • locator
  • postStart
  • preStop
  • stop
  • postStop
  • shutdown
  • preServiceStop

以下为一个 lifecycle section示例,为生命周期事件分配了事件处理程序。

lifecycle{

init "mysql_install.groovy"

start "mysql_start.groovy"

postStart "mysql_poststart.groovy"

preStop "mysql_preStop.groovy"

}

在某些情况下,一份recipe可能需要运行各种操作系统之上。以下一个lifecycle section 展示了为生命周期事件分配不同操作系统的事件件处理程序。

lifecycle{

init "tomcat_install.groovy"

start ([

"Win.*" : "tomcat_run.bat",

"Linux" : "tomcat_run.sh",

"Mac.*" : "tomcat_run.sh"

])

preStop ([

"Win.*" : "tomcat_stop.bat",

"Linux" : "tomcat_stop.sh",

"Mac.*" : "tomcat_stop.sh"

])

}

Process Locator Events

Cloudify的过程监控、活性检测、停止事件,使用进程ids来执行它们的函数。默认情况下, Cloudify通过扫描进程树来收集process ids。 进程树由service recipe启动,用于放置所有的叶子进程(leaf processes,这样的进程不再产生新的进程)。

定位器事件程序 (locator) 在 startDetection 事件后被触发,允许你重写Cloudify收集的默认process ids列表。通过在服务recipe的lifecycle section中定义定位器程序事件的事件处理程序。就可以写自己的代码来收集服务进程ids,并返回列表给Cloudify,用于监控。 这使得Cloudify可以监控服务的所有进程,并可以在所有相关联的服务已停止时,唯一标识该服务。

或者,如果你根本不想监控进程,定义一个关闭的进程定位器,返回 NO_PROCESS_LOCATORS (这表示一个空的process ids列表).
例用,当你有一个服务进行频繁的产生和自相杀死进程,或者你不想对服务的活性进行监控时,这个定义很有效。

以下为一个例子 :

service {

name "simple-background"

icon "icon.png"

type "WEB_SERVER"

lifecycle {

start (["Win.*":"run.bat", "Linux":"run.sh"])

startDetection {

return ServiceUtils.isPortOccupied(8090)

}

locator {

NO_PROCESS_LOCATORS

}

}

}

如果没有在服务recipe中定义locator 关闭, Cloudify 会执行默认操作。

如果在服务recipe的 lifecycle section没有定义 start 事件处理程序, 从而machine会使用镜像的预配置来启动。 process locator 不会被触发. 因此,如果想监控服务的 processes,需要在服务recipe的monitors section中定义相关监控代码。

下面是服务recipe的 locator closure 例子

service {

name "simple-background"

icon "icon.png"

type "WEB_SERVER"

 

lifecycle {

start (["Win.*":"run.bat", "Linux":"run.sh"])

startDetection {

return ServiceUtils.isPortOccupied(7777)

}

locator {

return ServiceUtils.ProcessUtils.getPidsWithMainClass("javaprocess.jar")

/* Uncomment to return pids for httpd and apache processes

return ServiceUtils.ProcessUtils.getPidsWithQuery("State.Name.re=httpd|apache") */

/* Uncomment to return pids for either Windows or *nix httpd processes

def winPids = ServiceUtils.ProcessUtils.getPidsWithName("httpd.exe")

def linuxPids = ServiceUtils.ProcessUtils.getPidsWithName("httpd")

List<Long> merge = []

merge.addAll(winPids)

merge.addAll(linuxPids)

return merge */

}

}

}

在事件处理程序内获取服务上下文(Retrieving the Service Context from within Event Handlers)

服务上下文可在事件处理脚本或在闭包中使用Service Context API来获取。以下例子是在Groovy event处理脚本中如何采用 ServiceContextFactory 来获取一个服务实例上下文的例子。

import org.cloudifysource.dsl.context.ServiceContextFactory;

def context = ServiceContextFactory.getServiceContext()

也可以在一个外部Groovy文件中使用ServiceContextFactory ,即不一定要在服务描述文件中使用。

要获得上下文的实例ID,只要简单的使用 context 变量,即可获得服务上下文的实例。如下:

def instanceId = context.instanceId

基于none-jvm可执行文件不能直接访问服务上下文。然而,一些上下文的信息可以通过以下环境变量:

  • LOOKUPGROUPS
  • LOOKUPLOCATORS
  • USM_CLUSTER_NAME
  • USM_APPLICATION_NAME
  • USM_SERVICE_NAME
  • USM_PU_UNIQUE_NAME
  • USM_INSTANCE_ID
  • USM_NUMBER_OF_INSTANCES
  • USM_RUNNING_NUMBER
  • USM_SERVICE_FILE_NAME

生命周期事件使用USM来调用外部事件处理程序,见下图:

Best Practices: Lifecycle Event Handlers

当定义生命周期事件处理程序时,最好的方法是分而治之。把任务分成简单的逻辑步骤,每个在下一步骤开始前完成,例如:

Event Task Step
preInstall Get the service binaries
install Unzip the service binaries
postInstall Tweak configuration files as required
preStart Verify the installation files and folder structure
start

Start the service

postStart Register service instances with a load balancer

这种方法使配方更容易维护和故障排除。此外,通过设计事件外部处理程序脚本这种方式,可以在不同的应用程序重用他们的recipes。

标签: