1

场景

根据记录键是否存在于 CRM 中,从外部数据库创建或更新 CRM 中的记录。

平台CRM 2015 Online

方法 SSIS,带有 .Net 4 脚本组件

问题: 无论我做什么,我每秒都无法获得超过 1 条记录。我真的希望我做错了什么

我在做什么:

  1. 使用 Guid 和 Key 字段从 CRM 获取所有记录的列表。
  2. 将记录分成多个任务。
  3. 根据 (1) 中的先前列表中是否存在记录,使用 Create 或 Update 在每个任务中创建 ExecuteMultipleRequest。
  4. 为每个线程创建一个 OrganizationService(在连续线程循环样式之间重用(参见下面的代码))。
  5. 运行执行多个。
  6. 为速度哭泣。

结果似乎不会随着并行任务的数量或批量大小而变化。它基本上总是每秒大约 0.9-1.5 条记录。

我已经尝试过从 1 个线程(1000 件)到 16 个线程(每个线程 1 件)的所有方法。

这篇声称每秒 200-300 条记录是可能的帖子正在嘲讽我一些激烈的事情:邪恶的嘲讽博客帖子,每秒 300 条记录到 CRM 在线

项目中的代码片段(试图只复制可能相关的内容):

上下文创建。

 foreach (int i in Enumerable.Range(1, _MaxThreads * 2))
 {
    var crmConnection = CrmConnection.Parse(connectionString);
    var organisationservice = new OrganizationService(crmConnection);
    _OrgServiceList.Add(organisationservice);
 }

我如何创建我的任务:

private void ImportNewBatch(List<Customer> dataSet)
{
    var service = _OrgServiceList[_CurrentServicePosition];
    _CurrentServicePosition++;

    if (_CurrentServicePosition >= _OrgServiceList.Count)
        _CurrentServicePosition = 0;

    var aTask = new Task(() => WorkerThread(dataSet, service), TaskCreationOptions.None);
    aTask.Start();
    _RunningThreads.Add(aTask);

    if (_RunningThreads.Count >= _MaxThreads)
        Task.WaitAny(_RunningThreads.ToArray());

    _RunningThreads.RemoveAll(t => t.IsCompleted);
}

执行多个查询

var requestWithResults = new ExecuteMultipleRequest()
{
    Settings = new ExecuteMultipleSettings()
    {
        ContinueOnError = true,
        ReturnResponses = true
    },
    Requests = new OrganizationRequestCollection()
};

更新 1 从 Microsoft 获得了关于在线 CRM 的半非官方答案,其他人可能也会感兴趣:

  • 在线 CRM 的良好性能约为 10 条记录/秒。
  • 性能很大程度上取决于您是否有插件。
  • CRM Online 会限制多个查询,以便一次只能运行两 (2) 个查询,这两个查询之后的所有查询都将依次排队和处理。
  • CRM 检查您的 ip 和登录名,因此您无法绕过多个用户或单独上下文的限制。
  • 拥有更多许可证的解决方案将为您带来更高的性能,即,在所有其他条件相同的情况下,拥有 100 个许可证的实例将比拥有 5 个许可证的实例快。
4

4 回答 4

4

您将始终受到 Dynamics CRM Online 为您的实例提供的性能的限制。我知道在本地场景中,我已经能够实现每秒数万次插入(没有运行插件/工作流的正常记录。)

我不会尝试在您的代码中使用多线程,我会使用平衡数据分配器来实现所需的功能。这有点痛苦——因为你必须复制目的地,但它确实有效。

您可以在 Sonoma 合作伙伴的博客上阅读一些关于将Balanced Data Distributor 与 CRM 结合使用的亮点。我会在这里复制它,但它的代码不多,主要是图像。

于 2015-02-12T16:32:16.230 回答
3

您只能在 CRM 中同时拥有两个ExecuteMultipleRequest。因此,尝试拥有两个以上的线程是没有意义的。

ExecuteMultipelRequests确保最大化单个调用中正在执行的请求数。从您对您正在做什么的解释来看,听起来您一次只在 CRM 中放置一个更新/创建请求。

我还会检查以确保没有任何插件因您的导入而被执行。

也有点不确定您事先使用创建组织连接。如果您在单个请求中放入 1000 次更新(以每秒 1 次),则该单个请求需要将近 17 分钟才能完成。创建新服务在亚秒范围内,因此您不妨为每个请求创建一个新服务,以确保您没有多线程问题,因为组织服务不是多线程安全的。

于 2015-02-11T14:27:56.140 回答
1

无法轻松找到有关SSIS 脚本组件的多线程使用的信息,所以只有尝试一下才能帮助您。

这是您进行Task创作的方式:

var aTask = new Task(() => WorkerThread(dataSet, service), TaskCreationOptions.None);
aTask.Start();

在这里,您只提供要执行的委托,没有其他信息。默认情况下,该Script组件可能是单线程的,因此您的所有任务都直接在您的主线程中执行,而无需使用 ThreadPool

考虑Task提供的创建TaskScheduler.Default,因为它将使用它可以快速实现结果的全部资源:

TaskFactory.StartNew(delegate here, null, TaskCreationOptions.None, TaskScheduler.Default)

所以你的代码中的其他问题:

if (_RunningThreads.Count >= _MaxThreads)
    Task.WaitAny(_RunningThreads.ToArray());

这是一个不好的做法。默认情况下,ThreadPool它更清楚是否应该推进某些任务。

aTask.Start();

在此处考虑async\await使用,因为它对您的代码更有效。


更新:我认为不会ThreadPool同时启动的任务数量大于处理器数量。您可以通过检查它的内部特性轻松地在您的机器上检查它,但我记得,它4在每个时刻都在附近。

根据 MSDN

可以排队到线程池的操作数量仅受可用内存的限制;但是,线程池限制了进程中可以同时处于活动状态的线程数
从 .NET Framework 4 开始,进程的线程池的默认大小取决于几个因素,例如虚拟地址空间的大小。一个进程可以调用该GetMaxThreads方法来确定线程数。
您可以使用GetMaxThreadsSetMaxThreads方法控制最大线程数。

于 2015-02-10T10:27:44.173 回答
1

我必须不同意 Dayrl 关于 2 个线程的评论;在 On Premise CRM 中,2 线程限制不适用;不是每个公司或任何东西。我为同一家公司使用了最多 50 个线程的 executeMultiple。但是你必须小心不要通过同一个 OganizationProxy 发送多个 ExecuteMultiple 请求。正如 MSDN 文档所述,组织代理不是线程安全的。确保您在单独的代理上的最简单方法是构建组织代理池。或许这里的诀窍是,您将拥有多个 Web 服务器会话。

使用这种技术,我可以使 16 核 CRM 机器的 CPU 饱和并每秒推送插入,直到我的限制是 SQL 服务器的磁盘。我使用 CRM 本地实体执行此操作。即,如果您通过采用所有默认值在 CRM 中创建新实体。使用这项技术,我使用两台 16 CORE CRM FE 机器每秒实现了 3,900 次插入。这没有调整 .Net 线程池。

被忽视的白皮书Microsoft Dynamics CRM 2011 数据加载性能和可扩展性案例研究讨论了每台服务器使用 10 个线程。但是我已经在同一个服务器和同一个组织上使用了 10 多个带有 executeMutliple 的线程,以至于我在多台服务器上的 CPU 使用率达到了 97%。

于 2015-08-28T20:16:09.210 回答