ServiceNow表API返回重复/不返回所有记录

本文关键字:返回 记录 API ServiceNow | 更新日期: 2023-09-27 18:02:53

我试图将所有数据从ServiceNow CMDB数据表中拉到我自己的SQL数据库中。我计划在需要与新的SN实现同步的客户遗留系统中维护数据时,将其用于自动更新。

我们的SN环境有许多域,许多客户等。这意味着大量的数据。尝试在单个API调用中提取所有记录自然会导致超时异常,因为数据太大。Web API建议批处理数据,这就是我所实现的:

        ...
        var offset = 0;
        while (true)
        {
            var requestUrl = string.Format("{0}/api/now/table/cmdb_ci_vm_instance?sysparm_offset={1}&sysparm_limit={2}&sysparm_exclude_reference_link=true", url, offset, batchSize);
            var result = ApiRequest.Get(new Uri(requestUrl), _credential, null, out response);
            if (result == HttpStatusCode.OK)
            {
                var virtualmachineRo = JsonConvert.DeserializeObject<VirtualMachineRootObject>(response);
                if (virtualmachineRo.result.Count < batchSize)
                {
                    virtualmachines.AddRange(virtualmachineRo.result);
                    break;
                }
                virtualmachines.AddRange(virtualmachineRo.result);
                offset += virtualmachineRo.result.Count;
            }
            else
            {
                break;
            }
        }
        ....

我使用过不同的批量大小,它给了我不同的结果。这取决于我碰到的是哪个表,有时会得到重复的,有时不会,有时会得到不同的重复的。在几乎所有情况下,当我DO获得一个副本时,该副本将替换流中的一个有效记录,这意味着我"丢失"了一个有效记录。

我通过查看来自serviceNow的原始数据流并查看重复项来确认这一点,并验证serviceNow中是否有记录没有显示在我的流中(这通常是在我尝试创建缺失记录和SN响应时发现的"忽略-没有字段更改"表明记录已经存在)

我试图搜索并找到任何有类似问题的人,但没有找到任何东西。在直接打开SN的票证之前,我希望看看我的代码是否做错了什么,或者这似乎是我所期望的——一个与平台相关的错误。

ServiceNow表API返回重复/不返回所有记录

所以这几乎可以肯定是他们的API中与服务帐户访问相关的错误。以下是我所做的,以及我认为正在发生的事情(以及我的工作!)

在尝试了一些不同的逻辑之后,我遇到了以下情况:

{0}/api/now/table/cmdb_ci_vm_instance?sysparm_offset=0&sysparm_limit=750&sysparm_exclude_reference_link=true&sysparm_query=ORDERBYsys_id
2016-08-19 12:46:15,277 [INFO ] Returned Records Count: 750
{0}/api/now/table/cmdb_ci_vm_instance?sysparm_offset=750&sysparm_limit=750&sysparm_exclude_reference_link=true&sysparm_query=ORDERBYsys_id
2016-08-19 12:46:28,243 [INFO ] Returned Records Count: 746

注意,在第二次传递中,我要求750条记录,但只得到746条(差4)。其他批次继续像往常一样返回750条,最后我在检索的5200多条记录中精确地获得了4条重复记录。因为第二遍返回的值小于我要求的750,我的代码因为认为数据是完整的而中断了。

为了解决这个问题(最初),我对上面的代码做了以下操作:
if (virtualmachineRo.result.Count == 0)
{
    //AddRange(virtualmachineRo.result);
    break;
}

我不再相信仅仅因为返回的记录数量少于sysparm_limit,我就检索了所有记录。

看起来当数据从数据库中取出时,一个单独的进程根据您的权限过滤数据。因此,第二批删除4条记录-但数据库不知道任何更好的…因此,在下一次传递时,当我通过从746调用返回的实际计数增加偏移量时,它返回相同的数据集,并且批处理的最后4条记录与下一页数据中的前4条记录相同。(在数据流中确认-在排序数据时,会导致重复的数据出现在不同的地方,并且根据批量大小/顺序也会复制不同的记录!)

我无法相信这是预期的行为,而且它肯定没有在Wiki中记录。无论哪种方式,对于遇到这种情况的人来说,解决方法都很简单:即使返回的计数小于批处理大小,也必须继续提取数据,直到返回0条记录。然后你必须过滤掉重复的内容,比如:

yourrecords.GroupBy(x => x.sys_id).Select(x => x.First()).ToList();

问题就解决了

您可以尝试在主键(sys_id)上添加显式排序,以确保每个批处理查询。您可以通过添加URL参数sysparm_query=ORDERBYsys_id

来做到这一点

你的URL看起来像:"{0}/api/now/table/cmdb_ci_vm_instance?sysparm_offset={1}&sysparm_limit={2}&sysparm_exclude_reference_link=true&sysparm_query=ORDERBYsys_id"