Я реализовал мультитенантность так: http://blog.trixi.cz/2012/01/multitenancy-using-spring-and-postgresql/
TL; DR: У меня есть база данных postgres с одной схемой для каждого из моих арендаторов. Я использую java apache dbcp2 для настройки пула соединений. Для каждого арендатора я сохраняю BasicDataSource на карте, и для каждого запроса я ищу источник данных на этой карте, чтобы установить соединение для этого арендатора. Каждый источник данных установил правильный путь для своего 'арендатора.
Я пытаюсь выяснить возможную конфигурацию пула соединений для этой настройки.
До сих пор я использовал какую-то случайную, совершенно неверную конфигурацию, такую как:
maxTotal 100
maxIdle 30
maxWaitMillis 10000
testOnBorrow true
testWhileIdle true
validationQuery select 1
minEvitableIdleTimeMillis 300000
timeBetweenEvictionRunsMillis -1
removeAbandonedOnMaintenance true
removeAbandonedOnBorrow true
В postgres у меня есть эта настройка:
max_connections 100
С этой конфигурацией я теперь сталкиваюсь с исключениями:
org.postgresql.util.PSQLException: FATAL: remaining connection slots are reserved for non-replication superuser connections
Пожалуйста, помогите мне понять:
maxTotal
слишком велико, так как определяется
источник данных, которых у меня столько же, сколько и арендаторов
maxTotal
никогда не должно быть больше, чем max_connections
в postgres для этого, n * maxTotal < max_connections
, где n
- количество арендаторов, которых я
есть
- Я вижу много незанятых соединений, но очень мало активных, поэтому
maxIdle
слишком много слишком
- установка
timeBetweenEvictionRunsMillis
в -1
делает настройку minEvictableIdleTimeMillis
неиспользованной, поскольку поток выселения никогда не запускается вообще
Итак, мой следующий подход будет выглядеть примерно так:
maxTotal 8
maxIdle 2
minIdle 0
maxWaitMillis 30000
testOnBorrow true
validationQuery select 1
removeAbandonedOnMaintenance true
removeAbandonedOnBorrow true
Итак, я хочу сохранить одновременные соединения для каждого арендатора, максимально разрешив до 8 соединений. Я также хочу свести к минимуму количество незанятых соединений, чтобы ни один арендатор не задерживал слишком много соединений.
Здесь возникает еще несколько вопросов:
Нужен ли поток evictor для работы maxIdle? То есть я должен установить timeBetweenEvictionRunsMillis
?
Стоит ли подумать об использовании другого механизма пула соединений, например, pgBouncer? Я полагаю, что можно было бы интерпретировать мою настройку как множество отдельных приложений, использующих одну общую базу данных, таким образом, необходимость в pgBouncer ...
Есть ли какой-нибудь нестатический способ настройки моих пулов в соответствии с количеством арендаторов? Скажем, сегодня у меня 20 арендаторов, и, возможно, на следующей неделе у меня будет 40 ...