Первая пара в этом примере, строго говоря, излишня, но проясняет смысл всей конструкции.

А как используются ACL? Метод install_acl приводит ACL в действие. Его необходимо вызывать перед обращением к start_service, иначе он не возымеет эффекта.

# Продолжение примера...

DRb.install_acl(acl)

DRb.start_service(nil, some_object)

# ...

Теперь, после запуска сервиса любой неавторизованный запрос на соединение приведет к исключению RuntimeError.

Это, конечно, не все, что можно сказать о библиотеке drb. Но для обзора вполне достаточно. В следующем разделе мы рассмотрим простой drb-сервер и drb-клиент, близкие к реальным программам. А затем поговорим о программах Rinda и Ring.

20.2. Пример: эмуляция биржевой ленты

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

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

Сначала рассмотрим модуль DrbObservable. Это прямолинейная реализация паттерна Observer (Наблюдатель), описанного в замечательной книге Э. Гаммы, Р. Хелма, Р. Джонсона и Дж. Влиссидеса «Паттерны проектирования» (см. сноску в разделе 12.3.1). Еще этот паттерн называют «Издатель-Подписчик».

В листинге 20.1 наблюдатель определен как объект, отвечающий на вызов метода update. Сервер добавляет наблюдателей по их просьбе и посылает им уведомления, обращаясь к методу notify_observers.

Листинг 20.1. Модуль DrbObservable

module DRbObservable

 def add_observer(observer)

  @observer_peers ||= []

  unless observer.respond_to? :update

   raise NameError, 'наблюдатель должен отвечать на вызов 'update''

  end

  @observer_peers.push observer

 end

 def delete_observer(observer)

  @observer_peers.delete observer if defined? @observer_peers

 end

 def notify_observers(*arg)

  return unless defined? @observer_peers

  for i in @observer_peers.dup

   begin

    i.update(*arg)

   rescue

    delete_observer(i)

   end

  end

 end

end

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

Листинг 20.2. Канал биржевых котировок (drb-сервер)

require 'drb'

require 'drb_pbserver'

# Генерировать случайные котировки.

class MockPrice

 MIN = 75

 RANGE = 50

 def initialize(symbol)

  @price = RANGE / 2

 end

 def price

  @price += (rand() - 0.5)*RANGE

  if @price < 0

   @price = -@price

  elsif @price >= RANGE

   @price = 2*RANGE - @price

  end

  MIN + @price

 end

end

class Ticker # Периодически получать котировку акций.

 include DRbObservable

 def initialize(price_feed)

  @feed = price_feed

  Thread.new { run }

 end

 def run

  lastPrice = nil

  loop do

   price = @feed.price

   print 'Текущая котировка: #{price} '

Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

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

Отметить Добавить цитату