gifts2017

Космические технологии O-Planet: 1С и навигация в асинхронном пространстве

Опубликовал Олег Пономаренко (O-Planet) в раздел Программирование - Практика программирования

Сегодня мы направим наш челнок в мир асинхронной интерактивности, туда, где ...
Итак, если вы сегодня решили скоротать вечер на борту нашего челнока, то приготовьтесь к незабываемым впечатлениям. Сразу скажу, что комфортабельные лайнеры с многотомными тех.инструкциями – это не по мне. Все там продумано кем-то за тебя, а потому нет уверенности, что ты чем-то управляешь. Наш кораблик стартует только после удара кулаком по крышке гипердрайва, при старте от него обязательно отваливается очередная «лишняя деталь», но в замен ты получаешь полноту ощущения полета, и конечно в финале оказываешься самым быстрым во Вселенной.

В общем, у вас еще есть время соскочить. Тем же, кто «на корабле» не говорю «пристегнитесь» - не поможет…


Когда только начинаешь осваивать web-программирование, то серьезные неудобства нам, привыкшим к Word, может доставить невозможность явно задать точные координаты объектов на web-странице средствами html. Позднее, когда пытаешь реализовать на своей страничке некую интерактивность, сталкиваешься с неприятной особенностью web: при обновлении твой клиент теряет все промежуточные данные. Поэтому, организовать игру крестики-нолики, чат или корзину покупок на сайте, не прибегая к кукисам или сессиям – задача не такая и простая. Большинство же чатов, форумов, тех же корзин покупок в Интернет-магазинах чаще всего сделано достаточно топорно: ваше состояние идентифицируется записью в базе данных на сервере по некоему идентификатору. Когда вы делаете очередной запрос к серверу, то передаете ему этот идентификатор и суть запроса. Сервер находит Вашу запись, смотрит, что можно сделать и генерирует в ответ страничку, вновь возвращая идентификатор и «забывая» о вашем существовании в тот же миг. Это вполне стандартная процедура web-серфинга. Ее отличают две особенности:

1. Между моментами отправки запроса и получением ответа от сервера ваш браузер «висит»
2. При получении ответа страница полностью перерисовывается, теряя всю прежнюю информацию, например, информацию о выбранном товаре


Но сегодня мы направим наш челнок в мир асинхронной интерактивности, туда, где и первая, и вторая проблемы web решены. Более того, мы откажемся от «многотомных инструкций», связанных с PHP и MySql, заменив их привычной и всеми любимой оболочкой 1С. В завершении полета нам предстоит наблюдать рождение сверхновой, имя которой ярко и незабываемо: Асинхронный 1С-сервер: «АС-1С»

Асинхронная вселенная.

Итак, у нас есть подвисающая и перерисовывающаяся web-страничка. Давайте разделим ее на два фрейма. В первом будем делать обычные http-запросы к серверу. Разумеется, этот фрейм подвиснет, дожидаясь ответа и полностью обновится при его получении. Сделаем его невидимым. И пока наш невидимый друг «разговаривает» с сервером, мы будем продолжать работать во втором, рабочем фрейме, периодически опрашивая по таймеру состояние первого. Как только сервер подаст «условный знак», что страница в первом фрейме полностью сформировалась (например, сформирует < div id=”END”>END</div> в конце), мы без труда достанем оттуда все, что нам нужно по frame1.name.outerHTML, и лишь частично обновим содержание рабочего фрейма, не перерисовывая всей страницы в нем, а потому не теряя ни единого бита пользовательских данных.

Собственно, это и есть асинхронный подход. Он выражается в том, что два процесса (наши фреймы) работают параллельно друг с другом, обмениваясь информацией по условному сигналу.

Асинхронные запросы сплошь и рядом используются в микропроцессорной технике, когда нельзя, чтобы процесс, ожидающий ответа, «висел». Для этого назначаются "флаги" – условные биты в регистрах состояния. Если флаг поменялся с 0 на 1, то это говорит процессу, контролирующему состояние флага, что пора что-то прочитать. Сделав это, он обязательно сбрасывает флаг – просигналит о том, что данные прочитаны полностью, и он готов принять новую порцию информации. Как видите, никакой передачи управления и потери контроля.

ФОФЧ тьфу… AJAX

Приходя к радостному пониманию преимущества асинхронных запросов, незадачливый web-навигатор устремляется в поиски приемлемой технологии, реализующей такие запросы, и наталкивается на скалу под названием AJAX. С легкой руки Гарретта (не он ли был прообразом персонажа в Thief? &#61516; ) асинхронность почти повсеместно ассоциируется с php, mysql, xml javascript и страшным XMLHttpRequest … В общем, многие «ниасиливают» и отказываются от идеи асинхронности. Мы же с вами потому и в космосе, что там, где что-то «ниасиливаем», начинаем творить сами.

Асинхронный клиент

Те, кто въехал в специфику асинхронного подхода без труда напишут клиент, делающий асинхронные запросы, на любом доступном языке программирования. 1С не будет здесь исключением. Асинхронный клиент, написанный на 1С, это достаточно интересная тема. Во-первых, любое количество подключений к базе на сервере, даже если там стоит однопользовательская версия 1С. Во-вторых, никакого зависания, если сервер не отвечает. В-третьих, возможность работать из любой части галактики, где есть доступ к Интернет. Зачем и кому, спросит кто-то, могут понадобиться «асинхронные одинэсины»? Думаю, применение этой технологии может быть самым широким и неожиданным: удаленные офисы, торговые представители с ноутбуками, корпоративные справочные системы… Я использую асинхронный обмен данными при сетевом варианте работы сервера дисконтных карт в составе «Кассирочки». Кстати, всем известный «Штрих-кассир» использует именно такую технологию, передавая данные о продажах и делая запрос об остатках товаров в реальном времени в «Штрих-мастер» на сервере.

Для создания асинхронного клиента на базе 1С, воспользуемся функцией «ОбработкаОжидания». Глобальный модуль простейшего асинхронного клиента, позволяющего делать до 10-и запросов к серверу и ожидать ответа, не прекращая работу, будет выглядеть примерно так:

Перем ЕстьВопрос Экспорт;
Перем ЕстьОтвет Экспорт;
Перем ТекстВопроса Экспорт;
Перем ТекстОтвета Экспорт;
Перем ПапкаОбмена Экспорт;

Функция ЗаписатьВопрос(Инфо) Экспорт
  Если ЕстьВопрос=1 Тогда 
    Возврат 0; // не обработан предыдущий вопрос
  КонецЕсли;
  ТекстВопроса=Инфо;
  ЕстьВопрос=1;
  Возврат 1; // текущий вопрос записан в переменную ТекстВопроса 
      // и ожидает отправки на сервер
КонецФункции

Функция БылДанОтвет() Экспорт
  Возврат ЕстьОтвет; // Имеется необработанный ответ в переменной ТекстОтвета
КонецФункции

Функция ПолучитьОтвет() Экспорт
  Если ЕстьОтвет=1 Тогда
    ЕстьОтвет=0; // Текущий ответ был прочитан, можно получать новый ответ
    Возврат ТекстОтвета;
  КонецЕсли;
  Возврат "";
КонецФункции

Процедура РаботаССервером()
  Если ЕстьОтвет=0 Тогда // Если нет необработанного ответа
    Если ФС.СуществуетФайл(ПапкаОбмена+"ответ.txt")=1 Тогда
      Т=СоздатьОбъект("Текст");
      Т.Открыть(ПапкаОбмена+"ответ.txt");
      ТекстОтвета=Т.ПрочитатьСтроку(1);
      ФС.УдалитьФайл(ПапкаОбмена+"ответ.txt"); // Сообщаем серверу, что ответ прочитан
      ЕстьОтвет=1; // Прочитан новый ответ
    КонецЕсли;
  КонецЕсли;
  Если ЕстьВопрос=1 Тогда // Если есть необработанный вопрос
    К=1;
    // Проверяем, есть ли возможность записать вопрос
    Пока ФС.СуществуетФайл(ПапкаОбмена+"вопрос"+К+".txt")=1 Цикл
      К=К+1;
      Если К>10 Тогда
        Возврат; // Имеется 10 непрочитанных сервером вопросов
      КонецЕсли;
    КонецЦикла;
    Т=СоздатьОбъект("Текст");
    Т.ДобавитьСтроку(ТекстВопроса);
    Т.Записать(ПапкаОбмена+"вопрос"+К+".txt");
    ЕстьВопрос=0; // Текущий вопрос обработан и направлен серверу
  КонецЕсли;
КонецПроцедуры

ЕстьВопрос=0;
ЕстьОтвет=0;
ОбработкаОжидания("РаботаССервером ",1); 


Для создания более крутого Интернет аналога, нам потребуется внешняя компонента, реализующая доступ к Интернет, и обрабатывающая наши запросы в фоновом режиме. Как только сервер присылает ответ, наша компонента должна формировать событие в процедуре ОбработкаВнешнегоСобытия.

Но можно быть проще, воспользовавшись внешним приложением, например, подключиться к браузеру по OLE и периодически опрашивать его объектную модель на наличие пресловутого < div id=”END”>END</div> . Еще проще? Пожалуйста. Запускаем параллельно еще одну 1С, и пусть она занимается Интернет с помощью стандартных библиотек, формируя текстовые файлы с полученной информацией в определенном каталоге. Мы же продолжаем работать в нашей базе. И как только мы видим появление такого файла, значит, нам прислали долгожданный ответ. Разумеется, ни что не мешает использовать прямое ftp-подключение к серверу, чтобы периодически опрашивать, а не появился ли нужный нам файлик…

Асинхронный сервер

Ну почему??? Почему какой-то там Гарретт может позволить себе брякнуть с будуна AJAX, и вся планета будет это повторять? Нет, мы-то чем хуже! Сегодня мы говорим «АС-1С» И пусть эта аббревиатура станет крылатой!

Работа нашего асинхронного сервера 1С будет напоминать работу клиента, поэтому, приводить его код не имеет смысла. Мы опрашиваем наличие файлов с вопросами, и пока они есть, обрабатывать их, формируя ответы. При этом, стоит следить, чтобы не обработанные клиентами ответы не затирались.

Но, говоря о применении 1С в качестве серверной программы, мне хотелось бы акцентировать внимание на замене им mysql и xml. По сути, используя 1С, мы имеем мощнейший инструмент обработки данных. Намного более мощный, чем mysql. Ни что также не мешает нам заменить xml-шаблоны модулем генерации страничек в составе все того же нашего 1С. Соответственно, при таком подходе php-код обработки Интернет запросов уменьшится до минимума. Это разгрузит модуль обмена данными с клиентами, и увеличит пропускную способность нашего web-сервера в несколько раз.

Остается вопрос, как более мягко связать web-сервер c 1С? Конечно, можно использовать все те же текстовые файлы обмена. Но в Интернет-варианте это будет выглядеть как-то уж очень топорно. Интересный вариант решения поставленной задачи предлагает сочетание технологии внешних компонент с расширением ISAPI web-сервера. Расширение ISAPI позволяет получать доступ внешнему приложению к серверному потоку данных. Кроме того, в отличие от CGI, ISAPI-библиотека находится в памяти постоянно, а не загружается и выгружается при каждом новом запросе. Это позволит организовать постоянный обмен данными ядра сервера с 1С на высокой скорости.

***

Надеюсь, наш круиз в асинхронные web-дали останется незабываемым, а вариации на тему 1С в рамках асинхронности подарят всем участникам круиза, наблюдавшим свет сверхновой АС-1С, интересные идеи. Только не забывайте чаще стучать по крышке гипердрайва…

См. также

Подписаться Добавить вознаграждение
Комментарии
1. Сhe Burashka (CheBurator) 22.12.07 06:08
ну, нормалек...
весь вопрос в том, что 1С-ина - интерактивная система. а юзер ждать не станет.. пока там его задание на формирование отчета в очереди у сервака валяется.. сам сформирует быстрее... но для кучи всяких прочих вещей - нормуль...
2. AlexQC (alexqc) 24.12.07 10:15
> Интересный вариант решения поставленной задачи предлагает сочетание технологии внешних компонент с расширением ISAPI web-сервера. Расширение ISAPI позволяет получать доступ внешнему приложению к серверному потоку данных.

..... И мы получим 1С:веб-расширение :)
3. AlexQC (alexqc) 24.12.07 11:45
Кстати, внесу пару дополнений.

Во- первых, вместо обработкиОжидания() в ГМ можно применять аналогичную в любой форме (недокументированная ф-ция Форма.ОбработкаОжидания("ПроцедураФормы",Таймаут) ). Плюс в том что обработка м.б. внешней, и можно несколько различных обработок запустить (в т.ч с разными таймаутами). Минус - что ее закрыть могут :) (но если это чисто сервер и никто за ним не сидит - то нормально.). Еще есть вариант с Форма.Обновить(), но он иногда проглючивает, потому не привожу.

Во-вторых, можно запустить несколько серверов - для "параллельной" обработки кучи запросов. Но в этом случае
нужно следить, чтоб два сервера не обработали один файл. Это можно сделать либо заведением для каждого сервера своего каталога и переносом обрабатываемых файлов туда, либо созданием для обрабатываемого файла файла-флага (для "обычной" 1С подойдет xBase-объект, пока он открыт-соотв. дбф блокирован) - наличие флага будет свидетельствавать об "захвате" файла. А для 1С++ можно поступить еще проще - накладывать файловые блокировки (объект binaryData).
4. Олег Пономаренко (O-Planet) 24.12.07 16:59
Угу. Спасибо. Есть еще _GetPerformanceCounter()
5. Руслан Харисов (fAngel) 26.04.08 11:14