Назад | Перейти на главную страницу

TCP-соединение видно только в Linux

Я имею дело с проблемой связи между двумя машинами. Машина A - это коробка с Windows Server 2012, а машина B - это коробка Centos 8. Машина A - это виртуальная машина, работающая под управлением VMWare, а B - это физическая машина x86_64. Я не верю, что между двумя машинами есть брандмауэр.

У нас есть приложения на A и B, которые общаются друг с другом через TCP. Машина B открывает прослушивающий TCP-порт и принимает входящие соединения, а машина A подключается к этому TCP-порту. Обычно это нормально работает.

Однако есть сценарий, который вызывает состояние отказа. Если мы убиваем приложение на A и перезапускаем его, оно устанавливает новое соединение с B. Однако связь между A и B перестает работать на этом порте на некоторое время.

Я обнаружил, что на A после выполнения kill / restart netstat показывает только недавно подключенное TCP-соединение как ESTABLISHED (и вообще не показывает старое соединение), а на B, a netstat показывает как старое соединение, так и новое соединение как ESTABLISHED. Покопавшись в приложении, работающем на B, я определил, что, поскольку оно все еще видит старое соединение как активное (поскольку ОС сообщает о нем как ESTABLISHED), оно продолжает отправлять ответы на старое соединение при получении запросов на новое соединение.

Через некоторое время (~ 2 часа?) Машина B, кажется, обнаруживает, что старое TCP-соединение прервано, и начинает отправлять ответы на правильное TCP-соединение, поэтому связь снова начинает работать.

Меня смущает то, почему netstat вывод асимметричный. Если B видит соединение как ESTABLISHED, но A вообще не видит соединения, тогда я пришел к выводу, что либо A, либо B не соответствуют стандарту TCP. Мне кажется, что Windows на машине A не закрывает TCP-соединение чисто, когда приложение прекращает работу, в результате чего соединение разрывается, а не закрывается изящно.

Если мой вывод верен и одна машина не выполняет TCP правильно, то я вижу несколько потенциальных решений, но ни одно из них не соответствует моим потребностям:

  1. Закройте старое соединение на B при обнаружении нового соединения: это мое текущее решение
  2. Используйте тайм-аут на уровне приложения (или TCP keepalive?), Чтобы определить, когда соединение прерывается: это было бы моим предпочтительным решением
  3. Полностью закрыть соединения на A, когда приложение убито: это было бы неплохо, но я не контролирую приложение на A, поэтому было бы сложно внести это изменение

В качестве альтернативы, есть ли способ настроить параметр в Windows, чтобы разорванные соединения были закрыты чисто, или конфигурацию в CentOS, чтобы Linux быстрее обнаруживал разорванные соединения?