你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

Azure CDN 开发入门

可以使用适用于 JavaScript 的 Azure CDN SDK 来自动创建和管理 CDN 配置文件和终结点。 本教程介绍一个简单的 Node.js 控制台应用程序的创建示例,演示几个可用的操作。 本教程不会详细介绍适用于 JavaScript 的 Azure CDN SDK 的所有方面。

要完成本教程,应已安装并配置了 Node.js 6.x.x 或更高版本。 可以使用任何需要的文本编辑器创建 Node.js 应用程序。 为了编写本教程,我使用了 Visual Studio Code

先决条件

在编写 CDN 管理代码之前,需要做一些准备工作,使代码能够与 Azure 资源管理器进行交互。 若要执行此准备工作,你需要:

  • 创建一个资源组,用来包含本教程中创建的 CDN 配置文件
  • 配置 Microsoft Entra ID 以提供应用程序的身份验证
  • 将权限应用于资源组,使得只有来自 Microsoft Entra 租户的已授权用户可与 CDN 配置文件进行交互

创建资源组

  1. 登录到 Azure 门户

  2. 单击“创建资源”。

  3. 搜索“资源组”,在“资源组”窗格中,单击“创建”。

    创建新资源组

  4. 将资源组命名为 CdnConsoleTutorial。 选择订阅,并选择离你最近的位置。 如果需要,可以单击“固定到仪表板”复选框,将资源组固定到门户中的仪表板。 这便于以后查找该资源组。 完成选择后,单击“创建”。

    “资源组”对话框的屏幕截图。

  5. 创建资源组之后,如果未将它固定到仪表板,可以依次单击“浏览”和“资源组”找到它。 要打开该资源组,请单击它。 记下订阅 ID。 稍后需要用到此信息。

    CDN 控制台教程部分的屏幕截图。

创建 Microsoft Entra 应用程序并应用权限

可通过下面两种方式在 Microsoft Entra ID 中进行应用身份验证:个人用户或服务主体。 服务主体类似于 Windows 中的服务帐户。 不是向特定用户授予与 CDN 配置文件进行交互的权限,权限将授予给服务主体。 服务主体通常用于自动化的非交互式流程。 尽管本教程涉及到编写交互式控制台应用,但重点介绍服务主体身份验证方式。

创建服务主体需要多个步骤,包括创建 Microsoft Entra 应用程序。 要创建它,请遵循此教程

重要

请务必遵循链接的教程中的所有步骤。 必须完全按照说明完成操作,这很重要。 请务必记下租户 ID租户域名(通常是 .onmicrosoft.com 域,除非指定了自定义域)、客户端 ID客户端身份验证密钥,因为稍后需要用到这些信息。 请妥善保护客户端 ID客户端身份验证密钥,因为任何人都可以使用这些凭据以服务主体的身份执行操作。

执行“Configure multi-tenant application”(配置多租户应用程序)步骤时,请选择“No”(否)。

执行将应用程序分配到角色步骤时,请使用前面创建的资源组 CdnConsoleTutorial 而不是“读者”角色来分配“CDN 配置文件参与者”角色。 在资源组中为应用程序分配“CDN 配置文件参与者”角色之后,请返回本教程。

创建服务主体并分配“CDN 配置文件参与者”角色之后,资源组的“用户”边栏选项卡看起来应类似于以下图像。

“用户”边栏选项卡

交互式用户身份验证

如果想要使用交互式个人用户身份验证而不是服务主体身份验证,操作过程与适用于服务主体的过程类似。 事实上,需要遵循的过程基本相同,只是要做一些轻微的更改。

重要

仅当选择使用个人用户身份验证而不是服务主体身份验证时,才要执行后续步骤。

  1. 创建应用程序时,请选择“本机应用程序”而不是“Web 应用程序”。

    本机应用程序

  2. 在下一页上,系统会提示输入重定向 URI。 系统不会验证 URI,但请记住输入的 URI。 稍后需要用到此信息。

  3. 不需要创建客户端身份验证密钥

  4. 我们不会向“CDN 配置文件参与者”角色分配服务主体,而是分配个人用户或组。 在本示例中,可以看到已将“CDN 演示用户”分配到“CDN 配置文件参与者”角色。

    个人用户访问权限

创建项目并添加 npm 依赖项

现在我们已经为 CDN 配置文件创建了一个资源组,并且向 Azure AD 应用程序授予了管理该组中的 CDN 配置文件和终结点的权限,接下来可以开始创建应用程序了。

创建一个文件夹以存储应用程序。 在当前路径中带有 Node.js 工具的控制台中,将当前位置设置为此新文件夹,并通过执行以下命令来初始化项目:

npm init

然后,将看到一系列问题,用于初始化项目。 对于入口点,本教程使用 app.js。 可以在下面的例子中看到我的其他选择。

NPM init 输出的屏幕截图。

我们的项目现在使用 packages.json 文件进行初始化。 我们的项目将使用 npm 包中包含的部分 Azure 库。 我们将使用 Node.js 中适用于 Microsoft Entra 身份验证的库 (@Azure/identity),以及适用于 JavaScript 的 Azure CDN 客户端库 (@Azure/Azure Resource Manager-cdn)。 让我们将它们作为依赖项添加到项目。

npm install --save @azure/identity
npm install --save @azure/arm-cdn

当包安装完成后,package.json 文件应与此示例类似(版本号可能不同):

{
  "name": "cdn_node",
  "version": "1.0.0",
  "description": "Azure CDN Node.js tutorial project",
  "main": "app.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "Cam Soper",
  "license": "MIT",
  "dependencies": {
    "@azure/arm-cdn": "^7.0.1",
    "@azure/identity": "^2.0.4"
  }
}

最后,使用文本编辑器创建一个空白文本文件,并在项目文件夹的根目录中将其保存为 app.js。 我们已经准备好编写代码。

要求、常量、身份验证和结构

在编辑器中打开 app.js 后,让我们来编写程序的基本结构。

  1. 在顶部用以下指令为我们的 npm 包添加“require”:

    const { DefaultAzureCredential } = require("@azure/identity");
    const { CdnManagementClient } = require('@azure/arm-cdn');
    
  2. 我们需要定义我们的方法将使用的一些常量。 添加以下内容。 请务必根据需要使用值替换占位符,包括 <尖括号>

    //Tenant app constants
    const clientId = "<YOUR CLIENT ID>";
    const clientSecret = "<YOUR CLIENT AUTHENTICATION KEY>"; //Only for service principals
    const tenantId = "<YOUR TENANT ID>";
    
    //Application constants
    const subscriptionId = "<YOUR SUBSCRIPTION ID>";
    const resourceGroupName = "CdnConsoleTutorial";
    const resourceLocation = "<YOUR PREFERRED AZURE LOCATION, SUCH AS Central US>";
    
  3. 接下来,我们将实例化 CDN 管理客户端并为其提供凭据。

    var credentials = new DefaultAzureCredential();
    var cdnClient = new CdnManagementClient(credentials, subscriptionId);
    
  4. 我们的 Node.js 控制台应用程序会采用一些命令行参数。 让我们验证是否至少传递了一个参数。

    //Collect command-line parameters
    var parms = process.argv.slice(2);
    
    //Do we have parameters?
    if(parms == null || parms.length == 0)
    {
        console.log("Not enough parameters!");
        console.log("Valid commands are list, delete, create, and purge.");
        process.exit(1);
    }
    
  5. 这使我们进入程序的主要部分,在那里我们会基于传递的参数转到其他函数分支。

    switch(parms[0].toLowerCase())
    {
        case "list":
            cdnList();
            break;
    
        case "create":
            cdnCreate();
            break;
    
        case "delete":
            cdnDelete();
            break;
    
        case "purge":
            cdnPurge();
            break;
    
        default:
            console.log("Valid commands are list, delete, create, and purge.");
            process.exit(1);
    }
    
  6. 在程序的数个位置中,我们需要确保传入了正确数量的参数,如果它们看起来不正确,系统会显示一些帮助。 让我们创建函数以执行该操作。

    function requireParms(parmCount) {
        if(parms.length < parmCount) {
            usageHelp(parms[0].toLowerCase());
            process.exit(1);
        }
    }
    
    function usageHelp(cmd) {
        console.log("Usage for " + cmd + ":");
        switch(cmd)
        {
            case "list":
                console.log("list profiles");
                console.log("list endpoints <profile name>");
                break;
    
            case "create":
                console.log("create profile <profile name>");
                console.log("create endpoint <profile name> <endpoint name> <origin hostname>");
                break;
    
            case "delete":
                console.log("delete profile <profile name>");
                console.log("delete endpoint <profile name> <endpoint name>");
                break;
    
            case "purge":
                console.log("purge <profile name> <endpoint name> <path>");
                break;
    
            default:
                console.log("Invalid command.");
        }
    }
    
  7. 最后,我们会在 CDN 管理客户端上使用的函数是异步的,因此它们完成后需要一个回调方法。 让我们创建一个可以显示 CDN 管理客户端中输出(如有)并且能正常退出程序的函数。

    function callback(err, result, request, response) {
        if (err) {
            console.log(err);
            process.exit(1);
        } else {
            console.log((result == null) ? "Done!" : result);
            process.exit(0);
        }
    }
    

既然已经编写了程序的基本结构,我们现在应该创建基于我们的参数调用的函数。

列出 CDN 配置文件和终结点

让我们先从可列出现有配置文件和终结点的代码开始。 我的代码注释提供了预期的语法,以便我们了解每个参数的动向。

// list profiles
// list endpoints <profile name>
function cdnList(){
    requireParms(2);
    switch(parms[1].toLowerCase())
    {
        case "profiles":
            console.log("Listing profiles...");
            cdnClient.profiles.listByResourceGroup(resourceGroupName, callback);
            break;

        case "endpoints":
            requireParms(3);
            console.log("Listing endpoints...");
            cdnClient.endpoints.listByProfile(resourceGroupName, parms[2], callback);
            break;

        default:
            console.log("Invalid parameter.");
            process.exit(1);
    }
}

创建 CDN 配置文件和终结点

接下来,我们将编写用于创建配置文件和终结点的函数。

function cdnCreate() {
    requireParms(2);
    switch(parms[1].toLowerCase())
    {
        case "profile":
            cdnCreateProfile();
            break;

        case "endpoint":
            cdnCreateEndpoint();
            break;

        default:
            console.log("Invalid parameter.");
            process.exit(1);
    }
}

// create profile <profile name>
async function cdnCreateProfile() {
    requireParms(3);
    console.log("Creating profile...");
    var standardCreateParameters = {
        location: resourceLocation,
        sku: {
            name: 'Standard_Verizon'
        }
    };

    await cdnClient.profiles.beginCreateAndWait( resourceGroupName, parms[2], standardCreateParameters, callback);
}

// create endpoint <profile name> <endpoint name> <origin hostname>        
async function cdnCreateEndpoint() {
    requireParms(5);
    console.log("Creating endpoint...");
    var endpointProperties = {
        location: resourceLocation,
        origins: [{
            name: parms[4],
            hostName: parms[4]
        }]
    };

    await cdnClient.endpoints.beginCreateAndWait(resourceGroupName, parms[2], parms[3], endpointProperties, callback);
}

清除终结点

假设终结点已经创建,我们可能想在我们的程序中执行的一个常见任务是清除终结点中的内容。

// purge <profile name> <endpoint name> <path>
async function cdnPurge() {
    requireParms(4);
    console.log("Purging endpoint...");
    var purgeContentPaths = [ parms[3] ];
    await cdnClient.endpoints.beginPurgeContentAndWait(resourceGroupName, parms[2], parms[3], purgeContentPaths, callback);
}

删除 CDN 配置文件和终结点

我们将包括的最后一个函数将删除终结点和配置文件。

async function cdnDelete() {
    requireParms(2);
    switch(parms[1].toLowerCase())
    {
        // delete profile <profile name>
        case "profile":
            requireParms(3);
            console.log("Deleting profile...");
            await cdnClient.profiles.beginDeleteAndWait(resourceGroupName, parms[2], callback);
            break;

        // delete endpoint <profile name> <endpoint name>
        case "endpoint":
            requireParms(4);
            console.log("Deleting endpoint...");
            await cdnClient.endpoints.beginDeleteAndWait(resourceGroupName, parms[2], parms[3], callback);
            break;

        default:
            console.log("Invalid parameter.");
            process.exit(1);
    }
}

运行程序

现在可以使用我们最喜爱的调试器,或在控制台执行我们的 Node.js 程序。

提示

如果使用 Visual Studio Code 作为调试器,则需要设置环境以传递命令行参数。 Visual Studio Code 在 launch.json 文件中执行此操作。 寻找名为 args 的属性,并为参数添加一个字符串值数组,以使其看起来类似于:"args": ["list", "profiles"]

让我们首先列出我们的配置文件。

列出配置文件

返回了一个空数组。 因为我们的资源组中没有任何配置文件,所以这是预期的情况。 现在让我们创建一个配置文件。

创建配置文件

现在,让我们添加一个终结点。

创建终结点

最后,让我们删除配置文件。

删除配置文件

后续步骤

要查看有关适用于 JavaScript 的 Azure CDN SDK 的参考,请查看参考

要查找有关适用于 JavaScript 的 Azure SDK 的其他文档,请查看完整参考

使用 PowerShell 管理 CDN 资源。