До недавнего времени задача генерации отчётов через Web из приложения, написанного на Lazarus, была, скажем так, очень творческой.
Сегодня мы рады сообщить вам о выходе клиент-серверных компонентов для Lazarus в бета-тестирование. С их помощью можно создать и настроить под свои нужды сервер для удалённого построения и экспорта отчётов, а в роли клиента может выступать как ваша программа, так и Web-браузер.
Клиент-серверные компоненты в VCL FastReport реализованы уже давно, но до этого они не были адаптированы для Lazarus и функционировали только в Rad Studio Delphi и C++Builder.
Статья будет полезна не только тем, кто еще ни разу не пользовался ими, но и тем, кто захочет перенести свой FR-сервер в Linux, так как честно описывает как все преимущества, так и недостатки. Также мы встретили ошибку в самом Lazarus и нашли способ её решения.
А теперь перейдём к технической стороне вопроса.
Клиент-серверные компоненты в Lazarus доступны под двумя ОС: Windows и Linux (только GTK2). Они реализованы в пакете «fr6CS_lazarus.lpk» в зависимостях которого указан пакет экспортов, следовательно до его установки требуется установить пакет экспортов, находящийся в папке «Source/ExportPack».
После установки пакета клиент-серверных компонентов у вас появится новая вкладка «FastReport 6.0 Client/Server», где будет находится 4 компонента:
1. TfrxReportServer – это серверный компонент, сервер отчетов и HTTP-сервер “два в одном”. Самым важным его полем является ConfigFileName, где следует указать путь до xml-файла с настройками.
В этом файле можно указать множество настроек, вот лишь самые важные из них:
Обо всех настройках подробнее можно почитать тут.
2. TfrxServerConnection – клиентский компонент, содержащий информацию для удаленного подключения к TfrxReportServer, такую как: хост, порт, количество попыток при ошибке, таймаут и прочее.
3. TfrxReportClient - клиентский компонент, аналог TfrxReport, выполняет запрос отчета на сервере и отображение его на клиенте. Для получения информации о сервере он использует упомянутый компонент TfrxServerConnection. Может получить от сервера построенный отчёт и отобразить или экспортировать его своими силами (на машине клиента).
4. TfrxHTTPClient – клиентский компонент, предназначенный для получения произвольных файлов по протоколу HTTP. Например, он может запросить у сервера уже экспортированные отчёты.
Также мы предоставляем 3 демонстрационных приложения:
- 1 сервер - сразу вместе с отчётами и базами данных;
- 2 клиента - простой и “продвинутый”.
“Продвинутым” клиентом вы можете провести нагрузочное многопоточное тестирование нажав кнопку Start:
Также хотелось-бы напомнить, что клиентом может быть обычный браузер и генерацию сайта для веб-клиента тоже можно настроить на свой вкус, а демонстрационный сервер уже настроен для веб клиента.
Lazarus это кроссплатформенная IDE с открытым исходным кодом. Но в этой “бочке меда”, к сожалению, есть и “ложка дёгтя”. Начнём мы с самого неприятного, а именно с Linux сервера.
GTK2 имеет одно крайне неприятное свойство: однопоточность.
Это означает, что даже если 2 программы будут в бесконечном цикле рисовать фигурки на своих BitMap, то GTK2 будет сужать всё до 1 потока. Следовательно, в сумме эти 2 программы нарисуют меньше фигур, чем рисовала-бы одна программа, ибо часть времени будет потрачена на синхронизацию.
Но в данном случае синхронизация организуется без нашего участия.
А теперь возьмем, к примеру ситуацию, когда фигурки рисует 1 программа в нескольких потоках (у каждого потока свой локальный BitMap). В данном случае вам придётся создать в коде систему блокировок, ибо мы помним про однопоточность данной библиотеки. Но это должны быть не обычные критические секции, а глобальные критические секции уровня GTK2. И когда один из потоков входит в эту критическую функцию, то даже основная форма зависает, пока он из неё не выйдет.
Многопоточность с картинками можно организовать только, найдя аналогичный компонент, реализующий рисование, который независим от GTK2 (для данного примера с изображениями подойдёт, например, Cairo), в нашем же случае другой компонент не подходит.
Поэтому часть операций на сервере сужается до 1 потока.
И из-за данной особенности, в частности, лучше не использовать диалоги, ибо пока 1 клиент отвечает на диалог, то построение отчётов для других клиентов будет стоять на паузе.
Может возникнуть вопрос: «а зачем-же тогда вообще нужен однопоточный сервер?» и будете частично правы, так как это похоже на проблему «бутылочного горлышка» на дорогах, где общая пропускная способность дороги равна пропускной способности дороги в самом её узком месте.
Но будете правы лишь отчасти. До одного потока сужается лишь 3 большие операции: загрузка отчётов, построение и экспорт. Приём и передача осуществляется параллельно, а благодаря системе кеширования построенных отчётов в ряде случаев повторное построение и не понадобится.
И данное обстоятельство в сумме с мощным сервером сделает эту проблему намного менее заметной. К тому-же это проблема только для Linux (GTK2) ведь в Windows данная проблема отсутствует, а с выходом GTK3 (которая уже поддерживает многопоточность) в Lazarus она и вовсе исчезнет.
Остальные проблемы в разы меньше и по сравнению с этой даже крошечные.
Небольшая часть функционала была вырезана при портировании, а именно CGI и система авторизации. Как скоро мы их реализуем зависит от реальных запросов на них от наших клиентов.
Экспорт в HTML для Lazarus еще далёк от совершенства, пользоваться веб клиентом можно и нужно, ведь это удобно, но отчёты он будет отображать не совсем идеально.
Впрочем, вы можете настроить систему так, чтобы веб клиент получал экспортированные не в HTML отчёты, а допустим в PDF. Ведь большинство современных браузеров отлично могут отображать PDF файлы. Данный формат экспорта у нас реализован весьма качественно, в чем вы можете убедиться лично.
Также для желающих использовать наши новые компоненты в Linux, стоит упомянуть одну важную вещь: мы столкнулись с ошибкой в блокировке очереди сообщений и не могли её обойти. Нам удалось связаться с программистами в Lazarus, они эту проблему уже исправили и в следующей версии Lazarus всё будет стабильно работать. Пока что в версии 2.0.10 и ниже эту ошибку придётся исправлять локально. Это не займет много сил и времени, нужно лишь дописать 3 строчки в один из файлов Lazarus и пересобрать его, а именно:
1. Откройте папку, где расположен Lazarus (на Ubuntu, например, "/usr/share/lazarus/2.0.10")
2. Откройте в неё файл ~/lcl/interfaces/gtk2/gtk2msgqueue.pp
3. Найдите процедуру: procedure TGtkMessageQueue.Lock;
4. В этой процедуре найдите строчку: g_main_context_acquire(FMainContext);
Данный код не учитывает того, что функция g_main_context_acquire может завершиться безуспешно.
Поэтому замените её на:
repeat until g_main_context_acquire(FMainContext);
То есть вызываем g_main_context_acquire в цикле, пока она не вернет True (не завершится успешно).
Предлагаем вам опробовать наши новые компоненты для Lazarus, но хотим напомнить, что это бета-версия и она будет улучшаться по вашим запросам. В случае возникновения ошибок обязательно пишите нам в поддержку.