DotNETWeekly-io / DotNetWeekly

DotNet weekly newsletter
MIT License
207 stars 3 forks source link

【文章推荐】Azure Function 迁移 .NET 8 步骤 #694

Closed gaufung closed 1 month ago

gaufung commented 2 months ago

https://blog.elmah.io/lessons-learned-after-migrating-azure-functions-to-isolated-functions-on-net-8/

gaufung commented 1 month ago

image

Azure Function 将要移除 In-Process 模式,从而转向 Isolated 模式。那么在迁移的过程中需要注意什么呢? 首先这个两者的区别是:

首先需要一个 Startup.cs 文件

[assembly:FunctionsStartup(typeof(MyFunctionApp.Startup))]
namespace MyFunctionApp;
public class Startup : FunctionsStartup {
  public override void Configure(IFunctionsHostBuilder builder) {
    builder.Services.AddLogging(logging => { logging.AddConsole(); });
#pragma warning disable CS0618  // Type or member is obsolete
    builder.Services.AddSingleton<IFunctionFilter, MyExceptionFilter>();
#pragma warning restore CS0618  // Type or member is obsolete
  }
}

这个文件和之前的 ASP.NET Core 类型,可以添加依赖注入。

之后相应 Function 文件

namespace MyFunctionApp;
public class MyFunction {
  private readonly IMyDependency myDependency;

  public UptimeChecker(IMyDependency myDependency) {
    this.myDependency = myDependency;
  }

  [FunctionName("MyFunction")]
  public async Task Run([ TimerTrigger("0 */5 * * * *") ] TimerInfo myTimer,
                        ILogger log) {
    // Execute
  }
}

之后 local.settings.json 文件如下

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

csproj 文件如下

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net6.0</TargetFramework>
    <AzureFunctionsVersion>v4</AzureFunctionsVersion>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Microsoft.NET.Sdk.Functions" Version="4.2.0" />
    <PackageReference Include="Microsoft.Azure.Functions.Extensions" Version="1.1.0" />
  </ItemGroup>
  <ItemGroup>
    <None Update="host.json">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </None>
    <None Update="local.settings.json">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
      <CopyToPublishDirectory>Never</CopyToPublishDirectory>
    </None>
  </ItemGroup>
</Project>

由于现在是 .NET 6 版本,我们需要升级到 .NET 8,所以要继续处理

<TargetFramework>net8.0</TargetFramework>
<OutputType>Exe</OutputType>
<PackageReference Include="Microsoft.Azure.Functions.Worker" Version="1.10.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Timer" Version="4.0.1" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Sdk" Version="1.7.0" />

创建一个 program.cs 文件

var host = new HostBuilder()
    .ConfigureFunctionsWorkerDefaults((context, app) =>
    {
        app.UseMiddleware<MyExceptionMiddleware>();
    })
    .ConfigureServices(services =>
    {
        var dependency = new MyDependency();
        services.AddSingleton<IMyDependency>(dependency);
    })
    .ConfigureLogging(logging =>
    {
        logging.AddConsole();
    })
    .Build();

这里部分的内容的是来自之前的 Startup.cs 文件。之后更新 local.settings.json 文件

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

那么最后的 Function 文件修改

namespace MyFunctionApp {
public class MyFunction
(IMyDependency myDependency, ILogger<MyFunction> logger) {
  private readonly IMyDependency myDependency = myDependency;
  private readonly ILogger<MyFunction> logger = logger;

  [Function("MyFunction")]
  public async Task Run([ TimerTrigger("0 */5 * * * *") ] TimerInfo myTimer) {
    // Execute
  }
}
}