Альтернативы RMI для двунаправленных асинхронных вызовов и обратных вызовов через брандмауэры или NAT

Я пишу игру на основе серверно-клиентской архитектуры на Java.

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

На данный момент мой серверный и клиентский код довольно симметричны. Они создают реестр, затем экспортируют и связывают себя.

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

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

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


Я думал о возможных решениях, но не нашел подходящего:

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

  • Соединения TCP сами по себе допускают двустороннюю связь и могут определенно идентифицировать клиентов, поэтому RMI или JRemoting может быть взломаны для их поддержки, но я не знаю, как это сделать, и я не знаю ни о каких существующее решение.

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

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


Итак, в двух словах, я ищу способ:

  • вызвать сервер асинхронно или передать ему сообщение
  • вызвать клиента асинхронно или передать ему сообщение, даже за брандмауэром или NAT
  • идентифицировать клиента, отправляющего действие
  • желательно иметь возможность вызывать методы, а не просто передавать сообщения
  • сохраните возможность легко протестировать его с помощью JUnit и Mockito (несколько клиентов на машину)

Существуют ли какие-либо фреймворки для удаленного вызова методов с их поддержкой? Который лучший?


person Frigo    schedule 24.02.2013    source источник
comment
docs.oracle.com/javase/ 1.5.0/docs/guide/rmi/spec/rmi-arch6.html RMI через брандмауэры через прокси   -  person Srinath Ganesh    schedule 27.09.2013


Ответы (1)


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

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

Для моего проекта я вырезал всю свою работу и заменил ее CometD, которая поддерживает как Java, так и браузер (Javascript ) клиентов, и не мог быть счастливее. Это, безусловно, удовлетворит все ваши потребности - асинхронная связь, инициируемая с любой стороны, идентификация клиентов (и многие другие функции) и клиенты за NAT не будут проблемой после установления соединения. Также легко писать тесты, и вся структура была увеличена, чтобы иметь возможность обрабатывать 100 000 клиентов, что было бы невозможно для RMI.

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

Обновление: с тех пор я перешел в мир веб-приложений, в частности, используя Meteor.

person Andrew Mao    schedule 24.02.2013
comment
После некоторых исследований и возни я остановился на Apache Mina. Я сделал над ним тонкую оболочку, которая помимо обработки соединения помещает входящие сообщения в LinkedBlockingQueue, чтобы я мог обрабатывать их в игровом цикле. - person Frigo; 08.03.2013