PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

PostgreSQL-Verbindungspooling mit PgBouncer

Verbindungspooling ist eine einfache, aber effektive Möglichkeit, die Leistung Ihrer Apps zu verbessern und die Last auf Ihren PostgreSQL-Servern zu verringern. Lesen Sie weiter, um mehr über die Verwendung von PgBouncer zum Poolen von PostgreSQL-Verbindungen zu erfahren.

Warum Verbindungspooling?

PostgreSQL hat eine ziemlich schwergewichtige Verbindungsverarbeitungsarchitektur. Für jede eingehende Verbindung der Postmaster (der wichtigste Postgres-Daemon) gibt einen neuen Prozess aus (üblicherweise als Backend bezeichnet). ) damit umzugehen. Während dieses Design eine bessere Stabilität und Isolierung bietet, macht es es nicht besonders effizient bei der Handhabung kurzlebiger Verbindungen. Eine neue Postgres-Client-Verbindung umfasst TCP-Setup, Prozesserstellung und Backend-Initialisierung – all dies ist zeit- und systemressourcenintensiv.

Dies ist natürlich nur dann ein Problem, wenn Verbindungen zu oft erstellt und ohne Wiederverwendung verworfen werden. Leider ist es nicht ungewöhnlich, einen Cluster von Webknoten zu haben, auf denen in PHP oder anderen solchen Sprachen geschriebene Anwendungen ausgeführt werden, die sich einmal pro Seitenladevorgang mit der Datenbank verbinden müssen. Batch-Jobs, die schnell viele Verbindungen in schneller Folge herstellen, sind ebenfalls üblich. Einsatz von Verbindungspooling in solchen Szenarien kann die Belastung Ihres PostgreSQL-Servers drastisch reduzieren und die Abfragelatenzen drastisch verbessern.

Beim Verbindungspooling verbinden sich die Clients mit einem Proxyserver, der eine Reihe direkter Verbindungen zum echten PostgreSQL-Server aufrechterhält. Typischerweise bemerken (und sollten) die Clients nicht, dass sie mit einem Proxyserver und nicht mit dem eigentlichen Server verbunden sind. Der Proxy kann auf demselben Knoten wie der Client laufen (z. B. auf jedem Webknoten), in diesem Fall können sich die Clients mit dem Proxy über Unix-Domain-Sockets verbinden, die einen sehr geringen Verbindungsaufwand haben. Selbst wenn sich der Proxy auf einem anderen Knoten befindet und der Client eine TCP-Verbindung benötigt, um den Proxy zu erreichen, kann der Overhead eines neuen Postgres-Backends vermieden werden.

Was ist PgBouncer?

PgBouncer ist ein leichtgewichtiger Open-Source-Pooler für Single-Binary-Verbindungen für PostgreSQL. Es kann Verbindungen zu einer oder mehreren Datenbanken (auf möglicherweise verschiedenen Servern) bündeln und Clients über TCP- und Unix-Domain-Sockets bedienen.

PgBouncer verwaltet einen Pool von Verbindungen für jeden eindeutigen Benutzer und jedes Datenbankpaar. Es ist normalerweise so konfiguriert, dass eine dieser Verbindungen an eine neue eingehende Client-Verbindung übergeben und wieder an den Pool zurückgegeben wird, wenn der Client die Verbindung trennt. Sie können PgBouncer für ein aggressiveres Poolen konfigurieren, sodass es die Verbindung an Transaktions- oder Anweisungsgrenzen statt an Verbindungsgrenzen aufnehmen und an den Pool zurückgeben kann. Diese haben jedoch einige potenziell unerwünschte Folgen.

Sie sollten PgBouncer mit dem Paketmanager Ihrer Distribution installieren können:

# RedHat/CentOS/..
$ sudo yum install pgbouncer

# Debian/Ubuntu/..
$ sudo apt-get install pgbouncer

Es ist auch in den standardmäßigen Postgres APT- und YUM-Repositorys verfügbar, die verwendet werden können, wenn die Pakete Ihrer Distribution alt oder beschädigt sind.

PgBouncer basiert auf einer Hauptkonfigurationsdatei, die normalerweise als /etc/pgbouncer/pgbouncer.ini gespeichert wird . Sie können pgbouncer als systemd-Dienst aufrufen oder ihn einfach auch ohne Superuser-Rechte mit dem Pfad zu dieser Konfigurationsdatei ausführen.

Um es mal auszuprobieren, erstellen wir eine Datenbank db1 und einen Benutzer user1 auf unserem Server:

$ sudo -u postgres psql
psql (10.6 (Debian 10.6-1.pgdg90+1))
Type "help" for help.

postgres=# create user user1 password 'user1pass';
CREATE ROLE
postgres=# create database db1 owner user1;
CREATE DATABASE
postgres=#

Clients verbinden sich mit der Datenbank db1 mit dem Benutzernamen user1 undPasswort user1pass . Unser Ziel ist es, die Clients dazu zu bringen, sich mit PgBouncer zu verbinden, der die Verbindungen zum eigentlichen Server weiterleitet und zusammenfasst.

Lassen Sie uns nun eine Datei (irgendwo) mit diesem Inhalt erstellen:

[databases]
db1 = host=localhost dbname=db1

[pgbouncer]
listen_addr = 127.0.0.1
listen_port = 16432
auth_file = userlist.txt

Wir müssen auch eine „userlist.txt“-Datei im selben Verzeichnis erstellen, mit dem Benutzernamen und den (gehashten) Passwörtern der Benutzer, denen PgBouncer die Verbindung erlauben wird. Erstellen Sie „userlist.txt“ mit den folgenden Inhalten:

"user1" "md5638b81c77071ea624d1ad4adb1433540"

Der zweite Wert ist das MD5 von „user1passuser1“, dem „md5“ vorangestellt ist. Dies ist die übliche Postgres-Konvention.

Starten wir nun PgBouncer im Vordergrund:

$ /usr/sbin/pgbouncer pgbouncer.ini
2019-02-05 11:46:18.011 10033 LOG file descriptor limit: 1024 (H:1048576), max_client_conn: 100, max fds possible: 130
2019-02-05 11:46:18.012 10033 LOG listening on 127.0.0.1:16432
2019-02-05 11:46:18.013 10033 LOG listening on unix:/tmp/.s.PGSQL.16432
2019-02-05 11:46:18.014 10033 LOG process up: pgbouncer 1.9.0, libevent 2.0.21-stable (epoll), adns: c-ares 1.12.0, tls: OpenSSL 1.1.0j  20 Nov 2018

Wir haben jetzt einen PgBouncer gestartet, der auf 127.0.0.1 TCP-Port 16432 sowie auf dem Unix-Domain-Socket /tmp/.s.PGSQL.16432 lauscht . Die einzige auf diesem Proxy-Server verfügbare „Datenbank“ ist db1 . Der einzige Benutzer, der sich mit diesem Server verbinden kann, ist user1 . Versuchen wir, eine Verbindung mit psql herzustellen :

$ psql -U user1 -p 16432 -h localhost db1
Password for user user1:
psql (10.6 (Debian 10.6-1.pgdg90+1))
Type "help" for help.

db1=> select inet_server_addr(), inet_server_port();
 inet_server_addr | inet_server_port
------------------+------------------
 127.0.0.1        |             5432
(1 row)

db1=>

Der Client (psql) stellt erfolgreich eine Verbindung zu localhost:16432 her, aber Sie können sehen, dass die Verbindung tatsächlich an localhost:5432 weitergeleitet wird.

Sie können einige Male versuchen, die Verbindung zu trennen und erneut herzustellen, und dann überprüfen, wie viele Verbindungen auf dem aktuellen Server noch vorhanden sind:

postgres=# select count(*) from pg_stat_activity
postgres-#   where datname='db1' and usename='user1';
 count
-------
     1
(1 row)

PgBouncer wird die tatsächliche Verbindung nicht trennen, wenn der Client die Verbindung trennt. Sie können die minimalen, maximalen und reservierten Verbindungen konfigurieren, die PgBouncer für jeden Pool in der Konfigurationsdatei aufrechterhält.

PgBouncer bereitstellen

Wo wird PgBouncer installiert und ausgeführt? Es gibt verschiedene Antworten mit unterschiedlichen Vorteilen:

  • Auf dem Postgres-Serverknoten :Sie können es zusammen mit dem PostgreSQL-Server selbst auf demselben Knoten installieren. Die Clients verbinden sich mit dem PgBouncer-Port statt mit dem Postgres-Port. Dies wirkt wie ein „erweitertes“ Postgres, das intern Connection-Pooling durchführt. Sie müssen auch nur eine Kopie der Konfigurationsdateien für PgBouncer pflegen. Auf der anderen Seite bedeutet dies, dass auch auf dem PostgreSQL-Serverknoten tatsächlich etwas anderes ausgeführt wird, was möglicherweise nicht einfach oder zulässig (Firewalls, Richtlinien) oder sogar möglich (AWSRDS) ist.
  • Auf Client-Knoten :Sie können PgBouncer in jedem Client-Knoten installieren, zum Beispiel läuft auf jedem Web-Knoten Apache und PHP, und die PHP-Skripte verbinden sich mit dem lokalen PgBouncer. Dies hat den Vorteil, dass das Server-Setup nicht gestört werden muss und die Pool-Konfiguration verwendet werden kann, um die Serverlast vorhersehbar zu halten. Datenverkehr kann der Server schnell überlastet sein.
  • Als eigenständiger Cluster :Die dritte Option, um einen Cluster unabhängiger, zustandsloser PgBouncer-Knoten zu haben, denen ein TCP-Load-Balancer wie HAProxy vorangestellt ist. Diese Einrichtung ist zwar komplizierter als die beiden anderen Optionen, bietet aber maximale Kontrolle und Konfigurierbarkeit.

Verwaltung

Mit PgBouncer können sich als Administratoren gekennzeichnete Benutzer mit einer virtuellen Datenbank namens „pgbouncer“ verbinden und Befehle erteilen, um den Server zu steuern und Statistiken anzuzeigen. Um dies zu versuchen, markieren wir zunächst „Benutzer1“ als Administrator, indem wir die Datei „pgbouncer.ini“ ändern:

[databases]
db1 = host=localhost dbname=db1

[pgbouncer]
listen_addr = 127.0.0.1
listen_port = 16432
auth_file = userlist.txt
admin_users = user1

Jetzt kann sich Benutzer1 mit der Datenbank namens „pgbouncer“ verbinden:

$ psql -U user1 -p 16432 -h localhost pgbouncer
Password for user user1:
psql (10.6 (Debian 10.6-1.pgdg90+1), server 1.9.0/bouncer)
Type "help" for help.

pgbouncer=#

Von hier aus können Sie verschiedene Dinge tun, wie das Aktivieren oder Deaktivieren einer bestimmten Datenbank, das Überprüfen und Neuladen der Konfiguration und mehr:

pgbouncer=# RELOAD;
RELOAD
pgbouncer=# DISABLE db1;
DISABLE
pgbouncer=# ENABLE db1;
ENABLE
pgbouncer=# SHOW FDS;
 fd |  task  | user  | database |   addr    | port  |     cancel     | link | client_encoding | std_strings | datestyle | timezone  | pa
----+--------+-------+----------+-----------+-------+----------------+------+-----------------+-------------+-----------+-----------+---
  6 | pooler |       |          | 127.0.0.1 | 16432 |              0 |    0 |                 |             |           |           |
  7 | pooler |       |          | unix      | 16432 |              0 |    0 |                 |             |           |           |
  9 | server | user1 | db1      | 127.0.0.1 |  5432 | 45404395804679 |    0 | UTF8            | on          | ISO, MDY  | localtime |
(3 rows)

Überwachung

Es gibt auch Befehle, um verschiedene Statistiken über den PgBouncer anzuzeigen, darunter:

  • Statistiken pro Datenbank über Abfragedauer, Client-Wartezeit, Netzwerknutzung, Transaktionszahlen
  • Pro-Pool-Statistiken über die Anzahl der aktiven und wartenden Clients, inaktive und verwendete Serververbindungen

Statistiken werden mit Befehlen im Stil von „SHOW xyz“ abgerufen, wie dieser zum Abrufen von Pool-bezogenen Statistiken:

pgbouncer=# SHOW POOLS;
-[ RECORD 1 ]---------
database   | db1
user       | user1
cl_active  | 0
cl_waiting | 0
sv_active  | 0
sv_idle    | 0
sv_used    | 1
sv_tested  | 0
sv_login   | 0
maxwait    | 0
maxwait_us | 0
pool_mode  | session
-[ RECORD 2 ]---------
database   | pgbouncer
user       | pgbouncer
cl_active  | 1
cl_waiting | 0
sv_active  | 0
sv_idle    | 0
sv_used    | 0
sv_tested  | 0
sv_login   | 0
maxwait    | 0
maxwait_us | 0
pool_mode  | statement

Weiterführende Literatur

Auf der PgBouncer-Startseite finden Sie weitere Einzelheiten zu den verschiedenen Funktionen und Konfigurationsoptionen von PgBouncer.

  • PgBouncer-Startseite
  • PgBouncer-GitHub-Repository
  • Postgres-Wiki enthält Informationen zum Verbindungspooling
  • Pgpool ist eine weitere Option für das Verbindungspooling