NuGet

快速入门

首先,你需要已经配置了 NATS 服务器,并且知道访问这个服务器的 URL 地址。

安装 NuGet

使用你熟悉的方式安装 NuGet 库

dotnet add package Aspire.NATS.Net
  • 1.

使用示例

在项目的 Program.cs 中,调用 AddNatsClient() 扩展方法以在依赖注入容器中注册 INatsConnection 对象。该方法需要一个连接串作为参数。

builder.AddNatsClient("nats");
  • 1.

以后可以在通过 INatsConnection 来注入对象实例。例如,在 Web API 的控制器中

private readonly INatsConnection _connection;

public ProductsController(INatsConnection connection)
{
    _connection = connection;
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.

配置

基于你的需求和项目的使用方式,.NET Aspire NATS 组件提供了多种方式配置 NATS 连接。

使用连接串

当使用来自 ConnectionStrings 配置节中的连接串时,可以在调用 AddNatsClient() 方法的时候,提供连接串的名称。

builder.AddNatsClient("myConnection");
  • 1.

其中的连接串来自配置文件 appsettings.json

{
  "ConnectionStrings": {
    "myConnection": "nats://nats:4222"
  }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
使用配置提供器

.NET Aspire NATS 组件支持  Microsoft.Extensions.Configuration,它会从键 Aspire:Nats:Client 中加载 NatsClientSettings 配置。例如下面的 appsettings.json 中

{
  "Aspire": {
    "Nats": {
      "Client": {
        "DisableHealthChecks": true
      }
    }
  }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
使用内联代码

你还可以通过提供 Action<NatsClientSettings> configureSettings 委托来内联配置其它设置,例如,禁用健康检查:

builder.AddNatsClient("nats", settings => settings.DisableHealthChecks = true);
  • 1.

AppHost 扩展

在 AppHost 项目中,安装  Aspire.Hosting.Nats NuGet 库

dotnet add package Aspire.Hosting.Nats
  • 1.

然后,在 AppHost 的 Program.cs 中,注册 NATS 服务器并使用它。

// nats, the "nats" is the name of connection string 
// MUST call the WithJetStream() if it is requried
var nats = builder.AddNats("nats")
    .WithJetStream();

var myService = builder.AddProject<Projects.MyService>()
                       .WithReference(nats);
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.

这里的 WithReference() 方法,配置了 MyService 项目中名为 "nats" 的连接。请注意,在 MyService 项目的 Program.cs 中,使用如下方式来使用该连接。

builder.AddNatsClient("nats");
  • 1.

实现代码

注册用于连接到 NATS 服务器的 NATS 客户端的 INatsConnection 服务

  • connectionName,用于从 ConnectionStrings 配置节中提取 NATS 连接串的名称
  • configureSettings,用于定制 NatsClientSettings 配置项
  • configureOptions,用于定制 NatsOpts
public static void AddNatsClient(this IHostApplicationBuilder builder, string connectionName, Action<NatsClientSettings>? configureSettings = null, Func<NatsOpts, NatsOpts>? configureOptions = null)
        => AddNatsClient(builder, configurationSectionName: DefaultConfigSectionName, connectionName: connectionName, serviceKey: null, configureSettings: configureSettings, configureOptions: configureOptions);

private static void AddNatsClient(this IHostApplicationBuilder builder, string configurationSectionName, string connectionName, object? serviceKey, Action<NatsClientSettings>? configureSettings, Func<NatsOpts, NatsOpts>? configureOptions)
{
    ArgumentNullException.ThrowIfNull(builder);

    NatsClientSettings settings = new();
    builder.Configuration.GetSection(configurationSectionName).Bind(settings);

    if (builder.Configuration.GetConnectionString(connectionName) is string connectionString)
    {
        settings.ConnectionString = connectionString;
    }

    configureSettings?.Invoke(settings);

    NatsConnection Factory(IServiceProvider provider)
    {
        var options = NatsOpts.Default with
        {
            LoggerFactory = provider.GetRequiredService<ILoggerFactory>(),
        };

        if (configureOptions != null)
        {
            options = configureOptions(options);
        }

        if (settings.ConnectionString == null)
        {
            throw new InvalidOperationException($"NATS connection string not found: {connectionName}");
        }

        options = options with { Url = settings.ConnectionString };

        return new NatsConnection(options);
    }

    if (serviceKey == null)
    {
        builder.Services.TryAddSingleton(Factory);
        builder.Services.TryAddSingleton<INatsConnection>(static provider => provider.GetRequiredService<NatsConnection>());
    }
    else
    {
        builder.Services.TryAddKeyedSingleton<NatsConnection>(serviceKey, (provider, _) => Factory(provider));
        builder.Services.TryAddKeyedSingleton<INatsConnection>(serviceKey, static (provider, key) => provider.GetRequiredKeyedService<NatsConnection>(key));
    }

    if (!settings.DisableHealthChecks)
    {
        builder.TryAddHealthCheck(new HealthCheckRegistration(
            serviceKey is null ? "NATS" : $"NATS_{connectionName}",
            sp => new NatsHealthCheck(serviceKey is null
                ? sp.GetRequiredService<INatsConnection>()
                : sp.GetRequiredKeyedService<INatsConnection>(serviceKey)),
            failureStatus: default,
            tags: default,
            timeout: default));
    }

    if (!settings.DisableTracing)
    {
        builder.Services
            .AddOpenTelemetry()
            .WithTracing(tracer =>
            {
                tracer.AddSource(ActivityNameSource);
            });
    }
}

/// <summary>
/// Registers <see cref="INatsJSContext"/> service for NATS JetStream operations.
/// </summary>
/// <param name="builder">The <see cref="IHostApplicationBuilder" /> to read config from and add services to.</param>
/// <exception cref="ArgumentNullException">Thrown if mandatory <paramref name="builder"/> is null.</exception>
public static void AddNatsJetStream(this IHostApplicationBuilder builder)
{
    ArgumentNullException.ThrowIfNull(builder);

    builder.Services.AddSingleton<INatsJSContext>(static provider =>
    {
        return new NatsJSContextFactory().CreateContext(provider.GetRequiredService<INatsConnection>());
    });
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83.
  • 84.
  • 85.
  • 86.
  • 87.

源码

参考资料