Nginx代理Oracle本质是TCP层四层转发,不解析TNS/SQL内容;必须编译启用--with-stream模块,配置stream块中listen需so_keepalive=on、upstream指定真实IP:PORT并设合理超时与健康检查参数。

用 Nginx 做 Oracle 的 TCP 层代理,本质是把客户端的 TNS 连接请求(即发往 1521 端口的原始 TCP 流)在传输层做转发,不触碰 SQL 或 TNS 包内容。这适用于 Oracle 10g/11g 单实例、RAC VIP、甚至跨版本混合环境,绕过 SCAN 限制或客户端驱动兼容性问题,真正实现工业级稳定分发。
必须启用 stream 模块并正确编译
Nginx 默认不带四层代理能力。1.9.0 及以上版本才内置 ngx_stream_core_module,但需显式开启编译参数:
- 执行 ./configure --prefix=/usr/local/nginx --with-stream,不能遗漏 --with-stream
- 禁用无关模块可减小体积,例如 --without-http_rewrite_module(HTTP 重写与 TCP 代理无关)
- make && make install 后,检查 nginx -V 2>&1 | grep -o with-stream 是否输出,确认模块已加载
stream 配置要点:监听、上游、连接保活
Oracle 是典型的长连接数据库,连接建立后可能持续数分钟甚至数小时。配置中三个要素缺一不可:
- listen 端口必须带 so_keepalive=on:防止中间网络设备(如防火墙、负载均衡器)主动断连,避免“ORA-03113: end-of-file on communication channel”
- upstream 中每个 server 行要写完整 IP:PORT,不能用 localhost 或 127.0.0.1(除非后端真在同一台机器);建议加上 weight 和 max_fails/fail_timeout 实现基础健康感知
- proxy_connect_timeout 和 proxy_timeout 要设为合理值:Oracle 登录握手较慢,建议 connect_timeout ≥ 5s,proxy_timeout ≥ 30s,避免连接未建好就被中断
负载策略选 least_conn,慎用 ip_hash
Oracle 客户端(如 JDBC Thin、SQL*Plus、PL/SQL Developer)通常复用连接池,单个客户端 IP 可能发起大量并发会话。此时:
- 轮询(默认)适合后端节点性能均一、连接数波动小的场景
- least_conn更推荐——Nginx 会将新连接发给当前活跃连接数最少的节点,天然适配数据库连接池模型
- ip_hash 不适合 Oracle:同一应用服务器 IP 下有几十个线程共用连接池,全打到一个 DB 节点易造成倾斜,且无法应对 RAC 中 instance 故障转移
验证与可观测性不能只靠 sqlplus
连通性测试只是第一步。生产环境需确认流量真实分发且状态可控:
- 在 Nginx 侧开启 error_log logs/stream.log info,观察 stream log format(需自定义日志格式)记录每条连接的源 IP、目标后端、持续时间
- 在 Oracle 端执行 SELECT inst_id, username, program FROM gv$session WHERE type = 'USER',核对各实例上的会话分布是否符合预期权重
- 模拟节点宕机:临时停掉某台 Oracle 的监听(lsnrctl stop),观察 Nginx 日志是否在 fail_timeout 内自动剔除该节点,且新连接不再发往它











