2017-06-22 10 views
0

アプリケーションでは、ユーザーのトラフィックが非常に多く、毎秒約2000件のリクエストがあります。 Asp.Netコアでアプリケーションを作成し、dapperを使用しました。我々は、分散キャッシュの目的のためにredisキャッシュマネージャを使用しています。 私たちがこのサイトをホストして、毎秒リクエスト数が少ない(20または30)ことを確認したところ、うまくいきました。しかし、毎秒約50件以上のリクエストが発生した場合、サイトには
502がゲートウェイまたはプロキシサーバーとして機能している間に無効な応答を受信しました。
redisキャッシュをメモリキャッシュに変更した後、毎秒2000回のすべての要求に対して正常に動作するようになりました。 Redisバージョン3.2.100を使用しています ここではredisを使用して、より多くのリクエストに対してこのサイトを実行し、トラフィックが多い場合に502エラーを取得することはできません。 RedisのキャッシュRedisを実装したAsp.Netコアは、トラフィックが多い場合に502エラーを返します。

Redisのキャッシュからのキー/値を使用して、各操作に新しいConnectionMultiplexerを作成していると時間がかかっされる可能性があります削除/設定/取得に
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

あなたの呼び出しのために書かれた

コードレディスに。

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)を見ると、「ConnectionMultiplexerは多くのことを行います。呼び出し元間で共有され、再利用されるように設計されています。 -safeとこの使用の準備ができています。すべての後続の例では、再利用のために保存されたConnectionMultiplexerインスタンスがあると想定されます。

関連する問題