使用MS Graph API操作Azure AD B2C测试需长延迟的原因排查
问题分析与解决方案
为什么现在需要添加延迟?
- Azure AD B2C属于分布式系统,写入操作(比如
EnableUser里的Patch更新)返回成功后,数据并不会立刻同步到所有读取节点——这是最终一致性的特性。之前同步延迟较短,测试能直接读到最新数据,但近期可能因为B2C服务负载调整、租户资源紧张等原因,同步窗口变长,直接查询会拿到未更新的旧数据,导致测试失败。 - 另外,你的
GetUserById是通过GetUsers加Filter实现的集合查询,Graph API对这类查询可能存在缓存机制,进一步加剧了读取旧数据的概率。
替代固定延迟的可靠方案:轮询重试
不要用固定10秒等待,换成带超时的轮询重试机制,直到读取到更新后的属性再继续测试,既保证通过率,又不会浪费不必要的等待时间:
[Test] public async Task EnableUser() { IlgAdUser b2CUser = await _graphClient.CreateLocalUser(false, false, USER_FIRSTNAME_S, USER_LASTNAME_S, "some-password", USR_EMAIL_S); b2CUser.AccountEnabled.Should().Be(false); await _graphClient.EnableUser(b2CUser.Id); // 替换固定延迟为轮询重试 IlgAdUser? loaded = null; var timeout = TimeSpan.FromSeconds(30); var startTime = DateTime.UtcNow; do { await Task.Delay(TimeSpan.FromSeconds(1)); loaded = await _graphClient.GetUserById(b2CUser.Id); if (loaded?.AccountEnabled == true) break; } while (DateTime.UtcNow - startTime < timeout); loaded.Should().NotBeNull(); loaded.AccountEnabled.Should().Be(true); loaded.Should().BeEquivalentTo(b2CUser, options => options.Excluding(u => u.AccountEnabled).ComparingByMembers<IlgAdUser>()); }
额外优化建议
- 改用单用户直接查询:把
GetUserById从集合Filter查询改成直接调用Graph API的单用户接口,绕过集合查询的缓存,能更快拿到最新数据:
public async Task<IlgAdUser?> GetUserById(string userId) { using (_logger.BeginScope(nameof(GetUserById))) { if (string.IsNullOrWhiteSpace(userId)) throw new ArgumentNullException(nameof(userId)); try { string[] selectAttributes = await MakeUserAttributesList().ConfigureAwait(false); var user = await _graphClient.Users[userId].GetAsync(config => { config.QueryParameters.Select = selectAttributes; }).ConfigureAwait(false); if (user == null) return null; // 复用你原有的User到IlgAdUser的映射逻辑 return MapToIlgAdUser(user); } catch (Exception ex) { LogFailedToLoadUserById(userId, ex); string errMsg = $"Could not get user with Id={userId}"; throw new IlgGraphClientException(errMsg, ex); } } }
- 检查租户状态:如果使用的是共享B2C租户,排查是否有其他大量操作导致服务响应变慢;如果是私有租户,确认是否存在资源配额限制或服务状态异常。
内容的提问来源于stack exchange,提问作者AlexB
相关产品推荐
相关产品推荐

