在 Dokploy 中为 PostgreSQL 搭建 PgBouncer 数据库连接池(图文)

前言:为什么你需要一个连接池?

如果你正在使用 Node.js (尤其是像 Next.js 这样的框架) 配合 Prisma 操作 PostgreSQL 数据库,你很可能在某个阶段会遇到那个令人头疼的错误:“Error: Too many clients already”。这通常发生在应用并发量上升,或者在 Next.js 的构建 (next build) 阶段,因为它会尝试并行渲染多个页面,瞬间创建大量数据库连接。

虽然最直接的反应是增加 PostgreSQL 的 max_connections,但这只是一个临时的“创可贴”,它会消耗更多宝贵的服务器内存,并且无法从根本上解决连接风暴的问题。

一个更专业、更具扩展性的解决方案是在你的应用和数据库之间引入一个中间件——连接池工具PgBouncer 正是此领域的王者,它轻量、高效,能以极小的资源消耗管理成千上万的连接。

本指南将详细记录我们如何在 Dokploy 平台上,为一个正在运行的 PostgreSQL 数据库和一个需要进行静态站点生成 (SSG) 的 Next.js 应用,成功搭建并配置 PgBouncer 服务。我们将这个过程中的每一步、遇到的每一个坑、以及最终的解决方案都毫无保留地分享出来。

核心架构:我们要做什么?

我们的目标非常明确:将应用架构从“直连”模式升级为通过 PgBouncer 连接池管理的“中间人”模式。

部署前架构 (直连模式):

[Next.js App] —> [PostgreSQL Database]

  • 问题: 应用的每一次数据库操作都可能创建一个新的连接,在高并发或构建时极易耗尽数据库资源。

部署后架构 (连接池模式):

[Next.js App] —> [PgBouncer Pooler] —> [PostgreSQL Database]

  • 优势: Next.js 应用将所有连接请求都发送给 PgBouncer。PgBouncer 维护一个与 PostgreSQL 之间的小而稳定的连接池,高效地复用这些连接来处理大量请求。数据库本身将得到极大的保护。

Step 1: 创建 PgBouncer 服务骨架

我们的第一步是在 Dokploy 中创建一个新的应用,用于承载 PgBouncer。

  1. 在 Dokploy 仪表盘,点击 “Add new” -> “Application”。
  2. 在 “Provider” 部分,选择 Docker 作为来源。
  3. Docker Image 输入框中,填入镜像名称:edoburu/pgbouncer
  4. 此时先不要部署,直接进入下一步配置。
    在这里插入图片描述

Step 2: 暴露所需端口

为了让服务之间可以通过网络互相访问,我们需要将 PostgreSQL 和 PgBouncer 的端口都映射到宿主机上。

  1. 暴露 PostgreSQL 端口:

    • 进入你的 PostgreSQL 数据库服务的配置页面。
    • 导航到 Advanced -> Ports
    • 添加一条规则,将数据库的真实端口(例如 5633)映射出来。
      • Published Port: 5633
      • Published Port Mode: Host
      • Target Port: 5633
    • 保存并 Redeploy PostgreSQL 服务。
  2. 暴露 PgBouncer 端口:

    • 回到我们刚刚创建的 PgBouncer 服务的配置页面。
    • 导航到 Advanced -> Ports
    • 添加一条规则,将 PgBouncer 的监听端口 6432 映射出来。
      • Published Port: 6432
      • Published Port Mode: Host
      • Target Port: 6432
    • 保存设置。

[图片占位符:Dokploy 中为 PgBouncer 服务配置端口映射的弹窗界面]
在这里插入图片描述

Step 3: 准备并挂载 PgBouncer 配置文件

现在,我们需要为 PgBouncer 提供它的“灵魂”——配置文件。

1. 在本地准备配置文件

在这里插入图片描述
在这里插入图片描述

  • pgbouncer.ini (主配置文件): 创建一个文本文件,填入以下内容。

    [databases]
    # 定义数据库连接。这里的 key (YOUR_DATABASE_NAME) 最好和真实的 dbname 保持一致。
    # host 设置为你的服务器公网IP,port 设置为你的 PostgreSQL 真实端口。
    YOUR_DATABASE_NAME = host=YOUR_SERVER_PUBLIC_IP port=YOUR_POSTGRES_PORT dbname=YOUR_DATABASE_NAME[pgbouncer]
    # 监听所有网络接口,允许来自 Docker 外部和内部的连接
    listen_addr = *
    # PgBouncer 自身的监听端口,给 Next.js 应用连接
    listen_port = 6432# 认证方式必须是 md5,并且需要指定用户列表文件
    auth_type = md5
    auth_file = /etc/pgbouncer/userlist.txt# 定义哪些用户拥有管理和查看统计的权限
    admin_users = YOUR_DATABASE_USERNAME
    stats_users = YOUR_DATABASE_USERNAME# 连接池模式。transaction 是对大多数应用最安全、最推荐的模式
    pool_mode = transaction# 池大小等性能配置
    default_pool_size = 20
    max_client_conn = 1000# pgbouncer 进程的 pid 文件路径
    pidfile = /var/run/pgbouncer/pgbouncer.pid
    
  • userlist.txt (认证文件): 创建第二个文本文件,定义允许连接的用户名和密码。

    # 格式: "用户名" "密码"
    # 必须使用英文双引号将用户名和密码括起来,中间用一个空格隔开。
    "YOUR_DATABASE_USERNAME" "YOUR_DATABASE_PASSWORD"
    
2. 在 Dokploy 中挂载配置文件
  • 回到 PgBouncer 服务Advanced -> Volumes 设置区域。
  • 添加两个 File Mount 类型的挂载:
    • 第一个: 将 pgbouncer.ini全部内容粘贴进去,Mount Path 设置为 /etc/pgbouncer/pgbouncer.ini
    • 第二个: 将 userlist.txt全部内容粘贴进去,Mount Path 设置为 /etc/pgbouncer/userlist.txt

Step 4: 配置启动命令并部署 PgBouncer

  1. PgBouncer 服务Advanced -> Run Command 区域,明确告诉容器如何启动。
    • Command: pgbouncer /etc/pgbouncer/pgbouncer.ini
  2. 完成所有配置后,点击页面右上角的 Deploy 按钮部署 PgBouncer 服务。
  3. 检查 PgBouncer 的日志,确保它已正常启动,并且没有 broken auth fileconnect failed 等错误。

在这里插入图片描述
最后回到 General 中点击 Deploy 就可以部署成功了:

在这里插入图片描述

Step 5: 更新 Next.js 应用配置(决胜一步)

现在 PgBouncer 服务已经通过公网 IP 和指定端口(6432)完全就绪,我们可以直接让 Next.js 应用连接这个公开的地址。这个方法可以同时解决构建和运行时的连接问题。

  1. 进入你的 Next.js 应用在 Dokploy 的配置页面。

  2. 导航到 Environment 标签页。

  3. 找到 DATABASE_URL 这个环境变量(如果没有就新建一个)。

  4. 将其值设置为指向 PgBouncer 的公网地址

    postgresql://YOUR_DATABASE_USERNAME:YOUR_DATABASE_PASSWORD@YOUR_SERVER_PUBLIC_IP:6432/YOUR_DATABASE_NAME?pgbouncer=true
    

    重要: 请确保这里的 YOUR_SERVER_PUBLIC_IP 是您服务器的公网 IP,端口是 PgBouncer 的端口 6432

[图片占位符:Next.js 应用中配置 DATABASE_URL 环境变量的截图]

  1. 确认构建命令为默认值:在 “General” 标签页,确保 “Build Command” 是简单的 pnpm run buildnpm run build,不带任何 DATABASE_URL= 的前缀。
  2. 保存所有修改,然后点击 Deploy 部署你的 Next.js 应用。
  3. ?pgbouncer=true 是一个专门的 “兼容模式”开关,你用它来明确地告知 Prisma:“注意,你现在连接的不是一个真正的 PostgreSQL 数据库,而是一个 PgBouncer 连接池!请调整你的行为模式。”

总结

恭喜你!如果一切顺利,你的应用现在应该已经成功构建并运行起来了。

通过这次实践,我们不仅解决了一个棘手的数据库连接问题,还掌握了在类 PaaS 平台(如 Dokploy)上进行复杂服务编排的关键技能。我们学会了如何:

  • 使用 PgBouncer 管理连接池。
  • 通过端口映射和服务名进行服务间通信。
  • 利用文件挂载注入自定义配置。
  • 通过统一使用公网地址,快速解决在 CI/CD 流程中访问数据库的难题。

现在,你的应用架构变得更加健壮、高效且具备弹性,能够从容应对未来的流量挑战。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/89982.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/89982.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Mac获取终端历史

在 macOS 中,历史记录文件的位置取决于你使用的 shell。以下是针对不同 shell 的历史记录文件的默认位置:对于 Bash 用户: 历史记录文件通常位于 ~/.bash_history。对于 Zsh 用户(macOS Catalina及以后版本默认使用的shell&#x…

高频交易服务器篇

在 Binance 进行高频交易(HFT)时,服务器的低延迟、高稳定性和快速网络是关键。亚马逊云(AWS) 提供了多种适合高频交易的方案,以下是推荐的配置和优化策略:1. 选择 AWS 区域(Region&a…

MVC与MVVM架构模式详解:原理、区别与JavaScript实现

Hi,我是布兰妮甜 !在当今复杂的前端开发领域,如何组织代码结构一直是开发者面临的核心挑战。MVC和MVVM作为两种经典的架构模式,为前端应用提供了清晰的责任划分和可维护的代码组织方案。本文将深入探讨这两种模式的原理、实现差异…

从小白到进阶:解锁linux与c语言高级编程知识点嵌入式开发的任督二脉(2)

【硬核揭秘】Linux与C高级编程:从入门到精通,你的全栈之路! 第三部分:Shell脚本编程——自动化你的Linux世界,让效率飞起来! 嘿,各位C语言的“卷王”们! 在Linux的世界里&#xf…

锁和事务的关系

事务的4大特性(ACID) 原子性(Atomicity):事务被视为一个单一的、不可分割的工作单元一致性(Consistency):事务执行前后,数据库从一个一致状态转变为另一个一致状态,并且强制执行所有…

电动车信用免押小程序免押租赁小程序php方案

电动车信用免押租赁小程序,免押租小程序,信用免押接口申请、对接开发,可源码搭建,可二开或定制。开发语言后端php,前端uniapp。可二开定制 在线选择门店,选择车辆类型,选择租赁方式&#xff08…

机器学习在智能安防中的应用:视频监控与异常行为检测

随着人工智能技术的飞速发展,智能安防领域正经历着一场深刻的变革。智能安防通过整合先进的信息技术,如物联网(IoT)、大数据和机器学习,能够实现从传统的被动防御到主动预防的转变。机器学习技术在智能安防中的应用尤为…

MySQL中DROP、DELETE与TRUNCATE的深度解析

在MySQL数据库操作中,DROP、DELETE和TRUNCATE是三个常用的数据操作命令,它们都可以用于删除数据,但在功能、执行效率、事务处理以及对表结构的影响等方面存在显著差异。本文将从多个维度对这三个命令进行详细对比和解析,帮助读者更…

一条 SQL 语句的内部执行流程详解(MySQL为例)

当执行如下 SQL: SELECT * FROM users WHERE id 1;在数据库内部,其实会经历多个复杂且有序的阶段。以下是 MySQL(InnoDB 引擎)中 SQL 查询语句从发送到结果返回的完整执行流程。 客户端连接阶段 客户端(如 JDBC、My…

超详细yolo8/11-detect目标检测全流程概述:配置环境、数据标注、训练、验证/预测、onnx部署(c++/python)详解

文章目录 一、配置环境二、数据标注三、模型训练四、验证预测五、onnx部署c 版python版本 一、配置环境 我的都是在Linux系统下,训练部署的;模型训练之前,需要配置好环境,Anaconda、显卡驱动、cuda、cudnn、pytorch等&#xff1b…

阿里云Flink:开启大数据实时处理新时代

走进阿里云 Flink 在大数据处理的广袤领域中,阿里云 Flink 犹如一颗璀璨的明星,占据着举足轻重的地位。随着数据量呈指数级增长,企业对数据处理的实时性、高效性和准确性提出了前所未有的挑战 。传统的数据处理方式逐渐难以满足这些严苛的需…

【Linux】基础开发工具(1)

1. 软件包管理器 1.1 什么是软件包 在Linux下安装软件, ⼀个常用的办法是下载到程序的源代码, 并进行编译, 得到可执行程序. 但是这样太麻烦了, 于是有些人把⼀些常⽤的软件提前编译好, 做成软件包(可以理解成windows上 的安装程序)放在⼀个服务器上, 通过包管理器可以很⽅便…

蓝桥杯51单片机设计

#超声波原理# ①超声波测距原理:声波反射原理 声波分类: 超声波测距原理 超声波频率越高,波长越短,反身性越强,衍射性越弱 ②超声波模块原理 发射原理 跳线帽 接收原理 问题: 1.超声波发射模块需…

【LeetCode 热题 100】240. 搜索二维矩阵 II——排除法

Problem: 240. 搜索二维矩阵 II 编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target 。该矩阵具有以下特性: 每行的元素从左到右升序排列。 每列的元素从上到下升序排列。 文章目录 整体思路完整代码时空复杂度时间复杂度:O(M N)空间复…

Android Input 系列专题【inputflinger事件的读取与分发】

Android输入系统在native中的核心工作就是,从Linux驱动设备节点中读取事件,然后将这个事件进行分发,这两项工作分别交给了InputReader和InputDispatcher来做。 他们的源码都属于native层inputflinger里面的一部分,如下架构&#…

【大模型LLM】GPU计算效率评估指标与优化方法:吞吐率

GPU计算效率评估指标与优化方法:吞吐率 一、核心效率指标二、大模型吞吐率(Large Model Throughput)三、关键性能瓶颈分析四、实际测量工具五、优化策略总结 一、核心效率指标 吞吐率(Throughput) 定义:单位…

Nestjs框架: 集成 Prisma

概述 在 NestJS 的官方文档中,有两处对数据库进行了介绍 第一处位于左侧“Techniques(技术)”部分下的“数据库”板块,中文文档里同样有这个位置。 Database 第二处是下面的“Recipes (秘籍)”板块,这里有多个部分都与…

CppCon 2018 学习:What Do We Mean When We Say Nothing At All?

提供的内容深入探讨了C编程中的一些关键概念,特别是如何编写清晰、易维护的代码,并展示了一些C17的新特性。我将对这些内容做中文的解释和总结。 1. 良好的代码设计原则 什么是“良好的代码”? 能工作:代码实现了预期功能。能在…

C语言中的输入输出函数:构建程序交互的基石

在C语言的世界里,输入输出(I/O)操作是程序与用户或外部数据源进行交互的基本方式。无论是从键盘接收用户输入,还是将处理结果显示到屏幕上,亦或是读写文件,都离不开C语言提供的输入输出函数。本文将深入探讨…

高速信号眼图

横轴体系时域的抖动大小;纵轴体现电压的噪声。 噪声越大,眼高越小。 抖动越大,眼宽越窄。 眼图的模板是定义好的最大jitter和噪声的模板范围。就是信号的不可触碰区域。信号波形不能够触碰到模板或者进行模板中。也就是眼图中的线轨迹要在眼…