服务抽象

服务的定义、类型与配置方式。

服务是集群能力的命名抽象,通过 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 端口暴露。