使用 Visual Studio Code 將 Azure Functions 連線至 Azure 儲存體

Azure Functions 可讓您直接將 Azure 服務和其他資源連線至函式,而不需要自行撰寫整合程式碼。 這些繫結同時代表輸入和輸出,會宣告於函式定義內。 繫結中的資料會提供給函式作為參數。 「觸發程序」是一種特殊的輸入繫結。 雖然函式只有一個觸發程序,但可以有多個輸入和輸出繫結。 若要深入了解,請參閱 Azure Functions 觸發程序和繫結概念

本文會帶您了解如何使用 Visual Studio Code 將 Azure 儲存體連線至您在上一篇快速入門文章中建立的函式。 您新增至此函式的輸出繫結,會將資料從 HTTP 要求寫入至位於 Azure 佇列儲存體佇列中的訊息。

大部分的繫結都需要函式用來存取繫結服務的預存連接字串。 為了方便作業,可使用您以函數應用程式建立的儲存體帳戶。 此帳戶的連線已儲存在名為 AzureWebJobsStorage 的應用程式設定中。

注意

本文目前支援 Node.js v4 for Functions

設定您的本機環境

開始之前必須符合下列需求:

此文章假設您已從 Visual Studio Code 登入您的 Azure 訂用帳戶。 您可以從命令選擇區執行 Azure: Sign In 來登入。

下載函式應用程式設定

先前的快速入門文章中,您已在 Azure 中建立函數應用程式與必要的儲存體帳戶。 此帳戶的連接字串會安全地儲存在 Azure 的應用程式設定中。 在本文中,您會將訊息寫入至相同帳戶中的儲存體佇列。 在本機執行函式時若要連線至儲存體帳戶,必須將應用程式設定下載到 local.settings.json 檔案。

  1. F1 鍵可開啟命令選擇區,然後請搜尋並執行 Azure Functions: Download Remote Settings... 命令。

  2. 選擇您在先前的文章中所建立的函式應用程式。 選取 [全部皆是] 來覆寫現有的本機設定。

    重要

    由於 local.settings.json 檔案中包含祕密,因此一律不會受到發佈,且會排除在原始檔控制範圍之外。

  3. 複製 AzureWebJobsStorage 值,其為儲存體帳戶連接字串值的金鑰。 您將使用此連線來確認輸出繫結會如預期般運作。

註冊繫結延伸模組

由於您是使用佇列儲存體輸出繫結,您必須先安裝儲存體繫結擴充才能執行專案。

您的專案已設定為使用擴充功能配套,這會自動安裝一組預先定義的擴充功能套件。

擴充功能配套已在專案根目錄的 host. json 檔案中啟用,如下所示:

{
  "version": "2.0",
  "extensionBundle": {
    "id": "Microsoft.Azure.Functions.ExtensionBundle",
    "version": "[3.*, 4.0.0)"
  }
}

現在,您可以將儲存體輸出繫結新增至您的專案。

您的專案已設定為使用擴充功能配套,這會自動安裝一組預先定義的擴充功能套件。

擴充功能配套已在專案根目錄的 host. json 檔案中啟用,如下所示:

{
  "version": "2.0",
  "logging": {
    "applicationInsights": {
      "samplingSettings": {
        "isEnabled": true,
        "excludedTypes": "Request"
      }
    }
  },
  "extensionBundle": {
    "id": "Microsoft.Azure.Functions.ExtensionBundle",
    "version": "[4.*, 5.0.0)"
  }
}

現在,您可以將儲存體輸出繫結新增至您的專案。

除了 HTTP 和計時器觸發程序以外,繫結皆會以擴充套件的形式實作。 在終端機視窗中執行下列 dotnet add package 命令來將儲存體套件新增至您的專案。

dotnet add package Microsoft.Azure.Functions.Worker.Extensions.Storage.Queues --prerelease

現在,您可以將儲存體輸出繫結新增至您的專案。

新增輸出繫結

若要寫入 Azure 儲存體 佇列:

  • extraOutputs將屬性新增至系結組態

    {
        methods: ['GET', 'POST'],
        extraOutputs: [sendToQueue], // add output binding to HTTP trigger
        authLevel: 'anonymous',
        handler: () => {}
    }
    
  • 在呼叫上方app.http新增函output.storageQueue

    const sendToQueue = output.storageQueue({
      queueName: 'outqueue',
      connection: 'AzureWebJobsStorage',
    });
    

若要寫入 Azure 儲存體 佇列:

  • extraOutputs將屬性新增至系結組態

    {
        methods: ['GET', 'POST'],
        extraOutputs: [sendToQueue], // add output binding to HTTP trigger
        authLevel: 'anonymous',
        handler: () => {}
    }
    
  • 在呼叫上方app.http新增函output.storageQueue

    const sendToQueue: StorageQueueOutput = output.storageQueue({
      queueName: 'outqueue',
      connection: 'AzureWebJobsStorage',
    });
    

在 Functions 中,每種繫結型別都需要 directiontype 和唯一的 name。 定義這些屬性的方式會取決於您函式應用程式的語言。

繫結屬性定義於 function.json 檔案的特定函式中。 根據繫結類型,可能需要額外的屬性。 佇列輸出組態會說明 Azure 儲存體佇列繫結所需的欄位。 擴充功能可讓您輕鬆地將繫結加入至 function.json 檔案。

若要建立繫結,請以滑鼠右鍵按一下 (在 macOS 上則為 Ctrl+按一下) HttpTrigger 資料夾中的 function.json 檔案,然後選擇 [新增繫結]。遵循提示來針對新繫結定義下列繫結屬性:

提示 Description
選取繫結方向 out 此繫結為輸出繫結。
選取具有下列方向的繫結 Azure Queue Storage 此繫結是 Azure 儲存體佇列繫結。
用以在程式碼中識別此繫結的名稱 msg 識別您的程式碼中參考之繫結參數的名稱。
要接收訊息的佇列 outqueue 作為繫結寫入目標的佇列名稱。 當 queueName 不存在,繫結會在第一次使用時加以建立。
"local.setting.json" 選取設定 AzureWebJobsStorage 包含儲存體帳戶連接字串之應用程式設定的名稱。 AzureWebJobsStorage 設定會包含您以函式應用程式建立之儲存體帳戶的連接字串。

繫結會新增至 function.json 中的 bindings 陣列,此時應該會顯示如下:

      "name": "msg",
      "queueName": "outqueue",
      "connection": "AzureWebJobsStorage"
    }
  ]
}

繫結屬性是藉由在 function_app.py 檔案中裝飾特定函式程式碼來定義。 您可以使用 queue_output 裝飾項目來新增 Azure 佇列儲存體輸出繫結

藉由使用 queue_output 裝飾項目,繫結方向會是「輸出」,型別為 Azure 儲存體佇列。 將下列裝飾專案新增至 HttpExample\function_app.py中的函式程式代碼:

@app.queue_output(arg_name="msg", queue_name="outqueue", connection="AzureWebJobsStorage")

在此程式碼中,arg_name 會識別程式碼中參考的繫結參數、queue_name 是寫入繫結的佇列名稱,而 connection 是包含儲存體帳戶連接字串的應用程式設定名稱。 在快速入門中,您會使用與函數應用程式 (AzureWebJobsStorage 設定) 相同的儲存體帳戶。 當 queue_name 不存在,繫結會在第一次使用時加以建立。

在 C# 專案中,是將繫結定義為函式方法上的繫結屬性。 確切的定義取決於您的應用程式是否在程序中執行 (C# 類別庫),還是處於隔離的背景工作處理序中。

開啟 HttpExample.cs 專案檔,並新增下列 MultiResponse 類別:

public class MultiResponse
{
    [QueueOutput("outqueue",Connection = "AzureWebJobsStorage")]
    public string[] Messages { get; set; }
    public HttpResponseData HttpResponse { get; set; }
}

MultiResponse 類別可讓您寫入名為 outqueue 的儲存體佇列和 HTTP 成功訊息。 多個訊息可以傳送至佇列,因為 QueueOutput 屬性會套用至字串陣列。

Connection 屬性會設定儲存體帳戶的連接字串。 在此情況下,您可以省略 Connection,因為您已經正在使用預設的儲存體帳戶。

在 Java 專案中,繫結會被定義為函式方法上的繫結註釋。 系統接著會根據這些註釋自動產生 function.json 檔案。

瀏覽至 src/main/java 底下您的函式程式碼位置,開啟 Function java 專案檔案,然後將下列參數新增至 run 方法定義:

@QueueOutput(name = "msg", queueName = "outqueue", 
connection = "AzureWebJobsStorage") OutputBinding<String> msg,

msg 參數是 OutputBinding<T> 類型,其代表會在函式完成時寫入輸出繫結的字串集合。 在此情況下,輸出是名為 outqueue 的儲存體佇列。 儲存體帳戶的連接字串是由 connection 方法設定。 您會傳遞包含儲存體帳戶連接字串的應用程式設定,而不是連接字串本身。

run 方法定義現在應該如下列範例所示︰

@FunctionName("HttpExample")
public HttpResponseMessage run(
        @HttpTrigger(name = "req", methods = {HttpMethod.GET, HttpMethod.POST}, authLevel = AuthorizationLevel.ANONYMOUS) 
        HttpRequestMessage<Optional<String>> request, 
        @QueueOutput(name = "msg", queueName = "outqueue", 
        connection = "AzureWebJobsStorage") OutputBinding<String> msg, 
        final ExecutionContext context) {

新增會使用輸出繫結的程式碼

在定義繫結之後,您即可使用繫結的 name 來以函式簽章中屬性的形式存取它。 藉由使用輸出繫結,您無須使用 Azure 儲存體 SDK 程式碼來進行驗證、取得佇列參考或寫入資料。 Functions 執行階段和佇列輸出繫結會為您進行這些工作。

新增使用 上的 context.extraOutputs 輸出系結物件來建立佇列訊息的程序代碼。 在 return 語句之前新增此程式碼。

context.extraOutputs.set(sendToQueue, [msg]);

此時,函式看起來會如下所示:

const { app, output } = require('@azure/functions');

const sendToQueue = output.storageQueue({
  queueName: 'outqueue',
  connection: 'AzureWebJobsStorage',
});

app.http('HttpExample', {
  methods: ['GET', 'POST'],
  authLevel: 'anonymous',
  extraOutputs: [sendToQueue],
  handler: async (request, context) => {
    try {
      context.log(`Http function processed request for url "${request.url}"`);

      const name = request.query.get('name') || (await request.text());
      context.log(`Name: ${name}`);

      if (name) {
        const msg = `Name passed to the function ${name}`;
        context.extraOutputs.set(sendToQueue, [msg]);
        return { body: msg };
      } else {
        context.log('Missing required data');
        return { status: 404, body: 'Missing required data' };
      }
    } catch (error) {
      context.log(`Error: ${error}`);
      return { status: 500, body: 'Internal Server Error' };
    }
  },
});

新增使用 上的 context.extraOutputs 輸出系結物件來建立佇列訊息的程序代碼。 在 return 語句之前新增此程式碼。

context.extraOutputs.set(sendToQueue, [msg]);

此時,函式看起來會如下所示:

import {
  app,
  output,
  HttpRequest,
  HttpResponseInit,
  InvocationContext,
  StorageQueueOutput,
} from '@azure/functions';

const sendToQueue: StorageQueueOutput = output.storageQueue({
  queueName: 'outqueue',
  connection: 'AzureWebJobsStorage',
});

export async function HttpExample(
  request: HttpRequest,
  context: InvocationContext,
): Promise<HttpResponseInit> {
  try {
    context.log(`Http function processed request for url "${request.url}"`);

    const name = request.query.get('name') || (await request.text());
    context.log(`Name: ${name}`);

    if (name) {
      const msg = `Name passed to the function ${name}`;
      context.extraOutputs.set(sendToQueue, [msg]);
      return { body: msg };
    } else {
      context.log('Missing required data');
      return { status: 404, body: 'Missing required data' };
    }
  } catch (error) {
    context.log(`Error: ${error}`);
    return { status: 500, body: 'Internal Server Error' };
  }
}

app.http('HttpExample', {
  methods: ['GET', 'POST'],
  authLevel: 'anonymous',
  handler: HttpExample,
});

新增使用 Push-OutputBinding Cmdlet 的程式碼,以使用 msg 輸出繫結將文字寫入至佇列。 在 if 陳述式中設定「確定」狀態之前,請先新增此程式碼。

$outputMsg = $name
Push-OutputBinding -name msg -Value $outputMsg

此時,您的函式必須顯示如下:

using namespace System.Net

# Input bindings are passed in via param block.
param($Request, $TriggerMetadata)

# Write to the Azure Functions log stream.
Write-Host "PowerShell HTTP trigger function processed a request."

# Interact with query parameters or the body of the request.
$name = $Request.Query.Name
if (-not $name) {
    $name = $Request.Body.Name
}

if ($name) {
    # Write the $name value to the queue, 
    # which is the name passed to the function.
    $outputMsg = $name
    Push-OutputBinding -name msg -Value $outputMsg

    $status = [HttpStatusCode]::OK
    $body = "Hello $name"
}
else {
    $status = [HttpStatusCode]::BadRequest
    $body = "Please pass a name on the query string or in the request body."
}

# Associate values to output bindings by calling 'Push-OutputBinding'.
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
    StatusCode = $status
    Body = $body
})

msg 參數新增至函式定義和 if name: 陳述式下的 msg.set(name),以更新 HttpExample\function_app.py,使其符合下列程式碼:

import azure.functions as func
import logging

app = func.FunctionApp(http_auth_level=func.AuthLevel.ANONYMOUS)

@app.route(route="HttpExample")
@app.queue_output(arg_name="msg", queue_name="outqueue", connection="AzureWebJobsStorage")
def HttpExample(req: func.HttpRequest, msg: func.Out [func.QueueMessage]) -> func.HttpResponse:
    logging.info('Python HTTP trigger function processed a request.')

    name = req.params.get('name')
    if not name:
        try:
            req_body = req.get_json()
        except ValueError:
            pass
        else:
            name = req_body.get('name')

    if name:
        msg.set(name)
        return func.HttpResponse(f"Hello, {name}. This HTTP triggered function executed successfully.")
    else:
        return func.HttpResponse(
             "This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response.",
             status_code=200
        )

msg 參數是 azure.functions.Out class 的執行個體。 set 方法會將字串訊息寫入至佇列。 在此案例中,即為傳送至 URL 查詢字串中函式的 name

將現有的 HttpExample 類別取代為下列程式碼:

    [Function("HttpExample")]
    public static MultiResponse Run([HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequestData req,
        FunctionContext executionContext)
    {
        var logger = executionContext.GetLogger("HttpExample");
        logger.LogInformation("C# HTTP trigger function processed a request.");

        var message = "Welcome to Azure Functions!";

        var response = req.CreateResponse(HttpStatusCode.OK);
        response.Headers.Add("Content-Type", "text/plain; charset=utf-8");
        response.WriteString(message);

        // Return a response to both HTTP trigger and storage output binding.
        return new MultiResponse()
        {
            // Write a single message.
            Messages = new string[] { message },
            HttpResponse = response
        };
    }
}

現在,您可以使用新的 msg 參數,從您的函式程式碼寫入輸出繫結。 在成功回應之前新增下列一行程式碼,以將 name 的值新增至 msg 輸出繫結。

msg.setValue(name);

當您使用輸出繫結時,無須使用 Azure 儲存體 SDK 程式碼來進行驗證、取得佇列參考或寫入資料。 Functions 執行階段和佇列輸出繫結會為您進行這些工作。

您的 run 方法現在看起來應該如下列範例所示:

@FunctionName("HttpExample")
public HttpResponseMessage run(
        @HttpTrigger(name = "req", methods = {HttpMethod.GET, HttpMethod.POST}, authLevel = AuthorizationLevel.ANONYMOUS) 
        HttpRequestMessage<Optional<String>> request, 
        @QueueOutput(name = "msg", queueName = "outqueue", 
        connection = "AzureWebJobsStorage") OutputBinding<String> msg, 
        final ExecutionContext context) {
    context.getLogger().info("Java HTTP trigger processed a request.");

    // Parse query parameter
    String query = request.getQueryParameters().get("name");
    String name = request.getBody().orElse(query);

    if (name == null) {
        return request.createResponseBuilder(HttpStatus.BAD_REQUEST)
        .body("Please pass a name on the query string or in the request body").build();
    } else {
        // Write the name to the message queue. 
        msg.setValue(name);

        return request.createResponseBuilder(HttpStatus.OK).body("Hello, " + name).build();
    }
}

更新測試

因為原型也會建立一組測試,所以您需要更新這些測試,以處理 run 方法簽章中的新 msg 參數。

瀏覽至 src/test/java 底下的測試程式碼位置,開啟 Function.java 專案檔案,並以下列程式碼取代 //Invoke 下的程式碼行。

@SuppressWarnings("unchecked")
final OutputBinding<String> msg = (OutputBinding<String>)mock(OutputBinding.class);
final HttpResponseMessage ret = new Function().run(req, msg, context);

在本機執行函式

Visual Studio Code 可與 Azure Functions Core 工具整合,讓您能夠先在本機開發電腦上執行此專案,再發佈至 Azure。 如果您尚未在本機安裝 Core Tools,系統會在您第一次執行專案時提示您安裝。

  1. 若要呼叫您的函式,請按 F5 以啟動函式應用程式專案。 [終端] 面板會顯示核心工具的輸出。 您的應用程式會在 [終端] 面板中啟動。 您可以查看在本機所執行 HTTP 觸發函式的 URL 端點。

    本機函式 Visual Studio Code 輸出的螢幕快照。

    如果您尚未安裝 Core Tools,請在系統提示安裝時選取 [安裝] 來安裝 Core Tools。
    如果在 Windows 上執行時遇到問題,請確定 Visual Studio Code 的預設終端機未設定為 WSL Bash

  2. 執行 Core Tools 時,移至 [Azure: Functions] 區域。 在 [函式] 下方,展開 [本機專案]>[函式]。 以滑鼠右鍵按一下 (Windows) 或 Ctrl - 點擊 (macOS) HttpExample 函式,並選擇 [立即執行函式...]

    現在從 Visual Studio Code 執行函式的螢幕快照。

  3. 在 [輸入要求本文] 中,按下 Enter 向您的函式傳送要求訊息。

  4. 當函式在本機執行並傳回回應時,會在 Visual Studio Code 中引發通知。 [終端機] 面板會顯示函數執行的相關資訊於。

  5. Ctrl + C 以停止 Core Tools,並中斷偵錯工具的連線。

在本機執行函式

  1. 如先前的文章中所示,按一下 F5 可開啟函式應用程式專案和 Core Tools。

  2. 執行 Core Tools 時,移至 [Azure: Functions] 區域。 在 [函式] 下方,展開 [本機專案]>[函式]。 以滑鼠右鍵按一下 (於 macOS 則是 Ctrl + 按一下) HttpExample 函式,並選取 [立即執行函式]

    從 Visual Studio Code 執行函式的螢幕快照。

  3. 在 [輸入要求本文] 中,您會看到 { "name": "Azure" } 的要求訊息本文值。 請按 Enter 鍵,將此要求訊息傳送至您的函式。

  4. 傳回回應後,按一下 Ctrl + C 以停止 Core Tools。

因為您使用的是儲存體連接字串,所以函式會在本機執行時連到 Azure 儲存體帳戶。 您第一次使用輸出繫結時,Functions 執行階段會在儲存體帳戶中建立名為 outqueue 的新佇列。 您將會使用儲存體總管來確認佇列已連同新訊息一起被建立。

將儲存體總管連線到您的帳戶

如果您已經安裝 Azure 儲存體總管並將它連線至您的 Azure 帳戶,請略過此節內容。

  1. 執行 Azure 儲存體總管 工具,選取左側的連線圖示,然後選取 [新增帳戶]

    如何將 Azure 帳戶新增至 Microsoft Azure 儲存體總管 的螢幕快照。

  2. 在 [連線] 對話方塊中,選擇 [新增 Azure 帳戶],選擇您的 [Azure 環境],然後選取 [登入]

    登入 Azure 帳戶視窗的螢幕快照。

在您成功登入帳戶之後,您會看見與您的帳戶相關聯的所有 Azure 訂用帳戶。 選擇您的訂用帳戶,然後選取 [開啟總管]

檢查輸出佇列

  1. 在 Visual Studio Code 中,按 F1 鍵來開啟命令選擇區,然後搜尋並執行 Azure Storage: Open in Storage Explorer 命令,並選擇您的儲存體帳戶名稱。 您的儲存體帳戶會在 Azure 儲存體總管中開啟。

  2. 展開 [佇列] 節點,然後選取名為 outqueue 的佇列。

    佇列包含訊息,該訊息將您執行 HTTP 觸發程序函式時建立的輸出繫結排入佇列。 如果您叫用具有預設 name 值為 Azure 的函式,佇列訊息是:Name passed to the function: Azure

    Azure 儲存體 Explorer 中顯示的佇列訊息螢幕快照。

  3. 再次執行函式並傳送另一個要求,即會在佇列中看到新的訊息。

現在,您可以將更新的函式應用程式重新發行至 Azure。

重新部署並驗證更新的應用程式

  1. 在 Visual Studio Code 中,按 F1 開啟命令選擇區。 在命令選擇區中,搜尋並選取 Azure Functions: Deploy to function app...

  2. 選擇您在第一篇文章中所建立的函式應用程式。 由於您是要將專案部署至相同的應用程式,請選取 [部署] 來關閉關於覆寫檔案的警告。

  3. 部署完成之後,您可以再次使用 [立即執行函式] 功能來觸發 Azure 中的函式。

  4. 再次檢視儲存體佇列中的訊息,以確認輸出繫結會在佇列中產生新訊息。

清除資源

在 Azure 中,「資源」是指函式應用程式、函式、儲存體帳戶等等。 其會分組為「資源群組」,您可以藉由刪除群組來刪除群組中的所有項目。

您已建立完成這些快速入門所需的資源。 您可能必須支付這些資源,取決於您的帳戶狀態服務定價。 如果您不再需要資源,刪除方式如下:

  1. 在 Visual Studio Code 中,按 F1 開啟命令選擇區。 在命令選擇區中,搜尋並選取 Azure: Open in portal

  2. 選擇您的函數應用程式,並按下 Enter。 函式應用程式頁面會在 Azure 入口網站中開啟。

  3. 在 [概觀] 索引標籤中,選取 [資源群組] 旁的具名連結。

    從函式應用程式頁面選取要刪除的資源群組螢幕快照。

  4. 在 [資源群組] 分頁上,檢閱所含資源的清單,並確認這些是您想要刪除的項目。

  5. 選取 [刪除資源群組],並遵循指示。

    刪除需要幾分鐘的時間。 完成時,通知會出現幾秒鐘的時間。 您也可以選取分頁頂端的鈴鐺圖示以檢視通知。

下一步

您已更新 HTTP 觸發的函式,以將資料寫入至儲存體佇列。 現在,您可以深入了解如何使用 Visual Studio Code 來開發 Functions: