Pgbouncer cannot connect to server что делать
Перейти к содержимому

Pgbouncer cannot connect to server что делать

  • автор:

Postgresql – PgBouncer cannot connect to server

I figured it out. I was (partially?) guilty of trying to use too many new features in pgbouncer 1.7.

There are the TLS/SSL settings & then there is the HBA access controls. (TLS/SSL doesn't need HBA access controls & vice-versa to work). Also, since pgbouncer & the database are on the same box, there is no need for the extra overhead of TLS/SSL between pgbouncer & the database.

Simplifying to just use more commonly used user authentication settings proved to be the fix.

First, postgresql.conf & pg_hba.conf were left untouched as show above.

pgbouncer.ini , however, is this:

So the specific changes are auth_type = cert & auth_file = pgbouncer/users.txt (changing/removing the HBA references) & stripping out the 4 server_tls_. lines at the end.

The users authenticate to both pgbouncer and the postgres database using the SSL cert.

This also means that I have to put together a list of users that will be going through pgbouncer in ./pgbouncer/users.txt . The format should be just like this (for each user):

since pgbouncer will not be verifying any connections based on a password.

Как вынудить процесс использовать новый адрес DNS-сервера из обновлённого resolv.conf без перезапуска самого процесса

Я работаю системным администратором Unix. Однажды к нам в отдел эксплуатации сервисов упал тикет от программиста с выдержой из лога application-сервера в заголовке: «pgbouncer cannot connect to server«. Посмотрев логи pgbouncer’ов, я увидел, что периодически возникают lookup fail’ы при обращении к нашим DNS. Было установленно, что это связано не с работой наших DNS-серверов, а с ненадёжностью самого протокола UDP: иногда возникают потери пакетов по разным причинам.
image
В результате, было решено установить на каждом сервере с pgbouncer’ами по кэширующему BIND. И тут возникла интересная проблема: pgbouncer не перечитывал по сигналу HUP файл /etc/resolv.conf и продолжал обращаться к старым DNS-серверам. А перезагружать баунсеры категорически нельзя: есть проблемные проекты, которые очень болезненно относятся к разрывом сессий с базой.

В данной статье я расскажу как можно pgbouncer или любую другую программу, использующую библиотечный вызов getaddrinfo(), заставить перечитать resolv.conf и начать использовать новый DNS-сервер совершенно безболезненно для клиентов (без даунтайма).

Приступим

Сразу оговорюсь, что в моём случае pgbouncer’ы были версий 1.5.2 и собраны с libevent-1.4 под FreeBSD.

Если посмотреть в исходник pgbouncer’а, то можно увидеть в файле dnslookup.c следующий комментарий:

Это означает, что в случае когда pgbouncer собран с libevent1, для асинхронного резолва адресов используется функция getaddrinfo_a() из стандартной библиотеки libc.
Опытным путём было установлено, что асинхронная getaddrinfo_a() использует обычную функцию getaddrinfo() из libc. На последнюю функцию мы и будем ставить точку останова. Этот факт избавит нас от необходимости собирать pgbouncer с отладочными символами, так как gdb знает функцию getaddrinfo, не смотря на то, что libc собрана без отладочных символов.

Добавим в конфиг pgbouncer’а несуществующую базу, ссылающуюся на несуществующий домен (пригодится для тестов):

В отдельном окне запустим pgbouncer:

В другом окне подключимся к процессу с помощью отладчика gdb:

Поставим точку останова и позволим процессу выполняться дальше:

В другом окне попробуем подключиться к нашей базе с несуществующим доменом, чтобы инициировать попытку резолва:

В gdb мы видим, что мы попали в яблочко:

Как же работает getaddrinfo()?

С помощью мануалов и поисковика было выяснено, что эта функция при первом вызове читает файл resolv.conf, инициализирует в памяти структуру с кучей данных, среди которых можно найти и список DNS-серверов. Далее, функция пытается сделать резолв адреса при помощи первого адреса из списка. Если DNS-сервер не отвечает, функция делает активным следующий DNS-сервер из списка. И так по кругу. Функция читает resolv.conf только единожды.

Сначала я хотел пропатчить виртуальную память pgbouncer’а, найдя 4 байта адреса DNS-сервера в network order или host order формате. Для этого даже была написана программа «дампер памяти» на Си, которая позволяла дампить память процесса и искать определённый порядок байт. Но, как оказалось, в таком виде эти адреса в памяти найти невозможно. Понять же исходник getaddinfo() оказалось выше моих сил: очень много текста и всяческие goto чуть не сломали моё сознание. К тому же, я не являюсь программистом, а Си начал изучать всего месяц назад.

Кстати, моя программа, использующая ptrace и procfs подошла бы для pgbouncer’а собранного с libevent2: там ip-адреса DNS-серверов хранятся как раз в виде четырёх байт. Но описание данного опыта выходит за рамки статьи.

Что же делать?

Именно эта функция вызывается при первом вызове getaddrinfo() и инициализирует нужную нам структуру!
Повторный же вызов функции переинициализирует структуру и перечитает resolv.conf.

Проверим на практике

Подключимся трассировщиком к нашему «замороженному» pgbouncer’у и начнём grep’ать файл дампа трассировки:

В окне с gdb осуществим вызов функции res_init():

В окне с выводом результата трассировки мы видим:

Цель достигнута

Нам удалось заставить процесс перечитать resolv.conf, при этом не уронив сервер и не разорвав активные state’ы tcp. В момент заморозки запросы также не теряются.

Если мы захотим чтобы локальный кэширующий DNS начал использоваться немедленно, нам нужно проделать следующие шаги:

  1. Поменять в forwarders BIND’а серверы на новые (другие) рабочие DNS’серверы, которые до этого не использовались в resolv.conf и не будут использоваться, а затем сделать rndc reload
  2. Забанить локальным фаерволом обращения к старым DNS-серверам (кроме 127.0.0.1)
  3. Инициировать обращение pgbouncer’a к несуществующему серверу БД:

И последнее

Если вы захотите повторить мой опыт, настоятельно рекомендую тренироваться на тестовом стенде.
Если вы захотите «пулять» команду в gdb в batch mode, имейте в виду, что gdb нужно сначала дать время на чтение символов, а потом уже следует вызывать функции: я как-то из-за этого здорово напортачил, убив один из 8-ми работающих pgbouncer’ов.
batch mode для gdb у меня выполняется теперь так:

Надеюсь, мой опыт кому-то поможет чуть лучше понять как работают процессы в операционных системах.

Common Error Messages¶

This is caused by attempting to join local and distributed tables in the same query.

Resolution¶

For an example, with workarounds, see JOIN a local and a distributed table .

Could not receive query results¶

Caused when the the coordinator node is unable to connect to a worker.

Resolution¶

To fix, check that the worker is accepting connections, and that DNS is correctly resolving.

Canceling the transaction since it was involved in a distributed deadlock¶

Deadlocks can happen not only in a single-node database, but in a distributed database, caused by queries executing across multiple nodes. Citus has the intelligence to recognize distributed deadlocks and defuse them by aborting one of the queries involved.

We can see this in action by distributing rows across worker nodes, and then running two concurrent transactions with conflicting updates:

Resolution¶

Detecting deadlocks and stopping them is part of normal distributed transaction handling. It allows an application to retry queries or take another course of action.

Could not connect to server: Cannot assign requested address¶

This occurs when there are no more sockets available by which the coordinator can respond to worker requests.

Resolution¶

Configure the operating system to re-use TCP sockets. Execute this on the shell in the coordinator node:

This allows reusing sockets in TIME_WAIT state for new connections when it is safe from a protocol viewpoint. Default value is 0 (disabled).

SSL error: certificate verify failed¶

As of Citus 8.1, nodes are required talk to one another using SSL by default. If SSL is not enabled on a Postgres server when Citus is first installed, the install process will enable it, which includes creating and self-signing an SSL certificate.

However, if a root certificate authority file exists (typically in

/.postgresql/root.crt ), then the certificate will be checked unsuccessfully against that CA at connection time. The Postgres documentation about SSL support warns:

Resolution¶

Possible solutions are to sign the certificate, turn off SSL, or remove the root certificate.

Could not connect to any active placements¶

When all available worker connection slots are in use, further connections will fail.

Resolution¶

This error happens most often when copying data into Citus in parallel. The COPY command opens up one connection per shard. If you run M concurrent copies into a destination with N shards, that will result in M*N connections. To solve the error, reduce the shard count of target distributed tables, or run fewer \copy commands in parallel.

Remaining connection slots are reserved for non-replication superuser connections¶

This occurs when PostgreSQL runs out of available connections to serve concurrent client requests.

Resolution¶

The max_connections GUC adjusts the limit, with a typical default of 100 connections. Note that each connection consumes resources, so adjust sensibly. When increasing max_connections it’s usually a good idea to increase memory limits too.

Using PgBouncer can also help by queueing connection requests which exceed the connection limit. Citus Cloud has a built-in PgBouncer instance, see Scaling Connections (pgBouncer) to learn how to connect through it.

PgBouncer cannot connect to server¶

In a self-hosted Citus cluster, this error indicates that the coordinator node is not responding to PgBouncer.

Resolution¶

Try connecting directly to the server with psql to ensure it is running and accepting connections.

Unsupported clause type¶

This error no longer occurs in the current version of citus. It used to happen when executing a join with an inequality condition:

Resolution¶

Upgrade to Citus 7.2 or higher.

Cannot open new connections after the first modification command within a transaction¶

This error no longer occurs in the current version of citus except in certain unusual shard repair scenarios. It used to happen when updating rows in a transaction, and then running another command which would open new coordinator-to-worker connections.

Resolution¶

Upgrade to Citus 7.2 or higher.

Cannot create uniqueness constraint¶

As a distributed system, Citus can guarantee uniqueness only if a unique index or primary key constraint includes a table’s distribution column. That is because the shards are split so that each shard contains non-overlapping partition column values. The index on each worker node can locally enforce its part of the constraint.

Trying to make a unique index on a non-distribution column will generate an error:

Enforcing uniqueness on a non-distribution column would require Citus to check every shard on every INSERT to validate, which defeats the goal of scalability.

Resolution¶

There are two ways to enforce uniqueness on a non-distribution column:

  1. Create a composite unique index or primary key that includes the desired column (C), but also includes the distribution column (D). This is not quite as strong a condition as uniqueness on C alone, but will ensure that the values of C are unique for each value of D. For instance if distributing by company_id in a multi-tenant system, this approach would make C unique within each company.
  2. Use a reference table rather than a hash distributed table. This is only suitable for small tables, since the contents of the reference table will be duplicated on all nodes.

Function create_distributed_table does not exist¶

Resolution¶

When basic Citus Utility Functions are not available, check whether the Citus extension is properly installed. Running \dx in psql will list installed extensions.

One way to end up without extensions is by creating a new database in a Postgres server, which requires extensions to be re-installed. See Creating a New Database to learn how to do it right.

STABLE functions used in UPDATE queries cannot be called with column references¶

Each PostgreSQL function is marked with a volatility, which indicates whether the function can update the database, and whether the function’s return value can vary over time given the same inputs. A STABLE function is guaranteed to return the same results given the same arguments for all rows within a single statement, while an IMMUTABLE function is guaranteed to return the same results given the same arguments forever.

Non-immutable functions can be inconvenient in distributed systems because they can introduce subtle changes when run at slightly different times across shard replicas. Differences in database configuration across nodes can also interact harmfully with non-immutable functions.

One of the most common ways this can happen is using the timestamp type in Postgres, which unlike timestamptz does not keep a record of time zone. Interpreting a timestamp column makes reference to the database timezone, which can be changed between queries, hence functions operating on timestamps are not immutable.

Citus forbids running distributed queries that filter results using stable functions on columns. For instance:

In this case the comparison operator < between timestamp and timestamptz is not immutable.

Resolution¶

Avoid stable functions on columns in a distributed UPDATE statement. In particular, whenever working with times use timestamptz rather than timestamp . Having a time zone in timestamptz makes calculations immutable.

© Copyright 2023, Citus Data, a Microsoft Company. Revision 5935e323 .

Saved searches

Use saved searches to filter your results more quickly

You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session. You switched accounts on another tab or window. Reload to refresh your session.

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pgbouncer cannot connect to server #724

pgbouncer cannot connect to server #724

Comments

We have this strange behaviour where we see immediate rejection from pgbouncer when we connect as below, but on restart it works just fine. this happened on a couple of servers, so does not seem to be a config issue, since a reboot just «fixes» the problem.

the warning in the logs (FATAL database does not exist) coincides with the «START» of the psql errors and continue until the service is restarted.

problem connecting

$ psql -U mydb -p 7432
psql: error: could not connect to server: FATAL: pgbouncer cannot connect to server

#after restart of pgbouncer it connects fine

$ psql -U mydb -p 7432
Password for user mydb:

i also took a core dump and here is the bt but not sure if it was helpful

$ pgbouncer —version
PgBouncer 1.16.0
libevent 2.1.11-stable
adns: c-ares 1.16.1
tls: OpenSSL 1.1.1k 25 Mar 2021

$ uname -a
#1 SMP Wed Apr 22 09:31:13 -00 2020 x86_64 Intel(R) Xeon(R) Gold 5218 CPU @ 2.30GHz GenuineIntel GNU/Linux

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *