Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Конспект лекций РСОИ.doc
Скачиваний:
20
Добавлен:
04.11.2018
Размер:
1.93 Mб
Скачать

3.2. Об’єктно-орієнтована архітектура .Net Remotіng – основа створення розподілених систем Mіcrosoft .Net.

.NET Remotіng – це об’єктно-орієнтована архітектура для підтримки розподілених застосунків у Mіcrosoft .NET. Іншими словами, .Net Remotіng – один з можливих варіантів реалізації взаємодії процесів, що виконуються (в загальному випадку) у розподіленому обчислювальному середовищі під керуванням .Net Framework. За допомогою Remoting можна звертатись до екземплярів класів .Net, які містяться за межами власного домену (application domain). Це може бути як інший застосунок всередині одного процесу (наприклад, звернення з одного asp.net застосунка до об’єктів іншого), інший процес на тій самій машині, або процес на іншій машині (в тому числі і підключеній через Internet). На рис. 3.7 зображена загальна схема функціонування механізму Remoting.

Сервер при запуску настроює Remoting для використання певного протоколу. При цьому вказується транспортний протокол і протокол доступу. Потім сервер реєструє всі класи, до яких він надає доступ.

Клієнт, при необхідності доступу до віддалених об'єктів, також вказує протоколи доступу й надсилає запит на сервер. Сервер у відповідь на цей запит створює у себе викликаний об'єкт і передає його ідентифікатор клієнтові. Клієнт створює в себе спеціальний проксі-клас, який потім використовує як об'єкт у власному домені.

Розглянемо функціональні можливості просторів імен, що забезпечують віддалену взаємодію. Бібліотеки базових класів .NET містять дуже багато просторів імен, що дозволяють будувати розподілені застосунки. Більшість типів, що містяться в цих просторах імен, перебувають у mscorlib.dll, але доповнення й розширення базових просторів імен винесені в окремий компонувальний блок System.Runtime.Remoting.dll. У таблиці 3.7 пропонуються короткі описи просторів імен віддаленої взаємодії .NET 2.O.

Таблиця 3.7

Простори імен віддаленої взаємодії .NET

Назва

Опис

1

2

System.Runtime.Remoting

Базовий простір імен, що повинен використатися при побудові будь-якого розподіленого застосунка NET

System.Runtime.Remoting.

Activation

Відносно малий простір імен, у якому визначаються кілька типів, що забезпечують тонке настроювання процесу активізації віддаленого об’єкту

System.Runtime.Remoting.

Channels

Містить типи, що представляють канали і приймачі каналів

System.Runtime.Remoting.

Channels.Http

Містить типи, що використовують протокол HTTP для транспорту повідомлень і об'єктів у віддалену точку та назад

System.Runtime.Remoting.

Channels.IPC

Простір імен, що з'явився в .NET 2.0 і містить типи, що використовують архітектуру IPC Win32. Архітектура IPC (Interprocess Communication – взаємодія процесів) забезпечує швидку взаємодію доменів застосунків, що існують на одній фізичній машині

System.Runtime.Remoting.

Channels.TCP

Містить типи, що використовують протокол TCP для транспорту повідомлень і об'єктів у віддалену точку і назад

System.Runtime. Remoting.

Contexts

Дозволяє конфігурувати параметри об'єктного контексту

System.Runtime. Remoting.Lifetime

Містить типи, що керують циклом існування віддалених об'єктів

System.Runtime.Remoting.

Messaging

Містить типи, що використовуються для створення і передавання об'єктів повідомлень

Таблиця 3.7 (закінчення)

1

2

System.Runtime.Remoting.

Metadata

Містить типи, що використовуються для налагодження параметрів генерування форматування повідомлень SOAP

System.Runtime.Remoting.

Metadata.W3cXsd2001

Містить типи, що представляють формат XSD (XML Schema Definition — визначення схеми XML) відповідно до стандартів Консорціуму W3C, прийнятих в 2001 року

System.Runtime.Remoting.

MetadataServices

Містить типи, що використовуються засобом командного рядка soapsuds.exe при конвертуванні метаданих віддаленої інфраструктури .NET в XML-схеми (і назад)

System.Runtime.Remoting.Proxies

Містить типи, що забезпечують функціональні можливості для об'єктів, що виконують завдання агента (proxy)

System.Runtime.Remoting.Services

Визначає ряд загальних базових класів (і інтерфейсів), які зазвичай використовуються тільки внутрішніми агентами віддаленої взаємодії

Каркас віддаленої взаємодії .NET. Коли клієнти та сервери обмінюються інформацією через границі застосунків, середовище CLR змушене використовувати низькорівневі примітиви, що забезпечують настільки "прозору" взаємодію сторін, наскільки це можливо. Це означає, що не потрібно створювати величезні за обсягом блоки програмного коду підтримки мережевого з'єднання, щоб викликати метод віддаленого об’єкту. Серверному процесові також не треба "самостійно" діставати мережевий пакет із черги та перетворювати повідомлення у формат, зрозумілий віддаленому об'єктові. Середовище CLR подбає про зазначені вище процеси, використовуючи свій стандартний набір примітивів віддаленої взаємодії.

За суттю, шар віддаленої взаємодії .NET забезпечує спільну роботу наступних чотирьох ключових елементів:

  • агенти;

  • повідомлення;

  • канали;

  • форматери.

Далі розглянемо кожний із зазначених елементів по черзі і з'ясуємо, як їхня комбінація дозволяє здійснювати віддалені виклики методів.

Агенти та повідомлення. Клієнти та об'єкти сервера взаємодіють не безпосередньо, а через посередника, який зазвичай зветься агентом (або proxy-модулем). Роль агента .NET полягає у створенні для клієнта ілюзії того, що він взаємодіє із запитаним віддаленим об'єктом в одному домені застосунка. Щоб створити таку ілюзію, агент пропонує інтерфейс (члени, властивості, поля тощо), ідентичний інтерфейсу віддаленого типу. З погляду клієнта такий агент і є віддаленим об'єктом. Однак "за лаштунками" агент скеровує виклики віддаленому об'єктові.

Формально такий агент, який викликає клієнт безпосередньо, називається прозорим агентом (transparent proxy). Цей об'єкт, що генерується середовищем CLR автоматично, відповідає за перевірку того, що при виклику віддаленого методу клієнт одержить потрібне число параметрів (і вони будуть потрібного типу). Тому прозорий агент можна інтерпретувати, як фіксований шар взаємодії, якого не можна програмно змінити або розширити.

Прозорий агент може виконувати перевірку вхідних аргументів, відповідна інформація упаковується в інший тип, який генерується середовищем CLR, що називається об'єктом повідомлення. За визначенням всі об'єкти повідомлень реалізують інтерфейс System.Runtime.Remoting, Messaging.IMessage.

public interface IMessage

{

IDictionary Properties { get; }

}

Інтерфейс IMesaage визначає єдина властивість (з ім'ям Properties), що забезпечує доступ до колекції, яка використовується для зберігання наданих клієнтом аргументів. Після наповнення об’єкту повідомлення вмістом середовищем CLR. він буде переданий спорідненому типу, що зветься реальним агентом (real proxy).

Реальний агент – це сутність, яка фактично посилає об'єкт повідомлення в канал (поняття каналу буде обговорюватися нижче). Реальний агент, що (на відміну від прозорого агента) може бути розширений програмістом, виражається базовим типом класу з ім'ям RealProxy. Підкреслимо, що середовище CLR генерує клієнтську реалізацію реального агента для використання за замовчуванням. Але щоб мати уявлення про функціональні можливості, запропоновані абстрактним базовим класом RealProxy, треба познайомитися з формальним визначення цього типу, наведеним нижче:

public abstract class RealProxy: object - {

public virtual ObjRef Creat.eObjRef (Type requestedType);

public virtual bool Equals (object obj);

public virtual IntPtr GetCOMIUnknown (bool fIsMarshelled);

public virtual int GetHashCode();

public virtual void GetObjectData(SerializationInfo Info, StreamingContext context);

public Type Get ProxiIedType();

public static object GetStubData (.Real Proxy rp);

public virtual object GetTransparentProxy ();

public Type Get Type();

public IConstructionReturnMessage InitializeServerObject (IConstuctionCallMessage ctorMsg);

public virtual IMessage Invoke (Imessage msg);

public virtual void SetCOMIUnknowa (IntRtr i);

public static void SetStubBata (RealProxy rp, object stubData);

public virtual IntPtr SuppartsInterface (ref Guid iid);

public virtual string Tostring();

Зазначимо, що можлива користувацька реалізація реального агента, яка здійснюється з використанням методу RealProxy.Invoke(). За допомогою методу Invoke () згенерований середовищем CLR прозорий агент у фоновому режимі передає відформатований об'єкт повідомлення типу RealProxy.

Канали. Після того, як агенти перевірять та відформатують аргументи, які надходять від клієнта, упаковані в об'єкт повідомлення, відповідний IMessage-сумісний тип передається від реального агента об'єкту каналу. Канали – це сутності, відповідальні за транспортування повідомлення віддаленому об'єктові та, якщо це необхідно, за те, щоб значення, що повертається віддаленим об'єктом, було доставлено назад клієнтові. У бібліотеках базових класів .NЕТ 2.0 пропонуються готові реалізації трьох каналів:

  • TCP-канал;

  • HTTP-канал;

  • IPC-канал.

TCP-канал у .NЕТ реалізується типом класу TcpChannel і використовується для передавання повідомлень із використанням мережевого протоколу TCP/IP. Клас TcpChannel зручний тим, що форматовані пакети виявляються винятково "легкими", оскільки повідомлення перетворюються у щільний двійковий формат за допомогою BinaryFormatter. При використанні типу TcpChannel віддалений доступ здійснюється швидше. Недоліком є те, що TCP-канали не узгоджуються із брандмауером автоматично й можуть вимагати втручання сервисів адміністратора системи, щоб одержати дозвіл на перетинання границі машини.

HTTP-канал, що реалізується типом класу HttpChannel, перетворює об’єкти повідомлення у формат SOAP (Simple Object Access Protocol), використовуючи для цього відповідний форматер SOAP. Цей форматер опирається на XML і тому результат в такому випадку є об’ємнішим, ніж у випадку TcpChannel, а отже при використанні HttpChannel віддалений доступ може здійснюватися повільніше. Основні переваги HTTP-каналу в тому, що SOAP стандартизований і теоретично його можна використовувати з клієнтів, які створені без застосування .Net Remoting, можливий доступ через стандартно налаштовані проксі-сервери, не створює постійного з’єднання, а також більшість мережевих екранів дозволяє текстовим пакетам передаватися через порт із номером 80, отже, втручання сервісів адміністратора системи не потрібне.

Для вибору протоколу можна користуватися таким алгоритмом:

ЯКЩО

необхідний доступ через проксі-сервер, налаштувати який на певний порт неможливо

або можливе використання із клієнтів, створених без застосування .Net Remoting

або якщо необхідно контролювати вміст обміну,

ТО

варто використовувати HttpChannel,

ІНАКШЕ

TcpChannel.

TcpChannel та HttpChannel – це двонапрямлені канали. У випадку, якщо програмний проект має клієнт-серверну архітектуру, використання саме двонапрямлених каналів недоцільне. Понад це, якщо між клієнтом і сервером міститься проксі-сервер, функціонування двонапрямлених каналів на клієнті неможливе. Для подібних випадків існують два різновиди односпрямованих каналів. Наприклад, для протоколу HTTP це HttpClientChannel і HttpServerChannel.

Однак кількість протоколів не обмежується використанням форматів Http+SOAP та Tcp+бінарний. Існує можливість створення власного каналу і форматера, реалізувавши IChannel і IRemotingFormatter відповідно. Можна також використовувати BinaryFormatter разом з HttpChannel і SoapFormatter з TcpChannel.

Нарешті, в.NET 2.0 надається доступ до IPC-каналу, представленому типом IpcChannel, що визначає комунікаційний канал зв'язку для віддаленої взаємодії. Через те, що IpcChannel при перетині доменів застосунків діє в обхід традиційних систем мережевої комунікації, IpcChannel виявляється набагато швидшим, ніж HTTP- і TCP-канали, однак, може використовуватися тільки для взаємодії доменів застосунка на одному комп'ютері. Тому IpcChannel не може застосовуватися для побудови розподілених застосунків, що допускають використання багатьох фізичних комп'ютерів. Але тип IpcChannel може виявитися ідеальним варіантом тоді, коли ви хочете забезпечити найвищу швидкість обміну інформацією між двома локальними програмами.

Важливо розуміти, що незалежно від типу каналу, який ви обираєте для використання, і HttpChannel, і TcpChannel, і IpcChannel реалізують інтерфейси IChannel, IChannelSender та IChannelReceiver. Інтерфейс IChannel визначає невеликий набір членів, що забезпечують загальну функціональність всіх типів каналів. Роль IChannelSender полягає у визначенні для каналів загальної множини членів, що дозволяють відсилати інформацію певному одержувачеві. З іншого боку, IChannelReceiver визначає множину членів, що дозволяють каналу одержувати інформацію від певного відправника.

Щоб дозволити застосункам клієнта і сервера зареєструвати обраний ними канал, потрібно використовувати метод ChannelServices.RegisterChannel (), що одержує тип, який реалізує IChannel. Нижче наведено фрагмент програмного коду, що демонструє, як домен серверного застосунка може зареєструвати Http-канал, що використовує порт 32469.

// Створення і реєстрація HttpChannel-сервера з портом 32469.

Http Channel c = new Http Channel (32469);

Channel Services .Register Channel (c);

Форматери .NET. Заключним елементом головоломки віддаленої взаємодії .NET є форматер. Типи TcpChannel та Http Channel використовують свої внутрішні форматери, завданням яких є переклад об’єкта повідомлення в терміни відповідного протоколу. Як зазначалось раніше, тип TcpChannel використовує тип BinaryFormatter, у той час як тип HttpChannel використовує функціональні можливості типу SoapFormatter.

Після створення відформатованого повідомлення воно передається в канал, яким зрештою досягає необхідного домена застосунка. У домені застосунка повідомлення перетворюється зі специфічних термінів протоколу знову у терміни .NET, після чого елемент, що називається диспетчер, викликає потрібний метод віддаленого об’єкту.

Прозорий агент, реальний агент, об’єкт повідомлення і диспетчер можна, як правило, просто ігнорувати, оскільки частіше за все придатні параметри віддаленої взаємодії, які пропонуються за замовчуванням. Послідовність подій віддаленої взаємодії .NET показана на рисунку 3.8, на якому зображена схема процесу комунікації двох об’єктів з різних доменів застосунків.

Передавання об’єктів клієнтові. У Remoting об'єкти передаються за значенням (by value) або за посиланням (by reference).

Примітка 1. Зверніть увагу на те, що параметри методів і значення, що повертаються, як правило, передаються за значенням. Створюючи класи, екземпляри яких передбачається передавати (повертати) у методи віддалених об'єктів за значенням, необхідно їх позначати атрибутом [Serializable] або реалізувати в них інтерфейс ISerializable.

При передаванні за посиланням передається тільки ідентифікатор (точніше, спеціальний об'єкт, ObjRef). Клієнт створює спеціальний проксі-клас, який скеровує виклики методів на сервер і одержує значення, що повертається. Об'єкт, переданий за посиланням, повинен успадковуватися від MarshalByRefObject. Насправді створюються два проксі-класи – «реальний» проксі (real proxy) і «прозорий» проксі (transparent proxy). Клієнт спілкується із другим, котрий, у свою чергу, створюється та керується першим. «Прозорий» проксі має такий самий набір методів, як і віддалений клас. При його використанні у клієнта створюється враження, що клас, з яким він працює, перебуває в адресному просторі клієнта, але насправді виклики методів серіалізуються та передаються каналами зв'язку екземпляру віддаленого об’єкту.

Примітка 2. Проксі створюється автоматично на базі інформації про типи об’єктів (reflection), але існує можливість реалізувати свій власний проксі.

Відзначимо одну відмінність між передаванням за значенням і за посиланням. У випадку передавання за значенням на клієнті повинен бути присутній код самого об’єкту. Як результат цього клієнтський код доводиться частіше оновлювати, оскільки будь-яка зміна серверного коду потребує відновлення клієнта. Другий недолік – наявність серверного коду на клієнті, що дає потенційному зловмисникові додаткові можливості, тому що код .Net чудово дизасемблюється. Виходячи із цього, треба дуже обережно підходити до передавання за значенням класів, що містять критично важливі дані і логіку. А при передаванні за посиланням цілком достатньо наявності опису інтерфейсу (збірки, що містить опис інтерфейсу без його реалізації).

Активація об’єктів. Для об'єктів, переданих за посиланням, існує два механізми створення об'єктів: на сервері (server activated) і на клієнті (client activated).

Об’єкти, що активуються сервером (server activated), не створюються на сервері в момент створення клієнтом проксі-класу. Замість цього вони створюються в момент першого виклику, або при кожному виклику методів. При цьому існують два типи подібних об'єктів – Singleton та SingleCall. Перші гарантують, що реальний екземпляр буде завжди один для всіх клієнтів. Другі створюють новий об'єкт для кожного виклику методу (модель, схожа на Web Services).

Примітка. У випадку об'єктів, що активуються сервером за замовчуванням немає жодної гарантії, що одному посиланню на клієнті буде відповідати завжди один і той самий екземпляр класу на сервері. Навіть Singleton, якщо до нього довгий час не зверталися, може бути сервером знищений, незважаючи на те, що клієнт все ще зберігає на нього посилання. Якщо потрібно створити дійсний сінглтон, тобто екземпляр, єдиний для усього застосунка, то варто перекрити метод InitializeLifetimeService і повернути з нього null. Це гарантує, що сервер ніколи цей екземпляр не знищить.

Об'єкти, що активуються клієнтом (client activated), на противагу тим, що активуються сервером, керуються клієнтом. Саме клієнт визначає час життя того чи іншого екземпляра. Однак, існує проблема видалення об'єктів, які керуються клієнтом, пов'язана з тим, що зв'язок сервер-клієнт принципово ненадійний. Об'єкти ж мають бути гарантовано знищені. Ситуація особливо загострюється у випадку протоколів, що не встановлюють постійного з'єднання, таких як HTTP. Класичний підхід до вирішеня цієї проблеми - клієнт періодично відсилає на сервер повідомлення про те, що клієнт живий. У технології Remoting використовується інший підхід: кожному екземпляру призначається час життя; по закінченні цього часу сервер посилає клієнтові запит, якщо клієнт дозволяє видалити екземпляр, або якщо відповіді від клієнта немає, сервер видаляє об'єкт.