pgBouncer прекрасно работает, но иногда становится недоступным

9

Я запускаю pgBouncer перед занятой базой данных Postgres 9. Большую часть времени работает нормально. Но каждые несколько часов я получаю сообщение об ошибке из моего приложения, за исключением psycopg2:

OperationalError ('не удалось подключиться к серверу: невозможно назначить запрошенный адрес. Сервер работает на хосте "neo-hulk" и принимает соединения TCP / IP через порт 6432?')

Это приложение на Python с кучей рабочих из сельдерея, выполняющих задания. Когда появляются эти ошибки, я проверяю pgbouncer db и размер пула находится в допустимых пределах. После некоторых экспериментов я установил максимальный размер пула равным 400, а размер пула равным 200. Режим пула - это «сессия» (запросы в основном автоматические, почти нет транзакций).

Что делает pgBouncer «исчезающим» таким образом? это только в течение коротких периодов времени (и в целом мы говорим о крошечном количестве запросов по сравнению с огромным количеством запросов, которые он обрабатывает), но те запросы, которые терпят неудачу, важны.

Спасибо!

Harel
источник
Операционная система и версия? Версия ядра Linux? Точные версии PostgreSQL и PgBouncer? Вы запускали PgBouncer на уровне журнала отладки и видели, сообщает ли он что-нибудь полезное?
Крейг Рингер
Debian 6. Linux версия 2.6.32-5-amd64 (Debian 2.6.32-48squeeze1) pgbouncer версия 1.5.4 Postgres 9.1. Журнал не регистрирует подключение / отключение, так как я думал, что это было немного, но при появлении этих ошибок приложения ошибок нет. Ошибка возникает из-за того, что psycopg2 думает, что нет сервера БД, с которым можно было бы общаться, хотя этой проблемы не существовало до pgbouncer
Harel
1
Хм, так что нынешний PgBouncer, а ядро ​​древнее, но довольно стабильное. Я думаю, вам нужно включить более детальную регистрацию в PgBouncer -vvvи посмотреть, сможете ли вы сопоставить аномальный вывод журнала с вашими ошибками во времени.
Крейг Рингер
Я сделал "set verbose = 1; reload;" в оболочке pgbouncer и не смог найти ничего необычного в журнале. это производственная система, поэтому не удалось остановить службу, работающую как демон, с параметром -vvv. Надеюсь, у меня такой же результат. обратите внимание, что ошибка говорит о том, что он вообще не может подключиться к pgbouncer, т. е. не может найти его прослушивающим в этом порту. Тысячи соединений сделаны постоянно, и странно, что небольшое количество таких соединений терпит неудачу.
Харель
Tricky; это звучит как потенциальное состояние гонки, но в каком / где ...
Крейг Рингер

Ответы:

15

Часть « Невозможно назначить запрошенный адрес » в сообщении об ошибке происходит из стека TCP ядра. При периодическом обнаружении это обычно означает, что пространство доступных сокетов исчерпано из-за слишком большого количества сокетов в состоянии ожидания ( TIME_WAITили менее вероятно FIN_WAIT_1или FIN_WAIT_2)

Диапазон портов сокетов может быть выведен с помощью cat /proc/sys/net/ipv4/ip_local_port_range. Значение по умолчанию для стандартного ядра Linux обычно 32768 61000.

Вы можете проверить результат netstat -ton|grep WAITна клиенте (ах) и на хосте pgBouncer, когда система занята. -oФлаг будет показывать счетчики времени ожидания , связанные с состояниями ожидания.

Если общее количество TCP-сокетов близко к 61000-32768=28232этому, вероятно, проблема в исчерпании этого диапазона. Поскольку закрытый сокет проводит в TIME_WAITсостоянии 60 секунд в нормальном состоянии, если клиентский хост подключается более 28232 раз в течение одной минуты, новые соединения не будут работать с указанной ошибкой, пока порты не будут освобождены.

В качестве первого обходного пути диапазон портов TCP может быть расширен:

 # echo "1025 65535" >/proc/sys/net/ipv4/ip_local_port_range

Если это не устраивает, проверьте tcp_tw_recycleи tcp_tw_reuseфлаги, а также перестройка через /proc/sys/net/ipv4и sysctl.

Они определены как (от man tcp):

       tcp_tw_recycle (Boolean; по умолчанию: отключено; начиная с Linux 2.4)
              Включите быструю утилизацию сокетов TIME_WAIT. Включение этого
              опция не рекомендуется, так как это вызывает проблемы при работе
              с NAT (трансляция сетевых адресов).

       tcp_tw_reuse (Boolean; по умолчанию: отключено; начиная с Linux 2.4.19 / 2.6)
              Разрешить повторное использование сокетов TIME_WAIT для новых соединений, когда это
              безопасно с точки зрения протокола. Это не должно быть изменено без
              совет / запрос технических экспертов.

Лично я имел успех, tcp_tw_recycleкогда столкнулся с этой проблемой с клиентским приложением MySQL, но не воспринимайте это как рекомендацию, мое понимание TCP в лучшем случае поверхностно.

Даниэль Верите
источник
1
Этот ответ показывает что-либо баг поверхностное понимание TCP. Спасибо за это. Я увеличил диапазон портов и позволил ему какое-то время работать, чтобы посмотреть, будет ли он иметь какой-либо эффект. (Нужно ли перезагрузить компьютер после установки?)
Harel
Я думаю, что увеличение порта сделало это. Пока что я не получил ни одной ошибки. Приблизительное количество строк netstat в клиенте показывает близкое к 20K, поэтому оттуда ограничение по умолчанию до 28K не будет длинным. Спасибо за это!
Харель
1
Хорошо! Вы хотите установить настройку /etc/sysctl.confтак, net.ipv4.ip_local_port_range = 1025 65535чтобы она сохранялась при перезагрузке.
Даниэль Верите
Спасибо. С тех пор я получил ошибки, но не ту, что все еще хорошо. Позвольте ему работать в течение нескольких дней и внесут изменения в Пермь. Я рад, что до сих пор это работает, потому что другие изменения пугают меня :)
Harel