Перейти к основному содержимому

Уровень 2.0

Клиентское подключение​

В этом разделе рассмотрим, как происходит подключение к серверу баз данных – с локальной машины и по сети, через Unix-сокеты и TCP/IP.

Клиент-серверное взаимодействие​

PostgreSQL как и СУБД Pangolin реализует классическую схему клиент-серверного взаимодействия. Когда сервер запускается, происходит следующее:

Сначала запускается головной процесс postmaster. Этот процесс запускает несколько дочерних процессов (процессы экземпляра), поддерживающих базы данных кластера в работоспособном состоянии, и открывает Unix-сокет и несколько сетевых портов, с помощью которых клиенты могут подключаться к серверу. Когда приходит клиент, головной процесс запускает отдельный серверный процесс для его обслуживания.

Схема клиент-серверного взаимодействия

Процессы экземпляра обмениваются информацией между собой с помощью стандартных средств межпроцессного взаимодействия – IPC (Inter Process Communications). Это могут быть разделяемая память, очереди сообщений. Чтобы увидеть подробности, воспользуйтесь командами man 2 ipc и man ipcs.

Клиент и обслуживающий его серверный процесс взаимодействуют с помощью сетевого протокола прикладного уровня (Application Layer OSI). Этот протокол работает через TCP/IP для сетевых подключений или через Unix-сокеты для локальных. Протокол открытый и допускает различные реализации.

Наиболее простой способ — использовать штатную клиентскую библиотеку libpq с широким набором возможностей.

В любом случае клиент формирует запрос SQL и по сетевому протоколу отправляет его серверу, дожидаясь от него ответа.

Этапы взаимодействия клиента и сервера​

Клиент инициирует соединение с сервером, используя специальный сетевой протокол PostgreSQL, основанный на сообщениях. Протокол поддерживает сетевые соединения TCP/IP и локальные Unix-сокеты.

В зависимости от настроек сервер может отклонить соединение либо продолжить его. Если настроена аутентификация, то сервер требует:

  • идентификацию клиента — когда клиент сообщает, кто он такой;
  • аутентификацию – подтверждение, что это именно он.

При успешной аутентификации дальнейшее обслуживание клиента осуществляет серверный процесс (backend).

Все взаимодействие клиента с экземпляром после успешной аутентификации происходит с серверным процессом, который будет обслуживать клиента в течение всей сессии. Как только сессия прерывается, этот серверный процесс автоматически завершается.

Параметры соединения​

Типичное подключение через клиент psql:

[student@ServerName ~]$ psql
psql (15.5)
Type "help" for help.
student=> \conninfo
You are now connected to database "student" as user "student" via socket in "/tmp" at port "5432".

Где:

  • student — база данных, с которой производится соединение;
  • student — пользователь, зарегистрированный в СУБД;
  • /tmp — адрес или имя сервера, либо путь к Unix-сокету;
  • 5432 — TCP-порт, по умолчанию 5432 в PostgreSQL. В СУБД Pangolin порт TCP по умолчанию — 5433 по соображениям безопасности.

Команда psql запускает интерактивную оболочку стандартного клиента PostgreSQL.

Встроенная команда (метакоманда в терминах psql) \conninfo информирует о том, как выполнено соединение. В данном случае — через Unix-сокет в каталоге /tmp.

Сокеты​

Сетевые соединения производятся через сокеты:

  • Unix-сокеты — файлы особого типа, работают только для локальных соединений;
  • Internet-сокеты — привязаны к сетевым интерфейсам.

Посмотрим, какие сокеты открыты на сервере:

[student@ServerName ~]$ sudo -u postgres ss -ln | grep 5432

Где:

  • ss (socket status) – утилита для просмотра информации о сокетах. Читайте о нем в man ss;
  • -l – показывает только слушающие сокеты;
  • -n – выводит адреса и порты в числовом формате.
u_str LISTEN 0 tcp LISTEN 0 tcp LISTEN 0
290 290 290
/tmp/.s.PGSQL.5432 20416 0.0.0.0:5432 [::]:5432
* 0 0.0.0.0:* [::]:*
А что в выводе?

Значение полей в выводе:

ПолеОписание
u_str/tcpтип сокета (Unix stream или TCP)
LISTENсостояние сокета (ожидание подключений)
0количество байт в очереди приема
290максимальная длина очереди ожидания (backlog)
адрес сокетапуть к Unix-сокету (/tmp/.s.PGSQL.5432) или IP-порт
0 0.0.0.0:*удаленный адрес (для слушающих всегда * – любой)

Исходя из этого, вот что мы видим:

  1. Unix-сокет – /tmp/.s.PGSQL.5432. Он слушает локальные соединения через файл сокета. Число 20416 – это inode этого файла, по которому его можно идентифицировать в файловой системе.
  2. TCP-сокет IPv4 – 0.0.0.0:5432. Прослушивает все сетевые интерфейсы (адрес 0.0.0.0 означает любой) на порту 5432.
  3. TCP-сокет IPv6 – [::]:5432. Аналогичяно для протокола IPv6.

Unix-сокеты — один из способов межпроцессного взаимодействия IPC (в MS Windows не поддерживается). Сокеты — это файлы особого типа. Например:

[student@ServerName ~]$ sudo find /tmp -type s -iname '*sql*' -ls 2>/dev/null
265667 0 srwxrwxrwx 1 postgres postgres 0 окт 18 13:24 /tmp/.s.PGSQL.5432
[student@ServerName ~]$ sudo lsof /tmp/.s.PGSQL.5432 2>/dev/null
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
postgres 116380 postgres 7u unix 0x0000000045d05bdc 0t0 1560935 /tmp/.s.PGSQL.5432 type=STREAM

В каталоге /tmp есть файл .s.PGSQL.5432 — Unix-сокет, что показывает команда find, которая нашла все Unix-сокеты в /tmp. В их имени есть подстрока sql с игнорированием регистра. Команда lsof подтвердила, что файл открыт процессом postgres. Читайте справку по командам man find и man lsof.

Настройки сервера для сокетов​

Параметры, определяющие, какие сокеты открывает сервер, задаются в конфигурации. Посмотреть их можно с помощью самого исполняемого файла postgres:

[postgres@ServerName ~]$ postgres -C listen_addresses 2> /dev/null
*
[postgres@ServerName ~]$ postgres -C port 2> /dev/null
5432
[postgres@ServerName ~]$ postgres -C unix_socket_directories 2> /dev/null
/tmp
Разбор команд:

  • postgres – обращение к исполняемому файлу;
  • -C – выводит параметры конфигурации сервера;
  • listen_addresses/-h – сетевые интерфейсы для Internet-сокетов (* – все интерфейсы, по умолчанию прослушивается только loopback интерфейс localhost);
  • port/-p – TCP-порт, который прослушивает сервер (5432);
  • unix_socket_directories/-k – каталог файловой системы, где будет размещен Unix-сокет (/tmp).

Информация о сервере​

При старте экземпляра в каталоге PGDATA создается файл postmaster.pid. Ранее головной процесс экземпляра назывался postmaster, поэтому файл унаследовал это имя. Он содержит служебную информацию о работающем процессе:

[student@ServerName ~]$ sudo -u postgres cat $PGDATA/postmaster.pid
819
/pgdata/06/data
1726069733
5432
/tmp
*
786435 0
ready

Содержимое файла от первой строки к последней:

  • PID головного процесса;
  • Каталог данных кластера;
  • Время старта кластера (в секундах с эпохи Unix);
  • Порт, прослушиваемый сервером;
  • Каталог Unix-сокета;
  • Прослушиваемые интерфейсы;
  • Идентификатор разделяемой памяти;
  • Статус сервера.

Получение информации о сеансе​

В открытом сеансе можно получить данные о нем и о сервере с помощью специальных функций:

[postgres@ServerName ~]$ psql -qtU postgres -d student
postgres@student=# SELECT user; -- Имя пользователя в сеансе
postgres
postgres@student=# SELECT current_catalog; -- Имя базы данных, к которой подключились
student
postgres@student=# SELECT inet_server_port (); -- Порт TCP (NULL для Unix-сокета)
postgres@student=# \c - - localhost
postgres@student=# SELECT inet_server_port (); -- Подключение через Internet-сокет
5432
postgres@student=# SELECT inet_server_addr (); -- Адрес сервера IPv6 ::1
postgres@student=# \c - - 127.0.0.1
postgres@student=# SELECT inet_server_addr (); -- Адрес сервера IPv4
127.0.0.1

Метакоманда \c выполняет переключение с новыми параметрами (в примере – смена адреса сервера).

Библиотека libpq​

Большинство клиентов (включая psql) скомпилировано с библиотекой libpq для работы с СУБД Pangolin:

[postgres@ServerName ~]$ ldd `which psql`
linux-vdso.so.1 (0x00007ffdc5d57000)
libpq.so.5 => /usr/pangolin/lib/libpq.so.5
(0x00007f6792efa000)
...
Что тут видно?

Разбор использованных команд:

  • which psql – показывает полный путь к исполняемому файлу psql;
  • обратные кавычки – подставляют результат выполнения команды как аргумент для ldd;
  • ldd – утилита для вывода зависимостей от динамических библиотек (подробнее можно прочитать в справке man ldd).

В примере видно, что для работы psql необходима библиотека libpq.so.5, которая реализует протокол взаимодействия с сервером.

libpq предоставляет API для подключения клиента к серверу и реализует разбор параметров строк подключения. Параметры задаются в виде пар ключ-значение, либо в виде URI.

Основные параметры подключения:

  • host — задает имя узла или путь к Unix-сокету для подключения;
  • hostaddr — имя узла для подключения без разрешения имен (resolve);
  • port — TCP-порт для подключения;
  • dbname — имя БД для подключения;
  • user — устанавливает имя пользователя, подключающегося к базе данных;
  • password — пароль.

Подведем итоги​

  • Клиент инициирует соединение с сервером, формирует запросы, а сервер их обрабатывает и отвечает клиенту;
  • Соединение происходит через Unix-сокет или Internet-сокет. В зависимости от настроек может требоваться аутентификация;
  • Для соединения необходимы адрес сервера, порт, имя базы данных и имя пользователя;
  • Прослушиваемые сервером сокеты настраиваются и ограничивают круг клиентов, которые могут подключиться.

Самопроверка​

Вопрос 1

Какие параметры нужно указать при подключении к серверу? Не рассматриваем случай, когда некоторые утилиты могут брать значения по умолчанию. Если параметры не заданы явно, укажите, что является параметрами подключения в общем случае.

Вопрос 2

Что означает значение параметра listen_addresses = 0.0.0.0 ?

Вопрос 3

Какую информацию о сервере можно получить из файла PGDATA/postmaster.pid?

Вопрос 4

Какой метакомандой psql можно получить информацию о текущем подключении?