我一直以來都是 Serverless 架構的信徒,因為實在是不太想自己管伺服器,我從 2018 年就開始採用 Azure Functions 技術,到目前為止歷經了 4 個大版本,到現在終於算是穩定些了。不過即便到目前為止,你要是照著官方文件下去設定,肯定會在很多不同的環節鬼打牆,地雷一直都沒有少過。這篇文章我將介紹如何使用 .NET 8.0 與 Azure Functions Core Tools 來開發函式應用程式,並說明如何部署應用程式到 Azure App Service 使用 Consumption Plan (Y1
) 方案來執行!
安裝 Azure Functions 開發環境
-
安裝或升級 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
-
安裝 VS Code 編輯器
-
安裝與 Azure Functions 相關的 VS Code 擴充套件
C# Dev Kit
Azure Functions
Azure Tools
Azurite
.NET Core Extension Pack
REST Client
建立 Azure Functions 應用程式
-
建立 Azure Functions 應用程式
func init linebots --worker-runtime dotnet-isolated
使用 VS Code 開啟 linebots
資料夾
code linebots
第一次開啟可以讓 VS Code 自動進行最佳化設定
-
建立一個新的 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;
}
}
}
預設接受 GET
與 POST
要求,且授權等級設定為 Function
層級 (Authorization level)。
若要允許匿名存取,可以將 AuthorizationLevel.Function
改為 AuthorizationLevel.Anonymous
。
-
啟動 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__/
-
本機偵錯
你可以很方便的直接在 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
擴充套件來執行這個檔案,你就可以看到回應結果了。
部署 Azure Functions 應用程式至 Azure App Service
-
選擇正確的 Azure 租用戶 (Tenant)
-
選擇正確的 Azure 訂用帳戶 (Subscription)
-
使用 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
-
建立 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)。
-
部署網站
執行以下命令部署網站:
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 在幫你產生程式碼時,可能會產生錯誤的程式碼。這時你就必須自己手動修改程式碼,或者參考官方文件來修改程式碼,這應該算是比較地雷的地方。
相關連結