2016-08-18 133 views
2

我试图将所有数据从ServiceNow CMDB数据表中抽取到我自己的SQL数据库中。我计划在数据在需要与新SN实现同步的客户遗留系统中进行维护时将其用于自动更新。ServiceNow Table API返回重复/不返回所有记录

我们的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的票之前,我希望看看是否有一些错误的代码,或者我认为这是一个与平台相关的bug。

回答

2

因此,这是几乎可以肯定他们的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(); 

问题就解决了。

0

您可以尝试在主键(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"

+0

这听起来像一个很好的解决方法 - 我现在要试一试。会回到你身边。 (这也符合我的假设 - 他们没有在批量购买前在SN端订购数据。) –

+0

不幸的是,这并没有奏效 - 更奇怪的是,如果我不批量并试图拖动整个数据集(这太大),它会超时......但会返回一个包含2000-4000条记录的部分数据集。每次都不一样。我希望HTTP代码是408或类似的东西,但是我得到一个部分数据集,其中嵌入了一个错误,但仍然是一个HTTP 200.非常令人沮丧= / –