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