2015-07-09 24 views
6

Önbellekten bilgi almak için kullandığım aşağıdaki kod var. Uygulamamın çok fazla bağlantı açıp açmayacağını bilmiyorum ya da sadece bu hata azure redis önbelleğinde geçici bir başarısızlıktan kaynaklanıyor. Bu hizmet hizmet için bağlantı yok: Azure Redis Önbellek kullanılırken

Bu

yığın izleme

[RedisConnectionException GET UserProfileInformation|[email protected]: Bağlantı Bu işlemi hizmet kullanılabilir] olduğu StackExchange.Redis.ConnectionMultiplexer.ExecuteSyncImpl (Mesaj c mesajı ResultProcessor 1 processor, ServerEndPoint server) in c:\TeamCity\buildAgent\work\3ae0647004edff78\StackExchange.Redis\StackExchange\Redis\ConnectionMultiplexer.cs:1922 StackExchange.Redis.RedisBase.ExecuteSync(Message message, ResultProcessor 1 işlemci, ServerEndPoint sunucusu): \ TeamCity \ buildAgent iş \ \ 3ae0647004edff78 \ StackExchange.Redis \ Stack Exchange \ Redis RedisBase.cs \: 80 StackExchange.Redis.RedisDatabase.StringGet (RedisKey anahtarı CommandFlags bayraklar) C: \ TeamCity \ buildAgent iş \ \ 3ae0647004edff78 \ StackExchange.Redis \ Stack Exchange \ Redis RedisDatabase.cs \: 1431 xx.Utils.SampleStackExchangeRedisExtensions.Get (IDatabase önbellek, Yaylı anahtar) C: \ Proyectos \ xx \ xx \ utils \ SampleStackExchangeRedisExtensions.cs: 20
xx.Cache.UserProfile.GetUserProfile C (string identityname): \ Proyectos \ xx \ xx \ Cache \ UserProfile.cs: 22
x.Controllers.UserProfileController.GetPropertiesForUser () C: \ Proyectos \ xx \ xx \ Kontrol UserProfileController.cs \: +61
System.Web.Mvc.ActionMethodDispatche) 16
lambda_method (Kapatma, ControllerBase, Nesne [] r.Execute (ControllerBase kontrolör, Nesne [] parametreler) +14

Ve bu kodu olan

public static Models.UserProfile GetUserProfile(string identityname) 
     { 
      /// It needs to be cached for every user because every user can have different modules enabled. 

      var cachekeyname = "UserProfileInformation|" + identityname; 
      IDatabase cache = CacheConnectionHelper.Connection.GetDatabase(); 
      Models.UserProfile userProfile = new Models.UserProfile(); 
      object obj = cache.Get(cachekeyname); 
      string userProfileString; 
      if (obj != null) 
      { 
       //get string from cache 
       userProfileString = obj.ToString(); 

       //conver string to our object 
       userProfile = JsonConvert.DeserializeObject<Models.UserProfile>(userProfileString); 
       return userProfile; 
      } 
      else 
      { 
       #region Get User Profile from AD 
       Uri serviceRoot = new Uri(SettingsHelper.AzureAdGraphApiEndPoint); 
       var token = AppToken.GetAppToken(); 

       ActiveDirectoryClient adClient = new ActiveDirectoryClient(
       serviceRoot, 
       async() => await AppToken.GetAppTokenAsync()); 

       string userObjectID = ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier").Value; 

       Microsoft.Azure.ActiveDirectory.GraphClient.Application app = (Microsoft.Azure.ActiveDirectory.GraphClient.Application)adClient.Applications.Where(
        a => a.AppId == SettingsHelper.ClientId).ExecuteSingleAsync().Result; 
       if (app == null) 
       { 
        throw new ApplicationException("Unable to get a reference to application in Azure AD."); 
       } 

       string requestUrl = string.Format("https://graph.windows.net/{0}/users/{1}?api-version=1.5", SettingsHelper.Tenant, identityname); 
       HttpClient hc = new HttpClient(); 
       hc.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token); 
       HttpResponseMessage hrm = hc.GetAsync(new Uri(requestUrl)).Result; 

       if (hrm.IsSuccessStatusCode) 
       { 
        Models.UserProfile currentUserProfile = JsonConvert.DeserializeObject<Models.UserProfile>(hrm.Content.ReadAsStringAsync().Result); 

        //convert object to json string 
        userProfileString = JsonConvert.SerializeObject(currentUserProfile); 

        cache.Set(cachekeyname, userProfileString, TimeSpan.FromMinutes(SettingsHelper.CacheUserProfileMinutes)); 
        return currentUserProfile; 
       } 
       else 
       { 
        return null; 
       } 
       #endregion 
      } 
     } 




public static class SampleStackExchangeRedisExtensions 
    { 
     public static T Get<T>(this IDatabase cache, string key) 
     { 
      return Deserialize<T>(cache.StringGet(key)); 
     } 

     public static object Get(this IDatabase cache, string key) 
     { 
      return Deserialize<object>(cache.StringGet(key)); 
     } 

     public static void Set(this IDatabase cache, string key, object value, TimeSpan expiration) 
     { 
      cache.StringSet(key, Serialize(value), expiration); 
     } 

     static byte[] Serialize(object o) 
     { 
      if (o == null) 
      { 
       return null; 
      } 
      BinaryFormatter binaryFormatter = new BinaryFormatter(); 
      using (MemoryStream memoryStream = new MemoryStream()) 
      { 
       binaryFormatter.Serialize(memoryStream, o); 
       byte[] objectDataAsStream = memoryStream.ToArray(); 
       return objectDataAsStream; 
      } 
     } 

     static T Deserialize<T>(byte[] stream) 
     { 
      BinaryFormatter binaryFormatter = new BinaryFormatter(); 
      if (stream == null) 
       return default(T); 

      using (MemoryStream memoryStream = new MemoryStream(stream)) 
      { 
       T result = (T)binaryFormatter.Deserialize(memoryStream); 
       return result; 
      } 
     } 

Sorular şunlardır: 1. Nasıl gösterilen gibi bir bağlantı istisna kontrol edebilirsiniz Böylece kullanıcı hatayı almaz ve bunun yerine redis kullanılamıyorsa DB'ye gider? 2. Azure redis önbellek için geçici hata işleme ile tekrar denemek için zaten var mı?

cevap

8

Bunların geçici hatalar olduğuna inanıyorum. Basit yeniden deneme mantığını uygulamaya koymadan önce bunların çoğunu uygulama günlüklerimde gördüm. Ayrıca birkaç zaman aşımına da sahibim. Çok basit bir yeniden deneme mantığı, artı syncTimeout=3000 ekleyerek bağlantı dizgisini reddetmek için tüm bunları benim için çözdü.

Ayrıca
public object Get(string key) 
{ 
    return Deserialize(Cache.StringGet(key)); 
} 

public object GetWithRetry(string key, int wait, int retryCount) 
{ 
    int i = 0; 
    do 
    { 
     try 
     { 
      return Get(key); 
     } 
     catch (Exception) 
     { 
      if (i < retryCount + 1) 
      { 
       Thread.Sleep(wait); 
       i++; 
      } 
      else throw; 
     } 
    } 
    while (i < retryCount + 1); 
    return null; 
} 
2

Bu özel durumla tüm işlemleri yeniden denemek için Önbellek Deposu'nda Polly kullanıyorum. Polly'den Retry yöntemini denedim, ancak bu yanlış karar ve şimdi WaitAndRetry kullanıyorum. Bazı uyku süresi ile işlemi tekrar deneyebilir Bu yöntemle - bununla size operasyon için Redis son sürüme paketi Nuget

0

Güncelleme REDIS için sıraya olabilir ve mayın yaptığı gibi sorununuzu çözmelidir!