Как я могу выполнять синхронные вызовы rpc

StackOverflow https://stackoverflow.com/questions/281922

  •  07-07-2019
  •  | 
  •  

Вопрос

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

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

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

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

Добавление и разъяснение:

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

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

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

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

Это было полезно?

Решение

Если вы даже подумываете о Поджигателе, проверьте RPyC во-первых, еще раз рассмотрим XML-RPC.

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

Если вы self.transport.loseConnection() в вашем Протоколе вы не будете оставлять открытые соединения.

Другие советы

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

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

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

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

Для синхронного клиента 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() возможно, вызов придется повторять до тех пор, пока вы не получите пустую строку, но это показывает основы.

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

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

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

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

Добавление и разъяснение:

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top