- PVSM.RU - https://www.pvsm.ru -
На днях закрыли очередной проект. Суть: создание новой версии интернет-каталога. Старая версия сайта, в силу ряда причин, клиента не устраивала. Особенностью проекта была его номенклатурная база. Объём номенклатуры каталога составлял ~26000 позиций раскиданных по дереву из 513 узлов + характеристики товара. Почти каждая номенклатурная позиция имела описание на 1-2К текста.
Файл выгрузки каталога в формате ComerceML 2 [1] для старого сайта весил 104 MB. Формировался на стороне 1С 10 минут и после передачи на
В качестве альтернативы XML формату решили выгрузить в JSON. Идея была в том, чтобы попробовать разобрать JSON чем-то, что имеет нативную реализацию парсера, а именно node.js с его JSON.parse().
Наш 1С-ник, разобравшись с новым для него форматом, в несколько итераций добился того, что выгрузка 1С формировала валидный JSON. Время формирования выгрузки сократилось с 10 до 3.5 минут. Те же данные которые в XML формате занимали 104 мегабайта, уместились в 58 мегабайт JSON. Но это было ожидаемо, неожиданностью стало другое…
Для тестирования времени разбора выгрузки я набросал тестовый код:
// Node.js
var fs = require('fs');
function parser(filename, callback){
fs.readFile(filename, { encoding:'utf8' }, function(err, dataFromFile){
var parsedData;
if(err){
callback(err);
} else {
try {
console.time('parse data'); // парсинг - синхронная операция...
parsedData = JSON.parse(dataFromFile.toString().trim()); // <- собственно сам парсинг.
console.timeEnd('parse data'); // ... поэтому измеряем задержку "в лоб".
callback(null, parsedData );
}
catch (e){
callback(e)
}
}
});
}
parser('../import/import.json', function(err, data){
if(err){
throw (err);
}
console.log('groups', data.groups.length);
console.log('items', data.items.length);
console.log('properties', data.properties.length);
});
Запустив его на своей машине (CPU 3.3GHz), я даже не успел привстать чтобы пойти за чаем. Результат и скорость с которой он был выведен в консоль, заставил меня предположить, что в коде баг и он не отработал корректно…
> node parse.js
parse data: 718ms
groups 513
items 26098
properties 149
Но это был не баг. Данные действительно были разобраны и помещены в память за ⅔ секунды. Количество элементов в коллекциях полностью совпадало с заявленным количеством в 1С. Оставалось только найти под столом отпавшую челюсть и написать сервис с полным циклом обработки данных.
В целом выгрузка на сайт отрабатывает по стандартной схеме:
Сервис обработчика выгрузки реализован по схеме:
На продакшене (DigitalOcean, тариф за $10 [4]), с момента вызова и до пункта 3 сервис отрабатывает в целом через 3-4 секунды, после чего повторный вызов сервиса будет возвращать флаг занятости пока заливается база. Весь цикл обработки выгрузки с занесением данных в базу составляет 80 — 90 секунд. Загрузка процессора в момент парсинга выглядит как единичный пик до 70% с основанием в 10 — 30%.
В итоге:
При всей своей скорости JSON.parse() очень неудобен для отладки. В случае наличия ошибки в структуре JSON, вы получаете практически ноль отладочной информации. На этапе пока ваш 1С специалист осваивает JSON очень выручает модуль JSON Lint [5]. Он может быть использован как отдельная утилита или в качестве библиотеки. В отличии от штатного парсера он сообщает в объект исключения номер строки JSON-файла где произошло недоразумение, что при разборе косяков в файле в десятки мегабайт кардинально облегчает жизнь. Цена за такое удобство — скорость. Она упадёт в 5-7 раз по сравнению с нативным JSON.parse().
Тот же тестовый код с JSON Lint будет выглядеть так.
// Node.js
var fs = require('fs'),
jsonlint = require("jsonlint"); // Очень полезен на этапе отладки
function parser(filename, callback){
fs.readFile(filename, { encoding:'utf8' }, function(err, dataFromFile){
var parsedData;
if(err){
callback(err);
} else {
try {
console.time('parse data'); // парсинг - синхронная операция...
/* Используем Jsonlint если нам нужна более подробная информация о месте ошибки в структуре JSON.
* Работает медленнее в 5-7 раз чем нативный JSON.parse().
*/
parsedData = jsonlint.parse(dataFromFile); // тот же парсинг, но с дебагом и поэтессами.
console.timeEnd('parse data'); // ... поэтому измеряем задержку "в лоб".
callback(null, parsedData );
}
catch (e){
callback(e)
}
}
});
}
parser('../import/import.json', function(err, data){
if(err){
throw (err);
}
console.log('groups', data.groups.length);
console.log('items', data.items.length);
console.log('properties', data.properties.length);
});
В заключение хочу традиционно пожелать, чтобы этот материал был ещё кому-нибудь полезен также как был полезен нам.
Автор: Staltec
Источник [6]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/javascript/40726
Ссылки в тексте:
[1] ComerceML 2: http://v8.1c.ru/edi/edi_stnd/90/92.htm
[2] хостинг: https://www.reg.ru/?rlink=reflink-717
[3] Monit: http://habrahabr.ru/post/73506/
[4] DigitalOcean, тариф за $10: https://www.digitalocean.com/pricing
[5] JSON Lint: https://github.com/zaach/jsonlint
[6] Источник: http://habrahabr.ru/post/189812/
Нажмите здесь для печати.