Распределенные системы и алгоритмы

Разработка централизованного алгоритма балансировки распределенного приложения

Разбить на страницы
Показывать лекцию целиком

Постановка задачи:

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

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

Рекомендация: при выполнении работы использовать программные средства технологии .NET.

Описание централизованного алгоритма балансировки

Обычно практичное и полное решение задачи балансировки загрузки состоит из четырех шагов:

  • Оценка загрузки вычислительных узлов.
  • Инициация балансировки загрузки.
  • Принятие решений о балансировке.
  • Перемещение объектов.
  • В последующих частях конкретизируется каждый шаг балансировки с рассмотрением различных методов решения.

    Оценка загрузки

    На этом этапе осуществляется приблизительная оценка загрузки каждого процессора. Полученная информация о загрузке используется в качестве базы данных для процесса балансировки, во-первых, для определения возникновения дисбаланса, вовторых, для определения нового распределения объектов имитационной модели путем вычисления объема работ, необходимого для перемещения объектов. Отсюда, качество работы балансировки загрузки напрямую зависит от точности и полноты информации в базе данных.

    В основном такая база данных состоит из двух типов данных:

  • Данные о работе процессора (информация уровня процессора). Эти данные включают: загрузку процессора, время простоя процессора, фоновую загрузку процессора, скорость передачи информации по линиям связи и т.д.
  • Данные о работе распределенного приложения. Данные включают время выполнения отдельной задачи, время простоя, интенсивность обмена информацией и т.д.
  • Коммуникационная модель содержит важную информацию для принятия решений о перемещении задач при балансировке загрузки. При необходимости переместить объект с перегруженного процессора A на недогруженный процессор B целесообразно выбрать для перемещения тот объект, который наиболее интенсивно сообщается с задачами, уже расположенными на B.

    При распределении задач между процессорами производится оценка коммуникаций. Затраты на двухточечную связь между двумя задачами могут быть определены через объем передаваемых данных ( b – объём сообщений в байтах) и частоту коммуникации ( n – количество сообщений за единицу времени). Используя величины затрат процессора на каждое сообщение и каждый байт, можно оценить общие затраты на коммуникацию между двумя задачами: $$\alpha \cdot n + \beta \cdot b$$, где b – общий объем всех n сообщений.

    Оценка загрузки процессора и объекта может быть произведена несколькими способами. Один из способов (аналитический), обычно используемый при статической балансировке загрузки и состоит в приблизительной оценке загрузки каждого объекта на основе знаний о приложении. К этим знаниям относятся:

  • функция от размера объема данных, отражающая сложность алгоритма
  • модель коммуникаций между задачами.
  • Другой способ сбора данных о загрузке состоит в измерении загрузки процессоров и задач. Большинство современных машин снабжено счетчиками времени (с точностью до микросекунд), которые могут быть использованы для измерения времени выполнения каждой задачи. Также этот метод потенциально предоставляет автоматическое решение задачи оценки стоимости загрузки. Преимущество метода состоит в том, что он является точным и не требует больших усилий программиста. К недостаткам можно отнести следующее: стратегии балансировки, основанные на этом методе (измерение) учитывают прошлое распределение нагрузок. Если загрузка задач меняется непредсказуемым образом, то метод будет неточным.

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

    Рекомендации по выполнению: использовать аналитический способ оценки загрузки.

    Инициализация балансировки загрузки

    Для продуктивности балансировки необходимо какимто образом определять момент ее инициализации.

    Для этого следует:

  • Определить момент возникновения дисбаланса загрузки.
  • Определить степень необходимости балансировки путем сравнения возможной пользы от ее проведения и затрат на нее.
  • Дисбаланс загрузки может определяться синхронно и асинхронно.

    При синхронном определении дисбаланса все процессоры (компьютеры сети) прерывают работу в определенные моменты синхронизации и определяют дисбаланс загрузки путем сравнения загрузки отдельного процессора с общей средней загрузкой.

    При асинхронном определении дисбаланса каждый процессор хранит историю своей загрузки. В этом случае момент синхронизации для определения степени дисбаланса отсутствует. Вычислением объема дисбаланса занимается фоновый процесс, работающий параллельно с приложением.

    Рекомендации по выполнению: следует использовать синхронный способ определения баланса

    Принятие решений в процессе балансировки

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

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

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

    Рекомендации по выполнению: следует придерживаться централизованной стратегией.

    Перемещение объектов

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

    Рекомендации по выполнению: следует использовать технологию .Net Remoting.

    Использование .NET Remoting

    .NET Framework Remoting является технологией, на основе которой становится возможным взаимодействие между процессами. Структура удаленного доступа, также называемая .NET Remoting или просто Remoting, предоставляет простой набор классов и инструментов для обеспечения возможности межпроцессного взаимодействия.

    Клиент содержит объект, называемый прокси, который на самом деле является указателем на объект, существующий в процессе сервера. Клиент думает, что объект является локальным; однако, когда делаются обращения к этому объекту, структура удаленного доступа отвечает за то, чтобы гарантировать передачу вызова для исполнения серверу. Чтобы произвести удаленный вызов, структура удаленного доступа отвечает за форматирование запроса в формат данных, который понимает сервер. Как только вызов отформатирован, он передается в транспортный канал, который передает вызов на машину сервера.

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

    Терминология .NET Remoting

    Как и любая другая технология .NET Remoting вводит свои термины и понятия. Рассмотрим основные термины, связанные с удаленным доступом в .NET.

    MarshalByRefObject

    Имеется два способа, которыми клиент может взаимодействовать с объектами, расположенными на сервере. Вопервых, мы можем передавать клиенту ссылку на объект, выполняющийся на сервере. Клиент будет осуществлять вызовы по этой ссылке. Как будто это локальный объект. Однако когда производятся вызовы, ссылка будет на самом деле передавать вызовы в серверный процесс, там исполнять запрос и при помощи маршалинга передавать результаты обратно клиенту. Объекты, которые доступны через удаленный доступ как MarshalByRefObject, исполняются на сервере; на стороне клиента не выполняется никакой работы. Клиент имеет объектпрокcи, который отвечает за взаимодействие с сервером. Объект на сервере наследуется от System.MarshalByRefObject, который является базовым классом для того, чтобы позволить клиенту взаимодействовать с прокcиобъектами.

    Сериализуемый (ByValue по значению)

    В отличие от MarshalByRefObject; мы можем реализовать объект, который, будучи созданным, передается назад клиенту. Клиент запрашивает объект у сервера, сервер создает этот объект, сериализует его в текстовое или двоичное представление и полностью передает его клиенту. Как только клиент получает этот объект в сое распоряжение, между клиентом и сервером не происходит никакого взаимодействия. Все вызовы выполняются относительно объекта, который выполняется на стороне клиента, как будто клиент сам создал этот объект. Сериализуемые объекты часто называются "Передаваемыми" (маршализуемыми) по значению, чтобы подчеркнуть то, что клиенту передается весь объект целиком, а не только ссылка на него.

    В .NET все, что мы должны сделать, чтобы передавать наш объект от сервера к клиенту по значению это предоставить атрибут Serializable. Структура удаленного доступа сама позаботится об упаковке объекта, пересылке его к клиенту и воссоздании его в пространстве клиента.

    Форматер

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

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

    В дополнение к предоставлению возможности создавать ваш собственный форматер, структура удаленного доступа предлагает два готовых форматера двоичный форматер и форматер SOАР.

    Двоичный форматер очень эффективен, так как он может сериализовать объект в очень маленький байтовый поток. Все объекты, сериализованные при помощи двоичного форматера, также должны им десериализоваться, так что он является идеальным решение, если у вас на обоих концах провода имеется .NET.

    Однако эффективность двоичного форматера имеет свою цену; его выходной поток не является читабельным для человека и ограничен теми платформами, на которых установлен двоичный форматер. В настоящий момент двоичный форматер был реализован, только на платформе ,NET, так что использование двоичного форматера требует, чтобы вы посылали данные от сервера .NET к клиенту .NET и обратно.

    Форматер SOAP передает данные в формате сообщений SOAP. Сообщения SOAP более многословны, чем их двоичные аналоги, что делает их менее эффективными, чем сообщения в двоичном формате.

    Однако форматер SOAP имеет гораздо больше возможностей, чем двоичный форматер, с точки зрения предоставления переносимости и взаимодействия с сообщениями. Возможно, наиболее интересным использованием SOAP является возможность обрабатывать и интерпретировать сообщения SOAP любой платформой, которая понимает SOAP. Эта гибкость позволяет нам реализовать сервер и клиента для различных платформ, в частности для .NET и Java, но не только для них. Клиент Java может принимать сообщение Java от сервера .NET, и наоборот. Это является основой вебслужб. Единственным еще не указанным требованием для обеспечения межплатформенного взаимодействия является передача сообщения SOAP по одному и тому же протоколу или каналу.

    Канал

    Аналогично тому, как клиент и сервер должны договориться по формату сообщений, они также должны договориться о механизме взаимодействия, или канале, с помощью которого будут передаваться данные. Каналы являются транспортными механизмами, с помощью которых передаются данные. Например, World Wide Web использует в качестве соглашения по каналу взаимодействия HTTP. Если клиентский компьютер может послать запрос HTTP к серверу, то сервер может ответить при помощи ответа HTTP и взаимодействие успешно состоится. Если клиентский компьютер передает запрос, используя канал SMTP, и получает данные в формате HTTP, то взаимодействия не произойдет. Аналогично веб, клиенты и серверы удаленного доступа должны договориться о канале взаимодействия.

    Аналогично тому, как можно в .NET Remoting написать наш собственный форматер, также возможно создать наш собственный канал. Создание канала будет вопросом реализаций набора идентификаторов, которые будет понимать как клиент; так и сервер. Например, мы можем реализовать канал SMTP и посылать сообщения в формате SMTP.

    .NET Framework поставляется с двумя готовыми каналами, которые называются каналами TCP и HTTP. Канал TCP взаимодействует по протоколу TCP и очень эффективен. Канал HTTP посылает сообщения по протоколу HTTP, высокоуровневому протоколу, основанному на TCP/IP.

    Аналогично двоичному форматеру, канал TCP ограничен теми платформами, которые могут осуществлять взаимодействие по TCP. Обычно это означает, что, так же как и двоичный форматер, обе стороны взаимодействия должны быть клиентами .NET.

    Канал HTTP посылает сообщения по протоколу HTTP. Если процессы клиента и сервера могут осуществлять взаимодействие по каналу HTTP, то взаимодействие будет успешным. Так как HTTP основан на TCP, канал HTTP не так эффективен, как взаимодействие на основе TCP. Однако так как протокол HTTP очень популярен и реализован на большинстве платформ, канал HTTP более гибок.

    Принципы работы с каналами/форматерами

    Комбинация канал/форматер является важным решением, которое мы должны принять при разработке. Использование настроечные файлов позволяет динамически изменять форматер и канал после развертывания приложения. Даже при наличии возможности изменения форматера и канала, при разработке приложения необходимо принять правильное решение относительно конфигурации. Не являясь строгим правилом, следующая таблица дает рекомендации по выбору форматера.

    КаналФорматерХарактеристики
    TCP Двоичный Самая быстрая комбинация канал/форматер. Эта комбинация эффективного канала TCP и короткого двоичного формата является идеальным выбором для обеспечения скорости. Идеальным при условии, что оба клиента используют .NET.
    TCP SOAP Обычно не используется. Если вы укажете канал TCP, то вы будете ограничены теми платформами, которые могут взаимодействовать по сырому TCP. При написании этой книги использование каналов TCP требовало .NET, в которой следует использовать двоичный форматер.
    HTTP Двоичный Обычно не используется. Двоичный форматер реализован только в .NET. При наличии на обоих концах клиентов .NET, наилучшую производительность обеспечит комбинация TCP и двоичного форматера.
    HTTP SOAP Идеальна для стандартизованного взаимодействия между клиентами .NET и "не.NET". Производительность не так хороша, как в случае комбинации TCP/двоичный. Однако гибкость, предлагаемая этой комбинацией, идеальна для предоставления взаимодействия со всеми, кто поддерживает стек HTTP и SOAP. Является основой вебслужб.

    Создание объекта с возможностью удаленного доступа

    В данной лабораторной работе необходимо создать объект, который будет размещаться на сервере и вызываться клиентом через канал HTTP с использованием форматера канала HTTP по умолчанию (форматера SOAP). Так как на обоих концах взаимодействия имеется .NET, также легко можно бы использовать канал TCP и двоичный форматер.

    Целью данной лабораторной работы является демонстрация вызова функциональности сервера через вызов удаленного доступа.

    В данной работе мы создадим объект с простым вычислительным методом и покажем его исполнение на сервере. Необходимо разработать следующие компоненты приложения:

  • вызываемый удаленно объект;
  • сервер, который будет содержать этот объект удаленного доступа;
  • клиент, который будет использовать объект удаленного доступа.
  • Архитектура приложения представлена на рисунке.

    Клиент будет создавать объект Order и будет думать, что он локален по отношению к процессу клиента. Однако при использовании объекта Order структура удаленного доступа будет упаковывать вызов в сообщение SOAP и передавать его через HTTP порт 8080 на сервер. Сервер будет распаковывать сообщение SOAP, исполнять метод и запаковывать сообщение для возврата сообщения SOAP клиенту. Клиент будет распаковывать ответный вызов, и получать результаты вызова метода.

    Перед тем, как мы реализуем сервер и клиента удаленного доступа, нам требуется создать объект или набор объектов, которые можно будет вызывать через удалённый доступ. Чтобы предоставить наш класс, нам требуется определить, реализовывать ли наш объект как MarshalByRefObject или как сериализуемый. Так как мы хотим использовать логику исполнения нашего объекта на сервере, мы должны создать объект MarshalByRefObject.

    Следующий код предоставляет базовый объект, который будет доступен через удаленный доступ:

    using System;
    using System.Collections.Generic;
    using System.Text;
    
    namespace Order
    {
        public class Order:MarshalByRefObject
        {
            private DateTime m_creation;
    
            public Order()
            {
                m_creation = DateTime.Now;
            }
    
            public String GetMachineName()
            {
                Console.WriteLine("Order.GetMachineName() called.");
                return String.Format("Order object created at: {0} on {1}", 
                    m_creation.ToLongTimeString(), Environment.MachineName);
            }
    
            public Double CalculateItem(Double cost, int TaxCode)
            {
                Console.WriteLine("Order.CalculateItem() called.");
                switch (TaxCode)
                {
                    case 0:
                        return cost;
                    case 1:
                        return cost*1.06;
                    case 2:
                        return cost*1.12;
                    default:
                        throw new Exception("Error!");
                }
            }
        }
    }

    Заметьте, что логика объекта не изменяется изза того, что мы планируем сделать его доступным через удаленный доступ. Единственным отличием между этим и стандартным объектами заключается в том, что он наследуется от MarshalByRefObject, что делает его доступным через уделенный доступ.

    Мы храним время создания объекта, чтобы можно было определить, когда объект был создан. Свойство GetMachineName возвращает имя машины, на которой выполняется код объекта. Имя машины докажет, что объект на самом деле исполняется в процессе сервера. Метод CalculateItem() является небольшим примером бизнеслогики, которая может находиться в классе Order. Очевидно, что для целей демонстрации мы создаем простую функцию. Если бы это был настоящий объект Order, то метод был бы гораздо сложнее; возможно, метод CalculateItem() возвращал бы документ XML, определяющий весь заказ на покупку.

    Хорошим правилом при создании объектов удаленного доступа является отсутствие у них состояний. Так как объекты удаленного доступа будут вызываться из многих клиентских приложений, мы не хотим хранить открытые экземпляры для каждого пользователя.

    Создание сервера

    Теперь, когда мы создали объект, нам требуется поместить этот объект на нашем сервере. Объект удаленного доступа требует наличия сервера, который предоставляет этот объект через порт клиентам. Каждый объект удаленного доступа должен быть опубликован на хосте сервера. Хостом может быть IIS, служба Windows или самостоятельно реализованный хост. Для простоты мы создадим наш собственный хост для публикации этого объекта удаленного доступа.

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Runtime.Remoting;
    
    namespace Server
    {
        class Program
        {
            static void Main(string[] args)
            {
                Console.WriteLine("Server started.");
                RemotingConfiguration.Configure("server.exe.config");
                Console.WriteLine("Server is running. Press <Enter> to exit.");
                Console.ReadLine();
            }
        }
    }

    Перед тем, как мы сможем запустить сервер, мы должны определить объекты удаленного доступа, которые следует опубликовать. Структура удаленного доступа позволяет нам читать конфигурацию из настроечного файла приложения. Мы могли бы "зашить" конфигурацию непосредственное приложение, но в этом случае изменение конфигурации потребовало бы перекомпиляции сервера. Настроечные файлы предлагают гораздо более гибкое решение, чем "зашивание" конфигурации в хост сервера.

    Как только настроенный файл создан, мы говорим среде выполнения удаленного доступа получить конфигурацию из этого файла при помощи строки:

    RemotingConfiguration.Configure("server.exe.config");

    Файл server.exe.config имеет следующий вид:

    <?xml version="1.0" encoding="utf8" ?>
    <configuration>
      <system.runtime.remoting>
        <application>
          <channels>
            <channel ref="http" port="8080"/>
          </channels>  
          <service>
            <wellknown mode="Singleton" type="Order.Order, Order" objectUri="Order.soap"/>
          </service>  
        </application>  
      </system.runtime.remoting>
    </configuration>

    Структура удаленного доступа читает узел < system.runtime.remoting > и настраивает среду выполнения удаленного доступа в соответствии с его содержимым. Этот настроечный файл должен быть размещен в той же директории, где и server.exe.

    В файле указывается, какой канал необходимо открыть для объекта. Так как используется канал HTTP, тэг канала задается следующим образом:

    <channel ref="http" port="8080"/>

    Мы также должны открыть объект, и для этого имеется два типа создания объекта wellknown и activated. Аналогично объектам СОМ, объекты типа activated могут иметь состояние и их время жизни определяется клиентом. Объекты типа wellknown создаются в процессе сервера и время их жизни определяется сервером.

    Имеется два режима объектов wellknown Singleton и SingleCall. В режиме Singleton создается один объект для обработки всех запросов. Объект сохраняется между запросами клиентов. Объекты SingleCall создаются для каждого запроса переданного клиентом. Каждый раз, когда приходит клиентский запрос, создается новый объект, обслуживается запрос клиента, а затем объект удаляется. Объект Singleton великолепно подходит, если вы хотите совместно использовать общие данные для всех запросов клиентов.

    Объекты SingleCall не оставляют следов, так как все созданные объекты уничтожаются при завершении обработки запроса.

    Вот иллюстрация использования объекта Singleton:

    <wellknown mode="Singleton" type="Order.Order, Order" objectUri="Order.soap"/>

    Свойство type говорит среде выполнения удаленного доступа, какой объект должен быть опубликован, и объявляется в формате <тип>, <сборка>. Здесь свойство type говорит, что мы хотим опубликовать объект Order из сборки Order.dll. Чтобы это всё правильно работало, сборка Order.dll должна располагаться там, где среда выполнения сможет ее найти. Мы устанавливаем Order.dll в той же физической директории, что и Server.exe. Заметьте, что расширение .dll сборки не указывается.

    Свойство objectUri является идентификатором, под которым наш объект будет опубликован. Так как по одному и тому же каналу и порту может вызываться много различных объектов, мы должны дать каждому объекту уникальный идентификатор, чтобы отличать их друг от друга. Мы даем ему расширение .soap, чтобы указать, что этот объект будет использовать форматер SOAP. Так как форматер SOAP является форматером по умолчанию для канала HTTP, мы не должны указывать форматер в этом настроечном файле.

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

    Создание клиента

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

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Runtime.Remoting;
    
    namespace Client
    {
        class Program
        {
            static void Main(string[] args)
            {
                Console.WriteLine("Клиент создан в {0} на {1}",
                    DateTime.Now.ToLongTimeString(),Environment.MachineName);
                RemotingConfiguration.Configure("client.exe.config");
                Order.Order o = new Order.Order();
                Console.WriteLine(o.GetMachineName());
                Console.WriteLine("Итоговая стоимость: {0}",
                    o.CalculateItem(12.48,2));
                Console.ReadLine();
            }
        }
    }

    Чтобы откомпилировать эти приложение, мы должны создать ссылки на объект среды выполнения удаленного доступа и Order.dll. Может показаться странным, что нам требуется ссылка на Order.dll, так как объект исполняется исключительно на сервере. Клиенту, чтобы он мог осуществлять вызов серверного объекта, требуются метаданные из объекта удаленного доступа. Без этих метаданных компилятор и среда выполнения не будут иметь ни малейшего представления, что представляет из себя объект удаленного доступа. Мы также можем получить метаданные с помощью инструмента soapsuds.exe. Для краткости мы будем хранить экземпляр Order.dll на стороне клиента. За дополнительной информацией по вопросам о метаданных обратитесь к документации по .NET SDK и, в частности, по инструменту командной строки soapsuds.exe.

    Точно так же, как и на сервере, клиент реализует настроечный файл для получения конфигурации своего объекта удаленного доступа. Файл называется client.exe.config и хранится в той же директории, что и клиентское приложение:

    <?xml version="1.0" encoding="utf8" ?>
    <configuration>
      <system.runtime.remoting>
        <application>
          <client>
            <wellknown type="Order, Order" url="http://mobil185:8080/Order.soap"/>
          </client>
        </application>
      </system.runtime.remoting>
    </configuration>

    Рекомендации по выполнению: при выполнении задания следуют использовать волновой алгоритм для структуры – неориентированное дерево. Волновой алгоритм приведен ниже.

    Волновой алгоритм для структуры – дерева

    Предположим, что соединение сайтов распределенной системы каналами образует граф – неориентированное дерево. Из теории графов известны следующие факты для деревьев:

  • дерево – связный ациклический граф;
  • количество вершин в дереве на единицу больше, чем количество ребер;
  • в нетривиальном дереве имеется, по крайней мере, две вершины, степени которых равны единице; эти вершины называются висячими или терминальными; остальные вершины имеют степень, не меньше 2.
  • В описываемом алгоритме инициаторами являются все висячие вершины. Любой инициатор может передать маркер только одному соседнему сайту. Любой другой сайт v (не инициатор), имеющий степень deg(v), генерирует маркер только в том случае, если получил маркеры от deg(v) – 1 соседа, т.е. от всех смежных сайтов, кроме одного. Тогда сайт v отправляет маркер тому единственному соседу, от которого маркера еще не было (вполне возможно, что этот сосед просто задержался с передачей).

    Если задержавшийся сосед все же передаст маркер, т.е. сайт v получит deg(v) маркеров, то сайт v выполнит процедуру return(OK). Выполнение процедуры return(OK) любым из сайтов завершает работу распределенного алгоритма.

    (рис l-1) Шаг 1. Маркеры, инициированные висячими вершинами дерева (рис l-2) Шаг 2. Продвижение маркеров по дереву (рис l-3) Шаг 3. Заключительное перемещение маркеров

    Описанный алгоритм не столь очевиден, как алгоритм для кольцевой архитектуры. Поэтому нам нужны гарантии его правильности, а именно, гарантии того, что если какойлибо из сайтов выполнил процедуру return(OK), все остальные сайты vi получили, по крайней мере, по deg(vi) – 1 маркеров и сгенерировали или готовы сгенерировать выходные маркеры.

    Рисунки l-2l-3 иллюстрируют на примере некоторого дерева продвижение маркеров. На шаге 2 вершины, уже получившие маркеры, обозначены соответствующими числами. После выполнения шага 3, вершина, обозначенная "a" и имеющая степень 3, получит последние два маркера. Количество полученных маркеров станет равным трем, и будет выполнена процедура return(OK).

    Отметим, что эти рисунки и приведенные выше комментарии к ним справедливы для случая, когда перемещение любого маркера по любому ребру дерева требует одного и того же времени, а генерация маркера происходит мгновенно. Инициаторы также одновременно генерируют свои маркеры.

    В противном случае процесс закончится в какой-либо другой (не висячей) вершине дерева. Если же какая-либо из висячих вершин – инициаторов сильно запоздает с генерацией своего маркера, то может возникнуть непредусмотренная ситуация получения маркера висячей вершиной.

    Сказанное еще раз подтверждает то, что выполнение распределенного алгоритма не является строго детерминированным во времени, но, тем не менее, при правильном построении алгоритма может быть детерминированным по результатам.

    Отчетность:

    В результате выполнения лабораторной работы должны быть представлены следующие материалы:

  • Программа;
  • Исходные тексты;
  • Презентация работы;
  • Презентация, в которой освещаются вопросы реализации консервативных алгоритмов.
  • Страницы:

    Постановка задачи:

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

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

    Рекомендация: при выполнении работы использовать программные средства технологии .NET.

    Описание централизованного алгоритма балансировки

    Обычно практичное и полное решение задачи балансировки загрузки состоит из четырех шагов:

  • Оценка загрузки вычислительных узлов.
  • Инициация балансировки загрузки.
  • Принятие решений о балансировке.
  • Перемещение объектов.
  • В последующих частях конкретизируется каждый шаг балансировки с рассмотрением различных методов решения.

    Оценка загрузки

    На этом этапе осуществляется приблизительная оценка загрузки каждого процессора. Полученная информация о загрузке используется в качестве базы данных для процесса балансировки, во-первых, для определения возникновения дисбаланса, вовторых, для определения нового распределения объектов имитационной модели путем вычисления объема работ, необходимого для перемещения объектов. Отсюда, качество работы балансировки загрузки напрямую зависит от точности и полноты информации в базе данных.

    В основном такая база данных состоит из двух типов данных:

  • Данные о работе процессора (информация уровня процессора). Эти данные включают: загрузку процессора, время простоя процессора, фоновую загрузку процессора, скорость передачи информации по линиям связи и т.д.
  • Данные о работе распределенного приложения. Данные включают время выполнения отдельной задачи, время простоя, интенсивность обмена информацией и т.д.
  • Коммуникационная модель содержит важную информацию для принятия решений о перемещении задач при балансировке загрузки. При необходимости переместить объект с перегруженного процессора A на недогруженный процессор B целесообразно выбрать для перемещения тот объект, который наиболее интенсивно сообщается с задачами, уже расположенными на B.

    При распределении задач между процессорами производится оценка коммуникаций. Затраты на двухточечную связь между двумя задачами могут быть определены через объем передаваемых данных ( b – объём сообщений в байтах) и частоту коммуникации ( n – количество сообщений за единицу времени). Используя величины затрат процессора на каждое сообщение и каждый байт, можно оценить общие затраты на коммуникацию между двумя задачами: $$\alpha \cdot n + \beta \cdot b$$, где b – общий объем всех n сообщений.

    Оценка загрузки процессора и объекта может быть произведена несколькими способами. Один из способов (аналитический), обычно используемый при статической балансировке загрузки и состоит в приблизительной оценке загрузки каждого объекта на основе знаний о приложении. К этим знаниям относятся:

  • функция от размера объема данных, отражающая сложность алгоритма
  • модель коммуникаций между задачами.
  • Другой способ сбора данных о загрузке состоит в измерении загрузки процессоров и задач. Большинство современных машин снабжено счетчиками времени (с точностью до микросекунд), которые могут быть использованы для измерения времени выполнения каждой задачи. Также этот метод потенциально предоставляет автоматическое решение задачи оценки стоимости загрузки. Преимущество метода состоит в том, что он является точным и не требует больших усилий программиста. К недостаткам можно отнести следующее: стратегии балансировки, основанные на этом методе (измерение) учитывают прошлое распределение нагрузок. Если загрузка задач меняется непредсказуемым образом, то метод будет неточным.

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

    Рекомендации по выполнению: использовать аналитический способ оценки загрузки.

    Инициализация балансировки загрузки

    Для продуктивности балансировки необходимо какимто образом определять момент ее инициализации.

    Для этого следует:

  • Определить момент возникновения дисбаланса загрузки.
  • Определить степень необходимости балансировки путем сравнения возможной пользы от ее проведения и затрат на нее.
  • Дисбаланс загрузки может определяться синхронно и асинхронно.

    При синхронном определении дисбаланса все процессоры (компьютеры сети) прерывают работу в определенные моменты синхронизации и определяют дисбаланс загрузки путем сравнения загрузки отдельного процессора с общей средней загрузкой.

    При асинхронном определении дисбаланса каждый процессор хранит историю своей загрузки. В этом случае момент синхронизации для определения степени дисбаланса отсутствует. Вычислением объема дисбаланса занимается фоновый процесс, работающий параллельно с приложением.

    Рекомендации по выполнению: следует использовать синхронный способ определения баланса

    Принятие решений в процессе балансировки

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

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

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

    Рекомендации по выполнению: следует придерживаться централизованной стратегией.

    Перемещение объектов

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

    Рекомендации по выполнению: следует использовать технологию .Net Remoting.

    Использование .NET Remoting

    .NET Framework Remoting является технологией, на основе которой становится возможным взаимодействие между процессами. Структура удаленного доступа, также называемая .NET Remoting или просто Remoting, предоставляет простой набор классов и инструментов для обеспечения возможности межпроцессного взаимодействия.

    Клиент содержит объект, называемый прокси, который на самом деле является указателем на объект, существующий в процессе сервера. Клиент думает, что объект является локальным; однако, когда делаются обращения к этому объекту, структура удаленного доступа отвечает за то, чтобы гарантировать передачу вызова для исполнения серверу. Чтобы произвести удаленный вызов, структура удаленного доступа отвечает за форматирование запроса в формат данных, который понимает сервер. Как только вызов отформатирован, он передается в транспортный канал, который передает вызов на машину сервера.

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

    Терминология .NET Remoting

    Как и любая другая технология .NET Remoting вводит свои термины и понятия. Рассмотрим основные термины, связанные с удаленным доступом в .NET.

    MarshalByRefObject

    Имеется два способа, которыми клиент может взаимодействовать с объектами, расположенными на сервере. Вопервых, мы можем передавать клиенту ссылку на объект, выполняющийся на сервере. Клиент будет осуществлять вызовы по этой ссылке. Как будто это локальный объект. Однако когда производятся вызовы, ссылка будет на самом деле передавать вызовы в серверный процесс, там исполнять запрос и при помощи маршалинга передавать результаты обратно клиенту. Объекты, которые доступны через удаленный доступ как MarshalByRefObject, исполняются на сервере; на стороне клиента не выполняется никакой работы. Клиент имеет объектпрокcи, который отвечает за взаимодействие с сервером. Объект на сервере наследуется от System.MarshalByRefObject, который является базовым классом для того, чтобы позволить клиенту взаимодействовать с прокcиобъектами.

    Сериализуемый (ByValue по значению)

    В отличие от MarshalByRefObject; мы можем реализовать объект, который, будучи созданным, передается назад клиенту. Клиент запрашивает объект у сервера, сервер создает этот объект, сериализует его в текстовое или двоичное представление и полностью передает его клиенту. Как только клиент получает этот объект в сое распоряжение, между клиентом и сервером не происходит никакого взаимодействия. Все вызовы выполняются относительно объекта, который выполняется на стороне клиента, как будто клиент сам создал этот объект. Сериализуемые объекты часто называются "Передаваемыми" (маршализуемыми) по значению, чтобы подчеркнуть то, что клиенту передается весь объект целиком, а не только ссылка на него.

    В .NET все, что мы должны сделать, чтобы передавать наш объект от сервера к клиенту по значению это предоставить атрибут Serializable. Структура удаленного доступа сама позаботится об упаковке объекта, пересылке его к клиенту и воссоздании его в пространстве клиента.

    Форматер

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

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

    В дополнение к предоставлению возможности создавать ваш собственный форматер, структура удаленного доступа предлагает два готовых форматера двоичный форматер и форматер SOАР.

    Двоичный форматер очень эффективен, так как он может сериализовать объект в очень маленький байтовый поток. Все объекты, сериализованные при помощи двоичного форматера, также должны им десериализоваться, так что он является идеальным решение, если у вас на обоих концах провода имеется .NET.

    Однако эффективность двоичного форматера имеет свою цену; его выходной поток не является читабельным для человека и ограничен теми платформами, на которых установлен двоичный форматер. В настоящий момент двоичный форматер был реализован, только на платформе ,NET, так что использование двоичного форматера требует, чтобы вы посылали данные от сервера .NET к клиенту .NET и обратно.

    Форматер SOAP передает данные в формате сообщений SOAP. Сообщения SOAP более многословны, чем их двоичные аналоги, что делает их менее эффективными, чем сообщения в двоичном формате.

    Однако форматер SOAP имеет гораздо больше возможностей, чем двоичный форматер, с точки зрения предоставления переносимости и взаимодействия с сообщениями. Возможно, наиболее интересным использованием SOAP является возможность обрабатывать и интерпретировать сообщения SOAP любой платформой, которая понимает SOAP. Эта гибкость позволяет нам реализовать сервер и клиента для различных платформ, в частности для .NET и Java, но не только для них. Клиент Java может принимать сообщение Java от сервера .NET, и наоборот. Это является основой вебслужб. Единственным еще не указанным требованием для обеспечения межплатформенного взаимодействия является передача сообщения SOAP по одному и тому же протоколу или каналу.

    Канал

    Аналогично тому, как клиент и сервер должны договориться по формату сообщений, они также должны договориться о механизме взаимодействия, или канале, с помощью которого будут передаваться данные. Каналы являются транспортными механизмами, с помощью которых передаются данные. Например, World Wide Web использует в качестве соглашения по каналу взаимодействия HTTP. Если клиентский компьютер может послать запрос HTTP к серверу, то сервер может ответить при помощи ответа HTTP и взаимодействие успешно состоится. Если клиентский компьютер передает запрос, используя канал SMTP, и получает данные в формате HTTP, то взаимодействия не произойдет. Аналогично веб, клиенты и серверы удаленного доступа должны договориться о канале взаимодействия.

    Аналогично тому, как можно в .NET Remoting написать наш собственный форматер, также возможно создать наш собственный канал. Создание канала будет вопросом реализаций набора идентификаторов, которые будет понимать как клиент; так и сервер. Например, мы можем реализовать канал SMTP и посылать сообщения в формате SMTP.

    .NET Framework поставляется с двумя готовыми каналами, которые называются каналами TCP и HTTP. Канал TCP взаимодействует по протоколу TCP и очень эффективен. Канал HTTP посылает сообщения по протоколу HTTP, высокоуровневому протоколу, основанному на TCP/IP.

    Аналогично двоичному форматеру, канал TCP ограничен теми платформами, которые могут осуществлять взаимодействие по TCP. Обычно это означает, что, так же как и двоичный форматер, обе стороны взаимодействия должны быть клиентами .NET.

    Канал HTTP посылает сообщения по протоколу HTTP. Если процессы клиента и сервера могут осуществлять взаимодействие по каналу HTTP, то взаимодействие будет успешным. Так как HTTP основан на TCP, канал HTTP не так эффективен, как взаимодействие на основе TCP. Однако так как протокол HTTP очень популярен и реализован на большинстве платформ, канал HTTP более гибок.

    Принципы работы с каналами/форматерами

    Комбинация канал/форматер является важным решением, которое мы должны принять при разработке. Использование настроечные файлов позволяет динамически изменять форматер и канал после развертывания приложения. Даже при наличии возможности изменения форматера и канала, при разработке приложения необходимо принять правильное решение относительно конфигурации. Не являясь строгим правилом, следующая таблица дает рекомендации по выбору форматера.

    КаналФорматерХарактеристики
    TCP Двоичный Самая быстрая комбинация канал/форматер. Эта комбинация эффективного канала TCP и короткого двоичного формата является идеальным выбором для обеспечения скорости. Идеальным при условии, что оба клиента используют .NET.
    TCP SOAP Обычно не используется. Если вы укажете канал TCP, то вы будете ограничены теми платформами, которые могут взаимодействовать по сырому TCP. При написании этой книги использование каналов TCP требовало .NET, в которой следует использовать двоичный форматер.
    HTTP Двоичный Обычно не используется. Двоичный форматер реализован только в .NET. При наличии на обоих концах клиентов .NET, наилучшую производительность обеспечит комбинация TCP и двоичного форматера.
    HTTP SOAP Идеальна для стандартизованного взаимодействия между клиентами .NET и "не.NET". Производительность не так хороша, как в случае комбинации TCP/двоичный. Однако гибкость, предлагаемая этой комбинацией, идеальна для предоставления взаимодействия со всеми, кто поддерживает стек HTTP и SOAP. Является основой вебслужб.

    Создание объекта с возможностью удаленного доступа

    В данной лабораторной работе необходимо создать объект, который будет размещаться на сервере и вызываться клиентом через канал HTTP с использованием форматера канала HTTP по умолчанию (форматера SOAP). Так как на обоих концах взаимодействия имеется .NET, также легко можно бы использовать канал TCP и двоичный форматер.

    Целью данной лабораторной работы является демонстрация вызова функциональности сервера через вызов удаленного доступа.

    В данной работе мы создадим объект с простым вычислительным методом и покажем его исполнение на сервере. Необходимо разработать следующие компоненты приложения:

  • вызываемый удаленно объект;
  • сервер, который будет содержать этот объект удаленного доступа;
  • клиент, который будет использовать объект удаленного доступа.
  • Архитектура приложения представлена на рисунке.

    Клиент будет создавать объект Order и будет думать, что он локален по отношению к процессу клиента. Однако при использовании объекта Order структура удаленного доступа будет упаковывать вызов в сообщение SOAP и передавать его через HTTP порт 8080 на сервер. Сервер будет распаковывать сообщение SOAP, исполнять метод и запаковывать сообщение для возврата сообщения SOAP клиенту. Клиент будет распаковывать ответный вызов, и получать результаты вызова метода.

    Перед тем, как мы реализуем сервер и клиента удаленного доступа, нам требуется создать объект или набор объектов, которые можно будет вызывать через удалённый доступ. Чтобы предоставить наш класс, нам требуется определить, реализовывать ли наш объект как MarshalByRefObject или как сериализуемый. Так как мы хотим использовать логику исполнения нашего объекта на сервере, мы должны создать объект MarshalByRefObject.

    Следующий код предоставляет базовый объект, который будет доступен через удаленный доступ:

    using System;
    using System.Collections.Generic;
    using System.Text;
    
    namespace Order
    {
        public class Order:MarshalByRefObject
        {
            private DateTime m_creation;
    
            public Order()
            {
                m_creation = DateTime.Now;
            }
    
            public String GetMachineName()
            {
                Console.WriteLine("Order.GetMachineName() called.");
                return String.Format("Order object created at: {0} on {1}", 
                    m_creation.ToLongTimeString(), Environment.MachineName);
            }
    
            public Double CalculateItem(Double cost, int TaxCode)
            {
                Console.WriteLine("Order.CalculateItem() called.");
                switch (TaxCode)
                {
                    case 0:
                        return cost;
                    case 1:
                        return cost*1.06;
                    case 2:
                        return cost*1.12;
                    default:
                        throw new Exception("Error!");
                }
            }
        }
    }

    Заметьте, что логика объекта не изменяется изза того, что мы планируем сделать его доступным через удаленный доступ. Единственным отличием между этим и стандартным объектами заключается в том, что он наследуется от MarshalByRefObject, что делает его доступным через уделенный доступ.

    Мы храним время создания объекта, чтобы можно было определить, когда объект был создан. Свойство GetMachineName возвращает имя машины, на которой выполняется код объекта. Имя машины докажет, что объект на самом деле исполняется в процессе сервера. Метод CalculateItem() является небольшим примером бизнеслогики, которая может находиться в классе Order. Очевидно, что для целей демонстрации мы создаем простую функцию. Если бы это был настоящий объект Order, то метод был бы гораздо сложнее; возможно, метод CalculateItem() возвращал бы документ XML, определяющий весь заказ на покупку.

    Хорошим правилом при создании объектов удаленного доступа является отсутствие у них состояний. Так как объекты удаленного доступа будут вызываться из многих клиентских приложений, мы не хотим хранить открытые экземпляры для каждого пользователя.

    Создание сервера

    Теперь, когда мы создали объект, нам требуется поместить этот объект на нашем сервере. Объект удаленного доступа требует наличия сервера, который предоставляет этот объект через порт клиентам. Каждый объект удаленного доступа должен быть опубликован на хосте сервера. Хостом может быть IIS, служба Windows или самостоятельно реализованный хост. Для простоты мы создадим наш собственный хост для публикации этого объекта удаленного доступа.

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Runtime.Remoting;
    
    namespace Server
    {
        class Program
        {
            static void Main(string[] args)
            {
                Console.WriteLine("Server started.");
                RemotingConfiguration.Configure("server.exe.config");
                Console.WriteLine("Server is running. Press <Enter> to exit.");
                Console.ReadLine();
            }
        }
    }

    Перед тем, как мы сможем запустить сервер, мы должны определить объекты удаленного доступа, которые следует опубликовать. Структура удаленного доступа позволяет нам читать конфигурацию из настроечного файла приложения. Мы могли бы "зашить" конфигурацию непосредственное приложение, но в этом случае изменение конфигурации потребовало бы перекомпиляции сервера. Настроечные файлы предлагают гораздо более гибкое решение, чем "зашивание" конфигурации в хост сервера.

    Как только настроенный файл создан, мы говорим среде выполнения удаленного доступа получить конфигурацию из этого файла при помощи строки:

    RemotingConfiguration.Configure("server.exe.config");

    Файл server.exe.config имеет следующий вид:

    <?xml version="1.0" encoding="utf8" ?>
    <configuration>
      <system.runtime.remoting>
        <application>
          <channels>
            <channel ref="http" port="8080"/>
          </channels>  
          <service>
            <wellknown mode="Singleton" type="Order.Order, Order" objectUri="Order.soap"/>
          </service>  
        </application>  
      </system.runtime.remoting>
    </configuration>

    Структура удаленного доступа читает узел < system.runtime.remoting > и настраивает среду выполнения удаленного доступа в соответствии с его содержимым. Этот настроечный файл должен быть размещен в той же директории, где и server.exe.

    В файле указывается, какой канал необходимо открыть для объекта. Так как используется канал HTTP, тэг канала задается следующим образом:

    <channel ref="http" port="8080"/>

    Мы также должны открыть объект, и для этого имеется два типа создания объекта wellknown и activated. Аналогично объектам СОМ, объекты типа activated могут иметь состояние и их время жизни определяется клиентом. Объекты типа wellknown создаются в процессе сервера и время их жизни определяется сервером.

    Имеется два режима объектов wellknown Singleton и SingleCall. В режиме Singleton создается один объект для обработки всех запросов. Объект сохраняется между запросами клиентов. Объекты SingleCall создаются для каждого запроса переданного клиентом. Каждый раз, когда приходит клиентский запрос, создается новый объект, обслуживается запрос клиента, а затем объект удаляется. Объект Singleton великолепно подходит, если вы хотите совместно использовать общие данные для всех запросов клиентов.

    Объекты SingleCall не оставляют следов, так как все созданные объекты уничтожаются при завершении обработки запроса.

    Вот иллюстрация использования объекта Singleton:

    <wellknown mode="Singleton" type="Order.Order, Order" objectUri="Order.soap"/>

    Свойство type говорит среде выполнения удаленного доступа, какой объект должен быть опубликован, и объявляется в формате <тип>, <сборка>. Здесь свойство type говорит, что мы хотим опубликовать объект Order из сборки Order.dll. Чтобы это всё правильно работало, сборка Order.dll должна располагаться там, где среда выполнения сможет ее найти. Мы устанавливаем Order.dll в той же физической директории, что и Server.exe. Заметьте, что расширение .dll сборки не указывается.

    Свойство objectUri является идентификатором, под которым наш объект будет опубликован. Так как по одному и тому же каналу и порту может вызываться много различных объектов, мы должны дать каждому объекту уникальный идентификатор, чтобы отличать их друг от друга. Мы даем ему расширение .soap, чтобы указать, что этот объект будет использовать форматер SOAP. Так как форматер SOAP является форматером по умолчанию для канала HTTP, мы не должны указывать форматер в этом настроечном файле.

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

    Создание клиента

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

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Runtime.Remoting;
    
    namespace Client
    {
        class Program
        {
            static void Main(string[] args)
            {
                Console.WriteLine("Клиент создан в {0} на {1}",
                    DateTime.Now.ToLongTimeString(),Environment.MachineName);
                RemotingConfiguration.Configure("client.exe.config");
                Order.Order o = new Order.Order();
                Console.WriteLine(o.GetMachineName());
                Console.WriteLine("Итоговая стоимость: {0}",
                    o.CalculateItem(12.48,2));
                Console.ReadLine();
            }
        }
    }

    Чтобы откомпилировать эти приложение, мы должны создать ссылки на объект среды выполнения удаленного доступа и Order.dll. Может показаться странным, что нам требуется ссылка на Order.dll, так как объект исполняется исключительно на сервере. Клиенту, чтобы он мог осуществлять вызов серверного объекта, требуются метаданные из объекта удаленного доступа. Без этих метаданных компилятор и среда выполнения не будут иметь ни малейшего представления, что представляет из себя объект удаленного доступа. Мы также можем получить метаданные с помощью инструмента soapsuds.exe. Для краткости мы будем хранить экземпляр Order.dll на стороне клиента. За дополнительной информацией по вопросам о метаданных обратитесь к документации по .NET SDK и, в частности, по инструменту командной строки soapsuds.exe.

    Точно так же, как и на сервере, клиент реализует настроечный файл для получения конфигурации своего объекта удаленного доступа. Файл называется client.exe.config и хранится в той же директории, что и клиентское приложение:

    <?xml version="1.0" encoding="utf8" ?>
    <configuration>
      <system.runtime.remoting>
        <application>
          <client>
            <wellknown type="Order, Order" url="http://mobil185:8080/Order.soap"/>
          </client>
        </application>
      </system.runtime.remoting>
    </configuration>

    Рекомендации по выполнению: при выполнении задания следуют использовать волновой алгоритм для структуры – неориентированное дерево. Волновой алгоритм приведен ниже.

    Волновой алгоритм для структуры – дерева

    Предположим, что соединение сайтов распределенной системы каналами образует граф – неориентированное дерево. Из теории графов известны следующие факты для деревьев:

  • дерево – связный ациклический граф;
  • количество вершин в дереве на единицу больше, чем количество ребер;
  • в нетривиальном дереве имеется, по крайней мере, две вершины, степени которых равны единице; эти вершины называются висячими или терминальными; остальные вершины имеют степень, не меньше 2.
  • В описываемом алгоритме инициаторами являются все висячие вершины. Любой инициатор может передать маркер только одному соседнему сайту. Любой другой сайт v (не инициатор), имеющий степень deg(v), генерирует маркер только в том случае, если получил маркеры от deg(v) – 1 соседа, т.е. от всех смежных сайтов, кроме одного. Тогда сайт v отправляет маркер тому единственному соседу, от которого маркера еще не было (вполне возможно, что этот сосед просто задержался с передачей).

    Если задержавшийся сосед все же передаст маркер, т.е. сайт v получит deg(v) маркеров, то сайт v выполнит процедуру return(OK). Выполнение процедуры return(OK) любым из сайтов завершает работу распределенного алгоритма.

    (рис l-1) Шаг 1. Маркеры, инициированные висячими вершинами дерева (рис l-2) Шаг 2. Продвижение маркеров по дереву (рис l-3) Шаг 3. Заключительное перемещение маркеров

    Описанный алгоритм не столь очевиден, как алгоритм для кольцевой архитектуры. Поэтому нам нужны гарантии его правильности, а именно, гарантии того, что если какойлибо из сайтов выполнил процедуру return(OK), все остальные сайты vi получили, по крайней мере, по deg(vi) – 1 маркеров и сгенерировали или готовы сгенерировать выходные маркеры.

    Рисунки l-2l-3 иллюстрируют на примере некоторого дерева продвижение маркеров. На шаге 2 вершины, уже получившие маркеры, обозначены соответствующими числами. После выполнения шага 3, вершина, обозначенная "a" и имеющая степень 3, получит последние два маркера. Количество полученных маркеров станет равным трем, и будет выполнена процедура return(OK).

    Отметим, что эти рисунки и приведенные выше комментарии к ним справедливы для случая, когда перемещение любого маркера по любому ребру дерева требует одного и того же времени, а генерация маркера происходит мгновенно. Инициаторы также одновременно генерируют свои маркеры.

    В противном случае процесс закончится в какой-либо другой (не висячей) вершине дерева. Если же какая-либо из висячих вершин – инициаторов сильно запоздает с генерацией своего маркера, то может возникнуть непредусмотренная ситуация получения маркера висячей вершиной.

    Сказанное еще раз подтверждает то, что выполнение распределенного алгоритма не является строго детерминированным во времени, но, тем не менее, при правильном построении алгоритма может быть детерминированным по результатам.

    Отчетность:

    В результате выполнения лабораторной работы должны быть представлены следующие материалы:

  • Программа;
  • Исходные тексты;
  • Презентация работы;
  • Презентация, в которой освещаются вопросы реализации консервативных алгоритмов.
  • Вернуться к учебному плану