Oracle RAC集群的高可用不能只依赖数据库层面的故障转移,应用连接层同样需要快速感知节点状态。ONS(Oracle Notification Service)是Oracle Clusterware内置的事件通知服务,它通过发布订阅模型把集群中的节点、实例、服务状态变化推送到已经注册的客户端。客户端收到通知后可以立即清理失效连接、触发快速故障转移,而不必等待TCP超时或SQL执行失败。先梳理ONS事件类型与传播过程,能够帮助理解后续配置和代码为什么这样设计。

在RAC环境中,ONS并不是简单的单节点广播,而是由每个节点上的ONS守护进程共同维护一张集群事件拓扑。应用客户端可以只连接一个或多个ONS地址,就能收到全集群范围内与数据库服务相关的事件。理解这一点对多节点客户端配置非常重要。
一、ONS在RAC集群中的角色与事件类型
RAC集群由多个节点组成,实例和服务可以在不同节点间漂移。当某个节点发生故障、实例被终止或者服务切换到其他节点时,数据库内部会生成对应的High Availability事件。ONS负责把这些事件封装成通知消息,发送给所有已订阅的客户端。常见的FAN事件包括数据库整体状态变化、单个实例启动或关闭、节点加入或离开集群、服务启动或停止,以及负载均衡建议事件。
相比应用层通过SQL探测或连接超时来判断节点可用性,ONS采用主动推送方式,事件延迟通常只有几秒钟。以JDBC连接池为例,如果连接池没有启用ONS,节点崩溃后连接池中残留的失效连接可能要等到下一次使用并遭遇网络超时才会被清理,这期间业务请求会连续失败。而启用ONS之后,连接池可以监听实例宕机事件,立刻将这些连接标记为无效并重新从存活节点获取连接。
ONS事件传播依赖每个节点上的ONS守护进程。节点之间通过远程端口6200通信,应用客户端通常通过节点的远程端口或专门的客户端端口接收通知。一个节点上的ONS守护进程故障不会阻断其他节点继续发布事件,但客户端必须保证至少有一个可用ONS地址可以连接。
二、RAC服务端ONS配置与状态检查
Oracle RAC默认会随Clusterware启动ONS,但在生产环境中仍然需要确认各节点ONS状态是否正常。可以使用srvctl命令查看全部节点的ONS资源状态,也可以登录具体节点使用onsctl工具检查本地ONS进程。建议在进行客户端对接前,先在每个节点上执行一次完整状态检查,确保ONS已经运行且端口监听正常。
# 查看所有节点ONS资源状态 srvctl status ons # 在单个节点查看ONS状态 onsctl status # 如果ONS未运行,可以启动 srvctl start ons # 需要停止时使用 srvctl stop ons
ONS使用两个主要端口:本地端口默认6100,远程端口默认6200。客户端如果与RAC节点同网段或者使用单播,一般配置远程端口6200。集群内部的节点间通信也使用远程端口。防火墙策略需要同时放行这两个端口,尤其是在客户端与数据库不在同一安全区域时,只开放数据库监听端口1521是不够的,ONS端口未放行会导致客户端始终收不到事件。
服务端配置通常不需要大量修改,默认参数已经适用于大多数场景。若确有调整需求,需要检查每个节点上的ons配置文件,确认节点列表和端口设置一致。在RAC中添加或删除节点后,也要重新核对ONS配置,避免新节点没有被客户端识别,或者旧节点仍残留在客户端配置中导致订阅延迟。
三、客户端订阅通知的两种主要方式
客户端订阅ONS通知分为直接订阅和间接订阅两种思路。直接订阅适用于OCI或Java原生接口,应用代码显式创建订阅者并处理事件回调。间接订阅则依托JDBC连接池或UCP,连接池内部实现ONS监听,应用无需编写事件处理逻辑,只需开启对应开关并指定ONS配置地址即可。
无论采用哪种方式,客户端都需要知道RAC集群中ONS节点的地址。对于直接订阅,可以通过客户端ons配置文件列出节点,也可在代码中设置节点列表。一个典型的客户端配置如下,使用XML格式描述两个RAC节点的ONS远程端口。
<onsconfig>
<nodes>
<node name="racnode1" host="192.168.1.11" port="6200"/>
<node name="racnode2" host="192.168.1.12" port="6200"/>
</nodes>
</onsconfig>
配置中之所以要写入多个节点,不是因为某个事件会从多个节点重复发送,而是为了提高订阅可靠性。如果客户端只配置一个节点,该节点重启或网络中断时,客户端将暂时失去事件来源。多节点配置可以保证只要集群中还有可用节点,客户端就能继续接收通知。
直接订阅方式更灵活,应用可以针对特定事件类型做定制处理,例如只关心服务停止事件,或者在收到节点宕机通知后触发告警。间接订阅方式则更适合大多数Java应用,因为它和连接池生命周期集成,配置简单,不容易遗漏事件处理逻辑。UCP连接池在收到实例故障事件后,会自动执行快速连接故障转移,快速失效连接并尝试从其他节点获取新连接。
四、Java代码示例:开启UCP连接池的ONS通知
在Java应用中使用UCP连接池时,开启ONS通知通常只需要两个关键属性:开启快速连接故障转移,以及指定ONS节点配置。下面示例创建一个启用ONS的PoolDataSource,并获取一个数据库连接。
import oracle.ucp.jdbc.PoolDataSource;
import oracle.ucp.jdbc.PoolDataSourceFactory;
import java.sql.Connection;
import java.sql.SQLException;
public class UcpOnsDemo {
public static void main(String[] args) throws SQLException {
PoolDataSource pds = PoolDataSourceFactory.getPoolDataSource();
pds.setConnectionPoolName("ONS_POOL");
pds.setConnectionFactoryClassName("oracle.jdbc.pool.OracleDataSource");
pds.setURL("jdbc:oracle:thin:@//scan-rac:1521/dbservice");
pds.setUser("app_user");
pds.setPassword("app_password");
// 开启快速连接故障转移
pds.setFastConnectionFailoverEnabled(true);
// 指定ONS远程节点,多个节点用逗号分隔
pds.setONSConfiguration("nodes=racnode1:6200,racnode2:6200");
Connection conn = pds.getConnection();
System.out.println("UCP connection obtained with ONS enabled");
conn.close();
}
}
上述代码中,setFastConnectionFailoverEnabled(true) 是UCP启用FAN事件处理的关键方法。连接池在后台订阅ONS事件,不需要额外线程或回调代码。设置ONS节点时,端口使用远程端口6200,主机名或IP地址要和客户端ons配置保持一致。
如果应用需要直接处理ONS事件,例如在收到数据库宕机事件时写日志或触发监控,可以使用Oracle Notification Service API。以下示例订阅数据库状态DOWN事件,并在回调中输出事件信息。
import oracle.ons.Notification;
import oracle.ons.NotificationService;
import oracle.ons.Subscriber;
import oracle.ons.SubscriptionException;
public class OnsSubscriberDemo {
public static void main(String[] args) throws SubscriptionException {
NotificationService ns = NotificationService.getInstance();
Subscriber subscriber = new Subscriber() {
public void onNotification(Notification notification) {
String eventType = notification.getType();
String eventBody = notification.getBody();
System.out.println("Received event type: " + eventType);
System.out.println("Event body: " + eventBody);
}
};
// 订阅数据库实例宕机事件
ns.subscribe(subscriber, "database/status", "DOWN");
System.out.println("Subscribed to database DOWN events via ONS");
}
}
直接订阅时需要注意事件名称和过滤条件是否与数据库实际事件匹配。不同的数据库版本和补丁级别在事件名称上可能存在差异,调试阶段可以暂时订阅较宽泛的事件范围,确认收到通知后再收窄过滤条件。正式环境中建议只订阅必要的状态事件,避免无关通知占用应用处理资源。
五、常见故障排查与高可用建议
如果客户端收不到ONS事件,首先排查网络端口。可以使用onsctl ping测试本地ONS进程,也可以从客户端机器利用telnet或nc测试远程端口6200的连通性。很多问题并不是配置写错,而是防火墙只放行了数据库监听端口,没有放行ONS端口,导致TCP连接被静默丢弃。
# 检查本地ONS是否能响应 onsctl ping # 查看ONS日志 tail -f /u01/app/grid/diag/crs/racnode1/crs/trace/ons.log # 从客户端测试ONS远程端口连通性 nc -vz 192.168.1.11 6200
其次是检查客户端配置是否完整。如果客户端只写了一个ONS地址,而该节点恰好宕机,应用会暂时失去订阅能力。生产环境建议至少配置两个或更多ONS节点,并保证这些节点分布在不同机柜或可用区。客户端配置路径也要注意,Windows环境下常见的放置位置是 C:\app\oracle\network\admin 目录,该目录必须对应用运行账户可读。
还需要关注ONS和数据库服务的版本兼容性。部分客户端使用旧版JDBC驱动,可能无法正确解析新版本ONS事件格式。遇到问题时,可以先升级JDBC驱动到与数据库相同或更高的小版本,并在测试环境验证事件接收是否正常。对于JDBC连接池,还要确认连接池本身是否支持FAN事件,不同实现之间的行为可能不同。
高可用方面,除了多节点ONS配置外,还应当将ONS状态纳入日常巡检。可以周期执行所有节点的srvctl status ons命令,并检查日志中是否存在持续的错误。RAC集群运维中,ONS虽然资源较小,但它直接影响应用故障切换速度,因此不应被忽略。合理配置ONS订阅与通知机制,能够让RAC在节点故障时把影响控制在秒级,而不是让业务等待默认的TCP超时时间。
Oracle RACONS订阅通知修改时间:2026-09-27 03:11:14