Azure Functions与C# 12及.NET 8 Isolated Process迁移指南

发布:2024-09-21 11:17 阅读:120 点赞:0

一. 概述

Azure Functions不断发展,C# 12和.NET 8 Isolated Process的引入为开发者提供了提升性能、可扩展性和可维护性的机会。本文将指导如何将Azure Functions从旧版本迁移到C# 12与.NET 8 Isolated Process模型,并提供具体的代码示例与最佳实践。

二. 理解.NET 8 Isolated Process模型

.NET 8 Isolated Process模型将Azure Functions的运行时与函数代码分离,从而提高性能并简化依赖管理。在此模型下,需使用Microsoft.Azure.Functions.WorkerMicrosoft.Azure.Functions.Worker.Sdk包。

1. 关键步骤

  • 更新项目文件:使用Microsoft.Azure.Functions.Worker替代Microsoft.NET.Sdk.Functions
  • 调整入口点:根据新模型修改函数应用的入口点。

示例:项目文件迁移

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net8.0TargetFramework
    <AzureFunctionsVersion>v4AzureFunctionsVersion
    <OutputType>ExeOutputType
    <ImplicitUsings>enableImplicitUsings
    <Nullable>enableNullable
  PropertyGroup>
  <ItemGroup>
    <FrameworkReference Include="Microsoft.AspNetCore.App" /> 
    <PackageReference Include="Microsoft.Azure.Functions.Worker" Version="1.20.1" /> 
    <PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Http" Version="3.1.0" /> 
    <PackageReference Include="Microsoft.Azure.Functions.Worker.Sdk" Version="1.16.4" /> 
  ItemGroup>
Project>

三. 升级代码以利用C# 12特性

1. 构造函数参数处理与初始化

使用C# 12的主构造函数简化代码。

之前的实现

namespace AzureFunctionsApp.Shared.Models
{
    public class Person
    {
        public string FirstName { get; }
        public string LastName { get; }
        public string EmailAddress { get; }
        public string TelephoneNumber { get; }

        public Person(string firstName, string lastName, string emailAddress, string telephoneNumber)
        {
            FirstName = firstName; // 初始化FirstName
            LastName = lastName; // 初始化LastName
            EmailAddress = emailAddress; // 初始化EmailAddress
            TelephoneNumber = telephoneNumber; // 初始化TelephoneNumber
        }
    }
}

之后的实现

namespace AzureFunctionsApp.Shared.Models
{
    public readonly record struct Person(string FirstName, string LastName, string EmailAddress, string TelephoneNumber)
    // 使用只读记录结构以提高性能和内存效率
}

四. 重构为异步编程模型

Isolated Process模型提倡异步操作,确保所有I/O绑定操作都是异步的,避免线程阻塞。

1. 之前的实现

using AzureFunctionsApp.Shared.Services.Interfaces;

namespace AzureFunctionsApp.Shared.Services
{
    public class DataService
    {
        public async Task<stringGetData()
        {
            var data = await SomeLongRunningOperation(); // 调用长时间运行的操作
            await DoAnotherAsyncOperation(); // 调用另一个异步操作
            return data; // 返回数据
        }

        public async Task<stringSomeLongRunningOperation()
        {
            await Task.Delay(1000); // 延迟1秒
            return "Data from long-running operation"// 返回数据
        }

        public async Task DoAnotherAsyncOperation()
        {
            await Task.Delay(500); // 延迟0.5秒
        }
    }
}

2. 之后的实现

确保所有支持异步操作的方法调用都被正确等待。

IDataService接口

namespace AzureFunctionsApp.Shared.Services.Interfaces
{
    public interface IDataService
    {
        string GetData()// 同步获取数据
        Task<stringGetDataAsync()// 异步获取数据

        Task<stringSomeLongRunningOperationAsync()// 异步长时间运行操作

        Task DoAnotherAsyncOperationAsync()// 异步另一个操作
    }
}

DataService类

using AzureFunctionsApp.Shared.Services.Interfaces;

namespace AzureFunctionsApp.Shared.Services
{
    public class DataService : IDataService
    {
        public string GetData()
        {
            return "Hello from Ziggy Rafiq!"// 返回问候语
        }

        public async Task<stringGetDataAsync()
        {
            var data = await SomeLongRunningOperationAsync(); // 调用异步长时间运行操作
            await DoAnotherAsyncOperationAsync(); // 调用异步另一个操作
            return data; // 返回数据
        }

        public async Task<stringSomeLongRunningOperationAsync()
        {
            await Task.Delay(1000); // 延迟1秒
            return "Long-running operation result"// 返回结果
        }

        public async Task DoAnotherAsyncOperationAsync()
        {
            await Task.Delay(500); // 延迟0.5秒
        }
    }
}

五. 适应依赖注入和配置

在Isolated Process模型中,依赖注入和配置管理的方式有所不同。使用IServiceCollection配置服务,使用ConfigurationBuilder配置应用设置。

示例

using AzureFunctionsApp.Shared.Services;
using AzureFunctionsApp.Shared.Services.Interfaces;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

var host = new HostBuilder()
    .ConfigureFunctionsWebApplication() // 配置函数Web应用
    .ConfigureServices(services =>
    {
        services.AddSingleton(); // 注册数据服务为单例
        services.AddApplicationInsightsTelemetryWorkerService(); // 注册Application Insights服务
    })
    .Build();

host.Run(); // 启动主机

六. 配置设置

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;

namespace AzureFunctionsApp
{
    public class ZiggyFunction
    {
        private readonly ILogger _logger; // 日志记录器
        private readonly IConfiguration _configuration; // 配置对象

        public ZiggyFunction(ILogger logger, IConfiguration configuration)
        {
            _logger = logger; // 初始化日志记录器
            _configuration = configuration; // 初始化配置对象
        }

        [Function(nameof(ZiggyFunction))// 定义函数名称
        public IActionResult Run([HttpTrigger(AuthorizationLevel.Function, "get""post")] HttpRequest req) // 定义HTTP触发器
        {
            string? ziggyAppSettingConfiguration = string.IsNullOrWhiteSpace(_configuration["ZiggyAppSetting"]) ? "ZiggyDefaultValue" : _configuration["ZiggyAppSetting"]; // 获取配置值

            _logger.LogInformation("Hello from Ziggy Rafiq"); // 记录信息
            return new OkObjectResult("Welcome to Ziggy Azure Functions!"); // 返回欢迎消息
        }
    }
}

七. 总结

通过迁移到C# 12与.NET 8 Isolated Process,Azure Functions用户能够受益于改进的性能和新语言特性。理解新模型、利用现代C#特性,并适应异步编程和依赖注入的代码,能够有效实现过渡。务必测试和验证无服务器应用程序,以确保平稳迁移,提升应用的效率和可扩展性。