服务抽象
服务的定义、类型与配置方式。
服务是集群能力的命名抽象,通过 HAProxy 端口对外暴露,实现流量路由与负载均衡。
服务定义
什么是服务
服务(Service)是对数据库访问能力的抽象:
- 命名:通过名称标识,如
pg-test-primary - 端口:通过端口区分,如
:5433 - 路由:根据规则将流量路由到目标实例
- 封装:隐藏底层集群的复杂性
服务的价值
传统方式: 服务方式:
客户端 → IP:Port → 单个实例 客户端 → 服务 → 多个实例
↓
自动选择健康实例
故障自动切换
读写自动分离
默认服务类型
primary 服务
读写服务,将流量路由到主库。
┌─────────────────────────────────────────────────────────────┐
│ pg-test-primary (:5433) │
│ │
│ 客户端 → HAProxy:5433 │
│ │ │
│ ▼ (健康检查: 是否为主库) │
│ Pgbouncer:6432 │
│ │ │
│ ▼ │
│ PostgreSQL:5432 (Primary) │
└─────────────────────────────────────────────────────────────┘
特点:
- 有且仅有一个目标(主库)
- 通过 Patroni 健康检查确定主库
- 经过 Pgbouncer 连接池
replica 服务
只读服务,将流量路由到从库。
┌─────────────────────────────────────────────────────────────┐
│ pg-test-replica (:5434) │
│ │
│ 客户端 → HAProxy:5434 │
│ │ │
│ ▼ (健康检查: 是否为从库) │
│ ┌──────┴──────┐ │
│ ▼ ▼ │
│ Pgbouncer:6432 Pgbouncer:6432 │
│ │ │ │
│ ▼ ▼ │
│ PostgreSQL PostgreSQL │
│ (Replica 1) (Replica 2) │
└─────────────────────────────────────────────────────────────┘
特点:
- 可有多个目标(所有从库)
- 轮询负载均衡
- 无从库时可回落到主库
default 服务
直连服务,绕过连接池直接访问主库。
┌─────────────────────────────────────────────────────────────┐
│ pg-test-default (:5436) │
│ │
│ 客户端 → HAProxy:5436 │
│ │ │
│ ▼ (绕过 Pgbouncer) │
│ PostgreSQL:5432 (Primary) │
└─────────────────────────────────────────────────────────────┘
用途:
- DDL 操作
- 管理维护
- 需要持久连接的场景
offline 服务
离线服务,访问不承载在线流量的实例。
┌─────────────────────────────────────────────────────────────┐
│ pg-test-offline (:5438) │
│ │
│ 客户端 → HAProxy:5438 │
│ │ │
│ ▼ (选择 offline 角色或 pg_offline_query=true) │
│ PostgreSQL:5432 (Offline) │
└─────────────────────────────────────────────────────────────┘
用途:
- ETL 抽取
- 分析查询
- 报表生成
服务配置
默认服务定义
pg_default_services:
- name: primary
port: 5433
dest: primary
check: /primary
selector: "[]"
haproxy:
maxconn: 3000
balance: roundrobin
options:
- option httpchk
- option http-keep-alive
- name: replica
port: 5434
dest: replica
check: /replica
selector: "[]"
backup: "[? pg_role == `primary`]"
- name: default
port: 5436
dest: postgres
check: /primary
selector: "[]"
- name: offline
port: 5438
dest: offline
check: /replica
selector: "[? pg_role == `offline` || pg_offline_query ]"
自定义服务
pg_services:
- name: standby
port: 5435
dest: replica
check: /sync # 只路由到同步从库
selector: "[? pg_role == `replica` && sync_state == `sync` ]"
- name: delayed
port: 5439
dest: postgres
check: /replica
selector: "[? pg_role == `delayed` ]"
服务参数
| 参数 | 说明 | 示例 |
|---|---|---|
name |
服务名后缀 | primary |
port |
服务端口 | 5433 |
dest |
目标类型 | primary, replica, postgres, offline |
check |
健康检查路径 | /primary, /replica |
selector |
实例选择器 | JMESPath 表达式 |
backup |
备份实例选择器 | JMESPath 表达式 |
健康检查
HAProxy 通过 Patroni REST API 进行健康检查:
| 端点 | 说明 | 响应 |
|---|---|---|
/primary |
是否为主库 | 200/503 |
/replica |
是否为从库 | 200/503 |
/sync |
是否为同步从库 | 200/503 |
/async |
是否为异步从库 | 200/503 |
/health |
实例是否健康 | 200/503 |
HAProxy → GET http://patroni:8008/primary
← 200 OK (是主库,可接收流量)
← 503 Service Unavailable (不是主库)
服务发现
服务信息自动注册到监控系统:
# /etc/prometheus/targets/pgsql.yml
- labels:
cls: pg-test
ins: pg-test-1
targets:
- 10.10.10.11:9630 # pg_exporter
- 10.10.10.11:9631 # pgbouncer_exporter
- 10.10.10.11:8008 # patroni
HAProxy 统计信息通过 9101 端口暴露。