免费开源的 .NET 分布式组件库 Exceptionless Foundatio
前言
在互聯(lián)網(wǎng)時(shí)代,分布式應(yīng)用、系統(tǒng)變得越來(lái)越多,我們?cè)谑褂?.Net 技術(shù)構(gòu)建分布式系統(tǒng)的時(shí)候,需要使用到一些組件或者是助手庫(kù)來(lái)幫助我們提高生產(chǎn)力以及應(yīng)用程序解耦,但是縱觀.Net圈,能夠符合要求的這樣的組件并不是很多,并且沒(méi)有一個(gè)通用的抽象組件能夠?qū)⑦@些接口集成起來(lái),今天就為大家介紹一款開(kāi)源的組件庫(kù) Foundatio,他們同樣出自于Exceptionless團(tuán)隊(duì)之手,下面就來(lái)看看吧。
目錄
Foundatio 介紹
Getting Started
緩存
隊(duì)列
鎖
消息
工作任務(wù)
文件存儲(chǔ)
度量
日志示例程序源碼
總結(jié)
Foundatio 介紹
GitHub :?https://github.com/exceptionless/Foundatio
Foundatio 是一個(gè)插件式的,松耦合的一套構(gòu)建分布式應(yīng)用的程序庫(kù),出自于Exceptionless團(tuán)隊(duì)。
Foundatio 同時(shí)支持 .NET Framework 4.6 和 .NET Core。
通過(guò) Foundatio 我可以獲得哪些幫助呢?
如果你是面對(duì)接口(抽象)構(gòu)建的程序,你可以很容易的對(duì)接口實(shí)現(xiàn)進(jìn)行切換。
具有友好的依賴注入,還在使用 .Net Framework的朋友可以體驗(yàn)一下,它具有比Autofac,Unity等更簡(jiǎn)易的操作和更友好的接口。
可以更加方便的使用緩存了,Foundatio幫助我們封裝了很多緩存的客戶端實(shí)現(xiàn),比如RedisCache、InMemoryCache、ScopedCache等等。
消息總線,你不必自己構(gòu)建或者使用復(fù)雜且昂貴的NServiceBus了,很多時(shí)候我們僅僅需要的是一個(gè)可以在本地或者云上運(yùn)行的簡(jiǎn)單的消息總線。
存儲(chǔ),現(xiàn)在你可以很方便的通過(guò)一致的接口來(lái)使用分布式存儲(chǔ)了,包括內(nèi)存文件存儲(chǔ)、文件夾文件存儲(chǔ),Azure文件存儲(chǔ),AWS S3文件存儲(chǔ)。
Foundatio 主要包含以下模塊:
緩存(Caching)
隊(duì)列(Queues)
鎖(Locks)
消息(Messaging)
工作任務(wù)(Jobs)
文件存儲(chǔ)(File Storage)
度量(Metrics)
日志(Logging)
這些組件都以NuGet包的形式提供出來(lái)供我們很方便的使用,
下面依次來(lái)看看每一個(gè)組件的用途和使用方法吧。
Getting Started
緩存
緩存是一種空間換時(shí)間的技術(shù),你可以通過(guò)緩存來(lái)快速的獲取一些數(shù)據(jù)。
Foundatio Cache 提供了一致的接口ICacheClient?來(lái)很容易的存儲(chǔ)或者讀取緩存數(shù)據(jù),并且提供了4中不同的緩存客戶端的實(shí)現(xiàn)。他們分別是:
1、InMemoryCacheClient:內(nèi)存緩存的實(shí)現(xiàn),這種緩存的生命周期為當(dāng)前進(jìn)程, 有一個(gè)MaxItems屬性,可以設(shè)置最多緩存多少條數(shù)據(jù)。
2、HybridCacheClient:InMemoryCacheClient?具有相同的實(shí)現(xiàn),但是此接口提供、IMessageBus?可以用來(lái)跨線程之間的同步。
3、RedisCacheClient:一個(gè) Redis 客戶端的實(shí)現(xiàn)。
4、RedisHybridCacheClient:一個(gè)RedisCacheClient?、InMemoryCacheClient?的混合實(shí)現(xiàn),通過(guò)RedisMessageBus來(lái)保持內(nèi)存緩存跨線程之間的同步。
注意:如果本地緩存的項(xiàng)已經(jīng)存在,在調(diào)用Redis進(jìn)行序列化保存的時(shí)候可能會(huì)有性能問(wèn)題。
5、ScopedCacheClient:傳入ICacheClient和scope,scope 可以設(shè)置一個(gè)字符串,來(lái)制定一個(gè)緩存鍵前綴,這樣可以很方便的進(jìn)行批量存儲(chǔ)和刪除。
例子:
using Foundatio.Caching;ICacheClient cache = new InMemoryCacheClient(); await cache.SetAsync("test", 1); var value = await cache.GetAsync<int>("test");隊(duì)列
提供了一個(gè)先進(jìn),先出的消息管道,Foundatio 提供了一個(gè)IQueue接口,并且擁有 4 種不同的隊(duì)列實(shí)現(xiàn)。
1、InMemoryQueue:一個(gè)內(nèi)存隊(duì)列實(shí)現(xiàn),隊(duì)列的生命周期為當(dāng)前進(jìn)程。
2、RedisQueue:一個(gè) Redis 隊(duì)列實(shí)現(xiàn)。
3、AzureServiceBusQueue:一個(gè)基于Azure的服務(wù)消息隊(duì)列實(shí)現(xiàn)。
4、AzureStorageQueue:一個(gè)基于Azure的存儲(chǔ)隊(duì)列實(shí)現(xiàn)。
例子:
using Foundatio.Queues;IQueue<SimpleWorkItem> queue = new InMemoryQueue<SimpleWorkItem>();await queue.EnqueueAsync(new SimpleWorkItem {Data = "Hello"});var workItem = await queue.DequeueAsync();鎖
鎖主要是確保無(wú)論在什么時(shí)候資源只被消費(fèi)一次,Foundatio 提供了一個(gè)ILockProvider接口,并且有兩種不同的鎖機(jī)制的實(shí)現(xiàn)。
1、CacheLockProvider:一個(gè)緩存鎖實(shí)現(xiàn)進(jìn)程間通訊。
2、ThrottlingLockProvider:只允許一定數(shù)量的請(qǐng)求進(jìn)入ILockProvider的實(shí)現(xiàn)。你可以使用這個(gè)api調(diào)用外部服務(wù),它將通過(guò)這個(gè)節(jié)氣門(mén)鎖來(lái)限制所有的請(qǐng)求。
這里使用了Throttle這個(gè)單詞,中文意思是節(jié)氣門(mén)。為了方便理解給大家科普一下:在汽車的汽油機(jī)系統(tǒng)中,節(jié)氣門(mén)是一個(gè)很重要的組件,是用來(lái)控制氣體進(jìn)入引擎的一套可控的閥門(mén)。
流程大概就是 空氣-->節(jié)氣門(mén)-->氣缸,相當(dāng)于是汽車發(fā)動(dòng)機(jī)的咽喉,車子加速是否靈活,與節(jié)氣門(mén)的清潔是很有關(guān)系的。所以此處用了Throttle這個(gè)單詞,非常的形象。
需要注意的時(shí)候,所有的鎖都是基于ICacheClient的,所以要確保你代碼中的鎖是否跨機(jī)器的。
例子:
using Foundatio.Lock;using Foundatio.Messaging;ILockProvider locker = new CacheLockProvider(new InMemoryCacheClient(), new InMemoryMessageBus());await locker.AcquireAsync("test");// ...
ILockProvider locker = new ThrottlingLockProvider(new InMemoryCacheClient(), 1, TimeSpan.FromMinutes(1)); ILock locks = await locker.AcquireAsync("test");// ...
消息
允許通過(guò)你的應(yīng)用程序發(fā)布訂閱消息。Foundatio 提供了一個(gè)IMessageBus接口,并且有4 種不同的實(shí)現(xiàn)。
1、InMemoryMessageBus:一個(gè)內(nèi)存消息總線實(shí)現(xiàn)。這個(gè)消息總線的生命周期為當(dāng)前進(jìn)程。
2、RedisMessageBus:一個(gè) Redis 消息總線實(shí)現(xiàn)。
3、RabbitMQMessageBus:一個(gè) RabbitMQ 消息總線實(shí)現(xiàn)。
4、AzureServiceBusMessageBus:一個(gè)Azure Service消息總線實(shí)現(xiàn)。
例子
using Foundatio.Messaging;public class Program{ ? ?
public static void Main(string[] args) {MessageBusTest();Console.ReadKey();} ? ?
public static async void MessageBusTest() {IMessageBus messageBus = new InMemoryMessageBus();messageBus.Subscribe<SimpleMessageA>(msg => {Console.WriteLine(msg.Data);}); ? ? ? ?await messageBus.PublishAsync(new SimpleMessageA { Data = "Hello" });} ? ?
? ?public class SimpleMessageA{ ? ? ? ?public string Data { get; set; }} }
工作任務(wù)
允許你運(yùn)行一個(gè)長(zhǎng)時(shí)間的任務(wù),并且不用擔(dān)心會(huì)被終止。Foundatio提供了一下不同的方法來(lái)定義一個(gè)Job。
1、Jobs:提供了一、IJob?接口,和一個(gè)默認(rèn)的基類JobBase。直接上代碼吧:
using Foundatio.Jobs;public class HelloWorldJob : JobBase { ?
?public int RunCount { get; set; } ?
??protected override Task<JobResult> RunInternalAsync(JobRunContext 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(TimeSpan.FromMilliseconds(10)).Token); // job.RunCount > 10;
2、Queue Processor Jobs:和上面的Jobs差不多,只是這個(gè)是基于隊(duì)列的。
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 HelloWorld
QueueItem. container.RegisterSingleton<IQueue<HelloWorldQueueItem>>(() => new InMemoryQueue<HelloWorldQueueItem>());// To trigger the job we need to queue the HelloWorldWorkItem message.
// This assumes that we injected an instance of
IQueue<HelloWorldWorkItem> queuevar 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;
3、Work Item Jobs:這種類型的Job適合于那些不經(jīng)常發(fā)生,但是應(yīng)該在一個(gè)Job(例如:刪除一個(gè)實(shí)體,有很多子級(jí))。
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 recieve these messages just inject IMessageSubscriber// and Subscribe to messages of type WorkItemStatusawait ctx.ReportProgressAsync(0, "Starting Hello World Job"); ? ? ?
??await Task.Delay(TimeSpan.FromSeconds(2.5)); ? ? ? ?await ctx.ReportProgressAsync(50, String.Format("Reading value")); ? ? ?
?? ?await Task.Delay(TimeSpan.FromSeconds(.5)); ? ? ? ?await ctx.ReportProgressAsync(70, String.Format("Reading value.")); ? ? ? ?
?? ?await Task.Delay(TimeSpan.FromSeconds(.5)); ? ? ? ?await ctx.ReportProgressAsync(90, String.Format("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.RegisterSingleton(handlers); ?// Register the queue for WorkItemData.
container.RegisterSingleton<IQueue<WorkItemData>>(() => new InMemoryQueue<WorkItemData>()); ?// The job runner will automatically look for and run all registered WorkItemHandlers.
new JobRunner(container.GetInstance<WorkItemJob>(), instanceCount: 2).RunInBackground();
?? ?? ?await queue.EnqueueAsync(new HelloWorldWorkItem { Message = "Hello World" });
文件存儲(chǔ)
Foundatio File Storage 提供了一致的接、IFileStorage?來(lái)很容易的存儲(chǔ)或者讀取文件,并且提供了4中不同的文件存儲(chǔ)的實(shí)現(xiàn)。他們分別是:
1、InMemoryFileStorage:基于內(nèi)存的文件存儲(chǔ),生命周期為當(dāng)前進(jìn)程。
2、FolderFileStorage:文件夾存儲(chǔ),存儲(chǔ)到硬盤(pán)中。
3、AzureFileStorage:Azure Blob 存儲(chǔ)的實(shí)現(xiàn)。
4、S3Storage:AWS S3 存儲(chǔ)的實(shí)現(xiàn)。
建議在服務(wù)中注入IFileStorage接口的時(shí)候,使用單例方式注入。
例子:
using Foundatio.Storage;IFileStorage storage = new InMemoryFileStorage();await storage.SaveFileAsync("test.txt", "test");string content = await storage.GetFileContentsAsync("test.txt")度量
關(guān)于Metrics的概念,可以參考?這篇博文。
提供了一個(gè)IMetricsClient?接口,并且有 4 中不同的實(shí)現(xiàn):
1、InMemoryMetricsClient:內(nèi)存 metrics 的實(shí)現(xiàn)。
2、RedisMetricsClient:Redis metrics 的實(shí)現(xiàn)。
3、StatsDMetricsClient:statsd metrics 的實(shí)現(xiàn)。
4、MetricsNETClient:Metrics.NET?的實(shí)現(xiàn)。
建議在服務(wù)中注入IMetricsClient接口的時(shí)候,使用單例方式注入。
例子:
await metrics.CounterAsync("c1");await metrics.GaugeAsync("g1", 2.534);
await metrics.TimerAsync("t1", 50788);
日志
提供了一個(gè)流暢型的日志 api, 可用于在應(yīng)用程序記錄日志消息。并且可以在不需要改變應(yīng)用程序代碼的情況下,切換各個(gè)日志框架。
例子:
ILoggerFactory loggerFactory = new LoggerFactory(); ILogger log = loggerFactory.CreateLogger("Program"); log.Info("Application starting up"); // ORlog.Info().Message("Application starting up").Write();log.Error(ex, "Writing a captured exception out to the log."); // Orlog.Error().Exception(ex).Message("Writing a captured exception out to the log.").Write();示例程序源碼
示例程序GitHub:
https://github.com/exceptionless/Foundatio.Samples
總結(jié)
感謝 Exceptionless 團(tuán)隊(duì)給我們提供了這么簡(jiǎn)單易用的 Foundatio 框架,還在等什么,快在你的項(xiàng)目中用起來(lái)吧。
相關(guān)文章:
免費(fèi)開(kāi)源分布式系統(tǒng)日志收集框架 Exceptionless
使用 Exceptionless 作為 Log Server 搭配 NLog 記錄系統(tǒng)日志
使用Elasticsearch 與 NEST 庫(kù) 構(gòu)建 .NET 企業(yè)級(jí)搜索
為elasticsearch集成一些實(shí)用 插件以及配置的開(kāi)箱即用的版本
Exceptionless 本地部署
原文地址:http://www.cnblogs.com/savorboard/p/exceptionless-foundatio.html
.NET社區(qū)新聞,深度好文,微信中搜索dotNET跨平臺(tái)或掃描二維碼關(guān)注
總結(jié)
以上是生活随笔為你收集整理的免费开源的 .NET 分布式组件库 Exceptionless Foundatio的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: ASP.NET Core 静态文件及JS
- 下一篇: 自包含 .NET Core应用程序