Oracle RAC 负载均衡和透明应用失败切换的配置和测试过程

来源:互联网 发布:原油ela数据 编辑:程序博客网 时间:2024/04/28 05:40

Oracle RAC 负载均衡和透明应用失败切换的配置和测试过程

时间:2011-11-15 14:31来源:未知作者:admin 点击: 181次
 
第1节 测试名词解释 这个文档被用来给配置提供一个指引 :
1) 仅仅客户端连接时间负荷平衡
2) 服务器和客户端同时的连接负荷平衡
3) 仅仅服务器端的连接负荷平衡
4) 透明的应用 failover 在配置 Net Services 特征前,这有一些每种方法的单一和混合的应用的定
第1节               测试名词解释

这个文档被用来给配置提供一个指引:

1) 仅仅客户端连接时间负荷平衡

2) 服务器和客户端同时的连接负荷平衡

3) 仅仅服务器端的连接负荷平衡

4) 透明的应用failover

在配置Net Services特征前,这有一些每种方法的单一和混合的应用的定义:

1.1      客户端连接failover

连接时失败切换可以使客户端初始化连接第一次失败时可以连接到另外一个侦听器。侦听器协议地址的数量决定了有多少个侦听器可以被尝试。没有连接时失败切换,Oracle Net仅仅连接一个侦听器,默认时是on

1.2      透明应用Failover

透明应用FailoverTAF)是高可用运行环境的一种运行时的failover,例如Oracle 9i RACOracle 9i Real Application Clusters GuardTAF 失败和重新建立应用--服务的连接。它可以使客户端应用程序在连接失败时自动重新新连接到数据库,重新执行一个程序中的SELECT操作。重新连接自动发生在Oracle Call Interface(OCI)库。

1.3      客户端连接Load Balancing

客户端load balancing 特征能使客户端在所有的侦听器中随机选择廉洁。Oracle Net程序通过在一个随机的协议地址列表的顺序,平衡不同的侦听器的负载。没有客户端的load balancing,Oracle Net程序顺序的处理协议地址列表中的地址直到一个成功。

1.4      服务器端侦听器连接Load Balancing

服务器端侦听器连接load balanceing特征在不同进程和dispatchers之间提高了不平衡激活的连接数目的执行性,侦听器选择最少负载的dispatcher来管理进行的客户端的连接。在Oracle 9i RAC环境中,连接时的load balancing也有平衡多个进程的激活的连接的能力。

由于dynamic service registration,一个侦听器总是依赖负载的信息,而无论它们的位置,而知道所有的进程和diapathers,如果共享服务已经配置,一个侦听器决定哪一个进程,哪一个dispathers发送客户端的请求。在一个共享服务器的配置里,侦听器选择一个dispatcher在以下的顺序里:

1. 最小负载的节点

2. 最小负载的进程

3. 最小负载的dispatcher for that instance

在一个专用的服务配置,侦听器以下面的顺序选择一个进程:

1.最少负载的节点

2.最少负载的进程

如果一个数据库服务有多个进程在多个节点上,侦听器选择在最少负载的节点上的最小负载的进程。如果共享服务已经配置,则选择进程的最小负载的dispatchers被选择。

第2节  配置实例
主要包括的是服务器端的init.ora,listener.ora和tnsnames.ora文件以及客户端的tnsnames.ora文件。
针对本项目的双节点的群集设置,主要配置如下:
hostname  service name  sid name  instance_name  ORACLE_HOME
========  ===========  ========   =============  ===============
node1   test1      rac           rac1         rac1       /oracle/product/9201
node2   test2      rac           rac2         rac2       /oracle/product/9201
2.1 init.ora
所有节点的init.ora 文件必须配置如下:
remote_listener='LISTENERS_RAC'
rac1.local_listener="LISTENER_rac1”
rac2.local_listener="LISTENER_rac2"
# dispatchers="(pro=ipc)(dis=0)"
db_name='rac'  /**********可以不用*************/
rac1.instance_name='rac1'
rac2.instance_name='rac2'
2.2 show parameter
既然service_names在init.ora文件中没有规定,它缺省是db_name.db_domain。每一个节点列出它的主机名和instance_name。随着以上的设置,在你启动进程后,当你从第一个节点检查sql 会话时,你将会发现下面的信息:
1)节点一
SQL> show parameter db_name
NAME      TYPE    VALUE
db_name   string    rac
SQL> show parameter db_domain
NAME      TYPE      VALUE
db_domain  string
SQL> show parameter service_names
NAME          TYPE      VALUE
service_names  string    rac
SQL> show parameter instance_name
NAME              TYPE      VALUE
instance_name     string    rac1
SQL> show parameter listener
NAME                    TYPE      VALUE
local_listener          string    LISTENER_rac1
mts_listener_address    string
mts_multiple_listeners  boolean   FALSE
remote_listener         string    LISTENERS_RAC
2)节点二
SQL> show parameter db_name
NAME       TYPE      VALUE
db_name    string    rac
SQL> show parameter db_domain
NAME           TYPE      VALUE
db_domain      string
SQL> show parameter service_names
NAME            TYPE      VALUE
service_names    string    rac
SQL> show parameter instance_name
NAME               TYPE      VALUE
instance_name      string    rac2
SQL> show parameter listener
NAME                    TYPE      VALUE
local_listener         string    LISTENER_rac2
mts_listener_address   string
mts_multiple_listeners boolean   FALSE
remote_listener        string    LISTENERS_RAC
2.3 listener.ora
test1 listener.ora file
LISTENER =
  (DESCRIPTION_LIST =
    (DESCRIPTION =
      (ADDRESS_LIST =
        (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC))
      )
      (ADDRESS_LIST =
        (ADDRESS = (PROTOCOL = TCP)(HOST = test1)(PORT = 1521))
      )
    )
  )

SID_LIST_LISTENER =
  (SID_LIST =
    (SID_DESC =
      (SID_NAME = PLSExtProc)
      (ORACLE_HOME = /oracle/product/9201)
      (PROGRAM = extproc)
    )
    (SID_DESC =
      (ORACLE_HOME = /oracle/product/9201)
      (SID_NAME = rac1)
    )
  )

Test2 listener.ora file
LISTENER =
  (DESCRIPTION_LIST =
    (DESCRIPTION =
      (ADDRESS_LIST =
        (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC))
      )
      (ADDRESS_LIST =
        (ADDRESS = (PROTOCOL = TCP)(HOST = test2)(PORT = 1521))
      )
    )
  )
SID_LIST_LISTENER =
  (SID_LIST =
    (SID_DESC =
      (SID_NAME = PLSExtProc)
      (ORACLE_HOME = /oracle/product/9201)
      (PROGRAM = extproc)
    )
    (SID_DESC =
      (ORACLE_HOME = /oracle/product/9201)
      (SID_NAME = rac2)
    )
  )

2.4 tnsnames.ora
test1—test2 and client side tnsnames.ora file
LISTENERS_RAC =
  (ADDRESS_LIST =
    (ADDRESS = (PROTOCOL = TCP)(HOST = test1)(PORT = 1521))
    (ADDRESS = (PROTOCOL = TCP)(HOST = test2)(PORT = 1521))
  )
LISTENER_RAC2 =
  (ADDRESS = (PROTOCOL = TCP)(HOST = test2)(PORT = 1521))

LISTENER_RAC1 =
  (ADDRESS = (PROTOCOL = TCP)(HOST = test1)(PORT = 1521))
RAC2 =
  (DESCRIPTION =
    (ADDRESS_LIST =
      (ADDRESS = (PROTOCOL = TCP)(HOST = test2)(PORT = 1521))
    )
    (CONNECT_DATA =
      (SERVICE_NAME = rac)
      (INSTANCE_NAME = rac2)
    )
  )
RAC1 =
  (DESCRIPTION =
    (ADDRESS_LIST =
      (ADDRESS = (PROTOCOL = TCP)(HOST = test1)(PORT = 1521))
    )
    (CONNECT_DATA =
      (SERVICE_NAME = rac)
      (INSTANCE_NAME = rac1)
    )
  )

RAC =
  (DESCRIPTION =
    (ADDRESS_LIST =
      (ADDRESS = (PROTOCOL = TCP)(HOST = test1)(PORT = 1521))
      (ADDRESS = (PROTOCOL = TCP)(HOST = test2)(PORT = 1521))
      (LOAD_BALANCE = on)
(FAILOVER=on)
    )
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = rac)
      (failover_mode=(type=select)(method=basic))/********TAF使用的配置**********/
    )
  )

EXTPROC_CONNECTION_DATA =
  (DESCRIPTION =
    (ADDRESS_LIST =
      (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC))
    )
    (CONNECT_DATA =
      (SID = PLSExtProc)
      (PRESENTATION = RO)
    )
  )
//////////////////////////////////////////////////////////////
failover =
  (DESCRIPTION =
    (enable=broken)
    (LOAD_BALANCE = yes)
    (ADDRESS = (PROTOCOL = TCP)(HOST = test1)(PORT = 1521))
    (ADDRESS = (PROTOCOL = TCP)(HOST = test2)(PORT = 1521))
    (CONNECT_DATA =
      (SERVICE_NAME = rac)
      (failover_mode=(type=select)(BACKUP=cletus)(method=basic))
    )
  )
//////////////////////////////////////////////////////////////////
2.5 配置注释
1) LISTENERS_RAC, LISTENER_rac1, LISTENER_rac2是net_service_name (连接描述) for remote_listener和local_listener.在客户端,你并不需要这些参数。
2) failover 是为透明应用失败切换(TAF)测试的net_service_name 。
3) RAC 是客户端的负载平衡的 net_service_name,如果你不需要配置TAF,这有另外一种设置客户端连接负载平衡的配置方法, 下面是另外一种办法:
RAC_alternative =
    (DESCRIPTION =
    (ADDRESS_LIST =
      (LOAD_BALANCE = yes)
      (ADDRESS = (PROTOCOL = TCP)(HOST = test1)(PORT = 1521))
      (ADDRESS = (PROTOCOL = TCP)(HOST = test2)(PORT = 1521))
    )
    (CONNECT_DATA =
      (SERVICE_NAME = rac)
    )
  )
注:  (load_balance=yes)可以使Net程序以一种随机的顺序处理地址列表中的侦听器,平衡不同侦听器之间的负载。当被设成OFF,Net程序 将以顺序的方式处理直到一个成功。这个参数必须在你的net service name (connect descriptor)正确的配置. 缺省情况下这个参数被设成ON, Load balancing能联系到ADDRESSes和DESCRIPTIONs的设置并且在ADDRESS_LIST里进行规定。如果你使用 ADDRESS_LIST,(load_balance=yes)将会在(ADDRESS_LIST=)部分。如果你不使用ADDRESS_LIST, (load_balance=yes)将会在(description=)部分里,我建议不使用(ADDRESS_LIST=) 字句。
4)(failover=on)缺省是在ADDRESS_LISTs, DESCRIPTION_LISTs和一个DESCRIPTIONs的设置里,因此你不需要规定。它是作为connect-time-failover,请注意不要与透明应用切换(TAF)发生冲突。
5)(failover_mode=):在FAILOVER_MODE参数必须包括在一个net_service_name的CONNECT_DATA部分。
6)这儿在(failover_mode=)里没有(backup=failover),
7) There is no (backup=failover) in (failover_mode=), this 暗示着
(failover_mode= (type=select)(method=basic)(backup=failover)),它意味着无论是否failover发生,连接的会话将会 切换到net_service_name又进行失败切换,当使用PRECONNECT来pre-establish连接时BACKUP应该被规定,需要详 细的TAF信息,请参考Oracle官方文档。

2.5 通常的误解点

如果你想要远程进程在本地注册,甚至你的侦听器使用端口1521,你依然需要在你的init.ora文件中设置local_listener。否 则,仅仅使用remote_listener="LISTENERS_RAC",你不能得到远程的进程在本地的注册而且也不可能得到服务器端侦听器的负载 平衡,这个是由于Bug 2194549。

注意:如果你不是运行9.0.1.3(小于版本9.2),使用专用连接,服务器端的负载平衡将会路由大部分的连接到一个节点,这是由于Bug 2134254,解决办法是在init.ora文件中添加dispatchers="(pro=ipc)(dis=0)"

 =================================================================

2.6 透明应用失败切换(TAF) 测试

请熟悉WebIV Note 97926.1 - Richard Powell 为TAF的解释所写的Failover 事务和限制 [连接时的失败切换和TAF],下面仅仅提供透明应用失败切换的测试方法:

> sqlplus system/system@rac

SQL*Plus: Release 9.0.1.3.0 - Production on Thu Jun 6 19:44:57 2002

(c) Copyright 2001 Oracle Corporation.  All rights reserved.

Connected to:

Oracle9i Enterprise Edition Release 9.0.1.3.0 - 64bit Production

With the Partitioning and Real Application Clusters options

JServer Release 9.2.0.1.0 - Production

 

SQL> col sid format 999

SQL> col serial# format 9999999

SQL> col failover_type format a13

SQL> col failover_method format a15

SQL> col failed_over format a11

SQL> select sid, serial#, failover_type, failover_method, failed_over

     from v$session where username =‘system’;

       SID    SERIAL# FAILOVER_TYPE FAILOVER_METHOD FAILED_OVER

---------- ---------- ------------- --------------- -----------

        13          8 SELECT        BASIC           NO

如果你在failover_type和failover_method没有看到什么,请停止,需要修复你的tnsnames.ora文件,你不能继续测试“shutdown abort”或重启服务器。

 

SQL> select instance_name from v$instance;

INSTANCE_NAME----------------

Rac1

***由于是负载平衡,我们需要找出当前连接到哪一个进程上,现在我们继续我们的TAF测试。******

 

SQL> select count(*) from

(select * from dba_source

union

select *  from dba_source

union

select *   from dba_source

union

select *    from dba_source

union

select *     from dba_source)

/

*** 在这个时候,使用命令 ‘shutdown abort’关闭当前连接节点,所有的查询并没有停止

COUNT(*)

----------

     60221

*** The query results is back without any error. 

 

SQL> col sid format 999

SQL> col serial# format 9999999

SQL> col failover_type format a13

SQL> col failover_method format a15

SQL> col failed_over format a11

SQL> select sid, serial#, failover_type, failover_method, failed_over

     from v$session where username = ‘system’;

 

       SID    SERIAL# FAILOVER_TYPE FAILOVER_METHOD FAILED_OVER

---------- ---------- ------------- --------------- -----------

        13          5 SELECT        BASIC           YES

 

SQL> select instance_name from v$instance;

INSTANCE_NAME

----------------

Rac2

 

*** 注意:它failed over到 rac2而且没有不同serial#和failed_over flag 被设置。

重新启动rac1,确定数据库恢复到了2个进程。

SQL> select count(*) from

(select * from dba_source

union

select *  from dba_source

union

select * from dba_source

union

select * from dba_source

union

select * from dba_source)

/

*** 在这个时候,使用命令 ‘shutdown abort’关闭当前连接节点2,所有的查询并没有停止

  COUNT(*)

----------

     60221

The query results is back without any error. 

SQL>         

    SID    SERIAL#    FAILOVER_TYPE FAILOVER_METHOD FAILED_OVER

---------- ---------- ------------- --------------- -----------

        14         20 SELECT        BASIC           YES

SQL> select instance_name from v$instance;

INSTANCE_NAME

----------------

Rac1

*** 注意:它failed over到 rac1而且没有不同serial#和failed_over flag 被设置。

测试表格:

 

Rac1

Rac2

客户端连接

程序运行情况

结论

正常运行

 

 

 

 

 

Shut rac1

 

 

 

 

 

Shut rac2

 

 

 

 

 

 

第3节 测试方法

测试方法论:

1. 你总是先开始简单后转到更复杂的测试。

2、在你启动侦听和进程之后,检查从命令“lsnrctl services”的输出,”lsnrctl status”不论你设置正确与否都不能给你提供有效的信息。如果”lsnrctl services”输出不正确,继续之前更正listener.ora或init.ora文件。

3、从服务器端测试客户端的load balance连接,检查verify.sql提供的信息,你可以注释出你不需要的sql脚本。

4、从服务器端测试服务器端侦听器load  balance,并且检查它的输出信息。

5、从服务器端测试TAF的连接,并且在关闭进程或重启服务器之前检查failover_type和failover_mothod。

 

3.1 测试脚本和设置

=====================================================================

在启动测试之前,可以使用下面的行如你所要的重复多次创建一个loop.sh文件

loop.sh

nohup sqlplus system/system@rac @verify.sql &

   sleep 1

nohup sqlplus system/system@rac @verify.sql &

   sleep 1

nohup sqlplus system/system@rac @verify.sql &

   sleep 1

nohup sqlplus system/system@rac @verify.sql &

   sleep 1

 

verify.sql (检查输出信息)

REM  set pagesize 1000

REM  the following query is for TAF connection verification

col sid format 999

col username format 9999999

col serial# format 9999999

col failover_type format a13

col failover_method format a15

col failed_over format a11

select sid, serial#, failover_type, failover_method, failed_over

  from v$session where username = ‘system’;

 

REM  the following query is for load balancing verification

select instance_name from v$instance;

exit

 

REM you can also combine two queries:

col inst_id format 999

col sid format 999

col serial# format 9999999

col failover_type format a13

col failover_method format a15

col failed_over format a11

select inst_id, sid, serial#, failover_type, failover_method, failed_over from v$session where username = 'system';

 

REM  a simple select to see the distribution of users when testing connection REM  load balancing

select inst_id, count(*) from gv$session group by inst_id;

运行这个测试,简单的输入”./loop.sh”,输出文件将被定向到nohup.out。

====================================================================

 

3.2 客户端连接Load Balancing测试

不需要服务器端侦听器连接load balancing,而仅仅客户端的load balancing,移除init.ora文件的remote_listener并且重新启动所有进程,这样将没有远程进程在侦听器注册,你将仅仅为每个进程发现本地服务器。

 

Test1$ lsnrctl service'

test2$ lsnrctl service'

 

简单运行 './loop.sh'脚本,并且定期检查输出信息。

> grep rac1 nohup.out | wc -l

> grep rac2 nohup.out | wc -l

 

测试表格:

检查次数     连接次数

RAC1

RAC2

测试结论

1

 

 

 

2

 

 

 

3

 

 

 

4

 

 

 

5

 

 

 

6

 

 

 

总测试结论和效果

 

 

===================================================================

 

3.3 服务器端连接Load Balancing (混合客户端连接Load Balancing)

服务器端的侦听器负载均衡是侦听器路由连接到低负荷的进程,添加remote_listener参数到init.ora文件并且重启所有的进程,记住检查‘lsnrctl services’的输出信息:

Test1 $ lsnrctl service'

test2 $ lsnrctl service'

注意: 比较“lsnrctl status”下面的输出,你将会发现比上面更多的信息,请注意到在一个节点它自己的进程,例如:test1上的rac1,你将会有本地的服务和远程的服 务。别的远程进程,你仅仅发现远程服务器。请确认远程服务器地址是正确而不是空的主机名:

test1 $ lsnrctl status

====================================================================

简单运行 './loop.sh'脚本,并且定期检查输出信息。

 

> grep rac1 nohup.out | wc -l

> grep rac2 nohup.out | wc -l

测试表格:

检查次数     连接次数

RAC1

RAC2

测试结论

1

 

 

 

2

 

 

 

3

 

 

 

4

 

 

 

5

 

 

 

6

 

 

 

总测试结论和效果

 

After the testing, you can check 'lsnrctl services' from all 2 nodes  again:

====================================================================

 

3.4 仅仅服务器端Load Balancing测试

如你所喜欢,你去除客户端的负载平衡可以移除或注释出客户端的侦听器的(LOAD_BALANCE = yes)并且检查服务器端的负载平衡属性。客户端的tnanames.ora文件:

  ( rac =

#     (LOAD_BALANCE = yes)

      (ADDRESS = (PROTOCOL = TCP)(HOST = test1)(PORT = 1521))

      (ADDRESS = (PROTOCOL = TCP)(HOST = test2)(PORT = 1521))

      (CONNECT_DATA =

      (SERVICE_NAME = rac)

    )

  )

  在这种情况下,所有的连接全部到test1的侦听器并且被路由到别的进程。

测试结果:

> grep rac1 nohup.out | wc -l

> grep rac2 nohup.out | wc -l

测试表格:

检查次数     连接次数

RAC1

RAC2

测试结论

1

 

 

 

2

 

 

 

3

 

 

 

4

 

 

 

5

 

 

 

6

 

 

 

总测试结论和效果

 

 在测试完成之后,在这个的测试里,可以使用下面的输出信息,与前面的测试进行比较。

test1 $ lsnrctl services’

test2 $ lsnrctl services’

 你将会注意到从test1的lsnrctl service’输出信息有所有的节点连接总数信息。然而,另外一个节点test2有它自己的进程建立连接总数信息。这是由于没有客户端的load balancing (load_balance=on),所有的连接连接到test1(地址列表中的第一个地址)并且被test1路由到别的进程。

第4节 Trouble shooting

如果依然存在问题,你将发送下面所有的打印屏幕到Oracle 支持点。

1. 所有服务器的listener.ora,tnsnames.ora, sqlnet.ora 文件

2. 所有服务器的'lsnrctl services' 输出信息

3. 如果是sql会话,收集下列信息:

show parameter db_name

show parameter db_domain

show parameter service_name

show parameter instance_name

show parameter listener

4. ‘hostname’输出和 /etc/hosts 文件或 nslookup `hostname`输出信息

5. 客户端的tnsnames.ora, sqlnet.ora 文件

6. 客户端和服务器短的sqlnet.log文件,服务器端的listener.log 文件

7. 在客户端和服务器端的sqlnet.ora 文件,如下面设置追踪参数并且把sqlnet的客户端/服务器端的追踪文件发送到我们

trace_level_client = 16

trace_unique_client = on

#请给下面的参数提供一个具有写权限的合法的目录

trace_directory_client = /oracle/product/ora920/network/trace

trace_level_server = 16

#请给下面的参数提供一个具有写权限的合法的目录

following parameter

trace_directory_server = /oracle/product/ora920/network/trace 

trace_timestamp_client = on

trace_timestamp_server = on

8.当你完成测试,请确定你注释出下面的两行:

# trace_level_client = 16

# trace_level

(责任编辑:admin)