Рис Физический и логический обмен данными по сети 21 Рис Ахитектура процессов в распределенных системах

Вид материалаДокументы

Содержание


Main structure of an IOR.
GIOP Messages
Упомянуть о важности ServiceContext, обещать привести пример с BiDirGIOP.
The server need not send replies in the same order in
Пример LOCATION_FORWARD
GIOP использует CDR (Common data representation)
Теперь структура занимает меньше места (было – 16, теперь 14)
SupplierAdmin supplierAdmin = e.for_suppliers()
ConsumerAdmin ca = null
Подобный материал:
1   2   3   4   5   6   7

Main structure of an IOR.




Interoperable Object Reference

IOR

String Length: 26

IOR::type_id: IDL:dcs/demo/Calc:1.0

Sequence Length: 1

Profile ID: TAG_INTERNET_IOP (0)

Sequence Length: 124

Endianess: Big Endian (0)

IIOP Major Version: 1

IIOP Minor Version: 2

String Length: 15

IIOP::Profile_host: 83.149.249.206

IIOP::Profile_port: 60004

Sequence Length: 34

Object Key: 726F6F742F4269446972504F415F5365727665722F426944...(“root/CalcPOA/calc:1”)

Sequence Length: 2

IIOP Component TAG: 0

Sequence Length: 8

component_data: ....JAC.

IIOP Component TAG: 1

Sequence Length: 28

component_data: ............................


Несколько профилей (для машины с двумя сетевыми интерфейсами)

>>ipconfig

Windows 2000 IP Configuration

Ethernet adapter Local Area Connection:

       Connection-specific DNS Suffix  . :

       IP Address. . . . . . . . . . . . : ссылка скрыта

       Subnet Mask . . . . . . . . . . . : ссылка скрыта

       Default Gateway . . . . . . . . . : ссылка скрыта


PPP adapter Connection to Internet at Rapier24i-15Parkovay:

       Connection-specific DNS Suffix  . :

       IP Address. . . . . . . . . . . . : ссылка скрыта

       Subnet Mask . . . . . . . . . . . : ссылка скрыта

       Default Gateway . . . . . . . . . : ссылка скрыта

================================================================
был запущен сервер (на TAO) со следующими параметрами:
... -ORBEndpoint iiop://10.10.64.15:50022, 212.5.76.66:50022
IOR объекта был зарегистрирован на сервисе именований, запущенном на dcs.
Дапм IOR (сгруженного с сервиса именований dcs):

IOR #1:

byteorder: little endian

type_id: IDL:iarnet/ResourceAgents/matlab/MxArrayFactory:1.0

Profile #1: iiop

iiop_version: 1.2

host: 10.10.64.15

port: 50022

object_key: (27)

20 1 15 0 82 83 84 98 "....RSTb"

117 166 68 131 64 10 0 1 "u.D.@..."

0 0 0 1 0 0 0 2 "........"

0 0 0 "..."

Component: TAG_ORB_TYPE = 0x54414f00

Native char codeset:

"ISO 8859-1:1987; Latin Alphabet No. 1"

Native wchar codeset:

"ISO/IEC 10646-1:1993; UTF-16, UCS Transformation Format 16-bit form"

Profile #2: iiop

iiop_version: 1.2

host: 212.5.76.66

port: 50022

object_key: (27)

20 1 15 0 82 83 84 98 "....RSTb"

117 166 68 131 64 10 0 1 "u.D.@..." (Заметить, что ObjKey у разных профилей – один и тот же.)

0 0 0 1 0 0 0 2 "........"

0 0 0 "..."

Component: TAG_ORB_TYPE = 0x54414f00

Native char codeset:

"ISO 8859-1:1987; Latin Alphabet No. 1"

Native wchar codeset:

"ISO/IEC 10646-1:1993; UTF-16, UCS Transformation Format 16-bit form"


    1. GIOP

Еще раз сказать о сниферах Ethereal Wireshark, где есть диссекторы протоколов GIOP, IIOP. «Лучше один раз увидеть»


General Inter-ORB Protocol

Magic number: GIOP

Version: 1.2

Flags: 0x01 (little-endian )

Message type: Request

Message size: 68

General Inter-ORB Protocol Request

Request id: 2

Response flags: SYNC_WITH_TARGET (3)

Reserved: 0 0 0

TargetAddress Discriminant: 0

KeyAddr (object key length): 29

KeyAddr (object key): ...0_RootPOA.CSPOA..demo:calc

Operation length: 4

Request operation: add

ServiceContextList

Sequence Length: 0

Stub data (8 bytes)


General Inter-ORB Protocol

Magic number: GIOP

Version: 1.2

Flags: 0x00 (big-endian )

Message type: Reply

Message size: 17

General Inter-ORB Protocol Reply

Request id: 2

Reply status: No Exception (0)

ServiceContextList

Sequence Length: 0

Stub data (5 bytes)


Синхронизация ответ-на-запрос посредством уникального ID (unsigned long)

GIOP Messages



Рассказывать подробно только про Request и Reply.



Заметить, что информация о кодировке big/little-endian передается в самом начале, во «флаговых» битах 7-го байта GIOP Header. Длина сообщения, закодированная в последних 4-х байтах – уже может быть закодирована разными способами.

Byte 7 is a flags byte. The least significant bit of the flags byte indicates whether the remainder of the message is in big-endian or little-endian encoding: a value of 0 indicates big-endian. The second-least significant bit indicates fragmentation. A value of 1 indicates that this message is a fragment with more fragments to follow. A value of 0 indicates that this message is a complete message or is the last message in a sequence of fragments.

Byte 8 indicates the message type. Its value is the ordinal value of one of the MsgType_1_1 enumerators. The value 0 indicates a Request message. Bytes 9-12 are a 4-byte unsigned value that indicates the size of the message (not counting the 12 header bytes). The value is encoded as big-endian or little-endian as indicated by the least significant bit of the flags byte.


Request Message Format



request_id

This field is used by the client to associate the request with its response. The client sets the request_id to a unique number when it sends the request. A Reply message also has a request_id field; when the server sends the reply for a request, it returns the corresponding request_id to the client. In that way, the client can have replies for more than one request outstanding at a time.

Упомянуть о важности ServiceContext, обещать привести пример с BiDirGIOP.


response_expected

This field is a Boolean value that is set to true for a normal synchronous request, meaning that the client requires a reply for the request. If the operation being invoked by the client is a oneway operation, the client-side run time can set this field to false (to indicate to the server that no reply is wanted) or to true to allow the client to receive a system exception or a LOCATION_FORWARD reply (


operation

This field is a string that contains the name of the operation being invoked. If the client sends the request to read or write an attribute, the operation name is_get_attribute_name or _set_attribute_name, respectively.


Reply Message Format





request_id

The request_id field returns the ID of the corresponding request to the client. The

client uses it to associate replies with requests. This allows the client to have several

replies outstanding simultaneously. The server need not send replies in the same order in

which it receives requests because some requests may take longer to complete than others.


reply_status

The reply_status field indicates the result of the request.

NO_EXCEPTION

This indicates that the request completed successfully.

USER_EXCEPTION

The request raised a user exception.

SYSTEM_EXCEPTION

The server-side ORB or the server-side application code raised a system exception.

LOCATION_FORWARD

This reply indicates that the request cannot be processed by this server, but the client

should try again at a different address.


Пример LOCATION_FORWARD

Каждый CORBA объект может быть пропингован, посредством специальной операции

_non_existent() – возвращает FALSE если объект «жив».

Ниже приводится пример обмена сообщениями GIOP когда клиентская сторона использует «фиктивный» (на самом деле, - общеизвестный) адрес некоторой службы.

Нарисовать

Кл. <-> Серв.

-> Req id 4

<- Repl LOC._FORWARD id 4

->Req id 4

<- Reply No Exception id 4


Client -> _non_existent() ->Server

General Inter-ORB Protocol

Magic number: GIOP

Version: 1.0

Byte ordering: big-endian

Message type: Request

Message size: 60

General Inter-ORB Protocol Request

ServiceContextList

Sequence Length: 0

Request id: 4

Response expected: 1

Object Key length: 17

Object Key: 44656661756C745265706F7369746F7279 (DefaultRepository)

Operation length: 14

Request operation: _non_existent

Requesting Principal Length: 0

Server Reply

General Inter-ORB Protocol

Magic number: GIOP

Version: 1.0

Byte ordering: little-endian

Message type: Reply

Message size: 208

General Inter-ORB Protocol Reply

ServiceContextList

Sequence Length: 0

Request id: 4

Reply status: Location Forward (3)

IOR

String Length: 33

IOR::type_id: IDL:omg.org/CORBA/Repository:1.0

Sequence Length: 1

Profile ID: TAG_INTERNET_IOP (0)

Sequence Length: 144

Endianess: Little Endian (1)

IIOP Major Version: 1

IIOP Minor Version: 2

String Length: 15

IIOP::Profile_host: 83.149.249.206

IIOP::Profile_port: 30003

Sequence Length: 54

Object Key: ABACAB305F526F6F74504F4100496E746572666163655265...(RootPOA/RealImplementation… )

Sequence Length: 1

IIOP Component TAG: 1

Sequence Length: 44

component_data: ............ ...............................

Клиент повторяет запрос (с тем же ID) по указанному IOR. Причем Request ID – тот же 4.


GIOP использует CDR (Common data representation)



Strings and wide strings are encoded as an unsigned long (aligned on a 4-byte offset) that indicates the length of the string, including its terminating NUL byte, followed by the bytes of the string, terminated by a NUL byte. For example, the string "Hello" occupies 10 bytes. The first 4 bytes are an unsigned long with value 6, the next 5 bytes contain the characters Hello, and the final byte contains an ASCII NUL byte. This means that an empty string occupies 5 bytes: 4 bytes containing a length of 1, followed by a single NUL byte.

4 байта – длина строки unsigned long

Заметьте, что в little/big-endian кодировке

‘H’ ‘e’ ‘l’ ‘l’ ‘o’

содержание

NULL byte

Т.е. Hello занимает 4 + 5 + 1 = 10 байтов.

Аналогично хранятся sequence

Структуры

Structures are encoded as a sequence of structure members in the order in which they are defined in IDL. Each structure member is aligned according to the rules in Table 13.1; padding bytes of undefined value are inserted to maintain alignment. Consider the following structure:

struct CD {

char c;

double d;

};

This structure contains a character, which can occur anywhere in a byte stream, followed by a double value, which must be aligned on an 8-byte boundary. Figure 13.1 shows how this structure would appear on the wire, assuming it starts at the beginning of a byte stream.

1 байт – ‘c’



Заполнитель до 8 байтов

2-8

8 байт – на double (выровнено – по 8)

9-16


Заметьте, что если поменять местами описание полей в IDL – длина будет другой.

Общая длина Message Body может зависеть и от порядка декларации параметров операции

It is interesting to note that a structure of type CD does not always appear as a 16-byte value. Depending on the other data that precedes the structure on the wire, the length of the structure may vary. For example, consider the following operation, which accepts a string followed by a structure of type CD:

interface foo {

void op(in string s, in CD ds);

};

When a client marshals a request to invoke op, it sends all the in parameters end-to-end according to CDR encoding rules. Assume for the moment that the parameters when sent inside the request begin at an 8-byte offset and that the client sends the string "Hello" as the value of the parameter s. Figure 13.2 shows the resulting encoding.

6 – длина «Hello»

1-4

Hello\0

5-10

‘c’

11

заполнитель

12-15

8 байт – на double (выровнено – по 8)

16-24

Теперь структура занимает меньше места (было – 16, теперь 14)

The encoding for the value "Hello" consumes 10 bytes: 4 bytes for the length and 6 bytes for the actual string. The second parameter is the structure of type CD. Because the member c is of type char, it can be aligned anywhere, so the value of c is encoded immediately following the string at byte offset 10. The d member of the structure must be aligned on an 8-byte boundary, so c is followed by 5 bytes of padding, followed by the 8 bytes required to hold the value of d


Пример использования GIOP ServiceContext в Bidirectional IIOP

As mentioned in Section 13.4, CORBA 2.3 added GIOP 1.2 and IIOP 1.2 to enable bidirectional communication. This allows client and server to reverse roles without the need to open a separate connection that may be blocked by a firewall. At the time of writing, the specification is undergoing changes, and implementations are unlikely to appear before mid-1999, so we do not cover version 1.2 in detail in this chapter. Here is a summary of the major changes.

GIOP 1.2 does not add new message types but adds extensions to most of the message headers and bodies. These extensions support the additional information that must be exchanged for bidirectional communication.

GIOP 1.2 adds a LOCATE_FORWARD_PERM reply status, which is intended to ease

object migration (see Section 14.5).

GIOP 1.2 tightens the alignment restrictions for a request body to make remarshaling after a LOCATE_FORWARD reply more efficient.

IIOP 1.2 adds additional information to the service context to support bidirectional communication. It also defines a policy that enables bidirectional communication only if both client and server agree to use it. This policy allows administrators to disable bidirectional communication over insecure links and thereby prevent clients from masquerading as someone else's call-back object. If bidirectional communication is disabled, GIOP 1.2 uses a separate connection for callbacks.


Пример

module demo

{

module bidir

{

interface ClientCallback

{

void hello( in string message );

};


interface Server

{

void register_callback( in ClientCallback cc );

void callback_hello( in string message );

};

};

};

Сценарий для демонстрации BiDirGIOP.

Вначале – как это выглядит без использования BiDir

Процесс 1

Процесс 2

CallBack – сервер

Клиент регистратора

Сервер-регистратор;

Клиент CallBack

1. Передает IOR CB – серверу регистратору






Принимает IOR и создает представителя CB

2.

Вызывает CB (вызов идет на тот порт, что слушает POA 1)




Процесс 1

Процесс 2

CallBack – сервер

Клиент регистратора

Сервер-регистратор;

Клиент CallBack

1. Передает IOR CB – серверу регистратору

В BiDirServiceContext передает host:port, которые будут в IOR CallBack’ка

открыто сокетное соединение (H – host)

S12={H1:SocketPort1;H2:POAPort2}




Принимает IOR и создает представителя CB. Сохраняет открытым соединение H1:SocketP1

Записывает H1:POA_Port1 -> S12

2.

Вызывает CB, где указан адрес {H1:POAPort1}, но ORB просматривает таблицу BiDir и использует для передачи данных уже открытое соединение (вызов идет на порт SocketPort1)


General Inter-ORB Protocol

General Inter-ORB Protocol Request

Request id: 0

Response flags: SYNC_WITH_TARGET (3)

Reserved: 0 0 0

TargetAddress Discriminant: 0

KeyAddr (object key length): 34

KeyAddr (object key): root/BiDirPOA_Server/BiDirServerID

Operation length: 18

Request operation: register_callback

ServiceContextList

Sequence Length: 2

0000 0000 0000 0000 0000 0000 .... .... = VSCID: 0x00000000

.... .... .... .... .... .... 0000 0101 = SCID: 0x00000005

Service Context ID: BI_DIR_IIOP (5)

BI_DIR_IIOP

context_data: ............83.149.249.217...b (внутренний IP:60002)

struct ListenPoint { //0f’8’’3’…’\NUL’00ea62 (BigEndian)

string host;

unsigned short port;

};


typedef sequence ListenPointList;


struct BiDirIIOPServiceContext {// BI_DIR_IIOP Service Context

ListenPointList listen_points;

};

Sequence Length: 12

Endianess: Big Endian (0)

0000 0000 0000 0000 0000 0000 .... .... = VSCID: 0x00000000

.... .... .... .... .... .... 0000 0001 = SCID: 0x00000001

Service Context ID: CodeSets (1)

CodeSets

char_data: 0x00010001

wchar_data: 0x00010109

Stub data (176 bytes) (передается IOR CallbackClient на хосте за NAT)


General Inter-ORB Protocol

General Inter-ORB Protocol Request

Request id: 2

Response flags: SYNC_WITH_TARGET (3)

Reserved: 0 0 0

TargetAddress Discriminant: 0

KeyAddr (object key length): 34

KeyAddr (object key): root/BiDirPOA_Server/BiDirServerID

Operation length: 15

Request operation: callback_hello

ServiceContextList

Sequence Length: 1

0000 0000 0000 0000 0000 0000 .... .... = VSCID: 0x00000000

.... .... .... .... .... .... 0000 0101 = SCID: 0x00000005

Service Context ID: BI_DIR_IIOP (5)

BI_DIR_IIOP

context_data: ............83.149.249.217...b

Stub data (18 bytes) (“Test string”)


Теперь «сервер» вызывает метод CallBack

General Inter-ORB Protocol

General Inter-ORB Protocol Request

Request id: 1

Response flags: SYNC_WITH_TARGET (3)

Reserved: 0 0 0

TargetAddress Discriminant: 0

KeyAddr (object key length): 34

KeyAddr (object key): root/BiDirPOA_Client/BiDirClientID

Operation length: 6

Request operation: hello

ServiceContextList

Sequence Length: 0

Stub data (18 bytes) (та же самая строка)

Прием BiDir IIOP есть пример решения задачи прозрачности местонахождения, т.к. основная часть кода (где реализован прикладной сценарий) остается неизменной. Требуется лишь инициализировать транспорт ORB со специальными опциями и политиками…

Не бог весть какой Бином Ньютона, однако это готовое решение.


CDR не предусматривает self-describing в самих данных.

Именно поэтому нужен IDL, стабы и скелетоны.

Для «полноценных» динамических вызовов нужна спец. служба ! Interface Repository

DII & DSI

module demo {


module dii {

interface server {

void add(in long i, in long j, out long r );

};

};

};


На клиентской стороне

org.omg.CORBA.Object s = nc.resolve(name);

org.omg.CORBA.Request r_out = s._request("add");


r_out.add_in_arg().insert_long(3);

r_out.add_in_arg().insert_long(4);


org.omg.CORBA.Any out_arg = r_out.add_out_arg();

out_arg.type(orb.get_primitive_tc(org.omg.CORBA.TCKind.tk_long));


r_out.set_return_type(orb.get_primitive_tc(org.omg.CORBA.TCKind.tk_void));


r_out.invoke();

if (r_out.env().exception() != null) {

throw r_out.env().exception();

} else {

System.out.println("1: " + out_arg.extract_long());

}


На серверной

public void invoke(org.omg.CORBA.ServerRequest request) {

String op = request.operation();

if (op.equals("add")) {


package demo.events;


/**

* @authors Joerg v. Frantzius, Rainer Lischetzki, Gerald Brose 1997

*

* A simple demo for using the event channel as a push supplier of events.

*

*/


import org.omg.CosEventChannelAdmin.*;

import org.omg.CosEventComm.*;

import org.omg.CosNaming.*;

import org.omg.CORBA.Any;


class PushSupplierDemo extends PushSupplierPOA

{


public PushSupplierDemo( String[] args )

{

org.omg.CosEventChannelAdmin.EventChannel e = null;

org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(args, null);


try

{

org.omg.PortableServer.POA poa = org.omg.PortableServer.POAHelper.narrow

(orb.resolve_initial_references ("RootPOA"));

poa.the_POAManager().activate();

NamingContextExt nc = NamingContextExtHelper.narrow(

orb.resolve_initial_references("NameService"));


e = EventChannelHelper.narrow(nc.resolve(nc.to_name("eventchannel.example")));

}

catch(Exception ex)

{

ex.printStackTrace();

}


SupplierAdmin supplierAdmin = e.for_suppliers();

ProxyPushConsumer proxyPushConsumer = supplierAdmin.obtain_push_consumer();


try

{

proxyPushConsumer.connect_push_supplier( _this(orb) );

}

catch (org.omg.CosEventChannelAdmin.AlreadyConnected ex)

{

ex.printStackTrace();

}


for(int i=0; i < 30; i++)

{

try

{

Any any = orb.create_any();

any.insert_string("Test the channel!" + i);

System.out.println("Pushing event # " + (i) );

proxyPushConsumer.push( any );

}

catch(Disconnected d)

{

d.printStackTrace();

}

}

proxyPushConsumer.disconnect_push_consumer();

}


public void disconnect_push_supplier ()

{

System.out.println ("Supplier disconnected");

}


public static void main(String[] args)

{

PushSupplierDemo demo = new PushSupplierDemo( args );

}

}


package demo.events;


/**

* @authors Joerg v. Frantzius, Rainer Lischetzki, Gerald Brose 1997

* * A simple demo for using the event channel as a push consumer

* of events. This consumer unregisters and quits after receiving

* 5 events.

* */


import org.omg.CosEventChannelAdmin.*;

import org.omg.CosEventComm.*;

import org.omg.CosNaming.*;


public class PushConsumerDemo implements PushConsumerOperations

{

private short count = 0;

private ProxyPushSupplier myPps = null;

private int limit = 25;


static org.omg.CORBA.ORB orb = null;


public PushConsumerDemo( ProxyPushSupplier _pps ) {

myPps = _pps;

}


public void disconnect_push_consumer() {

System.out.println("Consumer disconnected.");

}


static public void main (String[] args) {

EventChannel ecs = null;

ConsumerAdmin ca = null;

PushConsumer pushConsumer = null;

ProxyPushSupplier pps = null;


try {

orb = org.omg.CORBA.ORB.init(args, null);

NamingContextExt nc =

NamingContextExtHelper.narrow(

orb.resolve_initial_references("NameService"));


ecs = EventChannelHelper.narrow(nc.resolve(

nc.to_name("eventchannel.example")));

}

catch(Exception e) {

e.printStackTrace();

}


ca = ecs.for_consumers();

pps = ca.obtain_push_supplier();


try {

org.omg.PortableServer.POA poa =org.omg.PortableServer.POAHelper.narrow(

orb.resolve_initial_references("RootPOA"));


poa.the_POAManager().activate();


PushConsumerPOATie pt = new PushConsumerPOATie( new PushConsumerDemo( pps ));

pt._this_object(orb);

pushConsumer = PushConsumerHelper.narrow(poa.servant_to_reference(pt) );

pps.connect_push_consumer( pushConsumer );

System.out.println("PushConsumerImpl registered.");

orb.run();

}

catch(Exception e) {

e.printStackTrace();

}

System.out.println("Quit.");

}


public synchronized void push(org.omg.CORBA.Any data)

throws org.omg.CosEventComm.Disconnected {

count++;

System.out.println("event " + count + " : " + data.extract_string());

if( count >= limit ) {

System.out.println("unregister");

myPps.disconnect_push_supplier();

// System.exit(0);

orb.shutdown(false);

}

}

}

    1. Репозиторий типов (Interface Repository)

Фактически, представляет собой службу CORBA, т.е. специальный серверный процесс, позволяющий хранить (пополнять, модифицировать) список типов данных и типов интерфейсов объектов РВС.



  1. Пример отображения содержимого Репозитория Интерфейсов (IR браузер, т.н. Mao’s CORBA Brawser)



    1. Message Oriented M/w (Event / Notification Service)

Начну с примера «распределенного» суммирования.

Распараллеливание работы удаленных вычислителей достигается за счет более совершенной архитектуры.

Рассмотрим задачу вычисления суммы N чисел {x1, x2, x3, …, xN} . На обычном «однопроцессорном» компьютере эта задача требует выполнения N-1 операций сложения.

// x – определен выше как массив чисел float[] x; x.length = N

float res;

for (int i = 0, res = 0.; i < N; i++)

res += x[i];


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

Процедура вычисления суммы в таком случае может быть записана следующим образом



public static float DistrSum (float[] x, CalcOperations[] calcs) {

int N = x.length; // Number of summands

ResHolder[] xHolder;

while (N > 1) {

int n;

xHolder = new ResHolder[N/2];

for (n = 0; n < N/2; n++) { // храним промежуточные значения сумм в том же массиве

// x[n] = calcs[n].add(x[2*n], x[2*n+1]); // Неэффективный синхронный вызов

xHolder[n] = calcs[n].ami_add(x[2*n], x[2*n+1]); // асинхронный вызов функции add

}

// Цикл синхронизации (требует асинхронного вызова команд калькулятора)

for (n = 0; n < N/2; n++)

x[n] = xHolder[n].getValue(); // Блокирующий вызов, НО локально. Задержка <<

// Или

//int k = -1;

//while (k < N/2) {

// for (n = 0; n < N/2; n++)

// if (xHolder[n].poll()) {

// x[n] = xHolder[n].getValue();

k++;

//}

//};

if ( 2*n < N) {// N – нечетное вида 2*n + 1

// x[n] = x[N-1];

x[n] = xHolder[N-1].getValue();

n++;

}

N = n;

}

return x[0];

}


// …

public interface CalcOperations

{

float add(int a, int b);

float sub(int a, int b);

float mult(int a, int b);

float div(int a, int b) throws DivisionByZero;

}