Website development
26 April 2011

Разработка распределенного приложения, часть компонентов которого находится за firewall

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

Firewall обычно появляется между приложениями вне корпоративной сети и внутри неё, а так же на границах DMZ, которые обычно имеют место в инфраструктуре, в которой система рассчитана на внешних пользователей, а сервер находиться в intranet. Причем сообщение от клиента может проходить через несколько DMZ, проникая не через один firewall.

Firewall добавляет следующие особенности, о которых необходимо помнить:
  1. Соединение не пересылающее никаких данных закрывается через определенный промежуток времени.
  2. Соединение не пересылающее никаких данных может превратиться в черную дыру (black hole), которая проявляется таким образом, что вы посылаете сообщения, они успешно уходят, но не доходят до получателя.
  3. Все порты, по которым будет идти общение, должны быть известны заранее и прописаны в firewall, таким образом технологии, открывающие произвольные порты, не работают в таком окружении.

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

Для того чтобы ваше соединение не было закрыто firewall при простаивании, надо не давать ему простаивать. Обычно этого добиваются, вводя специальные служебные типы сообщений, вроде ping или heartbeat, которые пересылаются по сети в обе стороны с заданным промежутком времени. Промежуток времени, очевидно, выбирается таким, чтобы в интервал, через который firewall закрывает простаивающее соединение, посылалось несколько служебных сообщений. Если в качестве примера рассмотреть пул соединений к базе данных, то в качестве такого служебного сообщения может выступать validation query. Подробнее об этом я уже писал тут.

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

Для борьбы с черными дырами, чтобы быть уверенными, что ваше сообщение дошло до адресата, можно пользоваться стратегией request-response, т.е. на каждое отосланное сообщение ожидать короткого ответа и только потом отпускать управление. Либо опять просто не давать соединению простаивать, как написано выше. Подробнее о том, как гарантировать доставку сообщений через firewall и не только, я подробно описывал здесь.

Самая распространенная технология, использующая произвольные порты в java, наверное, RMI. Можно возразить, что это довольно древняя технология, не получившая большого распространения. Вот только JMX, которая сейчас используется практически везде, в качестве самого распространенного протокола общения использует именно RMI. И если вы предпочитаете использовать JConsole, то скорее всего вам понадобиться этот самый протокол. Однако не все так плохо, так как RMI позволяет зафиксировать порт. Как это сделать я подробно описал тут. Правда если вы захотите не просто дергать методы, а еще получать асинхронно нотификации (callback) с сервера на клиенте, то здесь уже у вас ничего не выйдет, по крайней мере я так сразу не нашел, как зафиксировать порт для этого. Впрочем, в JMX я данной функциональностью никогда не пользуюсь, а если потребуется, можно всегда реализовать её через polling.

Еще хочу заметить, что если у вас в production есть firewall, то очень важно иметь firewall с такими же настройками и в UAT окружении. Если это по какой-то причине невозможно, то необходимо его хотя бы эмулировать, устанавливая все соединения между компонентами не на прямую, а через специальный proxy, которая обрывает ваше соединение или превращает его в черную дыру через определенный интервал, в течении которого по соединению не пересылалось никаких данных.

+14
2.3k 22
Comments 5