在云原生架构中,数据库路由器是实现读写分离、连接路由和多源数据整合的关键组件。Azure 生态并未提供一个名为"Database Router"的独立服务,而是需要根据数据库类型和场景组合不同的原生功能与开源中间件。本文系统梳理了在 Azure SQL Database、Azure Database for MySQL 和 PostgreSQL 上实现读写分离的路由方案,并深入探讨了如何利用 Apache ShardingSphere-Proxy 构建统一的异构数据库接入层,将 Oracle、MySQL、SQL Server、PostgreSQL 等多种数据源整合为一个逻辑入口。
在 Azure 上构建数据库路由器并非单一服务的开箱即用,而是需要根据数据库类型和业务需求精准组合工具。对于同构的读写分离,Azure SQL 的内置只读路由最为简便,Azure MySQL 和 PostgreSQL 则可借助 MySQL Router 和 Pgpool-II 以低成本实现。当需求演化为融合 Oracle、SQL Server、MySQL、PostgreSQL 等多种数据库的统一接入时,Apache ShardingSphere-Proxy 展现出极强的适配能力,它可以将异构数据源抽象为逻辑表,并在 Azure 云原生环境中轻松实现高可用和安全加固。无论选择何种方案,遵循网络隔离、强制 TLS、连接池优化和可观测性等原则,都是保障生产稳定性的基石。
文章给出了详细的配置示例、部署架构和涵盖安全、高可用、可观测性的最佳实践,为在 Azure 上设计企业级数据路由层提供完整参考。
1. 引言
现代应用架构中,数据库层的弹性与扩展能力直接决定了整个系统的吞吐量和可靠性。数据库路由器的职责在于透明地分发数据库流量:将写操作指向主节点,将读查询分发到只读副本,甚至在多种异构数据库之间进行智能路由。在 Azure 上,实现这些能力的方式取决于所使用的数据库服务类型------从 Azure SQL 内置的只读副本期扩展到需要自行托管 MySQL Router、Pgpool-II,再到可跨多种数据库的 ShardingSphere-Proxy。本文将分两部分展开:第一部分介绍 Azure 第一方数据库服务的读写分离路由实现,第二部分聚焦于跨异构数据库的统一路由整合,并辅以可落地的配置案例和最佳实践。
2. Azure 数据库的读写分离路由
2.1 Azure SQL 数据库:内置只读路由
Azure SQL 数据库(单数据库和弹性池)提供原生的读取横向扩展 功能,无需部署任何额外组件即可将只读流量自动路由到高可用的只读副本。其原理基于连接字符串中的 ApplicationIntent 属性。
配置与使用
-
在 Azure 门户中,进入数据库的"计算与存储"边栏,将"读取横向扩展"设置为"已启用"。
-
应用程序使用两套连接池:一套用于读写,一套用于只读。
-
读写连接字符串不带
ApplicationIntent或明确设置为ReadWrite:Server=tcp:my-server.database.windows.net,1433;Database=SalesDB;User ID=admin;Password=xxx; -
只读连接字符串添加
ApplicationIntent=ReadOnly:Server=tcp:my-server.database.windows.net,1433;Database=SalesDB;User ID=admin;Password=xxx;ApplicationIntent=ReadOnly;Azure 网关会自动将此类连接路由到当前可用的只读副本。
推荐配置
- 为读写和只读分别配置连接池(如 HikariCP),避免互相影响。
- 使用 Azure AD 托管标识进行身份验证,消除静态密码。
- 对于延迟敏感型应用,将只读副本与主副本部署在同一区域;若需灾备,配合自动故障转移组使用。
最佳实践
- 严格区分流量:报表、查询和历史数据读取使用只读端点,写操作必须使用读写端点。
- 通过动态管理视图
sys.dm_database_replica_states监控副本延迟,若延迟超过业务容忍阈值,可暂时将部分查询切换回主副本。 - 启用审计和 Azure Monitor 告警,跟踪只读副本的健康状况和连接数。
2.2 Azure Database for MySQL:使用 MySQL Router
Azure Database for MySQL 灵活服务器支持最多 10 个只读副本,但本身不提供自动读写分离路由。此时可以在 Azure 虚拟网络中部署 MySQL Router,由它来充当连接代理。
架构与部署
将 MySQL Router 部署在应用所在的 VNet 中的 Ubuntu VM 或 AKS 容器内,通过 Private Link 连接 MySQL 主服务器和副本。
配置示例 (/etc/mysqlrouter/mysqlrouter.conf)
ini
[routing:primary]
bind_address = 0.0.0.0:6446
destinations = my-primary.mysql.database.azure.com:3306
routing_strategy = first-available
[routing:x_ro]
bind_address = 0.0.0.0:6447
destinations = replica1.mysql.database.azure.com:3306,replica2.mysql.database.azure.com:3306
routing_strategy = round-robin
启动 Router:mysqlrouter --config /etc/mysqlrouter/mysqlrouter.conf
应用写操作连接 6446 端口,读操作连接 6447 端口。
推荐配置
- TLS 强制 :在 Azure MySQL 服务器上强制 SSL,Router 端配置
client_ssl_mode=PASSTHROUGH或指定 CA 证书路径。 - 高可用 Router 集群:至少部署两个 Router 实例,前端通过 Azure 内部负载均衡器提供浮动 IP,避免单点故障。
- 路由策略 :默认轮询,可根据负载情况改为
least-connections。
最佳实践
- 将 Router 与应用部署在同一 VNet,完全避免公网暴露。
- 编写健康检查脚本,定期探测
destinations中副本的状态,自动剔除故障节点;虽然 MySQL Router 可配合 InnoDB Cluster 动态发现拓扑,但 Azure 托管副本需手动维护列表,建议通过定时任务从 Azure CLI 获取副本列表并更新配置。 - 设置
max_connect_errors和连接超时,防止雪崩。
2.3 Azure Database for PostgreSQL:使用 Pgpool-II
Azure Database for PostgreSQL 灵活服务器同样提供只读副本,但原生的读写分离需要依靠连接池/负载均衡中间件。Pgpool-II 是常用的选择,兼具连接池、读写分离和负载均衡能力。
配置与使用
在 Azure VM 上安装 Pgpool-II,配置 pgpool.conf:
backend_hostname0 = 'pg-primary.postgres.database.azure.com'
backend_port0 = 5432
backend_weight0 = 1
backend_flag0 = 'ALWAYS_PRIMARY|DISALLOW_TO_FAILOVER'
backend_hostname1 = 'pg-replica.postgres.database.azure.com'
backend_port1 = 5432
backend_weight1 = 1
backend_flag1 = 'DISALLOW_TO_FAILOVER'
load_balance_mode = on
statement_level_load_balance = on
应用统一连接 Pgpool 的 5432 端口,Pgpool 会解析 SQL 语句类型,将 SELECT 分发到副本,写操作发往主节点。
推荐配置
- 开启
sr_check以监控流复制延迟,设置delay_threshold自动排除延迟过高的副本。 - 为每个后端配置合理的
max_pool大小,避免撑满 Azure 的连接限制。 - 配合 PgBouncer 使用可以获得更好的连接复用效果,但需注意架构复杂度。
最佳实践
- 网络隔离:Pgpool 通过 Private Endpoint 连接数据库,应用通过 VNet 内部 IP 访问 Pgpool。
- 使用
/*NO LOAD BALANCE*/注释强制部分查询走主节点,避免复制延迟造成的数据不一致。 - 启用 TLS 并验证证书,Pgpool 支持
ssl = on及相关参数。
3. 跨数据库类型的统一路由器:ShardingSphere-Proxy 异构整合
上述方案均为同构数据库的读写分离。当企业需要从同一入口连接 Oracle、MySQL、SQL Server、PostgreSQL 等多种数据库时,必须引入能够解析和代理多种数据库协议的数据路由中间件。Apache ShardingSphere-Proxy 是当前在 Azure 上实现此目标的最成熟开源方案。
3.1 场景与选型
典型需求:遗留系统使用 Oracle,新业务分别采用 Azure SQL Database、Azure Database for MySQL 和 PostgreSQL,应用不希望维护多个数据库连接和驱动,期望通过单一 SQL 入口操作所有数据,甚至能进行跨库查询(有限度)。
选型理由:
- 多数据库支持:ShardingSphere-Proxy 支持 MySQL、PostgreSQL、SQL Server、Oracle 等作为后端存储。
- 协议适配:对外可暴露为 MySQL 或 PostgreSQL 协议,应用只需使用一种驱动。
- 透明路由:通过 YAML 或 DistSQL 定义逻辑表与实际数据节点的映射关系,支持分片、读写分离、加密等治理能力。
- 云原生友好:可容器化部署在 Azure Kubernetes Service (AKS) 或虚拟机,便于扩展。
3.2 统一接入架构
[ App Cluster ]
| (MySQL 协议 :3307)
[ Azure Internal LB ]
|
[ ShardingSphere-Proxy Pod-1, Pod-2, ... ]
|
├── JDBC/SSL ── Oracle on Azure VM (Private IP)
├── JDBC/SSL ── Azure SQL Database (Private Link)
├── JDBC/SSL ── Azure Database for MySQL (Private Link)
└── JDBC/SSL ── Azure Database for PostgreSQL (Private Link)
应用只需连接负载均衡器的 IP 和端口,Proxy 根据预配置的规则将 SQL 分发到正确的物理库。
3.3 部署与配置实例
部署方式:推荐在 AKS 中以 Deployment 方式运行 ShardingSphere-Proxy 容器。
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: shardingsphere-proxy
spec:
replicas: 2
selector:
matchLabels:
app: proxy
template:
metadata:
labels:
app: proxy
spec:
containers:
- name: proxy
image: apache/shardingsphere-proxy:latest
ports:
- containerPort: 3307
volumeMounts:
- name: config
mountPath: /opt/shardingsphere-proxy/conf
volumes:
- name: config
configMap:
name: proxy-config
核心配置 :
server.yaml 设置对外协议和模式:
yaml
mode:
type: Cluster
repository:
type: ZooKeeper
props:
namespace: governance
server-lists: zk-svc:2181
props:
proxy-frontend-database-protocol-type: MySQL
config-sharding.yaml 定义四个异构数据源和路由规则(示例场景:订单表按区域分片到 MySQL 和 PostgreSQL,员工表直接存于 SQL Server,客户档案留在 Oracle):
yaml
dataSources:
ds_mysql:
url: jdbc:mysql://mysql-flex.mysql.database.azure.com:3306/sales?useSSL=true&requireSSL=true
username: mysql_user
password: mysql_pwd
ds_sqlserver:
url: jdbc:sqlserver://sqlsrv.database.windows.net:1433;database=hr;encrypt=true;trustServerCertificate=false
username: sql_user
password: sql_pwd
ds_oracle:
url: jdbc:oracle:thin:@10.0.1.5:1521/ORCLPDB1
username: ora_user
password: ora_pwd
ds_pg:
url: jdbc:postgresql://pg-flex.postgres.database.azure.com:5432/logistics?ssl=true
username: pg_user
password: pg_pwd
rules:
- !SHARDING
tables:
t_order:
actualDataNodes: ds_mysql.t_order,ds_pg.t_order
databaseStrategy:
standard:
shardingColumn: region
shardingAlgorithmName: region_sharding
t_employee:
actualDataNodes: ds_sqlserver.t_employee
databaseStrategy:
none:
t_customer:
actualDataNodes: ds_oracle.t_customer
databaseStrategy:
none:
shardingAlgorithms:
region_sharding:
type: INLINE
props:
algorithm-expression: ds_${['west' -> 'mysql', 'east' -> 'pg']}
上述配置使得应用可以执行 SELECT * FROM t_order WHERE region='west',Proxy 自动将其路由至 ds_mysql;若 region='east' 则路由至 ds_pg。而 t_employee 的查询则直接发往 SQL Server,t_customer 发往 Oracle,应用完全不需要关心物理位置。
连接测试:应用使用 MySQL 客户端连接 Proxy:
bash
mysql -h <proxy-cluster-ip> -P 3307 -u root -p
即可对逻辑表进行查询。
3.4 异构整合最佳实践
- 安全 :
- 所有数据源强制 SSL,Proxy 与数据库之间通过 VNet 和 Private Link 通信。
- 使用 Azure Key Vault 存储数据库凭据,在 Proxy 启动脚本中通过
az keyvault secret show注入环境变量。 - 对于 Azure SQL 和 PostgreSQL,逐步迁移到 Azure AD 托管标识认证,Proxy 可通过获取令牌或 MSI 扩展对接。
- 高可用 :
- Proxy 集群采用至少两个副本,前端使用 Azure 标准内部负载均衡器,会话亲和性设为 None,分发 TCP 流量。
- 元数据存储在 Azure 托管的 ZooKeeper 服务(如 AKS 中的 ZK Helm Chart 或 Azure VM 自建),实现配置动态同步与故障转移。
- 性能与隔离 :
- 为每个数据源设置连接池上限(
maxPoolSize),防止一个忙碌的 Oracle 实例耗尽 Proxy 所有连接。 - 启用查询熔断和超时(
sqlFederation或 Proxy 自带的 circuit breaker),避免级联故障。 - 避免跨异构数据库的 JOIN:Proxy 支持有限,应由应用层拆分为多次查询并组合。
- 为每个数据源设置连接池上限(
- 运维治理 :
- 通过 DistSQL 动态管理数据源,如
ADD DATASOURCE ds_new (...)无需重启。 - 集成 Azure Monitor 和 Log Analytics,收集 Proxy 日志和性能指标,设置连接数、慢 SQL 告警。
- 使用基础设施即代码(Terraform/Bicep)部署整个拓扑,确保环境可复现。
- 通过 DistSQL 动态管理数据源,如
3.5 其他替代方案
- Denodo、TIBCO 数据虚拟化:提供更强大的跨源查询优化和缓存,但为商业软件,成本较高。
- PostgreSQL FDW :如果统一入口为 PostgreSQL,可用
postgres_fdw、oracle_fdw、tds_fdw映射外部表,但查询性能受限,且写操作支持有限。 - Azure Synapse Link:主要用于 Cosmos DB 到 Synapse 的近实时同步,不支持通用多源路由。
综合来看,ShardingSphere-Proxy 是当前在 Azure 上实现异构数据库统一路由成本最低、灵活性最强的方案。
4. 跨场景通用最佳实践
无论使用哪种路由器,在 Azure 上运维都应遵循以下准则:
安全
- 所有组件之间启用 TLS 1.2+,拒绝明文连接。
- 利用 Azure AD 托管标识进行数据库认证,减少凭据管理。
- 路由器部署在私有子网,通过 Azure 防火墙或 NSG 精细控制访问来源。
高可用与灾备
- 路由器层必须冗余,至少双副本,前端挂载 Azure 内部负载均衡器或 Keepalived。
- 定期进行故障转移演练,验证只读副本提升或路由器切换时应用能否无感恢复。
- 对只读副本设置延迟告警,若复制延迟超过阈值则自动暂停读流量的分发。
可观测性
- 将路由器的指标(连接数、查询速率、错误率)和日志接入 Azure Monitor 或 Prometheus + Grafana。
- 配置分布式追踪,在路由器层注入 trace ID,关联后端数据库的慢查询。
连接管理
- 在应用端或路由器端配置合理的连接池,避免耗尽 Azure 数据库的连接限制。
- 调整空闲超时,与 Azure 网关的默认超时(如 Azure SQL 约 30 分钟)对齐,防止意外断开。
配置管理
- 使用 Terraform/Bicep 定义路由器实例、负载均衡器和后端数据库,确保版本受控。
- 敏感信息(密码、证书)统一存放在 Azure Key Vault,通过 CSI 驱动或初始化脚本动态加载。