Двунаправленные опции RPC для мультиязычного клиента / сервера - PullRequest
3 голосов
/ 15 октября 2011

Я пытаюсь изложить идею для проекта, в котором графический интерфейс на стороне клиента может быть разработан на python, а графический интерфейс может управляться бэкэндом на потенциально любом другом языке, кроме RPC. Более конкретно, сейчас я работаю с PyQt на стороне клиента, а Go - в качестве начального бэкэнда.

Вот мои цели:

  • PyQt клиент
    • Роли : просмотр, контроллер
    • Односторонние вызовы (SIGNAL / SLOT), такие как: button.clicked -> RPC.handleSignal
    • Запрос / ответ RPC , например: rowCount = model.rowCount -> RPC.call.model.rowCount
  • Агностический бэкэнд (в этом случае перейдите)
    • Роли : контроллер, модель
    • Односторонние вызовы (Emit SIGNAL), такие как: model.dataChanged -> RPC.emitSignal

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

Я сейчас смотрю на Thrift, скажем, на облегченный базовый RPC без IDL. Но в основном мой вопрос заключается в том, будет ли грязным подход пытаться использовать Thrift в виде двух файлов .thrift с клиент / сервер <----> клиент / сервер (два соединения), чтобы получить двунаправленную функциональность ? Преимущество, которое я вижу в Thrift, заключается в IDL, так что я могу специально создавать свой интерфейс, а внутренний код может просто реализовывать нужные части.

У кого-нибудь есть рекомендации по решению этой проблемы? Два интерфейса Thrift? Один интерфейс Thrift, который предоставляет сервис, позволяющий клиенту установить второй простой сокет для приема односторонних вызовов от сервера? Или Thrift здесь даже немного перебор? В то время как интерфейс backend -> GUI на самом деле представляет собой только одну сервисную функцию, GUI -> backend может немного расшириться (modelHandlers, slotHandlers, общие запросы состояния сервера).

(Изменить) Другие мысли

Часть меня думает, что шаблон мог бы быть сделан с любой платформой RPC, и это было бы так?

  1. Запускается процесс внутреннего сервера; прослушивает порт
  2. Клиентский графический интерфейс запускается; подключается к серверу RPC; прослушивает новый порт; отправляет порт на сервер через вызов RPC
  3. Сервер получает порт от клиента и связывается с ним для второго соединения RPC
  4. Клиент и сервер имеют 2 соединения для двунаправленного RPC

1 Ответ

2 голосов
/ 15 октября 2011

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

В зависимости от вашей системы RPC она может или не может использоватьTCP и он могут иметь или не иметь двунаправленную связь (точнее, инициализацию двунаправленной связи).

Теперь, для thrift , кажется, что неттам еще много документации (нет ссылки на API).Но, проверяя пример кода, кажется, что он абстрагируется от обработки соединения и использует только связь запрос / ответ.Таким образом, в этом случае да, вам придется прослушивать клиентский порт с определенным портом и сообщать серверу, чтобы сервер мог инициировать передачу запроса / ответа .

Go сам предоставляет пакет rpc , который предназначен исключительно для передачи данных, поэтому не поможет.

Однако он также предоставляет websocket пакет .Хотя изначально он был нацелен на связь между веб-сервером и веб-браузером, он представляет собой двунаправленный протокол (в конце концов, это то, о чем идет речь) и может использоваться любым типом приложений.Возможно, он не настолько эффективен в отношении размера / полосы пропускания, но он выполняет свою работу.

Я не уверен в состоянии реализации в пакете go.Тип Conn имеет поле источника, но пример функции Conn.Dial передает http://localhost;Я не уверен, заменяется ли это удаленно доступным источником веб-сокета.Функция Handler.ServeHTTP предоставляет http.ResponseWriter, который вы также можете использовать для инициации соединения. По крайней мере, это первое, что я бы протестировал.

Альтернатива, если вам удобно использовать определенный формат данных и самостоятельно управлять сетью , это Protobuf .Существует проект сообщества для привязки go к protobuf .Затем вы можете обработать TCP-соединение самостоятельно (подключиться к нему и отправить ваши данные, получить данные, сохранить информацию о соединении и т. Д.).

Что касается других альтернатив , вы можете проверить страница пакетов сообщества и / или страница проектов сообщества (особенно Go Ajax и go-xmlrpc - хотя и то, и другое на данный момент очень элементарно).

...