C#10 和 .NET6 企业级应用开发(五)

从高并发到企业级应用:C# 和 Go 的完美结合 C# 和 Go 在现代软件开发中各有优势,适合在不同的场景中发挥各自的特长。通过合理的架构设计,C# 和 Go 可以在同一个系统中无缝协作,实现高效、可靠、可扩展的应用系统。无论是构建微服务、处理高并发任务,还是突破性能瓶颈,C# 和 Go 的结合都能为团队提供极大的灵活性和效率。希望通过本文的探讨,你能了解如何在实际项目中将 C# 和 Go 双剑合璧,充分发挥其优势,提升开发效率和系统性能。 阅读详情

原文:zh.annas-archive.org/md5/b71782931b1ec965a99239b2cd142e50

译者:飞龙

协议:CC BY-NC-SA 4.0

第五部分:健康检查、单元测试、部署和诊断

就像对我们一样,任何企业应用程序的健康状况都应该是容易检查的,而且在出现任何异常的情况下,我们应该提前得到通知,这样我们就可以采取纠正措施,而不会导致停机。在本部分中,我们将将新的.NET 6 健康和性能检查 API 集成到我们的应用程序中,并对我们的应用程序进行单元测试。然后我们将学习如何以现代 DevOps 的方式部署我们的应用程序,并了解如何在生产中监控、诊断和排除应用程序的故障。

本部分包括以下章节:

  • 第十四章*,健康和诊断*

  • 第十五章*,测试*

  • 第十六章*,在 Azure 中部署应用程序*

第十四章:第十四章:健康和诊断

现代软件应用程序已经演变成复杂和动态,并且具有分布式特性。对这些应用程序的需求是能够全天候在任何设备上工作。为了实现这一点,重要的是要知道我们的应用程序始终可用并响应请求。客户体验将在服务未来的发展和组织的收入中扮演重要角色。

一旦应用程序上线,监控应用程序的健康状况至关重要。定期监控应用程序健康将帮助我们主动检测任何故障,并在它们造成更多损害之前解决它们。应用程序监控现在已成为日常运营的一部分。为了诊断在线应用程序上的任何故障,我们需要拥有正确的遥测和诊断工具。我们捕获的遥测数据也将帮助我们识别那些用户没有直接看到或报告的问题。

让我们了解应用程序健康监控以及.NET 6 提供了哪些功能。

本章我们将学习以下主题:

  • 介绍健康检查

  • ASP.NET Core 6 中的健康检查 API

  • 使用 Application Insights 监控应用程序

  • 执行远程调试

到本章结束时,您将能够熟练构建.NET 6 应用程序的健康检查 API,并使用 Azure Application Insights 来捕获遥测信息和诊断问题。

技术要求

为了完成本章中的任务,您需要以下软件:

  • 安装了 Azure 开发工作负载的 Visual Studio 2022 Community Edition(某些部分需要企业版)

  • Azure 订阅

预期您对 Microsoft .NET 有基本了解,以及如何在 Azure 中创建资源。

本章中使用的代码可以在github.com/PacktPublishing/Enterprise-Application-Development-with-C-10-and-.NET-6-Second-Edition/tree/main/Enterprise%20Application找到。

介绍健康检查

健康检查是对应用程序的全面审查,帮助我们了解应用程序的当前状态,并使用可见指标采取纠正措施。健康检查由应用程序作为 HTTP 端点公开。健康检查端点用作某些编排器和负载均衡器的健康探测,以将流量从失败的节点路由出去。健康检查用于监控应用程序依赖项,如数据库、外部服务和缓存服务。

在下一节中,我们将学习如何在 ASP.NET Core 6 中构建健康检查 API 的支持。

ASP.NET Core 6 中的健康检查 API

ASP.NET Core 6 有一个内置的中间件(通过Microsoft.Extensions.Diagnostics.HealthChecks NuGet 包提供),用于报告作为 HTTP 端点公开的应用程序组件的健康状态。这个中间件使得集成数据库、外部系统和其他依赖项的健康检查变得非常简单。它也是可扩展的,因此我们可以创建我们自己的自定义健康检查。

在下一节中,我们将向我们的Ecommerce门户添加一个健康检查端点。

添加健康检查端点

在本节中,我们将向我们的Packt.Ecommerce.Web应用程序添加一个健康检查端点:

  1. 为了添加一个健康检查端点,我们首先需要将Microsoft.Extensions.Diagnostics.HealthChecks NuGet 包引用添加到Packt.Ecommerce.Web项目中,如下面的截图所示:

https://github.com/OpenDocCN/freelearn-csharp-zh/raw/master/docs/entp-appdev-csp10-dn6/img/Figure_14.1_B18507.jpg

图 14.1 – NuGet 引用,Microsoft.Extensions.Diagnostics.HealthChecks

现在,我们需要将HealthCheckService注册到依赖容器中。Microsoft.Extensions.Diagnostics.HealthChecks包定义了AddHealthChecks扩展方法,用于将HealthCheckService添加到容器中。我们可以从Program.cs文件中调用AddHealthChecks方法来添加DefaultHealthCheckService模块:

// Removed code for brevity.
// Add health check services to the container.
builder.Services.AddHealthChecks();
  1. 让我们继续配置健康检查端点到我们的 Web 应用程序。使用MapHealthChecks方法映射健康端点,如下面的代码所示,在Program.cs文件中。这将添加健康检查端点路由到应用程序。这将内部配置HealthCheckResponseWriters.WriteMinimalPlainText框架方法以输出响应。WriteMinimalPlainText将仅输出健康检查服务的总体状态:

    // Removed code for brevity.
    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllerRoute(
             name: "default",
             pattern: 
            "{controller=Products}/{action=Index}/{id?}");
        endpoints.MapHealthChecks("/health");
    });
    
  2. 运行应用程序并浏览到<<Application URL>>/health URL。您将看到以下输出:

https://github.com/OpenDocCN/freelearn-csharp-zh/raw/master/docs/entp-appdev-csp10-dn6/img/Figure_14.2_B18507.jpg

图 14.2 – 健康检查端点响应

我们添加的健康端点提供了关于服务可用性的基本信息。在下一节中,我们将看到如何监控依赖服务的状态。

监控依赖 URI

企业应用程序依赖于多个其他组件,例如数据库和包括KeyVault在内的 Azure 组件,以及其他微服务(例如我们的Ecommerce网站)依赖于订单服务、产品服务等。这些服务可能属于同一组织内的其他团队,或者在某些情况下,它们可能是外部服务。通常,监控依赖服务是一个好主意。我们可以利用AspNetCore.HealthChecks.Uris NuGet 包来监控依赖服务的可用性。

让我们继续增强我们的健康端点以监控产品和订单服务:

  1. 将 NuGet 包引用添加到AspNetCore.HealthChecks.Uris。现在,修改健康检查注册以注册产品和订单服务,如下面的代码片段所示:

    // Add health check services to the container.
    services.AddHealthChecks()
    .AddUrlGroup(new Uri(this.Configuration.GetValue<string>("ApplicationSettings:ProductsApiEndpoint ")), name: "Product Service")
    .AddUrlGroup(new Uri(this.Configuration.GetValue<string>("ApplicationSettings:OrdersApiEndpoint ")), name: "Order Service");
    

健康检查中间件还提供了关于单个健康检查状态的详细信息。

  1. 现在我们修改我们的健康检查中间件,以输出如下代码所示的详细信息:

    // Removed code for brevity.
    app.UseEndpoints(endpoints =>
    {
       endpoints.MapControllerRoute(
            name: "default",
            pattern: "{controller=Products}/{action=Index}/{id?}");
    endpoints.MapHealthChecks("/health", new 
              HealthCheckOptions
            {
              ResponseWriter = async (context, report) =>
              {
    context.Response.ContentType = 
                   "application/json";
                 var response = new
          {
             Status = report.Status.ToString(),
             HealthChecks = report.Entries.Select(x => new
             {
                Component = x.Key,
                Status = x.Value.Status.ToString(),
                Description = x.Value.Description,
              }),
              HealthCheckDuration = report.TotalDuration,
          };
          await context.Response.WriteAsync(
            JsonConvert.SerializeObject(response))
            .ConfigureAwait(false);
        },
       });
    });
    

在此代码中,健康检查中间件被重写,通过提供HealthCheckOptions和ResponseWriter来将其状态、健康检查持续时间、组件名称和描述作为其响应写入。

  1. 现在,如果我们运行项目并导航到健康检查 API,我们应该看到以下输出:

https://github.com/OpenDocCN/freelearn-csharp-zh/raw/master/docs/entp-appdev-csp10-dn6/img/Figure_14.3_B18507.jpg

图 14.3 – 健康检查端点响应状态

我们已经学习了如何自定义健康检查端点的响应,以及如何利用第三方库来监控依赖 URI 的状态。如果您希望集成通过 Entity Framework Core 使用的数据库的检查,可以利用Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore库。有关使用此库的更多信息,请参阅docs.microsoft.com/en-us/aspnet/core/host-and-deploy/health-checks?view=aspnetcore-6.0#entity-framework-core-dbcontext-probe。

可以在github.com/Xabaril/AspNetCore.Diagnostics.HealthChecks找到针对不同服务的更广泛的健康检查包集合。在下一节中,我们将学习如何构建自定义健康检查。

构建自定义健康检查

ASP.NET Core 6 中的健康检查中间件是可扩展的,这意味着它允许我们扩展并创建自定义健康检查。我们将通过构建进程监控器来学习如何构建和使用自定义健康检查。在某些场景中,可能需要监控机器上运行的特定进程。如果进程(例如,反恶意软件服务)没有运行,或者如果第三方 SaaS 服务的许可证即将到期/已到期,我们可能会将它们标记为健康问题。

让我们在Packt.Ecommerce.Common项目中开始创建ProcessMonitor健康检查:

  1. 在Packt.Ecommerce.Common中添加一个名为HealthCheck的项目文件夹,并添加两个类,ProcessMonitor和ProcessMonitorHealthCheckBuilderExtensions,如下面的截图所示:

https://github.com/OpenDocCN/freelearn-csharp-zh/raw/master/docs/entp-appdev-csp10-dn6/img/Figure_14.4_B18507.jpg

图 14.4 – 添加自定义健康检查后的项目结构

自定义HealthCheck中间件需要 NuGet 引用为Microsoft.Extensions.Diagnostics.HealthChecks。

  1. ASP.NET Core 6 中的自定义健康检查应该实现IHealthCheck接口。该接口定义了当请求到达健康端点 API 时将被调用的CheckHealthAsync方法。

  2. 按照以下代码实现ProcessMonitorHealthCheck类:

    public class ProcessMonitorHealthCheck : IHealthCheck
    {
       private readonly string processName;
       public ProcessMonitorHealthCheck(string 
         processName) => this.processName = processName;
       public Task<HealthCheckResult> 
         CheckHealthAsync(HealthCheckContext context, 
         CancellationToken cancellationToken = default)
        {
            Process[] pname = 
             Process.GetProcessesByName(this.processName);
            if (pname.Length == 0)
            {
                return Task.FromResult(new 
                  HealthCheckResult(context.Registration
                 .FailureStatus, description: $"Process 
                  with the name {this.processName} is not 
                  running."));
            }
            else
            {
                return Task.FromResult(
                  HealthCheckResult.Healthy());
            }
        }
    }
    

在CheckHealthAsync方法中,根据processName中指定的名称获取进程列表。如果没有这样的进程,则返回健康检查失败,否则,返回状态为失败。

  1. 现在我们有了自定义健康检查中间件,让我们添加一个扩展方法来注册。修改ProcessMonitorHealthCheckBuilderExtensions类,如下面的代码片段所示:

    public static class ProcessMonitorHealthCheckBuilderExtensions
        {
            public static IHealthChecksBuilder 
              AddProcessMonitorHealthCheck(
                this IHealthChecksBuilder builder,
                string processName = default,
                string name = default,
                HealthStatus? failureStatus = default,
                IEnumerable<string> tags = default)
            {
                return builder.Add(new 
                  HealthCheckRegistration(
                   name ?? "ProcessMonitor",
                   sp => new 
                   ProcessMonitorHealthCheck(processName),
                   failureStatus,
                   tags));
            }
        }
    

这是一个针对IHealthCheckBuilder的扩展方法。我们可以看到,在代码片段中添加ProcessMonitorHealthCheck会将它注册到容器中。

  1. 现在我们来使用我们构建的自定义健康检查。在下面的代码中,我们为notepad注册了ProcessMonitorHealthCheck健康检查:

    // Add health check services to the container.
    Builder.Services.AddHealthChecks()
    .AddUrlGroup(new Uri(this.Configuration.GetValue<string>("ApplicationSettings :ProductsApiEndpoint")), name: "Product Service")
    .AddUrlGroup(new Uri(this.Configuration.GetValue<string>("ApplicationSettings :OrdersApiEndpoint")), name: "Order Service")
    .AddProcessMonitorHealthCheck("notepad", name: "Notepad monitor");
    
  2. 现在,当你运行应用程序并导航到健康检查 API 时,如果你机器上正在运行notepad.exe,你将看到图 14.5中显示的输出:

https://github.com/OpenDocCN/freelearn-csharp-zh/raw/master/docs/entp-appdev-csp10-dn6/img/Figure_14.5_B18507.png

图 14.5 – 健康检查端点的响应

我们可以在我们的健康检查端点上启用跨源资源共享(CORS)、授权和主机限制。有关详细信息,请参阅docs.microsoft.com/en-us/aspnet/core/host-and-deploy/health-checks?view=aspnetcore-6.0。

在某些场景中,根据它们探测的应用程序状态,健康检查 API 被分为两种类型。它们如下:

  • 准备就绪探针:这些指示应用程序正在正常运行,但尚未准备好接收请求。

  • 存活探针:这些指示应用程序是否已崩溃并需要重启。

准备就绪探针和存活探针都用于控制应用程序的健康状态。失败的准备就绪探针将阻止应用程序处理流量,而失败的存活探针将重启节点。我们在 Kubernetes 等托管环境中使用准备就绪和存活探针。

我们已经学习了如何将健康检查 API 添加到 ASP.NET Core 6 应用程序中。在下一节中,我们将学习 Azure Application Insights 以及它是如何帮助监控应用程序的。

使用 Application Insights 监控应用程序

监控应用程序对于为最终用户提供一流体验至关重要。在当前这个超级快速数字市场的时代,应用程序监控对于推动业务投资回报率和保持竞争优势至关重要。我们应该关注的参数包括页面/API 性能、最常使用的页面/API、应用程序错误和系统健康等。当系统出现异常时,应设置警报,以便我们可以纠正它并最小化对用户的影响。

您已经在 第七章,在 .NET 6 中进行日志记录 中介绍了将 Application Insights 集成到应用程序及其关键功能。让我们在 Azure 门户中打开 Application Insights 并了解其不同的功能。在概览仪表板上,除了 Azure 订阅、位置和仪器密钥外,我们还可以看到以下关键指标:

https://github.com/OpenDocCN/freelearn-csharp-zh/raw/master/docs/entp-appdev-csp10-dn6/img/Figure_14.6_B18507.jpg

图 14.6 – Application Insights 仪表板

失败的请求 图显示了在所选时间段内失败的请求数量。这是我们应关注的指标;许多失败表示系统不稳定。服务器响应时间 表示服务器对调用的大致响应时间。如果响应时间过高,更多的用户将看到应用程序响应滞后,这可能会导致用户沮丧,我们可能会因此失去用户。

服务器请求 图表示对应用程序的总调用次数;这将给我们展示系统使用模式。可用性 图表示应用程序的运行时间。在本章后面配置的可用性测试将显示 可用性 图。通过点击每个图表,我们可以获取与相应指标相关的更多详细信息,包括请求和异常详情。我们可以更改持续时间来查看所选间隔的图表。

概览仪表板上的图表显示最近的指标。在希望了解过去特定时间点的系统工作情况时,这可能很有用。

在下一节中,我们将了解 Application Insights 的一些最重要的功能,包括实时指标、遥测事件和远程调试功能。

实时指标

默认情况下启用了实时指标。实时指标以 1 秒的延迟捕获,与按时间聚合的分析指标不同。只有当实时指标面板打开时,才会流式传输实时指标的数据。收集的数据仅在图表上存在。在实时指标监控期间,所有事件都从服务器传输,并且不会被采样。如果应用程序部署在 Web 农场中,我们还可以根据服务器过滤事件。

Live Metrics 展示了各种图表,例如入站和出站请求,以及内存和 CPU 利用率的整体健康状况。在右侧面板中,我们可以看到捕获的遥测数据,它将列出请求、依赖调用和异常。Live Metrics 在我们需要通过观察失败率和性能来评估已发布到生产环境的修复方案时被利用。我们也会在运行负载测试时监控这些数据,以查看负载对系统的影响。

对于像我们的 Ecommerce 应用这样的应用程序,了解用户如何使用应用程序、最常用的功能和用户如何遍历应用程序非常重要。在下一节中,我们将学习如何在 Application Insights 中进行使用分析。

使用 Application Insights 进行使用分析

在 第十一章,创建 ASP.NET Core 6 Web 应用程序 中,你学习了如何将 Application Insights 与视图集成。当 Application Insights 与视图集成时,它可以帮助我们深入了解人们如何使用应用程序。Application Insights 下的 使用 部分的 用户 刀片提供了有关使用应用程序的用户数量的详细信息。用户通过存储在浏览器 cookie 中的匿名 ID 来识别。请注意,使用不同浏览器和机器的单一个人被计为多个用户。会话 和 事件 刀片分别表示用户活动的会话以及某些页面或功能被使用的频率。你还可以根据你在 第七章,在 .NET 6 中记录日志 中了解的自定义事件生成关于用户、会话和事件的报告。

在使用分析中,还有一个有趣的工具叫做 用户流程。用户流程 工具可视化用户如何在不同页面和应用程序功能之间导航。用户流程提供了在用户会话期间给定事件之前和之后发生的事件。图 14.7 展示了给定时间点的用户流程。这告诉我们,从主页开始,用户主要导航到 产品详情 页面或 账户登录 页面:

https://github.com/OpenDocCN/freelearn-csharp-zh/raw/master/docs/entp-appdev-csp10-dn6/img/Figure_14.7_B18507.jpg

图 14.7 – 我们电商应用的用户流程

让我们添加一些自定义事件,并查看用户流程与这些自定义事件之间的关系。在 Packt.Ecommerce.Web 应用程序的 OrderController 的 Create 动作方法中添加一个自定义事件,如下面的代码片段所示。这将跟踪用户在 购物车 页面上点击 下单 按钮时发生的自定义事件:

this.telemetry.TrackEvent("Create Order");

同样,让我们添加一个自定义事件跟踪,当用户在 产品详情 页面上点击 加入购物车 按钮时。为此,添加以下代码片段:

this.telemetry.TrackEvent("Add Item To Cart");

添加自定义事件后,用户流程将显示与这些事件相关的应用程序的不同活动。用户流程是一个方便的工具,可以了解有多少用户正在离开页面以及他们在页面上点击了什么。请参考章节末尾的进一步阅读部分提供的 Azure 应用洞察文档,以了解更多关于使用分析的其他有趣功能,包括群体、漏斗和保留。

当有足够的遥测事件时,你可以使用一个名为智能检测的应用洞察功能,它能够自动检测系统中的异常并向我们发出警报。在下一节中,我们将学习关于智能检测的内容。

智能检测

智能检测不需要任何配置或代码更改。它基于从系统中捕获的遥测数据工作。警报将在系统的智能检测选项卡下显示,并且这些警报将发送给具有监控读取器和监控贡献者角色的用户。我们可以在设置选项下为这些警报配置额外的收件人。一些智能检测规则包括页面加载时间慢、服务器响应时间慢、每日数据量异常增加和依赖项数量下降。

对于应用程序,我们需要监控的一个重要方面是可用性。在下一节中,我们将学习如何利用应用洞察来监控应用程序的可用性。

应用程序可用性

在应用洞察中,我们可以为任何从互联网可访问的http或https端点设置可用性测试。这不需要对我们的应用程序代码进行任何更改。我们可以为可用性测试配置健康检查端点(<App Root URL>/health)。

要配置可用性测试,请转到 Azure 门户中的应用洞察资源,并执行以下步骤:

  1. 在调查菜单下选择可用性,如图所示:

![图 14.8 – 应用洞察的可用性部分

![img/Figure_14.8_B18507.jpg]

图 14.8 – 应用洞察的可用性部分

  1. 点击添加测试以添加可用性测试,如前一张截图所示。

  2. 在Commerce 可用性测试中,选择<<App root url>>/health。将其他选项保留在默认值,然后点击创建。

  3. 一旦测试配置完成,应用洞察将从所有配置的区域每 5 分钟调用一次配置的 URL。我们可以如下查看可用性测试结果:

![图 14.9 – 可用性测试结果

![img/Figure_14.9_B18507.jpg]

图 14.9 – 可用性测试结果

  1. 在创建测试时选择的默认区域为巴西南部、东亚、日本东部、东南亚和英国南部。我们可以添加或删除将在其上运行可用性测试的任何区域。建议至少配置五个区域。

  2. 如果我们想在以后的时间添加新的区域,我们可以编辑可用性测试并选择新的区域(例如,西欧),如下面的屏幕截图所示,然后点击保存:

https://github.com/OpenDocCN/freelearn-csharp-zh/raw/master/docs/entp-appdev-csp10-dn6/img/Figure_14.10_B18507.jpg

![图 14.10 – 编辑可用性测试区域

我们还可以在 Application Insights 中将多步骤 Web 测试配置为可用性测试。

备注

您可以使用以下文档来帮助您配置多步骤 Web 测试:docs.microsoft.com/en-us/azure/azure-monitor/app/availability-multistep。

Application Insights 提供了一个非常好的工具来查询捕获的遥测事件。在下一节中,我们将了解 Application Insights 中的搜索功能。

搜索

Application Insights 中的搜索功能有助于探索遥测事件,如请求、页面视图和异常。我们还可以查询我们在应用程序中编码的跟踪。搜索可以从概览选项卡或从调查选项卡的搜索选项中打开:

https://github.com/OpenDocCN/freelearn-csharp-zh/raw/master/docs/entp-appdev-csp10-dn6/img/Figure_14.11_B18507.jpg

https://github.com/OpenDocCN/freelearn-csharp-zh/raw/master/docs/entp-appdev-csp10-dn6/img/Figure_14.12_B18507.jpg

https://github.com/OpenDocCN/freelearn-csharp-zh/raw/master/docs/entp-appdev-csp10-dn6/img/Figure_14.14_B18507.jpg

图 14.14 – 端到端事务详情

我们甚至可以通过点击异常来进一步深入。这将显示诸如方法名称和堆栈跟踪等详细信息,这将帮助我们确定失败的原因。

使用 Application Insights,我们可以对捕获的遥测数据编写自定义查询,以获得更有意义的见解。在下一节中,我们将学习如何编写查询。

日志

要对捕获的遥测数据进行查询,请按照以下步骤导航:

  1. 前往Application Insights | 监控 | 日志。这将显示日志页面,其中包含我们可以运行的示例查询:

https://github.com/OpenDocCN/freelearn-csharp-zh/raw/master/docs/entp-appdev-csp10-dn6/img/Figure_14.15_B18507.jpg

图 14.15 – Application Insights 日志

  1. 在建议的样本查询中选择请求计数趋势。这将为我们生成一个查询并运行它。一旦运行完成,我们将看到结果和图表被填充,如下面的截图所示:

https://github.com/OpenDocCN/freelearn-csharp-zh/raw/master/docs/entp-appdev-csp10-dn6/img/Figure_14.16_B18507.jpg

图 14.16 – 日志搜索结果

在 Application Insights 中捕获的遥测数据进入不同的表,涵盖请求、异常、依赖项、跟踪和页面视图。这里生成的查询汇总了请求表中的遥测数据,并渲染了一个时间图表,其中时间轴被分成 30 分钟。

我们根据需求选择时间范围。我们甚至可以在查询中指定时间范围,而不是从菜单选项中选择。这里创建的查询可以保存并在以后重新运行。这里还有一个配置警报的选项,我们曾在第七章中了解到,即.NET 6 中的日志记录。这里编写查询使用的语言是 Kusto。

注意

有关 Kusto 查询语言的更多信息,请参阅以下文档:docs.microsoft.com/en-us/azure/data-explorer/kusto/concepts/。

Kusto 基于关系数据库结构。使用 Kusto 查询语言,我们可以编写复杂的分析查询。Kusto 支持按组聚合、计算列和连接函数。

让我们再举一个例子,我们想要识别每个客户城市的 95 百分位服务响应时间。这个查询将如下编写:

requests
| summarize 95percentile=percentile(duration, 0.95) by client_City
| render barchart

在前面的查询中,我们使用percentile函数来识别 95 百分位并按区域进行汇总。结果以条形图的形式呈现。

对于前面的查询,我们看到以下图表:

https://github.com/OpenDocCN/freelearn-csharp-zh/raw/master/docs/entp-appdev-csp10-dn6/img/Figure_14.17_B18507.jpg

图 14.17 – Kusto 百分位摘要结果

从渲染的图表中,我们可以推断出来自钦奈的请求响应时间比来自西姆纳巴德的请求响应时间更快。

现在,让我们找到任何导致请求失败的异常,并按请求和异常类型进行汇总。为了得到这个结果,我们将requests表与exceptions表连接,并根据请求名称和异常类型进行汇总,如下面的查询所示:

requests
| join kind= inner (
exceptions
) on operation_Id
| project requestName = name, exceptionType = type
| summarize count=sum(1)  by requestName, exceptionType

如果我们运行这个查询,我们会得到以下截图所示的按请求名称和异常类型汇总的结果:

https://github.com/OpenDocCN/freelearn-csharp-zh/raw/master/docs/entp-appdev-csp10-dn6/img/Figure_14.18_B18507.jpg

图 14.18 – Kusto 失败的请求异常

搜索是 Application Insights 的强大功能,用于诊断和修复生产站点的故障。建议点击 Application Insights 的不同功能并探索它们。

当您创建 Application Insights 资源时,将创建一个日志分析工作区,该工作区将持久保存通过 Application Insights 捕获的遥测数据。使用日志分析工作区以及应用程序度量,我们还可以查询和监控与 Azure 资源相关的关键指标,例如在 Cosmos DB 中消耗的 RU/s。本节中运行的所有查询都是在日志分析工作区中执行的。我们可以在 Azure 门户中创建仪表板,并将所有与我们要跟踪的应用程序关键指标相关的图表固定在仪表板上。

注意

参考 Azure 文档以了解更多关于日志分析的信息:docs.microsoft.com/en-us/azure/azure-monitor/logs/log-analytics-overview。

在本节中,我们学习了如何使用 Azure Monitor 监控在 Azure 中部署的应用程序。为了更好地分析和调试任何生产故障,我们可能想了解特定错误发生时应用程序的状态。在下一节中,我们将学习 Application Insights 的快照调试器功能如何使我们实现这一点。

配置快照调试器

快照调试器监控我们应用程序的异常遥测。它自动收集应用程序中发生的顶级异常的快照,包括当前源代码的状态和变量。

注意

快照调试器功能仅在 Visual Studio 的企业版中可用。

现在让我们继续配置我们的Ecommerce应用的快照调试器:

  1. 将Microsoft.ApplicationInsights.SnapshotCollector NuGet 包添加到Packt.Ecommerce.Web项目中。

  2. 将以下using语句添加到Startup.cs中:

    using Microsoft.ApplicationInsights.SnapshotCollector;
    
  3. 通过在ConfigureServices方法中添加以下行,将快照收集器添加到您的服务中:

    services.AddApplicationInsightsTelemetry(this.Configuration["ApplicationInsights:InstrumentationKey"]);
    builder.Services.AddSnapshotCollector((configuration) => this.Configuration.Bind(nameof(SnapshotCollectorConfiguration), configuration));
    
  4. 要模拟失败,请将以下代码添加到EcommerceService类的GetProductsAsync方法中。如果存在任何产品,此代码将引发错误:

    public async Task<IEnumerable<ProductListViewModel>> GetProductsAsync(string filterCriteria = null)
    {        
                // Code removed for brevity
                if (products.Any())
                {
                    throw new InvalidOperationException();
                }
                return products;
    }
    
  5. 现在,让我们继续运行应用程序。我们在主页上看到一个错误。刷新页面,因为调试快照是为至少发生两次的错误而设计的。

  6. 现在,打开 Application Insights 中的搜索选项卡。按异常事件类型进行筛选:

https://github.com/OpenDocCN/freelearn-csharp-zh/raw/master/docs/entp-appdev-csp10-dn6/img/Figure_14.19_B18507.jpg

图 14.19 – 异常遥测

  1. 点击异常进入详情页面。在详情页面中,我们看到已经为异常创建了调试快照,如以下截图所示:

https://github.com/OpenDocCN/freelearn-csharp-zh/raw/master/docs/entp-appdev-csp10-dn6/img/Figure_14.20_B18507.jpg

图 14.20 – 调试快照

  1. 点击调试快照图标。这将带我们到调试快照页面:

https://github.com/OpenDocCN/freelearn-csharp-zh/raw/master/docs/entp-appdev-csp10-dn6/img/Figure_14.21_B18507.jpg

图 14.21 – 调试快照窗口

  1. 要查看调试快照,需要应用程序洞察快照调试器角色。由于调试状态可能包含敏感信息,因此默认情况下不会添加此角色。单击添加应用程序洞察快照调试器角色按钮。这将向当前登录用户添加该角色。

  2. 一旦角色添加完成,我们就可以在页面上看到调试快照的详细信息,以及一个下载快照的按钮:

https://github.com/OpenDocCN/freelearn-csharp-zh/raw/master/docs/entp-appdev-csp10-dn6/img/Figure_14.22_B18507.jpg

图 14.22 – 下载调试快照

  1. 单击 diagsession。在 Visual Studio 中打开下载的 diagsession 文件:

https://github.com/OpenDocCN/freelearn-csharp-zh/raw/master/docs/entp-appdev-csp10-dn6/img/Figure_14.23_B18507.jpg

图 14.23 – Visual Studio 中的调试快照视图

  1. 现在,单击 InvalidOperationException:

https://github.com/OpenDocCN/freelearn-csharp-zh/raw/master/docs/entp-appdev-csp10-dn6/img/Figure_14.24_B18507.jpg

图 14.24 – Visual Studio 中的调试快照

在此调试会话中,我们可能需要将监视器添加到局部变量和类变量,以了解它们的状态,这将有助于调试。

注意

请参阅以下文档以了解有关快照调试器配置的更多信息:docs.microsoft.com/en-us/azure/azure-monitor/app/snapshot-debugger-vm。

随着应用程序的增长并与多个其他服务集成,将面临在生产环境中调试和解决出现的问题的挑战。在某些情况下,我们无法在预生产环境中重现它们。通过我们捕获的遥测数据和 Application Insights 提供的工具,我们将能够分析问题并解决问题。快照调试器是一个强大的工具,用于调试关键问题。Application Insights 收集遥测数据并通过后台进程批量发送。使用 Application Insights 对我们应用程序的影响很小。

可能存在我们需要调试一个运行中的应用程序的情况。使用 Visual Studio,我们可以将调试器附加到远程运行的应用程序以进行调试。在下一节中,我们将学习如何实现这一点。

执行远程调试

在本节中,我们将学习如何将调试器附加到我们在 Azure App Service 中部署的应用程序。使用 Visual Studio 提供的工具,远程调试应用程序很容易。在 Azure App Service 中部署应用程序的内容在 第十六章,在 Azure 中部署应用程序 中介绍。我们可以通过执行以下操作将调试器附加到已部署的服务:

  1. 通过右键单击Packt.Ecommerce.Web项目并从上下文菜单中选择发布,或通过设置构建|发布****Packt.Ecommerce.Web菜单项来启动发布窗口。

  2. 通过在发布向导中选择 Azure App Service 资源,为 Packt.Ecommerce.Web 创建一个 发布 配置文件。

  3. 创建 发布 配置文件后,您可以通过从 托管 选项中选择 附加调试器 来将调试器附加到在 Azure App Service 中运行的应用程序实例,如下面的屏幕截图所示:

https://github.com/OpenDocCN/freelearn-csharp-zh/raw/master/docs/entp-appdev-csp10-dn6/img/Figure_14.25_B18507.jpg

图 14.25 – Visual Studio 的发布窗口

  1. 一旦调试器连接,应用程序将在 Azure App Service 中通过浏览器打开。我们可以在 Visual Studio 中添加断点,并像在本地开发环境中一样调试应用程序。为了有效地调试,我们需要将应用程序的调试版本部署到 Azure App Service。

虽然这是远程部署应用程序的强大功能,但在将调试器附加到生产实例时应格外小心,因为我们将会看到实时客户数据。我们可以将调试器附加到 Azure App Service 的预发布槽位以调试和修复问题,然后从那里交换预发布槽位以将修复推广到生产。本章未涵盖 Application Insights 和 Azure Monitor 的许多其他重要功能。强烈建议在 Azure 文档中进一步探索它们。

摘要

本章向您介绍了使用 Application Insights 对应用程序进行健康检查和诊断问题的概念。我们学习了如何构建健康检查 API 并将健康检查模块添加到我们的 Ecommerce 应用程序中,这将帮助我们监控应用程序的健康状况。本章还介绍了 Azure Application Insights 的关键特性,它是一个强大的工具,用于捕获遥测数据和诊断问题。

我们学习了如何使用智能检测功能检测 Application Insights 中的异常和警报。我们还了解了快照和远程调试,这些有助于在生产环境中运行的实时应用程序中解决问题。

在下一章中,我们将学习不同的测试方法,以确保在部署到生产环境之前应用程序的质量。

问题

在阅读本章后,我们应该能够回答以下问题:

  1. 一旦应用程序部署到生产环境,定期监控应用程序并不那么重要。对还是错?

a. 正确

b. 错误

答案:b

  1. 自定义健康检查模块应该实现哪个接口?

a. IHealth

b. IApplicationBuilder

c. IHealthCheck

d. IWebHostEnvironment

答案:c

  1. 在 Application Insights 中显示实时指标数据的延迟是多少?

a. 1 分钟

b. 1 秒

c. 10 秒

d. 5 秒

答案:b

  1. 在 Application Insights 日志中编写查询所使用的查询语言是什么?

a. SQL

b. C#

c. JavaScript

d. Kusto

答案:d

进一步阅读

第十五章:第十五章:测试

任何应用程序的成功取决于用户使用它的难易程度。任何软件产品的寿命直接取决于产品的质量。

测试是软件开发生命周期(SDLC)的一个重要方面,并确保产品满足客户的要求和质量要求。测试同样重要,因为随着我们进入 SDLC 的后期阶段,修复错误的成本会增加。

在本章中,我们将学习不同类型的测试以及 Visual Studio 为测试提供的工具,以及查看我们可以使用的第三方工具,以确保我们在.NET 6 中构建的产品质量。

在本章中,我们将学习以下内容:

  • 测试类型

  • 单元测试

  • 功能测试

  • 理解负载测试的重要性

到本章结束时,您将了解确保产品质量所需的一切知识。

技术要求

您将需要 Visual Studio 2022 社区版。(某些部分需要企业版。)

除了 Visual Studio,您还需要 JMeter,可以从这里下载:jmeter.apache.org/download_jmeter.cgi。您还需要对 Microsoft .NET 有基本的了解。

介绍测试

软件测试是一种检查应用程序是否按预期执行的方法。这些期望可能与功能、响应性或软件在运行时消耗的资源有关。

根据执行方式,软件测试可以大致分为以下两类:

  • 手动测试:在手动测试中,测试人员通过使用测试的应用程序手动执行测试用例,并验证预期的结果。手动测试比替代方案需要更多的努力。

  • 自动化测试:自动化测试由专门的自动化测试软件执行。此自动化软件在测试的应用程序中运行于特定环境中,并验证预期的输出。自动化测试可以节省大量时间和人力。在某些情况下,实现 100%的自动化可能需要付出很多努力,并且以相对较低的投资回报率(ROI)来维护自动化。

根据对测试应用程序内部信息(如代码流和依赖模块集成)的了解,软件测试也可以广泛地按以下方式进行分类:

  • 黑盒测试:在黑盒测试中,负责测试的个人没有关于系统内部的信息。这里的重点是系统的行为。

  • 白盒测试:在白盒测试中,测试人员了解系统的内部结构、设计和实现。白盒测试的重点是测试实现中存在的替代路径。

在软件测试中,我们验证应用程序的不同方面。软件测试还有以下变体,基于它验证的应用程序方面以及它使用的工具或框架:

  • 单元测试:单元测试关注应用程序的最小单元。在这里,我们验证单个类或函数。这通常在开发阶段完成。

  • 功能测试:这通常被称为集成测试。其主要目的是确保应用程序按要求执行。

  • 回归测试:回归测试确保任何最近的变化都没有对应用程序性能产生不利影响,并且现有功能没有受到任何变化的影响。在回归测试中,根据应用程序中引入的变化,执行所有或部分功能测试用例。

  • 烟雾测试:在每次部署后进行烟雾测试,以确保应用程序稳定且准备就绪。这也被称为构建验证测试(BVT)。

  • 负载测试:负载测试用于确定系统的整体有效性。在负载测试期间,我们模拟集成系统上的预期负载。

  • 压力测试:在压力测试中,我们将系统推到预期容量或负载之外。这有助于我们识别系统中的瓶颈和故障点。性能测试是用于压力测试和负载测试的通用术语。

  • 安全测试:安全测试是为了确保应用程序的完美执行。在安全测试中,我们专注于评估安全方面的各种元素,如完整性、机密性和真实性等。

  • 可访问性测试:可访问性测试旨在确定不同能力的人是否能够使用应用程序。

现在我们已经看到了不同类型的测试,在接下来的章节中,我们将详细介绍单元测试、功能测试和负载测试,因为它们对于确保应用程序的稳定性至关重要。

注意

要深入了解安全方面,请尝试使用静态代码分析工具进行安全测试:docs.microsoft.com/en-us/azure/security/develop/security-code-analysis-overview。更多关于可访问性的信息可以在这里找到:accessibilityinsights.io/。

性能测试、可访问性测试和安全测试是我们执行以评估应用程序非功能性方面的测试,例如性能、可用性、可靠性、安全性和可访问性。

现在,让我们看看如何为我们电子商务应用程序执行单元测试。

单元测试

单元测试是测试应用程序最小隔离单元的一种方式。它是软件开发中的重要步骤,有助于早期隔离问题。

单元测试对我们构建的软件质量有直接影响。建议在编写任何方法后立即编写单元测试。如果我们遵循测试驱动开发(TDD)的方法论,我们首先编写测试用例,然后继续实现功能。

在下一节中,我们将学习如何在 Visual Studio 中创建单元测试并运行它们。

Visual Studio 中的单元测试

我们选择使用 Visual Studio,因为它具有创建和管理测试用例的强大工具。

使用 Visual Studio,我们可以创建、调试和运行单元测试用例。我们还可以检查已执行的测试的代码覆盖率。此外,它还具有实时单元测试功能,在修改代码的同时运行单元测试,并将结果实时显示。

我们将在接下来的章节中探讨所有这些功能。

创建和运行单元测试

让我们继续创建一个单元测试项目,以对Packt.ECommerce.Order项目进行单元测试。

执行以下步骤以创建单元测试用例:

  1. 在Tests文件夹中添加一个新的项目,并将其命名为Packt.ECommerce.Order.UnitTest:

![Figure 15.1 – Visual Studio xUnit 测试项目

![img/Figure_15.1_B18507.jpg]

图 15.1 – Visual Studio xUnit 测试项目

  1. 将Packt.ECommerce.Order项目添加到新创建的测试项目中。

  2. 向测试项目添加一个新类,并将其命名为OrdersControllerTest。我们将在这个类中添加所有与OrdersController相关的测试用例。

  3. 现在,让我们添加一个简单的测试来测试OrdersController控制器的构造函数。我们将进行的测试是断言成功创建OrderController控制器。现在让我们添加测试,如下面的代码所示:

    [Fact]
    public async Task Create_Object_OfType_OrderController ()
    {
    OrdersController testObject = new 
            OrdersController(null);
          Assert.NotNull(testObject);
    }
    

Create_Object_OfType_OrderController测试方法被赋予Fact属性;这是xUnit框架发现测试方法所必需的。在这里,我们通过检查创建的对象的null条件来进行断言。

  1. Visual Studio 提供测试资源管理器来管理和运行测试。让我们通过转到测试 | 测试资源管理器来打开它。

  2. 构建解决方案以在测试资源管理器中查看测试。

  3. 在通过右键单击并从上下文菜单中选择运行创建的OrderController_Constructor测试中:

![Figure 15.2 – 从测试资源管理器窗口的测试运行上下文菜单

![img/Figure_15.2_B18507.jpg]

图 15.2 – 从测试资源管理器窗口的测试运行上下文菜单

  1. 一旦测试执行完毕,我们可以在右侧窗格中看到测试结果。从结果中,我们可以看到测试已成功执行,如下所示:

![Figure 15.3 – 从测试资源管理器获取的测试结果

![img/Figure_15.3_B18507.jpg]

图 15.3 – 从测试资源管理器获取的测试结果

我们已经在 Visual Studio 中创建并执行了一个简单的测试。在下一节中,我们将学习如何模拟OrdersController的依赖项以验证功能。

使用 Moq 模拟依赖项

通常,被测试的方法会调用其他外部方法或服务,我们称之为依赖项。为了确保被测试方法的函数性,我们通过为依赖项创建模拟对象来隔离依赖项的行为。

在一个应用程序中,类可能依赖于其他类;例如,我们的OrdersController类依赖于OrderService。在测试OrdersController时,我们应该隔离OrderService的行为。

为了理解模拟,让我们为OrdersController的GetOrdersAsync操作方法创建单元测试。

让我们看看我们正在为其编写单元测试用例的GetOrderById方法:

//This is the GetOrderById action method in OrdersController.cs
[HttpGet]
[Route("{id}")]
public async Task<IActionResult> GetOrderById(string id)
{
     var order = await 
       this.orderService.GetOrderByIdAsync(id)
       .ConfigureAwait(false);
     if (order != null)
     {
          return this.Ok(order);
     }
     else
     {
          return this.NotFound();
     }
}

在这个方法中,调用orderService的GetOrderByIdAsync以根据传入的id实例获取订单。控制器操作将返回从OrderService检索到的订单id;否则,返回NotFound操作。

正如我们所看到的,代码流有两个路径:

  • 一条路径是当订单存在时。

  • 另一条路径是当订单不存在时。

通过单元测试,我们应该能够覆盖这两个路径。所以,现在出现的问题是,我们如何模拟这两个情况?

我们想要在这里模拟OrderService的响应。为了模拟OrderService的响应,我们可以利用Moq库。为了利用 Moq,我们需要将Moq包的 NuGet 引用添加到Packt.ECommerce.Order.UnitTest测试项目中。

让我们在OrdersControllerTest类中添加测试方法,如下所示,以测试OrdersController的GetOrderById方法,以验证当OrderService返回订单对象的情况:

[TestMethod]
public async Task When_GetOrdersAsync_with_ExistingOrder_receive_OkObjectResult()
{
     var stub = new Mock<IOrderService>();
    stub.Setup(x => x.GetOrderByIdAsync(
It.IsAny<string>())).Returns(Task.FromResult(new 
      OrderDetailsViewModel { Id = "1" }));
    OrdersController testObject = new 
      OrdersController(stub.Object);
    var order = await 
      testObject.GetOrderById("1").ConfigureAwait(false);
    Assert.IsType<OkObjectResult>(order, 
      typeof(OkObjectResult));
}

从代码中,我们可以观察到以下内容:

  • 由于IOrderService通过控制器注入注入到OrderController中,我们可以向OrderController注入一个模拟的OrderService,这将帮助我们通过改变模拟对象的行为来测试OrderController的所有代码路径。

  • 我们利用Mock类为IOrderService创建一个存根(也称为模拟),并覆盖前面的代码中的GetOrderByIdAsync行为。

  • 我们为IOrderService接口创建一个Mock对象实例,并通过在Mock对象上调用Setup方法来设置GetOrderByIdAsync的行为。

  • GetOrderByIdAsync方法被模拟,使得对于它接收到的任何参数值,mock对象将返回具有Id为1的OrderDetailsViewModel对象。

  • 由于我们通过构造函数注入将模拟对象注入到OrderService中,因此每当调用IOrderService中的任何方法时,调用将转到IOrderService的模拟实现。

  • 最后,我们通过验证从OrderController返回到OkObjectResult的结果类型来断言测试结果。

现在,让我们添加一个测试用例来验证当订单不存在时接收NotFound结果的行为,如下所示:

[TestMethod]
public async Task When_GetOrdersAsync_with_No_ExistingOrder_receive_NotFoundResult()
{
     var stub = new Mock<IOrderService>();
stub.Setup(x => 
     x.GetOrderByIdAsync(It.IsAny<string>()))
    .Returns(Task.FromResult<OrderDetailsViewModel>(null));
     OrdersController testObject = new 
       OrdersController(stub.Object);
     var order = await testObject
       .GetOrderById("1").ConfigureAwait(false);
Assert.IsType<NotFoundResult>(order, 
       typeof(NotFoundResult));
}

在这个测试用例中,我们通过从OrderService存根返回一个null值来模拟订单不存在的行为。这将使OrdersController的GetOrderById操作方法返回NotFoundResult,并在测试用例中进行验证。

注意

OrderService类依赖于IHttpClientFactory、IOptions、Mapper和DistributedCacheService。因此,为了为这个添加单元测试,我们应该模拟它们所有。您可以在 GitHub 代码示例的OrderServiceTest测试类中的When_GetOrderByIdAsync_with_ExistingOrder_receive_Order测试方法中查看更多详细信息。

在本节中,我们看到了如何利用xUnit框架创建单元测试。还有几个其他测试框架可用于在.NET 中创建单元测试。这里值得提到的两个框架是 MSTest 和 NUnit。尽管这些框架在测试执行方式上存在一些差异,但所有这些框架都非常出色,并提供诸如模拟和并行执行等功能。由于其简单性和可扩展性,xUnit 相对于竞争框架有一定的优势。我们还可以使用 xUnit 中的Theory编写数据驱动测试,如下面的代码片段所示:

[Theory]
[InlineData(999, 19.98)]
[InlineData(2000, 100)]
public void When_ComputeTotalDiscount_with_OrderTotalAmount(double number, double expectedResult)
{
<<Code removed for brevity>>
   OrdersService testObject = new 
     OrdersService(httpClientFactory, mockOptions, mapper, 
     mockCacheService.Object);
   var result = testObject.ComputeTotalDiscount(number);
   Assert.Equal(result, expectedResult);
}

在前面的代码片段中,测试方法通过InlineData属性传递的测试数据执行。

在单元测试中,我们的目标是通过对依赖类的行为进行模拟来测试一个特定的类。如果我们与其他依赖类一起测试这些类,我们称之为集成测试。我们在各种级别编写集成测试:在特定模块或程序集的级别,在微服务级别,或在整个应用级别。

现在我们已经为我们的电子商务解决方案添加了单元测试用例,在下一节中,我们将检查这些测试的代码覆盖率。

代码覆盖率

代码覆盖率是衡量我们的测试用例覆盖了多少代码的一个指标。Visual Studio 提供了一个工具来查找单元测试的代码覆盖率。我们可以运行测试 | 分析代码覆盖率来对所有测试进行操作,如下所示:

![图 15.4 – 文本探索器中的“分析代码覆盖率”上下文选项]

](https://github.com/OpenDocCN/freelearn-csharp-zh/raw/master/docs/entp-appdev-csp10-dn6/img/Figure_15.4_B18507.jpg)

图 15.4 – 文本探索器中的“分析代码覆盖率”上下文选项

这也可以从测试资源管理器的上下文菜单中完成。

注意

分析代码覆盖率功能仅在 Visual Studio 的企业版中可用。如果您使用的是社区版,您可以使用 Visual Studio 免费扩展程序,marketplace.visualstudio.com/items?itemName=FortuneNgwenya.FineCodeCoverage,来查看代码覆盖率结果。

这将运行所有测试用例并识别任何未测试的代码块。我们可以在以下代码覆盖率结果窗口中查看代码覆盖率结果:

![图 15.5 – Visual Studio 代码覆盖率结果窗口]

https://github.com/OpenDocCN/freelearn-csharp-zh/raw/master/docs/entp-appdev-csp10-dn6/img/Figure_15.5_B18507.jpg

图 15.5 – Visual Studio Code 覆盖率结果窗口

GetOrderByIdAsync,该方法的代码覆盖率是GetOrdersAsync为0.00%,因为我们没有测试用例来测试它。代码覆盖率为我们提供了关于我们的单元测试有效性的良好指示。

建议为解决方案中的所有类创建单元测试用例。通过添加单元测试来验证所有类和功能,将会有更高比例的代码被单元测试用例覆盖。随着代码覆盖率的提高,我们将在开发过程中对解决方案进行更改时能够更早地捕获更多错误。我们应该在提交更改之前确保所有测试用例都通过。在下一章,第十六章,在 Azure 中部署应用程序,我们将学习如何将运行测试用例与 Azure DevOps 管道集成。

到目前为止,我们已经通过模拟依赖关系和编写单元测试用例来测试单个模块或类。在集成和部署整个解决方案后测试功能也很重要。在下一节中,我们将学习如何为我们电子商务应用执行功能测试。

小贴士

Visual Studio 的代码指标和代码分析工具对于确保我们编写的代码的可维护性和可读性非常有用。您可以在以下位置找到有关代码指标的信息:docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-values?view=vs-2022。

对于代码分析,请访问此处:docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/overview。

功能测试

在功能测试中,我们验证我们构建的应用是否符合功能需求。功能测试通过提供一些输入并断言应用的响应或输出来进行。在进行功能测试时,我们将应用视为一个整体;我们不是验证单个内部组件。

功能测试可以分为三个任务:

  1. 识别待测试系统的功能

  2. 确定具有预期输出的输入

  3. 执行这些测试以评估系统是否按预期响应

功能测试的执行可以通过在应用上执行测试步骤手动进行,或者我们可以使用工具来自动化它们。通过自动化功能测试,可以显著缩短应用的上市时间。

在下一节中,我们将学习如何自动化功能测试用例。

自动化功能测试用例

手动执行功能测试用例在应用程序测试中仍然相关。然而,考虑到更短的部署周期和客户对快速获取新功能的期望,手动测试可能会非常耗时且效率低下,尤其是在早期识别缺陷方面。使用自动化,我们可以获得新的效率,加速测试过程,并提高软件质量。有多种工具和框架可用于自动化功能测试用例。

在本节中,我们将了解最受欢迎的自动化框架 Selenium。让我们开始:

  1. 首先,让我们创建一个名为 MSTest 的项目,并将其命名为 Packt.ECommerce.FunctionalTest。

  2. 向此项目添加 Selenium.WebDriver、Selenium.WebDriver.ChromeDriver 和 WebDriverManager NuGet 包。这些包是我们运行 Selenium 测试所必需的。

  3. 让我们从一项简单的测试开始,以验证我们电子商务应用程序的标题。为此,创建一个名为 HomePageTest 的测试类和一个名为 When_Application_Launched_Title_Should_be_ECommerce_Packt 的测试方法,就像我们在 单元测试 部分所做的那样,如下面的代码所示:

    [TestClass]
    public class HomePageTest
    {
       [TestMethod]
        public void When_Application_Launched_Title
          _Should_be_ECommerce_Packt()
    {
    }
    }
    
  4. 要执行我们的功能测试,我们应该启动一个浏览器并使用该浏览器导航到电子商务应用程序。MSTest 框架提供了一个特殊函数来执行测试所需的初始化和清理操作。我们将创建一个 Chrome 网络驱动程序来执行功能测试。

让我们继续添加初始化和清理方法,如下面的代码所示:

[TestClass]
public class HomePageTest
{
     ChromeDriver _webDriver = null;
     [TestInitialize]
public void InitializeWebDriver()
     {
            var d = new DriverManager();
            d.SetUpDriver(new ChromeConfig());
            _webDriver = new ChromeDriver();
     }
     [TestMethod]
     public void When_Application_Launched_Title
       _Should_be_ECommerce_Packt()
     {
     }
     [TestCleanup]
     public void WebDriverCleanup()
     {
            _webDriver.Quit();
     }
}

在前面的代码中,InitializeDriver 方法被赋予 TestInitialize 属性,以通知框架这是一个测试初始化方法。在测试初始化中,我们创建 ChromeDriver 并初始化类变量。测试用例完成后,我们应该关闭浏览器实例;我们通过在 WebDriverCleanup 方法中调用 Quit 方法来完成此操作。为了通知测试框架这是一个清理方法,它应该被赋予 TestCleanup 属性。

  1. 现在,让我们添加测试用例以导航到电子商务应用程序并验证标题,如下面的代码所示:

    [TestMethod]
    public void When_Application_Launched_Title_Should_be_ECommerce_Packt()
    {
         _webDriver.Navigate().GoToUrl("https://localhost:
           44365/");
    Assert.AreEqual("Ecommerce Packt", 
           _webDriver.Title);
    }
    

在我们的 Chrome 网络驱动程序上调用 GoToUrl 以导航到电子商务应用程序。一旦导航成功,我们可以通过断言网络驱动程序的 Title 属性来验证页面标题。

  1. 从 When_Application_Launched_Title_Should_be_ECommerce_Pact 测试用例运行测试用例,并选择 运行。这将打开 Chrome 浏览器并导航到指定的电子商务 URL,然后断言页面标题。测试用例执行完毕后,浏览器将被关闭。我们可以在 测试资源管理器 中看到结果,如下面的截图所示:

https://github.com/OpenDocCN/freelearn-csharp-zh/raw/master/docs/entp-appdev-csp10-dn6/img/Figure_15.6_B18507.jpg

图 15.6 – 创建测试项目后的解决方案结构

  1. 现在,我们将扩展功能测试以验证搜索功能。为了测试这个功能,我们应该在搜索框中输入文本并点击搜索按钮。然后,检查结果以查看返回的测试结果是否仅针对搜索的产品。

  2. 让我们通过添加When_Searched_For_Item测试方法来自动化测试用例,如下面的代码所示:

    [TestMethod]
    public void When_Searched_For_Item()
    {
          _webDriver.Navigate().GoToUrl("https://localhost
            :44365/");
          var searchTextBox = 
          _webDriver.FindElement(By.Name("SearchString"));
           searchTextBox.SendKeys("Orange Shirt");
           _webDriver.FindElement(By.Name("searchButton"))
             .Click();
           var items = 
            _webDriver.FindElements(By.ClassName("product-
            description"));
           var invaidProductCout = items.Where(e => e.Text 
            != "Orange Shirt").Count();
           Assert.AreEqual(0, invaidProductCout);
    }
    

在这个测试用例中,在导航到主页后,在search字符串中输入搜索文本。

Selenium 使得编写功能测试变得非常简单。我们应该尝试自动化所有功能测试用例,例如用户管理、将产品添加到购物车和下订单。当所有功能测试用例都自动化后,我们将处于更好的位置来测试和验证新版本的功能,并保持我们应用程序的质量。还有其他功能测试工具可用,例如 QTP 和 Visual Studio Coded UI 测试。

我们已经了解了功能测试,它验证了应用程序的功能。同样重要的是评估应用程序对特定负载的响应能力。在下一节中,我们将学习如何在我们的电子商务应用程序上执行性能测试。我们可以利用自动化的功能测试用例来执行 BVT 或回归测试。

注意

请参阅文档以了解更多关于 Selenium 测试的信息:www.selenium.dev/documentation/en/。

压力测试

用户期望应用程序能够快速响应用户的操作。任何响应缓慢都会导致用户沮丧,最终我们可能会失去他们。即使应用程序在正常负载下运行良好,我们也应该知道我们的应用程序在需求突然增加时的表现,并为此做好准备。

压力测试的主要目标不是寻找错误,而是消除应用程序的性能瓶颈。进行压力测试是为了向利益相关者提供有关其应用程序速度、可扩展性和稳定性的信息。在下一节中,我们将学习如何使用 JMeter 进行压力测试。

使用 JMeter 进行压力测试

JMeter 是由 Apache 软件基金会构建的开源测试工具。它是用于执行压力测试的最受欢迎的工具之一。JMeter 可以通过创建虚拟并发用户来模拟对应用程序的重负载。

让我们继续创建我们的电子商务应用程序的 JMeter 压力测试。

要了解如何使用 JMeter 进行压力测试,我们将创建一个包含两个主页和产品搜索页面的测试。尝试以下步骤来创建压力测试:

  1. 从下载位置启动 Apache JMeter。我们将看到如下窗口:

![Figure 15.7 – Apache JMeter]

![img/Figure_15.7_B18507.jpg]

Figure 15.7 – Apache JMeter

  1. 通过在左侧面板的测试计划上右键单击并选择添加 | 线程(用户) | 线程组,添加一个线程组。线程组定义了将执行测试用例的用户池。有了它,我们可以配置模拟的用户数量、启动所有用户的时长以及执行测试的次数。

  2. 让我们命名线程组为Load and Query Products并将用户数量设置为30。设置5秒,如下截图所示:

![Figure 15.8 – Adding a thread group in Apache JMeter

![img/Image87474.jpg]

图 15.8 – 在 Apache JMeter 中添加线程组

这将在5秒内模拟30个用户负载。使用线程组,我们还可以控制测试应该运行多少次。

  1. 要添加测试请求,右键单击线程组并选择添加 | 采样器 | HTTP 请求。

让我们设置https、localhost和44365(本地运行的电子商务门户的端口号)。将此测试命名为Home Page,如下截图所示:

![Figure 15.9 – Adding the Home Page HTTP request in JMeter

![img/Image87486.jpg]

图 15.9 – 在 JMeter 中添加主页面的 HTTP 请求

让我们再添加一个 HTTP 请求采样器来获取特定产品的详细信息。对于此请求,将productId查询参数设置为Cloth.3,将productName设置为Orange%20Shirt,如下截图所示:

![Figure 15.10 – Adding the Product Details page HTTP request in JMeter

![img/Figure_15.10_B18507.jpg]

图 15.10 – 在 JMeter 中添加产品详情页面的 HTTP 请求

  1. 通过点击ECommerce保存此测试计划。

  2. 要查看结果,我们应该为此测试添加一个监听器。右键单击测试组并选择添加 | 监听器 | 以表格形式查看结果。

  3. 一旦添加了监听器,就可以通过选择运行 | 开始来运行测试。

  4. 测试运行完成后,你将看到如下截图所示的结果。这将给我们每个请求的响应时间:

![Figure 15.11 – Test results table in JMeter

![img/Figure_15.11_B18507.jpg]

图 15.11 – JMeter 中的测试结果表格

JMeter 提供了多种监听器来查看结果,例如摘要报告和图形结果,它们将以另一种方式展示测试结果。我们可以轻松地使用 JMeter 配置不同类型的采样器,以及配置使用不同 HTTP 方法和动态测试的请求,其中请求依赖于另一个 API 的响应。一旦测试计划在 JMeter 中,我们可以利用 JMeter 命令行工具从多个数据中心运行它,以模拟地理分布的负载并汇总结果。

JMeter 提供的灵活性,以及其广泛的文档,使其成为最常用的性能测试工具。JMeter 还可以用于执行功能测试。

我们可以使用 Azure 负载测试服务来生成高负载,使用我们在本节中创建的 JMeter 测试。Azure 负载测试抽象化了执行 JMeter 脚本和负载测试应用程序所需的基础设施。Azure 负载测试收集基于 Azure 的应用程序的确切资源数据,以帮助您识别 Azure 应用程序组件中的性能瓶颈。

注意

在撰写本书时,Azure 负载测试处于预览阶段。有关负载测试的更多详细信息,请参阅 Azure 文档中的docs.microsoft.com/en-us/azure/load-testing/overview-what-is-azure-load-testing。建议使用预期负载的一倍半到两倍进行负载测试。在运行性能测试后,建议使用Application Insights来分析请求的服务器响应时间,API 在负载条件下的响应依赖性,以及更重要的是,测试进行过程中发生的任何故障。

小贴士

建议使用 Azure DevOps 管道运行自动化测试。使用文档了解如何将测试与 Azure DevOps 管道集成:

Selenium:docs.microsoft.com/en-us/azure/devops/pipelines/test/continuous-test-selenium?view=azure-devops

JMeter 测试:github.com/Azure-Samples/jmeter-aci-terraform

摘要

在本章中,我们探讨了软件开发的一个重要方面:测试。我们学习了不同类型的测试以及我们在 SDLC 中应该使用它们的阶段。

我们学习了单元测试的概念以及如何通过使用Moq框架模拟依赖项来关注特定的调用进行测试。我们还介绍了使用 Selenium 创建自动化功能测试,以在将电子商务应用程序发布到生产之前测试其功能。

最后,我们学习了 JMeter,这是进行负载测试最常用的工具。下一章将专注于在 Azure 中部署应用程序。

问题

  1. 正误判断?我们只有在应用程序开发完成后才开始考虑测试。

a. 正确

b. 错误

答案:b

  1. 以下哪一项是软件测试的一种类型?

a. 安全测试

b. 功能测试

c. 可访问性测试

d. 所有上述选项

答案:d

  1. 正误判断?单元测试的更高代码覆盖率百分比有助于缩短上市时间。

a. 正确

b. 错误

答案:a

第十六章:第十六章:在 Azure 中部署应用程序

部署是一系列我们执行的活动,以使软件应用程序可供使用。一般方法是从代码开始,然后构建、测试并将其部署到目标系统。根据应用程序类型和业务需求,你采取的代码部署方法可能会有所不同。它可能像将目标系统关闭,用新版本替换现有代码,然后重新启动系统那样简单;或者,它可能涉及其他更复杂的方法,如蓝绿部署,其中你将代码部署到一个与生产环境相同的预发布环境,运行测试,然后将流量重定向到预发布环境以使其达到生产状态。

现代软件开发采用敏捷和 DevOps 来缩短开发周期,并频繁且可靠地交付新功能、更新和错误,以向客户提供更多价值。为此,你需要一套工具来规划、协作、开发、测试、部署和监控。

在本章中,我们将学习 Azure DevOps 是什么,以及它提供的用于快速可靠交付的工具。

本章涵盖了以下主题:

  • 介绍 Azure DevOps

  • 理解 CI 管道

  • 理解 CD 管道

  • 部署 ASP.NET 6 应用程序

技术要求

对于本章,你需要具备 Azure、Visual Studio 2022、Git 的基本知识,以及一个具有贡献者角色的活跃 Azure 订阅。如果你没有,你可以在azure.microsoft.com/en-in/free注册一个免费账户。

本章的代码可以在以下位置找到:https://github.com/PacktPublishing/Enterprise-Application-Development-with-C-10-and-.NET-6-Second-Edition/tree/main/Chapter16。

介绍 Azure DevOps

要将产品理念付诸实践,无论团队规模大小,你都需要一种高效的方式来规划你的工作,在团队内部进行协作,并构建、测试和部署。Azure DevOps 可以帮助你解决这些挑战,并提供各种服务和工具以助你成功。Azure DevOps 服务可以通过网页或从流行的开发 IDE,如 Visual Studio、Visual Studio Code 和 Eclipse 访问。Azure DevOps 服务既可在云端使用,也可在本地使用 Azure DevOps Server。

Azure DevOps 提供以下服务:

  • 看板:提供一套工具,使用 Scrum 和 Kanban 方法来规划和工作、缺陷和问题的跟踪

  • 仓库:提供源代码管理,使用 Git 或团队基础版本控制(TFVC)来管理你的代码

  • 管道:提供一系列服务以支持持续集成(CI)和持续交付(CD)

  • 测试计划:提供一套测试管理工具,以推动应用程序的质量,并实现端到端的可追溯性

  • 工件:允许你从公共和私有源共享包,以及与 CI 和 CD 管道集成

除了这些服务之外,Azure DevOps 还帮助您管理团队的知识库,管理仪表板,使用小部件共享进度和趋势,并配置通知。它还允许您添加或开发自定义扩展,并与流行的第三方服务(如 Campfire、Slack 和 Trello)集成。

Azure DevOps 服务提供免费和付费订阅。要注册免费账户,请按照docs.microsoft.com/en-us/azure/devops/user-guide/sign-up-invite-teammates?view=azure-devops中概述的步骤操作。

以下是从一个示例项目中截取的主屏幕截图:

https://github.com/OpenDocCN/freelearn-csharp-zh/raw/master/docs/entp-appdev-csp10-dn6/img/Figure_16.1_B18507.jpg

图 16.1 – Azure DevOps 主页

让我们详细了解 Azure DevOps 及其每个服务。

看板

看板帮助您为项目定义一个流程并跟踪工作。当您在 Azure DevOps 中创建一个新的项目时,您可以选择一个流程模板,如敏捷、基本、Scrum 或能力成熟度模型集成(CMMI)流程。流程模板决定了您可以在项目中使用的工项类型和工作流程。工项帮助您跟踪工作,而工作流程帮助您跟踪工项的进度。以下图显示了工项的层次结构以及 Scrum 流程模板的工作流程:

https://github.com/OpenDocCN/freelearn-csharp-zh/raw/master/docs/entp-appdev-csp10-dn6/img/Figure_16.2_B18507.jpg

图 16.2 – 工作项层次结构及 Scrum 流程的工作流程

要进一步自定义或定义您的工作流程和工项类型,您可以选择基于之前提到的流程模板创建自己的流程模板。

让我们更深入地了解工作项和工作流程。

工作项

工作项帮助您跟踪项目中的功能、需求和错误。您可以在层次结构中对需求进行分组。通常,我们从称为史诗的高级需求开始,它可以进一步分解为功能和产品待办事项。产品待办事项是优先级较高、分配给团队成员并在冲刺中交付的可交付成果。任务是为待办事项和错误创建的,以跟踪对产品待办事项的缺陷。

协作功能允许您通过在工作项上讨论或提问来在团队内部进行沟通。您可以提及团队成员或链接另一个工作项,并随时查看所有操作或讨论的历史记录。您还可以选择关注工作项,以便在它更新时收到警报。

工作流程

工作流可以帮助您审查项目的进度和健康状况。例如,产品待办事项项以新状态创建。一旦它被产品负责人审查和批准,它就被移动到已批准,然后它被优先排序并分配给冲刺中的团队成员,并移动到已承诺,当它完成时,它被移动到完成。工作流可以帮助您跟踪项目的健康状况。

您可以使用 Kanban 板查看所有工作项的状态,并使用拖放功能轻松地将工作项移动到不同的状态。以下截图展示了由不同状态的工作项组成的 Kanban 板:

https://github.com/OpenDocCN/freelearn-csharp-zh/raw/master/docs/entp-appdev-csp10-dn6/img/Figure_16.3_B18507.jpg

图 16.3 – Kanban 看板

注意

如果您创建自己的流程模板,您可以自定义工作项或创建新的工作项,并自定义或定义工作流以满足您的业务需求。

要了解有关流程模板及其差异的更多信息,您可以参考docs.microsoft.com/en-us/azure/devops/boards/get-started/what-is-azure-boards?view=azure-devops&tabs=scrum-process#work-item-types。

接下来,让我们更深入地了解代码库。

代码库

代码库提供版本控制工具,您可以使用这些工具来管理您的代码。版本控制系统允许您跟踪团队对代码所做的更改。它为每个更改创建快照,您可以在任何时间审查它,并在需要时回滚到它。Azure DevOps 提供Git和TFVC作为您的版本控制系统。

Git 是目前最广泛使用的版本控制系统,并且越来越成为版本控制系统的标准。Git 是一个分布式版本控制系统,其中包含版本控制系统的本地副本,您可以在本地查看历史记录或提交更改,即使您离线,一旦连接到网络,它将同步到服务器。然而,TFVC 是一个集中式版本控制系统,每个文件在开发机器上只有一个版本,历史记录保存在服务器上。有关 Git 的更多信息,您可以参考docs.microsoft.com/en-in/azure/devops/repos/git/?view=azure-devops,有关 TFVC,您可以参考docs.microsoft.com/en-in/azure/devops/repos/tfvc/?view=azure-devops。

以下为代码库的关键服务:

  • main或master,您可以从它创建另一个分支。这样,您可以隔离您的更改以进行功能开发或错误修复。您可以创建任意数量的分支,与团队成员共享,提交您的更改,并安全地将它们合并回master。

  • 分支策略帮助您在开发过程中保护分支。当您在分支上启用分支策略时,任何更改都必须通过提交请求进行,这样您就可以进行审查、提供反馈和批准更改。作为分支策略,您可以配置所需的最小批准者数量,检查链接的工作项和评论解决情况,并强制构建成功以完成提交请求。

以下屏幕截图展示了在分支上定义的策略:

https://github.com/OpenDocCN/freelearn-csharp-zh/raw/master/docs/entp-appdev-csp10-dn6/img/Image87446.jpg

图 16.4 – 分支策略

在这里,创建了一个策略来验证在代码合并到分支之前构建。

  • 提交请求允许您审查代码、添加评论,并确保在代码合并到分支之前得到解决。根据配置的分支策略,您可以添加强制审查员来审查和批准更改。您可以将工作项关联到提交请求以启用更改的可追溯性。以下屏幕截图展示了示例提交请求:

https://github.com/OpenDocCN/freelearn-csharp-zh/raw/master/docs/entp-appdev-csp10-dn6/img/Figure_16.5_B18507.jpg

图 16.5 – 提交请求

提交请求有一个标题和描述,用户可以审查文件并比较它们与之前的版本,检查构建状态和链接的工作项,并进行批准。

接下来,让我们了解管道。

管道

管道允许您配置、构建、测试并将代码部署到任何目标系统。使用管道,您可以为代码的持续集成和持续部署启用一致性和质量交付。您可以使用针对使用流行语言(如.NET、Java、JavaScript、Node.js、PHP 和 C++)构建的许多应用程序类型的管道,并将它们部署到云或本地服务器。您可以使用 YAML 文件或基于 UI 的经典编辑器定义管道。

CI 自动化构建和测试您的项目以确保质量和一致性。CI 可以配置为按计划运行或当新代码合并到您的分支时运行,或者两者都运行。CI 生成由 CD 管道用于部署到目标系统的工件。

CD 使您能够自动将代码部署到目标系统并运行测试。CD 可以配置为按计划运行。

接下来,让我们更深入地了解测试计划。

测试计划

Azure DevOps 提供了一套工具来提高您项目中的质量。它提供基于浏览器的测试管理解决方案,具有所有手动和探索性测试所需的功能。它提供了在测试套件或测试计划下组织测试用例的能力,您可以使用它们来跟踪功能或发布的质量。以下是对这些功能的解释:

  • 测试用例用于验证应用程序的各个部分。它们包含测试步骤,您可以使用它们来断言需求。您可以通过将其导入测试套件或测试计划来重用测试用例。

  • 测试套件是一组执行以验证功能或组件的测试用例。您可以创建静态测试套件、基于需求的套件和基于查询的套件。

  • 测试计划是一组测试套件或测试用例,用于跟踪每个发布迭代的每个迭代的质量。

接下来,让我们更深入地了解工件。

工件

工件使得在团队之间共享代码变得容易。您可以从公共和私有源轻松创建和共享 Maven、npm 或 NuGet 包源,它们在 CI 和 CD 流水线中易于使用。工件基于标准打包格式,可以轻松集成到开发 IDE 中,如 Visual Studio,作为包源。

Azure DevOps 使团队内部能够协调和协作,并帮助您以高质量一致地交付项目。使用 CI 和 CD,您可以自动化代码的构建和部署。

在下一节中,让我们了解 CI 流水线。

理解 CI 流水线

CI 是一种实践,您在其中自动化代码的构建和测试。在 Azure DevOps 中,您可以创建流水线并将它们配置为在代码合并到您的目标(master/main)分支时自动触发,按计划运行,或两者兼而有之。您可以选择使用 YAML 文件或基于 UI 的经典编辑器创建流水线。

下图说明了从开发者的机器到云的代码典型流程:

https://github.com/OpenDocCN/freelearn-csharp-zh/raw/master/docs/entp-appdev-csp10-dn6/img/Figure_16.6_B18507.jpg

https://github.com/OpenDocCN/freelearn-csharp-zh/raw/master/docs/entp-appdev-csp10-dn6/img/Figure_16.6_B18507.jpg

图 16.6 – 代码的典型流程

从前面的截图,我们可以看到以下内容:

  1. 开发者使用 Visual Studio、Visual Studio Code 或 Visual Studio for Mac 等开发工具来编写代码。

  2. 代码更改被移动到仓库中。

  3. CI 流水线被触发,验证构建,运行测试,并发布工件。CD 流水线被触发,并将代码部署到目标系统。

  4. 开发者使用 Application Insights 来持续监控和改进应用程序。

    注意

    YAML(代表YAML Ain’t Markup Language)是定义流水线的首选方式。它提供了与经典编辑器相同的功能。您可以将这些文件检查到仓库中,并像管理任何其他源文件一样管理它们。有关更多详细信息,您可以参考docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=azure-devops&tabs=schema%2Cparameter-schema。

让我们了解流水线的核心组件和流程。

理解流水线的流程和组件

流水线是一组定义,用于执行构建和测试代码的操作。流水线定义包含触发器、变量、阶段、作业、步骤和任务。当我们运行流水线时,它会执行流水线定义中定义的任务。以下各节中,我们将了解这些组件的每个部分。

触发器

流水线的 trigger 部分。

在以下代码片段中,流水线被配置为在代码推送到 master 分支或 releases 文件夹下的任何分支时触发。可选地,我们还可以在流水线中指定路径过滤器,以便仅在代码更改满足路径条件时触发:

trigger:
  branches:
    include:
    - master
    - releases/*
  paths:
    include:
    - web
    exclude:
    - docs/README.md

您还可以配置流水线根据计划自动运行。在以下代码片段中,流水线被配置为每天上午 9:30 运行。计划使用 cron 表达式指定,并且您可以指定多个计划。如果将 always 设置为 true,即使代码没有更改,也会触发构建:

schedules:
- cron: "30 9 * * *"
  displayName: Daily build
  branches:
    include:
    - master
  always: false

变量

变量可以通过赋予值并在流水线中的多个位置重用来定义。您可以在根目录、阶段或作业中定义变量。在流水线中可以使用三种不同类型的变量 – 用户定义的变量、系统变量和环境变量:

variables:
 buildConfiguration: 'Release'
. . . .
. . . .
- task: DotNetCoreCLI@2
  displayName: Publish
  inputs:
   command: 'publish'
   publishWebProjects: false
   projects: '**/*HelloWorld.csproj'
   arguments: '--configuration $(BuildConfiguration) --output $(build.artifactstagingdirectory)/web'

在前面的代码片段中,buildConfiguration 变量被定义为 Release 值,并在任务的 arguments 部分中使用。build.artifactstagingdirectory 系统变量包含工件目录的位置。

阶段

阶段是一组默认按顺序运行的作业。您也可以指定前一个阶段执行状态的条件,或添加审批检查以控制阶段何时运行。

以下是一个具有多个阶段的示例流水线定义:

stages:
- stage: Build
  jobs:
  - job: build
    steps:
    - script: echo building code
- stage: Test
  jobs:
  - job: windows
    steps:
    - script: echo running tests on windows
  - job: linux
    steps:
    - script: echo running tests on Linux
- stage: Deploy
  dependsOn: Test
  jobs:
  - job: deploy
    steps:
    - script: echo deploying code

在前面的示例中,配置了三个阶段,它们按顺序依次运行。Test 阶段包含两个可以并行运行的作业,而 Deploy 阶段依赖于 Test 阶段。

以下是对前面示例的流水线执行摘要的截图,您可以通过点击每个阶段来查看日志:

https://github.com/OpenDocCN/freelearn-csharp-zh/raw/master/docs/entp-appdev-csp10-dn6/img/Figure_16.7_B18507.jpg

图 16.7 – 流水线运行摘要

作业

testNull 变量:

variables:
- name: testNull
  value: ''
jobs:
  - job: BuildJob
    steps:
    - script: echo Building!
    condition: eq('${{ variables.testNull }}', '')

在前面的代码中,作业被配置为仅在 testNull 为空时运行。

步骤和任务

步骤是您流水线中的任务组。这些可能是构建您的代码、运行测试或发布工件。每个步骤都在代理上执行,并可以访问流水线工作区。

DotNetCoreCLI@2 任务构建 csproj:

- task: DotNetCoreCLI@2
  displayName: build
  inputs:
   command: 'build'
   projects: '**/*.csproj'
   arguments: '--configuration $(BuildConfiguration)'

要了解更多关于流水线的知识,您可以参考 docs.microsoft.com/en-in/azure/devops/pipelines/create-first-pipeline?view=azure-devops&tabs=java%2Ctfs-2018-2%2Cbrowser。

在下一节中,让我们更深入地了解 CD 流水线。

理解 CD 流水线

CD 是一个自动化将代码部署到目标环境的流程。CD 管道使用 CI 管道产生的工件并部署到一个或多个环境。像 CI 管道一样,我们可以使用 YAML 文件或经典编辑器来定义 CD 管道。您可以为前一个阶段的执行状态指定条件或添加批准检查以部署,这在生产部署中是一个非常常见的场景。

您还可以配置运行自动化的 UI 测试以在部署后进行合理性检查。根据合理性检查的结果,您可以配置它自动将代码提升到更高环境。

在任何时间点,如果某个阶段的部署失败,我们可以从之前的版本重新部署代码。根据项目设置下配置的保留策略,Azure DevOps 会保留构建工件,以便可以轻松地在任何时间部署任何版本的代码。如果您在部署后发现应用程序有任何问题,您可以轻松地找到最后一个已知的好版本,并部署代码以最小化业务影响。

让我们在下一节中更深入地了解这个内容。

持续部署与 CD 对比

持续部署是在将新代码合并到您的存储库时自动部署到目标系统,而 CD 使应用程序在任何时间都可以部署到目标系统。Azure DevOps 提供多阶段管道;您可以通过配置具有阶段的管道来实现这一点。

持续部署通常配置在较低的环境,如开发或测试,而对于较高环境,如预发布或生产,您应该考虑 CD,以便您可以在较低环境中验证更改并批准将代码部署到较高环境。

以下屏幕截图展示了多阶段管道,其中自动构建和发布到开发环境,并在测试阶段等待批准。在这种情况下,将代码发布到测试需要批准:

https://github.com/OpenDocCN/freelearn-csharp-zh/raw/master/docs/entp-appdev-csp10-dn6/img/Figure_16.8_B18507.jpg

图 16.8 – 待批准的多阶段管道

要了解如何配置 Azure 管道中的批准和检查的更多信息,您可以参考docs.microsoft.com/en-in/azure/devops/pipelines/process/approvals?view=azure-devops&tabs=check-pass。

要查看管道运行的详细信息,您可以点击任何阶段来查看该运行的日志。日志帮助我们排查部署失败的问题。以下屏幕截图展示了管道运行的日志:

https://github.com/OpenDocCN/freelearn-csharp-zh/raw/master/docs/entp-appdev-csp10-dn6/img/Figure_16.9_B18507.jpg

图 16.9 – 管道执行细节

在前面的屏幕截图中,您会注意到您可以查看管道中配置的阶段、作业和任务,并且您可以点击任务来查看日志。

在下一节中,我们将学习如何创建一个构建和部署应用程序的管道。

部署 ASP.NET 6 应用程序

到目前为止,在本章中,我们已经探讨了 Azure DevOps,了解了它提供的工具和服务,然后学习了 CI 和 CD 管道。在本节中,我们将学习如何创建 Azure DevOps 项目,克隆存储库,将代码推送到存储库,并创建 CI 和 CD 管道以将代码部署到 Azure App Service。

注意

在部署示例应用程序之前,请务必检查 技术要求 部分,以确保您已设置好所有内容。

您可以按照以下步骤部署 ASP.NET 6 应用程序到 Azure:

  1. 登录到您的 Azure DevOps 账户。如果您还没有 Azure DevOps 账户,可以按照docs.microsoft.com/en-us/azure/devops/user-guide/sign-up-invite-teammates?view=azure-devops中给出的步骤创建一个;您也可以按照以下步骤进行操作:

  2. 在 Azure DevOps 的主页上,为您的项目提供一个名称,例如 HelloWorld,然后对于 版本控制,选择 Git,对于 工作项流程,您可以选择 敏捷:

https://github.com/OpenDocCN/freelearn-csharp-zh/raw/master/docs/entp-appdev-csp10-dn6/img/Figure_16.10_B18507.jpg

https://github.com/OpenDocCN/freelearn-csharp-zh/raw/master/docs/entp-appdev-csp10-dn6/img/Figure_16.10_B18507.jpg

图 16.10 – 新的 Azure DevOps 项目

  1. 现在,让我们创建一个服务连接,我们将在管道中使用它来连接和部署代码到 Azure App Service。

从左侧菜单导航到 项目设置 | 服务连接 | 创建服务连接 | Azure 资源管理器 | 服务主体(自动):

https://github.com/OpenDocCN/freelearn-csharp-zh/raw/master/docs/entp-appdev-csp10-dn6/img/Figure_16.11_B18507.jpg

https://github.com/OpenDocCN/freelearn-csharp-zh/raw/master/docs/entp-appdev-csp10-dn6/img/Figure_16.11_B18507.jpg

图 16.11 – 新的服务主体

服务主体使管道能够连接到您的 Azure 订阅以管理资源或将您的代码部署到 Azure 服务。

  1. 选择一个订阅并为创建服务连接的连接提供一个名称。Azure DevOps 使用此服务连接来连接 Azure 资源并部署代码:

https://github.com/OpenDocCN/freelearn-csharp-zh/raw/master/docs/entp-appdev-csp10-dn6/img/Figure_16.12_B18507.jpg

https://github.com/OpenDocCN/freelearn-csharp-zh/raw/master/docs/entp-appdev-csp10-dn6/img/Figure_16.12_B18507.jpg

图 16.12 – 新的服务主体

  1. 一旦创建项目,您应该会看到一个类似于以下页面的页面。从左侧菜单中,在 仓库 下选择 分支:

https://github.com/OpenDocCN/freelearn-csharp-zh/raw/master/docs/entp-appdev-csp10-dn6/img/Figure_16.13_B18507.jpg

https://github.com/OpenDocCN/freelearn-csharp-zh/raw/master/docs/entp-appdev-csp10-dn6/img/Figure_16.13_B18507.jpg

图 16.13 – Azure DevOps 主页 | 仓库屏幕

  1. 复制以下链接,我们将使用它来克隆存储库到本地计算机:

https://github.com/OpenDocCN/freelearn-csharp-zh/raw/master/docs/entp-appdev-csp10-dn6/img/Figure_16.14_B18507.jpg

https://github.com/OpenDocCN/freelearn-csharp-zh/raw/master/docs/entp-appdev-csp10-dn6/img/Figure_16.14_B18507.jpg

图 16.14 – 克隆仓库

  1. 要将存储库克隆到您的系统,请打开命令提示符并导航到您想要克隆代码的文件夹,然后运行以下命令。

将 <organization> 替换为您的 Azure DevOps 组织:

git clone https://<organization>@dev.azure.com/<organization>/HelloWorld/_git/HelloWorld
  1. 由于我们的存储库是新的且为空,我们需要向其中添加代码。以下 dotnet CLI 命令可以帮助我们创建一个 ASP.NET 6 应用程序和一个 xUnit 项目,创建一个解决方案文件,并将一个 Web 和测试项目添加到其中。按顺序运行每个命令以继续:

    dotnet new mvc --auth Individual -o HelloWorld
    dotnet new xunit -o HelloWorld.Tests
    dotnet new sln
    dotnet sln add HelloWorld/HelloWorld.csproj
    dotnet sln add HelloWorld.Tests/HelloWorld.Tests.csproj
    
  2. 运行以下命令来构建代码并运行测试以验证是否一切正常:

    dotnet build
    dotnet test
    

现在我们已经测试了代码,接下来让我们看看如何为使用代码创建 CI/CD 管道。

创建 CI/CD 管道

在运行测试后,我们需要查看 CI/CD 管道是如何创建的。执行以下步骤:

  1. 接下来,我们需要创建一个 CI/CD 的管道。你可以使用在 github.com/PacktPublishing/Enterprise-Application-Development-with-C-10-and-.NET-6-Second-Edition/blob/master/Chapter16/Pipelines/HelloWorld/azure-ci-pipeline.yml 可用的代码,并将其保存到存储库的根目录中。让我们称它为 azure-ci-pipeline.yml。

此管道被配置为在新代码合并到 main 分支时触发。

  1. 它被配置为有三个阶段——构建、开发和测试——其中构建阶段被配置为构建代码、运行单元测试和发布工件。开发和测试阶段被配置为将代码部署到 Azure App Service。

  2. 依赖关系在开发和测试阶段进行配置,其中开发阶段依赖于构建,测试依赖于开发阶段。

让我们检查这个 YAML 文件的一些重要部分。

以下片段包含一个定义变量的部分:

trigger:
- main
variables:
  BuildConfiguration: 'Release'
  buildPlatform: 'Any CPU'
  solution: '**/*.sln'
  azureSubscription: 'HelloWorld-Con' # replace this
  # with your service connection name to connect Azure 
  #subscription
  devAppServiceName: 'webSitejtrb7psidvozs' # replace 
  #this with your app service name
  testAppServiceName: 'webSitejtrb8psidvozs' # replace 
  #this with your app service name

你会注意到在 YAML 文件中声明了三个变量。在保存文件之前,请提供适当的值:

  • azureSubscription:提供你的服务连接名称。

  • devAppServiceName:提供开发部署的应用服务名称。

  • testAppServiceName:提供测试部署的应用服务名称。

要构建代码,我们使用 DotNetCoreCLI@2 任务并配置 command、projects 和可选的 arguments:

- task: DotNetCoreCLI@2
  displayName: Build
  inputs:
    command: 'build'
    projects: '**/*.csproj'

command 被配置为 build,路径设置为 csproj 以构建 projects 中的代码。此任务运行 .NET CLI 命令,因此我们也可以使用其他 .NET CLI 命令配置此任务,例如 run、test、publish、restore 等。

  1. 要发布代码,使用 PublishBuildArtifacts@1 任务。它配置了 PathtoPublish、ArtifactName 和 publishLocation:

    - task: PublishBuildArtifacts@1
      inputs:
        PathtoPublish: 
          '$(Build.ArtifactStagingDirectory)/web'
        ArtifactName: 'drop'
        publishLocation: 'Container'
    

PathtoPublish 被配置为工件目录的位置,其中包含可用的构建工件,ArtifactName 为 drop,publishLocation 为 Container 以将工件发布到 Azure Pipelines。或者,我们也可以将 publishLocation 配置为 FileShare。

以下代码片段执行所需的操作以部署代码:

- download: current
  artifact: drop
- task: AzureWebApp@1
  displayName: 'Azure App Service Deploy: website'
  inputs:
    azureSubscription: '$(azureSubscription)'
    appType: 'webApp'
    appName: '$(devAppServiceName)'
    package: '$(Pipeline.Workspace)/drop/*.zip'
    deploymentMethod: 'auto'

在部署作业中,第一步是下载工件,并且工件的名称应该与在 PublishBuildArtifacts@1 任务中配置的名称相同,在这种情况下,是 drop。

AzureWebApp@1 任务用于将工件部署到 Azure App Service。所需的参数包括 azureSubscription、appType、appName、package 和 deploymentMethod(作为 auto)。

现在工件已经准备好了,我们可以看到代码是如何被提交的,以及代码更改是如何被推送到远程仓库的。

推送代码

现在代码和流水线都已经准备好了,下一步是将这些更改提交并推送到 Azure DevOps 仓库:

  1. 在命令提示符中,运行以下命令以在本地提交更改并将它们推送到 Azure DevOps:

    git add .
    git commit -m "Initial Commit"
    git push
    
  2. 在 Azure DevOps 中,导航到 流水线 并点击 创建流水线 来创建一个新的流水线:

https://github.com/OpenDocCN/freelearn-csharp-zh/raw/master/docs/entp-appdev-csp10-dn6/img/Figure_16.15_B18507.jpg

图 16.15 – 新建流水线

  1. 要配置流水线,我们需要执行四个步骤。选择你的仓库所在的云服务,选择仓库,配置流水线,然后保存。对于此实现,选择 Azure Repos Git 以继续,然后选择你的仓库:

https://github.com/OpenDocCN/freelearn-csharp-zh/raw/master/docs/entp-appdev-csp10-dn6/img/Figure_16.16_B18507.jpg

图 16.16 – 源代码选择

  1. 在 配置 选项卡中,选择 现有 Azure 流水线 YAML 文件 以继续:

https://github.com/OpenDocCN/freelearn-csharp-zh/raw/master/docs/entp-appdev-csp10-dn6/img/Figure_16.17_B18507.jpg

图 16.17 – 配置流水线

  1. 选择我们在仓库中保存的流水线文件,然后点击 继续,然后点击 运行 来触发流水线:

https://github.com/OpenDocCN/freelearn-csharp-zh/raw/master/docs/entp-appdev-csp10-dn6/img/Figure_16.18_B18507.jpg

图 16.18 – YAML 文件选择

  1. 这将打开一个页面,我们可以看到流水线的状态。以下截图是从流水线运行中获取的。你会注意到已经创建了三个阶段:

https://github.com/OpenDocCN/freelearn-csharp-zh/raw/master/docs/entp-appdev-csp10-dn6/img/Figure_16.19_B18507.jpg

图 16.19 – 流水线运行摘要

在构建阶段,你会注意到有两个正在进行的作业。

开发阶段和测试阶段正在等待构建完成。

可选地,你可以在 Azure App Service 上启用部署槽位,并配置流水线以将代码部署到非生产部署槽位,例如,预生产。一旦你检查了已部署代码的合理性,你可以将 生产 槽位与 预生产 槽位交换。交换是瞬时的,并且没有任何停机时间,你可以将最新的更改提供给用户。如果你发现任何问题,你可以交换回先前的槽位以回到最后一个已知的好版本。有关更多信息,你可以参考 docs.microsoft.com/en-us/azure/app-service/deploy-staging-slots。

  1. 流水线执行完成后,从左侧菜单导航到 流水线 下的 环境。你会注意到已经创建了开发和测试环境:

https://github.com/OpenDocCN/freelearn-csharp-zh/raw/master/docs/entp-appdev-csp10-dn6/img/Figure_16.20_B18507.jpg

图 16.20 – 环境

  1. 点击 测试 阶段,在更多操作选择中,选择 审批和检查 以继续:

https://github.com/OpenDocCN/freelearn-csharp-zh/raw/master/docs/entp-appdev-csp10-dn6/img/Figure_16.21_B18507.jpg

图 16.21 – 批准和检查

  1. 您将找到许多可供选择的功能,例如批准、分支控制、工作日等:

https://github.com/OpenDocCN/freelearn-csharp-zh/raw/master/docs/entp-appdev-csp10-dn6/img/Figure_16.22_B18507.jpg

图 16.22 – 添加检查

  1. 选择批准以继续,它将打开一个对话框,我们可以选择用户/组作为审批者。提供必要的详细信息并点击创建:

https://github.com/OpenDocCN/freelearn-csharp-zh/raw/master/docs/entp-appdev-csp10-dn6/img/Figure_16.23_B18507.jpg

图 16.23 – 添加批准

  1. 重新运行管道以测试更改。您将注意到管道在测试阶段等待执行:

https://github.com/OpenDocCN/freelearn-csharp-zh/raw/master/docs/entp-appdev-csp10-dn6/img/Figure_16.24_B18507.jpg

图 16.24 – 具有挂起批准的多阶段管道

  1. 点击审查,这将打开一个对话框以批准或拒绝。点击批准以完成部署:

https://github.com/OpenDocCN/freelearn-csharp-zh/raw/master/docs/entp-appdev-csp10-dn6/img/Figure_16.25_B18507.jpg

图 16.25 – 批准或拒绝

总结来说,在本节中,我们从在 Azure DevOps 中创建新项目开始,然后克隆仓库到本地系统,使用.NET CLI 创建了一个简单的 ASP.NET Core 应用程序,创建了一个 YAML 管道来构建、测试和发布工件并将它们部署到 Azure App Service,并将代码提交并推送到仓库。接下来,我们通过在仓库中选择 YAML 文件创建了一个新的 CI/CD 管道,并触发了管道。在环境中,我们配置了批准检查并触发了管道以查看其工作情况。

摘要

在本章中,我们了解了 Azure DevOps 是什么,以及它提供的工具和服务。我们了解了服务如看板、代码库、管道、测试计划和工件如何帮助我们高效地执行项目。

接下来,我们探讨了 CI 和 CD 管道及其核心组件。我们还学习了它们如何帮助我们自动化代码的构建和部署。通过学习如何创建 ASP.NET 6 应用程序以及使用 CI 和 CD 管道构建和部署到 Azure App Service 的管道,我们结束了本章。

我希望这本书能帮助您提高.NET 技能,并激励您尝试构建更多其应用。您可以通过参考章节的笔记和进一步阅读部分来探索更多主题。

对于企业应用,我们还涵盖了典型电子商务应用的快乐路径场景,并且可以根据在第一章中定义的需求进一步扩展,即设计和架构企业应用。有示例扩展端到端流程的认证/授权,使用 API 网关进行服务间通信和认证,并实现通知服务,以便您了解更多。

我们祝愿您在 C#和.NET 项目中一切顺利。祝您学习愉快!

问题

  1. 持续部署与 CD 有何不同?

a. CD 与数据库协同工作,而持续部署支持 Web 应用程序。

b. 持续部署每次都发布到环境,而 CD 在任何一次都发布到环境。

c. 持续部署需要云服务,而 CD 与本地服务器协同工作。

d. 持续部署在任何一次都发布到环境,而 CD 每次都发布到环境。

答案:b

  1. 持续部署方法的特点是什么?(选择两个)

a. 专注于缩短周期时间

b. 少量复杂发布

c. 基于资源的流程管理

d. 自我管理和响应性团队

答案:a 和 d

  1. 哪个组件提供了对提交的应用代码更改质量的首次反馈?

a. 自动部署

b. 自动配置

c. 自动构建

d. 自动测试

答案:c

进一步阅读

想了解更多关于 Azure DevOps 的信息,您可以参考docs.microsoft.com/en-in/azure/devops/user-guide/services?view=azure-devops,以及关于管道,您可以参考docs.microsoft.com/en-in/azure/devops/pipelines/get-started/pipelines-get-started?view=azure-devops.

https://github.com/OpenDocCN/freelearn-csharp-zh/raw/master/docs/entp-appdev-csp10-dn6/img/Image87706.jpg

Packt.com

订阅我们的在线数字图书馆,全面访问超过 7,000 本书和视频,以及行业领先的工具,帮助您规划个人发展并推进您的职业生涯。如需更多信息,请访问我们的网站。

第十七章:为什么订阅?

  • 通过来自 4,000 多位行业专业人士的实用电子书和视频,节省更多时间学习,更多时间编码

  • 通过为您量身定制的技能计划提高您的学习效果

  • 每月免费获得一本电子书或视频

  • 完全可搜索,便于轻松访问关键信息

  • 复制粘贴、打印和收藏内容

你知道 Packt 提供每本书的电子书版本,包括 PDF 和 ePub 文件吗?您可以在 packt.com 升级到电子书版本,并且作为印刷书客户,您有权获得电子书副本的折扣。如需了解更多详情,请联系我们 customercare@packtpub.com。

在 www.packt.com,您还可以阅读一系列免费的技术文章,注册各种免费通讯,并享受 Packt 书籍和电子书的独家折扣和优惠。

您可能还会喜欢的其他书籍

如果您喜欢这本书,您可能还会对 Packt 的这些其他书籍感兴趣:

https://www.packtpub.com/product/modernizing-your-windows-applications-with-the-windows-app-sdk-and-winui/9781803235660

使用 Windows App SDK 和 WinUI 现代化您的 Windows 应用程序

Matteo Pagani, Marc Plogas

ISBN: 9781803235660

  • 理解 Windows App SDK 和 WinUI 的关键概念

  • 通过创建新应用程序或增强现有应用程序来集成新功能

  • 通过采用 Fluent Design 和新的交互模式,如触摸和手写笔,改进您的应用程序 UI

  • 使用通知更有效地与您的用户互动

  • 使用 Windows App SDK 将您的应用程序与 Windows 生态系统集成

  • 使用 WinML 通过人工智能提升您的任务

  • 使用 MSIX 在 LOB 和面向客户的场景中部署您的应用程序

https://packt.link/9781803235257

使用 C# 10 和 .NET 6 的软件架构 - 第三版

Gabriel Baptista, Francesco Abbruzzese

ISBN: 9781803235257

  • 使用经过验证的技术克服现实世界的架构挑战

  • 应用分层架构等架构方法

  • 利用容器等工具有效地管理微服务

  • 快速掌握 Azure 功能,以提供全球解决方案

  • 使用 C# 10 编程和维护 Azure Functions

  • 理解何时最好使用测试驱动开发 (TDD)

  • 在现代架构中使用 ASP.NET Core 实现微服务

  • 用人工智能丰富您的应用程序

  • 获取 DevOps 原则的最佳实践,以启用 CI/CD 环境

Packt 正在寻找像您这样的作者

如果您有兴趣成为 Packt 的作者,请访问 authors.packtpub.com 并今天申请。我们已与成千上万的开发者和技术专业人士合作,就像您一样,帮助他们将见解分享给全球科技社区。您可以提交一般申请,申请我们正在招募作者的特定热门话题,或者提交您自己的想法。

分享您的想法

现在您已经完成了《使用 C# 10 和 .NET 6 开发企业级应用程序》,我们非常想听听您的想法!如果您在亚马逊购买了这本书,请点击此处直接跳转到该书的亚马逊评论页面,分享您的反馈或在该购买网站上留下评论。

您的评论对我们和科技社区都非常重要,它将帮助我们确保我们提供的是高质量的内容。

您可能还会喜欢的其他书籍

您可能还会喜欢的其他书籍

C#企业级Web应用开发实践教程 本文还有配套的精品资源,点击获取 简介:本项目通过开发一个基于.NET框架和***技术的真实企业网站,展示了构建功能完备、高效且易于维护的Web应用程序的过程。项目采用三层架构设计,分离表现层、业务逻辑层和数据访问层,增强代码的可重用性、可扩展性和可维护性。开发者将学习C#后端逻辑编写、前端页面设计,并掌握数据缓存、安全性措施、错误处理和性能优化等关键技术,以提高Web应用... 阅读详情

相关推荐

C#与.NET6个人博客站项目源码详解及实战

NET 6平台作为微软近年来的重大更新,带来了显著的性能提升,特别是运行时性能的优化。这些优化不仅增强了应用程序的启动速度和运行效率,还降低了内存占用,使.NET应用更加轻量化,更适合现代云原生应用和服务。在.NET 6中,运行时性能的提升主要得益于JIT(即时编译)的改进、垃圾回收器的优化以及多线程和异步编程模型的改进。JIT编译器现在更智能地优化热点代码,减少了执行时间和内存消耗。而垃圾回收器(GC)则进行了多项改进,包括减少内存碎片和提高回收效率。

weixin_35756373的博客 1088

如何在 ASP.Net Core 中实现 健康检查

健康检查 常用于判断一个应用程序能否对 request 请求进行响应,ASP.Net Core 2.2 中引入了 健康检查 中间件用于报告应用程序的健康状态。 ASP.Net Core 中的 健康检查 落地做法是暴露一个可配置的 Http 端口,你可以使用 健康检查 去做一个最简单的活性检测,比如说:检查网络和系统的资源可用性,数据库资源是否可用,应用程序依赖的消息中间件或者 Azure cloud service 的可用性 等等,这篇文章我们就来讨论如何使用这个 健康检查中间件。 注册健康检查服务 要注册

一线码农的专栏 920

基于ArcObjects和C#.NET的地理信息系统应用开发完整指南

ArcObjects是ESRI公司为开发者提供的一套COM组件库,旨在通过高级编程接口,让开发者能够创建、编辑和扩展地理信息系统(GIS)应用程序。它是构建定制GIS应用的基础,可运行于多种编程环境中,包括C#.NET,因此被广泛用于企业级GIS应用开发。ArcGIS地图控件是集成于ArcObjects中的一个强大工具,用于在各种应用程序中实现地图展示功能。它提供了丰富的API接口,可允许开发者控制地图的显示、添加图层、实现交互等。

weixin_34162851的博客 1176

.NET6之MiniAPI(十三):健康检查

程序员开发程序,是“生”的过程,运维人员负责日常运维,是“养”的过程,在养的过程,运维人员希望在第一时间了解程序的状况,健康检查,是最基础的手段。var builder = WebAppl...

dotNET跨平台 1231

基于C#.NET的ArcObjects与GIS应用开发实战指南

ArcObjects 是由 Esri(Environmental Systems Research Institute, 环境系统研究学会)开发的一套用于构建定制地理信息系统(GIS)应用程序的组件库。它是一个强大的开发平台,允许开发者利用.NET和COM技术集成GIS功能到各种应用程序中。

weixin_30481539的博客 1033

NET应用架构设原则、模式与实践.pdf

NET应用架构设原则、模式与实践

Microsoft.NET 企业级应用架构设计(读书笔记)

前言 常用名词解释 简称 备注 ANSI 美国国家标准学会(American National Standards Institute) IEEE 电气和电子工程师学会(Institute of Electrical and Electronics E...

155

ArcGIS 10.2 保姆级安装与破解教程(含License Manager启动失败解决方案)

本文提供ArcGIS 10.2中文版的保姆级安装与破解教程,详细讲解从环境检查到License Manager配置的全流程,特别针对License Manager启动失败等常见问题提供专业解决方案,帮助用户顺利完成地理信息系统软件的安装与激活。

weixin_26757925的博客 1181

企业架构模式——分层

一、分层设计的基本概念 在分解复杂的软件系统时,软件设计者用的最多的技术之一就是分层。在计算机体系机构中,可以看到,到处都有分层的例子,最为典型的,就是存储器的层次结构,如图所示: 图1:计算机存储器的层次模型 可以看到,存储器的层次结构是按访问速度、存储容量等参数划分的,不同的层次有不同的职责。CPU内部的寄存器组是访问速度最快的存储设备,用于存储CPU运算过程中的指令和数据;主存中存储的的则是执行中程序(进程)需要的代码和数据。由于CPU访问主存的速度很慢,因此引入了高速缓存处理器(高速缓存)

zhangnian_it的专栏 1171

nsight-system教程

参考nsight-compute使用教程-优快云博客。

youzjuer的博客 1894

【SpringBoot香樟转转】debugDay01

在学黑马程序员的苍穹外卖项目,刚开始学,想用maven编译一下代码,结果报错,找不到符号。本着先理解原则,看着能找到这个变量呀。

m0_72696598的博客 1737

C#10 和 .NET6 企业级应用开发(一)

NET 6 是一个开源、免费的全栈框架,用于编写针对任何平台的应用程序。该框架为你提供了轻松编写应用程序的机会,包括云应用。作为软件开发者,我们肩负着构建复杂企业应用程序的责任。在这本书中,我们将学习使用 C# 10 和.NET 6 构建企业应用程序的各种高级架构和概念。这本书可以作为在.NET 6 中构建企业应用程序时的参考。它包含了对基本概念的逐步解释、实际示例和自我评估问题,你将深入了解并接触到构建专业企业应用程序所需的.NET 6 的每一个重要组件。

龙哥盟 1204

云服务器安装ros教程

要在 CentOS 7 系统上安装 RouterOS,您需要将 RouterOS 安装为虚拟机或直接安装到物理硬盘上。这里提供的是将 RouterOS 安装到物理硬盘上的步骤,这将完全替换现有的 CentOS 7 系统。请确保您已经备份了所有重要数据。

qq_37662563的博客 2145

C#10 和 .NET6 企业级应用开发(二)

DI 是一种技术,其中对象接收它所依赖的对象。DI 模式实现了作为单一职责原则、开闭原则、里氏替换原则、接口隔离原则和依赖倒置原则SOLID)设计原则一部分的 DI 原则,如第一章设计和架构企业应用程序中所述。使用 DI,代码将更易于维护、阅读、测试和扩展。DI 是帮助实现更易于维护代码的最知名方法之一。图 5.1 – DI 关系负责处理Order实体。.NET IoC 容器((客户端))。IoC 容器(也称为DI 容器)是一个用于实现自动 DI 的框架。在图 5.1中,这被称为注入器。

龙哥盟 1011

告别手动打点!用Cesium为你的大疆无人机快速生成区域巡查航线(保姆级教程)

本文详细介绍了如何利用Cesium平台为大疆无人机快速生成区域巡查航线的保姆级教程。通过自动化航线规划,告别传统手动打点的繁琐操作,实现高效、无死角的区域覆盖。文章涵盖环境搭建、实战案例及高级优化技巧,特别适合无人机操作员和巡检工作者提升工作效率。

weixin_30399821的博客 519

红日-VulnStack靶场-ATT&CK(二):从Weblogic漏洞到域控渗透实战

本文详细解析了红日安全团队VulnStack靶场中从Weblogic漏洞到域控渗透的完整攻击链。通过实战演示Weblogic反序列化漏洞利用、Cobalt Strike持久化控制、域内信息收集及PsExec横向移动等关键技术,复现了企业内网渗透的典型场景,并提供了防御建议。

tgb3456789的博客 936

pro-c-sharp-10:掌握C 10与.NET 6核心技术的开源项目

pro-c-sharp-10:掌握C# 10与.NET 6核心技术的开源项目 项目介绍 在现代软件开发领域,C# 作为一种强大且灵活的编程语言,以其优雅的语法和强大的功能,赢得了众多开发者的喜爱。而pro-c-sharp-10项目,则是一个专门为学习C# 10和.NET 6技术的开发者设计的开源项目。该项目来源于Andrew Troelsen和Phil Japikse合著的《Pro C# 10 w...

gitblog_01193的博客 814

微信小程序 - 解决报错 operateAudio:fail audioInstance is not set(wx.getRecorderManager苹果ios真机调试运行,播放音频播放出错解决)

微信小程序,苹果ios系统,真机测试报错,播放音频报错operateAudio:fail audioInstance not exist,errCode: -1,小程序生成音频播放报错errMsg,真机调试报错开发者工具没问题,wx.getRecorderManager,音频实例,InnerAudioContext,各种方法都试了不行,只有ios苹果手机有这个问题,IOS 出现 operateAudio,在iOS无法播放的解决方案,更新到最新版本了还是不行,链接没有特殊字符,微信小程序全局音频设置,手机上播

🏆 前端领域优质创作者 1万+

C#10 和 .NET6 企业级应用开发(三)

有多种方法可以提高应用程序的性能,缓存是企业在应用中使用的关键技术之一。缓存就像一个临时数据存储,具有有限的大小和有限的数据,但与原始数据源相比,数据访问速度要快得多,通常只存储数据的一个子集,即最常使用且不经常变化的数据。缓存存储可能只是计算机的 RAM,该 RAM 在执行过程中被进程使用,或者它可能是像 Redis 这样的东西,它使用内存和磁盘来存储数据。这里的关键是它通常位于比原始存储层访问时间更低的硬件上。缓存可以在架构的每一层实现,以便从最接近用户的那一层检索数据。

龙哥盟 531

【WorkBuddy专栏68】HY3绕路部署vsDS4直击根因——一次真实踩坑揭露两个AI模型的推理差距

【WorkBuddy专栏68】HY3绕路部署vsDS4直击根因——一次真实踩坑揭露两个AI模型的推理差距

AI人人懂 560

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

C#9 和 .NET5 企业级应用开发(一)

NET 5 是一个开源的免费平台,可以编写针对任何平台的应用。该平台还为您提供了轻松编写应用的机会,面向任何平台,包括云。作为软件开发人员,我们被赋予构建复杂企业应用的责任。在本书中,我们将学习使用 C# 9 和构建企业应用的各种高级架构和概念.NET 5。这本书将作为使用构建企业应用所需的所有功能的圣经.NET 5。通过对基本概念、实例和自我评估问题的逐步解释,您将深入了解和接触到的每个重要组成部分.NET 5 需要构建一个专业的企业应用。

龙哥盟 1145

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

C#10 和 .NET6 企业级应用开发(四)

到目前为止,我们已经构建了应用程序的所有核心组件,如数据访问层和服务层,所有这些组件主要是服务器端组件,也称为后端组件。在本章中,我们将构建我们的电子商务应用程序的呈现层/用户界面(UI),也称为客户端组件。UI 是应用程序的界面;一个好的呈现层不仅有助于保持用户对应用程序的参与度,而且鼓励用户返回应用程序。这在企业应用程序中尤为重要,一个好的呈现层有助于用户轻松地浏览应用程序,并帮助他们轻松地执行依赖于应用程序的日常活动。我们将专注于理解 ASP.NET Core MVC,并使用 ASP.NET Core

龙哥盟 472

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

J2EE(Java 2 Platform, Enterprise Edition)和.NET是两种主流的企业级应用开发平台

NET是微软公司推出的一个跨平台的、统一的开发平台,它支持多种编程语言(如C#、VB.NET等)和多种操作系统(如Windows、Linux等)。.NET的核心组件包括ASP.NET、Windows Forms、WPF等,这些组件可以协同工作,实现丰富的用户界面和高效的数据处理。在这方面,J2EE和.NET都有各自的优势和劣势,具体取决于项目的需求和团队的技术偏好。:J2EE和.NET都支持多线程编程,但由于底层实现的不同,它们在处理多线程任务时的性能也会有所差异。

[Blog][Domain] programb.blog.youkuaiyun.com 743

C#9 和 .NET5 企业级应用开发(三)

任何网络应用,无论是内容管理系统、社交网络平台还是电子商务应用,都需要将数据保存到永久存储中,以便用户可以根据需要检索、消费和处理数据。在第八章理解缓存中,我们讨论了使用缓存存储;但是,缓存存储是临时存储,数据仍然需要保存到永久存储中。所以,我们需要一个不只是支持不同实体上各种CRUD(简称创建/读取/更新/删除)操作,还支持高可用性,并在宕机时恢复任何数据的存储,也就是灾难恢复。更好的系统设计的关键标准之一是在系统的早期阶段设计一个数据模型。

龙哥盟 517

C#9 和 .NET5 企业级应用开发(四)

ASP.NET Core 身份是一个基于会员资格的系统,提供了一个简单的方法来添加登录和用户管理功能到您的应用。它提供了一个 UI 和应用编程接口API)来创建新的用户帐户、提供电子邮件确认、管理用户配置文件数据、管理密码(如更改或重置密码)、登录、注销等,并启用多因素身份验证MFA它还允许您与外部登录提供商集成,如微软账户、谷歌、脸书、推特和许多其他社交网站,以便用户可以使用他们现有的账户注册,而不是创建新的账户,从而增强用户体验。

龙哥盟 792

NET 5、NET 6、NET 7、NET 8 和 .NET 9 之间的区别

各版本的演进体现了微软对云原生、高性能计算和开发者体验的持续投入,企业可根据自身需求和技术路线选择最适合的版本。

Code365 6266
上一篇: C#10 和 .NET6 企业级应用开发(四)
下一篇: 增强现实企业级项目(一)
绝不原创的飞龙
绝不原创的飞龙 优质创作者: 人工智能、数据科学与机器学习技术领域 优质创作者: 人工智能、数据科学与机器学习技术领域
博客等级 码龄15年 4万+粉丝 2万+原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值