springboot+pgbouncer+postgres数据库连接池集成方案及问题解决

news2024/11/13 9:12:12

期望通过每一次分享,让技术的门槛变低,落地更容易。 —— around

前言

旨在解决微服务项目全是连接池并影响数据库并发连接,作者的环境是基于sprongboot微服务连接postgres数据库,每个微服务的DAO层配置都使用了连接池技术。后续微服务太多,导致连接到一个数据库上默认创建的连接太多(整体数据库连接数 = 微服务数量 x 连接池默认创建连接数量),因此在连接池上做处理,统一迁移至数据库端,同时为以后升级数据集群管理工具准备。

编写文本的最大原因是网上关于pgbouncer的文章质量太差,于是个人记录一下踩坑情况与实际解决方案。

作者环境:centos7 + postgres14 + pgbouncer1.18 + springboot2.4.5

目录

    1. 安装pgbouncer
    1. 错误收集
    1. springboot连接pgbouncer

正文

1.安装pgbouncer

使用yum直接安装

yum install pgbouncer -y

安装完毕后注意看几个目录是否存在

/etc/pgbouncer/
/var/log/pgbouncer/

接着打开pgbouncer.ini文件进行配置修改,关注以下几个参数项,建议按本文直接设置

vi /etc/pgbouncer/pgbouncer.ini

====begin======
[databases]
postgres = host=127.0.0.1 port=5432 dbname=postgres

listen_addr = *
listen_port = 6432

# 如果你安装的postgres是低于14版本,则使用auth_type = md5,否则请按我的设置
auth_type = scram-sha-256
auth_file = /etc/pgbouncer/userlist.txt

# 管理账号
admin_users = postgres
stats_users = postgres

# 支持session、transaction、statement三种模式,不明白去搜索
pool_mode = transaction

server_reset_query = DISCARD ALL

# 是否忽略jdbc连接参数
ignore_startup_parameters = extra_float_digits

server_check_query = select 1

server_check_delay = 30

# 最大连接池数量
max_client_conn = 400

# 默认连接池数量
default_pool_size = 36

reserve_pool_size = 5

dns_max_ttl = 15

修改完毕后直接保存文件,接着不要着急启动,启动肯定直接失败,以下内容就是我启动后造成的错误日志

LOG  (nodb)/postgres@127.0.0.1:33082 closing because: password authentication failed (age=0s)
WARNING (nodb)/postgres@127.0.0.1:33082 pooler error: password authentication failed

下面接着配置连接池与postgres的信任连接,既然连接自然需要数据库账号密码了,按照上述的配置文件,用户应该是在/etc/pgbouncer/userlist.txt中,但你肯定找不到这个文件,它需要我们自己去创建,提供2个方法:

  • 使用pgbouncer脚本:
    cd /etc/pgbouncer到这个目录,找到mkauth.py文件,直接对这个文件执行命令即可(注:通过yum安装方式才有依赖环境)

    # 字符串引号部分,空格不要处理,填写的内容实际上就是访问你postgres数据库的属性,请参考自己的设置修改
    /etc/pgbouncer/mkauth.py  /etc/pgbouncer/userlist.txt  "host=127.0.0.1 dbname=postgres port=5432 user=postgres password=postgres"
    

    生成完毕后请检查一下自己在/etc/pgbouncer目录下的userlist.txt文件,该文件包含你postgres所有的账号信息,请调整一下该文件的内容,主要是处理空引号的问题

    vi /etc/pgbouncer/userlist.txt
    
    # old
    "postgres" "SCRAM-SHA-256$4096:St3x1cVA+cTJDsiGEnqjoA==" "" 
    
    # new
    "postgres" "SCRAM-SHA-256$4096:St3x1cVA+cTJDsiGEnqjoA=="
    

    最后请记得给该文件授权一下,避免后续缺权限无法使用。

    chmod -R 755 /etc/pgbouncer/userlist.txt
    
  • 使用postgres数据库表:
    在数据库安装的服务器上直接登录数据库

    # 请修改成自己的数据库访问地址和账号
    psql -p 5432 postgres -h 127.0.0.1 -U postgres
    
    # 登录后直接查询pg_shadow获取账号密码信息
    select usename, passwd from pg_shadow;
    

    对上述查到的数据库账号信息,自己直接复制出来,不需要全部复制,只复制自己希望暴露出来通过pgbouncer方式登录系统的账号。
    复制之后的数据直接按照下面的格式创建文件并存储账号密码信息

    vi /etc/pgbouncer/userlist.txt
    
    # 账号 密码
    "postgres" "SCRAM-SHA-256$4096:St3x1cVA+cTJDsiGEnqjoA=="
    
    

    最后请记得给该文件授权一下,避免后续缺权限无法使用。

    chmod -R 755 /etc/pgbouncer/userlist.txt
    

接着启动你的数据库吧,这里不能使用root启动,会导致pgbouncer启动失败。我们执行如下命令

 #  切换用户
su - pgbouncer

 # 启动
pgbouncer -d /etc/pgbouncer/pgbouncer.ini

启动完毕后查询pgbouncer状态systemctl status pgbouncer,如果显示为下图,表示成功。
在这里插入图片描述

如果如下图显示,则表示出现了问题,我们需要针对性检查问题,据具体问题详见第二章。
在这里插入图片描述

2.错误收集

  • FATAL PgBouncer should not run as root
    说明pgbouncer的启动用户是通过root账号启动的,使用yum安装的话,直接通过如下操作完成

    su - pgbouncer
    
    # 启动
    pgbouncer -d /etc/pgbouncer/pgbouncer.ini
    
  • ERROR could not open auth_file /etc/pgbouncer/userlist.txt: Permission denied
    说明当前pgbouncer的用户文件是没有权限读取的,请设置权限

    chmod -R 755 /etc/pgbouncer/userlist.txt
    
  • FATAL unix socket is in use, cannot continue
    说明pgbouncer重复启动了,需要关闭之前启动的(就算启动失败了),完成后再次启动

    # 查找进程
    ps -ef |grep pg
    
    # 找到正在启动的进程然后删除掉
    kill -9 pid
    
    # 上述不可用也能使用此方式
    kill `cat /var/run/pgbouncer/pgbouncer.pid`
    
  • closing because: unsupported startup parameter: extra_float_digits=2
    表示当前用户连接到pgbouncer携带的参数有问题,存在jdbc无法连接的问题,进入pgbouncer安装所在服务

    vi /etc/pgbouncer/pgbouncer.ini
    
    # 是否忽略jdbc连接参数
    ignore_startup_parameters = extra_float_digits
    
    # 修改完成后,记得重启pgbouncer,应该生效了
    
  • pooler error: unsupported startup parameter: search_path
    表示额外携带的参数内容有误,这时候建议去自己的代码项目上检查一下datasource连接了

    # 原始连接池
    url: jdbc:postgresql://ip:端口/数据库?currentSchema=public&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&stringtype=unspecified
    
    # 删除 currentSchema=public,添加prepareThreshold=0
    url: jdbc:postgresql://ip:端口/数据库?prepareThreshold=0&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&stringtype=unspecified
    

    完成后重启开发环境连接,继续去后台查看pgbouncer的实际log,输出为如下表示正常

    # /var/log/pgbouncer/pgbouncer.log
    LOG listening on 0.0.0.0:6432
    2023-02-27 13:59:45.696 CST [29731] LOG listening on [::]:6432
    2023-02-27 13:59:45.696 CST [29731] LOG listening on unix:/tmp/.s.PGSQL.6432
    
  • ERROR: No such user: postgres
    表示进行登录到sql界面的账号不存在,需要检查postgresql数据库是否有这个账号且是生效状态

  • psql: error: connection to server at “127.0.0.1”, port 6432 failed: FATAL: SASL authentication failed
    表示进行登录到sql界面的账号密码错误,需要检查postgresql数据库对应账号的真实密码

3.springboot连接pgbouncer

请先保证/etc/pgbouncer/pgbouncer.inilisten_addr能够接到你的ip访问,如果不清楚先给listen_addr = *,以后清楚了再调。

listen_addr = *

接着直接在springboot项目的yml文件中修改之前的连接池配置,同时调整datasource配置如下

spring:
  datasource:
    # 例子:jdbc:postgresql://192.168.100.10:6432/postgres?prepareThreshold=0&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&stringtype=unspecified
    url: jdbc:postgresql://pgbouncer-ip:pgbouncer端口/数据库?prepareThreshold=0
    driverClassName: org.postgresql.Driver
    username: postgres(pgbouncer中数据库对应的用户名)
    password: postgres(pgbouncer中数据库对应的密码)

最后

本文仅提供关于pgbouncer相关介绍与问题处理方式,为后续切换posgresql集群和双master方案做准备,预计后续发布Bucardo与Slony-l的方案。

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

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

相关文章

一个线程两次调用start()方法会出现什么情况?

第17讲 | 一个线程两次调用start()方法会出现什么情况? 今天我们来深入聊聊线程,相信大家对于线程这个概念都不陌生,它是 Java 并发的基础元素,理解、操纵、诊断线程是 Java 工程师的必修课,但是你真的掌握线程了吗&am…

如何编程实现从多数据库操作数据

对于数据量很大的复杂系统,有时候会采用分库或者分表的减轻单台数据库服务器压力,截止目前有一些工具直接支持读写分离等,例如ShardingSphere,如果不采用工具框架,从编码出发,如何实现从多个数据库读写数据…

FFmpeg 中的多线程解码

1.共享变量的互斥互斥锁(mutex-lock)是一种信号量,用来防止两个线程在同一时刻访问相同的共享资源,它有锁定状态和非锁定状态。在任意时刻,一个线程要想存取共享数据,线程必须首先获得mutex-lock&#xff0…

一种全新的图像变换理论的实验(四)——研究目的替代DCT和小波

一、前言 2023年02月28日凌晨1点 以前我定义为这个算法是滤波算法,实则上应该算是一种新变换算法,比如傅里叶变换(FFT)、离散余弦变换(DCT),以及小波变换。所以就把所有的标题改变了一下。 本次…

MySQL的InnoDB 三种行锁,SQL 语句加了哪些锁?

InnoDB 三种行锁: Record Lock(记录锁):锁住某一行记录 Gap Lock(间隙锁):锁住一段左开右开的区间 Next-key Lock(临键锁):锁住一段左开右闭的区间 哪些语句…

前端面试题 —— HTML

目录 一、src 和 href 的区别 二、对 HTML 语义化的理解 三、DOCTYPE(⽂档类型) 的作⽤ 四、script 标签中 defer 和 async 的区别 五、常⽤的 meta 标签有哪些? 六、HTML5 有哪些更新 八、行内元素有哪些?块级元素有哪些? 空(void)元素…

【正点原子FPGA连载】第十九章FreeRtos Hello World实验 摘自【正点原子】DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南

1)实验平台:正点原子MPSoC开发板 2)平台购买地址:https://detail.tmall.com/item.htm?id692450874670 3)全套实验源码手册视频下载地址: http://www.openedv.com/thread-340252-1-1.html 第十九章FreeRto…

项目调研丨以太坊再质押项目EigenLayer白皮书四大看点(内附完整版中文白皮书)

北京时间2月21日下午,被众多一线投研机构视为2023年以太坊最重要的创新,有可能开启以太坊新叙事方向的项目Eigenlayer终于披露了其第一版白皮书。EigenLayer是以太坊的再质押集,允许共识层ETH质押者选择验证构建在以太坊生态系统之上的新软件…

第七节 面向对象

面向对象 1.类和对象是什么? )类:是共同特征的描述(设计图);对象:是真实存在的具体实例。 2.如何设计类? public class 类名 { 1、成员变量(代表属性的,一般是名词) 2、成员方法(代表行为的,一般是动词) 3.如何创建对象? 类名对象名new 类名(); 4.拿到对象后怎么…

ubuntu 编译安装支持CUDA的OpenCV

安装须知 cuda支持 在安装完“ linux CUDAtoolkitcudnntensorrt 的安装”之后进行支持cuda的opencv安装 否则报错:CMake Error at modules/dnn/CMakeLists.txt:41 (message): DNN: CUDA backend requires CUDA Toolkit. Please resolve dependency or disable OPE…

Ubuntu 安装指定版本 Mysql,并设置远程连接(以安装mysql 5.5 为例)

目录 一、安装Mysql 1、卸载Mysql(可跳过) 2、安装mysql 软件源 3、安装mysql 5.5 4、验证测试 二、设置远程登录 1、允许使用root账号远程连接 2、Mysql 允许远程登录 一、安装Mysql 1、卸载Mysql(可跳过) 如果之前安装…

数据结构六大排序

1.插入排序 1.插入排序 思路: 从第一个元素开始认为是有序的,去一个元素tem从有序序列从后往前扫描,如果该元素大于tem,将该元素一刀下一位,循环步骤3知道找到有序序列中小于等于的元素将tem插入到该元素后&#xff0…

卡特兰数

文章目录1、简介1.1 何为卡特兰数1.2 卡特兰数的通项公式2、应用2.1 题目1:括号合法题目描述思路分析2.2 题目2:进出栈的方式2.2.1 题目描述2.2.2 思路分析2.3 题目3:合法的序列2.3.1 题目描述2.3.2 思路分析2.3.3 代码实现2.4 题目4&#xf…

分布式ID生成系统

目录背景常用分布式ID生成系统介绍UUIDSnowflake背景 在大多数复杂的分布式系统中,往往需要对大量的数据和消息进行唯一标识。而对分布式系统后台数据库的分库分表后需要有一个唯一的ID来表示一条数据或者是消息。那么我们分布式系统ID一般都有哪些需求呢&#xff1…

IP地址、主机名、域名解析(DNS)

1.什么是IP地址 每一台联网的电脑都会有一个地址,用于和其他计算机进行通讯 IP地址主要有两个版本:v4 v6 IPV4版本的地址格式名为:a.b.c.d,其中abcd表示0-225的数字,如192.168.88.10为一个标准地址 查看IP地址&#x…

Android 蓝牙开发——HCI log 分析(二十)

HCI log 是用来分析蓝牙设备之间的交互行为是否符合预期,是否符合蓝牙规范。对于蓝牙开发者来说,通过 HCI log 可以帮助我们更好地分析问题,理解蓝牙协议。 一、抓取HCI log 1、手机抓取HCI log 在开发者选项中打开启用蓝牙HCI信息收集日志开关,Android系统就开始自动地收…

计算机SCI论文选题和投稿需要注意什么? - 易智编译EaseEditing

科研创新与选题 科研创新是至关重要的,往往关系到论文是否顺利发表。 摆在我们面前的,往往是别人挑剩下的资料,似乎毫无写作价值,很多人便知难而退,干脆不写论文了。 其实,应该问问自已“我有什么&#xf…

Flask应用的基本组成部分、模板引擎Jinja2的使用、Flask-WTF、SQLAlchemy

目录标题1. Flask应用的基本组成部分1.1 路由(Routing)1.2 视图函数(View Function)1.3 请求(Request)1.4 响应(Response)2. 模板引擎Jinja2的使用2.1 入门案例2.2 条件判断2.3 循环…

Python采集m3u8格式做个小姐姐动态壁纸~

人生苦短,我用python 首先,我和大家一样喜欢看小姐姐~ 其次,看美丽的事物会让人更加有动力去… 我编不下去了哈哈哈,我就是爱看充满美感的人儿~ 更多python好看的:点击此处跳转文末名片获取 环境 Pythonpycharm 模块使用 第…

使用virtualenv和pip构建项目所需的独立Python环境

1、为什么需要独立的Python环境?在讲技术前,想先讲讲目的。为什么我们需要独立的Python环境?这里就借用virtualenv的文档来解释吧。virtualenv is a tool to create isolated Python environments.The basic problem being addressed is one …