この記事は、Microsoft Azure Advent Calendar 2024 の 15 日目 の記事です。
qiita.com
Azure Functions の In-Process モデルは、.NET 8 までの対応となっており、2026 年 11 月 10 日よりサポート終了となります。
.NET 9 が GA しましたので、In-Process モデルから Isolated Worker Process モデルにマイグレーションしました。移行したリポジトリは、こちらです。
github.com
Application
Isolated Worker Process モデルにマイグレーションする手順は、こちらのドキュメントの通りです。今回は Deployment Slots を使わずダイレクトに移行します。
azure.github.io
csproj ファイル
PropertyGroup に OutputType を追加し、Target Framework も合わせて更新します。
<PropertyGroup> <TargetFramework>net9.0</TargetFramework> <AzureFunctionsVersion>v4</AzureFunctionsVersion> <UserSecretsId>2586a5fb-4b07-4712-be4b-75721384d340</UserSecretsId> <OutputType>Exe</OutputType> <ImplicitUsings>enable</ImplicitUsings> <Nullable>enable</Nullable> </PropertyGroup>
Nuget Library は、In-Process モデルのパッケージを Microsoft.Azure.Functions.Worker に置き換えます。
<!--<PackageReference Include="Microsoft.NET.Sdk.Functions" Version="4.5.0" />--> <!--<PackageReference Include="Azure.Extensions.AspNetCore.Configuration.Secrets" Version="1.3.1" />--> <!--<PackageReference Include="Microsoft.Azure.Functions.Extensions" Version="1.1.0" />--> <!--<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="9.0.0" />--> <PackageReference Include="Microsoft.Azure.Functions.Worker" Version="2.0.0" /> <PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Http" Version="3.2.0" /> <PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore" Version="2.0.0" /> <PackageReference Include="Microsoft.Azure.Functions.Worker.Sdk" Version="2.0.0" />
Queue Trigger の Function があるので、こちらのパッケージも置き換えます。他のトリガーやバインディングがある場合は、個別に置き換えが必要です。
<!--<PackageReference Include="Microsoft.Azure.WebJobs.Extensions.Storage" Version="5.3.0" />--> <PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Storage.Queues" Version="5.5.0" />
シークレット関連は、バージョン更新するだけで OK です。
<PackageReference Include="Azure.Identity" Version="1.13.1" /> <PackageReference Include="Azure.Extensions.AspNetCore.Configuration.Secrets" Version="1.3.2" />
Application Insights のパッケージも追加しておきます。
<PackageReference Include="Microsoft.ApplicationInsights.WorkerService" Version="2.22.0" /> <PackageReference Include="Microsoft.Azure.Functions.Worker.ApplicationInsights" Version="2.0.0" />
最後に、 新しい ItemGroup を追加します。
<ItemGroup> <Using Include="System.Threading.ExecutionContext" Alias="ExecutionContext" /> </ItemGroup>
Program.cs ファイル
このアプリケーションでは、Azure Functions のプロジェクトに拡張の NuGet パッケージをインストールして Startup クラスを実装していました。
- appsettings.json の追加
- Azure Key Vault の参照(Azure 環境のみ)
- secrets.json の利用(ローカル開発環境のみ)
[assembly: FunctionsStartup(typeof(FunctionApp.Startup))] namespace FunctionApp { public class Startup : FunctionsStartup { public override void Configure(IFunctionsHostBuilder builder) { var context = builder.GetContext(); builder.Services.Configure<MySettings>(context.Configuration.GetSection("Function")); } public override void ConfigureAppConfiguration(IFunctionsConfigurationBuilder builder) { var context = builder.GetContext(); builder.ConfigurationBuilder .AddJsonFile(Path.Combine(context.ApplicationRootPath, "appsettings.json"), optional: true, reloadOnChange: false) .AddJsonFile(Path.Combine(context.ApplicationRootPath, $"appsettings.{context.EnvironmentName}.json"), optional: true, reloadOnChange: false) .AddEnvironmentVariables(); if (context.EnvironmentName != "Development") { var config = builder.ConfigurationBuilder.Build(); builder.ConfigurationBuilder .AddAzureKeyVault(new Uri(config["Function:KeyVaultUrl"]), new DefaultAzureCredential()); } } } }
Startup クラスの実装を Program.cs ファイルに置き換えます。IHostApplicationBuilder を使うことで、ASP.NET Core のプログラミングモデルに寄せて実装できる ASP.NET Core integration を有効化できます。
var builder = FunctionsApplication.CreateBuilder(args); builder.ConfigureFunctionsWebApplication(); builder.Configuration.AddUserSecrets(Assembly.GetExecutingAssembly()); builder.Services .Configure<MySettings>(builder.Configuration.GetSection("Function")) .AddApplicationInsightsTelemetryWorkerService() .ConfigureFunctionsApplicationInsights(); if (builder.Configuration["AzureWebJobsStorage"] != "UseDevelopmentStorage=true") { if (!string.IsNullOrEmpty(keyVaultUrl)) { builder.Configuration.AddAzureKeyVault(new Uri(keyVaultUrl), new DefaultAzureCredential()); } } builder.Build().Run();
local.settings.json ファイル
FUNCTIONS_WORKER_RUNTIME プロパティの値を dotnet-isolated へ変更します。
{ "IsEncrypted": false, "Values": { "AzureWebJobsStorage": "UseDevelopmentStorage=true", "FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated", "StorageBindingConnection": "UseDevelopmentStorage=true" }
Http Trigger Function
Isolated Worker Process モデルでは、Function の引数で ILogger を受け取れないため、コンストラクタの引数で受け取るように変更します。
private readonly ILogger<HttpFunction> _logger; // 追加 private readonly MySettings _settings; //public HttpFunction(IOptions<MySettings> optionsAccessor) public HttpFunction(ILogger<HttpFunction> logger, IOptions<MySettings> optionsAccessor) { _logger = logger; // 追加 _settings = optionsAccessor.Value; }
Function を定義する属性は、FunctionName から Function に変更します。
//[FunctionName(nameof(HttpFunction))] //public IActionResult Run([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req, ILogger log) [Function(nameof(HttpFunction))] public IActionResult Run([HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequest req)
Queue Trigger Function
ILogger をコンストラクタの引数で受け取る変更は Http Trigger と同様です。Queue Trigger ではメッセージを QueueMessage 型で受け取れるようになります。
//[FunctionName(nameof(QueueFunction))] // public void Run([QueueTrigger("myqueue-items", Connection = "StorageBindingConnection")] string myQueueItem, ILogger log) [Function(nameof(QueueFunction))] public void Run([QueueTrigger("myqueue-items", Connection = "StorageBindingConnection")] QueueMessage message)
ローカル開発環境で Visual Studio からデバッグ実行すると、エラーが発生しました。
<Error> <Code>InvalidHeaderValue</Code> <Message>The value for one of the HTTP headers is not in the correct format.</Message> <HeaderName>x-ms-version</HeaderName> <HeaderValue>2024-08-04</HeaderValue> </Error>
どうやら Nuget Package を更新したことで、ライブラリとエミュレータで Azure Storage の API バージョンが一致していないことが原因のようです。
Azurite のバージョンが 3.12 だったので、最新の 3.33 に更新することで解決しました。
Azure Functions
Azure Functions 側は、環境変数の FUNCTIONS_WORKER_RUNTIME の値を dotnet-isolated へ変更します。
.NET Version は、環境変数の変更を Save した後に変更しました。
GitHub Actions を組んでいるので、こちらの DOTNET_VERSION も忘れずに更新します。
env: AZURE_FUNCTIONAPP_PACKAGE_PATH: '.' # set this to the path to your web app project, defaults to the repository root DOTNET_VERSION: '9.0.x' # set this to the dotnet version to use
以上で、無事に Isolated Worker Process モデルへのマイグレーションが完了しました。