2016-08-18 2 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; 
      } 
     } 
     .... 

Я работал с различными размерами пакетными, и это дает мне разные результаты. В зависимости от того, в какой таблице я нажимаю, иногда я получаю дубликаты, иногда я этого не делаю, иногда я получаю разные дубликаты. Почти во всех случаях, когда I DO получить дубликат, дубликат заменяет действительную запись в потоке, что означает, что я «отсутствует» действительная запись.

Я подтвердил это, посмотрев на поток необработанных данных, поступающий из serviceNow и увидев дубликаты, и проверил, что в ServiceNow нет записей, которые не отображались в моем потоке (что обычно обнаруживается, когда я пытаюсь создать отсутствует запись, а SN отвечает «игнорируется - поле не изменено», что указывает на то, что запись уже существует.)

Я попытался найти и найти кого-нибудь с похожими проблемами, но ничего не нашел. Перед тем, как открыть билет с помощью SN прямо, я надеялся увидеть, было ли что-то, что я делал неправильно с моим кодом, или если это похоже на то, что я ожидаю - ошибка, связанная с платформой.

ответ

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 как обычно, и в итоге я набрал ровно 4 дубликата из 5200+ найденных записей. Поскольку второй проход возвращался меньше, чем 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

К сожалению, это не сработало - что еще более странно, если я не сделаю пакет и attemp, чтобы вытащить весь набор данных (который слишком велик), время истекает ... но возвращает частичный набор данных из 2000-4000 записей. Разные каждый раз. Я бы ожидал HTTP-код 408 или что-то подобное, но вместо этого я получаю частичный набор данных с ошибкой, встроенной в поток ответов, но все же HTTP 200. Очень растеряние = / –

Смежные вопросы