The Will Will Web

記載著 Will 在網路世界的學習心得與技術分享

使用 .NET 8.0 與 Azure Functions Core Tools 開發與部署函式應用程式

我一直以來都是 Serverless 架構的信徒,因為實在是不太想自己管伺服器,我從 2018 年就開始採用 Azure Functions 技術,到目前為止歷經了 4 個大版本,到現在終於算是穩定些了。不過即便到目前為止,你要是照著官方文件下去設定,肯定會在很多不同的環節鬼打牆,地雷一直都沒有少過。這篇文章我將介紹如何使用 .NET 8.0Azure Functions Core Tools 來開發函式應用程式,並說明如何部署應用程式到 Azure App Service 使用 Consumption Plan (Y1) 方案來執行!

image

安裝 Azure Functions 開發環境

  1. 安裝或升級 Azure Functions Core Tools 工具

    若要在 VS Code 之中進行偵錯,那麼你一定要安裝 x64 的版本!

    choco install azure-functions-core-tools --params "'/x64:true'" -y
    

    升級的時候如果沒加上 --params "'/x64:true'" 參數,那麼就會安裝 x86 的版本。

    choco upgrade azure-functions-core-tools --params "'/x64:true'" -y
    

    查詢版本

    func --version
    
    4.0.5571
    
  2. 安裝 VS Code 編輯器

  3. 安裝與 Azure Functions 相關的 VS Code 擴充套件

    C# Dev Kit

    Azure Functions

    Azure Tools

    Azurite

    .NET Core Extension Pack

    REST Client

建立 Azure Functions 應用程式

  1. 建立 Azure Functions 應用程式

    func init linebots --worker-runtime dotnet-isolated
    

    使用 VS Code 開啟 linebots 資料夾

    code linebots
    

    第一次開啟可以讓 VS Code 自動進行最佳化設定

    Detected an Azure Functions Project in folder "linebots" that may have been created outside of VS Code. Initialize for optimal use with VS Code?

  2. 建立一個新的 HTTP Trigger 函式

    func new --template "Http Trigger" --name FirstHttpTrigger
    

    這個命令會產生一個 FirstHttpTrigger.cs 程式,程式內容如下:

    using System.Net;
    using Microsoft.Azure.Functions.Worker;
    using Microsoft.Azure.Functions.Worker.Http;
    using Microsoft.Extensions.Logging;
    
    namespace linebots
    {
        public class FirstHttpTrigger
        {
            private readonly ILogger _logger;
    
            public FirstHttpTrigger(ILoggerFactory loggerFactory)
            {
                _logger = loggerFactory.CreateLogger<FirstHttpTrigger>();
            }
    
            [Function("FirstHttpTrigger")]
            public HttpResponseData Run([HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequestData req)
            {
                _logger.LogInformation("C# HTTP trigger function processed a request.");
    
                var response = req.CreateResponse(HttpStatusCode.OK);
                response.Headers.Add("Content-Type", "text/plain; charset=utf-8");
    
                response.WriteString("Welcome to Azure Functions!");
    
                return response;
            }
        }
    }
    

    預設接受 GETPOST 要求,且授權等級設定為 Function 層級 (Authorization level)。

    若要允許匿名存取,可以將 AuthorizationLevel.Function 改為 AuthorizationLevel.Anonymous

  3. 啟動 Azurite 模擬器

    Azurite 是一套開放原始碼的 Azure Storage 模擬器,提供免費的本機儲存體環境,可用來測試您的 Azure Blob、Queue,以及 Table 儲存體等應用。如果測試無誤,就可以切換成使用雲端的 Azure 儲存體帳戶。這套 Azurite 模擬器提供 Windows、Linux 和 macOS 的跨平台支援。

    詳見: 使用 Azurite 模擬器進行本機 Azure 儲存體開發

    你可以透過 VS Code 的 F1 > Azurite: Start 命令,快速啟動 Azure Storage 模擬器。

    預設 Azurite 會在你的專案根目錄建立幾個目錄與檔案,這些檔案建議加入 .gitignore 忽略清單,否則這些檔案會被加入到版控中:

    __azurite*
    __blobstorage__/
    __queuestorage__/
    
  4. 本機偵錯

    你可以很方便的直接在 VS Code 中按下 F5 開始偵錯,或者執行以下命令啟動執行:

    func start
    

    這支 API 的網址: http://localhost:7071/api/FirstHttpTrigger

    注意: 進入偵錯時,執行檔的當前目錄會在 bin\Debug\net8.0 目錄下。如果用 func start 啟動的話,執行檔的當前目錄會在 bin\output 目錄下。

    測試 API 時,你可以建立一個 FirstHttpTrigger.http 檔案,內容如下:

    GET http://localhost:7071/api/FirstHttpTrigger
    

    然後透過 VS Code 的 REST Client 擴充套件來執行這個檔案,你就可以看到回應結果了。

    REST Client .http file

部署 Azure Functions 應用程式至 Azure App Service

  1. 選擇正確的 Azure 租用戶 (Tenant)

  2. 選擇正確的 Azure 訂用帳戶 (Subscription)

  3. 使用 Azure CLI 登入並選擇預設的訂用帳戶

    這個步驟還不需要先建立資源群組。

    # 先清空現有的登入資訊
    az account clear
    
    # 使用 Device Code 登入 (這個步驟會顯是一個網址與一個裝置代碼)
    az login --use-device-code
    
    # 開啟瀏覽器,輸入 https://microsoft.com/devicelogin
    
    # 從瀏覽器輸入裝置代碼以進行身份驗證
    
    # 選擇正確的訂用帳戶
    az account set -s "Microsoft Azure Sponsorship"
    
    # 查詢登入的資訊
    az account show -o jsonc
    
    # 查詢目前訂用帳戶下有多少資源群組
    az group list
    
  4. 建立 Azure 資源

    在 VS Code 開啟 Azure 側邊欄(Sidebar),登入 Azure 帳戶,列出所有 Azure 資源。

    點擊 Azure 側邊欄的右上角 + 符號,選擇 Create Function App in Azure,輸入 duotify-linebots 名稱,選擇 .NET 8 Isolated,選擇 Japan East 區域。這個過程會自動建立許多資源,其中包含 duotifylinebots 資源群組、duotifylinebots 儲存體帳戶、duotifylinebots Application insights、duotify-linebots 函式應用程式、ASP-duotify-linebots-xxxx App Service Plan (Y1 Consumption plan)。

  5. 部署網站

    執行以下命令部署網站:

    func azure functionapp publish duotify-linebots
    

    如果你選擇使用 Function 層級的授權,那你必須進入 Azure Portal 找到 duotify-linebots 函式應用程式的 Overview 頁籤,該頁面下方有個 FirstHttpTrigger 函式,點進 Function Keys 可以複製名為 default 的 Function keys 金鑰。之後若要呼叫這個 API 的話,就必須用以下網址結構來呼叫 Function 執行:

    <api-url>?code=f9qr9TaxgFqWpEZk5pNkHNquKnRf2BhcXOc-GnDuNhF4AzFuqRwQBA==
    

    例如:

    https://duotify-linebots.azurewebsites.net/api/firsthttptrigger?code=f9qr9TaxgFqWpEZk5pNkHNquKnRf2BhcXOc-GnDuNhF4AzFuqRwQBA==
    

    下次更新程式只要再執行一次上述命令即可再次部署!

如何從 local.settings.json 檔案中取得組態設定值

在 Azure Functions 的應用程式中,所有組態設定都是放在 local.settings.json 檔案中,預設內容如下:

{
  "IsEncrypted": false,
  "Values": {
    "FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated",
    "AzureWebJobsStorage": "UseDevelopmentStorage=true"
  },
  "ConnectionStrings": {}
}

注意: 這個 local.settings.json 檔案預設不會被加入到 Git 版控中,因為這個檔案在建立專案的時候,就已經被加入到 .gitignore 檔案中。若是多人開發專案,建議將這些組態設定寫入專案的 README.md 文件中,讓其他開發者知道有這些設定。

以前我們在 ASP.NET Core 之中,要取得組態都要靠 IConfiguration 服務,但在 Azure Functions 之中,你可以直接使用 Environment.GetEnvironmentVariable 來取得組態設定,以下是程式碼範例:

var runtime = Environment.GetEnvironmentVariable("FUNCTIONS_WORKER_RUNTIME")!;

從 Azure 下載 local.settings.json 應用程式設定

當你想重新建立開發環境時,因為 local.settings.json 並不在版控中,所以你在本機基本上是無法成功執行的。

還好 Azure Functions Core Tools 提供了一個 func azure functionapp fetch-app-settings 命令,可以從 Azure 下載應用程式設定,並且將設定直接寫入 local.settings.json 應用程式設定檔中,這樣你就可以在本機測試 Azure Functions 了。

func azure functionapp fetch-app-settings duotify-linebots

這裡有個小地雷要注意,當你在下載應用程式設定時,如果專案中還沒有 local.settings.json 應用程式設定檔的存在,那麼下載回來的 local.settings.json 檔案會是「已加密」的版本,你還需要透過以下命令才能進行解密,否則你會看不到內容,也無法編輯:

func settings decrypt

取得 Storage account 的連接字串

在你建立好 Azure Functions 網站與相對應的儲存體帳戶後,你可以使用以下命令取得儲存體帳戶的連接字串:

func azure storage fetch-connection-string duotifylinebots

上述命令會在 local.settings.json 檔案中新增一個 duotifylinebots_STORAGE 設定,並填入 Azure Storage 的連接字串。這個命令的方便之處在於,當你想在本機測試 Azure Functions 並希望直接連結 Azure Storage 進行測試時比較方便。不過大部分的情況下,都應該在本機測試 Storage 即可。

使用 GitHub Copilot 的注意事項

由於 Azure Functions 至今推出過 4 個版本,每個版本之間的差異非常大,因此 GitHub Copilot 在幫你產生程式碼時,可能會產生錯誤的程式碼。這時你就必須自己手動修改程式碼,或者參考官方文件來修改程式碼,這應該算是比較地雷的地方。

相關連結

留言評論