Foundatio.Xunit 10.7.1
前缀已保留
dotnet add package Foundatio.Xunit --version 10.7.1
NuGet\Install-Package Foundatio.Xunit -Version 10.7.1
<PackageReference Include="Foundatio.Xunit" Version="10.7.1" />
paket add Foundatio.Xunit --version 10.7.1
#r "nuget: Foundatio.Xunit, 10.7.1"
// Install Foundatio.Xunit as a Cake Addin #addin nuget:?package=Foundatio.Xunit&version=10.7.1 // Install Foundatio.Xunit as a Cake Tool #tool nuget:?package=Foundatio.Xunit&version=10.7.1
构建松散连接的分布式应用程序的插件式基础块。
包含 Redis、Azure、AWS、RabbitMQ、Kafka 以及内存(用于开发)中的实现。
为什么选择 Foundatio?
在构建几个大型云应用时,我们发现缺乏优秀解决方案(这并非说没有解决方案)来构建可扩展的分布式应用程序,同时保持开发体验简单。以下是我们构建和使用 Foundatio 的几个例子:
- 希望针对抽象接口进行构建,以便轻松更换实现。
- 希望这些块对依赖注入友好。
- 缓存:我们最初使用开源的 Redis 缓存客户端,但后来它变成了一个具有高许可费用的商业产品。不仅如此,而且没有内存实现,所以每个开发人员都需要设置和配置 Redis。
- 消息总线:我们最初考虑过NServiceBus(一款优秀的产品),但是它的许可费用很高(他们也必须盈利),而且对开源不友好。我们还研究过MassTransit(另一款优秀的产品),但当时发现Azure的支持不足,并且本地设置很麻烦(对于内存存储)。我们想要一个简单易用、本地或云端都能工作的消息总线。
- 存储:我们找不到任何现有的项目能够解耦并支持内存、文件存储或Azure Blob存储。
总结来说,如果您希望在应用程序可扩展的同时无需忍受开发和测试的痛苦,请使用Foundatio!
实现方式
- Redis - 缓存、存储、队列、消息、锁、度量
- Azure存储 - 存储、队列
- Azure ServiceBus - 队列、消息
- AWS - 存储、队列、度量
- Kafka - 消息
- RabbitMQ - 消息
- Minio - 存储
- Aliyun - 存储
- SshNet - 存储
入门(开发)
您可以通过NuGet包管理器安装Foundatio。如果您需要帮助,请提出问题或加入我们的Discord聊天室。如果您有任何疑问,我们随时都在这里为您解答!
本节仅用于开发目的!如果您尝试使用Foundatio库,请从NuGet获取。
- 您需要安装Visual Studio Code。
- 打开
Foundatio.sln
Visual Studio解决方案文件。
使用Foundatio
以下各节仅展示了Foundatio功能的一小部分。我们建议您查看源代码以获取更多信息。如果您有任何疑问或需要帮助,请告诉我们!
缓存
缓存允许您以闪电般的速度存储和访问数据,从而节约创建或获取数据的昂贵操作。我们提供了四种不同的缓存实现,它们都源自于ICacheClient
接口
- InMemoryCacheClient:一个内存缓存客户端实现。这种缓存实现仅在进程生存期内有效。值得注意的是,内存缓存客户端具有通过
MaxItems
属性缓存最后X个项的能力。我们使用它来在Exceptionless中仅保留最后250个解析的geoip结果。 - HybridCacheClient:这种缓存实现同时使用
ICacheClient
和InMemoryCacheClient
,并通过IMessageBus
在每个进程之间保持缓存同步。这可以带来巨大的性能提升
,因为如果项存在于本地缓存中,您将节省序列化操作和远程缓存调用。 - RedisCacheClient:Redis缓存客户端实现。
- RedisHybridCacheClient:一种混合缓存客户端实现,使用
RedisCacheClient
作为ICacheClient
,并使用RedisMessageBus
作为IMessageBus
。 - ScopedCacheClient:该缓存实现接受一个
ICacheClient
实例和一个字符串scope
。该作用域会被添加到每个缓存键的前面。这使得对所有缓存键进行作用域划分并轻松删除变得更加简单。
示例
using Foundatio.Caching;
ICacheClient cache = new InMemoryCacheClient();
await cache.SetAsync("test", 1);
var value = await cache.GetAsync<int>("test");
队列
队列提供先入先出(FIFO)的消息投递。我们提供了四种不同的队列实现,它们都继承自IQueue
接口。
- InMemoryQueue:一种内存队列实现。此队列实现仅对进程的有效生命周期有效。
- RedisQueue:一种Redis队列实现。
- AzureServiceBusQueue:一种Azure Service Bus队列实现。
- AzureStorageQueue:一种Azure Storage队列实现。
- 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
接口的锁定实现。
- CacheLockProvider:一种使用缓存进行进程间通信的锁定实现。
- ThrottlingLockProvider:一种只允许一定数量的锁通过的锁定实现。你可以用它来限制对某些外部服务的API调用,它会跨所有请求该锁的进程进行限制。
- 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
接口的消息总线实现。
- InMemoryMessageBus:一种内存消息总线实现。此消息总线实现仅对进程的有效生命周期有效。
- RedisMessageBus:一种Redis消息总线实现。
- RabbitMQMessageBus:一种RabbitMQ实现。
- KafkaMessageBus:一种Kafka实现。
- 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" });
作业
允许您运行持久运行的过程(在进程内或进程外),无需担心其被提前终止。根据您的用例,我们提供了三种定义工作方式的途径。
- 工作:所有工作都必须从
IJob
接口继承。我们还提供了一个可以从之继承的JobBase
基类,它提供了Job上下文和日志记录功能。然后您可以通过在工作实例上调用RunAsync()
或在JobRunner
类上创建实例并调用其中一个Run方法来运行工作。JobRunner可以用来方便地将工作作为Azure Web Jobs运行。
示例
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;
- 队列处理器工作:队列处理器工作非常适合与来自队列数据的工作配合使用。队列处理器工作必须从
QueueJobBase<T>
类继承。然后您可以直接在工作实例上调用RunAsync()
或将其传递给JobRunner
类。JobRunner可以用来方便地将工作作为Azure Web Jobs运行。
示例
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;
- 工作项工作:工作项工作将在工作池中与其他工作项工作一起运行。此类工作非常适合那些不太经常发生但应包含在作业中的事情(例如:删除具有许多子项的实体)。它在您在
消息总线
上发布消息时将被触发。此类工作必须从WorkItemHandlerBase
类继承。然后您可以通过JobRunner
类来运行所有共享工作项。JobRunner可以用来方便地将工作作为Azure Web Jobs运行。
示例
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
接口继承。
- InMemoryFileStorage:一个内存文件实现。此文件存储实现仅对进程的生命周期有效。
- FolderFileStorage:一个使用硬盘进行存储的文件存储实现。
- AzureFileStorage:一个Azure Blob存储实现。
- S3FileStorage:一个AWS S3文件存储实现。
- RedisFileStorage:一个Redis文件存储实现。
- MinioFileStorage:一个Minio文件存储实现。
- AliyunFileStorage:一个阿里云文件存储实现。
- RedisFileStorage:一个Redis文件存储实现。
我们建议使用所有IFileStorage
实现作为单例。
示例
using Foundatio.Storage;
IFileStorage storage = new InMemoryFileStorage();
await storage.SaveFileAsync("test.txt", "test");
string content = await storage.GetFileContentsAsync("test.txt")
度量
我们提供了从IMetricsClient
接口继承的五个实现。
- InMemoryMetricsClient:一个内存指标实现。
- RedisMetricsClient:Redis度量实现。
- StatsDMetricsClient:statsd度量实现。
- MetricsNETClient:Metrics.NET实现。
- AppMetricsClient:AppMetrics实现。
- CloudWatchMetricsClient:AWS CloudWatch实现。
我们建议使用所有IMetricsClient
实现作为单例。
示例
IMetricsClient metrics = new InMemoryMetricsClient();
metrics.Counter("c1");
metrics.Gauge("g1", 2.534);
metrics.Timer("t1", 50788);
示例应用程序
我们有幻灯片和示例应用程序,展示了如何使用Foundatio。
感谢所有做出贡献的人
产品 | 版本 兼容的以及额外计算的目标框架版本。 |
---|---|
.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 已计算。 |
-
.NETStandard 2.0
- Foundatio (>= 10.7.1)
- Microsoft.Extensions.Logging (>= 6.0.0)
- System.Collections.Immutable (>= 6.0.0)
- xunit (>= 2.6.0)
NuGet 包 (1)
显示 1 个依赖于 Foundatio.Xunit 的顶级 NuGet 包
包 | 下载 |
---|---|
Foundatio.TestHarness 构建分布式应用的插件式基础块。 |
GitHub 仓库 (2)
显示 2 个依赖于 Foundatio.Xunit 的最受欢迎的 GitHub 仓库
仓库 | 星标 |
---|---|
exceptionless/Exceptionless
Exceptionless 应用
|
|
exceptionless/Exceptionless.DateTimeExtensions
DateTimeRange、工作日和多种 DateTime、DateTimeOffset、TimeSpan 扩展方法
|
版本 | 下载 | 最后更新 |
---|---|---|
10.7.1 | 6,184 | 3/27/2024 |
10.7.0 | 4,591 | 1/5/2024 |
10.6.1 | 8,219 | 6/23/2023 |
10.6.0 | 12,037 | 1/1/2023 |
10.5.0 | 9,704 | 5/18/2022 |
10.4.0 | 3,368 | 3/7/2022 |
10.3.1 | 1,438 | 1/20/2022 |
10.3.0 | 808 | 1/20/2022 |
10.2.5 | 1,057 | 12/7/2021 |
10.2.4 | 1,141 | 12/3/2021 |
10.2.3 | 658 | 11/22/2021 |
10.2.2 | 2,923 | 9/23/2021 |
10.2.1 | 2,414 | 7/19/2021 |
10.2.0 | 846 | 7/8/2021 |
10.1.4 | 918 | 6/16/2021 |
10.1.3 | 1,538 | 4/23/2021 |
10.1.2 | 669 | 4/23/2021 |
10.1.1 | 1,320 | 4/15/2021 |
10.1.0 | 713 | 4/13/2021 |
10.0.2 | 2,056 | 1/20/2021 |
10.0.1 | 2,438 | 11/2/2020 |
10.0.0 | 1,684 | 9/16/2020 |
10.0.0-beta9 | 1,193 | 8/25/2020 |
10.0.0-beta8 | 845 | 8/3/2020 |
10.0.0-beta7 | 722 | 7/29/2020 |
10.0.0-beta6 | 1,091 | 7/7/2020 |
10.0.0-beta5 | 958 | 6/20/2020 |
10.0.0-beta3 | 743 | 6/14/2020 |
10.0.0-beta2 | 819 | 6/6/2020 |
10.0.0-beta10 | 786 | 9/15/2020 |