← Hyperdrive (Postgres & MySQL) / hyperdrive / concepts
Жизненный цикл соединения
Понимание того, как работают подключения между Workers, Hyperdrive и исходной базой данных, необходимо для создания эффективных приложений на основе Hyperdrive.
Поддерживая пул подключений к вашей базе данных внутри сети Cloudflare, Hyperdrive сокращает семь обращений к базе данных, которые иначе потребовались бы ещё до отправки запроса: TCP-рукопожатие (1 раз), согласование TLS (3 раза) и аутентификацию в базе данных (3 раза).
Как управляются соединения
При использовании клиента базы данных в Cloudflare Worker жизненный цикл подключения работает иначе, чем в традиционных серверных средах. Вот что происходит:
Без Hyperdrive каждый вызов Worker потребовал бы установки нового подключения напрямую к исходной базе данных. Для завершения TCP-рукопожатия, согласования TLS и аутентификации в базе данных такому подключению нужно несколько проходов через интернет: это 7x проходов и дополнительная задержка ещё до того, как запрос вообще начнёт выполняться.
Hyperdrive решает эту задачу, разделяя установку соединения на две части: быстрое периферийное соединение и оптимизированный путь к базе данных.
-
Настройка подключения на периферийной сети: Драйвер базы данных в коде вашего Worker устанавливает подключение к экземпляру Hyperdrive. Это происходит на периферии, в непосредственной близости от вашего Worker, поэтому подключения создаются очень быстро. Именно поэтому вы используете специальную строку подключения Hyperdrive.
-
Один цикл обмена данными между регионами: Поскольку аутентификация уже выполнена на периферии, Hyperdrive достаточно всего одного обращения между регионами к вашей базе данных вместо нескольких обращений, которые потребовались бы при установке подключения.
-
Получение существующего подключения из пула: Hyperdrive использует существующее подключение из пула, расположенное в непосредственной близости от вашей базы данных, что минимизирует задержку.
-
Если нет доступных подключений, создать новое: При необходимости новые подключения создаются из региона, расположенного близко к вашей базе данных, что снижает задержку при их установке.
-
Выполнить запрос: Ваш запрос выполняется в базе данных, а результаты возвращаются в Worker через Hyperdrive.
-
Закрытие подключения: Когда ваш Worker завершает обработку запроса, подключение клиента базы данных в Worker автоматически удаляется сборщиком мусора. Однако Hyperdrive сохраняет подключение к исходной базе данных открытым в пуле и готовым к повторному использованию при следующем вызове Worker. Это означает, что последующие запросы всё равно будут проходить быструю настройку подключения на периферии, но при этом будут повторно использовать одно из существующих подключений из пула Hyperdrive рядом с вашей базой данных.
Очистка клиентских подключений
После того как Worker завершает обработку запроса, клиент базы данных автоматически удаляется сборщиком мусора, а периферийное подключение к Hyperdrive закрывается. При этом Hyperdrive сохраняет базовое подключение к исходной базе данных открытым в своём пуле для повторного использования.
Вам не не необходимо вызвать client.end(), sql.end(), connection.end() (или аналогичный) для очистки клиентов базы данных. Соединения между Workers и Hyperdrive закрываются автоматически по завершении запроса или вызова, в том числе когда Workflow или Потребитель очереди завершится, либо когда Durable Object переходит в спящий режим или вытесняется при простое.
import { Client } from "pg";
export default {
async fetch(request, env, ctx): Promise<Response> {
const client = new Client({
connectionString: env.HYPERDRIVE.connectionString,
});
await client.connect();
const result = await client.query("SELECT * FROM pg_tables");
// No need to call client.end() — Hyperdrive automatically cleans
// up the client connection when the request ends. The underlying
// pooled connection to your origin database remains open for reuse.
return Response.json(result.rows);
},
} satisfies ExportedHandler<Env>;Не создавайте клиенты баз данных или пулы подключений в глобальной области видимости. Вместо этого создавайте новый клиент при каждом вызове обработчика: пул подключений Hyperdrive обеспечивает высокую скорость этой операции.
import { Client } from "pg";
// 🔴 Bad: Client created in the global scope persists across requests.
// Workers do not allow I/O across request contexts, so this client
// becomes stale and subsequent queries will throw hard errors.
const globalClient = new Client({
connectionString: env.HYPERDRIVE.connectionString,
});
await globalClient.connect();
export default {
async fetch(request, env, ctx) {
// ✅ Good: Client created inside the handler, scoped to this request.
// Hyperdrive pools the underlying connection to your origin database,
// so creating a new client per request is fast and reliable.
const client = new Client({
connectionString: env.HYPERDRIVE.connectionString,
});
await client.connect();
const result = await client.query("SELECT * FROM pg_tables");
return Response.json(result.rows);
},
};import { Client } from "pg";
// 🔴 Bad: Client created in the global scope persists across requests.
// Workers do not allow I/O across request contexts, so this client
// becomes stale and subsequent queries will throw hard errors.
const globalClient = new Client({
connectionString: env.HYPERDRIVE.connectionString,
});
await globalClient.connect();
export default {
async fetch(request, env, ctx): Promise<Response> {
// ✅ Good: Client created inside the handler, scoped to this request.
// Hyperdrive pools the underlying connection to your origin database,
// so creating a new client per request is fast and reliable.
const client = new Client({
connectionString: env.HYPERDRIVE.connectionString,
});
await client.connect();
const result = await client.query("SELECT * FROM pg_tables");
return Response.json(result.rows);
},
} satisfies ExportedHandler<Env>;Особенности жизненного цикла подключения
Durable Objects и постоянные соединения
В отличие от обычных Workers, Durable Objects может сохранять состояние между несколькими запросами. Если вы держите клиент базы данных открытым внутри Durable Object, соединение останется занятым в пуле соединений Hyperdrive. Долгоживущие Durable Objects способны исчерпать доступные соединения, если много объектов одновременно удерживают соединения открытыми.
Долгие транзакции
Hyperdrive работает в режим транзакционного пулинга, где подключение удерживается на протяжении всей транзакции. Долгие транзакции, содержащие несколько запросов, могут быстрее исчерпать доступные подключения Hyperdrive, поскольку каждая транзакция удерживает подключение из пула до своего завершения.
См. Лимиты чтобы узнать, сколько соединений доступно для вашей конфигурации Hyperdrive в зависимости от вашего тарифного плана Workers.