oracle rac不支持显式连接权重配置,所谓“80/20权重”需通过preferred/available实例角色、clb_goal策略、v$servicemetric负载值差异及fan感知协同实现近似效果。

Oracle RAC 中没有“连接权重”这个原生概念——CLB_GOAL 和 GOAL 控制的是负载分发策略(如响应时间、吞吐量),不是按 3:1 或 70%:30% 这类显式权重分配连接。所谓“基于服务的连接权重负载均衡”,本质是通过服务绑定 + 实例角色控制 + 负载指标组合,间接实现近似加权效果。
为什么不能直接配置 connection weight
Oracle 不提供类似 WEIGHT=70 的服务参数。服务(srvctl add service)只支持 -r(preferred)和 -a(available)实例列表,不接受数值权重。监听器分发新连接时,依据的是 CLB_GOAL 计算出的实时负载值(来自 V$SERVICEMETRIC.CURRENT_LOAD),而非静态配比。
- 试图在 tnsnames.ora 里用
LOAD_BALANCE=on模拟权重(比如重复写同一地址多次)完全无效:TNS 解析器只做随机选地址,不计数也不加权 - 修改
REMOTE_LISTENER指向某个 VIP 列表并调整顺序,也不会影响 SCAN Listener 的负载决策逻辑 -
PREFER_LEAST_LOADED_NODE=OFF是关闭动态负载判断,退化为轮询或首节点优先,反而破坏均衡意图
如何用 preferred/available 实现近似权重效果
当需要让 80% 新连接落到 node1、20% 落到 node2 时,可借助实例角色与故障转移行为构造“软权重”:
- 创建服务时指定
-r rac1 -a rac2:正常情况下所有新连接都路由到rac1(preferred 实例) - 在
rac1实例上设置CLB_GOAL = SERVICE_TIME,并确保其CURRENT_LOAD值长期偏低(例如限制并发会话数、调低PROCESSES)——这样即使有负载波动,SCAN Listener 仍倾向选它 - 在
rac2实例上设置相同CLB_GOAL,但保持默认资源上限;同时确认rac2的V$SERVICEMETRIC.CURRENT_LOAD始终显著高于rac1(可通过ALTER SYSTEM SET RESOURCE_LIMIT = TRUE+ profile 限流人为抬高) - 关键动作:执行
srvctl modify service -s mysvc -i rac1 -f强制服务在rac1故障时 failover 到rac2,但日常不主动触发——这使rac2成为“备用通道”,自然承接约 15–25% 的溢出连接(取决于负载抖动幅度)
验证 load 字段是否真实反映“倾向性”
光看 srvctl status service 显示 running 没用。必须确认 SCAN Listener 收到了差异化的负载数据:
- 在每个实例执行:
SELECT CURRENT_LOAD, SERVICE_NAME FROM V$SERVICEMETRIC WHERE SERVICE_NAME = 'mysvc';—— 确保rac1.CURRENT_LOAD稳定在 5–15,rac2.CURRENT_LOAD维持在 40–60 - 运行:
lsnrctl status LISTENER_SCAN1 | grep -A 5 "Service \"mysvc\""—— 输出中应看到类似:Service "mysvc" has 2 instance(s).Instance "rac1", status READY, has 3 handler(s) for this service.Instance "rac2", status READY, has 1 handler(s) for this service.
且每条 handler 行末带load=12和load=53这类明显差值 - 若 load 值全为 0 或全部相等,检查:
ALTER SYSTEM REGISTER;是否执行、REMOTE_LISTENER是否指向 SCAN 地址(不是 VIP)、AWR 是否启用(CLB_GOAL = SERVICE_TIME依赖 AWR 快照)
Java 应用连接池必须配合 FAN 才能感知负载变化
UCP/OJDBC 默认不重路由已建立连接。即使 SCAN Listener 把新连接分给 rac2,旧连接仍卡在 rac1 上,导致“权重”只体现在新建会话层面:
- 在 JDBC URL 中启用 FAN:
jdbc:oracle:thin:@mydb?oracle.jdbc.fanEnabled=true - 连接池需配置
setFastConnectionFailoverEnabled(true)和setInitialPoolSize(5)(避免空池无连接可重路由) - 验证 FAN 是否生效:
SELECT * FROM V$ACTIVE_SERVICES WHERE NAME = 'mysvc';中FAILOVER_TYPE应为SESSION或SELECT,且GOAL设为SERVICE_TIME - 不启用 FAN 时,所谓“80/20”只是新建连接的瞬时分布,无法维持——这点极易被忽略











