Блог → Стыковка базы V7 с витриной интернет магазина. Часть 4

Ну и наконец, переходим к реализации системы. Мы исходим из того, что обе части проекта - web-витрина и учетная система уже существуют и каждая из них может работать самостоятельно. Остается связать их между собой. На стороне web-витрины всё будет довольно просто. Из чего состоит web-витрина? Это база данных (неважно какая - MySQL, SQLite или обычный текстовый файл), интерфейс пользователя и бизнес-логика, связывающая второе с первым.

Для связи с учётной системой нам понадобится:
• Доработать бизнес-логику таким образом, чтобы события, происходящие на web-витрине (регистрация нового покупателя, оформление нового заказа) попадали в файл задач для учетной системы. Скорее всего, придется доработать и базу данных - ведь задачи до отсылки нужно где-то хранить.
• Написать модуль, который будет периодически "сливать" новые задачи в файл задач и посылать его учетной системе (выкладывать в директорию или отсылать по почте).
• Написать модуль, который будет разбирать файл задач, приходящий от учетной системы, и выполнять необходимые действия с базой данных (добавлять и удалять номенклатуру, изменять цены и пр.)
• Повесить прием и передачу данных на "будильник" (т.е. на cron).

Техническая реализация всего этого очень сильно зависит от внутреннего устройства web-магазина, поэтому о ней говорить мы не будем - как сказал один умный человек, "если идея понятна, то код не нужно изобретать, он очевиден". Для высокоуровневых языков это правило вполне работает.

А вот на стороне учётной системы всё будет немного сложнее. Во-первых, необходимо выделить машину под "сервер обмена данными". Эта машина вовсе не обязательно должна принадлежать к классу серверов - достаточно обычной офисной "рабочей лошадки", на которой можно крутить V7 без особых "тормозов". Этот "сервер обмена" должен быть подключен к Интернету, и на нём пожизненно должна быть запущена копия клиента V7 - именно на ней и будут выполняться все задачи, приходящие от нашей web-витрины.

Вы можете спросить, в чём отличие такого подхода от принципа работы "Web-расширения"? Справедливый вопрос. Отвечаю. Здесь клиент V7 работает не в качестве сервера приложений, а в качестве "эмулятора пользователя" - с тем же успехом можно посадить живого оператора, который будет читать XML-файл задач и нажимать нужные кнопки. Понятно, что в данном конкретном случае машина справится лучше человека - она нажимает на кнопки быстрее и не делает опечаток.

Сервер обмена будет выполнять две основные задачи:
• получать файл задач от web-витрины, разбирать его и вносить информацию в учетную систему;
• анализировать изменения в базе данных учетной системы, формировать файл задач для web-витрины и отсылать его адресату.

С первой задачей всё просто: скачали XML-файл, разобрали его, записали в базу данных новые заказы и успокоились. Информация, приходящая от web-витрины, по определению будет однообразной - тут сложно что-то придумать, кроме персональных данных покупателей, заказов и комментариев к ним. А вот вторая задача далеко не проста. Нам нужно совместить несколько противоречивых требований:
• для формирования файла задач необходимо анализировать практически всю базу данных учетной системы (цены на всю номенклатуру, изменения доступных остатков всех товаров на складе и пр.);
• анализ должен занимать минимальное количество времени;
• анализ должен производится автоматически, без участия пользователя.

Как это сделать? Можно, конечно, плюнуть на тотальную автоматизацию, посадить оператора и дать ему две большие кнопки "Закачать на сайт прайс-листы" и "Закачать на сайт текущие остатки" - но это, очевидно, не самое лучшее решение. Если у нас большая номенклатура и/или товарооборот, то нажимать на эти кнопки придется слишком часто. И ведь каждый раз мы будем прокачивать тонну избыточной информации - допустим, у нас в прайс-листе двести позиций, цены поменялись только у двух - зачем же перекачивать на web-витрину остальные сто девяносто восемь? Так что лучше будет оператора из системы убрать и заменить его программным кодом.

Для этого нам потребуется:
• Создать в базе данных хранилище для текущих задач web-витрине. Лучше всего сделать его в виде служебного (т.е. недоступного пользователям) справочника. Этот справочник будет содержать уникальный номер задачи, текст задачи (прямо фрагмент XML), и, возможно, флаг "отослано". Дополнительные поля - имя пользователя, чьи действия породили задачу, таймштампы и прочее - по желанию.
• В тот момент, когда в учетной системе производится интересное для web-витрины событие (перезапись элемента справочника номенклатуры или цен, проведение документа, делающего движения по складу и т.п.), нужно вызывать глобальную процедуру, которая сформирует текст задачи и запишет эту задачу в служебный справочник.
• На нашем "сервере обмена" периодически запускать (не руками, конечно, а через IdleProcessing) обработку-синхронизатор, которая просмотрит справочник задач, выберет оттуда те задачи, которые еще не были отосланы, сформирует файл задач и вышлет его web-витрине.
• Если используется механизм оповещения о выполнении задач, то этот же синхронизатор будет анализировать файлы, приходящие от web-витрины, выбирать оттуда отчеты о выполнении задач, и удалять соответствующие задачи из справочника. Если механизма отчетности нет, то их можно удалять сразу же.
• И, конечно же, синхронизатор будет вести лог - чтобы пользователь потом мог внятно отвечать на вопросы типа "а почему у нас на сайте цены двухнедельной давности, мы же эту скидку давно отменили".

Если построить обмен данными таким образом, то все три условия будут выполнены:
• В файл задач будет попадать вся необходимая информация, причем ровно в том объеме, в каком надо. Если цена изменилась только на две позиции, в файле задач будет только два пункта, а не двести.
• Формирование файла задач будет происходить быстро - нам нужно перебрать только один небольшой служебный справочник, а не половину базы данных.
• Вся эта механика будет абсолютно прозрачна для пользователей учетной системы, им не придется делать никаких лишних телодвижений.

Конечно, потребуется тщательно просмотреть всю конфигурацию - но объём кода, который придется написать, будет не таким и большим. Главное - не пропустить те места конфигурации, где производится модификация важной для web-витрины информации. Причем не стоит забывать о том, что удаление информации - это тоже модификация.

Описанная в статье концепция - не просто теория, на самом деле она уже реализована в коде, и подтвердила свою эффективность, так что позволю себе дать несколько практических советов:
• Постарайтесь минимизировать инструментарий. Если можно обойтись одной внешней компонентой - не нужно подключать две. Чем меньше навешено дополнительных библиотек на V7 - тем легче ей дышится.
• Если вы делаете подробный лог операций - обязательно предусмотрите детализацию лога на несколько уровней. Иначе логи потом некуда будет складывать. И не забудьте про механизм обрезания старых логов.
• Не используйте для записи XML-документов MSXML - это напрасная трата системных ресурсов. XML-документ является обычным текстовым файлов и его гораздо быстрее и проще будет записать руками.
• Не используйте для чтения XML мост к MSXML, реализованный в V7Plus. MSXML прекрасно вызывается напрямую из V7 (его методы подробно описаны в документации от MS). Убрав мост, вы избавитесь от лишнего источника непонятных ошибок и не будете зависеть от версии MSXML.
• Всегда сжимайте XML-файлы, они на 90% состоят из пустого места. На любом 'nix-сервере обязательно найдется gzip.
• Не поленитесь написать хотя бы самый простенький XSLT-шаблон для своих XML-документов - поверьте, их гораздо удобнее просматривать в HTML, нежели в исходном виде.
• Не стоит разбивать файл задач на много мелких файлов, по задаче в каждом. Один большой файл быстрее и проще передать по каналам связи и обработать, чем толпу маленьких с теми же данными. Но соблюдайте меру - файл задач весом в пару мегабайт в архиве будет явным перебором.
• Для записи больших текстовых файлов не пользуйтесь штатным объектом V7::Text, пользуйтесь V7Plus::V7TextFile, это решение на порядок производительнее! Но не забывайте, что V7TextFile умеет работать только с одним файлом в один момент времени, не позволяет дописывать файлы и не понимает строки длиннее 32k.
• Система обмена данными, в которой реализован механизм отчетов о выполнении, работает гораздо стабильнее системы, в которой такого механизма нет.
• Обязательно сделайте визуализацию процесса обмена на стороне V7 - это сильно поможет при отладке. А если сделать ее стильной - то и произведет впечатление на вашего директора, знакомого с интернет-технологиями исключительно по глупым голливудским фильмам.

Какими достоинствами обладает описанная концепция? Во-первых, простота самой идеи. Концепции, которые просты, как табуретки, обычно работают лучше сложных и навороченных. Во-вторых, простота реализации и поддержки - и в случае возникновения ошибок можно быть уверенным, что это собственные ошибки, которые всегда можно не только найти, но и исправить. В-третьих, автономность каждой из сторон придает всей системе устойчивость - и web-витрина, и учетная система могут прекрасно работать сами по себе. Более того, в случае порчи и/или потери информации на одной из сторон (скажем, конкуренты "хакнули" наш сайт и уничтожили базу данных), большую часть информации можно будет восстановить по данным другой стороны.

И, наконец, главным, на мой взгляд, достоинством, является экономичность решения. Для её реализации не нужно ни мощного сервера, ни толстого канала, ни выделенного администратора. Все, что требуется - это один раз написать, отладить и запустить. Затраты на поддержание web-витрины в актуальном состоянии будут минимальными.

Разумеется, есть и недостатки. На мой взгляд, их два: запаздывание информации и проблемы с большим трафиком. Запаздывание информации проистекает из самого принципа асинхронного обмена: на одной стороне что-то произошло, а другая сторона узнает об этом не раньше, чем получит файл задач и разберет его. Более того, если другая сторона вообще "упала и валяется", то об этом станет известно далеко не сразу. Насколько этот недостаток критичен? Мне кажется, что не особенно. В худшем случае, мы примем через интернет заказ на товар, последнюю единицу которого только что списали со склада в офисе - но и тогда мы пошлем покупателю (разумеется, автоматически) красивое электронное письмо с нашими извинениями, перечнем доступных аналогов и пожеланием заходить к нам почаще (а потом менеджер перекопает логи, подсчитает количество таких вот писем и придумает систему квотирования товарной массы, но это уже из другой сказки).

Другой недостаток - проблемы с большим трафиком - проистекает из того, что собственно V7, на сколь мощной машине она бы не была запущена, имеет вполне конечную производительность, и если информация будет поступать быстрее, чем мы в состоянии прокачивать (а ведь нужно не просто взять и положить, но ещё и сжать-разжать, разобрать, проверить, выполнить ещё какие-то телодвижения в базе данных), то очень скоро вся система станет похожа на скоростной автобан, посреди которого кто-то умный врезал кусочек классической российской грунтовки длиной в пару километров. Если трафик будет превышать возможности системы, придется что-то придумывать - ставить дополнительные "серверы обмена" и как-то распараллеливать между ними задачи. Но практика показывает, что большой трафик бывает только у больших и мощных web-магазинов - а они давно все у себя автоматизировали, и проблема синхронизации данных сайта и учетной системе для них не актуальна. Так что и этот недостаток нельзя, по моему мнению, считать критичным.

Итак, что же мы имеем в "сухом остатке"? Состыковать учетную систему с web-витриной можно либо при помощи "Web-расширения" от 1С, либо собственными руками. "Web-pacширение" реализует синхронный обмен данными и использует клиентскую часть V7 в качестве сервера приложений, и может не подойти по ряду причин - дорого, небезопасно, неустойчиво, велико время простоя. Остаются руки.

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