AAD GraphClient API添加成员资格非常慢

时间:2016-12-16 07:58:52

标签: c# azure-active-directory azure-ad-graph-api

我正在测试一个控制台应用程序,它实现了一个sql server数据库和一个Azure Active Directory之间的同步(组,用户,组到组关系,人与组之间的关系)

我发现将用户添加到组中的速度非常慢。有关信息,我有大约200000个用户的容量可以附加到大约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;
    }

1 个答案:

答案 0 :(得分:0)

你是怎么称呼这种方法的?由于Azure Graph客户端使用 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)}");
                });
            });
        });
}