Foundatio.AppMetrics 10.7.1

前缀已保留
dotnet add package Foundatio.AppMetrics --version 10.7.1                
NuGet\Install-Package Foundatio.AppMetrics -Version 10.7.1                
此命令旨在在 Visual Studio 的包管理器控制台中使用,因为它使用 NuGet 模块的 Install-Package 版本。
<PackageReference Include="Foundatio.AppMetrics" Version="10.7.1" />                
对于支持 PackageReference 的项目,将此 XML 节复制到项目文件中以引用该包。
paket add Foundatio.AppMetrics --version 10.7.1                
#r "nuget: Foundatio.AppMetrics, 10.7.1"                
#r 指令可以在 F# Interactive 和 Polyglot Notebooks 中使用。将此复制到交互工具或脚本的源代码中,以引用包。
// Install Foundatio.AppMetrics as a Cake Addin
#addin nuget:?package=Foundatio.AppMetrics&version=10.7.1

// Install Foundatio.AppMetrics as a Cake Tool
#tool nuget:?package=Foundatio.AppMetrics&version=10.7.1                

FoundatioFoundatio

Build status NuGet Version feedz.io Discord

用于构建松散耦合的分布式应用的插件式基础块。

包括 Redis、Azure、AWS、RabbitMQ、Kafka 和内存(用于开发)中的实现。

为什么选择 Foundatio?

在构建几个大型云计算应用时,我们发现缺少许多构建可扩展分布式应用的关键部件的优秀解决方案(这并不是说没有解决方案),同时保持开发体验简单。以下是为什么我们构建并使用 Foundatio 的一些原因:

  • 想针对抽象接口进行构建,以便轻松更改实现。
  • 希望块对依赖注入友好。
  • 缓存:我们最初使用的是开源的Redis缓存客户端,但后来它变成了一个具有高许可成本的商业产品。更糟糕的是,没有内存实现,所以每个开发人员都需要设置和配置Redis。
  • 消息总线:我们最初考虑了 NServiceBus(优秀产品),但它具有高许可成本(他们也需要吃),并且对开源不友好。我们还研究了 MassTransit(另一个优秀产品),但当时发现在Azure上的支持不足,并且本地设置痛苦(对于内存)。我们想要一个简单的工作的消息总线,无论是在本地还是在云端。
  • 存储:我们找不到任何现有项目,它可以解耦并支持内存、文件存储或Azure Blob存储。

总结来说,如果您想要无痛苦的开发和测试,同时允许您的应用程序扩展,请使用Foundatio!

实现

入门(开发)

Foundatio可以通过NuGet包管理器安装。如果您需要帮助,请提交问题或加入我们的Discord聊天室。如果您有任何问题,我们随时都在这里帮助您!

本节仅用于开发目的!如果您正在尝试使用Foundatio库,请从NuGet获取。

  1. 您需要安装Visual Studio Code
  2. 打开Foundatio.sln Visual Studio解决方案文件。

使用Foundatio

以下各节只包含Foundatio可能实现的一小部分。我们建议您查看源代码以获取更多信息。如果您有任何问题或需要帮助,请让我们知道!

缓存

缓存允许您以闪电般的速度存储和访问数据,节省您获取数据或创建数据的昂贵操作。我们提供了四种不同的缓存实现,这些实现是从ICacheClient接口派生的。

  1. InMemoryCacheClient:一个内存缓存客户端实现。此缓存实现仅在进程的生命周期内有效。值得注意的是,内存缓存客户端可以通过MaxItems属性缓存最后X个条目。我们使用它在Exceptionless中仅保留最后250个解析的geoip结果
  2. HybridCacheClient:这种缓存实现同时使用ICacheClientInMemoryCacheClient,并通过使用IMessageBus在进程之间同步缓存。如果在本地缓存中存在该项,则这可以在性能上带来巨大收益,因为您将节省序列化操作和对远程缓存的调用。
  3. RedisCacheClient:Redis缓存客户端实现。
  4. RedisHybridCacheClientHybridCacheClient的实现,使用RedisCacheClient作为ICacheClient,并使用RedisMessageBus作为IMessageBus
  5. ScopedCacheClient:这种缓存实现采用ICacheClient的实例和一个字符串scope。作用域被添加到每个缓存键的开头。这使得您可以轻松地作用域所有缓存键并轻松地删除它们。
示例
using Foundatio.Caching;

ICacheClient cache = new InMemoryCacheClient();
await cache.SetAsync("test", 1);
var value = await cache.GetAsync<int>("test");

队列

队列提供先进先出(FIFO)的消息传递。我们提供四种不同的队列实现,这些实现都源自于IQueue接口

  1. InMemoryQueue:内存队列实现。这种队列实现在进程的生命周期内有效。
  2. RedisQueue:Redis队列实现。
  3. AzureServiceBusQueue:Azure Service Bus 队列实现。
  4. AzureStorageQueue:Azure Storage 队列实现。
  5. SQSQueue:AWS SQS 实现。
示例
using Foundatio.Queues;

IQueue<SimpleWorkItem> queue = new InMemoryQueue<SimpleWorkItem>();

await queue.EnqueueAsync(new SimpleWorkItem {
    Data = "Hello"
});

var workItem = await queue.DequeueAsync();

锁确保任何给定时间内只有一个消费者可以访问资源。我们提供了两个不同的锁实现,这些实现都源自于ILockProvider接口

  1. CacheLockProvider:使用缓存进行进程间通信的锁实现。
  2. ThrottlingLockProvider:仅允许一定数量的锁通过。您可以使用此功能来限制对某些外部服务的API调用的数量,并且它将在所有请求该锁的进程间进行限制。
  3. ScopedLockProvider:此锁实现采用ILockProvider的实例和一个字符串scope。作用域被添加到每个锁键的开头。这使得您可以轻松地作用域所有锁并轻松地释放它们。

需要注意的是,所有锁提供程序都接受一个ICacheClient。这允许您确保您的代码在不同机器之间正确锁定。

示例
using Foundatio.Lock;

ILockProvider locker = new CacheLockProvider(new InMemoryCacheClient(), new InMemoryMessageBus());
var testLock = await locker.AcquireAsync("test");
// ...
await testLock.ReleaseAsync();

ILockProvider throttledLocker = new ThrottlingLockProvider(new InMemoryCacheClient(), 1, TimeSpan.FromMinutes(1));
var throttledLock = await throttledLocker.AcquireAsync("test");
// ...
await throttledLock.ReleaseAsync();

消息传递

允许您发布和订阅通过应用程序的消息流。我们提供四种不同的消息总线实现,这些实现都源自于IMessageBus接口

  1. InMemoryMessageBus:内存消息总线实现。此消息总线实现在进程的生命周期内有效。
  2. RedisMessageBus:Redis消息总线实现。
  3. RabbitMQMessageBus:RabbitMQ实现。
  4. KafkaMessageBus:Kafka实现。
  5. AzureServiceBusMessageBus:Azure Service Bus实现。
示例
using Foundatio.Messaging;

IMessageBus messageBus = new InMemoryMessageBus();
await messageBus.SubscribeAsync<SimpleMessageA>(msg => {
  // Got message
});

await messageBus.PublishAsync(new SimpleMessageA { Data = "Hello" });

工作队列

允许您运行长时间运行的过程(进程中或进程外),而不必担心其被提前终止。根据您的用例,我们提供了三种不同的定义作业的方法。

  1. 作业:所有作业都必须从IJob接口继承。我们还有一个您可以从中继承的JobBase基类,它提供作业上下文和日志记录功能。您可以通过在作业上调用RunAsync()或在创建了JobRunner的实例后调用Run方法之一来运行作业。JobRunner可用于将作业轻松地作为Azure Web作业运行。
示例
using Foundatio.Jobs;

public class HelloWorldJob : JobBase {
  public int RunCount { get; set; }

  protected override Task<JobResult> RunInternalAsync(JobContext context) {
     RunCount++;
     return Task.FromResult(JobResult.Success);
  }
}
var job = new HelloWorldJob();
await job.RunAsync(); // job.RunCount = 1;
await job.RunContinuousAsync(iterationLimit: 2); // job.RunCount = 3;
await job.RunContinuousAsync(cancellationToken: new CancellationTokenSource(10).Token); // job.RunCount > 10;
  1. 队列处理器作业:队列处理器作业非常适合处理来自队列的数据触发的作业。队列处理器作业必须从QueueJobBase继承。然后,您可以通过在作业上调用RunAsync()或在将其传递给JobRunner中时运行作业。JobRunner可用于轻松地将作业作为Azure Web作业运行。
示例
using Foundatio.Jobs;

public class HelloWorldQueueJob : QueueJobBase<HelloWorldQueueItem> {
  public int RunCount { get; set; }

  public HelloWorldQueueJob(IQueue<HelloWorldQueueItem> queue) : base(queue) {}

  protected override Task<JobResult> ProcessQueueEntryAsync(QueueEntryContext<HelloWorldQueueItem> context) {
     RunCount++;

     return Task.FromResult(JobResult.Success);
  }
}

public class HelloWorldQueueItem {
  public string Message { get; set; }
}
 // Register the queue for HelloWorldQueueItem.
container.AddSingleton<IQueue<HelloWorldQueueItem>>(s => new InMemoryQueue<HelloWorldQueueItem>());

// To trigger the job we need to queue the HelloWorldWorkItem message.
// This assumes that we injected an instance of IQueue<HelloWorldWorkItem> queue

IJob job = new HelloWorldQueueJob();
await job.RunAsync(); // job.RunCount = 0; The RunCount wasn't incremented because we didn't enqueue any data.

await queue.EnqueueAsync(new HelloWorldWorkItem { Message = "Hello World" });
await job.RunAsync(); // job.RunCount = 1;

await queue.EnqueueAsync(new HelloWorldWorkItem { Message = "Hello World" });
await queue.EnqueueAsync(new HelloWorldWorkItem { Message = "Hello World" });
await job.RunUntilEmptyAsync(); // job.RunCount = 3;
  1. 工作项作业:工作项作业将在工作项池中与其他工作项作业一起运行。此类作业非常适合不经常发生但应放在作业中的事情(例如:删除有多个子实体的实体)。将在您在消息总线上发布消息时触发该作业。作业必须从WorkItemHandlerBase继承。然后,您可以通过JobRunner运行所有共享作业。JobRunner可用于轻松地将作业作为Azure Web作业运行。
示例
using System.Threading.Tasks;
using Foundatio.Jobs;

public class HelloWorldWorkItemHandler : WorkItemHandlerBase {
  public override async Task HandleItemAsync(WorkItemContext ctx) {
    var workItem = ctx.GetData<HelloWorldWorkItem>();

    // We can report the progress over the message bus easily.
    // To receive these messages just inject IMessageSubscriber
    // and Subscribe to messages of type WorkItemStatus
    await ctx.ReportProgressAsync(0, "Starting Hello World Job");
    await Task.Delay(TimeSpan.FromSeconds(2.5));
    await ctx.ReportProgressAsync(50, "Reading value");
    await Task.Delay(TimeSpan.FromSeconds(.5));
    await ctx.ReportProgressAsync(70, "Reading value");
    await Task.Delay(TimeSpan.FromSeconds(.5));
    await ctx.ReportProgressAsync(90, "Reading value.");
    await Task.Delay(TimeSpan.FromSeconds(.5));

    await ctx.ReportProgressAsync(100, workItem.Message);
  }
}

public class HelloWorldWorkItem {
  public string Message { get; set; }
}
// Register the shared job.
var handlers = new WorkItemHandlers();
handlers.Register<HelloWorldWorkItem, HelloWorldWorkItemHandler>();

// Register the handlers with dependency injection.
container.AddSingleton(handlers);

// Register the queue for WorkItemData.
container.AddSingleton<IQueue<WorkItemData>>(s => new InMemoryQueue<WorkItemData>());

// The job runner will automatically look for and run all registered WorkItemHandlers.
new JobRunner(container.GetRequiredService<WorkItemJob>(), instanceCount: 2).RunInBackground();
 // To trigger the job we need to queue the HelloWorldWorkItem message.
 // This assumes that we injected an instance of IQueue<WorkItemData> queue

 // NOTE: You may have noticed that HelloWorldWorkItem doesn't derive from WorkItemData.
 // Foundatio has an extension method that takes the model you post and serializes it to the
 // WorkItemData.Data property.
 await queue.EnqueueAsync(new HelloWorldWorkItem { Message = "Hello World" });

文件存储

我们提供了不同的文件存储实现,这些实现都从IFileStorage接口衍生而来。

  1. InMemoryFileStorage:内存文件实现。这种文件存储实现仅适用于进程的生命周期内。
  2. FolderFileStorage:使用硬盘进行存储的文件存储实现。
  3. AzureFileStorage:Azure Blob存储实现。
  4. S3FileStorage:AWS S3文件存储实现。
  5. RedisFileStorage:Redis文件存储实现。
  6. MinioFileStorage:Minio文件存储实现。
  7. AliyunFileStorage:阿里云文件存储实现。
  8. SshNetFileStorage:一个SFTP文件存储实现。

我们建议将所有 IFileStorage 实现作为单例使用。

示例
using Foundatio.Storage;

IFileStorage storage = new InMemoryFileStorage();
await storage.SaveFileAsync("test.txt", "test");
string content = await storage.GetFileContentsAsync("test.txt")

度量

我们提供了五个实现,它们继承自 IMetricsClient 接口

  1. InMemoryMetricsClient:一个内存中的度量值实现。
  2. RedisMetricsClient:一个Redis度量值实现。
  3. StatsDMetricsClient:一个statsd度量值实现。
  4. MetricsNETClient:一个 Metrics.NET 实现。
  5. AppMetricsClient:一个 AppMetrics 实现。
  6. CloudWatchMetricsClient:一个 AWS CloudWatch 实现。

我们建议将所有 IMetricsClient 实现作为单例使用。

示例
IMetricsClient metrics = new InMemoryMetricsClient();
metrics.Counter("c1");
metrics.Gauge("g1", 2.534);
metrics.Timer("t1", 50788);

示例应用

我们提供了演示如何使用Foundatio的幻灯片和一个 示例应用

感谢所有贡献者

contributors

产品 兼容和额外的计算目标框架版本。
.NET net5.0 已计算。 net5.0-windows 已计算。 net6.0 已计算。 net6.0-android 已计算。 net6.0-ios 已计算。 net6.0-maccatalyst 已计算。 net6.0-macos 已计算。 net6.0-tvos 已计算。 net6.0-windows 已计算。 net7.0 已计算。 net7.0-android 已计算。 net7.0-ios 已计算。 net7.0-maccatalyst 已计算。 net7.0-macos 已计算。 net7.0-tvos 已计算。 net7.0-windows 已计算。 net8.0 已计算。 net8.0-android 已计算。 net8.0-browser 已计算。 net8.0-ios 已计算。 net8.0-maccatalyst 已计算。 net8.0-macos 已计算。 net8.0-tvos 已计算。 net8.0-windows 已计算。
.NET Core netcoreapp2.0 已计算。 netcoreapp2.1 已计算。 netcoreapp2.2 已计算。 netcoreapp3.0 已计算。 netcoreapp3.1 已计算。
.NET Standard netstandard2.0 兼容。 netstandard2.1 已计算。
.NET Framework net461 已计算。 net462 已计算。 net463 已计算。 net47 已计算。 net471 已计算。 net472 已计算。 net48 已计算。 net481 已计算。
MonoAndroid monoandroid 已计算。
MonoMac monomac 已计算。
MonoTouch monotouch 已计算。
Tizen tizen40 已计算。 tizen60 已计算。
Xamarin.iOS xamarinios 已计算。
Xamarin.Mac xamarinmac 已计算。
Xamarin.TVOS xamarintvos 已计算。
Xamarin.WatchOS xamarinwatchos 已计算。
兼容的目标框架
包含的目标框架(在包中)
了解有关 目标框架.NET Standard 的更多信息。

NuGet 包

此包没有被任何 NuGet 包使用。

GitHub 仓库

此包没有被任何流行的 GitHub 仓库使用。

版本 下载 最后更新
10.7.1 468 3/27/2024
10.7.0 470 1/5/2024
10.6.1 538 6/23/2023
10.6.0 1,399 1/1/2023
10.5.0 1,525 5/18/2022
10.4.0 1,457 3/7/2022
10.3.1 799 1/20/2022
10.3.0 690 1/20/2022
10.2.5 587 12/7/2021
10.2.4 1,058 12/3/2021
10.2.3 535 11/22/2021
10.2.2 1,527 9/23/2021
10.2.1 1,543 7/19/2021
10.2.0 632 7/8/2021
10.1.4 713 6/16/2021
10.1.3 828 4/23/2021
10.1.2 581 4/23/2021
10.1.1 906 4/15/2021
10.1.0 611 4/13/2021
10.0.2 1,084 1/20/2021
10.0.1 1,911 11/2/2020
10.0.0 1,304 9/16/2020
10.0.0-beta9 888 8/25/2020
10.0.0-beta8 596 8/3/2020
10.0.0-beta7 659 7/29/2020
10.0.0-beta6 710 7/7/2020
10.0.0-beta5 807 6/20/2020
10.0.0-beta3 585 6/14/2020
10.0.0-beta2 675 6/6/2020
10.0.0-beta10 622 9/15/2020
10.0.0-beta1 658 5/26/2020
10.0.0-alpha3 624 5/5/2020
10.0.0-alpha2 614 4/27/2020
10.0.0-alpha1 578 4/25/2020
9.1.1 1,545 4/28/2020
9.1.0 711 4/28/2020
9.0.0 1,967 1/16/2020
8.1.2126 1,368 8/30/2019
8.1.2123 836 8/27/2019
8.1.2120 810 8/27/2019
8.1.2115 842 8/27/2019
8.1.2109 802 8/26/2019
8.1.2058 2,506 5/14/2019
8.1.2027 935 4/16/2019
8.0.1965 1,110 2/24/2019
8.0.1948 857 2/22/2019
7.1.1845 1,117 11/3/2018
7.1.1841 1,054 11/3/2018
7.1.1837 1,012 11/1/2018
7.1.1833 983 11/1/2018
7.0.1831 958 11/1/2018
7.0.1818 1,001 10/30/2018
7.0.1738 1,408 9/7/2018