当前位置: 首页 > 软件库 > 大数据 > 数据存储 >

storage

授权协议 MIT License
开发语言 C#
所属分类 大数据、 数据存储
软件类型 开源软件
地区 不详
投 递 者 江衡
操作系统 跨平台
开源组织
适用人群 未知
 软件概览

Storage.Net

One Interface To Rule Them All

About

Storage.NET is a field-tested .NET library that helps to achieve polycloud techniques.

It provides generic interface for popular cloud storage providers like Amazon S3, Azure Service Bus, Azure Event Hub, Azure Storage, Azure Data Lake Store thus abstracting Blob and Messaging services.

It also implements in-memory and on-disk versions of all the abstractions for faster local machine development. Connection strings are supported too!

Storage.Net is used by some big Fortune 500 companies, large, medium and small businesses, open-source projects and even desktop applications like this one:

Index

Intentions

I'm not really sure why there are so many similar storage providers performing almost identical function but no standard. Why do we need to learn a new SDK to achieve something trivial we've done so many times before? I have no idea. If you don't either, use this library.

Storage.Net abstracts storage implementation like blobs, tables and messages from the .NET Applicatiion Developer. It's aimed to provide a generic interface regardless on which storage provider you are using. It also provides both synchronous and asynchronous alternatives of all methods and implements it to the best effort possible.

Storage.Net supports Azure Service Bus, Azure Event Hub, Azure Storage, Azure Data Lake Store, Amazon S3, Azure Key Vault and many more, out of the box, with hassle-free configuration and zero learning path.

Local Development

Storage.Net also implements inmemory and on disk versions of all the abstractions, therefore you can develop fast on local machine or use vendor free serverless implementations for parts of your applciation which don't require a separate third party backend at a particular point in development.

This framework supports .NET Standard 2.0 and higher.

Implementations

Storage.Net defines two different storage types:

  • Blob Storage is used to store arbitrary files of any size, that do not have any structure. The data is essentially a binary file. Examples of a blog storage is Azure Blob Storage, Amazon S3, local folder etc.
  • Messaging is an asynchronous mechanism to send and receive messages between disconnected systems. For instance MSMQ, Azure Service Bus, Amazon Simple Queue etc.

Some effort has been made to document the supported storage options, you are welcome to contribute to documentation, or browse the following sections:

Geting Started

Blob Storage

Blob Storage stores files. A file has only two properties - ID and raw data. If you build an analogy with disk filesystem, file ID is a file name.

Blob Storage is really simple abstraction - you read or write file data by it's ID, nothing else.

The entry point to a blog storage is IBlobStorage interface. This interface is small but contains all possible methods to work with blobs, such as uploading and downloading data, listing storage contents, deleting files etc. The interface is kept small so that new storage providers can be added easily, without implementing a plethora of interface methods.

In addition to this interface, there are plency of extension methods which enrich the functionality, therefore you will see more methods than this interface actually declares. They add a lot of useful and functionality rich methods to work with storage. For instance, IBlobStorage upload functionality only works with streams, however extension methods allows you to upload text, stream, file or even a class as a blob. Extension methods are also provider agnostic, therefore all the rich functionality just works and doesn't have to be reimplemented in underlying data provider.

All the storage implementations can be created either directly or using factory methods available in the Storage.Net.StorageFactory.Blobs class. More methods appear in that class as you reference a NuGet package containing specific implementations, however there are a few built-in implementations available out of the box as well. After referencing an appropriate package from NuGet you can call to a storage factory to create a respective storage implementation:

You can also use connection strings to create blob storage instances. Connection strings are often useful if you want to completely abstract yourself from the underlying implementation. Please read the appropriate implementation details for connection string details. For instance, to create an instance of Azure Blob Storage provider you could write:

IBlobStorage storage = StorageFactory.Blobs.FromConnectionString("azure.blobs://...parameters...");

In this example we create a blob storage implementation which happens to be Microsoft Azure blob storage. The project is referencing an appropriate nuget package. As blob storage methods promote streaming we create a MemoryStream over a string for simplicity sake. In your case the actual stream can come from a variety of sources.

using Storage.Net;
using Storage.Net.Blobs;
using System.IO;
using System.Text;

namespace Scenario
{
   public class DocumentationScenarios
   {
      public async Task RunAsync()
      {
         //create the storage using a factory method
         IBlobStorage storage = StorageFactory.Blobs.AzureBlobStorageWithSharedKey(
            "storage name",
            "storage key");

         //upload it
         string content = "test content";
         using (var s = new MemoryStream(Encoding.UTF8.GetBytes(content)))
         {
            await storage.WriteAsync("mycontainer/someid", s);
         }

         //read back
         using (var s = new MemoryStream())
         {
            using (Stream ss = await storage.OpenReadAsync("mycontainer/someid"))
            {
               await ss.CopyToAsync(s);

               //content is now "test content"
               content = Encoding.UTF8.GetString(s.ToArray());
            }
         }
      }
   }
}

This is really simple, right? However, the code looks really long and boring. If I need to just save and read a string why the hell do I need to dance around with streams? That was examply my point when trying to use external SDKs. Why do we need to work in an ugly way if all we want to do is something simple? Therefore with Storage.Net you can decrease this code to just two lines of code:

public async Task BlobStorage_sample2()
{
    IBlobStorage storage = StorageFactory.Blobs.AzureBlobStorageWithSharedKey(
		"storage name",
		"storage key");

    //upload it
    await storage.WriteTextAsync("mycontainer/someid", "test content");

    //read back
    string content = await storage.ReadTextAsync("mycontainer/someid");
}

You can find the list of supported blob storage implementations here.

High-level architecture

The basic architecture of blobs is depicted in the following diagram:

All of the core methods are defined in the IBlobStorage interface. This is the interface that's enough for a new storage provider to implement in order to add a new storage provider.

However, some providers support more than just basic operations, for instance Azure Blob Storage supports blob leasing, shared access signatures etc., therefore it actually implements IAzureBlobStorage interface that in turn implements IBlobStorage interface, and extends the functionality further. Same goes for AWS S3 and others.

However, when you are browsing IBlobStorage interface, intellisesnse will shows you a plethora of methods that are not there. This is because there are plenty of extension methods defined for it. Extension methods add extra useful stuff, such as ability to write/read strings, JSON objects and so on, but they in turn use only methods from IBlobStorage. The decision to split those methods into extension methods was because that is logical functionality not dependent on any underlying implementation. Also implementing new storage providers is much easier, as you only have to implement a subset of methods.

Transform Sinks

Transform sinks is another awesome feature of Storage.Net that works across all the storage providers. Transform sinks allow you to transform data stream for both upload and download to somehow transform the underlying stream of data. Examples of transform sinks would be gzipping data transparently, encrypting it, and so on.

Let's say you would like to gzip all of the files that you upload/download to a storage. You can do that in the following way:

IBlobStorage myGzippedStorage = StorageFactory.Blobs
   .AzureBlobStorageWithSharedKey("name", "key")
   .WithGzipCompression();

Then use the storage as you would before - all the data is compressed as you write it (with any WriteXXX method) and decompressed as you read it (with any ReadXXX method).

For more details on sinks available and how to implement your own sink, read this page.

Implementation Details

Due to the nature of the transforms, they can change both the underlying data, and stream size, therefore there is an issue with storage providers, as they need to know beforehand the size of the blob you are uploading. The matter becomes more complicated when some implementations need to calculate other statistics of the data before uploading i.e. hash, CRC and so on. Therefore the only reliable way to stream transformed data is to actually perform all of the transofrms, and then upload it. In this implementation, Storage.Net uses in-memory transforms to achieve this, however does it extremely efficiently by using Microsoft.IO.RecyclableMemoryStream package that performs memory pooling and reclaiming for you so that you don't need to worry about software slowdows. You can read more about this technique here.

This also means that today a transform sink can upload a stream only as large as the amount of RAM available on your machine. I am, however, thinking of ways to go further than that, and there are some beta implementations available that might see the light soon.

Messaging

Messaging is inteded for message passing between one or more systems in disconnected fashion. You can send a message somewhere and current or remote system picks it up for processing later when required. This paradigm somehow fits into CQRS and Message Passing architectural ideas.

To name a few examples, Apache Kafka, RabbitMQ, Azure Service Bus are all falling into this category - essentially they are designed to pass messages. Some systems are more advanced to others of course, but most often it doesn't really matter.

Storage.Net supports many messaging providers out of the box, including Azure Service Bus Topics and Queues, Azure Event Hub and others.

There are two abstractions available - message publisher and message receiver. As the name stands, one is publishing messages, and another is receiving them on another end.

Publishing Messages

To publish messages you will usually construct an instance of IMessagePublisher with an appropriate implementation. All the available implementations can be created using factory methods in the Storage.Net.StorageFactory.Messages class. More methods appear in that class as you reference an assembly containing specific implementations.

Receiving Messages

Similarly, to receive messages you can use factory methods to create receivers which all implement IMessageReceiver interface.

The primary method of this interface

Task StartMessagePumpAsync(
	Func<IEnumerable<QueueMessage>, Task> onMessageAsync,
	int maxBatchSize = 1,
	CancellationToken cancellationToken = default);

starts a message pump that listens for incoming queue messages and calls Func<IEnumerable<QueueMessage>, Task> as a call back to pass those messages to your code.

maxBatchSize is a number specifying how many messages you are ready to handle at once in your callback. Choose this number carefully as specifying number too low will result in slower message processing, whereas number too large will increase RAM requirements for your software.

cancellationToken is used to signal the message pump to stop. Not passing any parameter there will result in never stopping message pump. See example below in Use Cases for a pattern on how to use this parameter.

You can find the list of supported messaging implementations here.

Handling Large Messages

Storage.Net provides built-in capability to handle large message content by allowing you to offload message content over a certain threshold to an external blob storage. It works in the following way:

  1. Check that message content is larger than threshold value.
  2. If not, do the usual processing.
  3. If it is, upload message content as a blob to external storage, clear message content and add a custom header x-sn-large that points to the blob containing message content.

When receiving messages, it will check that x-sn-large header is present, and if so, will download blob, set it's content as message content, and return the message to the receiver.

Blob is deleted from the blob storage only when message is confirmed by the receiver.

Large message handling works on any supported queue implementation because it's implemented in the core library itself, outside of specific queue implementation. To enable it, call .HandleLargeContent on both publisher and receiver:

IBlobStorage offloadStorage = ...; // your blob storage for offloading content

IMessagePublisher publisher = StorageFactory.Messages
  .XXXPublisher(...)
  .HandleLargeContent(offloadStorage, thresholdValue);

IMessageReceiver receiver = StorageFactory.Messages
  .XXXReceiver(...)
  .HandleLargeContent(offloadStorage);

Serialising/deserialising QueueMessage

QueueMessage class itself is not a serialisable entity when we talk about JSON or built-in .NET binary serialisation due to the fact it is a functionally rich structure. However, you might want to transfer the whole QueueMessage across the wire sometimes. For these purposes you can use built-in binary methods:

var qm = new QueueMessage("id", "content");
qm.DequeueCount = 4;
qm.Properties.Add("key", "value");

byte[] wireData = qm.ToByteArray();

//transfer the bytes

QueueMessage receivedMessage = QueueMessage.FromByteArray(wireData);

These methods make sure that all of the message data is preserved, and also are backward compatible between any changes to this class.

Sponsorship

This framework is free and can be used for free, open source and commercial applications. Storage.Net (all code, NuGets and binaries) are under the MIT License (MIT). It's battle-tested and used by many awesome people and organisations. So hit the magic ⭐️ button, we appreciate it!!! �� Thx!

The core team members, Storage.Net contributors and contributors in the ecosystem do this open source work in their free time. If you use Storage.Net, and you'd like us to invest more time on it, please donate. This project increases your income/productivity/usabilty too.

Why charge/sponsor for open source?

Backers

Become a backer and show your support to our open source project.

Sponsors

Does your company use Storage.Net? Ask your manager or marketing team if your company would be interested in supporting our project. Support will allow the maintainers to dedicate more time for maintenance and new features for everyone. Also, your company's logo will show here - who doesn't want a little extra exposure?

Contributing

All contributions of any size and areas are welcome, being it coding, testing, documentation or consulting. The framework is heavily tested under stress with integration tests, in fact most of the code is tests, not implementation, and this approach is more preferred to adding unstable features.

PRs are raised against develop branch, master is for releases only.

All the builds (from PR or branches) are automatically generating NuGet packages which are placed into the following intermediate feed:

https://pkgs.dev.azure.com/aloneguid/AllPublic/_packaging/storagenet/nuget/v3/index.json

Builds from master branch publishes NuGet to nuget.org.

Code

Storage.Net tries to enforce idential behavior on all implementaions of storage interfaces to the smallest details possible and you will find a lot of test specifications which will help you to add another provider.

The solution is created in Visual Studio 2017 (Community Edition).

Documentation

When I think of the best way to document a framework I tend to think that working examples are the best. Adding various real world scenarios with working code is more preferrable than just documenting an untested API.

Reporting bugs or requesting features

Please use the GitHub issue tracker to do this.

Support

You can get support by raising an issue here, or contacting me directly for consulting services.

  • 翻译自cordova官方文档(如果需要链接,请自行对照原文链接进行查看): https://cordova.apache.org/docs/en/latest/cordova/storage/storage.html Storage(存储) Cordova Application支持很多用于存储的API。 在这里介绍的每种API都有各自的优势和劣势,你需要根据你的实际需要来选择最优方案。当然你也可

  • storageclass storageclass是一个存储类,通过创建storageclass可以动态生成一个存储卷供k8s用户使用。 [root@master ~]# kubectl explain storageclass KIND: StorageClass VERSION: storage.k8s.io/v1 DESCRIPTION: StorageClass de

  • 本文个人博客地址:https://www.huweihuang.com/kubernetes-notes/storage/storage-class.html StorageClass 1. StorageClass概述 StorageClass提供了一种描述存储类(class)的方法,不同的class可能会映射到不同的服务质量等级和备份策略或其他策略等。 StorageClass 对象中包含 p

  • Local Storage Local Storage,也叫本地存储,是 HTML5 中新增的 web 存储的功能,它解决了客户端存储的一些缺点,并提供更强大的功能和操作API。 Local Storage 有效期:永不失效,除非 web 应用主动删除。 // 清除指定 key window.localStorage.removeItem('key') // 清除所有 window.localSt

  • IE用户数据 在IE5.0中,微软通过一个自定义行为引入了持久化用户数据的概念。用户数据允许每个文档最多128KB数据,每个域名最多1MB数据。使用方式如下: <div style = "behavior:url(#default#userData)" id = "dataStore"></div> 首先使用CSS在指定元素上作处理,如上userData 获取该元素的引用,并使用setAttrib

  • k8s 对接ceph并使用StorageClass动态创建pvc 前提条件,已经安装ceph和k8s,具体环境信息如下: 一. 服务器环境 操作系统:centos 7.6 ceph版本:14.2.10(nautilus) k8s版本:v1.18.0 arch: ARM64 GO版本:go1.14.6 docker版本:19.03.12 在k8s中使用volume主要有两种使用方式,一种的静态方法,

 相关资料
  • 问题内容: 我想使用GCS存储桶作为blobstore的支持,但是我不知道如何在开发服务器上进行设置。 有使用实时服务器上的开发人员控制台执行此操作的说明,但是我在本地开发计算机上找不到有关如何执行此操作的任何信息… 问题答案: 事实证明,您根本不需要执行任何设置。我只是假设使用blobstore上传时有一个具有特定名称的名称,而其中一个是自动为我创建的。 顺便说一句,似乎没有任何地方记录着如何浏

  • 问题内容: 我一直在尝试加密文件,并将这些文件写回到同一位置。但是我收到错误消息说 我的档案是这个 我认为我已经提供了正确的许可。我用来加密文件的代码就是这个。 我在按钮内使用了这种方法 仍然我无法配置此错误。请有人帮忙! 问题答案: 我怀疑您运行的是Android 6.0棉花糖(API 23)或更高版本。在这种情况下, 必须先 实现运行时权限,然后才能尝试读取/写入外部存储。

  • 问题内容: Firebase存储在Firebase控制台中显示“错误加载预览” 最初,在上传和加载过程中,它在我的应用中运行良好。两天后,当我检查我的应用程序是否正常运行时。 Firebase控制台的屏幕截图: 我的图片上传代码: 我的图片加载代码: 如果您知道,请帮助我如何解决这个问题。 感谢Advance到Firebase专家 问题答案: 我刚刚就此问题通过电子邮件发送给Firebase团队。

  • 问题内容: 更新至后,此方法显示已弃用 ‘com.google.firebase:firebase-storage:15.0.2’ 官方网站上没有其他方法可以实现url,那么有什么方法可以以不推荐的方式实现Url? 问题答案: 在文档中它说: 该类的和方法现已弃用。使用from 代替。 因此,您需要在 异步检索具有可撤销令牌的长期下载URL。可以用于与他人共享文件,但是如果需要,开发人员可以在Fi

  • 问题内容: 我想开发一个Java应用程序(用于PC),可以将任何图片上传到Google Cloud Storage。尽管我整夜都在寻找解决方案,但是我不知道如何开始。你们中有人有将图像上传到Google Cloud Storage的经验吗?是否有更好的Google Cloud Storage替代品? 问题答案: 您可以公开文件,然后Blob的媒体链接可以在任何地方访问。 https://cloud

  • 问题内容: 我刚刚将项目更新为最新版本的Firebase Storage,现在收到警告:不建议使用downloadURL():使用StorageReference.downloadURLWithCompletion()获取当前的下载URL。 我看了看Firebase图片上传文档,但它仍然引用了现在使用的折旧价格。在下面的代码中,我将以字符串形式获取图像的下载URL。该代码有效,但由于已贬值,因此现

  • 问题内容: 我有一个CollectionView,我正在使用Firebase Storage中的图像进行填充。我将图像存储在“ userId”节点下。我想检查节点下可用的大量文件是否存在,因此可以将它们存储在数组中。 我试图分别为每个URL检索URL,但是,我认为这是一种非常错误的方法。但是,我不知道如何以最有效的方式做到这一点以及放在哪里。这是我所做的: 另外,将图像作为NSData来获取是否比

  • 本文向大家介绍H5的Web Storage带来什么好处?相关面试题,主要包含被问及H5的Web Storage带来什么好处?时的应答技巧和注意事项,需要的朋友参考一下 存储的数据量更大,可以达到 5M; 减少不必要的数据请求,不会自动把数据发送给服务器 localStorage 可以把数据永久保存在本地,除非显示的清除或删除数据 支持事件通知机制 API 更加方便