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

Azure Functions 讓你能將 Azure 服務和其他資源連接到函數,而不必自己寫整合程式碼。 這些繫結同時代表輸入和輸出,會宣告於函式定義內。 繫結中的資料會提供給函式作為參數。 「觸發程序」是一種特殊的輸入繫結。 雖然函式只有一個觸發器,但可以有多個輸入和輸出綁定。 想了解更多,請參考Azure Functions觸發與綁定概念。

在本文中,你會學習如何使用 Visual Studio Code 將 Azure 儲存體 連接到你在上一篇快速入門文章中建立的函式。 您新增到此函式的輸出繫結會將 HTTP 要求中的資料寫入 Azure Queue 儲存體佇列中的訊息。

大多數綁定都需要一個儲存的連接字串,函式會用來存取已綁定的服務。 為了方便使用,你可以使用你用功能應用程式建立的 storage 帳號。 此帳戶的連線已儲存在名為 AzureWebJobsStorage 的應用程式設定中。

注意

本文目前支援適用於 Functions 的 Node.js v4。

設定您的本機環境

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

  • 安裝 Visual Studio Code 的 Azure 儲存體 擴充功能。

  • 安裝 Azure 儲存體總管。 儲存體總管 是一款用來檢視輸出綁定產生的佇列訊息的工具。 儲存體總管 支援於 macOS、Windows 及基於 Linux 的作業系統。

本文假設你已經從 Visual Studio Code 登入了 Azure 訂閱。 你可以從指令面板中執行 Azure: Sign In 登入。

下載函式應用設定

在之前的快速入門文章中,你在 Azure 建立了一個功能應用程式,並創建了所需的儲存體帳戶。 這個帳號的 連接字串 會安全地儲存在 Azure 的應用程式設定中。 在本文中,您將訊息寫入相同帳戶的儲存體佇列。 在本地執行此功能時,若要連接你的 storage 帳號,必須下載 local.settings.json 檔案的應用程式設定。

  1. 按 F1 開啟指令面板,然後搜尋並執行指令 Azure Functions: Download Remote Settings...。

  2. 選擇您在上一篇文章中建立的函式應用程式。 選取全部皆是,以覆寫現有的本機設定。

    重要

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

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

註冊繫結延伸模組

因為你使用的是佇列儲存體輸出綁定,必須先安裝 Storage 綁定擴充功能才能執行專案。

你的專案設定為使用 擴充套件,這些套件會自動安裝一組預設的擴充套件。

你可以在專案根目錄的 host.json 檔案中啟用擴充包。 此檔案應包含以下 extensionBundle 元素:

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

現在,你可以把 storage 輸出綁定加到 project 裡。

你的專案設定為使用 擴充套件,這些套件會自動安裝一組預設的擴充套件。

你可以在專案根目錄的 host.json 檔案中啟用擴充包。 此檔案應包含以下 extensionBundle 元素:

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

現在,你可以把 storage 輸出綁定加到 project 裡。

除了 HTTP 和計時器觸發程序以外,繫結皆會以擴充套件的形式實作。 在終端機視窗執行以下 dotnet add package 指令,將 Storage 擴充套件加入你的project。

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

現在,你可以把 storage 輸出綁定加到 project 裡。

新增輸出繫結

要寫入 Azure 儲存體佇列:

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

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

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

要寫入 Azure 儲存體佇列:

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

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

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

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

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

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

提示 值 說明
選取繫結方向 out 此繫結為輸出繫結。
選取具方向性的繫結... Azure Queue Storage 綁定是 Azure 儲存體 佇列綁定。
用以在程式碼中識別此繫結的名稱 msg 識別您的程式碼中參考之繫結參數的名稱。
要傳送訊息的佇列 outqueue 繫結寫入的佇列名稱。 當 queueName 不存在,繫結會在第一次使用時加以建立。
從 "local.setting.json" 中選取設定 AzureWebJobsStorage 一個應用程式設定名稱,其包含儲存帳戶的連接字串。 AzureWebJobsStorage 設定包含你用函式應用程式建立的儲存帳戶的「連接字串」。

系統會在您的 bindings 中新增一個繫結到 陣列,內容應如下所示:

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

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

使用 queue_output 裝飾器,綁定方向隱含為「out」,類型則為 Azure 儲存體 Queue。 在 function_app.py中,將以下裝飾者加入你的功能代碼:

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

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

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

打開 HttpExample.cs project 檔案,並新增以下 MultiResponse 類別:

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

MultiResponse 類別允許你寫入名為 outqueue 的 storage 佇列及 HTTP 成功訊息。 多個訊息可以傳送至佇列,因為 QueueOutput 屬性會套用至字串陣列。

Connection屬性設定了儲存帳戶的連接字串。 在這種情況下,你可以省略 Connection,因為你已經在使用預設的 storage 帳號。

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

請瀏覽 src/main/java 下函式程式碼的位置,開啟 Function.java project,並在 run 方法定義中加入以下參數:

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

msg 參數是一個 OutputBinding<T> 型態,代表一組字串,當函式完成時會以訊息形式寫入輸出綁定。 此時輸出為名為 outqueue 的 storage 隊列。 儲存帳戶的連接字串由connection 方法設定。 你傳遞的不是 連接字串 本身,而是包含 Storage account 連接字串 的應用程式設定。

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
})

更新 HttpExample\function_app.py 以符合下列程式碼,並將 msg 參數新增至函式定義,並在 msg.set(name) 陳述式下加入 if name::

import azure.functions as func
import logging

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

@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。

將現有 Run 方法替換為以下程式碼:

[Function("HttpExample")]
public MultiResponse Run([HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequest req)
{
    _logger.LogInformation("C# HTTP trigger function processed a request.");

    var message = "Welcome to Azure Functions!";

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

現在,您可以使用新的 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();
    }
}

更新測試

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

瀏覽到你的測試程式碼位置: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 工具整合,讓你能在本地開發電腦上執行此project,然後再發佈到Azure。 如果你還沒有在本地安裝 Core Tools,第一次執行 project 時會被提示安裝。

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

    Visual Studio Code 區域函式輸出截圖。

    如果您尚未安裝 Core Tools,請根據提示選擇 Install 來安裝 Core Tools。
    如果你在 Windows 上遇到困難,請確認 Visual Studio Code 的預設終端機沒有設成 WSL Bash。

  2. 執行核心工具後,前往 Azure: Functions 區域。 在 Functions 下,展開 Local Project>Functions。 以滑鼠右鍵按一下 (Windows) 或 Ctrl - 點擊 (macOS) HttpExample 函式,並選擇 [立即執行函式...]。

     來自 Visual Studio Code 的執行函數截圖。

  3. 在輸入請求正文中,按下Enter向您的函式傳送請求訊息。

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

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

在本機執行函式

  1. 如前文所述,按下 F5 以啟動函式應用程式專案及核心工具。

  2. 執行核心工具後,前往 Azure: Functions 區域。 在 Functions 下,展開 Local Project>Functions。 以滑鼠右鍵按一下 (於 macOS 則是 Ctrl + 按一下) HttpExample 函式,並選取 [立即執行函式]。

     Visual Studio程式碼執行功能的截圖。

  3. 在 Enter 請求主體中,你會看到請求訊息主體值為 { "name": "Azure" }。 請按 Enter 鍵,將此要求訊息傳送至您的函式。

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

因為你用的是 storage 連接字串,功能在本地執行時會連接到 Azure storage 帳號。 當 Functions 執行時首次使用輸出綁定時,會在你的 storage 帳號建立一個名為 outqueue 的新佇列。 你會使用 儲存體總管 來驗證佇列是否已建立以及是否已加入新訊息。

將 儲存體總管 連接到你的帳號

如果你已經安裝了 Azure 儲存體總管 並連接到你的 Azure 帳號,請跳過這一段。

  1. 執行 Azure 儲存體總管 工具,選擇左側的連接圖示,然後選擇 新增帳戶。

     截圖,說明如何將Azure帳號加入Microsoft Azure 儲存體總管.

  2. 在 Connect 對話框中,選擇 新增Azure帳號,選擇你的 Azure 環境,然後選擇 登入...。

    你Azure帳號視窗登入的截圖。

成功登入帳號後,你會看到所有與帳號相關的 Azure 訂閱。 選擇您的訂閱方案,然後選取 開啟資源管理器。

檢查輸出佇列

  1. 在Visual Studio程式碼中,按 F1 開啟指令面板,然後搜尋並執行指令 Azure 儲存體: Open in 儲存體總管,選擇你的storage帳號名稱。 你的 storage 帳戶會在 Azure 儲存體總管 中開啟。

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

    佇列包含訊息,這些訊息是當您執行 HTTP 觸發的函式時,由佇列輸出繫結所建立的。 如果你呼叫函式時預設的 name 值為 Azure,佇列訊息會變成 Name,傳給函式:Azure。

    Azure 儲存體總管 中顯示的佇列訊息的截圖。

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

現在,是時候將更新後的功能應用程式重新發佈到 Azure。

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

  1. 在Visual Studio程式碼中,按 F1 開啟指令面板。 在指令面板中搜尋並選擇 Azure Functions: Deploy to function app...。

  2. 選擇您在第一篇文章中所建立的功能應用程式。 因為你將專案重新部署到同一個應用程式,請選擇Deploy以忽略有關覆寫檔案的警告。

  3. 部署完成後,你又可以再使用 Execute Function Now... 功能,用來觸發該功能Azure。 此指令會自動取得函式 access 金鑰,並在呼叫 HTTP 觸發端點時使用該金鑰。

  4. 同樣地, 查看 storage 佇列中的訊息以驗證輸出綁定是否在佇列中產生新訊息。

清除資源

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

您已建立資源以完成這些快速入門。 根據您的帳戶狀態及服務價格,您可能會被收取這些資源的費用。 如果您不再需要資源,刪除方式如下:

  1. 在Visual Studio程式碼中,按 F1 開啟指令面板。 在指令面板中搜尋並選擇 Azure: Open in portal。

  2. 選擇您的函數應用程式,並按下 Enter。 function app 頁面會在 Azure portal 開啟。

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

    函數應用程式頁面中的螢幕擷取畫面,顯示選取要刪除的資源群組。

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

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

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

下一步

你已經更新了 HTTP 觸發函式,將資料寫入 Storage 隊列。 現在你可以進一步了解如何使用 Visual Studio Code 開發函式: