使用 IBM Cloud 时,经常遇见的一个问题是“如何在 IBM Cloud 上安排任务?”使用 IBM 裸机服务器时,答案很简单:使用 cron 或一个类似的调度程序。但在使用 IBM Cloud 平台即服务 (PaaS) 时,答案稍微复杂一点。
IBM Cloud PaaS 没有类似 cron 的系统调度程序。它提供了 Workload Scheduler 服务,这是一个可以连接到您的 IBM Cloud 应用程序的特殊服务实例。此服务实例允许您自定义流程,这些流程按预先确定的时间表运行,并且能与其他各种工具集成,比如 Cloudant、MQTT、Hadoop 和 OpenWhisk。
在本教程中,我将通过一个真实示例介绍 Workload Scheduler 服务:保存应用程序数据库的每日备份。通过完成这个示例,您将了解所涉及的步骤,并能调整它们,使其适合您自己的进程调度用例。
在 GitHub 上获取样本代码
对于执行大量活动的应用程序,维护应用程序数据的定期备份很重要。在大多数情况下,这类数据被存储在一个数据库中,但它们也有可能采用文件资产或活动日志的形式。根据生成的数据量,可能需要每小时、每天、每周或按自定义时间间隔进行备份。
在本示例中,我假设应用程序的数据被存储在一个 MySQL 数据库中,而且此数据需要每天备份(作为一个 SQL 文件)。为了安全起见,备份应该与应用程序本身分开存储。本示例使用 Dropbox 作为备份存储区,但您可以使用任何存储服务,包括 IBM Cloud 自己的 Object Storage 服务。
本示例使用了 Workload Scheduler 服务的 REST 集成,通过在指定时间调用指定的 URL 端点来执行备份。这个 URL 端点是一个 PHP 脚本,它在内部执行以下操作:
通过 IBM Cloud Lite 快速轻松地构建您的下一个应用程序。您的免费帐户永不过期,而且您会获得 256 MB 的 Cloud Foundry 运行时内存,以及包含 Kubernetes 集群的 2 GB 存储空间。了解所有细节并确定如何开始。如果您不熟悉 IBM Cloud,请查阅 developerWorks 上的 IBM Cloud Essentials 课程 。
在开始之前,请确保您完成了需要做的所有准备工作:
备注:任何使用 Dropbox 和 SendGrid 服务的应用程序都必须分别遵守 Dropbox 和 SendGrid 服务条款。类似地,任何使用 IBM Cloud Platform 的应用程序都必须遵守IBM Cloud 的使用条款。开始实施您的项目之前,花几分钟阅读一下这些要求,确保您的应用程序满足这些要求。
“ 本教程仅介绍一个可能遇到的示例。您可以使用这里列出的流程来执行其他计划任务,比如发送每日活动摘要,清理不想要的文件,对日志进行归档等。 ”
要执行其任务,PHP 脚本需要使用以下依赖项:
{ "require": { "ifsnop/mysqldump-php": "2.*", "sendgrid/sendgrid": "6.*", "kunalvarma05/dropbox-php-sdk": “0.2.1" } }
shell> php composer.phar install
shell> cd myapp shell> mkdir public data
<?php $config = [ 'settings' => [ 'db' => [ 'name' => 'DATABASE-NAME', 'hostname' => 'DATABASE-HOST', 'username' => 'DATABASE-USERNAME', 'password' => 'DATABASE-PASSWORD', ], 'dropbox' => [ 'app-key' => 'DROPBOX-APP-KEY', 'app-secret' => 'DROPBOX-APP-SECRET', 'app-token' => 'DROPBOX-APP-TOKEN', 'app-folder' => 'DROPBOX-APP-FOLDER', ], 'sendgrid' => [ 'key' => 'SENDGRID-API-KEY', 'to' => 'RECIPIENT-EMAIL-ADDRESS' ], 'token' => 'guessme', ] ];
为了将文件上传到 Dropbox,该 PHP 脚本需要使用来自上一步的 Dropbox API PHP 客户端。这个客户端需要 3 个关键信息:一个 Dropbox 应用程序密钥、Dropbox 应用程序密码和一个应用程序令牌。此信息可从 Dropbox Web 仪表板获得。首先:
重要事项:不要与任何人共享 Dropbox 访问令牌和应用程序秘密密钥。
要发送电子邮件通知,PHP 脚本需要使用 SendGrid API。SendGrid 提供了一个用于实现此目标的 PHP SDK。要使用它,必须先获得一个 SendGrid API 密钥。
现在,您已准备好开始构建将用作 REST 服务并执行备份的 PHP 脚本了。使用下面的代码,这些代码应保存到 $APP_ROOT /public/backup.php 中。
<?php // load classes require '../vendor/autoload.php'; // load configuration require '../config.php'; use Ifsnop/Mysqldump as Mysqldump; use Kunnu/Dropbox/DropboxApp; use Kunnu/Dropbox/Dropbox; use Kunnu/Dropbox/DropboxFile; try { // look for token in POST data // reject request if not found or mismatch $json = file_get_contents('php://input'); $obj = json_decode($json); if (isset($obj->token) && ($obj->token == $config['settings']['token'])) { // initialize MySQL client // connect to database and dump contents to file $dump = new Mysqldump/Mysqldump( 'mysql:host=' .$config['settings']['db']['hostname'] . ';dbname=' .$config['settings']['db']['name'], $config['settings']['db']['username'], $config['settings']['db']['password'] ); $filename = '../data/' .$config['settings']['db']['name'] .'-' . date('Y-m-d-h-i-s', time()) .'.sql'; $dump->start($filename); // initialize Dropbox client $app = new DropboxApp( $config['settings']['dropbox']['app-key'], $config['settings']['dropbox']['app-secret'], $config['settings']['dropbox']['app-token'] ); $dropbox = new Dropbox($app); $dropboxFile = new DropboxFile($filename); $uploadedFile = $dropbox->upload($dropboxFile, "/" . basename($filename)); unlink($filename); // initialize SendGrid client $sg = new /SendGrid($config['settings']['sendgrid']['key']); $from = new SendGrid/Email(null, "no-reply@example.com"); $subject = "Database backup notification"; $to = new SendGrid/Email(null, $config['settings']['sendgrid']['to']); $content = new SendGrid/Content( "text/plain", "Your database backup was successful.Your backup filename is: " . basename($filename)); $mail = new SendGrid/Mail($from, $subject, $to, $content); $response = $sg->client->mail()->send()->post($mail); if ($response->statusCode() != 200 && $response->statusCode() != 202) { throw new /Exception('SendGrid failure, response code ' . $response->statusCode() ); } http_response_code(200); echo 'Backup successful'; } else { throw new Exception ('Invalid authentication token'); } } catch (/Exception $e) { http_response_code(500); echo $e->getMessage(); } exit;
此脚本执行了大量操作,让我们逐步分析一下:
POST
请求。如果找到一个请求,则在该请求中查找 “token”
密钥。将提供的令牌与配置文件中指定的令牌进行匹配。仅在令牌匹配时,才能进一步处理该请求。这提供了一个最简单的安全层,并确保仅接受有效的请求。 start()
方法,将目标数据库的内容导出到一个 SQL 文件,该文件(临时)存储在 data/ 目录中。 upload()
方法将 SQL 文件从 data/ 目录转移到 Dropbox 上的应用程序文件夹。然后删除临时文件。 post()
方法,通过 SendGrid 的服务器传输消息。 200
(正常)或 500
(错误)HTTP 响应代码终止。 要连接到目标 MySQL 数据库,PHP 脚本需要数据库主机名、用户名、密码和数据库名称。您有两个选择来指定这些值:
try
代码块之前(根据您连接到的服务,您可能需要使用不同的 JSON 密钥;本示例使用了 ClearDB)。 <?php // if IBM Cloud VCAP_SERVICES environment available // overwrite local credentials with IBM Cloud credentials if ($services = getenv("VCAP_SERVICES")) { $services_json = json_decode($services, true); $config['settings']['db']['hostname'] = $services_json['cleardb'][0]['credentials']['hostname']; $config['settings']['db']['username'] = $services_json['cleardb'][0]['credentials']['username']; $config['settings']['db']['password'] = $services_json['cleardb'][0]['credentials']['password']; $config['settings']['db']['name'] = $services_json['cleardb'][0]['credentials']['name']; }
默认情况下,第 2 步中创建的配置文件包含一个简单的身份验证令牌。这个令牌用于验证传入的 POST
请求。在部署该脚本之前,您应该将此令牌更新为只有您知道的一个不同值。
可以将执行备份的 PHP 脚本作为一个独立应用程序或另一个应用程序的一部分来部署到 IBM Cloud。只要可以通过公有 URL 访问它,Workload Scheduler 服务就能调用它。这为您提供了两个主要的部署选项:
请注意,在两种选项中,都可以将数据库实例连接到您的应用程序,并直接从 IBM Cloud 环境读取密钥变量(比如数据库凭证),而不使用配置文件。请参阅第 5 步了解关于操作方法的细节。
--- applications: - name: myapp-[initials] memory: 256M instances: 1 host: myapp-[initials] buildpack: https://github.com/cloudfoundry/php-buildpack.git stack: cflinuxfs2
{ "WEB_SERVER": "httpd", "WEBDIR": "public", "PHP_VERSION": "{PHP_70_LATEST}" }
extension=mysqli.so extension=mbstring.so extension=pdo.so extension=pdo_mysql.so
shell> cf api https://api.ng.bluemix.net shell> cf login shell> cf push
shell> cf bind-service myapp-[initials] "[database-service-id]"
shell> cf restage myapp-[initials]
POST
请求来测试该脚本。在 POST
请求中包含一个 JSON 文档,其中含有第 5 步中定义的令牌,如下所示: { "token": "guessme" }
如果一切正常,该 PHP 脚本会执行备份,并以 HTTP 200
成功代码作为响应。如果发生错误,响应将是 HTTP 500
错误代码,而且响应输出将包含对错误的描述。
如果成功备份,您应该能够在您的 Dropbox 应用程序文件夹中看到 SQL 文件。如果发生错误,可以使用“调试 IBM Cloud 上的 PHP 错误”来调试该脚本(参见下面的“相关主题”)。
现在您已能通过 POST
请求来手动触发备份,只剩下对该过程执行自动化了:
POST
。在 Body 部分,将请求内容类型指定为“application/json”,并创建一个包含令牌作为正文内容的 JSON 文档。
Workload Scheduler 现在应按定义的时间表运行该流程,而且每次都会调用 REST 端点并创建数据库的全新备份。可使用该流程的 History 选项卡来监控流程的执行。
本教程的目的是解释如何在 IBM Cloud 上安排任务。我考虑了一个常见用例(对应用程序数据执行定期备份),并描述了如何通过一个 IBM Cloud Workload Scheduler 实例以及可通过 REST 访问的 PHP 脚本来实现此目标。我使用了两个外部服务(用于存储文件的 Dropbox 和用于传送通知的 SendGrid)来演示如何使用 Workload Scheduler,以便利用 IBM Cloud 服务和第三方服务,按循环执行的时间表来执行任务。
显然,本教程仅介绍了一个可能遇到的示例。您可以使用这里列出的流程来执行其他计划任务,比如发送每日活动摘要,清理不想要的文件,对日志进行归档等。可以在 GitHub 上获取这里使用的 PHP 脚本,将此脚本作为起点。试用该脚本,然后开始修改它来满足您的特定需求。编码愉快!