ASP.NET Core 使用 Redis 和 Protobuf 進行 Session 快取

Savorboard發表於2016-06-17

前言

上篇博文介紹了怎麼樣在 asp.net core 中使用中介軟體,以及如何自定義中介軟體。專案中剛好也用到了Redis,所以本篇就介紹下怎麼樣在 asp.net core 中使用 Redis 進行資源快取和Session快取。 如果你覺得對你有幫助的話,不妨點個【推薦】。

目錄

  • Redis 介紹
  • asp.net core Session 介紹
  • Redis & Session 例項講解
  • Session的使用
  • 使用 Protobuf 給 Session新增擴充套件方法

Redis 介紹

下面是Redis官網的介紹:

Redis is an open source (BSD licensed), in-memory data structure store, used as database, cache and message broker. It supports data structures such as strings, hashes, lists, sets, sorted sets with range queries, bitmaps, hyperloglogs and geospatial indexes with radius queries. Redis has built-in replication, Lua scripting, LRU eviction, transactions and different levels of on-disk persistence, and provides high availability via Redis Sentinel and automatic partitioning with Redis Cluster.

Redis 是一個開源的(基於BSD許可),記憶體資料儲存結構,常用作資料庫,快取,和訊息佇列。它支援如字串、雜湊表、列表、集合、排序集範圍查詢、點陣圖、hyperloglogs半徑和地理空間索引與查詢。Redis內建主從連線,Lua指令碼、LRU回收,事務和不同級別檔案持久化,並提供了利用叢集的主從切換和自動分割槽等來保證高可用性。

Redis的深入介紹我就直接開傳送門了,不是本篇的重點,但是我給你們整理了一下,你們還是要感謝我滴:

redis 高可用部署及監控:http://blog.sina.com.cn/s/blog_75ad98f30101fwqj.html
redis 主從連線:http://www.tuicool.com/articles/fAnYFb
redis 事務: http://redisbook.readthedocs.io/en/latest/feature/transaction.html
redis 記憶體回收LRU:http://www.open-open.com/lib/view/open1427547789059.html
redis 資料持久化:http://qifuguang.me/2015/10/13/Redis%E6%8C%81%E4%B9%85%E5%8C%96/

以上知識學習完,使用和麵試時應付Redis的提問應該不成問題了。

asp.net core session 介紹

session本身是一個很難解釋的名詞,在http中session代表伺服器與瀏覽器的一次會話過程,這個過程可能一直,也可能間斷的。

asp.net core中的session以中介軟體的方式提供給我們來使用。

下面來看一下使用方法:
首先,新增session的NuGet包Microsoft.AspNetCore.Http.Abstractions到專案中,在startup.cs檔案的ConfigureServices(IServiceCollection services)函式中,使用app.UseSession()app.UseCaching()來使用session.

//在使用session之前要注入cacheing,因為session依賴於cache進行儲存
services.AddCaching();

services.AddSession();

新增了session之後就需要有儲存session的地方,可以使用記憶體儲存,也可以使用其他自定義儲存,比如redis或者SQL Server等。

// 重要: session的註冊必須在UseMvc之前,因為MVC裡面要用 
app.UseSession();

app.UseMvc(routes =>
{
    routes.MapRoute(
        name: "default",
        template: "{controller}/{action}/{id?}",
        defaults: new { controller = "Home", action = "Index" });
});

Redis & Session 例項講解

要在Session中使用Redis,只需要把services.AddCaching();換成services.AddDistributedRedisCache();就可以了,如下:

services.AddDistributedRedisCache(option => 
    {
    //redis 資料庫連線字串
        option.Configuration = Configuration.GetConnectionString("RedisConnection");
        
        //redis 例項名
        option.InstanceName = "master";
    }
);

Session的使用

在 asp.net core 的 MVC Controller 中,你可以HttpContext.Session來獲取Session物件。

如果不是在 Controller 中需要使用 Session 的話,可以使用IHttpContextAccessor這個介面通過注入的方式來獲取Session。

以下是在 Controller 中使用Session,需要引入Microsoft.AspNetCore.Http空間:

public class HomeController : Controller
{
    public IActionResult Index()
    { 
        HttpContext.Session.SetString("Test", "Ben Rules!");
        return View();
    }

    public IActionResult About()
    {
        ViewBag.Message = HttpContext.Session.GetString("Test");

        return View();
    }
}

以下是在除了 Controller 的其他地方使用 Session:

public class SomeOtherClass
{
    private readonly IHttpContextAccessor _httpContextAccessor;
    private ISession _session => _httpContextAccessor.HttpContext.Session;

    public SomeOtherClass(IHttpContextAccessor httpContextAccessor)
    {
        _httpContextAccessor = httpContextAccessor;
    }

    public void TestSet()
    {
        _session.SetString("Test", "Ben Rules!");
    }

    public void TestGet()
    {
        var message = _session.GetString("Test");
    }
}

使用 Protobuf 給 Session新增擴充套件方法

預設情況下,我們只能儲存byte[]到我們的Session當中,這讓我們使用起來很不方便,在Microsoft.HttpCore.Extension中 Microsoft 給提供了一個SetString,SetInt32 和GetString,GetInt32的方法,但是在很多情況下,我們是需要使用Session來儲存一個物件的,那麼此時就需要給Session新增一個擴充套件方法。

為了追求效率和效能,我們選擇Google的Protobuf序列化元件,而不使用Json.Net,在效能方面,Protobuf要比XML或者Json效率高很多。

在Nuget包中引入protobuf-net

public static class SessionExtensions
{
        public static T Get<T>(this ISession session, string key) where T : class {
            byte[] byteArray = null;
            if (session.TryGetValue(key, out byteArray)) {
                using (var memoryStream = new MemoryStream(byteArray)) {
                    var obj = ProtoBuf.Serializer.Deserialize<T>(memoryStream);
                    return obj;
                }
            }
            return null;
        }

        public static void Set<T>(this ISession session, string key, T value) where T : class {
            try {
                using (var memoryStream = new MemoryStream()) {
                    ProtoBuf.Serializer.Serialize(memoryStream, value);
                    byte[] byteArray = memoryStream.ToArray();
                    session.Set(key, byteArray);
                }
            }
            catch (Exception) {
                throw;
            }
           
        }
}

使用Protobuf-net序列化,需要在序列化的物件打上[ProtoContract][ProtoMember]等標記。

Ps:目前Redis的擴充套件Microsoft.Extensions.DependencyInjection下面的AddDistributedRedisCache還不支援RC2,可以去github上搜尋原始碼,新增到專案中,也可以留下郵箱,我會發給你。


本文地址:http://www.cnblogs.com/savorboard/p/5592948.html
作者部落格:Savorboard
歡迎轉載,請保留出處

相關文章