2017-06-22 13 views
0

在我們的應用程序中,我們的用戶流量很大,大約每秒2000個請求。 我們已經在Asp.Net內核中創建了應用程序並使用了精簡版。我們正在使用redis緩存管理器來實現分佈式緩存目的。 當我們主持這個網站並且每秒鐘檢查幾次(20或30)請求時,它工作正常。但是,當我們每秒的訪問次數超過50次時,網站會提供
502 - Web服務器在充當網關或代理服務器時收到無效響應。
我們將redis緩存更改爲內存緩存,然後它開始適用於每秒2000次的所有請求。 我們使用redis版本3.2.100 因此,在這裏使用redis,我們無法運行此網站以獲取更多請求,並在交通繁忙的情況下獲得502錯誤。對Redis的緩存使用redis實現的Asp.Net Core爲高流量提供502錯誤

using Common; 
using Common.DependencyInjection; 
using Newtonsoft.Json; 
using StackExchange.Redis; 
using System; 
using System.Text; 

namespace Service.Caching 
{ 
[TransientDependency(ServiceType = typeof(ICacheManager))] 
public class RedisCacheManager : ICacheManager 
{ 
    private readonly string _redisHost; 
    private readonly int _redisPort; 
    private readonly string _redisPassword; 
    private readonly ConfigurationOptions _configurationOptions; 

    public RedisCacheManager() 
    { 
     _redisHost = ConfigItems.RedisHost; 
     _redisPassword = ConfigItems.RedisPassword; 
     _redisPort = ConfigItems.RedisPort; 

     _configurationOptions = new ConfigurationOptions(); 
     configurationOptions.EndPoints.Add(_redisHost, redisPort); 
     _configurationOptions.Ssl = false; 
     //_configurationOptions.Password = _redisPassword; 
     _configurationOptions.AbortOnConnectFail = false; 
     _configurationOptions.SyncTimeout = int.MaxValue; 
     _configurationOptions.DefaultVersion = new Version(2, 8, 8); 
     _configurationOptions.WriteBuffer = 10000000; 
     _configurationOptions.KeepAlive = 180; 
    } 

    /// <summary> 
    /// Gets or sets the value associated with the specified key. 
    /// </summary> 
    /// <typeparam name="T">Type</typeparam> 
    /// <param name="key">The key of the value to get.</param> 
    /// <returns> 
    /// The value associated with the specified key. 
    /// </returns> 
    public T Get<T>(string key) 
    { 
     using (var connection = ConnectionMultiplexer.Connect(_configurationOptions)) 
     { 
      var db = connection.GetDatabase(-1); 
      //return (T)(object)db.StringGet(key); 

      return (T)ConvertToObject<T>(db.StringGet(key)); 
     } 
    } 

    /// <summary> 
    /// Adds the specified key and object to the cache. 
    /// </summary> 
    /// <param name="key">key</param> 
    /// <param name="data">Data</param> 
    /// <param name="cacheTime">Cache time</param> 
    public void Set(string key, object data, int cacheTime) 
    { 
     if (data == null) 
      return; 

     DateTime expireDate; 
     if (cacheTime == 99) 
      expireDate = DateTime.Now + TimeSpan.FromSeconds(30); 
     else 
      expireDate = DateTime.Now + TimeSpan.FromMinutes(cacheTime); 

     var value = (RedisValue)ConvertToByteArray(data); 

     using (var connection = ConnectionMultiplexer.Connect(_configurationOptions)) 
     { 
      var db = connection.GetDatabase(-1); 
      db.StringSet(key, value, new TimeSpan(expireDate.Ticks)); 
     } 
    } 

    /// <summary> 
    /// Gets a value indicating whether the value associated with the specified key is cached 
    /// </summary> 
    /// <param name="key">key</param> 
    /// <returns> 
    /// Result 
    /// </returns> 
    public bool IsSet(string key) 
    {    
     using (var connection = ConnectionMultiplexer.Connect(_configurationOptions)) 
     { 
      var db = connection.GetDatabase(-1); 
      return db.KeyExists(key); 
     } 
    } 

    /// <summary> 
    /// Removes the value with the specified key from the cache 
    /// </summary> 
    /// <param name="key">/key</param> 
    public void Remove(string key) 
    { 
     using (var connection = ConnectionMultiplexer.Connect(_configurationOptions)) 
     { 
      var db = connection.GetDatabase(-1); 
      db.KeyDelete(key); 
     } 
    } 

    /// <summary> 
    /// Removes items by pattern 
    /// </summary> 
    /// <param name="pattern">pattern</param> 
    public void RemoveByPattern(string pattern) 
    {    
     using (var connection = ConnectionMultiplexer.Connect(_configurationOptions)) 
     { 
      var server = connection.GetServer(_redisHost, _redisPort); 
      var keysToRemove = server.Keys(pattern: "*" + pattern + "*");//-1, pattern); 
      foreach (var key in keysToRemove) 
       Remove(key); 
     } 
    } 

    /// <summary> 
    /// Clear all cache data 
    /// </summary> 
    public void Clear() 
    { 
     using (var connection = ConnectionMultiplexer.Connect(_configurationOptions)) 
     { 
      var server = connection.GetServer(_redisHost, _redisPort); 
      //var keysToRemove = server.Keys(-1); 
      var keysToRemove = server.Keys(); 
      foreach (var key in keysToRemove) 
       Remove(key); 
     } 
    } 

    /// <summary> 
    /// Converts to byte array. 
    /// </summary> 
    /// <param name="data">The data.</param> 
    /// <returns>System.Byte[].</returns> 
    private byte[] ConvertToByteArray(object data) 
    { 
     if (data == null) 
      return null; 

     string serialize = JsonConvert.SerializeObject(data); 
     return Encoding.UTF8.GetBytes(serialize); 
    } 

    /// <summary> 
    /// Converts to object. 
    /// </summary> 
    /// <param name="data">The data.</param> 
    /// <returns>System.Object.</returns> 
    private T ConvertToObject<T>(byte[] data) 
    { 
     try 
     { 
      return JsonConvert.DeserializeObject<T>(Encoding.UTF8.GetString(data)); 
     } 
     catch (Exception ex) 
     { 
      return (T)Activator.CreateInstance(typeof(T)); 
     } 
    } 
} 

}

回答

1

你要調用編寫

代碼入門/設置/從Redis的緩存中刪除鍵/值可能會需要更長的時間,你在每個操作創建一個新的ConnectionMultiplexer到Redis。

https://gist.github.com/JonCole/925630df72be1351b21440625ff2671f#file-redis-bestpractices-stackexchange-redis-md在使用StackExchange.Redis時有一些最佳實踐。

https://docs.microsoft.com/en-us/azure/redis-cache/cache-dotnet-how-to-use-azure-redis-cache#connect-to-the-cache顯示推薦的使用模式。

而且,看StackExchange.Redis文檔(https://stackexchange.github.io/StackExchange.Redis/Basics),它說「ecause的ConnectionMultiplexer做了很多,它的目的是共享和調用者之間重用。你不應該創建每個操作的ConnectionMultiplexer,它是完全線程-safe並準備好了這個用法,在後面的所有例子中,假設你有一個ConnectionMultiplexer實例被存儲以供重用。

相關問題