Comments 14
Сняли блокер по переезду на pgx/v4 для Авито, да и для всех, кто использует pgx под нагрузкой.
На сколько я понимаю, проблема воспроизводится только при использовании pgxpool. Если использовать pgx со стандартным database/sql, то проблемы нет. Поэтому приведеная выше фраза не совсем корректная.
А вообще очень интересная история, спасибо, и молодцы что донесли до апстрима!
Спасибо!
И даже понятно, почему: пулер database/sql не ждет, пока PgConn закроет свои коннекты
У меня получилось воспроизвести, запуская приложение вне докера. У меня не получилось воспроизвести, запуская его в контейнере. Более того, я попробовал воспроизвести на версии 4.8.1 (вроде тут фикса ещё нет) и 4.0.0, у меня не получилось. Я немного запутался и мне не хотелось бы никого вводить в заблуждение, так что я записал пару скринкастов.
тест со стандартным пулом
pgxpool_4.8.1 (с клоном вашей репки)
pgx_sql (моя репка)
Да, получилось, даже в контейнере подтверждается: https://github.com/iosadchiy/pgx_pgbouncer_issue/tree/database-sql
Задал вопрос нашему другу https://github.com/jackc/pgx/issues/679#issuecomment-699638269
Слушайте. А кто-то вообще планы запросов строил? Нагрузку тестировал? Почему время ответа базы растет?
Данные кто и как моделировал? За ростом индексов кто то следит?
Из прочитанного мне вилится, что рабоиа с бд для вас черный ящик. Иначе провели бы работы по оптимизации базы, а не клиентского ПО
За моделирование данных, подбор индексов, за оптимизацию запросов у нас отвечает разработчик сервиса. Он при этом плотно взаимодействует с DBA, использует их экспертизу.
Вроде, при использовании pgbouncer, теряется часть функционала, связанная с соединением (подготовленные операторы, курсоры, асинхронные уведомления, ...)
Хороший вопрос. Непосредственные причины, по которым у нас появился pgbouncer, не назову: это было до меня. Думаю, дело вот в чем:
Можно работать и без connection pooler'а, но это требует от сервиса жесткой дисциплины:
- Нельзя делать долгие транзакции; недопустимо оставлять незакрытые транзакции
- Нужно всегда четко следить за размером пула
Звучит просто, но на практике ошибиться очень легко, особенно, когда делаешь несвязанную с базой задачу. А в старых сервисах на пыхе иногда пул вообще не ограничен.
Кроме того, база в LXC контейнере — это относительно новая конфигурация для Авито. Большинство сервисов работает с базами на "коммуналках" — базы делят один сервер. Ограничивать потребление ресурсов конкретной базой там непросто; основной способ — ограничение размера пула. ДБА хотят это явно контролировать, а не перекладывать на разработчиков.
В общем, хорошему сервису pgbouncer практически не мешает. А плохому не дает наделать глупостей и позволяет удовлетворительно работать. Как-то так.
Кстати, вот хорошая статья об этих проблемах https://brandur.org/postgres-connections
Килл происходит через отдельные соединения, и из-за этого все коннекты в баунсере заполнились и новые перестали проходить.
В качестве решений, в частности, предлагалось
Вот тут вам еще предлагали использовать odyssey вместо pgbouncer — https://github.com/pgbouncer/pgbouncer/issues/392#issuecomment-645998318
там это пофикшено: https://github.com/yandex/odyssey/issues/84
Мы тоже испытывали боли с pgbouncer и cancel request, и решили их комплексно...
Проверить испытывает ли ворклоад проблему с cancel request можно через метрику:
https://www.pgbouncer.org/usage.html#show-lists
если used_clients
> cl_active
, значит в cancel_req_list
копится очередь из cancel.
Есть так же другая проблема, которую не видно на метриках pgbouncer/postgres, бывает такое что под большой нагрузкой код начинает слишком часто отменять запросы и поскольку каждый cancel это новый коннект, то здесь (https://i.imgur.com/8Q0UbeC.png) уже втыкаемся в ограничения на стороне куба
заканчиваются эфемерные порты, которых по умолчанию 30к
диагностировать такое можно, например, так:
$ zcat pgbouncer.log-*.gz |fgrep 'cancel' | grep -o '2020-08-21 [0-9][0-9]:[0-9][0-9]' | sort |uniq -c
15617 2020-08-21 07:52
19656 2020-08-21 07:53
19306 2020-08-21 07:54
19616 2020-08-21 07:55
15222 2020-08-21 07:56
77 2020-08-21 07:57
64 2020-08-21 07:58
81 2020-08-21 07:59
87 2020-08-21 08:00
4515 2020-08-21 08:01
17948 2020-08-21 08:02
17027 2020-08-21 08:03
16986 2020-08-21 08:04
17215 2020-08-21 08:05
16577 2020-08-21 08:06
17108 2020-08-21 08:07
17152 2020-08-21 08:08
16881 2020-08-21 08:09
16968 2020-08-21 08:10
16258 2020-08-21 08:11
15627 2020-08-21 08:12
16722 2020-08-21 08:13
15944 2020-08-21 08:14
18246 2020-08-21 08:15
235 2020-08-21 08:16
74 2020-08-21 08:17
64 2020-08-21 08:18
59 2020-08-21 08:19
54 2020-08-21 08:20
18644 2020-08-21 08:21
16323 2020-08-21 08:22
17491 2020-08-21 08:23
17019 2020-08-21 08:24
16435 2020-08-21 08:25
16644 2020-08-21 08:26
17450 2020-08-21 08:27
17468 2020-08-21 08:28
16731 2020-08-21 08:29
6502 2020-08-21 08:30
но поскольку 30к это довольно не мало и сервисов, которые столько раз синхронно ходят в postgres немного, то встречается гораздо реже, чем subj, но имеет место быть. Надеюсь кому-нибудь будет полезна эта инфа.
Тут проблема была все-таки не в pgbouncer'е, а в pgx, так что замена на odyssey, возможно, и не помогла бы. Ну, и odyssey пока не в стеке компании; его использование пришлось бы долго обосновывать.
За подсветку проблемы с коннектами на поде — спасибо, полезно!
Мы тоже испытывали боли с pgbouncer и cancel request, и решили их комплексно...
А как решили, если не секрет?
Приключения одного бага или как починить pgx чужими руками