前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >.Net Aspire初体验

.Net Aspire初体验

作者头像
DotNet Whisperer
发布2024-08-14 15:34:21
1300
发布2024-08-14 15:34:21
举报
文章被收录于专栏:DotNet杂记

今天参加了Post Microsoft Build & AI Day深圳的集会,众多大佬分享了非常优质前沿的技术和实践,实在受益良多,为了消化吸收关于张队分享的.Net Aspire的内容,特实操一遍小示例并记录如下:

1、以VS2022为例,先升级到最新的版本v17.10.3,新建.NET Aspire Starter应用程序项目,选择文件夹及Redis勾选和勾选生成Tests(HTTPS不能去除勾选)。

 生成的文件夹结构如下:

 可以看到按模板生成了一个ApiService(这里是以前的天气广播内容);一个Web项目;一个AppHost( 一个Host,把ApiService及Web前端给引用进来);一个ServiceDefaults扩展类;一个Tests测试项目。

AspireApp1.ApiService项目的主要内容:

Program.cs:

代码语言:javascript
复制
 1 var builder = WebApplication.CreateBuilder(args);
 2 
 3 // Add service defaults & Aspire components.
 4 builder.AddServiceDefaults();
 5 
 6 // Add services to the container.
 7 builder.Services.AddProblemDetails();
 8 
 9 var app = builder.Build();
10 
11 // Configure the HTTP request pipeline.
12 app.UseExceptionHandler();
13 
14 var summaries = new[]
15 {
16     "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
17 };
18 
19 app.MapGet("/weatherforecast", () =>
20 {
21     var forecast = Enumerable.Range(1, 5).Select(index =>
22         new WeatherForecast
23         (
24             DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
25             Random.Shared.Next(-20, 55),
26             summaries[Random.Shared.Next(summaries.Length)]
27         ))
28         .ToArray();
29     return forecast;
30 });
31 
32 app.MapDefaultEndpoints();
33 
34 app.Run();
35 
36 record WeatherForecast(DateOnly Date, int TemperatureC, string? Summary)
37 {
38     public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
39 }

AspireApp1.Web项目的主要内容:

Program.cs:

代码语言:javascript
复制
 1 using AspireApp1.Web;
 2 using AspireApp1.Web.Components;
 3 
 4 var builder = WebApplication.CreateBuilder(args);
 5 
 6 // Add service defaults & Aspire components.
 7 builder.AddServiceDefaults();
 8 
 9 // Add services to the container.
10 builder.Services.AddRazorComponents()
11     .AddInteractiveServerComponents();
12 
13 builder.Services.AddOutputCache();
14 
15 builder.Services.AddHttpClient<WeatherApiClient>(client => client.BaseAddress = new("http://apiservice"));
16 
17 var app = builder.Build();
18 
19 if (!app.Environment.IsDevelopment())
20 {
21     app.UseExceptionHandler("/Error", createScopeForErrors: true);
22 }
23 
24 app.UseStaticFiles();
25 app.UseAntiforgery();
26 
27 app.UseOutputCache();
28 
29 app.MapRazorComponents<App>()
30     .AddInteractiveServerRenderMode();
31 
32 app.MapDefaultEndpoints();
33 
34 app.Run();

WeatherApiClient.cs:

代码语言:javascript
复制
 1 namespace AspireApp1.Web;
 2 
 3 public class WeatherApiClient(HttpClient httpClient)
 4 {
 5     public async Task<WeatherForecast[]> GetWeatherAsync(int maxItems = 10, CancellationToken cancellationToken = default)
 6     {
 7         List<WeatherForecast>? forecasts = null;
 8 
 9         await foreach (var forecast in httpClient.GetFromJsonAsAsyncEnumerable<WeatherForecast>("/weatherforecast", cancellationToken))
10         {
11             if (forecasts?.Count >= maxItems)
12             {
13                 break;
14             }
15             if (forecast is not null)
16             {
17                 forecasts ??= [];
18                 forecasts.Add(forecast);
19             }
20         }
21 
22         return forecasts?.ToArray() ?? [];
23     }
24 }
25 
26 public record WeatherForecast(DateOnly Date, int TemperatureC, string? Summary)
27 {
28     public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
29 }

AspireApp1.ServiceDefaults项目的主要内容:

Extensions.cs:

代码语言:javascript
复制
  1 using Microsoft.AspNetCore.Builder;
  2 using Microsoft.AspNetCore.Diagnostics.HealthChecks;
  3 using Microsoft.Extensions.DependencyInjection;
  4 using Microsoft.Extensions.Diagnostics.HealthChecks;
  5 using Microsoft.Extensions.Logging;
  6 using OpenTelemetry;
  7 using OpenTelemetry.Metrics;
  8 using OpenTelemetry.Trace;
  9 
 10 namespace Microsoft.Extensions.Hosting;
 11 
 12 // Adds common .NET Aspire services: service discovery, resilience, health checks, and OpenTelemetry.
 13 // This project should be referenced by each service project in your solution.
 14 // To learn more about using this project, see https://aka.ms/dotnet/aspire/service-defaults
 15 public static class Extensions
 16 {
 17     public static IHostApplicationBuilder AddServiceDefaults(this IHostApplicationBuilder builder)
 18     {
 19         builder.ConfigureOpenTelemetry();
 20 
 21         builder.AddDefaultHealthChecks();
 22 
 23         builder.Services.AddServiceDiscovery();
 24 
 25         builder.Services.ConfigureHttpClientDefaults(http =>
 26         {
 27             // Turn on resilience by default
 28             http.AddStandardResilienceHandler();
 29 
 30             // Turn on service discovery by default
 31             http.AddServiceDiscovery();
 32         });
 33 
 34         return builder;
 35     }
 36 
 37     public static IHostApplicationBuilder ConfigureOpenTelemetry(this IHostApplicationBuilder builder)
 38     {
 39         builder.Logging.AddOpenTelemetry(logging =>
 40         {
 41             logging.IncludeFormattedMessage = true;
 42             logging.IncludeScopes = true;
 43         });
 44 
 45         builder.Services.AddOpenTelemetry()
 46             .WithMetrics(metrics =>
 47             {
 48                 metrics.AddAspNetCoreInstrumentation()
 49                     .AddHttpClientInstrumentation()
 50                     .AddRuntimeInstrumentation();
 51             })
 52             .WithTracing(tracing =>
 53             {
 54                 tracing.AddAspNetCoreInstrumentation()
 55                     // Uncomment the following line to enable gRPC instrumentation (requires the OpenTelemetry.Instrumentation.GrpcNetClient package)
 56                     //.AddGrpcClientInstrumentation()
 57                     .AddHttpClientInstrumentation();
 58             });
 59 
 60         builder.AddOpenTelemetryExporters();
 61 
 62         return builder;
 63     }
 64 
 65     private static IHostApplicationBuilder AddOpenTelemetryExporters(this IHostApplicationBuilder builder)
 66     {
 67         var useOtlpExporter = !string.IsNullOrWhiteSpace(builder.Configuration["OTEL_EXPORTER_OTLP_ENDPOINT"]);
 68 
 69         if (useOtlpExporter)
 70         {
 71             builder.Services.AddOpenTelemetry().UseOtlpExporter();
 72         }
 73 
 74         // Uncomment the following lines to enable the Azure Monitor exporter (requires the Azure.Monitor.OpenTelemetry.AspNetCore package)
 75         //if (!string.IsNullOrEmpty(builder.Configuration["APPLICATIONINSIGHTS_CONNECTION_STRING"]))
 76         //{
 77         //    builder.Services.AddOpenTelemetry()
 78         //       .UseAzureMonitor();
 79         //}
 80 
 81         return builder;
 82     }
 83 
 84     public static IHostApplicationBuilder AddDefaultHealthChecks(this IHostApplicationBuilder builder)
 85     {
 86         builder.Services.AddHealthChecks()
 87             // Add a default liveness check to ensure app is responsive
 88             .AddCheck("self", () => HealthCheckResult.Healthy(), ["live"]);
 89 
 90         return builder;
 91     }
 92 
 93     public static WebApplication MapDefaultEndpoints(this WebApplication app)
 94     {
 95         // Adding health checks endpoints to applications in non-development environments has security implications.
 96         // See https://aka.ms/dotnet/aspire/healthchecks for details before enabling these endpoints in non-development environments.
 97         if (app.Environment.IsDevelopment())
 98         {
 99             // All health checks must pass for app to be considered ready to accept traffic after starting
100             app.MapHealthChecks("/health");
101 
102             // Only health checks tagged with the "live" tag must pass for app to be considered alive
103             app.MapHealthChecks("/alive", new HealthCheckOptions
104             {
105                 Predicate = r => r.Tags.Contains("live")
106             });
107         }
108 
109         return app;
110     }
111 }

AspireApp1.AppHost项目的主要内容:

Program.cs:

代码语言:javascript
复制
1 var builder = DistributedApplication.CreateBuilder(args);
2 
3 var apiService = builder.AddProject<Projects.AspireApp1_ApiService>("apiservice");
4 
5 builder.AddProject<Projects.AspireApp1_Web>("webfrontend")
6     .WithExternalHttpEndpoints()
7     .WithReference(apiService);
8 
9 builder.Build().Run();

还有一个Tests测试项目的内容:

WebTests.cs:

代码语言:javascript
复制
 1 using System.Net;
 2 
 3 namespace AspireApp1.Tests;
 4 
 5 public class WebTests
 6 {
 7     [Fact]
 8     public async Task GetWebResourceRootReturnsOkStatusCode()
 9     {
10         // Arrange
11         var appHost = await DistributedApplicationTestingBuilder.CreateAsync<Projects.AspireApp1_AppHost>();
12         await using var app = await appHost.BuildAsync();
13         await app.StartAsync();
14 
15         // Act
16         var httpClient = app.CreateHttpClient("webfrontend");
17         var response = await httpClient.GetAsync("/");
18 
19         // Assert
20         Assert.Equal(HttpStatusCode.OK, response.StatusCode);
21     }
22 }

2、我们将AspireApp1.AppHost项目设为启动项目,按F5运行。项目即启动生成和运行,可在输出窗口看到对应信息。等程序运行起来会自动打开一个浏览器概览仪表盘窗口如下:

 点击对应项目的终结点,即可看到对应的内容:

AspireApp1.ApiService:

 AspireApp1.Web:

 在仪表盘可以看到资源、控制台、结构化、跟踪、指标几个栏目,没有写一句代码,你的可观测、生产就绪的云原生分布式应用程序就搭建完成了。

以下是一些图示:

 另外多嘴一句,并不是用了Aspire就一定要上云,我突然有个主意,边缘运算、单体程序照样也可以用Aspire。另外Aspire和Dapr应该是有益的补充,而不是替代关系。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-06-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
云数据库 Redis®
腾讯云数据库 Redis®(TencentDB for Redis®)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档