Synthetics 运行时版本 - Amazon CloudWatch
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅中国的 Amazon Web Services 服务入门

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

Synthetics 运行时版本

创建或更新 Canary 时,您可以为 Canary 选择 Synthetics 运行时版本。Synthetics 运行时是调用脚本处理程序的 Synthetics 代码,以及捆绑依赖关系的 Lambda 层的组合。

CloudWatch Synthetics 目前支持脚本和木偶框架使用 Node.js 的运行时,以及使用 Python 编写脚本和框架的硒网络驱动程序的运行时。

我们建议您始终为 Canary 使用最新的运行时版本,以便能够使用最新的功能和对 Synthetics 库进行的更新。

CloudWatch Synthetics 运行时支持策略

Synthetics 运行时版本受维护和安全更新的约束。如果运行时版本的任何组件不再受支持,则该 Synthetics 运行时版本将被弃用。

您无法使用已弃用的运行时版本创建 Canary。使用已弃用运行时的 Canary 将继续运行。您可以停止、启动和删除这些 Canary。您可以通过将 Canary 更新为使用受支持的运行时版本,来更新使用已弃用运行时版本的现有 Canary。

如果您的金丝雀使用计划在未来 60 天内弃用的运行时,CloudWatch Synthetics 器将通过电子邮件通知您。我们建议您将 Canary 迁移到受支持的运行时版本,以便从最新版本中包含的新功能、安全性和性能增强中获益。

如何将金丝雀更新到新的运行时版本?

您可以通过使用 CloudWatch 控制台更新金丝雀的运行时版本Amazon CloudFormation,Amazon CLI或Amazon开发工具包。当您使用 CloudWatch 控制台时,您可以一次更新多达五个金丝雀,方法是在金丝雀列表页面中选择它们,然后选择操作更新运行时.

您可以通过首先使用 CloudWatch 控制台克隆金丝雀并更新其运行时版本来验证升级。这创建了另一个金丝雀,这是你原来的金丝雀的克隆。一旦您使用新的运行时版本验证了您的金丝雀,您可以更新原始金丝雀的运行时版本并删除克隆金丝雀。

您还可以使用升级脚本更新多个金丝雀。有关更多信息,请参阅金丝雀运行时升级脚本

如果升级金丝雀并失败,请参阅故障的金丝雀故障排除.

运行时弃用日期

运行时版本 弃用日期

syn-nodejs-2.2

2021 年 5 月 28 日

syn-nodejs-2.1

2021 年 5 月 28 日

syn-nodejs-2.0

2021 年 5 月 28 日

syn-nodejs-2.0-beta

2021 年 2 月 8 日

syn-1.0

2021 年 5 月 28 日

金丝雀运行时升级脚本

要将 Canary 脚本升级到支持的运行时版本,请使用以下脚本。

const AWS = require('aws-sdk'); // You need to configure your Amazon credentials and Region. // https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/setting-credentials-node.html // https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/setting-region.html const synthetics = new AWS.Synthetics(); const DEFAULT_OPTIONS = { /** * The number of canaries to upgrade during a single run of this script. */ count: 10, /** * No canaries are upgraded unless force is specified. */ force: false }; /** * The number of milliseconds to sleep between GetCanary calls when * verifying that an update succeeded. */ const SLEEP_TIME = 5000; (async () => { try { const options = getOptions(); const versions = await getRuntimeVersions(); const canaries = await getAllCanaries(); const upgrades = canaries .filter(canary => !versions.isLatestVersion(canary.RuntimeVersion)) .map(canary => { return { Name: canary.Name, FromVersion: canary.RuntimeVersion, ToVersion: versions.getLatestVersion(canary.RuntimeVersion) }; }); if (options.force) { const promises = []; for (const upgrade of upgrades.slice(0, options.count)) { const promise = upgradeCanary(upgrade); promises.push(promise); // Sleep for 100 milliseconds to avoid throttling. await usleep(100); } const succeeded = []; const failed = []; for (let i = 0; i < upgrades.slice(0, options.count).length; i++) { const upgrade = upgrades[i]; const promise = promises[i]; try { await promise; console.log(`The update of ${upgrade.Name} succeeded.`); succeeded.push(upgrade.Name); } catch (e) { console.log(`The update of ${upgrade.Name} failed with error: ${e}`); failed.push({ Name: upgrade.Name, Reason: e }); } } if (succeeded.length) { console.group('The following canaries were upgraded successfully.'); for (const name of succeeded) { console.log(name); } console.groupEnd() } else { console.log('No canaries were upgraded successfully.'); } if (failed.length) { console.group('The following canaries were not upgraded successfully.'); for (const failure of failed) { console.log('\x1b[31m', `${failure.Name}: ${failure.Reason}`, '\x1b[0m'); } console.groupEnd(); } } else { console.log('Run with --force [--count <count>] to perform the first <count> upgrades shown. The default value of <count> is 10.') console.table(upgrades); } } catch (e) { console.error(e); } })(); function getOptions() { const force = getFlag('--force', DEFAULT_OPTIONS.force); const count = getOption('--count', DEFAULT_OPTIONS.count); return { force, count }; function getFlag(key, defaultValue) { return process.argv.includes(key) || defaultValue; } function getOption(key, defaultValue) { const index = process.argv.indexOf(key); if (index < 0) { return defaultValue; } const value = process.argv[index + 1]; if (typeof value === 'undefined' || value.startsWith('-')) { throw `The ${key} option requires a value.`; } return value; } } function getAllCanaries() { return new Promise((resolve, reject) => { const canaries = []; synthetics.describeCanaries().eachPage((err, data) => { if (err) { reject(err); } else { if (data === null) { resolve(canaries); } else { canaries.push(...data.Canaries); } } }); }); } function getRuntimeVersions() { return new Promise((resolve, reject) => { const jsVersions = []; const pythonVersions = []; synthetics.describeRuntimeVersions().eachPage((err, data) => { if (err) { reject(err); } else { if (data === null) { jsVersions.sort((a, b) => a.ReleaseDate - b.ReleaseDate); pythonVersions.sort((a, b) => a.ReleaseDate - b.ReleaseDate); resolve({ isLatestVersion(version) { const latest = this.getLatestVersion(version); return latest === version; }, getLatestVersion(version) { if (jsVersions.some(v => v.VersionName === version)) { return jsVersions[jsVersions.length - 1].VersionName; } else if (pythonVersions.some(v => v.VersionName === version)) { return pythonVersions[pythonVersions.length - 1].VersionName; } else { throw Error(`Unknown version ${version}`); } } }); } else { for (const version of data.RuntimeVersions) { if (version.VersionName === 'syn-1.0') { jsVersions.push(version); } else if (version.VersionName.startsWith('syn-nodejs-2.')) { jsVersions.push(version); } else if (version.VersionName.startsWith('syn-nodejs-puppeteer-')) { jsVersions.push(version); } else if (version.VersionName.startsWith('syn-python-selenium-')) { pythonVersions.push(version); } else { throw Error(`Unknown version ${version.VersionName}`); } } } } }); }); } async function upgradeCanary(upgrade) { console.log(`Upgrading canary ${upgrade.Name} from ${upgrade.FromVersion} to ${upgrade.ToVersion}`); await synthetics.updateCanary({ Name: upgrade.Name, RuntimeVersion: upgrade.ToVersion }).promise(); while (true) { await usleep(SLEEP_TIME); console.log(`Getting the state of canary ${upgrade.Name}`); const response = await synthetics.getCanary({ Name: upgrade.Name }).promise(); const state = response.Canary.Status.State; console.log(`The state of canary ${upgrade.Name} is ${state}`); if (state === 'ERROR' || response.Canary.Status.StateReason) { throw response.Canary.Status.StateReason; } if (state !== 'UPDATING') { return; } } } function usleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); }