转自-阿里巴巴许春值
1、scan概念
什么叫 SCAN,SCAN (Single Client Access Name) 是 Oracle 从11g R2 开始推出的,客户端可以通过 SCAN 特性负载均衡地连接到 RAC 数据库。SCAN 提供一个域名来访问 RAC,域名可以解析 1个 到 3个 SCAN IP,我们可以通过 DNS 或者 GNS 来解析实现。其中 DNS 大家都很熟悉,这里不多说。GNS (Grid Naming Service) 则是 Oracle 11g R2 的新功能,可以通过 DHCP 服务为节点和 SCAN 分配 VIP 和 SCAN IP。另外还有个优点是,对于新加入集群的节点,它会自动分配 VIP 地址,更新集群资源,客户端依然通过 SCAN 特性负载均衡地连接到新增集群节点上。
除了 DNS 和 GNS 解析方法外,SCAN 也可以使用 hosts 文件来解析,但用过的人都知道,此方法不仅在安装 RAC 的时候产生问题(RAC 安装的时候的确会报错),后期使用也是存在问题的,比如 SCAN 域名只能定义一个 SCAN IP。所以这种方法也是 Oracle 不推荐使用的。但尽管如此,我见过很多生产上依然这样使用,也就是废弃了11g 的新特性 SCAN,而是依然采用 VIP 连接方式。SCAN 最明显的优点就是,当集群中新增加了节点或者删除了节点,不需要额外维护客户端。
2、RAC中网络ip概念
在 RAC 部署的时候,我们都会接触到很多关于地址的概念,以下简要介绍一下。
PUBLIC IP : 这是我们网卡上配置的真实 IP 地址,我们称为公共 IP,这个 IP 的存在关系到下面介绍的 VIP 能不能正确漂在其所在网卡上。注意,Public IP 是不提供给客户端去连接配置的,这并不是说通过 PUBLIC IP 无法连接实例,而是它会存在节点服务器宕机的时候所有向它请求的客户端都会有等待现象并且最后得到超时信息的缺点。
PRIVATE IP : 称为私网 IP(私有 IP),它是用于心跳同步的,也就是保证两台服务器数据同步。说到私网 IP,我简单说下 Oracle 另一个高可用性连接特性 – HAIP。其实 Cache Fusion 会消耗节点服务器很大的私网资源,另外,私网间无法通信还会引起 Brain Split(脑裂),以前为解决这种问题,可以采用网卡 bonding 技术,而 Oracle 在 11g R2 的时候 HAIP 技术来实现,HAIP - Highly Available Virtual IP 用于节点间的私网通信,支持同时使用多个网络连接来满足网卡间的负载均衡,并且还提高了 Cache Fusion 资源通信能力。
VIP : RAC 的每个节点都需要有一个虚拟 IP,这就是 VIP。VIP 需要和 PUBLIC IP 同一个子网,它们是由 GI 的 Clusterware 来管理的。VIP 在其节点服务器发生故障的时候会自动漂移到另外正常的节点服务器上,如果 RAC 是多个节点运行的,那具体漂移到哪个活动的节点将由 Clusterware 决定。VIP 发生漂移现象之后,其当前的节点服务器 LOCAL LISTENER 是不会监听它的请求的,所以有客户端向这个 VIP 发送请求时,Clusterware 的 FAN 会通知客户端向别的 VIP 发送请求,客户端收到通知后通过 Failover 机制把请求重新发送到 ADDRESS 列表中的其他 VIP 上。虽然有这种较复杂的过程,但始终对客户端是透明进行的,而且这个过程完成时间非常短暂,客户端也就几乎感受不到有节点宕机。等故障节点恢复正常,漂移的 VIP 也回到此节点上,继续提供服务。
SCAN VIP : SCAN VIP 就是我在刚开始常说的 SCAN IP,也就是由 DNS 或者 GNS、hosts 解析出来的 IP 地址。上面也说过,SCAN VIP 最多能有三个,它们循环地被客户端所请求到。这里大家可能会存在这样的问题,SCAN VIP 只有三个,那 RAC 是四节点或更多的节点情况怎么办?存在这种问题的原因归咎于对 SCAN VIP 的了解不足。其实,SCAN VIP 数量和节点数是没有任何关系的,SCAN VIP 会落到哪个节点上都是随机的。
GNS VIP : GNS VIP 同 SCAN VIP,也是 Oracle 从 11g R2 开始提供的。GNS VIP 是提供 GNS 服务的 IP 地址,它绑定到某个节点的 PUBLIC IP 所在网卡上,当节点出现故障,GNS 资源会自动切换到其他正常的节点继续提供 GNS 解析服务。如果我们不使用 GNS 解析方法,那么也不会存在 GNS VIP。
LOCAL LISTENER : 本地监听器,RAC 的每个节点上都会有独立的本地监听器,它会监听该节点的 Public IP 和 VIP,而每个节点的实例在启动的时候也向本地监听器进行注册,当然它也会向 SCAN 监听器注册,当 VIP 或者 PUBLIC IP(这种情况比较少见)有连接请求的时候,本地监听器就接受处理并和本地实例建立连接。如果某个节点故障,其上面的 VIP 会进行漂移,但本地监听器并不会产生漂移。
SCAN LISTENER : SCAN 监听器,它是实现 SCAN 负载均衡的原理所在。如果 RAC 上有三个 SCAN VIP,那么 SCAN 监听器也有三个,它们各自监听 SCAN VIP 的连接请求。SCAN 监听器跟着 SCAN VIP 随机分配到节点服务器上,如果某个节点发生故障,运行在此节点上的 SCAN VIP 会进行漂移,这时候 SCAN 监听器也跟着漂移到正常的节点上,继续为 SCAN VIP 监听连接请求,当 PMON 进程下次动态更新实例信息到该 SCAN 监听器之后,它又重新接受客户端的连接。这和 VIP 产生漂移的时候是有所区别的。
3、两个参数
LOCAL_LISTENER : 这是 Oracle 的参数,这个参数控制着本地监听器的注册,因为本地监听器的工作机制关系,通过本地监听器的数据库连接请求只会连接到本地节点的实例上。
REMOTE_LISTENER : 同 LOCAL_LISTENER 是 Oracle 的参数,通过这个设置,任何实例都会向 SCAN 监听器注册,所以 SCAN 监听器能够负载均衡地分发连接请求到节点本地监听器上,也就是连接到其本地节点上实例上。
4、scan解析与配置
SCAN 是在安装 GI(Grid Infrastructure) 时配置的,作为 Clusterware 资源被管理。忽略 hosts 解析之后,有两种方式配置和解析 SCAN: DNS 和 GNS(Grid Naming Service)。
这里重点说一下 DNS 解析 SCAN 方式
使用 DNS 解析 SCAN 的时候,DNS 服务器会采用 rr(round-robin) 的方式循环解析为它准备的3个 IP 地址,与 Oracle 11g R2 的客户端配合使不同的客户端能够连接到不同的 SCAN Listener 上,这相当于是 Oracle 10g 中配置的客户端负载均衡(通过 LOAD_BALANCE=yes 配置)。下面看一下客户端通过 SCAN 连接到数据库的过程,首先由 DNS 服务器解析 SCAN 名称,DNS 服务器返回 SCAN 对应的3个 IP 地址的列表,客户端会选择使用其中一个 SCAN VIP 地址作为连接地址,将命名方法解析后的连接信息发送到 SCAN VIP 对应的 SCAN Listener 上,SCAN Listener 通过负载均衡机制再把请求转发给比较空闲的服务器上的本地监听器,由本地监听器完成实例与客户端之间的连接。
使用 SCAN 连接数据库实例,整个过程实现了客户端的 Failover(Oracle 10g R2 是通过 FAILOVER=on 来配置),DNS 服务器返回的是一个 SCAN VIP 列表,客户端会选择其中一个连接到 RAC,如果这个 IP 地址不能正常访问,客户端会选择另一个 IP 地址继续连接,直到所有的地址都不能正常连接,才返回错误给客户端,整个过程对客户端程序来说依然是透明的。
需要注意的是,使用 SCAN 连接到数据库,不再需要客户端能解析节点的 PUBLIC IP 和 VIP,只需要客户端能够通过 DNS 服务器正常解析 SCAN 就可以了。负载均衡工作交给服务器端的 SCAN 实现。
至于 GNS 解析 SCAN,因为目前 GNS 服务存在不稳定的情况,也很少有企业将其投入到生产环境使用,而且其工作原理也较为复杂,所以在这里并不深入说明。
5、实例的动态注册
上面已经介绍了 LOCAL_LISTENER 和 REMOTE_LISTENER 两个和动态注册有关的参数,那我们看看它们在数据库中的表现形式:
本地监听器注册是由实例的 LOCAL_LISTENER 参数所控制的:
LOCAL_LISTENER 设置为向本地VIP地址进行注册,由于本地监听器是在本地的 PUBLIC IP 和 VIP 上监听,所以向 VIP 监听注册就能保证成功向本地监听器注册。
查看本地监听器的状态:
--这里注意:查看本地监听器信息的时候每个节点只能看到其上运行的实例。
SCAN 监听器的注册是由 REMOTE_LISTENER 参数控制的,任何实例都会向所有的 SCAN 监听器注册:
SQL> show parameter remote_listener
NAME TYPE VALUE
———————————— ———————- ——————————remote_listener string pos-cluster-scan:1521下面是 LISTENER_SCAN1 的一个状态信息,当然你也可以查看LISTENER_SCAN2和 LISTENER_SCAN3 的状态。
由于任何实例启动都会向所有的 SCAN 监听器动态注册,从 LISTENER_SCAN1 的 SCAN 监听器运行状态来看,SERVICE pos 包括了所有的实例名称。 SCAN 监听器是实时了解所有实例的运行情况的,因此它能够准确地将连接重定向到空闲服务器的本地监听器上。
下面我们通过日志查看实例的动态注册与动态更新
1)本地监听器动态注册日志:
[grid@pos2 ~]$ cd $ORACLE_BASE/diag/tnslsnr/pos2/listener/alert[grid@pos2 alert]$ grep service_register log_1.xml | head -3<txt>18-JUN-2012 13:58:23 * service_register * LsnrAgt * 0
<txt>18-JUN-2012 13:58:30 * service_register * +ASM2 * 0
<txt>18-JUN-2012 15:54:15 * service_register * pos2 * 0
-- 之所以选择log_1.xml历史文件是因为发现我的log.xml里基本都是更新日志,没有注册日志。2)本地监听器动态更新日志:[grid@pos2 alert]$ grep service_update log.xml | head -3<txt>16-OCT-2012 16:07:09 * service_update * pos2 * 0
<txt>16-OCT-2012 16:07:33 * service_update * pos2 * 0
<txt>16-OCT-2012 16:08:03 * service_update * pos2 * 0
3)SCAN监听器动态注册日志:[grid@rac1 ~]$ cd $ORACLE_BASE/diag/tnslsnr/rac1/listener_scan2/alert/[grid@rac1 ~]$ grep service_register log.xml | head -3<txt>13-AUG-2012 05:25:00 * service_register * LsnrAgt * 0
<txt>13-AUG-2012 20:29:07 * service_register * luocs1 * 0
<txt>13-AUG-2012 20:58:05 * service_register * luocs1 * 0
-- 这是我另一套测试RAC环境。4)SCAN监听器动态更新日志:[grid@rac1 ~]$ grep service_update log.xml | head -3<txt>13-AUG-2012 20:29:19 * service_update * luocs1 * 0
<txt>13-AUG-2012 20:30:19 * service_update * luocs1 * 0
<txt>13-AUG-2012 20:30:46 * service_update * luocs1 * 0
注意,如果你的 RAC 是通过 hosts 解析了 SCAN 域名的,那么系统里就找不到上面的 SCAN 监听器日志的路径。
实例的动态注册和动态更新过程是由实例的 PMON 进程完成的,正是因为 SCAN 监听器能够实时了解实例的负载情况,所以 SCAN 监听器能够负载均衡地将连接请求转发给合适实例的本地监听器来处理。
这里谈到负载均衡,那么就说下负载均衡中的优先级共享服务器配置中:
· 低负载节点
· 低负载实例
· 实例相关的低负载调度器
专用服务器配置中:
· 低负载节点
· 低负载实例
6、scan兼容性配置
介绍 SCAN 差不多了,这里还有个兼容性问题不能不说。要完美实现 SCAN 功能特性,其实对客户端的要求也是存在的。下面看下不同版本和 SCAN 之间的兼容性。
编号 | 客户端软件版本 | 服务器端软件版本 | SCAN 特性的使用 |
1 | 11g R2 | 11g R2 | 能够充分使用 SCAN 的特性 |
2 | 早于11g R2 版本 | 11g R2 | 不能充分感受到 SCAN 特性 |
3 | 11g R2 | 早于11g R2 版本 | 在服务器端没有 SCAN 的概念 |
4 | 早于11g R2 版本 | 早于11g R2 版本 | 在服务器端没有 SCAN 的概念 |
这里稍微详细说一下第2种情况,如果客户端低于11g R2 的版本,在 DNS 解析的3个 VIP 地址中,可能只能固定地使用第一个 SCAN VIP 连接数据库;如果该 SCAN VIP 对应的监听器出现故障,那么整个连接将会失败,客户端也会收到到错误信息。
那针对兼容性问题我们拿出各种客户端配置方法
1)客户端和服务器端软件版本都是11g R2的时候 Tnsnames.ora
RACSCAN =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = luocs-cluster-scan.grid.luocs.com)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = luocs10g)
)
) 2)客户端是早于11g R2的版本,服务器端是11g R2的时候 RACSCAN =
(DESCRIPTION =
(ADDRESS_LIST =
(LOAD_BALANCE=on)
(FAILOVER=on)
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.0.193)(PORT = 1521))
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.0.194)(PORT = 1521))
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.0.195)(PORT = 1521))
)
(CONNECT_DATA =
(SERVICE_NAME = luocs10g)
)
) 为了确保在早于11g R版本的客户端负载均衡和失败切换,我们需要在tnsnames.ora中添加3个SCAN VIP。 3)传统的RAC客户端配置方法 先从客户端正常地解析服务器所有节点的主机名称和相应的VIP名称, 最好和服务端/etc/hosts一致。当然,我们不解析名称的情况下还可以使用VIP地址,比如: LUOCSRAC =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.0.193)(PORT = 1521))
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.0.194)(PORT = 1521))
(LOAD_BALANCE = yes)
(FAILOVER = on)
)
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = luocs)
)
) 本地客户端hosts解析之后,使用名称: LUOCSRAC =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = rac1-vip.luocs.com)(PORT = 1521))
(ADDRESS = (PROTOCOL = TCP)(HOST = rac2-vip.luocs.com)(PORT = 1521))
(LOAD_BALANCE = yes)
(FAILOVER = on)
)
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = luocs)
)
) 注意:传统的客户端配置方法其实还有多种,这个在这里不细说。 4)JDBC字符串配置 早期版本: jdbc:oracle:thin:@(DESCRIPTION =(ADDRESS_LIST =(ADDRESS = (PROTOCOL = TCP)(HOST = rac1-vip.luocs.com)(PORT = 1521))(ADDRESS = (PROTOCOL = TCP)(HOST = rac2-vip.luocs.com)(PORT = 1521))(LOAD_BALANCE = yes)(FAILOVER = on))(CONNECT_DATA =(SERVER = DEDICATED)(SERVICE_NAME = luocs))) 11g R2: jdbc:oracle:thin@luocs-cluster-scan:1521/luocs
注意:JDBC 是不支持 TAF 的,所以通过 JDBC 连接无法实现 Failover,那有没有解决方法,我们可以使用应用的连接池来实现,也就是当连接的时候发现某些连接有故障,那自动切换到正常实例的连接。
最后我贴一下 SCAN 配置信息的检查方法和 DNS、GNS 方式 SCAN 解析实例。
首先 SCAN 配置信息的检查:
DNS 方式配置 SCAN:
然后我们在安装 GI 的时候使用 scan.luocs.com 即可,当然要不选择 Configure GNS。
GNS方式配置SCAN:
然后我们在安装GI的时候使用SCAN Name填写:rac-cluster-scan.gns-server.rac.com,选择Configure GNS,GNS Sub Domain填写gns-server.rac.com,GNS VIP Address填写192.168.77.95。其中SCAN Name的填写有讲究的,就是再不包含域名的情况下前面的字符不能超过15个,另外192.168.77.95就是GNS VIP。