Web-репорты в Lazarus под Linux

До недавнего времени задача генерации отчётов через Web из приложения, написанного на Lazarus, была, скажем так, очень творческой.

Сегодня мы рады сообщить вам о выходе клиент-серверных компонентов для Lazarus в бета-тестирование. С их помощью можно создать и настроить под свои нужды сервер для удалённого построения и экспорта отчётов, а в роли клиента может выступать как ваша программа, так и Web-браузер.

Клиент-серверные компоненты в VCL FastReport реализованы уже давно, но до этого они не были адаптированы для Lazarus и функционировали только в Rad Studio Delphi и C++Builder.

Статья будет полезна не только тем, кто еще ни разу не пользовался ими, но и тем, кто захочет перенести свой FR-сервер в Linux, так как честно описывает как все преимущества, так и недостатки. Также мы встретили ошибку в самом Lazarus и нашли способ её решения.

А теперь перейдём к технической стороне вопроса.

Клиент-серверные компоненты для отчётности в Lazarus

Клиент-серверные компоненты в Lazarus доступны под двумя ОС: Windows и Linux (только GTK2). Они реализованы в пакете «fr6CS_lazarus.lpk» в зависимостях которого указан пакет экспортов, следовательно до его установки требуется установить пакет экспортов, находящийся в папке  «Source/ExportPack».

После установки пакета клиент-серверных компонентов у вас появится новая вкладка «FastReport 6.0 Client/Server», где будет находится 4 компонента:

Web-репорты в Lazarus под Linux

1. TfrxReportServer – это серверный компонент, сервер отчетов и HTTP-сервер “два в одном”. Самым важным его полем является ConfigFileName, где следует указать путь до xml-файла с настройками.

В этом файле можно указать множество настроек, вот лишь самые важные из них:

Обо всех настройках подробнее можно почитать тут.

2. TfrxServerConnection – клиентский компонент, содержащий информацию для удаленного подключения к TfrxReportServer, такую как: хост, порт, количество попыток при ошибке, таймаут и прочее.

3. TfrxReportClient - клиентский компонент, аналог TfrxReport, выполняет запрос отчета на сервере и отображение его на клиенте. Для получения информации о сервере он использует упомянутый компонент TfrxServerConnection. Может получить от сервера построенный отчёт и отобразить или экспортировать его своими силами (на машине клиента).

4. TfrxHTTPClient – клиентский компонент, предназначенный для получения произвольных файлов по протоколу HTTP. Например, он может запросить у сервера уже экспортированные отчёты.

Также мы предоставляем 3 демонстрационных приложения:

- 1 сервер - сразу вместе с отчётами и базами данных;
- 2 клиента - простой и “продвинутый”.

“Продвинутым” клиентом вы можете провести нагрузочное многопоточное тестирование нажав кнопку Start:

Web-репорты в Lazarus под Linux

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

Web-репорты в Lazarus под Linux

“Бутылочное горлышко” GTK2

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 файлы. Данный формат экспорта у нас реализован весьма качественно, в чем вы можете убедиться лично.

Исправление ошибки в очереди сообщений Lazarus 2.0.10 

Также для желающих использовать наши новые компоненты в 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, но хотим напомнить, что это бета-версия и она будет улучшаться по вашим запросам. В случае возникновения ошибок обязательно пишите нам в поддержку.