Сборка, установка и настройка пулера соединений Yandex Odyssey

В мире пулеров PostgreSQL как известно 2 лидера — это Pgpool-II и PgBouncer, но есть и современные альтернативы в лице Yandex Odyssey и pgagroal.

В данной статье мы поговорим, а точнее установим и настроим Yandex Odyssey.

Исходные данные: ОС Oracle Linux 7
Задача: Собрать, установить и настроить пулер соединений Yandex Odyssey

В данной статье я не буду рассказывать об архитектуре или других особенностях Yandex Odyssey, все это хорошо описано в статье тут и на видео-докладе от создателей тут старее, а тут новее.

Отправной точкой для всего является репозиторий проекта на Github.

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

Для начала у нас на сервере должен быть подключен оффициальный репозиторий пакетов PostgreSQL из которого мы установим необходимые для сборки пакеты, далее мы установим cmake 3 и pam-dev, скачаем исходники и соберем их.

1. Если оффициальный репозиторий PostgreSQL у Вас не подключен, то подключаем и устанавливаем devel-пакеты нужной версии PgSQL, у меня это будет 10-я версия.

yum -y localinstall https://download.postgresql.org/pub/repos/yum/11/redhat/rhel-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm
yum -y install postgresql10-devel

2. Установим cmake и другие пакеты:

yum -y install cmake3 pam-devel

3. Сборка Odyssey из исходников:

cd ~
wget https://github.com/yandex/odyssey/archive/1.1.tar.gz -O odyssey-1.1.tar.gz
tar -zxf odyssey-1.1.tar.gz && rm -f odyssey-1.1.tar.gz
cd odyssey-1.1
mkdir build && cd build
cmake3 -DPOSTGRESQL_LIBPGPORT=/usr/pgsql-10/lib/libpgport.a -DPOSTGRESQL_LIBRARY=/usr/pgsql-10/lib/libpq.so -DPOSTGRESQL_INCLUDE_DIR=/usr/pgsql-10/include/server -DPQ_LIBRARY=/usr/pgsql-10/lib/libpq.a -DCMAKE_BUILD_TYPE=Release ..
make

Ниже я приведу вывод начала сборки и ее окончание:

# cmake3 -DPOSTGRESQL_LIBPGPORT=/usr/pgsql-10/lib/libpgport.a -DPOSTGRESQL_LIBRARY=/usr/pgsql-10/lib/libpq.so -DPOSTGRESQL_INCLUDE_DIR=/usr/pgsql-10/include/server -DPQ_LIBRARY=/usr/pgsql-10/lib/libpq.a -DCMAKE_BUILD_TYPE=Release ..
CMake Warning (dev) at /usr/share/cmake3/Modules/FindPackageHandleStandardArgs.cmake:272 (message):
  The package name passed to `find_package_handle_standard_args` (POSTGRESQL)
  does not match the name of the calling package (PostgreSQL).  This can lead
  to problems in calling code that expects `find_package` result variables
  (e.g., `_FOUND`) to follow a certain pattern.
Call Stack (most recent call first):
  cmake/FindPostgreSQL.cmake:52 (find_package_handle_standard_args)
  CMakeLists.txt:42 (find_package)
This warning is for project developers.  Use -Wno-dev to suppress it.

-- Found POSTGRESQL: /usr/pgsql-10/lib/libpq.so
-- Use shipped libmachinarium: /root/odyssey-1.1/third_party/machinarium
-- Use shipped libkiwi: /root/odyssey-1.1/third_party/kiwi
--
-- Odyssey (version: unknown release)
--
-- CMAKE_BUILD_TYPE:       Release
-- BUILD_DEBIAN:           OFF
-- POSTGRESQL_INCLUDE_DIR: /usr/pgsql-10/include/server
-- POSTGRESQL_LIBRARY:     /usr/pgsql-10/lib/libpq.so
-- POSTGRESQL_LIBPGPORT:   /usr/pgsql-10/lib/libpgport.a
-- PG_VERSION_NUM:         OFF
-- PQ_LIBRARY:             /usr/pgsql-10/lib/libpq.a
-- USE_BORINGSSL:          OFF
-- BORINGSSL_ROOT_DIR:
-- BORINGSSL_INCLUDE_DIR:
-- OPENSSL_VERSION:        1.0.2k
-- OPENSSL_ROOT_DIR:
-- OPENSSL_INCLUDE_DIR:    /usr/include
-- PAM_LIBRARY:            /usr/lib64/libpam.so
-- PAM_INCLUDE_DIR:        /usr/include/security
--
-- Configuring done
-- Generating done
-- Build files have been written to: /root/odyssey-1.1/build

# make
[  1%] Built target libkiwi
[  2%] Built target libmachinarium
[  2%] Built target build_libs
Scanning dependencies of target odyssey
[  3%] Building C object sources/CMakeFiles/odyssey.dir/daemon.c.o
[  4%] Building C object sources/CMakeFiles/odyssey.dir/pid.c.o
[  5%] Building C object sources/CMakeFiles/odyssey.dir/logger.c.o
....
....
[ 30%] Building C object sources/CMakeFiles/odyssey.dir/pam.c.o
[ 31%] Linking C executable odyssey
[ 31%] Built target odyssey
Scanning dependencies of target odyssey_test
[ 32%] Building C object test/CMakeFiles/odyssey_test.dir/odyssey_test.c.o
[ 33%] Building C object test/CMakeFiles/odyssey_test.dir/machinarium/test_init.c.o
[ 34%] Building C object test/CMakeFiles/odyssey_test.dir/machinarium/test_create0.c.o
....
....
[ 96%] Building C object test/CMakeFiles/odyssey_test.dir/odyssey/test_hgram.c.o
[ 97%] Linking C executable odyssey_test
[ 97%] Built target odyssey_test
Scanning dependencies of target odyssey_stress
[ 98%] Building C object stress/CMakeFiles/odyssey_stress.dir/odyssey_stress.c.o
[100%] Linking C executable odyssey_stress
[100%] Built target odyssey_stress

Если все прошло успешно и без ошибок, то у нас должен появиться бинарник sources/odyssey, проверим:

# file sources/odyssey
sources/odyssey: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, BuildID[sha1]=745f1f453c44b19ecc4782898c497dcbb4c0579f, not stripped

Отлично, идем дальше.

4. Создание пользователя, базовая настройка, запуск Odyssey:

Создание пользователя и вспомогательных каталогов:

groupadd --system odyssey
useradd --system --shell /sbin/nologin --gid odyssey --home-dir /var/lib/odyssey --no-create-home odyssey
mkdir /run/odyssey
chown -R odyssey:odyssey /run/odyssey
echo "d /run/odyssey 0755 odyssey odyssey - -" > /usr/lib/tmpfiles.d/odyssey.conf
mkdir /var/lib/odyssey
chown -R odyssey:odyssey /var/lib/odyssey
touch /var/log/odyssey.log
chown odyssey:odyssey /var/log/odyssey.log
mkdir /etc/odyssey

Копирование бинарника, unit-файла для systemd и базовая настройка Odyssey:

cd ~
cd odyssey-1.1
cp build/sources/odyssey /usr/bin
chmod a+x /usr/bin/odyssey
chown root:root /usr/bin/odyssey
cat odyssey.conf | sed \
-e '/^# pid_file.*/a \\pid_file \"/var/run/odyssey/odyssey.pid\"' \
-e 's|^unix_socket_dir.*|unix_socket_dir \"/var/run/odyssey\"|g' \
-e 's|^locks_dir.*|locks_dir \"/var/run/odyssey\"|g' \
> /etc/odyssey/odyssey.conf
chmod 644 /etc/odyssey/odyssey.conf
cp scripts/systemd/odyssey.service /usr/lib/systemd/system
systemctl daemon-reload
systemctl enable odyssey

Запуск Odyssey:

systemctl start odyssey

Проверим:

# systemctl status odyssey
● odyssey.service - Advanced multi-threaded PostgreSQL connection pooler and request router
   Loaded: loaded (/usr/lib/systemd/system/odyssey.service; enabled; vendor preset: disabled)
   Active: active (running) since Thu 2020-09-10 13:36:30 MSK; 1s ago
 Main PID: 24848 (odyssey)
   CGroup: /system.slice/odyssey.service
           └─24848 /usr/bin/odyssey /etc/odyssey/odyssey.conf

Sep 10 13:36:30 srv-pg-01 odyssey[24848]: 24848 10 Sep 13:36:30.144 info [none none] (rules)   pool_rollback    yes
Sep 10 13:36:30 srv-pg-01 odyssey[24848]: 24848 10 Sep 13:36:30.144 info [none none] (rules)   client_fwd_error yes
Sep 10 13:36:30 srv-pg-01 odyssey[24848]: 24848 10 Sep 13:36:30.144 info [none none] (rules)   storage          postgres_server
Sep 10 13:36:30 srv-pg-01 odyssey[24848]: 24848 10 Sep 13:36:30.144 info [none none] (rules)   type             remote
Sep 10 13:36:30 srv-pg-01 odyssey[24848]: 24848 10 Sep 13:36:30.144 info [none none] (rules)   host             localhost
Sep 10 13:36:30 srv-pg-01 odyssey[24848]: 24848 10 Sep 13:36:30.144 info [none none] (rules)   port             5432
Sep 10 13:36:30 srv-pg-01 odyssey[24848]: 24848 10 Sep 13:36:30.144 info [none none] (rules)   log_debug        no
Sep 10 13:36:30 srv-pg-01 odyssey[24848]: 24848 10 Sep 13:36:30.144 info [none none] (rules)
Sep 10 13:36:30 srv-pg-01 odyssey[24848]: 24848 10 Sep 13:36:30.149 info [none none] (server) listening on 0.0.0.0:6432
Sep 10 13:36:30 srv-pg-01 odyssey[24848]: 24848 10 Sep 13:36:30.150 error [none none] (server) bind to '[::]:6432' failed: Address family not support... protocol
Hint: Some lines were ellipsized, use -l to show in full.

Поверим процесс:

# ps -ef | grep [o]dyssey
odyssey  24848     1  0 13:36 ?        00:00:00 /usr/bin/odyssey /etc/odyssey/odyssey.conf

Проверим порт:

# netstat -ltupn | grep odyssey
tcp        0      0 0.0.0.0:6432            0.0.0.0:*               LISTEN      24848/odyssey

Итак, мы видим, что Odyssey запустился с базовым конфигом и принимает сетевые подключения на всех сетевых интерфейсах по порту 6432

Далее нам нужно настроить пул для нашей базы PostgreSQL, а возможно несколько пулов и баз, а так же необходимо настроить сервисную базу из которой можно получать статистику работы Odyssey.

Начнем настройку:

1. Для начала немного безопасности.

Как мы знаем Odyssey принимает соединения на всех интерфейсах по порту 6432, это может быть опасно если Ваш сервер смотрит в Интернет и Вы не закроете порт 6432 для всех желающих.
В моем случае я перенастрою Odyssey чтобы он принимал соединения только со 127.0.0.1, для этого откроем файл конфигурации /etc/odyssey/odyssey.conf и в секции listen отредактируем параметр host

Получилось так:

listen {
        host "127.0.0.1"
        port 6432
        backlog 128
}

2. Настроим административную консоль для просмотра статистики.

Для этого откроем файл конфигурации /etc/odyssey/odyssey.conf и добавим в конец строки:

storage "local" {
        type "local"
}
database "console" {
        user default {
                authentication "none"
                pool "session"
                storage "local"
        }
}

Сохраняем конфиг и перезапускаем Odyssey:

systemctl restart odyssey

Проверим порт:

# netstat -ltupn | grep odyssey
tcp        0      0 127.0.0.1:6432          0.0.0.0:*               LISTEN      13499/odyssey

Отлично, теперь Odyssey принимает подключения только на 127.0.0.1 порт 6432

Теперь можно подключиться к сервисной базе:

psql -h 127.0.0.1 -p 6432 -d console

Попробуем ввести некоторые команды для просмотра состояния. К слову сказать, разработчики Odyssey постарались сделать такие же команды как и у PgBouncer, хотя далеко не все.

psql (10.9, server 9.6.0)
Type "help" for help.

console=> show stats;
 database  | total_xact_count | total_query_count | total_received | total_sent | total_xact_time | total_query_time | total_wait_time | avg_xact_count | avg_query_count | avg_recv | avg_sent | avg_xact_time | avg_query_time | avg_wait_time
-----------+------------------+-------------------+----------------+------------+-----------------+------------------+-----------------+----------------+-----------------+----------+----------+---------------+----------------+---------------
 console   |                0 |                 0 |              0 |          0 |               0 |                0 |               0 |              0 |               0 |        0 |        0 |             0 |              0 |             0
(1 rows)

console=> show pools;
 database  |   user   | cl_active | cl_waiting | sv_active | sv_idle | sv_used | sv_tested | sv_login | maxwait | maxwait_us | pool_mode
-----------+----------+-----------+------------+-----------+---------+---------+-----------+----------+---------+------------+-----------
 console   | root     |         0 |          1 |         0 |       0 |       0 |         0 |        0 |       0 |          0 | session
(1 rows)

console=> show clients;
 type |   user   | database |  state  |   addr    | port  | local_addr | local_port | connect_time | request_time | wait | wait_us |      ptr      | link | remote_pid | tls
------+----------+----------+---------+-----------+-------+------------+------------+--------------+--------------+------+---------+---------------+------+------------+-----
 C    | root     | console  | pending | 127.0.0.1 | 27194 | 127.0.0.1  |       6432 |              |              |    0 |       0 | cbbfabe55cdbf |      |          0 |
(1 rows)

console=> show lists;
     list      | items
---------------+-------
 databases     |     0
 users         |     0
 pools         |     1
 free_clients  |     0
 used_clients  |     1
 login_clients |     0
 free_servers  |     0
 used_servers  |     0
 dns_names     |     0
 dns_zones     |     0
 dns_queries   |     0
 dns_pending   |     0
(12 rows)

console=> show databases;
   name    |   host    | port | database  | force_user | pool_size | reserve_pool | pool_mode | max_connections | current_connections | paused | disabled
-----------+-----------+------+-----------+------------+-----------+--------------+-----------+-----------------+---------------------+--------+----------
 console   |           |    0 | console   |            |         0 |            0 | session   |               0 |                   1 |      0 |        0
(1 rows)

console=> show servers;
 type |   user   | database | state  |   addr    | port | local_addr | local_port | connect_time | request_time | wait | wait_us |      ptr      | link | remote_pid | tls
------+----------+----------+--------+-----------+------+------------+------------+--------------+--------------+------+---------+---------------+------+------------+-----
(0 rows)

3. Включим ведение лога.

Для этого откроем файл конфигурации /etc/odyssey/odyssey.conf и раскоментируем настройку log_file, у меня получилось так:

log_file "/var/log/odyssey.log"

Файл /var/log/odyssey.log должен существовать и его владельцем должен быть пользователь odyssey. Мы создали файл в самом начале статьи.

Сохраняем конфиг и перезапускаем Odyssey:

systemctl restart odyssey

Теперь можно посмотреть что будет писаться в лог:

tail -f /var/log/odyssey.log

Пример записей при подключении к административной консоле:

13499 10 Sep 15:35:29.516 info [c01ac457670b6 none] (main) client disconnected
13499 10 Sep 15:35:32.336 info [ca45b52665e0c none] (startup) new client connection 127.0.0.1:27590
13499 10 Sep 15:35:32.336 info [ca45b52665e0c none] (startup) route 'console.root' to 'console.default'

Формат лога очень гибко настраивается параметром log_format
Так же можно настроить ведение отладочной информации в лог — log_debug
Можно настроить запись в лог конфигурации при старте — log_config
Можно настроить запись статистики сессий в лог — log_session
Можно настроить запись клиентских запросов в лог — log_query
Настроить периодическую запись в лог статистики — log_stats и ее интервал — stats_interval
А так же можно настроить запись логов в syslog — log_syslog, log_syslog_ident, log_syslog_facility
И даже вывод лога в stdout — log_to_stdout
В общем очень много всего по логгированию, что довольно удобно.

4. Теперь займемся настройкой сторджей, баз и пользователей для работы пулера.

Odyssey позволяет очень гибко настраивать пулы с привязкой к конкретной базе и даже к конкретному пользователю, а так же позволяет настраивать для них различные методы аутентификации: по паролю или сертификату (clear_text, md5, scram-sha-256, certificate), по паролю из какой-то внешней базы (конечно только из postgresql базы) и через PAM.

Секции storage (мы их уже видели когда настраивали административный доступ) описывают подключение к удаленному (type «remote») серверу PostgreSQL, по умолчанию настроена одна секция storage с именем «postgres_server» с параметром host «localhost», то есть пулер будет подключаться к PostgreSQL расположенному на этом же хосте что и он сам и на стандартном порту 5432, вот пример этой секции:

storage "postgres_server" {
    type "remote"
    host "localhost"
    port 5432
}

Учитывая, что у меня PostgreSQL работает там же где и пулер, то я эту секцию не меняю.

Следующая секция, которая есть по умолчанию — это database с именем default, ниже все ее настройки. Если вы откроете конфиг, то ко всем настройкам Вы увидите детальное описание, что довольно удобно и позволяет легко сделать новые секции с необходимыми настройками.

database default {
    user default {
        authentication "none"
        storage "postgres_server"
        pool "transaction"
        pool_size 0
        pool_timeout 0
        pool_ttl 60
        pool_discard no
        pool_cancel yes
        pool_rollback yes
        client_fwd_error yes
        application_name_add_host yes
        server_lifetime 3600
        log_debug no
        quantiles "0.99,0.95,0.5"
    }
}

В секцию default направляются все соединения если не были найдены иные маршруты для баз и пользователей. Как мы видим секция default связана с сервером (storage) «postgres_server».

Особого смысла менять секцию default нет, мы создадим отдельные маршруты для конкретных баз и пользователей чуть ниже. Все что не будет подпадать под наши правила будет отправляться в default, а учитывая что там указан authentication «none», то никто не сможет подключиться к PostgreSQL.

Давайте создадим 1 маршрут для базы pgbench и пользователя pgtest.

Для начала создадим пользователя и базу в Pg.

psql -qAtXc "CREATE ROLE pgtest WITH LOGIN PASSWORD 'verybigandstrongpasswd';"
psql -qAtXc "CREATE DATABASE pgbench OWNER pgtest;"

Проверим соединение:

# psql -h 127.0.0.1 -U pgtest -W pgbench
pgbench=> \conninfo
You are connected to database "pgbench" as user "pgtest" on host "127.0.0.1" at port "5432".

Теперь добавим в файл конфигурации /etc/odyssey/odyssey.conf настройки:

database "pgbench" {
    user "pgtest" {
        authentication "md5"
        password "verybigandstrongpasswd"
        storage "postgres_server"
        pool "transaction"
        pool_size 5
        pool_timeout 3
        pool_ttl 60
        pool_discard no
        pool_cancel yes
        pool_rollback yes
        client_fwd_error yes
        application_name_add_host yes
        server_lifetime 3600
        log_debug no
        quantiles "0.99,0.95,0.5"
    }
}

Это типовые настройки, я скорректировал только несколько из них:

authentication "md5"
password "verybigandstrongpasswd"
pool_size 5
pool_timeout 3

Теперь можно либо перезапустить Odyssey, либо послать сигнал HUP процессу для перезагрузки конфигурации.

systemctl restart odyssey

Теперь можно подключиться к базе pgbench через пулер:

psql -h 127.0.0.1 -p 6432 -U pgtest -W -d pgbench

Вводим пароль и мы должны успешно подключиться, в лог /var/log/odyssey.log будет что-то подобное:

21564 18 Sep 10:51:41.001 info [cc39f41130933 none] (startup) new client connection 127.0.0.1:39592
21564 18 Sep 10:51:41.001 info [cc39f41130933 none] (startup) route 'pgbench.pgtest' to 'pgbench.pgtest'
21564 18 Sep 10:51:41.001 info [cc39f41130933 sd46abe7338d4] (setup) new server connection localhost:5432 (connect time: 226 usec, resolve time: 140 usec)
21564 18 Sep 10:51:41.004 info [cc39f41130933 none] (setup) login time: 3241 microseconds

Посмотрим данные из административной консоли Odyssey:

psql -h 127.0.0.1 -p 6432 -d console

console=> show pools;
 database  |   user   | cl_active | cl_waiting | sv_active | sv_idle | sv_used | sv_tested | sv_login | maxwait | maxwait_us |  pool_mode
-----------+----------+-----------+------------+-----------+---------+---------+-----------+----------+---------+------------+-------------
 pgbench   | pgtest   |         0 |          1 |         0 |       0 |       0 |         0 |        0 |       0 |          0 | transaction
 console   | root     |         0 |          1 |         0 |       0 |       0 |         0 |        0 |       0 |          0 | session
(2 rows)

console=> show servers;
 type |   user   | database  | state  |   addr    | port | local_addr | local_port | connect_time | request_time | wait | wait_us |      ptr      | link | remote_pid | tls
------+----------+-----------+--------+-----------+------+------------+------------+--------------+--------------+------+---------+---------------+------+------------+-----
 S    | pgtest   | pgbench   | idle   | 127.0.0.1 | 5432 | 127.0.0.1  |      13834 |              |              |    0 |       0 | sc98d31063787 |      |          0 |
(1 rows)

console=> show databases;
   name    |   host    | port | database  | force_user | pool_size | reserve_pool |  pool_mode  | max_connections | current_connections | paused | disabled
-----------+-----------+------+-----------+------------+-----------+--------------+-------------+-----------------+---------------------+--------+----------
 pgbench   | localhost | 5432 | pgbench   |            |         5 |            0 | transaction |               0 |                   1 |      0 |        0
 console   |           |    0 | console   |            |         0 |            0 | session     |               0 |                   1 |      0 |        0
(2 rows)

console=> show clients;
 type |   user   | database |  state  |   addr    | port  | local_addr | local_port | connect_time | request_time | wait | wait_us |      ptr      | link | remote_pid | tls
------+----------+----------+---------+-----------+-------+------------+------------+--------------+--------------+------+---------+---------------+------+------------+-----
 C    | pgtest   | pgbench  | pending | 127.0.0.1 | 39592 | 127.0.0.1  |       6432 |              |              |    0 |       0 | cc39f41130933 |      |          0 |
 C    | root     | console  | pending | 127.0.0.1 | 43076 | 127.0.0.1  |       6432 |              |              |    0 |       0 | c4def02139fe8 |      |          0 |
(2 rows)

Мы видим данные о нашем пуле, сервере, базе и соединении.

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


Оставить комментарий

avatar
1000

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.

  Подписаться  
Уведомление о