Začátkem druhé poloviny 80. let, kdy se počítače začaly čím dál více vměšovat
do běžného života, se architektura klient-server začala rozvíjet stále
rychlejším tempem. Nejdříve se začala uplatňovat na mainframech a s nástupem
databázového inženýrství i na databázových serverech.
Z prostředků, které programátoři zprvu používali ve svých aplikacích, jasně
převládalo jejich vlastní proprietární řešení. Tento stav nedovoloval
propojení programového vybavení mezi více výrobci a mnohdy ani mezi produkty
jednoho výrobce.
Jedním z prvních standardů bylo RPC firmy Sun Microsystems. Toto řešení ovšem
nezachytilo rozjíždějící se vlak objektových technologií, ale i tak se dodnes
používá (např. v souborovém systému NFS). Nedlouho po boomu Internetu se
začaly hledat technologie, které by propojily programové vybavení jak přes
síť, tak mezi jednotlivými výrobci a to s co nejmenšími náklady (finančními a
intelektuálními). S nástupem dvouúrovňové architektury (two-tier) a později
tří a více úrovňových architektur (three/multi-tier) se začal vyvíjet
objektový distribuovaný systém, který by byl nezávislý na platformě jak
hardwarové, softwarové (operační systém), tak i na implementační (programovací
jazyk).
Klient-server a co dál?
Na počátku byla architektura klient-server, která byla používána již od roku
1980, ale až koncem 80. let získala na popularitě (zvláště na mainframech,
později v databázích). Zde si vývojáři sami implementovali vlastní systém pro
vzdálená volání ať už funkcí či metod při nástupu objektových technologií,
což v důsledku znamenalo sice rychlý rozvoj technologie, ale také poněkud
chaos a jistou nekompatibilitu mezi jednotlivými produkty. Tehdy se začaly
firmy sdružovat do různých konsorcií, která měla za úkol nastolit pořádek.
S nástupem tříúrovňové (three-tier) a víceúrovňové (multi-tier) architektury v
90. letech, se řada problémů odbourala, a to vložením další vrstvy (vrstev)
mezi klienta a server. Tato mezivrstva (často nazývaná aplikační server)
logicky odděluje účastníky, může také přidávat další funkcionalitu (např.
transakce, zpracování zpráv, připojení k databázovým serverům) a zvyšuje
výkonnost celého systému. Současně s vývojem architektur došlo i k rozvoji
Internetu a vznikl problém propojení různorodých počítačů a jejich operačních
systémů. Nastala otázka, jak spojit rozdílné operační systémy.
Jedna z mála technologií, které se v tříúrovňové architektuře úspěšně
používají, je CORBA. Vytváří jednotný objektový model, který není nezávislý na
operačním systému, programovém vybavení, programovacím jazyku a na síťovém
spojení počítače. Úspěšně, jednoduše a elegantně se vypořádala s heterogenním
prostředím, které je v současné době tím nejpalčivějším problémem ať už
podnikových sítí na straně jedné, nebo Internetu na straně druhé.
V současné době není problém zpřístupnit pomocí standardu CORBA (CORBA by se
mělo v češtině skloňovat buď předsunout slovo standard, které skloňovat
můžeme, nebo by to mělo znít CORBAy (což je strašné, že)) nesíťové staré
aplikace, které se v podnicích používají s uživateli a to tak, že pro
uživatele není rozdílu v tom, odkud k nim přistupují.
Object Management Architecture (OMA)
Historie architektury CORBA začíná v roce 1989, kdy byla založena OMG (Object
Management Group). Organizace, původně čítající 8 členů, v dnešní době
sdružuje přes 800 společností, firem a univerzit. Jejími členy jsou v podstatě
všichni významní výrobci softwaru i hardwaru (Sun, IBM, HP, atd.). Hlavním
cílem OMG je poskytnout svým členům prostředí pro vzájemnou komunikaci
vyúsťující v tvorbu široce přijímaných a životaschopných standardů pro oblast
distribuovaných objektově-orientovaných systémů.
Základem zapouzdřujícím všechny OMG technologie je OMA, poprvé zveřejněná v
roce 1991 v publikaci "Object Management Architecture Guide". Tvoří ji 2
části: základní objektový model (Core Object Model) a referenční model
(Reference Model).
Základní objektový model
Přístup OMG k chápání objektově-orientovaného paradigmatu je odražen v
základním objektovém modelu. Ten definuje základní koncepty a pojmy, jakými
jsou např. objekt, rozhraní (interface), operace (operation), dědičnost
(inheritance), atd. Všechny tyto pojmy jsou definovány jako čistě abstraktní,
bez jakékoliv návaznosti na konkrétní implementace.
Základní objektový model může být rozšířen o další koncepty, které pak tvoří
komponentu (component). Komponenty by měly být ortogonální jak k základnímu
modelu, tak i k sobě navzájem (tj. koncepty v nich obsažené by se neměly
vzájemně překrývat, duplikovat či vylučovat). Kombinací základního modelu a
jedné či více komponent vzniká profil (profile). Typickými příklady profilů
jsou např. CORBA, či ODP Reference Model.
Referenční model
Základní infrastruktura aplikací spolu se strukturou služeb, které tyto
aplikace mohou využívat, je definována v referenčním modelu. Tento definuje
následujících 5 základních komponent OMA:
Object Request Broker (ORB) je páteří celé architektury propojující ostatní
zbylé komponenty. Zajišťuje komunikaci mezi jednotlivými objekty v
distribuovaném prostředí formou doručování požadavků (requests) a následných
odpovědí (replies).
Object Services jsou základní služby se standardizovaným rozhraním, které
vývojáři aplikací mohou potřebovat k vyhledávání a spravování distribuovaných
objektů, koordinaci složených operací, atd. Příkladem takové služby může být
naming, trading, perzistence nebo podpora pro transakční zpracování.
Common Facilities sdružují rozhraní objektů jdoucí napříč aplikačním doménám.
Příkladem mohou být např. Distributed Document Componet Facility,
Internationalization Facility nebo Time Facility.
Domain Interfaces standardizují rozhraní objektů charakteristických pro
určitou aplikační doménu (oblast). Takovými oblastmi mohou být např.
telekomunikace, zdravotnictví či elektronické obchodování.
Application Objects jsou objekty specifické ryze pro konkrétní aplikaci. Tato
komponenta jako jediná není standardizována OMG.
Object Request Broker (ORB)
Základní komponentou architektury OMA je ORB, jehož funkcionalitu OMG
specifikuje v architektuře CORBA (Common Object Request Broker Architecture).
Jedná se o objektovou sběrnici, která objektům umožňuje transparentně vysílat
požadavky směrem k jiným objektům (ať již lokálním nebo vzdáleným) a následně
od těchto objektů přijímat odpovědi.
Klientská strana
K vyslání požadavku směrem k serverovému objektu, je klientu k dispozici
dvojí mechanismus: statické či dynamické vyvolání. Jednodušší a mnohem častěji
využívané statické vyvolání (SII Static Invocation Interface) je založeno na
znalosti rozhraní cílového objektu v době kompilace klienta. Definice
rozhraní zapsaná v jazyce IDL je využita k automatickému vytvoření stubů
(stubs) pro všechny metody daného rozhraní; chce-li klient zavolat určitou
operaci nad cílovým objektem, zavolá odpovídající stub, ten vezme všechny
parametry volání, které spolu s identifikací dané operace zabalí do zprávy
(marshalling) a předá jádru ORBu k doručení.
Dynamické vyvolání (DII Dynamic Invocation Interface) se používá v ne tak
často se vyskytujících případech, kdy rozhraní cílového objektu není dopředu,
v době kompilace klienta, známo. V tomto případě je nutné dynamicky, za běhu
aplikace, zjistit IDL rozhraní cílového objektu, na základě této informace
připravit potřebné parametry konkrétní-ho volání, tyto "ručně" vložit do
zprávy a předat ORBu k doručení.
Programátor tak vlastně zastupuje práci stubu. K dynamickému zjištění IDL
rozhraní cílového objektu lze použít Interface Repositorty (IR). IR je obvykle
samostatný server, který skrze standardizované rozhraní poskytuje IDL
definice CORBA objektů běžícím aplikacím.
Cílový CORBA objekt je v klientském adresovém prostoru obvykle zastupován
jiným objektem, tzv. proxy. V případě statického vyvolání má tato proxy stejné
rozhraní jako cílový objekt a jejími metodami jsou stuby. Lokální volání
metody nad proxy má tedy za následek pro klienta transparentní vyvolání
odpovídající metody nad cílovým objektem (tento mechanismus již známe z RPC).
Zbývá dodat, že pro serverovou stranu aplikace je transparentní, zda byl
požadavek zaslán skrze SII nebo DII.
Serverová strana
K doručení požadavku cílové implementaci na straně serveru může být taktéž
použito statického či dynamického mechanismu. Statický mechanismus (SSI Static
Skeleton Interface) opět vyžaduje znalost rozhraní cílového objektu již v době
kompilace serveru. K přijetí požadavku, vybalení parametrů a zavolání
implementace je použit automaticky generovaný skeleton.
Na druhé straně dynamický mechanismus (DSI Dynamic Skeleton Interface),
obdobně jako na straně klienta, nevyžaduje v době kompilace serveru žádnou
znalost rozhraní cílového objektu. Implementace od ORBu obdrží zprávu a je
sama zodpovědná za vyjmutí identifikace požadované operace, vybalení a
správnou interpretaci parametrů volání a za následné vykonání požadované
operace. Opět, ke zjištění očekávaného počtu a typu parametrů konkrétního
volání, lze použít Interface Repository.
Mezivrstvou mezi jádrem ORBu a implementacemi objektů je objektový adaptér
(Object Adapter), zakrývající z pohledu jádra ORBu rozdíly v prostředí, v němž
žijí implementace CORBA objektů. ORB tedy může být doplněn např. speciálním
adaptérem do prostředí databáze zprostředkujícím v databázi uložená data jako
CORBA objekty.
Standardně jsou definovány 2 adaptéry do objektově-orientovaných prostředí.
Starší, základní objektový adaptér (BOA Basic Object Adapter) a od verze CORBA
2.2 i nový, přenositelný objektový adaptér (POA Portable Object Adapter). Mezi
funkce objektových adaptérů patří např. vytváření a správa objektových
referencí (object references), aktivace či deaktivace cílových objektů, atd.
Objektové adaptéry obvykle spolupracují s Implementation Repository (ImplR),
kde se mohou nacházet data potřebná pro aktivaci CORBA objektů. Struktura
ImplR není standardizována a tudíž informace o CORBA objektech ukládané do
ImplR se u různých implementací ORBu liší.
Rozhraní ORBu, jádro ORBu a interoperabilita
Funkce ORBu, mezi něž patří např. duplikování či rušení objektových referencí,
jejich převod do řetězcové podoby, zjišťování rozhraní daného CORBA objektu
atd., jsou klientům i serverům zpřístupněny přes standardizované rozhraní (ORB
Interface).
Co se týče jádra ORBu, jeho podoba nebyla zpočátku standardizována. Až teprve
ve standardu CORBA 2.0 byl specifikován protokol GIOP (General Inter-ORB
Protocol) a jeho verze pro prostředí sítí TCP/IP a Internetu IIOP (Internet
Inter-ORB Protocol). V rámci těchto protokolů je definován formát zpráv
předávaných mezi klientem a serverem, který spolu s jednotným formátem
objektových referencí umožňuje interoperabilitu mezi ORBy různých výrobců.
Jazyk IDL a jeho mapování
Důležitým prvkem standardu CORBA je jazyk IDL (Interface Definition
Language), s jehož pomocí se, jak již název napovídá, definují rozhraní CORBA
objektů. Je to čistě deklarativní jazyk; nelze v něm zapsat žádný výkonný kód.
Syntaxe jazyka IDL, až na několik drobností, vychází z programátorům známé
syntaxe jazyka C++.
IDL specifikace rozhraní CORBA objektů jsou následně, s pomocí IDL
kompilátoru, mapovány do konkrétních programovacích jazyků, ve kterých již
lze dané objekty implementovat. Použitím tohoto mechanismu dochází k oddělení
implementace CORBA objektů od jejich rozhraní, čímž se dosahuje již jednou
zmíněné nezávislosti CORBA prostředí na programovacím jazyce. Jinak řečeno,
klient volá pouze metody nad rozhraním definovaném v IDL a nestará se o to,
jakým způsobem je daný objekt implementován.
V současné době existují OMG standardy mapování IDL do následujících jazyků:
C, C++, Smalltalk, Ada95, COBOL a nově i Java s tím, že mapování do ostatních
jazyků existují zatím pouze v proprietární formě (příkladem může být Borland
Delphi 4.0 a mapování do jazyka Pascal).
Na závěr povídání o IDL lze pouze podotknout, že všechny IDL deklarace mohou
být zpřístupněny běžícím aplikacím skrze Interface Repository.
Závěr
Princip fungování součástí standardu CORBA je možno si vyzkoušet na příkladu
na str. 4.
9 0690 / pen
Jednoduchá CORBA aplikace
Základní principy psaní a následného fungování distribuovaných CORBA aplikací
ilustruje následující jednoduchý příklad. Serverovou část aplikace bude tvořit
jediný objekt bankovní účet poskytující svým klientům operace pro vkládání či
vybírání peněz, případně zjišťování aktuálního stavu účtu. Tento server bude
implementován v jazyce C++ a poběží v prostředí operačního systému Unix.
Klientem bude jednoduchý applet Java běžící v prostředí Netscape
Communicatoru. Pro implementaci tohoto příkladu použijeme VisiBroker, jednu z
nejúspěšnějších implementací standardu CORBA, nedávno představenou firmou
Inprise také na našem trhu. Výhodu VisiBrokeru v tomto konkrétním případě by
mohlo být např. i to, že firma Netscape se rozhodla klientské knihovny od
VisiBrokeru zakomponovat do svých produktů (knihovna, kterou náš applet bude
potřebovat pro komunikaci skrze ORB, je tedy dostupná lokálně; množství kódu,
které s naším appletem musí přijít po síti, je tedy redukováno na únosné
minimum). Kromě instalace VisiBrokeru potřebujeme ještě překladače jazyka C++
a Java (potřebné verze udává dokumentace VisiBrokeru).
Postup tvorby distribuované CORBA aplikace lze rozdělit do následujících
kroků:
Specifikace rozhraní CORBA objektů v jazyce IDL
Generování klientské proxy a serverového skeletonu pomocí IDL kompilátoru
Implementace klienta v konkrétním implementačním jazyce (v našem případě Java)
Implementace serveru v konkrétním implementačním jazyce (v našem případě C++)
IDL specifikace
Prvním krokem v tvorbě distribuované CORBA aplikace je specifikace rozhraní
všech CORBA objektů. V našem případě je to objekt jediný bankovní účet.
Atributem tohoto objektu bude stav účtu, který lze přímo pouze číst. Pro
ostatní manipulace s účtem (vkládání/vybírání peněz) si definujme metody vlož/
vyber. Parametrem těchto metod nechť je částka, o kolik se má stav účtu
změnit, návratovou hodnotou pak nový stav účtu. Vše zapsáno v jazyce IDL
vypadá následovně:
// file account.idl
interface Account {
readonly attribute float balance;
float deposit (in float amount);
float withdraw (in float amount);
};
Následuje fáze, ve které se s pomocí IDL kompilátoru vygenerují kódy
klientské proxy a serverového skeletonu. Připomínáme, že klientskou proxy
potřebujeme mít v Javě, serverový skeleton v C++; to odpovídá použití
kompilátorů idl2java a idl2cpp systému VisiBroker.
Klient
K tomu, aby mohl začít spolupracovat se serverovým CORBA objektem, musí
klient udělat 2 věci zjistit referenci na daný CORBA objekt (v našem případě
ji applet obdrží v řetězcové podobě jako parametr) a poté požádat ORB o
vytvoření proxy pro daný objekt (lze provést např. v rámci voláním
string-to-object). Toto vše se vykonává v rámci inicializace celého appletu.
Poté už jen zbývá v reakci na uživatelovy akce volat metody nad danou proxy,
což má vždy za následek vyvolání vzdálené metody nad cílovým CORBA objektem.
// file ClientApplet.java
import java.awt.*;
public class ClientApplet extends java.applet.Applet {
private TextField _amountField, _balanceField;
private Button _checkBalance, _deposit, _withdraw;
private Account _account;
public void init() {
setLayout(new GridLayout(3, 2, 5, 5));
add(new Label("Amount"));
add(_amountField = new TextField());
add(_deposit = new Button("Deposit"));
add(_withdraw = new Button("Withdraw"));
add(_checkBalance = new Button("Check Balance"));
add(_balanceField = new TextField());
_balanceField.setEditable(false);
org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(this,
null);
_account = AccountHelper.narrow(
orb.string_to_object(getParameter("IOR")));
}
public boolean action(Event ev, Object arg) {
if(ev.target == _deposit) {
_account.deposit(new
Float(_amountField.getText()).floatValue());
_balanceField.setText(Float.toString
(_account.balance());
return true;
}
if(ev.target == _withdraw)
{
_account.withdraw(new
Float(_amountField.getText()).floatValue());
_balanceField.setText(Float.toString(_account.balance
)));
return true;
}
if(ev.target == _checkBalance)
{
_balanceField.setText(Float.toString(
_account.balance());
return true;
}
return false;
}
}
Zde by bylo vhodné poznamenat, že obecnějším a z hlediska teorie
distribuovaných systémů i "čistějším" způsobem získání reference a následně i
proxy pro cílový objekt by bylo použití objektových služeb (Naming Service,
Trading Service). Ačkoliv VisiBroker prvně jmenovanou službu též nabízí, její
použití je pro jednoduchost ukázkové aplikace vynecháno.
Implementace serveru
Implementaci serveru lze rozdělit do 2 částí. První část spočívá ve vytvoření
objektu implementujícího rozhraní příslušného CORBA objektu (v odborné
terminologii se pro takový objekt začíná vžívat jméno servlet). To lze např.
poděděním od automaticky vygenerovaného skeletonu třídy s následnou
implementací IDL rozhraní odpovídajících metod, jak ukazuje následující kód:
// file account_srvr.C
#include "account_s.hh"
class AccountImpl : public _sk_Account {
private:
CORBA::Float _balance;
public:
AccountImpl(const char *object_name=NULL) :
_sk_Account(object_name) {}
virtual CORBA::Float balance() {
return _balance;
}
virtual CORBA::Float deposit(CORBA::Float amount) {
return _balance += amount;
}
virtual CORBA::Float withdraw(CORBA::Float amount) {
return _balance -= amount;
}
};
(Pozn.: Spuštěním idl2cpp překladače na account.idl se vygenerují soubory
account_c.hh a account_c.cc obsahující kód klientské proxy a soubory
account_s.hh a account_s.cc obsahující kód serverového skeletonu. V tomto
případě využijeme pouze serverovou část; vkládáme soubor account_s.hh).
Druhá část implementace serveru spočívá ve vytvoření procesu, který na počátku
inicializuje knihovny ORBu a BOA, poté vytvoří instanci v předchozí části
vytvořeného implementačního objektu, tuto instanci registruje u BOA a přejde
do smyčky, ve které bude zpracovávat požadavky doručené ORBem. Vše opět
zachycuje následující kód:
int main(int argc, char* const* argv)
{
try {
CORBA::ORB_var orb = CORBA::ORB_init(argc, argv);
CORBA::BOA_var boa = orb->BOA_init(argc, argv);
AccountImpl account("TestAccount");
boa->obj_is_ready(&account);
boa->impl_is_ready();
} catch(const CORBA::Exception& e) {
cerr << e << endl;
return(1);
}
return(0);
}
Implementace serveru byla opět pro potřeby jednoduchosti této demonstrace
poněkud zjednodušena skutečná implementace bankovního účtu by veškerý pohyb na
účtu zaznamenávala do databáze (oddělila by se aplikační a datová logika
aplikace tak jak jsme zvyklí z vícevrstvých architektur) a vše by podléhalo
transakčnímu zpracování. VisiBroker pro tyto akce nabízí podporu v podobě
Integrated Transaction Service.
Posledními kroky před samotným spuštěním výsledné aplikace jsou kompilace
klienta (překladačem jazyka Java) a kompilace serveru (překladačem jazyka
C++). Připomínáme pouze, že kompilátory těchto jazyků je třeba získat
separátně obvykle nebývají součástí instalace systému CORBA. Nyní již stačí
vše zkompilovat a poté spustit a otestovat funkčnost.
Implementace architektury CORBA VisiBroker
Když firma Inprise (tehdy ještě Borland) koupila loni na jaře firmu Visigenic,
zařadila tím mezi své produkty i úspěšnou implementaci architektury CORBA
VisiBroker. Koncem roku se tento produkt objevil i na našem trhu. Sama
implementace podporuje OMG standard CORBA 2.0 a implementuje rozšíření, která
programátorům a správcům zjednodušují vývoj a posléze správu systému.
VisiBroker nabízí mapování jazyka IDL do jazyků C++ a Java. Samotný VisiBroker
lze použít na mnoha operačních systémech (Windows 95, 98 a NT, nejrozšířenější
UNIX platformy Solaris, HP-UX, AIX, SGI IRIX) a tím nabídnout interoperabilitu
mezi rozdílnými prostředími.
S VisiBrokerem se uživatelé Internetu, kteří používají prohlížeč od
společnosti Netscape, setkávají dnes a denně, protože byl zdarma zakomponován
přímo do jeho kódu (pouze mapování IDL do jazyka Java). Toto si můžeme přímo
vyzkoušet v příkladu, který je součástí tohoto TECH-Tipu, kde si předvádíme
spolupráci mezi serverem napsaném v C++ a klientem v jazyce Java, který
poběží jako applet v prohlížeči Netscape Communicator.
Inprise nabízí vývojářům nejenom implementaci CORBA standardu, ale také
nástroje pro vývoj těchto aplikací mezi nejznámější patří JBuilder 2, Delphi
4.0, C++ Builder 3 Enterprise, který ulehčuje práci programátorům při návrhu a
implementaci.
V současné době se na trh uvádí ITS (Integrated Transaction Service), která
bude využívána při elektronickém obchodování (Electronic Commerce). Pro
zajištění spolupráce mezi technologiemi COM a CORBA existuje produkt COM-CORBA
bridge. Z další rodiny produktů jmenujme Inprise Application Server
(aplikační server nabízející vývojářům širokou škálu standardních technologií
pro implementaci, běh a správu distribuovaných aplikací), který rovněž v sobě
obsahuje VisiBroker.
Mezi největší a nejznámější uživatele VisiBrokeru patří společnosti Netscape
(v prohlížečích Netscape Communicator a serverech Enterprise Server), Oracle,
Novell, Sybase, Hitachi a mnoho dalších.
Zájemci mohou získat časově omezenou verzi VisiBrokeru na stránce společnosti
Inprise (http:// www.inprise.com) a společně s námi si vyzkoušet již zmíněný
příklad. Na stránce společnosti Inprise naleznete také dokumentaci k produktu
a mnoho odkazů a příkladů.
Přehled vlastností VisiBrokeru (současná verze 3.3):
OMG CORBA standard 2.0, částečně 2.2
mapování do C++ a Java
IIOP, DII/DSI
Event Service, Naming Service, Interface Repository
rozšířené datové typy v IDL
podpora implementace a aktivace objektů (implementation repository, transient
and persistent object references)
bezpečný komunikační protokol IIOP (pomocí SSL, jedná se o doplňující produkt)
vícevláknovou architekturu (multithreads architecture)
interceptory a inteligentní stuby (pro modifikaci komunikace mezi objekty bez
zásahu do kódu objektů)
nástroje pro správu, monitorování systému
podpora pro replikaci serverů,
fault tolerance
utility pro začlenění do WWW
(GateKeeper)
Webové adresy
OMG: http://www.omg.org
VisiBroker hlavní stránka: http://www.inprise.com/visibroker