Forbidden
@Forbidden
CEO, CTO @ a-parser.com

Linux, закольцовывание сокета после падения процесса, почему?

Всем привет, столкнулся со следующей проблемой:
- debian 8
- REST сервис на nodejs(слушает порт, 50100)
- PHP(curl) клиент, довольно часто подключается, делает запрос, отключается

Все отлично работает до тех пор пока не выключить сервис(или он сам не упадет по какой либо причине), далее происходит следующее:
$ netstat -apne|grep 50100
tcp 0 0 127.0.0.1:50100 127.0.0.1:50100 ESTABLISHED 10000 2375204860 8054/php

php процесс который был подключен(или пытался подключится?) в момент отключения сервиса становится подключенным сам к себе, при этом он уходит в вечный poll:
rt_sigaction(SIGPIPE, NULL, {SIG_IGN, [PIPE], SA_RESTORER|SA_RESTART, 0x7fc404f7d8d0}, 8) = 0
rt_sigaction(SIGPIPE, {SIG_IGN, [PIPE], SA_RESTORER|SA_RESTART, 0x7fc404f7d8d0}, NULL, 8) = 0
poll([{fd=9, events=POLLIN|POLLPRI|POLLRDNORM|POLLRDBAND}], 1, 0) = 0 (Timeout)
rt_sigaction(SIGPIPE, {SIG_IGN, [PIPE], SA_RESTORER|SA_RESTART, 0x7fc404f7d8d0}, NULL, 8) = 0
poll([{fd=9, events=POLLIN}], 1, 1000) = 0 (Timeout)
rt_sigaction(SIGPIPE, NULL, {SIG_IGN, [PIPE], SA_RESTORER|SA_RESTART, 0x7fc404f7d8d0}, 8) = 0
rt_sigaction(SIGPIPE, {SIG_IGN, [PIPE], SA_RESTORER|SA_RESTART, 0x7fc404f7d8d0}, NULL, 8) = 0
poll([{fd=9, events=POLLIN|POLLPRI|POLLRDNORM|POLLRDBAND}], 1, 0) = 0 (Timeout)
rt_sigaction(SIGPIPE, {SIG_IGN, [PIPE], SA_RESTORER|SA_RESTART, 0x7fc404f7d8d0}, NULL, 8) = 0
poll([{fd=9, events=POLLIN}], 1, 1000) = 0 (Timeout)

Основная проблема - поднять обратно сервис, порт занят - пока не прибить php процесс порт не освободится
Более того, периодически разные php процессы могут занять этот порт на всех интерфейсах, включая ipv6

Почему так происходит и как с этим бороться?
  • Вопрос задан
  • 905 просмотров
Решения вопроса 1
@neol
Порты для исходящих подключений по умолчанию выбираются из диапазона 32768-60999 (задаётся sysctl net.ipv4.ip_local_port_range).
Используемый вами порт 50100 попадает в этот диапазон и когда PHP пытается подключиться к упавшему сервису, он рано или поздно натыкается на этот порт и подключается сам к себе.

Решить проблему можно задав диапазон портов в curl:


curl_setopt($ch, CURLOPT_LOCALPORT, 12345); // Начальный порт
curl_setopt($ch, CURLOPT_LOCALPORTRANGE, 10); // Количество портов в диапазоне

В данном примере будут использованы порты с 12345 до 12355.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы