Synthetics 运行时版本
创建或更新金丝雀时,您可以为金丝雀选择 Synthetics 运行时版本。Synthetics 运行时是调用脚本处理程序的 Synthetics 代码,以及捆绑依赖关系的 Lambda 层的组合。
CloudWatch Synthetics 目前支持将 Node.js 用于脚本和 Puppeteer 框架的运行时,以及使用 Python 编写脚本和将 Selenium Webdriver 用于框架的运行时。
我们建议您始终为金丝雀使用最新的运行时版本,以便能够使用最新的功能和对 Synthetics 库进行的更新。
当您创建金丝雀时,所创建的其中一个层是前面加上 Synthetics
的 Synthetics 层。该层归 Synthetics 服务账户所有,且包含运行时系统代码。
注意
每当您升级金丝雀以使用新版本的 Synthetics 运行时时,您的金丝雀使用的所有 Synthetics 库函数也会自动升级到 Synthetics 运行时支持的相同 NodeJS 版本。
CloudWatch Synthetics 运行时支持策略
Synthetics 运行时版本受维护和安全更新的约束。如果不再支持运行时版本的任何组件,则该 Synthetics 运行时版本将被弃用。
您无法使用已弃用的运行时版本创建金丝雀。使用已弃用运行时的金丝雀将继续运行。您可以停止、启动和删除这些金丝雀。您可以通过将金丝雀更新为使用受支持的运行时版本,来更新使用已弃用运行时版本的现有金丝雀。
如果您有使用计划将在未来 60 天内弃用的运行时的金丝雀,则 CloudWatch Synthetics 会通过电子邮件通知您。我们建议您将金丝雀迁移到受支持的运行时版本,以享受最新版本中包含的新功能、安全性和性能增强的益处。
如何将金丝雀更新到新的运行时版本?
您可以使用 CloudWatch 控制台、AWS CloudFormation、AWS CLI 或 AWS SDK 更新金丝雀的运行时版本。当使用 CloudWatch 控制台更新时,您可以一次最多更新五个金丝雀,方法是在金丝雀列表页面中选中它们,然后选择 Actions(操作)、Update Runtime(更新运行时)。
要验证升级,您可以先使用 CloudWatch 控制台克隆金丝雀,然后更新其运行时版本。这会再创建一个金丝雀,其是原始金丝雀的克隆。在使用新的运行时版本验证了金丝雀后,您便可以更新原始金丝雀的运行时版本并删除克隆金丝雀。
您还可以使用升级脚本更新多个金丝雀。有关更多信息,请参阅 金丝雀运行时升级脚本。
如果升级金丝雀失败,请参阅 排查失败金丝雀的问题。
运行时弃用日期
运行时版本 | 弃用日期 |
---|---|
|
2024 年 3 月 8 日 |
|
2024 年 3 月 8 日 |
|
2024 年 3 月 8 日 |
|
2024 年 3 月 8 日 |
|
2024 年 3 月 8 日 |
|
2024 年 1 月 8 日 |
|
2024 年 1 月 8 日 |
|
2024 年 3 月 8 日 |
|
2024 年 3 月 8 日 |
|
2024 年 3 月 8 日 |
|
2024 年 3 月 8 日 |
|
2024 年 3 月 8 日 |
|
2024 年 1 月 8 日 |
|
2024 年 1 月 8 日 |
|
2024 年 1 月 8 日 |
|
2022 年 11 月 13 日 |
|
2022 年 11 月 13 日 |
|
2022 年 11 月 13 日 |
|
2022 年 11 月 13 日 |
|
2022 年 11 月 13 日 |
|
2021 年 5 月 28 日 |
|
2021 年 5 月 28 日 |
|
2021 年 5 月 28 日 |
|
2021 年 2 月 8 日 |
|
2021 年 5 月 28 日 |
金丝雀运行时升级脚本
若要将金丝雀脚本升级到支持的运行时版本,请使用以下脚本。
const AWS = require('aws-sdk'); // You need to configure your AWS 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)); }