设为首页 收藏本站
查看: 2122|回复: 0

[经验分享] 免费开源的 .NET 分布式组件库 Exceptionless Foundatio

[复制链接]

尚未签到

发表于 2017-7-1 18:41:03 | 显示全部楼层 |阅读模式
前言
  在互联网时代,分布式应用、系统变得越来越多,我们在使用 .Net 技术构建分布式系统的时候,需要使用到一些组件或者是助手库来帮助我们提高生产力以及应用程序解耦,但是纵观.Net圈,能够符合要求的这样的组件并不是 很多,并且没有一个通用的抽象组件能够将这些接口集成起来,今天就为大家介绍一款开源的组件库 Foundatio,他们同样出自于Exceptionless团队之手,下面就来看看吧。

目录


  • Foundatio 介绍
  • Getting Started
    缓存
    队列

    消息
    工作任务
    文件存储
    度量
    日志
  • 示例程序源码
  • 总结

Foundatio 介绍
  GitHub : https://github.com/exceptionless/Foundatio
  Foundatio 是一个插件式的,松耦合的一套构建分布式应用的程序库,出自于Exceptionless团队。
  Foundatio 同时支持 .NET Framework 4.6 和 .NET Core。
  通过 Foundatio 我可以获得哪些帮助呢


  • 如果你是面对接口(抽象)构建的程序,你可以很容易的对接口实现进行切换。
  • 具有友好的依赖注入,还在使用 .Net Framework的朋友可以体验一下,它具有比Autofac,Unity等更简易的操作和更友好的接口。
  • 可以更加方便的使用缓存了,Foundatio帮助我们封装了很多缓存的客户端实现,比如RedisCache、InMemoryCache、ScopedCache等等。
  • 消息总线,你不必自己构建或者使用复杂且昂贵的NServiceBus了,很多时候我们仅仅需要的是一个可以在本地或者云上运行的简单的消息总线。
  • 存储,现在你可以很方便的通过一致的接口来使用分布式存储了,包括内存文件存储、文件夹文件存储,Azure文件存储,AWS S3文件存储。
  Foundatio 主要包含以下模块:


  • 缓存(Caching)
  • 队列(Queues)
  • 锁(Locks)
  • 消息(Messaging)
  • 工作任务(Jobs)
  • 文件存储(File Storage)
  • 度量(Metrics)
  • 日志(Logging)
  这些组件都以NuGet包的形式提供出来供我们很方便的使用,
DSC0000.png

  下面依次来看看每一个组件的用途和使用方法吧。

Getting Started

缓存
  缓存是一种空间换时间的技术,你可以通过缓存来快速的获取一些数据。
  Foundatio Cache 提供了一致的接口ICacheClient 来很容易的存储或者读取缓存数据,并且提供了4中不同的缓存客户端的实现。他们分别是:
  1、InMemoryCacheClient:内存缓存的实现,这种缓存的生命周期为当前进程, 有一个MaxItems属性,可以设置最多缓存多少条数据。
  2、HybridCacheClient:InMemoryCacheClient 具有相同的实现,但是此接口提供、IMessageBus 可以用来跨线程之间的同步。
  3、RedisCacheClient:一个 Redis 客户端的实现。
  4、RedisHybridCacheClient:一个RedisCacheClient 、InMemoryCacheClient 的混合实现,通过RedisMessageBus来保持内存缓存跨线程之间的同步。
  注意:如果本地缓存的项已经存在,在调用Redis进行序列化保存的时候可能会有性能问题。
  5、ScopedCacheClient:传入ICacheClient和scope,scope 可以设置一个字符串,来制定一个缓存键前缀,这样可以很方便的进行批量存储和删除。
  例子:

using Foundatio.Caching;
ICacheClient cache = new InMemoryCacheClient();
await cache.SetAsync("test", 1);
var value = await cache.GetAsync<int>("test");
队列
  提供了一个先进,先出的消息管道,Foundatio 提供了一个IQueue接口,并且拥有 4 种不同的队列实现。
  1、InMemoryQueue:一个内存队列实现,队列的生命周期为当前进程。
  2、RedisQueue:一个 Redis 队列实现。
  3、AzureServiceBusQueue:一个基于Azure的服务消息队列实现。
  4、AzureStorageQueue:一个基于Azure的存储队列实现。
  例子:

using Foundatio.Queues;
IQueue<SimpleWorkItem> queue = new InMemoryQueue<SimpleWorkItem>();
await queue.EnqueueAsync(new SimpleWorkItem {
Data = "Hello"
});
var workItem = await queue.DequeueAsync();

  锁主要是确保无论在什么时候资源只被消费一次,Foundatio 提供了一个ILockProvider接口,并且有两种不同的锁机制的实现。
  1、CacheLockProvider:一个缓存锁实现进程间通讯。
  2、ThrottlingLockProvider:只允许一定数量的请求进入ILockProvider的实现。你可以使用这个api调用外部服务,它将通过这个节气门锁来限制所有的请求。

  这里使用了Throttle这个单词,中文意思是节气门。为了方便理解给大家科普一下:在汽车的汽油机系统中,节气门是一个很重要的组件,是用来控制气体进入引擎的一套可控的阀门。
流程大概就是 空气-->节气门-->气缸,相当于是汽车发动机的咽喉,车子加速是否灵活,与节气门的清洁是很有关系的。所以此处用了Throttle这个单词,非常的形象。

  需要注意的时候,所有的锁都是基于ICacheClient的,所以要确保你代码中的锁是否跨机器的。
  例子:

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");
// ...
消息
  允许通过你的应用程序发布订阅消息。Foundatio 提供了一个IMessageBus接口,并且有4 种不同的实现。
  1、InMemoryMessageBus:一个内存消息总线实现。这个消息总线的生命周期为当前进程。
  2、RedisMessageBus:一个 Redis 消息总线实现。
  3、RabbitMQMessageBus:一个 RabbitMQ 消息总线实现。
  4、AzureServiceBusMessageBus:一个Azure Service消息总线实现。
  例子

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; }
}
}
工作任务
  允许你运行一个长时间的任务,并且不用担心会被终止。Foundatio提供了一下不同的方法来定义一个Job。
  1、Jobs:提供了一、IJob 接口,和一个默认的基类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差不多,只是这个是基于队列的。

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.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> queue
var 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适合于那些不经常发生,但是应该在一个Job(例如:删除一个实体,有很多子级)。

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 WorkItemStatus
await 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" });
文件存储
  Foundatio File Storage 提供了一致的接、IFileStorage 来很容易的存储或者读取文件,并且提供了4中不同的文件存储的实现。他们分别是:
  1、InMemoryFileStorage:基于内存的文件存储,生命周期为当前进程。
  2、FolderFileStorage:文件夹存储,存储到硬盘中。
  3、AzureFileStorage:Azure Blob 存储的实现。
  4、S3Storage:AWS S3 存储的实现。
  建议在服务中注入IFileStorage接口的时候,使用单例方式注入。
  例子:

using Foundatio.Storage;
IFileStorage storage = new InMemoryFileStorage();
await storage.SaveFileAsync("test.txt", "test");
string content = await storage.GetFileContentsAsync("test.txt")
度量
  关于Metrics的概念,可以参考 这篇博文。
  提供了一个IMetricsClient 接口,并且有 4 中不同的实现:
  1、InMemoryMetricsClient:内存 metrics 的实现。
  2、RedisMetricsClient:Redis metrics 的实现。
  3、StatsDMetricsClient:statsd metrics 的实现。
  4、MetricsNETClient:Metrics.NET 的实现。
  建议在服务中注入IMetricsClient接口的时候,使用单例方式注入。
  例子:

await metrics.CounterAsync("c1");
await metrics.GaugeAsync("g1", 2.534);
await metrics.TimerAsync("t1", 50788);
日志
  提供了一个流畅型的日志 api, 可用于在应用程序记录日志消息。并且可以在不需要改变应用程序代码的情况下,切换各个日志框架。
  例子:

ILoggerFactory loggerFactory = new LoggerFactory();
ILogger log = loggerFactory.CreateLogger("Program");
log.Info("Application starting up"); // OR
log.Info().Message("Application starting up").Write();
log.Error(ex, "Writing a captured exception out to the log."); // Or
log.Error().Exception(ex).Message("Writing a captured exception out to the log.").Write();
示例程序源码
  示例程序GitHub:
  https://github.com/exceptionless/Foundatio.Samples

总结
  感谢 Exceptionless 团队给我们提供了这么简单易用的 Foundatio 框架,还在等什么,快在你的项目中用起来吧。
  如果您觉得本文对您有帮助,想让更多人了解Exceptionless,感谢您帮忙点的【推荐】。
  如果您对 Exceptionless 感兴趣或者是想学习 Exceptionless 的代码,可以加入群
  Exceptionless QQ群:330316486


  本文地址:http://www.cnblogs.com/savorboard/p/exceptionless-foundatio.html
作者博客:Savorboard
欢迎转载,请在明显位置给出出处及链接


运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-390143-1-1.html 上篇帖子: 云服务厂商都在推荐轻量级的存储队列服务,用来取代原有的比较重的消息队列服务 下篇帖子: [转] .net core Session , Working with a distributed cache
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表