1. FAILOVER
FAILOVER就是着集羣中任何一個節點的故障都不會影響用戶使用,連接到故障節點的用戶會被自動轉移到健康節點,從用戶感受而言感覺不到這種切換,這個功能在oracle中被稱作FAILOVER.
ORACLE 10g的FAILOVER 可以細分爲三種:
l Client-side Connect time Failover
l TAF
l Service-Side TAF
注意:不要在listener.ora 中設置GLOBAL_DB_NAME,因爲這個參數會禁用Connect-time Failover 和 Transparent Application Failover
1.1. client-side connect time failover
含義是:如果用戶端tnsnames中配置了多個地址,用戶發起連接請求時,會先嚐試連接地址表中的第一個地址,如果連接嘗試失敗,則繼續嘗試使用第二個地址,直至連接成功或者遍歷了所有的地址。
這種failover的特點只在發起連接時纔去感知節點故障,如果發現節點沒有響應,則自動嘗試地址列表中的下一個地址。一旦連接建立以後,節點出現故障都不會作出處理,從客戶端的表現就是會話斷開,用戶程序必須重新建立連接。
啓用這種Failover的方式就是在客戶端的tnsnames.ora中添加FAILOVER=on 條目,這個參數默認是ON,所以即使不添加這個條目,客戶端也會獲得這種能力。
所謂TAF,就是連接建立以後、應用系統運行過程中,如果某個實例發生故障,連接到這個實例上的用戶會被遷移到其他的健康實例上。對於應用程序而言,這個遷移過程透明,不需要用戶的介入,當然這種透明也是有引號的,因爲用戶的位提交事務會回滾。
TAF的配置只需要在客戶端的tnsnames.ora中添加FAILOVER_MODE配置項,這個條目中有四個子項目需要定義。
a) METHORD選項用於定義何時創建到其他實例的連接,有BASIC 和PRECONNECT 兩個可選值。
l BASIC 是指在感知到節點故障時才創建到其它實例的連接。
l PRECONNECT是在最初建立連接時就同時建立到所有實例的連接,當發生故障時,立刻切換到其它鏈路上。
兩種方法的比較:BASIC會有時間延遲,PRECONNECT方式雖然沒有時間延遲,但是建立多個冗餘連接會消耗更多資源,兩者就是用時間換資源和用資源換時間的區別。
b) Type選項用於定義發生故障時對完成的SQL語句如何處理,其有兩種類型:session和select。
這兩種方式對於未提交事務都會自動回滾。區別在於對select語句的處理,對於後一種類型,用戶正在執行的select語句會被轉移到新的實例上,在新節點上繼續返回後續結果集,而已經返回的記錄集拋棄。
爲了實現這種select方式,oracle 必須爲每個session保存更多的內容,包括遊標、用戶上下文等。需要更多的資源也是用資源換時間的方案。
c) DEALY 和RETRIES 代表重試時間和重試次數
1.2.1. Client-Side Connect TimeFailover 和TAF的對照試驗
測試流程:
(一) 一個兩個節點RAC,節點分別是 NODE1-VIP ,NODE2-VIP
(二) 客戶端的TNSNAMES.ORA分別配置兩個條目,分別使用兩種FAILOVER
(三) 客戶端利用這兩個tnsnames條目,打開兩個窗口,建立兩個鏈接,做操作
(四) 在服務器上,用kill命令殺掉兩個鏈接對應的Server process 來模擬節點故障(也可以使用重啓節點的方式)
(五) 經過短暫實踐後,使用TAF的連接會自動轉移到其它實例上,用戶可以繼續在這個窗口執行語句;
(六) 而使用client-side connect time failover 的連接不會自動轉移,用戶必須重新連接。
1.2.2. 測試步驟
(一) 編輯客戶端tnsnames.ora文件,在其中添加兩個條目,分別使用兩種Failover 機制:wsxdb_cl 對應Client-side 而wsxdb_taf 對應TAF。兩個條目中都沒設置FAILOVER=ON選項默認就是ON。
wsxdb_cl=
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST =node1-vip)(PORT = 1521))
(ADDRESS = (PROTOCOL = TCP)(HOST =node2-vip)(PORT = 1521))
(LOAD_BALANCE = yes)
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = ocm.oracle.com)
)
)
wsxdb_taf=
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST =node1-vip)(PORT = 1521))
(ADDRESS = (PROTOCOL = TCP)(HOST =node2-vip)(PORT = 1521))
(LOAD_BALANCE = yes)
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = ocm.oracle.com)
(FAILOVER_MODE =
(TYPE = session)
(METHOD = basic)
(RETRIES = 180)
(DELAY = 5)
)
)
)
(二) 開啓兩個窗口,分別使用兩個TNS進行連接,爲了區分這兩個連接,這裏使用不同的用戶登陸。
第一個窗口使用client-side
SQL>conn scott/tiger@wsxdb_cl
第二個窗口使用 TAF
SQL>conn hr/hr@wsxdb_taf
(三) 連接成功後,在兩個窗口執行語句。
在第一個窗口中查看用戶連接到的實例
SQL>select instance_name from v$instance;
INSTANCE_NAME
--------------------------------
rac2
查看用戶連接的TAF配置
SQL>select username,failover_type,failover_method from v$session
2 where username in ('HR','SCOTT' );
USERNAME
------------------------------------------------------------
FAILOVER_TYPE FAILOVER_METHOD
----------------------------------------------
SCOTT
NONE NONE
查詢結構都爲NONE說明這個連接沒有使用TAF
在第二個窗口中,查看用戶連接的實例
SQL> select instance_name from v$instance;
INSTANCE_NAME
--------------------------------
rac1
查看用戶連接的TAF和TNS配置中相符
1 select username,failover_type,failover_method from v$session
2* where username in ('HR','SCOTT' )
SQL>/
USERNAME
------------------------------------------------------------
FAILOVER_TYPE FAILOVER_METHOD
----------------------------------------------
HR
SESSION BASIC
(四) 在服務端殺掉兩個連接對應的Server Process
查看兩個連接對應的Server process的OS PID
SQL>select spid from v$session a,v$process b where a.paddr=b.addr anda.username='HR';
SPID
------------
13950
SQL>select spid from v$session a,v$process b where a.paddr=b.addr anda.username='SCOTT';
SPID
------------
20946
[root@node1 ~]# ps aux |grep 13950|grep -v grep
oracle 13950 0.0 4.5 426716 46284 ? Ss 05:18 0:00 oraclerac1 (LOCAL=NO)
[root@node2 ~]# ps aux |grep20946|grep -v grep
oracle 20946 0.0 5.7 426916 59264 ? Ss 05:16 0:00 oraclerac2 (LOCAL=NO)
使用kill -9殺掉兩個OS PID
[root@node1 ~]# kill -9 13950
[root@node2 ~]# kill -9 20946
(五) 返回到兩個窗口,再實行sql語句,兩個連接都報同樣的錯誤
SQL>select instance_name from v$instance;
selectinstance_name from v$instance
*
第 1 行出現錯誤:
ORA-03113: 通信通道的文件結束
(六) 稍等幾秒後再次執行語句
第一個窗口
SQL>select instance_name from v$instance;
ERROR:
ORA-03114: 未連接到 ORALCE
第二個窗口
SQL> select instance_name from v$instance;
INSTANCE_NAME
--------------------------------
rac2
第一個窗口需要重新連接(連接時故障轉移)
第二個窗口過了一段時間後遷移到另一個實例
wsxdb_taf=
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST =node1-vip)(PORT = 1521))
(ADDRESS = (PROTOCOL = TCP)(HOST =node2-vip)(PORT = 1521))
(LOAD_BALANCE = yes)
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = ocm.oracle.com)
(FAILOVER_MODE =
(TYPE = session)
(METHOD = PRECONNECT)
(RETRIES = 180)
(DELAY = 5)
)
)
)
查看連接到的實例
SQL>CONN HR/HR@WSXDB_TAF
已連接。
SQL> select instance_name from v$instance;
INSTANCE_NAME
--------------------------------
rac1
查看OS PID
SQL> select spid from v$sessiona,v$process b where a.paddr=b.addr and a.username='HR';
SPID
------------
31994
[root@node1 ~]# ps aux |grep 31994|grep -v grep
oracle 31994 0.0 2.3 424120 24556 ? Ss 05:54 0:00 oraclerac1 (LOCAL=NO
殺掉OS PID
[root@node1 ~]# kill -9 31994
很快的切換到實例二
select instance_name from v$instance
INSTANCE_NAME
--------------------------------
rac2
1.2.4. 測試type爲select
wsxdb_taf=
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST =node1-vip)(PORT = 1521))
(ADDRESS = (PROTOCOL = TCP)(HOST =node2-vip)(PORT = 1521))
(LOAD_BALANCE = yes)
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = ocm.oracle.com)
(FAILOVER_MODE =
(TYPE = select)
(METHOD = basic)
(RETRIES = 180)
(DELAY = 5)
)
)
)
SQL> conn hr/hr@wsxdb_taf
查看用戶連接的實例
SQL> select instance_name from v$instance;
INSTANCE_NAME
--------------------------------
rac1
運行一個笛卡爾積,在運行過程中模擬斷電shutdown abort 實例1
SQL> select last_name,salary fromemployees a,employees b;
模擬斷電shutdown abort
SQL> shutdown abort
此時查詢會停止一會,接着繼續查詢
查詢完畢後查看用戶連接的實例,以及切換到實例二。
SQL> select instance_name fromv$instance;
INSTANCE_NAME
--------------------------------
rac2
Server-Side TAF 也是TAF,所有TAF有的特點它都具有;其次這種TAF是在服務器上配置,而不像TAF是在客戶端配置。
Server-side TAF 通過結合Service,在數據庫裏保存FAIL_MODE的配置,把所有的TAF配置保存在數據字典,從而省去了客戶端的配置工作,現在客戶端的TNS文件就不需要任何TAF的配置選項了。
從配置參數而言,Server-side TAF 和TAF相比多了一個INSTANCE role(實例角色)的概念。所謂實例角色就是當有多個instance 參與一個service時,可以配置優先使用哪一個instance爲用戶提供服務。用戶共有兩種可選角色。
l PREFERRED:首選實例,會優先選擇擁有這個歌角色的實例提供服務。
l AVAILABLE:後備實例,用戶連接會優先連接PREGERRED的instance,當PREFERRED的instance 不可用時,纔會被轉到AVAILABE的instance上。
要想使用Server-side TAF 必須配置Service。Service 可以在創建數據庫時創建,也可以在數據庫創建之後修改;既可以通過配置嚮導,也可以通過命令行方式配置。
1.3.1. 使用srvctl命令配置service
1. 創建service
srvctl add service -ddatabase_name -s service_name -r "preferred-instance" -a "avaliable-instance" -P<TAF_POLICY>
其中TAF-POLICY 選項可以爲BASIC 或PRECONNECT。
2. 查看配置
srvctl config service -d database-name [-s service-name] [-a]
如果不指定“-s service-name”就會顯示所有的service 配置,這些配置只包括preferred 和available
3. 是否自動運行service
數據庫啓動時會自動啓動所有的service。有時爲了維護的需要,需要禁用這個特性。在維護完成後再啓動這個特性。
srvctl enable/disable service -d database-name -s service-name -iinstance-name
4. 啓動service
srvctl start service -d database-name -s service-name -i instance-name -o startoption -c connect-string -q
如果不指定service-name 則所有的service都會被啓動;可以使用逗號分隔方式,同時啓動多個service。-i 指定在哪個實例上啓動service。
5. 停止service
srvctl stop service -d database-name -s service-name -c connect-string -q -f
其中-f選項可以強制關閉service ,並中斷了其所有的用戶連接。
6. 查看service狀態
srvctl status service -d database-name -s service-name -f -v
7. 刪除service
srvctl remove service -d database-name -s service-name -i instance -f
在使用srvctl 創建service時,必須要注意TAF策略必須通過dbms_service 包來配置。
1) 再添加服務之前,查看系統現有的service
SQL> show parameter service
NAME TYPE VALUE
------------------------------------ -----------------------------------------
service_names string ocm.oracle.com
2) 使用srvctl創建一個wsx服務
[oracle@node1 ~]$ srvctl add service-d ocm -s wsx -r rac1 -a rac2 -P basic
srvctl add service中,只有perferred纔會創建服務。 即在OCR中註冊一個ora.ocm.wsx.rac1.Srv的服務。
3) 查看服務
[oracle@node1~]$ crs_stat -t -v
Name Type R/RA F/FT Target State Host
----------------------------------------------------------------------
省略輸出
ora.ocm.wsx.cs application 0/0 0/1 OFFLINE OFFLINE
ora....ac1.srv application 0/0 0/0 OFFLINE OFFLINE
ora....ac2.srv application 0/0 0/0 ONLINE OFFLINE node2
4) 配置服務自動啓動
[oracle@node1~]$ srvctl enable service -d ocm -s wsx
PRKP-1018 : Service wsx already enabled.
5) 啓動服務,並查看狀態,狀態時ONLINE 說明已經啓動
[oracle@node1~]$ srvctl start service -d ocm -s wsx
[oracle@node1~]$ crs_stat -t -v
省略輸出
ora.ocm.wsx.csapplication 0/0 0/1 ONLINE ONLINE node1
ora....ac1.srv application 0/0 0/0 ONLINE ONLINE node1
6) 新創建的服務會自動添加到初始化參數中
SQL> show parameter service
NAME TYPE VALUE
----------------------------------------------- ------------------------------
service_names string ocm.oracle.com, wsx
7) 修改Service的TAF配置需要使用dbms_service.modify_service
SQL>begin
dbms_service.modify_service(
service_name => 'wsx',
failover_method=>dbms_service.failover_method_basic,
failover_type=>dbms_service.failover_type_select,
failover_retries => 180,
failover_delay=>5
);
end;
10 /
8) 確認參數已經生效
SQL> select name,failover_method,failover_typefrom dba_services;
wsx basic select
9) 使用srvctl 查看服務配置
[oracle@node1 admin]$ srvctl configservice -d ocm -s wsx
wsx PREF: rac1 rac2 AVAIL:
10) 查看監聽器
Service "wsx.oracle.com" has 2 instance(s).
Instance "rac1", status READY, has2 handler(s) for this service...
Handler(s):
"DEDICATED" established:0refused:0 state:ready
LOCAL SERVER
"DEDICATED" established:0refused:0 state:ready
REMOTE SERVER
(ADDRESS=(PROTOCOL=TCP)(HOST=node1.example.com)(PORT=1521))
Instance "rac2", status READY, has1 handler(s) for this service...
Handler(s):
"DEDICATED" established:2refused:0 state:ready
REMOTE SERVER
(ADDRESS=(PROTOCOL=TCP)(HOST=node2.example.com)(PORT=1521))
The command completed successfully
1.4. 配置Service 的注意事項
1). 數據庫的服務名是用service_name 參數來指定的,一個數據庫可以有多個服務名,但是service_name最長是4kb,不要手工來修改這個參數
2)最多可以創建64個service,每個數據庫有2個隱含的service,因此留給用戶的就只有62個service。不能修改這兩個隱含service的配置,並且也不能手工啓動或停止這2個服務。 這兩個隱含的service分別是:SYS$BACKGROUND 和 SYS$USERS.
3) 當使用dbca配置Service 時,dbca 會自動更新OCR,啓動Service, 當刪除service時,會停止service,並更新OCR.
4) 使用srvctl 這個工具時,命令只更新OCR中的配置,不會更新data dctionary 和 listener 中的信息,因此還需要使用dbma_servie 包來更新data dictionary,手工更改listener配置文件。 故推薦使用DBCA工具來配置更改service配置
5) 如果客戶端想通過Service 方式連接數據庫,需要在tns條目中使用service_name 方式引用數據庫。 如:
RAC =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = rac1-vip)(PORT = 1521))
(ADDRESS = (PROTOCOL = TCP)(HOST = rac2-vip)(PORT = 1521))
(LOAD_BALANCE=YES)
(
CONNECT_DATA=
(SERVER=DEDICATED)
(SERVICE_NAME=RAC)
)
客戶端tnsnames.ora內容
wsxdb=
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST =node1-vip)(PORT = 1521))
(ADDRESS = (PROTOCOL = TCP)(HOST =node2-vip)(PORT = 1521))
(LOAD_BALANCE = yes)
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME=wsx.oracle.com)
)
l 從客戶端連接
SQL> conn hr/hr@wsxdb
l 查詢當前用戶連接到的實例
SQL>select instance_name from v$instance;
INSTANCE_NAME
--------------------------------
rac2
l 在實例2上模擬斷電
SQL>shutdown abort
l 執行查詢語句
SQL>select instance_name from v$instance;
INSTANCE_NAME
--------------------------------
rac1
刪除服務
刪除服務之前先停止服務
[oracle@node2~]$ srvctl stop service -d ocm -s wsx
[oracle@node2~]$ srvctl disable service -d ocm -s wsx
刪除服務
[oracle@node2~]$ srvctl remove service -d ocm -s wsx
wsxPREF: rac1 AVAIL: rac2
Servicewsx is disabled.
Removeservice wsx from the database ocm? (y/[n]) y
OCR中的內容被刪除,但是數據字典裏還有該Service的內容,繼續清除數據字典裏的內容
SQL> selectname,failover_method,failover_type from dba_services;
wsx basic select
刪除數據字典內容
SQL>begin
2 dbms_service.delete_service(service_name=>'wsx');
3 end;
4 /
這種負載均衡時在用戶連接這個層次上進行的,也就是在用戶請求建立連接時,根據每個節點的負載決定把連接分配到哪個實例上。而一旦建立之後,會話的所有操作就都在這個實例上完成,而不會在分配到其他實例上。
ConnectionBalancing 有客戶端和服務器端兩種實現方法。
l 客戶端均衡
客戶端均衡時ORACLE 8使用的方法,配置方法師在客戶端的tnsnames.ora文件中假如LOAD_BALANCE=YES條目。當客戶端發起連接時,會從地址列表中隨機選取一個地址,再使用隨機算法把連接請求分散到各個實例。
這種配置方法,因爲在分配連接時沒有考慮每個節點的真實負載,最後分配結果不一定是平衡的;並且隨機算法需要長時間片,如果哦在短時間內同時發起多個連接,這些連接有可能被分配到一個節點上;甚至更壞的情況下,連接可能會被分配到故障節點上。因此oracle又引入了 服務器端均衡方式。
l 服務器端均衡(server-sideLB)
服務器端負載均衡的實現依賴於listener 收集的負載信息,。在數據庫運行過程中,PMON後臺進程會收集系統的負載信息,然後登記到listener中。最少一分鐘,最多十分鐘PMON就要做一次信息更新,並且如果節點的負載越高,更新頻率就越高 ,以保證listener 能夠掌握沒個節點準確的負載情況。如果listener關閉,PMON進程會每隔1秒鐘檢查listener是否重啓。除了這個自動的、定時的更新任務外,用戶也可以使用altersystem register 命令來手工進行這個過程。
這個自動更新動作,可以從LISTENER 的日誌中看到(
/u01/app/oracle/product/10.2.0/db_1/network/log)。當實例啓動時PMON進程進行的第一次登記過程叫做server-regiser而後的更新叫做service-update
listener日誌雖然記錄了PMON進程的註冊和更新動作,但是註冊的內容卻沒有體現,要想獲得這些內容,可以通過10257事件來獲得,這個時間就是跟蹤PMON活動。
SQL> select spid ,program from v$process whereprogram like '%PMON%';
SPID PROGRAM
------------------------------------------------------------
1893 [email protected] (PMON)
SQL>oradebug setospid 1893
Oraclepid: 2, Unix process pid: 1893, image: [email protected] (PMON)
SQL>oradebug event 10257 trace name context forever,level 16;
SQL>alter system register;
SQL>oradebug event 10257 trace name context off;
SQL>oradebug tracefile_name;
/u01/app/oracle/admin/ocm/bdump/rac1_pmon_1893.trc
PMON進程不僅會向本地的listener註冊,還可以向其他節點上的litener註冊。但到底是要想何處註冊,是由Remote_listener和local_listener這兩個參數決定。local_listener不用設置,而remote_listener需要設置, 是一個tnsname項
有了PMON的自動註冊機制後,集羣的每個節點的listener都掌握所有節點的負載狀態,當收到客戶端連接請求時,就會把連接轉給負載最小的節點,這個節點有可能是自己也有可能是其它節點,也就是listener會轉發用戶的連接請求。listener的節點選擇方法根據用戶所請求的連接方式會有所不同:
l 如果用戶請求的是dedicated專有連接,listener 首先選擇負載最小的節點,如果多個節點負載相同,則從中選擇負載最小的實例。
l 如果用戶請求的是sharedserver 共享連接,除了做節點負載比較和實例負載比較之外,還要所選擇的實例上,選擇負載最小的dispatcher進行轉發
server-sideLB 和client-sideLB二者可以互相工作,這是用戶的連接請求會先從地址列表中隨機選擇一個地址,然後向改地址的listener發出請求,listener 接到請求後,根據節點的負載情況挑選出最合適的節點轉發連接請求.
8. 測試LoadBalance
LoadBalance是listener內部的機制,沒有辦法跟蹤,可通過方法驗證。
通過listener 日誌區分路由來源
在client-sideLB 配置下,用戶會從地址列表中隨機選取一個Listener,發出連接請求。listener 收到連接請求後,要對這個請求進行路由。如果配置了Service-sideLB,Listener 會把這個請求路由到負載最小的實例;也就是說,Listener可能把用戶請求路由到本地實例,也可能路由的其他實例。這兩種來源可以從Listener日誌中區分。
區分路由到本地實例和遠程實例的關鍵點在於,Listener無論把用戶請求路由到本地或遠程,本地Listener日誌條目都有 “establish” 字樣,但是沒有“instance_name”字樣;而如果連接請求是由遠程Listener 轉發過來的,則日誌條目中同時有 “instance_name”和“establish”字樣。但是對於轉發來的請求,沒有記錄這個連接是從哪個Listener轉發來的。
1.1. 測試方法
測試腳本如下
[oracle@node1~]$ cat test.sh
#!/bin/sh
count=0
while[ $count -lt $2 ]
do
count=`expr $count + 1`
sqlplus -s hr/hr@$1 @test.sql
done
[oracle@node1~]$ cat test.sql
col"instance_name" format a20
selectinstance_name from v$instance
/
exit
測試client-sideLB
l 客戶端的tnsnames.ora內容
wsxdb_cl=
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST =node1-vip.example.com)(PORT = 1521))
(ADDRESS = (PROTOCOL = TCP)(HOST =node2-vip.example.com)(PORT = 1521))
(LOAD_BALANCE = yes)
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = ocm.oracle.com)
)
)
l 數據庫的準備工作
去掉service-sdieLB 內容
SQL>alter system set remote_listener='' scope=spfile sid='*';
重啓數據庫和listener
[oracle@node1~]$ srvctl stop database -d ocm
[oracle@node1~]$ srvctl stop listener -n node1
[oracle@node1~]$ srvctl stop listener -n node2
[oracle@node1~]$ srvctl start listener -n node2
[oracle@node1~]$ srvctl start listener -n node1
[oracle@node1~]$ srvctl start database -d ocm
重啓後清空兩個節點的日誌
[oracle@node1 log]$ cat /dev/null >listener_node1.log
[oracle@node2 log]$ cat /dev/null >listener_node2.log
l 執行測試腳本,參數1000代表建立1000個連接
[oracle@node1~]$ ./test.sh wsxdb_cl 1000 >wsxdb_cl.log
l 檢查結果
[oracle@node1~]$ grep rac1 wsxdb_cl.log |wc -l
465
[oracle@node1~]$ grep rac2 wsxdb_cl.log |wc -l
535
l 提取兩個節點的listener日誌內容
[oracle@node1log]$ grep establish listener_node1.log |wc -l
465
說明實例1共接受了465個用戶連接
[oracle@node1log]$ grep -i instance_name=raclistener_node2.log |wc -l
0
說明465個連接中有0個是從實例2的listener 路由過來的,也就是說客戶端發出了483個到實例1的連接請求
[or
[oracle@node2log]$ grep establish listener_node2.log|wc -l
535
說明實例1共接受了535個用戶連接
[oracle@node2log]$ grep -i instance_name=raclistener_node2.log |wc -l
0
說明535個連接中有0個是從實例1的listener 路由過來的,也就是說客戶端發出了535個到實例2的連接請求
以上是用了Client-sideLoad Balance ,也就是客戶端從TNS地址列表中隨機選擇實例發送請求。
1.2. 測試單純的Server-sideLB
l 準備客戶端tnsnames.ora內容,關閉client-sideLB及兩個實例的listener.ora的內容
註釋掉各個實例中缺省的sid_list_listener_name條目,這樣才能保證listener 獲得的信息都是動態註冊的,而不是從文件中讀取信息
#SID_LIST_LISTENER_NODE2=
# (SID_LIST =
# (SID_DESC =
# (SID_NAME = PLSExtProc)
# (ORACLE_HOME = /u01/app/oracle/product/10.2.0/db_1)
# (PROGRAM = extproc)
# )
# )
wsxdb_cl=
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST =node1-vip.example.com)(PORT = 1521))
(ADDRESS = (PROTOCOL = TCP)(HOST =node2-vip.example.com)(PORT = 1521))
(LOAD_BALANCE = off)
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = ocm.oracle.com)
)
)
l 數據庫端準備工作
SQL>alter system set remote_listener='LISTENERS_OCM' scope=spfile sid='*';
[oracle@node1~]$ srvctl stop database -d ocm
[oracle@node1~]$ srvctl stop listener -n node1
[oracle@node1~]$ srvctl stop listener -n node2
[oracle@node1~]$ srvctl start listener -n node2
[oracle@node1~]$ srvctl start listener -n node1
[oracle@node1~]$ srvctl start database -d ocm
清空兩個節點的日誌
[oracle@node1 log]$ cat /dev/null >listener_node1.log
[oracle@node2 log]$ cat /dev/null >listener_node2.log
l 執行測試腳本
l 測試結果
實例1
[oracle@node1log]$ grep establish listener_node1.log |wc -l
1000
[oracle@node1log]$ grep -i instance_name=rac listener_node1.log |wc -l
0
一共接受了1000個用戶的連接請求,其中有0個是從實例2的liste路由過來的。所以客戶端發起了1000個到實例1的連接請求。計算client-sideLB 爲1000-0=1000
實例2
[oracle@node2log]$ grep -i instance_name=rac listener_node2.log |wc -l
417
[oracle@node2log]$ grep establish listener_node2.log |wc -l
417
說明一個接受了417個用戶連接。其中417個是從實例1的listener路由過來的。計算client-sideLB爲417-417=0,即客戶端發出了0個到實例2的連接請求。
在這個中客戶端的tnsnames.ora配置中,使用LOAD_BALANCE=off,禁用了client-sideLB 所以用戶的1000個請求全部發給了實例1,因爲在地址列表中node1-vip是放在第一條。
l Listener路由到實例的連接請求數:實例1:1000-417=583,實例2:=0-0=0
l 遠程的listener路由到本實例的連接請求數:實例1:0 實例2:=417
l Server-sideLB 的分配 583/417
1.3. 測試混合的client-sideserver-side LB
客戶端tnsnames.ora
wsxdb_cl=
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST =node1-vip.example.com)(PORT = 1521))
(ADDRESS = (PROTOCOL = TCP)(HOST =node2-vip.example.com)(PORT = 1521))
(LOAD_BALANCE = yes)
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = ocm.oracle.com)
)
數據庫端
SQL>alter system set remote_listener='LISTENERS_OCM' scope=spfile sid='*';
[oracle@node1~]$ srvctl stop database -d ocm
[oracle@node1~]$ srvctl stop listener -n node1
[oracle@node1~]$ srvctl stop listener -n node2
[oracle@node1~]$ srvctl start listener -n node2
[oracle@node1~]$ srvctl start listener -n node1
[oracle@node1~]$ srvctl start database -d ocm
清空兩個節點的日誌
[oracle@node1 log]$ cat /dev/null >listener_node1.log
[oracle@node2 log]$ cat /dev/null >listener_node2.log
執行測試腳本
[oracle@node1~]$ ./test.sh wsxdb_cl 1000 >wsxdb_mix.log
查看測試結果
[oracle@node1~]$ grep rac1 wsxdb_mix.log |wc -l
289
[oracle@node1~]$ grep rac2 wsxdb_mix.log |wc -l
711
實例1
[oracle@node1log]$ grep -i instance_name=rac listener_node1.log |wc -l
190
[oracle@node1log]$ grep establish listener_node1.log |wc -l
656
共接受了656個用戶的連接請求其中有190個使用實例2的listener路由過來的。計算client-sideLB 656-190=466,即客戶端發出了466個到實例1的連接請求
[oracle@node2log]$ grep -i instance_name=rac listener_node2.log |wc -l
367
[oracle@node2log]$ grep -i establish listener_node2.log |wc -l
901
共接受了901個用戶的連接請求其中有367個使用實例1的listener路由過來的。計算client-sideLB 901-367=534,即客戶端發出了534個到實例2的連接請求
這種方法混好了client-side和server-side兩種LB,結果說明如下
l client-sideLB=466/534
l listener路由到本實例的連接請求數量:實例1466-367=99 實例2534-190=344
l 遠程的listener 路由到本實例的連接請求數量:實例1190 實例2367
l server-sideLB的分配 190/367