Как я могу сделать синхронные вызовы RPC - PullRequest
4 голосов
/ 11 ноября 2008

Я создаю программу, класс которой используется локально, но я хочу, чтобы этот же класс использовался одинаково в сети. Это означает, что мне нужно иметь возможность делать синхронные вызовы с любым из его открытых методов. Класс читает и записывает файлы, поэтому я думаю, что XML-RPC - это слишком много. Я создал базовый клиент / сервер RPC, используя примеры из витой, но у меня проблемы с клиентом.

c = ClientCreator(reactor, Greeter)
c.connectTCP(self.host, self.port).addCallback(request)
reactor.run()

Это работает для одного вызова, когда данные получены, я вызываю реактор.stop (), но если я сделаю еще какие-нибудь вызовы, реактор не будет перезапущен. Есть ли что-то еще, что я должен использовать для этого? может быть, другой витой модуль или другой фреймворк?

(Я не включаю детали того, как работает протокол, потому что главное - я получаю только один звонок из этого.)

Приложение и разъяснение:

Я поделился документом Google с заметками о том, что я делаю. http://docs.google.com/Doc?id=ddv9rsfd_37ftshgpgz

У меня написана версия, которая использует fuse и может объединять несколько локальных папок в точку монтирования fuse. Доступ к файлу уже обрабатывается в классе, поэтому я хочу, чтобы серверы предоставляли мне сетевой доступ к тому же классу. После продолжения поиска, я подозреваю, что pyro (http://pyro.sourceforge.net/) может быть тем, что я действительно ищу (просто основываясь на чтении их домашней страницы прямо сейчас), но я открыт для любых предложений.

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

Вывод: Я решил использовать rpyc, поскольку он дал мне именно то, что я искал. Сервер, который хранит экземпляр класса, которым я могу манипулировать, как если бы он был локальным. Если кому-то интересно, я выкладываю свой проект на Launchpad (http://launchpad.net/dstorage).

Ответы [ 4 ]

2 голосов
/ 25 ноября 2008

Почему вы чувствуете, что оно должно быть синхронным?

Если вы хотите, чтобы за один раз происходил только один из них, вызовите все вызовы через DeferredSemaphore, чтобы вы могли ограничить число фактических вызовов (любым произвольным значением).

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

Если вы просто не можете понять, как выразить логику вашего приложения в схеме реактора, вы можете использовать deferToThread и написать кусок чисто синхронного кода - хотя я думаю, что в этом нет необходимости.

2 голосов
/ 14 ноября 2008

Если вы даже рассматриваете Pyro, сначала проверьте RPyC и заново рассмотрите XML-RPC.

Относительно скрученного: попробуйте оставить реактор вверх, а не останавливать его, и просто ClientCreator(...).connectTCP(...) каждый раз.

Если вы self.transport.loseConnection() в своем протоколе, вы не оставите открытых соединений.

1 голос
/ 12 ноября 2008

Если вы используете Twisted, вы должны знать, что:

  1. Вы не будете делать синхронные звонки на какие-либо сетевые услуги
  2. Реактор может быть запущен только один раз, поэтому не останавливайте его (вызывая reactor.stop()), пока ваше приложение не будет готово к выходу.

Надеюсь, это ответит на ваш вопрос. Я лично считаю, что Twisted является точно правильным решением для вашего варианта использования, но вам нужно обойти проблему синхронности.

Приложение и разъяснение:

Часть того, что я не понимаю, это что когда я вызываю реактор.run () это кажется, зацикливается на том, что просто следит за сетевой активностью. Как я продолжать работать до конца моего программа пока что использует сеть? если Я могу пройти через это, тогда я могу вероятно, работать через проблема синхронности.

Именно это и делает реактор.run (). Он запускает основной цикл, который является реактором событий. Он будет ждать не только событий Entwork, но и всего, что вы запланировали. С Twisted вам нужно будет структурировать остальную часть вашего приложения таким образом, чтобы справиться с его асинхронной природой. Возможно, если бы мы знали, что это за приложение, мы могли бы посоветовать.

1 голос
/ 11 ноября 2008

Для синхронного клиента Twisted, вероятно, не правильный вариант. Вместо этого вы можете использовать модуль сокета напрямую.

import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((self.host, self.port))
s.send(output)
data = s.recv(size)
s.close()

Вызов recv() может повторяться до тех пор, пока не получите пустую строку, но это показывает основы.

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

...