Распределенные вычисления и технологии Inprise. Часть 3. Организация распределенных вычислений с помощью Inprise Entera
1. НАЗНАЧЕНИЕ И СОСТАВ INPRISE ENTERA
2.1. КОНФИГУРАЦИЯ И ЗАПУСК ENTERA BROKER
2.2. КОНФИГУРАЦИЯ ИСТОЧНИКА ДАННЫХ И СЕРВЕРА
2.3. СОЗДАНИЕ КЛИЕНТСКОГО ПРИЛОЖЕНИЯ С ПОМОЩЬЮ DELPHI ИЛИ C++BUILDER ENTERPRISE
2.4. ПЕРЕДАЧА ПАРАМЕТРОВ НА СЕРВЕР
3.2. ГЕНЕРАЦИЯ КОДА ДЛЯ СЕРВЕРА И КЛИЕНТА
3.3. СОЗДАНИЕ СЕРВЕРНОЙ ЧАСТИ (DELPHI)
3.4. СОЗДАНИЕ СЕРВЕРНОЙ ЧАСТИ (C/C++)
3.5. ТЕСТИРОВАНИЕ СЕРВЕРА ФУНКЦИОНАЛЬНОСТИ
3.6. СОЗДАНИЕ КЛИЕНТСКОГО ПРИЛОЖЕНИЯ (DELPHI)
3.7. СОЗДАНИЕ КЛИЕНТСКОГО ПРИЛОЖЕНИЯ (C/C++)
3.8. СОЗДАНИЕ КЛИЕНТСКОГО ПРИЛОЖЕНИЯ (VISUAL BASIC)
4. УПРАВЛЕНИЕ ФУНКЦИОНИРОВАНИЕМ ИНФОРМАЦИОННОЙ СИСТЕМЫ ПРЕДПРИЯТИЯ С ПОМОЩЬЮ INPRISE APPCENTER
4.3. СОЗДАНИЕ И РЕДАКТИРОВАНИЕ КОНФИГУРАЦИЙ
В предыдущей статье данного цикла была рассмотрена одна из самых недорогих технологий организации распределенных вычислений — технология Microsoft COM (точнее, ее расширение — COM+, реализованное в продукте Microsoft Transaction Server). Отметим, однако, что возможности создания распределенных систем ограничиваются не только использованием COM-технологии и соответственно MIDAS-ориентированными серверами. Нередко с целью обеспечения повышенной надежности серверы функциональности разрабатывают для платформ, отличных от Windows, и в этом случае используются технологии, отличные от COM. В данной статье будет рассмотрено создание серверов функциональности с помощью Inprise Entera, представляющего собой сервер приложений, функционирующий на многих платформах, таких как AIX, HP-UX, Solaris, Windows NT. Если говорить более точно, Entera представляет собой набор сервисов и утилит для создания и эксплуатации серверов функциональности и их клиентов, при этом и серверы, и клиенты могут быть созданы на различных языках программирования и для различных платформ. Это позволяет создавать многоуровневые системы в гетерогенной среде, где не только серверы баз данных, но и любые другие серверы функциональности могут выполняться под управлением платформ, отличных от Windows (например, на UNIX-платформах), что позволяет выбрать наиболее оптимальное для предприятия сочетание удобства, масштабируемости и надежности.
1. Назначение и состав Inprise Entera
Основное назначение серверов функциональности, созданных на базе Entera, — предоставлять содержащим только интерфейс пользователя «тонким» клиентским приложениям те или иные услуги, например, проведение сложных расчетов или доступ к данным, содержащимся на серверах баз данных. Являясь серверами доступа к данным (или иным сервером функциональности) для клиентского приложения, серверы на базе Entera могут быть, в свою очередь, клиентами серверных СУБД. Таким образом, с использованием Entera возможно построение трехзвенной системы, где в среднем звене содержатся средства доступа к данным, а также, при необходимости, бизнес-правила, в том числе те, что оформлены в виде исполняемых файлов, выполнение которых инициируется при необходимости. При этом нередко среднее звено состоит из комплекса серверов приложений, функционирующих на нескольких компьютерах, нередко под управлением различных операционных систем (рис. 1).
Entera поддерживает как стандарт распределенных вычислений DCE (Distributed Computing Environment), так и обмен данными между клиентом и сервером функциональности непосредственно с помощью протокола TCP/IP (только версия 3.2), позволяя при этом создавать клиентские приложения с помощью Delphi, Visual Basic, PowerBuilder, Smalltalk, Visual C++, Java, COBOL, C, C++, а также средств разработки 4-го поколения (в состав Entera входят соответствующие генераторы клиентского и серверного stub-кода). Поддерживается также широкий спектр серверных СУБД: Oracle, Sybase, Informix, Ingres, IBM DB2, Microsoft SQL Server (пользователям Entera доступны соответствующие сервисы доступа к данным, представляющие собой надстройки над клиентскими частями этих серверных СУБД).
Entera включает в себя помимо генераторов кода и сервисов доступа к данным специализированные сервисы, обеспечивающие надежность и производительность многозвенных информационных систем.
Entera Broker предоставляет клиентскому приложению список доступных в сети сервисов, оформленных в виде объектов, и находит для обратившегося клиента в этом списке нужный из них. Entera Broker представляет собой, по существу, так называемый Directory Service.
Сервисы безопасности (Security Services) обеспечивают доступ пользователей к этим объектам в соответствии с их правами (их обсуждение выходит за рамки данной статьи).
AppCenter, или сервис управления приложениями, обеспечивает надежность функционирования клиентских приложений, подключая их в случае отказа компьютеров, содержащих используемые ими объекты, к другим аналогичным объектам, доступным в сети. Этот сервис позволяет также описывать правила функционирования сервисов и групп сервисов (например, равномерная загрузка серверов или резервирование отказавшего сервера и др.)
Помимо стандартного комплекта Entera Developers Package разработчикам доступен ряд дополнительных продуктов: DCE Adapter — средство, предоставляющее возможность использования DCE клиентскими приложениями; Entera/Fx — набор утилит, включающих дополнительные средства повышения безопасности, средства равномерного распределения загрузки серверов приложений и др. Подробности о комплектах поставки и дополнительных продуктах можно узнать на Web-сайте www.inprise.com.
2. Создание серверов доступа к данным и клиентских приложений с помощью Entera 3.2 и Delphi 3/C++Builder 3 Enterprise
В типичных информационных системах с использованием Entera обычно имеется три звена:
1. Сервер баз данных.
2. Среднее звено, содержащее бизнес-правила, определяющие, каким образом можно получить данные, которые требуются приложению. Приложение, использующее эти данные, обращается к ним посредством Entera. В некоторых случаях правила могут быть сосредоточены в исполняемом файле, называемом сервером функциональности (functionality server), и этот сервер может обращаться к другому приложению среднего звена, поставляющему данные с сервера. Приложений среднего звена может быть несколько в зависимости от потребностей.
3. Презентационный слой — та часть информационной системы, которая создается с помощью Delphi или C++Builder. Приложение презентационного слоя запрашивает данные у приложения среднего звена и представляет их пользователю в виде, удобном для просмотра и редактирования.
В некоторых случаях эти три звена могут быть представлены в виде трех отдельных приложений, однако в общем случае каждое звено может состоять из нескольких отдельных приложений, что позволяет говорить о многозвенной архитектуре.
Наряду с версией Delphi и C++Builder Client/Server Suite имеются версии Delphi и C++Builder Enterprise, позволяющие создавать «тонкие» клиентские приложения для сервера приложений Inprise Entera c помощью компонентов TEnteraConnection и TEnteraProvider. Использование этих средств разработки будет рассмотрено далее.
В качестве примера рассмотрим использование Entera для Windows NT (использование Entera для UNIX требует примерно тех же приемов).
2.1. Конфигурация и запуск Entera Broker
Для создания сервера следует в первую очередь запустить Entera Broker. Типичный командный файл для запуска брокера выглядит следующим образом:
start "Entera Broker" broker -e broker.envКоманда start предназначена для создания процесса, в котором будет выполняться брокер. "Entera Broker" — заголовок окна, созданного командой start. Третий параметр — имя исполняемого файла broker.exe из каталога Entera\TCP. Параметр -e означает использование файла конфигурации, имя которого указано в последнем параметре команды. Этот файл имеет примерно следующий вид:
DCE_BROKER=elmanova, 16000 DCE_LOG=CLIENT.LOG DCE_DEBUGLEVEL=D,D
Первая строка указывает имя компьютера, на котором запущен брокер, и номер используемого порта. Вторая строка указывает, в какой файл выводить сообщения об ошибках. Третья строка указывает уровень вывода отладочных сообщений.
Для успешного запуска брокера следует иметь в одном каталоге файлы broker.env, broker.exe, clistart.exe (надстройка над ODBC, обеспечивающая доступ к данным и фактически представляющая собой собственно сам сервер доступа к данным) и odet30.dll (библиотека, содержащая функции Entera API для Windows NT). Иногда бывает нужно, чтобы переменная окружения ODEDIR указывала на каталог Entera\TCP:
Set ODEDIR=D:\OpenEnv\Entera\Tcp
Окно запущенного брокера представляет собой стандартное окно 32-разрядного консольного приложения.
Отметим, что, если используется Entera 3.2 для Windows NT, брокер должен выполняться под управлением именно Windows NT; если используется Entera 3.2 для другой платформы — все выполненные выше действия следует выполнить для этой платформы (отличия здесь невелики, так как в основном здесь используются обычные команды операционной системы для установки значений переменных среды и запуска приложений). Например, в случае UNIX все команды можно выполнить в терминальном режиме или внутри терминального окна, если используется какая-нибудь графическая среда.
2.2. Конфигурация источника данных и сервера
Теперь можно приступить к созданию сервера доступа к данным. Сразу же отметим, что этот сервер не обязан находиться на том же самом компьютере, где запущен брокер; кроме того, данный сервер может выполняться под управлением Windows 95/98, что неоднократно проверено экспериментально.
В качестве источника данных используем каталог DBDEMOS или BCDEMOS, описав его в Control Panel как ODBC-источник типа dBase 5 с именем edemo.
Если данный компьютер не содержит такого каталога, может подойти любой другой ODBC-источник. Отметим, что компьютер, содержащий сервер доступа к данным, вовсе не обязан содержать Delphi, С++Builder или иное средство разработки. В принципе, он может управляться c операционной системой, отличной от Windows, и в этом случае может потребоваться по-другому конфигурировать доступ к данным (например, настроив соответствующим образом клиентскую часть какой-либо серверной СУБД).
Для создания сервера требуется создать несколько SQL-предложений. Entera на их основе автоматически создаст серию вызовов удаленных процедур, выполняющих типичные задачи модификации данных, такие как выбор, вставка, удаление или изменение записи.
Создадим простейший пример такого скрипта для таблицы Animals.dbf из каталога DBDEMOS:
select_animals: SELECT NAME,SIZE,WEIGHT,AREA FROM ANIMALS; insert_animals: INSERT INTO ANIMALS (NAME,SIZE,WEIGHT,AREA) VALUES($NAME[CHAR],$SIZE[DOUBLE],$WEIGHT[DOUBLE],$AREA[CHAR]); delete_animals: DELETE FROM ANIMALS WHERE NAME='$NAME'; update_animals: UPDATE ANIMALS SET NAME= '$NAME', SIZE='$SIZE', WEIGHT='$WEIGHT', AREA= '$AREA' WHERE NAME='$NAME';
Теперь можно создать командный файл для превращения SQL-скрипта в сервер функциональности и загрузить последний в оперативную память.
SET DB_LOGIN= SET DB_PWD= start "Demo server" clistart -d edemo -s demo -e server.env -q anim.sql
Первые две строки устанавливают переменные среды, проверяемые сервером баз данных. В третьей строке с помощью команды start в окне с именем "Demo server" запускается утилита clistart — сервер доступа к данным, использующий ODBC-сервисы. Параметр этой утилиты -d указывает на имя ODBC-источника, созданного ранее. Параметр -s присваивает серверу имя demo. Параметр -e указывает на имя файла конфигурации. Параметр -q указывает на имя SQL-скрипта.
Файл конфигурации может выглядеть следующим образом:
DCE_BROKER=elmanova, 16000 DCE_LOG=SERVER.LOG DCE_DEBUGLEVEL=D,D В
В первой строке этого файла указывается, где выполняется брокер.
В результате выполнения этого командного файла сервер будет загружен в оперативную память.
Окно сервера также представляет собой стандартное окно запущенного 32-разрядного консольного приложения.
Отметим, что при использовании другого способа доступа к данным для создания сервера следует использовать соответствующую надстройку над клиентской частью серверной СУБД. Например, в случае доступа к Oracle такая надстройка называется orastart.exe, и в качестве параметра -d в этом случае указывается имя TNS-псевдонима соответствующей базы данных.
При создании сервера доступа к данным на платформе, отличной от Windows, следует использовать соответствующие версии утилит типа orastart. Команды и командные файлы также должны быть приведены в соответствие правилам используемой операционной системы. Выполнять их можно также в терминальном режиме или в терминальном окне — сервер доступа к данным не обладает пользовательским интерфейсом (но может создавать log-файлы, что обычно и используется).
2.3. Создание клиентского приложения с помощью Delphi или C++Builder Enterprise
После создания и запуска сервера доступа к данным можно приступить к созданию клиентского приложения.
Запустим Delphi 3 Enterprise (или C++Builder 3 Enterpise) и создадим новое приложение. На главной форме приложения поместим компоненты TEnteraConnection, TEnteraProvider, TClientDataset, TDataSource, TDBGrid и TDBNavigator. Установим свойство SQLFile компонента TEnteraConnection равным имени SQL-скрипта (его следует скопировать на компьютер, где будет функционировать клиент). Установим свойство ConfigFile этого же компонента равным имени файла окружения:
DCE_BROKER=elmanova, 16000 DCE_LOG=client1.LOG DCE_DEBUGLEVEL=D,D
Использование этого файла необходимо для того, чтобы клиент мог найти брокер в сети.
СвойствоTransportName компонента TEnteraConnection должно быть установлено равным tmTCP. Cвойство ServerName должно содержать имя сервера (значение параметра -s).
Далее свойство Server компонента TEnteraProvider следует установить равным имени компонента TEnteraConnection. После этого следует выбрать из выпадающих списков значения свойств SelectRPC, InsertRPC, DeleteRPC, UpdateRPC.
Далее следует установить свойство Provider компонента TClientDataSet равным имени компонента TEnteraProvider. Свойство RemoteServer следует оставить пустым (в отличие от случая использования этого компонента с серверами, управляемыми MIDAS).
Теперь можно установить свойство Active этого компонента равным true и связать его с источником данных и интерфейсными элементами формы (рис. 4. )
Теперь можно сохранить проект, скомпилировать и запустить его.
2.4. Передача параметров на сервер
Предположим, нам нужно выполнить параметризованный запрос:
select_animals: SELECT NAME,SIZE,WEIGHT,AREA FROM ANIMALS WHERE NAME=$NAME[CHARACTER];
Внесем соответствующие изменения в SQL-скрипт и перезапустим сервер.
Если теперь в клиентском приложении раскрыть список подсвойств SelectRPC компонента TEnteraProvider и выбрать подсвойство Params, можно просмотреть список всех параметров запроса и обнаружить, что параметр NAME изменил значение своего свойства ParamType на ptInput.
Модифицируем клиентское приложение, добавив компонент TEdit и кнопку.
Добавим обработчик события, связанный с нажатием на эту кнопку. Код для С++Builder при этом будет выглядеть так:
void __fastcall TForm1::Button1Click(TObject *Sender ) { ClientDataSet1->Close(); EnteraProvider1->SelectRPC->Params->Items[0]->Value=Edit1->Text; ClientDataSet1->Open(); }
Соответствующий код для Delphi выглядит так:
procedure TForm1.Button1Click(Sender: TObject); begin ClientDataSet1.Close; EnteraProvider1.SelectRPC.Params[0].Value:=Edit1.Text; ClientDataSet1.Open; end;
Теперь можно сохранить, скомпилировать и запустить клиентское приложение.
Отметим, что создание сервера доступа к данным с использованием стандарта DCE (Distributed Computing Environment), предоставляющего доступ к данным, и клиентского приложения с помощью Delphi/C++Builder Enterprise мало чем отличается от создания сервера и клиента с использованием непосредственного доступа с помощью TCP/IP.
Для создания DCE-сервера следует иметь DCE-версии файлов clistart.exe (или orastart.exe и т.д.) и odet30.dll. Следует также позаботиться о корректных значениях переменных окружения ODEDIR и PATH:
SET ODEDIR=C:\OPENENV\ENTERA\DCE PATH=%ODEDIR%\BIN;%PATH%
Файл конфигурации в данном случае имеет расширение DAP (Distributed Application Profile) и имеет примерно следующий вид:
[DCEApp] Broker=ncan_in_tcp:elmanova[] LogFile=client.log LogLevel=3
Во второй строке этого файла содержатся сведения о сетевом протоколе и имени компьютера, на котором функционирует брокер. В квадратных скобках указывается номер порта. Если они пусты, используется значение по умолчанию. Какой именно порт используется по умолчанию, можно определить, просмотрев log-файл, имя которого указано во второй строке конфигурационного файла. Третья строка указывает уровень вывода отладочных сообщений в log-файл.
Перед запуском сервера следует запустить брокер:
SET ODEDIR=C:\OPENENV\ENTERA\DCE PATH=%ODEDIR%\BIN;%PATH% start "Entera Broker" brk
Для запуска сервера следует выполнить команду:
start clistart -d edemo -e server.dap -q anim.sql
(в случае использования ODBC — источника данных) или
start orastart -d TEST1 -e server.dap -q ora1.sql
(в случае использования ORACLE).
Создание DCE-клиента с помощью Delphi/C++Builder Enterprise практически не отличается от создания TCP-клиента. Основные отличия заключаются в другом значении свойства TransportMode компонента TEnteraConnection — оно должно быть равно tmDCE, и в выборе другого имени конфигурационного файла (сlient.dap), имеющего примерно следующий вид:
[DCEApp] Broker=ncan_in_tcp:ws13[] LogFile=dbserv.log LogLevel=3
При запуске клиентского приложения оно обращается к брокеру, который, в свою очередь, находит для клиента один из запущенных серверов. После этого клиент соединяется непосредственно с сервером.
Как протестировать работу брокера и убедиться, что при наличии нескольких серверов в сети подключение клиентов к ним производится случайным образом (что позволяет осуществить баланс загрузки серверов)? Самый простой тест может заключаться в использовании доступа к каким-либо локальным таблицам с помощью серверов доступа к данным (например, той же самой таблицы Animals.dbf). Если в локальных версиях этих таблиц, содержащихся на разных компьютерах, где имеются серверы функциональности, будут содержаться разные данные, то каждый раз при запуске клиентского приложения в интерфейсных элементах формы будут также отображаться разные данные. Можно также поместить на форму клиентского приложения какой-нибудь интерфейсный элемент, осуществляющий установку и разрыв соединения с сервером, чтобы не перезапускать клиентское приложение.
В заключение отметим, что создание клиентских приложений может быть осуществлено не только с помощью Delphi/C++Builder Enterprise, но и при помощи многих других средств разработки, в том числе 16-разрядных (например, SQL Windows, Visual Basic, Delphi 1.0 или Delphi 2.0 Desktop). В этом случае следует использовать для соответствующего языка программирования генератор stub-кода, содержащего вызовы удаленных процедур, связанные с выполнением SQL-запросов (он входит в комплект поставки Entera и называется Object Interface Generator), и затем встраивать сгенерированный код в клиентское приложение, то есть использовать стандартные методы создания клиентских приложений, рассмотренные в следующем разделе. Компоненты TEnteraConnection и TEnetraProvider фактически просто реализуют функциональность, которая в ином случае содержалась бы в сгенерированном stub-коде.
3. Реализация вызовов удаленных процедур (RPC). Создание серверов функциональности и клиентских приложений
Помимо функциональности, связанной с доступом к базам данных, можно использовать Entera для реализации любой другой функциональности, то есть использовать RPC (Remote Procedure Calls — вызовы удаленных процедур) для удаленного доступа к функциям, осуществляющим любые другие действия (например, расчеты).
Отметим, что RPC являются основой механизма обмена данными между клиентом и сервером в рассмотренных выше примерах. Генерация этих вызовов осуществляется неявно при использовании компонента TEnteraProvider.
Ниже будут рассмотрены примеры явного вызова RPC (так называемые Simple RPC Calls). В этом случае следует создать stub-код для сервера и клиента; напомним, что вызовы удаленных процедур осуществляются за счет обмена пакетами данных (эта процедура иногда называется маршалингом, или маршрутизацией) между двумя stub-объектами в адресных пространствах сервера и клиента (подробнее об этом рассказано в первой статье данного цикла).
С целью иллюстрации этой процедуры создадим простейший TCP-сервер с помощью Entera 3.2.
3.1. Создание DEF-файла
Рассмотрим какую-либо функцию, написанную на Pascal, например, для вычисления синуса путем разложения в ряд:
function sin1(x: Double): Double; VAR I:INTEGER; R:DOUBLE;SL:DOUBLE;XX:DOUBLE; CONST DELTA=0.0001 ; begin SL:=X; I:=1; R:=0; XX:=X*X; WHILE (ABS(SL)>DELTA) DO BEGIN R:=R+SL; SL:=-(SL*XX/(2*I))/(2*I+1); inc(i); END; result:=R; end;
Реализация ее с помощью C++ выглядит так:
double sin1(double x) { int ii; double xx,r,sl,f,delta=0.0001; sl=x; ii=1; r=0; xx=x*x; f= fabs(sl); while (f>delta) { r=r+sl; sl=-(sl*xx/(2*ii))/(2*ii+1); f=fabs(sl); ii=ii+1 ; } return(r); }
Создадим простейшее приложение для тестирования этой функции:
unit SINTST; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, Buttons, TeEngine, Series, ExtCtrls, TeeProcs, Chart,a1; type TForm1 = class(TForm) Chart1: TChart; Series1: TFastLineSeries; BitBtn1: TBitBtn; procedure BitBtn1Click(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.DFM} function sin1(x: Double): Double; VAR I:INTEGER; R:DOUBLE;SL:DOUBLE;XX:DOUBLE; CONST DELTA=0.0001 ; begin SL:=X; I:=1; R:=0; XX:=X*X; WHILE (ABS(SL)>DELTA) DO BEGIN R:=R+SL; SL:=-(SL*XX/(2*I))/(2*I+1); inc(i); END; result:=R; end; {sin1} procedure TForm1.BitBtn1Click(Sender: TObject); VAR I:INTEGER;X:DOUBLE;Y:DOUBLE; begin FOR I:=1 TO 270 DO BEGIN X:=0.1*I; //Y:=SIN1(I); Y:=sin1(X); CHART1.SERIES[0].ADDXY(X,Y,FLOATTOSTR(X),clwHITE); END end; end.
Предположим, нам нужно разделить это приложение на сервер функциональности, вычисляющий синус, и «тонкий» клиент, рисующий график этой функции. В этом случае создание сервера функциональности следует начать с определения его интерфейса, для чего следует создать DEF-файл с описанием интерфейса этой функции на языке IDL (Interface Definition Language); вспомним, что IDL фактически представляет собой стандарт описания интерфейсов и все его диалекты похожи друг на друга.
[ uuid(cdf19a00-22c8-11d2-a36c-008048eb72de), version(1.0) ] interface a1{ double sin1( [in] double x); }
Этот код присваивает серверу уникальный код UUID (Universal Unique Identifier), который можно сгенерировать с помощью алгоритма, определенного Open Software Foundation и реализованного в ряде утилит и функций (например, есть функция Windows API CoCreateGUID, реализующая этот алгоритм). В случае TCP-сервера в действительности он не используется, так же как и номер версии сервера, но используется в случае DCE-сервера. Затем объявляется интерфейс сервера, в котором можно описать несколько функций (в нашем случае она одна).
При написании DEF-файлов следует учитывать соответствие типов данных в DEF-файлах и используемых для создания серверных и клиентских частей языков программирования:
Объявления в DEF-файле | Входные параметры Pascal | Выходные параметры Pascal |
---|---|---|
Short x | x: Smallint | var x: Smallint |
long x | x: Longint | var x: Longint |
int x | x: Integer | var x: Integer |
float x | x: Single | var x: Single |
double x | x: Double | var x: Double |
char x | x: Char | var x: Char |
3.2. Генерация кода для сервера и клиента
Для создания серверной и клиентской части распределенной системы на базе Entera следует сгенерировать stub-код («заглушку»), превращающую простые вызовы функций в вызовы удаленных процедур. В частности, при использовании удаленной функции следует сообщить компилятору о том, что ее реализация находится не в клиентском приложении, а на удаленном сервере. «Заглушка» нужна для того, чтобы компилятор мог найти нужную функцию, а ее реализация представляет собой код, осуществляющий вызов удаленных процедур.
Генерация stub-кода для сервера и клиента осуществляется автоматически с помощью утилиты rcmake.exe. Ee параметры в случае любой 32-разрядной версии Delphi выглядят так:
rpcmake -d myserv.def -c delphi2.0 -s delphi2.0
В случае С или С++ параметры rpcmake выглядят следующим образом:
rpcmake -d myserv.def -c c -s c
Здесь параметр -d - имя DEF-файла, -c — язык, для которого должен быть сгенерирован клиентский stub-код, -s — язык, для которого должен быть сгенерирован серверный stub-код (eстественно, эти языки могут быть разными).
В каталоге Entera\TCP\BIN имеется также утилита rpcmgui.exe, представляющая собой GUI-оболочку для rpcmake.exe.
Наиболее близким описанному выше процессу генерации кода из знакомых Windows-программистам процедур является, пожалуй, генерация stub- и proxy-кода Microsoft Visual C++ для динамически загружаемых библиотек, используемых в COM-сервере и COM-клиенте, с помощью компилятора MIDL на основании IDL-описания интерфейсов сервера. Отметим, что автоматическая генерация stub-кода на основании описания интерфейсов является сейчас общепринятым процессом при организации распределенных вычислений; создание такого кода «вручную» используется сегодня довольно редко.
3.3. Создание серверной части (Delphi)
В результате использования утилиты rpcmake.exe с парамерами, соответствующими выбору Delphi в качестве языка для сервера, получим следующие файлы: a1_c.pas (stub-код, который можно встраивать в клиентское приложение), a1_s.dpr (исходный текст консольного приложения для сервера функциональности), a1.pas — файл-заготовка, используемая при создании сервера, в который разработчику следует добавить код реализации функций (примерно так, как пишутся обработчики событий), a1.inc — код, содержащий объявления функций без их реализации (секция интерфейса).
Код для сервера a1_s.dpr, сгенерированный этой утилитой, выглядит следующим образом:
{$APPTYPE CONSOLE} program a1_s; uses SysUtils, ODET3020, a1; procedure rpc_sin1(dce_table: PTable; socket: Integer); var rv : Integer; x : Double; begin x := dce_pop_double(dce_table,'x'); dce_push_double(socket,'dce_result',sin1(x)); end; procedure rpc_handle(func: PChar; table: PTable; socket: Integer); begin if (StrComp(func,'sin1')=0) then rpc_sin1(table,socket) else dce_unknown_func(func, table, socket); end; {Constants and global variables follow} const VARLEN = 100; var ode_file : PChar; ode_server : PChar; dce_func : PChar; argarr : array[0..5] of array[0..VARLEN] of Char; argptrs : array[0..5] of PChar; argv : PChar; argc : Integer; dce_table : PTable; called_init_func : Integer; socket, rsocket, i, rv : Integer; msgstr : String; begin {main} GetMem(ode_file,VARLEN); GetMem(ode_server,VARLEN); GetMem(dce_func,VARLEN); called_init_func := 0; FillChar(argarr,SizeOf(argarr),#0); FillChar(argv,SizeOf(argv),#0); for i := 0 to ParamCount + 1 do begin StrCopy(argarr[i],PChar(ParamStr(i))); argptrs[i] := @argarr[i]; end; {for} argc := ParamCount + 1; argv := @argptrs; rv := parse_args(argc, argv, ode_file); if (rv=0) then begin Writeln('Env flag (-e) not set'); if ParamCount > 1 then StrCopy(ode_file,PChar(ParamStr(ParamCount))); end; if (dce_setenv(ode_file,NIL,NIL) = 0) then begin msgstr := 'Set env '+ode_file^+' failed'; WriteLn(msgstr); msgstr := 'Reason: '+dce_errstr; Writeln(msgstr); Halt(1); end; ode_server := dce_servername('a1'); dce_checkver(2, 0); socket := dce_init_server(ode_file,ode_server); if (socket <= 0) then begin Writeln('setup server failed'); Writeln('Reason: '+dce_errstr); dce_set_exit; end; while(True=True) do begin dce_table := dce_waitfor_call(socket,dce_func); if (Boolean(dce_should_exit) or Boolean(dce_err_is_fatal)) then Exit else begin if (Boolean(dce_server_is_ded)) then begin dce_spawn(socket,argc,argv,ode_file,ode_server); socket := dce_retsocket; (* save for future *) end; rsocket := dce_retsocket(); (* (old socket closed) *) rpc_handle(dce_func,dce_table,rsocket); dce_send(rsocket,dce_func); dce_recv_conf(rsocket); dce_release; dce_table_destroy(dce_table); if (dce_server_is_ded=0) then dce_close_socket(rsocket); end; {else} end; {while} FreeMem(ode_file,VARLEN); FreeMem(ode_server,VARLEN); FreeMem(dce_func,VARLEN); dce_close_socket(rsocket); dce_table_destroy(dce_table); end.
Секция интерфейса a1.inc выглядит следующим образом:
function sin1(x: Double): Double;
Код реализации функций a1.pas имеет следующий вид (жирным шрифтом выделены строки, которые следует добавить разработчику):
unit a1; interface uses SysUtils, ODET3020; {$include a1.inc} implementation function sin1(x: Double): Double; VAR I:INTEGER; R:DOUBLE;SL:DOUBLE;XX:DOUBLE; CONST DELTA=0.0001 ; begin SL:=X; I:=1; R:=0; XX:=X*X; WHILE (ABS(SL)>DELTA) DO BEGIN R:=R+SL; SL:=-(SL*XX/(2*I))/(2*I+1); inc(i); END; result:=R; end; {sin1} end. {unit}
Cервер можно скомпилировать из среды разработки или из командной строки, вызвав компилятор Pascal:
Dcc32 -b a1_s.dpr
Перед компиляцией проекта файл ODET3020.pas (интерфейс к ODET3020.DLL — библиотеке, содержащей Entera API) следует поместить в тот же каталог, что и компилируемый проект. Исполняемый файл также требует наличия этой библиотеки в каком-либо доступном каталоге.
Полученный сервер функциональности, как обычно, представляет собой консольное приложение.
3.4. Создание серверной части (C/C++)
В результате использования утилиты rpcmake.exe (или rpcmgui.exe) с парамерами, соответствующими выбору C или C++ в качестве языка для сервера, получим следующие файлы: a1_c.c (stub-код, который можно встраивать в клиентское приложение), a1_s.c (исходный текст консольного приложения для сервера функциональности), a1_s.h - h — файл для myserv_s.c, a1.h — h- файл, содержащий объявления функций без их реализации (используется в клиентском приложении). Реализацию этих функций (a1.c) следует создать разработчику.
Код для сервера a1.с, сгенерированный этой утилитой, выглядит следующим образом:
/*######################## # Server Proxy Procedure Code # generated by rpcmake version2.0 # on Thursday, December 31, 1998 at 19:17:39 # # interface: a1 # ######################## # server stub routines # ########################*/ #ifdef __mpexl #include "dceinc.h" #else #include#endif #include #include #include #ifdef __cplusplus extern "C" { #endif /* RPC stub and stub handle definitions */ void rpc_handle (char *, struct table *, int); void rpc_sin1 (struct table *, int); #ifdef __cplusplus } #endif void rpc_sin1 (struct table *dce_table,int Socket) { double x; int _i; double sin1(double); x = dce_pop_double(dce_table,"x"); dce_push_double(Socket,"dce_result", sin1(x)); } int main(int argc,char **argv) { char *ode_file = NULL,*ode_server = NULL; char dce_func[VARLEN]; struct table *dce_table; int called_init_func = 0; int socket,rsocket; if (!parse_args(&argc, argv,&ode_file)) { printf ("Env flag (-e) not set\n"); ode_file = argc > 1 ? argv[argc-1] : (char *) NULL; } if (dce_setenv(ode_file,NULL,NULL) == 0) { fprintf(stderr,"Set env %s failed\n", ode_file); fprintf (stderr,"Reason: %s\n", dce_errstr()); exit(1); } ode_server = dce_servername("a1"); dce_checkver(2, 0); if ((socket = dce_init_server( ode_file,ode_server)) <= 0) { fprintf (stderr,"setup server failed\n"); fprintf (stderr,"Reason: %s\n", dce_errstr()); dce_set_exit(); } while(1) { dce_table = dce_waitfor_call(socket,dce_func); if (dce_should_exit() || dce_err_is_fatal() ) {break; } else { if (dce_server_is_ded()) { dce_spawn(socket,argc,argv,ode_file,ode_server); socket = dce_retsocket(); /* save for future */ } rsocket = dce_retsocket(); /* (old socket closed) */ rpc_handle(dce_func,dce_table,rsocket); dce_send(rsocket,dce_func); dce_recv_conf(rsocket); dce_release(); dce_table_destroy(dce_table); if (!dce_server_is_ded()) { dce_close_socket(rsocket); } } } dce_close_socket(rsocket); dce_table_destroy(dce_table); return(0); } void rpc_handle(char *func,struct table *dce_table, int Socket) { if (strcmp(func,"sin1")==0) (void)rpc_sin1(dce_table,Socket); else (void)dce_unknown_func(func, dce_table, Socket); } H-файл a1_s.h выглядит следующим образом: /************************************* * * Server Header for a1 * Generated by rpcmake version 3.0 * on Thursday, December 31, 1998 at 19:17:39 * **************************************/ #ifdef __cplusplus extern "C" { #endif extern double sin1(double ); #ifdef __cplusplus } #endif
Разработчику следует создать код реализации функции, который должен иметь примерно следующий вид:
USEUNIT("A1_s.c"); USELIB("odet30.lib"); //----------------------------------------------------------------- double sin1(double x) { int ii; double xx,r,sl,f,delta=0.0001; sl=x; ii=1; r=0; xx=x*x; f= fabs(sl); while (f>delta) { r=r+sl; sl=-(sl*xx/(2*ii))/(2*ii+1); f=fabs(sl); ii=ii+1 ; } return(r); }
Отметим, что все функции, связанные с выделением памяти в обычном С-коде, следует заменить на соответствующие функции c префиксом dce_ (например, dce_malloc) из Entera API.
3.5. Тестирование сервера функциональности
Для тестирования сервера следует создать для него env-файл с описанием переменных окружения:
DCE_BROKER=elmanova,16000 DCE_DEBUGLEVEL=DEBUG,DEBUG DCE_LOG=server.log
Далее следует запустить Entera Broker (если он еще не запущен), создав предварительно конфигурационный файл broker.env:
start broker -e broker.env
Затем следует создать и запустить командный файл для запуска сервера:
set odedir = c:\OpenEnv\Entera\TCP start "IT IS A SERVER" a1_s -e server.env
Только после этого можно запускать или отлаживать клиентское приложение.
3.6. Создание клиентского приложения (Delphi)
Код, сгенерированный утилитой rpcmake для клиента Delphi (a1_c.pas), имеет следующий вид:
unit a1_c; interface uses SysUtils, Classes, ODET3020; function sin1(x: Double): Double; implementation function sin1(x: Double): Double; var dce_table : PTable; socket : Integer; rv : Integer; begin dce_table := nil; dce_checkver(2,0); socket := dce_findserver('a1'); if (socket > -1) then begin dce_push_double(socket,'x',x); dce_table := dce_submit('a1','sin1',socket); end; sin1 := dce_pop_double(dce_table,'dce_result'); dce_table_destroy(dce_table); end; end.
Этот код заставляет клиентское приложение обращатьcя к удаленной функции как к локальной. В действительности этот код представляет собой серию вызовов удаленных процедур. Все интерфейсы функций, к которым обращается клиент, содержатся в файле odet30.pas (dceinc.h), а их реализация — в файле odet30.dll.
Создадим клиентское приложение для тестирования созданного сервера. Создадим новый проект, добавим в него сгенерированный модуль a1_c.pas (a1_c.c в случае С++Builder) и сошлемся на него и на odet3020.pas в модуле, связанном с главной формой приложения. На форму поместим интерфейсные элементы, необходимые для тестирования сервера (примерно те же, что и в тестовом примере, расмотренном выше; можно сделать копию этого проекта и внести в нее необходимые изменения).
Создадим обработчики событий, связанных с нажатием на кнопки, а также с созданием и уничтожением формы:
unit sin_cln1; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, Buttons, TeEngine, Series, ExtCtrls, TeeProcs, Chart; type TForm1 = class(TForm) Chart1: TChart; Series1: TFastLineSeries; BitBtn1: TBitBtn; procedure BitBtn1Click(Sender: TObject); procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation uses a1_c, odet3020; {$R *.DFM} procedure TForm1.BitBtn1Click(Sender: TObject); VAR I:INTEGER;X:DOUBLE;Y:DOUBLE; begin FOR I:=1 TO 270 DO BEGIN X:=0.1*I; Y:=sin1(X); CHART1.SERIES[0].ADDXY(X,Y,FLOATTOSTR(X),clwHITE); END; end; procedure TForm1.FormCreate(Sender: TObject); Var rv : integer; msg : array [0 .. 200] of char; begin rv := dce_setenv ('client.env', nil, nil); if (rv = 0) then begin dce_error (msg); MessageDlg('TCP Error: ' + msg, mtInformation, [mbOK], 0); PostMessage(Handle, WM_QUIT, 0, 0); end; end; procedure TForm1.FormDestroy(Sender: TObject); begin dce_close_env; end; end.
Отметим, что при создании главной формы приложения следует вызвать процедуру dce_setenv из библиотеки odet3020.dll, указав имя конфигурационного файла client.env в качестве параметра. К моменту запуска клиента этот файл должен существовать примерно в следующем виде:
DCE_BROKER=elmanova, 16000 DCE_LOG=CLIENT.LOG DCE_DEBUGLEVEL=D,D
По окончании работы приложения следует вызвать процедуру dce_close_env, уничтожающую запущенные с помощью dce_setenv сервисы Entera.
3.7. Создание клиентского приложения (C/C++)
Код, сгенерированный утилитой rpcmake для клиента C/C++ (a1_c.c), имеет следующий вид:
/*######################## # Client Proxy Procedure Code # generated by rpcmake version 3.0 # on Thursday, December 31, 1998 at 19:17:39 # # interface: a1 # */ #include#if defined __mpexl || defined _MACINTOSH_ #include "dceinc.h" #else #include #endif double sin1(double x) { double rv = 0; int Socket; struct table *dce_table = NULL; dce_checkver(2, 0); if ((Socket = dce_findserver("a1")) >= 0) { dce_push_double(Socket,"x",x); dce_table = dce_submit("a1", "sin1", Socket); } rv = dce_pop_double(dce_table,"dce_result"); dce_table_destroy(dce_table); return(rv); } H-файл для него является следующим: **************************************/ * * Client Header for a1 * Generated by rpcmake version 3.0 * on Thursday, December 31, 1998 at 19:17:39 * **************************************/ #ifdef __cplusplus extern "C" { #endif extern double sin1(double ); #ifdef __cplusplus } #endif Код клиентского приложения, аналогичный приведенному выше для Delphi, в случае С++Builder выглядит следующим образом: //----------------------------------------- #include "dceinc.h" #include "myserv.h" USEUNIT("a1_c.c"); USELIB("odet30.lib"); //----------------------------------------- void __fastcall TForm1::FormCreate(TObject *Sender) { dce_setenv("client.env",NULL,NULL); } //--------------------------------------------------------------------------- void __fastcall TForm1::FormDestroy(TObject *Sender) { dce_release(); } //--------------------------------------------------------------------------- void __fastcall TForm1::BitBtn1Click(TObject *Sender) { int i; double x1,y; for (i=1;i<271;i++) { x1=0.1*float(i); y=sin1(x1); Chart1->Series[0]->AddXY(x1,y,FloatToStr(x1),clWhite); } } //-----------------------------------------
3.8. Создание клиентского приложения (Visual Basic)
Отметим, что клиентское приложение может быть создано с помощью любых версий и разновидностей Delphi (начиная с 1.0 и включая Standard-версии), любых версий C++Builder и вообще любых компиляторов С++. Помимо этого для создания клиентских приложений можно использовать и другие средства разработки. В качестве примера рассмотрим Visual Basic for Applications. Для начала создадим клиентский stub-код для Visual Basic, для чего произведем и выполним командный файл вида:
set ODEDIR=F:\OPENENV\ENTERA\TCP PATH=%ODEDIR%\BIN;%PATH% rpcmake.EXE -d myserv.def -c bas
В результате получим файл a1_c.vb вида:
Function sin1# (x#) dim dce_table as long, Socket as integer call dce_checkver(2,0) Socket = dce_findserver("a1") If (Socket > -1) Then Call dce_push_double(Socket,"x",x) dce_table = dce_submit("a1","sin1",Socket) End If sin1 = dce_pop_double(dce_table,"dce_result") Call dce_table_destroy(dce_table) End function
Теперь создадим новый документ MS Word 97 (или MS Excel 97), сделаем видимой панель инструментов Visual Basic, войдем в режим конструктора и выведем на экран панель интерфейсных элементов. Далее поместим в документ кнопку.
Затем дважды щелкнем на созданной кнопке и перейдем в редактор Visual Basic. Добавим к документу форму UserForm1, поместим на ней несколько меток.
Теперь создадим обработчик события, связанный с нажатием на кнопку CommandButton1 в документе (его прототип уже имеется в редакторе кода):
Private Sub CommandButton1_Click() x = sin1#(0.25) UserForm1.Label1.Caption = x x = sin1#(0.5) UserForm1.Label2.Caption = x x = sin1#(0.75) UserForm1.Label3.Caption = x x = sin1#(1#) UserForm1.Label4.Caption = x x = sin1#(1.25) UserForm1.Label5.Caption = x x = sin1#(1.5) UserForm1.Label6.Caption = x x = sin1#(1.75) UserForm1.Label7.Caption = x x = sin1#(2#) UserForm1.Label8.Caption = x x = sin1#(2.25) UserForm1.Label9.Caption = x x = sin1#(2.5) UserForm1.Label10.Caption = x x = sin1#(2.75) UserForm1.Label11.Caption = x x = sin1#(3#) UserForm1.Label12.Caption = x UserForm1.Show End Sub
После обработчика события добавим stub-код, содержащийся в сгенерированном файле a1_c.vb.
И, наконец, экспортируем в проект c помощью пункта меню Файл/Экспорт файла модуль odet30.bas из комплекта поставки Entera.Создадим файл client.env в каталоге, содержащем документ. Возможно, потребуется отредактировать присоединенный к проекту модуль, изменив параметры процедуры dce_setenv и указав путь к файлу client.env:
rv = dce_setenv("client.env", "", "")
Отметим, что библиотека odet30.dll должна быть доступна нашему приложению, так как из нее оно производит вызовы функций.Теперь можно вернуться в документ из среды разработки Visual Basic for Applications, выйти из режима конструктора и нажать кнопку в документе. На экране появится форма с результатами вызова удаленных процедур примерно следующего вида.
Напомним, что перед запуском приложения следует убедиться, что брокер и сервер запущены.
4. Управление функционированием информационной системы предприятия с помощью Inprise AppCenter
В рассмотренных в предыдущем разделе примерах требовалось запускать Entera Broker и серверы функциональности вручную. При эксплуатации системы, содержащей множество подобных серверов функциональности, выполняющихся под управлением различных платформ, процедура запуска необходимых приложений и наблюдения за их выполнением может оказаться весьма трудоемким процессом. Поэтому в таких системах нередко используются специальные средства управления серверами и наблюдения за ними. Inprise AppCenter представляет собой подобное средство, в значительной степени ориентированное на управление серверами функциональности, созданными с помощью Entera, и брокерами Entera.4.1. Обзор AppCenter
Inprise AppCenter представляет собой средство управления распределенными приложениями, позволяющее осуществлять мониторинг процессов и приложений промежуточного слоя, наблюдать за производительностью компонентов распределенной системы и устанавливать правила их функционирования (такие как баланс загрузки, связи между приложениями, создание резервных сервисов).
AppCenter состоит из пяти компонентов — утилиты просмотра (AppCenter Viewer), агента, монитора, репозитария и брокера.
Таблица 1. Компоненты AppCenter
Компонент | Описание |
---|---|
Viewer | Пользовательская утилита для конфигурации, контроля и управления приложениями |
Agent | Компонент, управляющий приложениями, содержащимися на данном компьютере. Должен присутствовать на всех компьютерах, входящих в распределенную систему, и быть запущен прежде, чем начнется управление распределенной системой |
Monitor | Средство контроля объектов, подлежащих управлению |
Repository | Централизованное хранилище данных о конфигурациях приложений и состоянии объектов, подлежащих управлению |
Broker | Сервис, способствующий поиску компонентов AppCenter |
Как видно из приведенной выше схемы, репозитарий AppCenter, хранящий сведения о сервисах промежуточного слоя, устанавливается в сети в одном экземпляре (напомним, что такие базы данных нужны в случае, если необходимо инициировать удаленный запуск сервера по запросу клиента). Компонент AppCenter Agent должен быть установлен на всех компьютерах, содержащих подлежащие управлению сервисы (он представляет собой сервис, позволяющий на определенных условиях удаленно запускать те или иные приложения, управляемые данным компьютером; напомним, что подобные сервисы в распределенных системах должны существовать обязательно, хотя бы из соображений элементарной безопасности).
AppCenter Broker также существует в одном экземпляре и предназначен, как и Entera Broker, для поиска в сети сервиса, необходимого для обратившегося клиента (то есть представляет собой Directory Service).
Что касается AppCenter Viewer, то это пользовательская утилита (написанная на Java и, соответственно, выполняемая под управлением разных платформ), позволяющая описывать правила функционирования управляемых сервисов. В сети можно иметь несколько компьютеров, содержащих AppCenter Viewer.
Каким образом происходит взаимодействие сервисов AppCenter c управляемыми сервисами? Прежде всего с помощью генерации брокером AppCenter IP-вызовов с определенной частотой c целью поиска агентов. Замеченные изменения регистрируются в базе данных. Отметим, что брокеры Entera являются по отношению к AppCenter Broker управляемыми приложениями.
4.2. Использование AppCente
Порядок запуска приложений AppCenter должен быть следующим:
1. Broker
2. Репозитарий (Database)
3. Агенты
4. Viewer
После запуска утилиты просмотра на экране появится диалог ввода имени пользователя и пароля. Далее AppCenter Viewer будет запущен в режиме редактирования. В левой части окна приложения находится навигатор, с помощью которого можно перемещаться по объектам, за которыми производится наблюдение. В правой части окна можно выбирать режимы просмотра и редактирования конфигураций.
С помощью AppCenter Viewer можно создавать так называемые конфигурации объектов, содержащие набор связанных между собой серверов функциональности или любых других приложений, описывая правила их функционирования.
4.3. Создание и редактирование конфигураций
В качестве простейшего примера создадим конфигурацию, устойчивую к сбоям. С этой целью щелкнем правой клавишей мыши по папке Configurations и из контекстного меню выберем пункт Wizards|New Entera Configuration. Введем для конфигурации имя Sinus.
Далее появится несколько диалоговых окон, в которых следует ввести данные в интерфейсные элементы. В частности, следует зарегистрировать используемые в данной конфигурации компьютеры, указать имена компьютеров, на которых функционируют серверы и брокеры, каталоги, в которых находятся исполняемые файлы серверов функциональности, указать номера TCP-портов для обращения к брокерам, и в результате будут автоматически сгенерированы env-файлы (ранее мы создавали их вручную).
В результате ответов на вопросы будет создана конфигурация из двух серверов функциональности с балансом загрузки.
Выбрав из контекстного меню опцию Properties, можно изменить свойства управляемых объектов (например, число попыток повторного запуска после остановки сервера).
Выбрав закладку Dependencies, можно установить связи между объектами (например, указать, какой брокер Entera обслуживает данный набор серверов).
Выбрав закладку Hosts, можно просмотреть или переопределить связи между компьютерами и серверами.
Теперь можно запустить конфигурацию и пронаблюдать, как поочередно запускаются объекты (в нашем случае исполняемые файлы a1_s.exe). Если это приложение принудительно закрыть, AppCenter будет снова пытаться запустить его, пока не будет достигнуто число попыток, указанное в параметре Weighting.
Можно создать конфигурацию и без использования экспертов, выбирая пункт New из соответствующих контекстных меню и определяя свойства вновь созданных объектов. Есть также возможность создания так называемых DUMMY-конфигураций, то есть конфигураций, не соответствующих никаким реальным объектам, с целью моделирования их поведения. Для имитации их поведения можно создавать макросы AppCenter.
Примерно так же можно создавать группы приложений, устойчивые к сбоям, в которых имеются основные и резервные дублирующие их объекты.
AppCenter обладает возможностью установки самых разнообразных правил функционирования объектов. В частности, можно организовать запуск и остановку конфигураций и отдельных объектов согласно расписанию (для этой цели в AppCenter можно создавать таймеры), определять, какой сервер является дублирующим для данного сервера, и др. Все сведения о конфигурациях, объектах, таймерах хранятся в общем репозитарии.
Отметим, что объекты AppCenter обычно создаются на основе шаблонов с заранее предопределенными свойствами. Однако у серверов функциональности могут быть и собственные характеристики, за которыми необходимо осуществлять наблюдение, например количество или интенсивность RPC-вызовов, объем передаваемых данных. Чтобы наблюдаемые объекты могли предоставлять такие характеристики, они должны содержать экспортирующие их вызовы функций Enterprise Management Interface (EMI) API (обсуждение которого выходит за рамки данной статьи). В этом случае следует создать собственный шаблон управляемого объекта (например, на основе уже имеющегося).
Для собственного шаблона объектов можно определить дополнительные свойства, которые при создании объектов на основе этого шаблона могут быть доступны для редактирования или наблюдения.
4.4. Мониторинг объектов
Существует несколько режимов работы AppCenter Viewer. Режим редактирования объектов был рассмотрен нами ранее. Помимо него имеется также режим мониторинга объектов.
Еще один режим (Icon Mode) позволяет отображать Viewer в виде пиктограммы, которая меняет вид и становится движущейся, если произошел сбой в работе какого-либо из управляемых объектов.
Последний из возможных режимов — Cockpit Mode — позволяет различными способами отображать параметры функционирования объектов (такие как число обращений клиентских приложений, время отклика и др.), а также вести журнал событий.
Cockpit (в переводе это слово означает «кабина самолета с приборными панелями») представляет собой набор графических объектов для отображения свойств наблюдаемых объектов. Создается он в режиме редактирования с помощью опции меню Cockpit/New. Методом drag-and-drop на появившуюся пустую форму можно перетаскивать пиктограммы наблюдаемых объектов. Далее из появившейся диалоговой панели можно выбрать тип графика и отображаемое свойство объекта, а также характеристики, специфические для данного способа отображения (высоту графика, цвет, масштаб и др.).
Типичный Cockpit выглядит примерно так.
При этом диаграммы, содержащие динамические параметры, меняются в соответствии с установленным при их создании значением частоты обновления.
В заключение отметим, что с помощью Inprise AppCenter можно управлять не только серверами или брокерами Entera, но и любыми другими приложениями, если таковые зарегистрированы в его репозитарии.
Российское представительство Inprise:
Тел.: 7(095)238-36-11
e-mail: info@inprise.ru
КомпьютерПресс 3'1999