oracle rac HA and LB


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,所以即使不添加這個條目,客戶端也會獲得這種能力。

1.2.       TAF

所謂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

第一個窗口需要重新連接(連接時故障轉移)

第二個窗口過了一段時間後遷移到另一個實例

1.2.3.      測試PRECONNECT

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

1.3.       Service-Side TAF

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)

     )

1.5.     測試Service-Side TAF

客戶端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  /

 

2.     LOADBALANCE

2.1.     CONNECTION BALANCING

這種負載均衡時在用戶連接這個層次上進行的,也就是在用戶請求建立連接時,根據每個節點的負載決定把連接分配到哪個實例上。而一旦建立之後,會話的所有操作就都在這個實例上完成,而不會在分配到其他實例上。

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

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章