2016-12-16 61 views
1

我正在測試一個控制檯應用程序實現的SQL Server數據庫和Azure的活動目錄(組,用戶,組與組的關係,人與組的關係)AAD GraphClient API添加會員很慢

之間的同步

我發現將用戶添加到組是非常緩慢的。有關信息,我有一個容量約爲20萬的用戶可以附加到約5000個組。

這裏是我的代碼示例一:

public static Dictionary<string, string> AddUsersToGroup(string groupName, string groupId, Dictionary<string, string> personToAddNames) 
{ 
    try 
    { 
     Dictionary<string, string> result = new Dictionary<string, string>(); 
     bool l_contextChanged = false; 

     // Get the group from its name 
     Group group = SearchGroup(groupName, groupId); 

     if (group != null) 
     { 
      foreach (KeyValuePair<string, string> personName in personToAddNames) 
      { 
       // Get the user from its name 
       User person = SearchUser(personName.Value, personName.Key); 
       if (person != null) 
       { 
        try 
        { 
         // check if the user already belongs to the group 
         if (_fullSync || !ExistUserInGroup(group, person)) 
         { 
          group.Members.Add(person); 
          l_contextChanged = true; 
         } 

         // Add the result to the dictionary (Argos Id + AAD Id) 
         result.Add(personName.Key, person.ObjectId); 
        } 
        catch (Exception e) 
        { 
        ... 
        } 
       } 
      } 

      // Save all the modifications on the group 
      if (l_contextChanged) 
      { 
       group.UpdateAsync().Wait(); 
      } 
     } 

     return result; 
    } 
    catch (Exception e) 
    { 
     ... 
    } 
} 

是否有將用戶添加到組,這將是另一種速度更快的方法?

UPDATE 我意識到通過將異步點應用於GraphClient API的操作但未獲得性能的測試:6000個用戶需要1小時。

據認爲,一組中加入的人數是可變的,從1到X

這裏是我的代碼示例:

public static Dictionary<string, string> AddUsersToGroup(string nomGroupe, string idGroupe, Dictionary<string, string> listeNomPersonneAAjouter) 
    { 
     try 
     { 
      Dictionary<string, string> resultat = new Dictionary<string, string>(); 
      bool l_contextChanged = true; 

      // Obtient le groupe depuis son nom pour avoir son id 
      Group groupePourAjoutUtilisateur = SearchGroup(nomGroupe, idGroupe); 

      if (groupePourAjoutUtilisateur != null) 
      { 
       Dictionary<Task<string>, string> l_taskNomPersonne = new Dictionary<Task<string>, string>(); 
       foreach (KeyValuePair<string, string> nomMailPersonneAAjouter in listeNomPersonneAAjouter) 
       { 
        l_taskNomPersonne.Add(AddUserToGroupAsync(groupePourAjoutUtilisateur, nomMailPersonneAAjouter.Key, nomMailPersonneAAjouter.Value), nomMailPersonneAAjouter.Key); 
       } 

       Task.WaitAll(l_taskNomPersonne.Keys.ToArray()); 

       foreach(KeyValuePair<Task<string>, string> l_task in l_taskNomPersonne) 
       { 
        resultat.Add(l_task.Value, l_task.Key.Result); 
       } 

       groupePourAjoutUtilisateur.UpdateAsync().Wait(); 

      } 

      return resultat; 
     } 
     catch (Exception e) 
     { 
      throw new ApplicationException(String.Format("Impossible d'ajouter la liste d'utilisateur au groupe {0} - {1} {2}", 
       nomGroupe, e.Message, e.InnerException != null ? e.InnerException.Message : String.Empty)); 
     } 
    } 


public static async Task<string> AddUserToGroupAsync(Group groupePourAjoutUtilisateur, string nomPersonneAAjouter, string mailPersonneAAjouter) 
    { 
     string l_return = string.Empty; 

     // Obtient l'utilisateur depuis son nom pour avoir son id 
     User personneAAjouter = SearchUser(mailPersonneAAjouter, nomPersonneAAjouter); 
     if (personneAAjouter != null) 
     { 
      try 
      { 
       // On vérifie que la personne n'existe pas déjà dans le groupe 
       // si on est en exécution différentielle 
       if (_fullSync || !ExistUserInGroup(groupePourAjoutUtilisateur, personneAAjouter)) 
       { 
        groupePourAjoutUtilisateur.Members.Add(personneAAjouter); 
       } 

       // retourne l'id AAD de la personne 
       l_return = personneAAjouter.ObjectId; 
      } 
      catch (Exception e) 
      { 
       Logs.Logger.Error(String.Format("Une erreur s'est produite lors du rattachement de l'utilisateur {0} au groupe {1}", 
        personneAAjouter.DisplayName, groupePourAjoutUtilisateur.DisplayName), 
        new Exception(String.Format("{0} - {1}", e.Message, e.InnerException.Message))); 
      } 
     } 

     return l_return; 
    } 

回答

0

你是如何調用該方法?由於Azure的圖形用戶正在使用的HTTP請求執行REST API,你可以考慮使用 異步編碼。而且我們也可以使用多線程來提高性能。

我也做了一個測試,以插入200個用戶,並將其添加到一個組。它花費大約10秒鐘。

這是給你參考代碼:

public async Task<string> AddUser(string accessToken, string displayName) 
{    
     try 
     { 
      HttpClient client = new HttpClient(); 
      var user = new User 
      { 
       accountEnabled = true, 
       displayName = displayName, 
       mailNickname = displayName, 
       passwordProfile = new PasswordProfile 
       { 
        password = "asdf123(", 
        forceChangePasswordNextLogin = false 
       }, 

       userPrincipalName = $"{displayName}@adfei3.onmicrosoft.com" 
      }; 


      var bodyContent = new StringContent(new JavaScriptSerializer().Serialize(user), Encoding.UTF8, "application/json"); 

      client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("bearer", accessToken); 

      HttpResponseMessage responseMessage = await client.PostAsync(addUserRequestUri, bodyContent); 
      var responseString = await responseMessage.Content.ReadAsStringAsync(); 

      var objectId = JObject.Parse(responseString)["objectId"].Value<string>(); 
      Console.ForegroundColor = ConsoleColor.Green; 
      Console.WriteLine($"OK:{displayName}|Task{Thread.CurrentThread.ManagedThreadId}"); 
      return objectId; 
     } 
     catch (Exception ex) 
     { 
      Console.ForegroundColor = ConsoleColor.Red; 
      Console.WriteLine($"Failed:{displayName}|Task{Thread.CurrentThread.ManagedThreadId}"); 
      return ""; 
     } 
} 

public async Task AddMember(string accessToken, string groupId, string objectId) 
{ 
     if (string.IsNullOrEmpty(objectId)) 
      return; 
     try 
     { 
      HttpClient client = new HttpClient(); 


      var bodyContent = new StringContent(String.Format("{{\"url\": \"https://graph.windows.net/adfei3.onmicrosoft.com/directoryObjects/{0}\"}}", objectId), Encoding.UTF8, "application/json"); 

      client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("bearer", accessToken); 

      Uri addMemberRequestUri = new Uri(String.Format(addMemberRequestString, groupId)); 

      HttpResponseMessage responseMessage = await client.PostAsync(addMemberRequestUri, bodyContent); 

      if (responseMessage.StatusCode == System.Net.HttpStatusCode.NoContent) 
      //return new MemberInfo { GroupId = groupId, UserInfo = userInfo, OK = true }; 
      { 
       Console.ForegroundColor = ConsoleColor.Green; 
       Console.WriteLine($"OK:{objectId}|Task{Thread.CurrentThread.ManagedThreadId}"); 
      } 
      else 
      { 
       Console.ForegroundColor = ConsoleColor.Red; 
       Console.WriteLine($"Failed:{objectId}|Task{Thread.CurrentThread.ManagedThreadId}"); 
      } 
     } 
     catch (Exception ex) 
     { 
      Console.ForegroundColor = ConsoleColor.Red; 
      Console.WriteLine($"Failed:{objectId}|Task{Thread.CurrentThread.ManagedThreadId}"); 
     } 
} 

public void Test() 
{ 
     DateTime beginTime = DateTime.Now; 
     string accessToken = ""; 
     string groupId = "92374923-09a2-4e74-a3f2-57bbbafacc8b"; 

     Parallel.ForEach(Enumerable.Range(1, 200), i => 
     { 
      AddUser(accessToken, "users" + i).ContinueWith(userId => 
      { 
       AddMember(accessToken, groupId, userId.Result).ContinueWith(a=> {      
        Console.ForegroundColor = ConsoleColor.Yellow; 
        Console.WriteLine($"Total time:{ DateTime.Now.Subtract(beginTime)}"); 
       }); 
      }); 
     }); 
} 
+0

你好,謝謝你的回答,我已經更新了我的帖子來回答你。 –