My Books

My Slides

rss 아이콘 이미지

GCS (Glocal Cache Service)와 관련된 인터널 문서를 읽다보면 GCS SHADOW란 용어를 접하게 됩니다. 하지만 GCS SHADOW의 명확한 동작원리에 대해서 언급한 문서를 찾기가 힘듭니다. 그나마 Juian Dyke의 2008년도 PDF 문서에 다음과 같은 정의와 구성도를 확인할 수 있습니다.


"GCS Shadow describes blocks held by other instances, but mastered locally" [Julian Dyke]


그림-1. GCS 메모리 구성도 (참조문헌: Julian Dyke PDF)


즉, GCS SHADOW란 마스터에 속한 블록을 다른 노드에서 사용할때 이를 표현하는 구조체입니다. (설명이 조금 어렵죠?) 그리고 "그림-1"에서 보여지는 것처럼 GCS SHADOW는 락 엘리먼트를 가지고 있지 않습니다. 그런데 이 설명과 그림만으로는 GCS SHADOW를 정확히 이해하기는 어렵습니다. (적어도 저의 경우는 그랬습니다) 그렇다면 GCS SHADOW는 어떻게 동작하고 어떤 목적으로 사용될까요? 이를 분석하기 위해 테스트를 진행한 결과를 다음과 같이 정리합니다.



1. GCS SHADOW의 동작 원리 및 목적


1-1. GCS SHADOW의 동작 원리

  1. 마스터 노드에서 해당 블록을 액세스할 경우에는 GCS CLIENT가 1개 생성되고 GCS SHADOW는 생성되지 않습니다.
  2. 리모트 노드에서 해당 블록을 액세스할 경우에는 리모트 노드에 GCS CLIENT가 1개 생성되고, 마스터 노드에는 이와 관련된 GCS SHADOW가 1개 생성됩니다. 여러 개의 리모트 노드에서 해당 블록을 액세스한다면 리모트 노드 개수만큼의 GCS SHADOW가 마스터 노드에 생성됩니다.
Note
설명의 편의성을 위해 GCS CLIENT와 GCS SHADOW로 나누었으나, 오라클 내부적으로는 모두 GCS SHADOW로 관리됩니다. GCS CLIENT는 락 엘리먼트가 있는 GCS 구조체 (X$KJBL내에 생성됨)이고 GCS SHADOW는 락 엘리먼트가 없는 GCS 구조체라고 이해하시면 좋습니다. 개인적인 생각이지만 오라클은 용어 및 약어 선정을 아주 잘하는 회사인것 같습니다. GCS SHADOW란 용어도 알고 보면 아주 적절한 용어라고 보입니다. 즉, 그림자와 같이 형체(X$KJBL 구조체)는 동일하지만 알맹이(락 엘리먼트)는 없는 것을 잘 표현하고 있습니다.


그런데 여기서 의문점이 하나 생기게됩니다. "오라클은 이러한 중복 관리를 부하를 감수하면서도 GCS SHADOW를 사용할까?"라는 것이죠. 예를 들어, 마스터 노드의 블록들을 리모트 노드에서 대량으로 액세스하게 되면, 마스터 노드에는 블록 개수만큼의 GCS SHADOW 구조체를 shared pool의 gcs shadow 영역에 생성해야하는 부하가 발생하게 됩니다. 이와 같은 오퍼레이션은 CPU 및 shared pool 사용 측면에서 모두 부하를 유발하게 됩니다. 그렇다면 왜 필요한걸까요?


1-2. GCS SHADOW의 목적
테스트를 통해 추론된 결론은 "GCS SHADOW의 목적은 마스터 노드에 속한 블록들의 사용 노드를 확인하기 위한 것"입니다. 그림-2~그림-4를 보시면 쉽게 이해될것 같습니다.


그림-2. 초기 상태


그림-3. RAC3 노드에서 UPDATE 수행  


그림-4. RAC2번 노드에서 SELECT 수행

Note
해당 블록의 마스터 노드는 OOW1이므로 OOW1의 GCS 리소스 구조체를 접근한 후, 해당 구조에 아래 딸린 GCS CLIENT/SHADOW 구조체를 확인합니다. 확인 결과, GCS SHADOW의 정보를 통해 해당 블록은 현재 3번 노드에 있다는 사실을 알 수 있습니다. 이와 같이 GCS SHADOW는 마스터 블록의 사용 노드를 확인하기 위한 용도로 사용된다고 할 수 있습니다. 


이러한 결론을 이끌어냈던 테스트 방법에 대해서 자세히 살펴보도록 하겠습니다.



2. GCS SHADOW의 동작원리 분석을 위한 테스트 내역


2-1. 테스트 데이터 생성

SCOTT @ OOW1 > drop table t1 purge;
SCOTT @ OOW1 > create table t1 (c1 number, dummy char(10));
SCOTT @ OOW1 > insert into t1 select level, level from dual connect by level<=10000;
SCOTT @ OOW1 > commit;
SCOTT @ OOW1 > create index t1_idx01 on t1(c1) nologging;
SCOTT @ OOW1 > exec dbms_stats.gather_table_stats(user,'T1');


2-2. 초기 상태 확인

-- 레코드 1건 조회

SCOTT @ OOW1 > select /*+ index(t1 t1_idx01) */
       count(*),
       max(dbms_rowid.rowid_relative_fno(rowid)) file_no,
       max(dbms_rowid.rowid_block_number(rowid)) blk_no
from   t1
where  c1=1
and    dummy <> '9999';

-- 해당 레코드가 속한 블록의 마스터 노드 확인 (마스터 노드가 0번 즉, OOW1번 노드임을 확인)

SCOTT @ OOW1 > @fnd_blk_master T1 1

        C1     OBJ_NO    FILE_NO     BLK_NO
---------- ---------- ---------- ----------
         1      93240          8        134

INST      CLASS KJBRNAME                       KJBLNAME2       KJBRGRANT KJBRMASTER
---- ---------- ------------------------------ --------------- --------- ----------
OOW1          1 [0x86][0x8],[BL][ext 0x0,0x0]  134,8,BL        KJUSEREX           0


2-3. OOW3 노드에서 UPDATE 수행 후의 변경 사항 확인

-- 테스트의 편의성을 위해 모든 노드에서 alter system flush buffer cache 수행 후 3번 노드에서 update 수행

SCOTT @ OOW3 > update  t1 set c1=-1 where c1=1;

-- 결과 확인
 
SCOTT @ OOW1 > @fnd_gcs_detail 8 134

                            X$BH X$BH       X$BH                   X$BH
INST ADDR                  CLASS STATE      LE_ADDR                 TCH
---- ---------------- ---------- ---------- ---------------- ----------
OOW3 00007F37A4573068          1 XCUR       0000000072FF5948          1

     X$KJBR               X$KJBR X$KJBR
INST RESP                 MASTER NAME
---- ---------------- ---------- ------------------------------
OOW1 000000006946A358          0 [0x86][0x8],[BL][ext 0x0,0x0]

     X$KJBL               X$KJBL X$KJBL    X$KJBL     X$BH                   X$BH X$BH
INST LOCKP                 OWNER GRANT     LOCKST     LE_ADDR               CLASS STATE
---- ---------------- ---------- --------- ---------- ---------------- ---------- ----------
OOW1 0000000069722CF8          2 KJUSEREX  GRANTED
OOW3 0000000072FF59D0          2 KJUSEREX  GRANTED    0000000072FF5948          1 XCUR


결과분석
1. 3번 노드에 XCUR 버퍼 1개 할당
2. 해당 블록의 마스터 노드는 0번 (즉, OOW1)임을 재확인
3. 3번 노드에 GCS CLIENT 1개 생성. 그리고 1번 노드에 GCS SHADOW 1개 생성됨


2-4. OOW2 노드에서 SELECT 수행 후의 변경 사항 확인

-- 2번 노드에서 SELECT 수행 

SCOTT @ OOW2 > select * from t1 where c1=2;

-- 결과 확인
 
SCOTT @ OOW1 > @fnd_gcs_detail 8 134

                            X$BH X$BH       X$BH                   X$BH
INST ADDR                  CLASS STATE      LE_ADDR                 TCH
---- ---------------- ---------- ---------- ---------------- ----------
OOW2 00007F6A25D42AD8          1 CR         00                        1

OOW3 00007F37A4572EE8          1 XCUR       0000000072FF5948          1
     00007F37A4573068          1 CR         00                        0

     X$KJBR               X$KJBR X$KJBR
INST RESP                 MASTER NAME
---- ---------------- ---------- ------------------------------
OOW1 000000006946A358          0 [0x86][0x8],[BL][ext 0x0,0x0]

     X$KJBL               X$KJBL X$KJBL    X$KJBL     X$BH                   X$BH X$BH
INST LOCKP                 OWNER GRANT     LOCKST     LE_ADDR               CLASS STATE
---- ---------------- ---------- --------- ---------- ---------------- ---------- ----------
OOW1 0000000069722CF8          2 KJUSEREX  GRANTED
OOW3 0000000072FF59D0          2 KJUSEREX  GRANTED    0000000072FF5948          1 XCUR


결과분석
1. 3번 노드의 XCUR 버퍼를 1개 복사해서 새로운 XCUR 버퍼 할당. 기존 XCUR 버퍼는 CR 버퍼로 락 다운그레이드됨 (ADDR로 확인)
2. 2번 노드에 CR 버퍼 복사 (3번 노드의 CR 버퍼를 전송받음)
3. CR 버퍼에 대해서는 락 엘리먼트 및 GCS CLIENT 및 SHADOW를 생성하지 않는 것을 확인


스크립트


이 글에 사용된 스크립트는 다음과 같습니다.

fnd_blk_master 
fnd_gcs_detail


글을 마치며


설명을 단순화하기 위해서 테스트의 예제를 UPDATE로 했지만, SELECT 및 UPDATE등 다양한 테스트를 한 후 fnd_gcs_detail 스크립트를 이용해서 결과를 분석해보시면 RAC 내부 동작원리를 좀 더 파악할 수 있으리라 생각됩니다. 그리고 이번 포스팅을 끝으로 3개월 동안 진행한 "RAC 동작원리에 대한 연재"를 마무리하려고 합니다. GCS, GES 및 RAC 관련 파라미터에 대한 설명은 연재 내에서 다루기보다는 "성능 분석"이라는 새로운 주제 내에서 다룰 예정입니다. 지금까지는 다소 지루한 개론 부분이었다면 앞으로는 실용적인 측면을 가미한 내용으로 찾아뵙도록 하겠습니다.  


저작자 표시 비영리 변경 금지
신고
크리에이티브 커먼즈 라이선스
Creative Commons License

[16] X$BH, X$LE, X$KJBL을 이용한 마스터 노드 확인 방법

RAC 2016.07.29 04:28 Posted by 시연아카데미

현재 RAC GRD (Global Resource Directory)에 대해서 연구중입니다. GRD의 동작원리를 파악하기 위해서는 리소스 마스터 노드 및 사용 노드에 대한 분석이 필수적이며 이를 위해 주로 3개의 X$ 테이블을 이용합니다.

  • X$BH   (버퍼 헤더 구조 파악)  : V$BH의 베이스 테이블
  • X$LE   (락 엘리먼트 구조 파악) : V$LOCK_ELEMENT의 베이스 테이블
  • X$KJBL (BL 락 구조 파악)     : V$GES_ENQUEUE의 베이스 테이블


V$를 이용하지 못하는 이유는 V$에는 각 뷰간의 조인에 필요한 연결고리 칼럼이 제공되지 않기 때문입니다. 따라서 부득이하게 X$를 이용합니다. X$ 간의 연결고리 칼럼은 다음과 같습니다.

  • X$BH.LE_ADDR = X$LE.LE_ADDR 
  • X$LE.LE_KJBL = X$KJBL.KJBLLOCKP 

 
 
그런데 X$를 이용하면 불편한 점이 몇 가지 있습니다. SYS 유저로만 조회가 가능하다는 점과 GV$ 뷰와 같이 모든 노드의 X$ 정보를 한번에 확인할 수 있는 방법이 없다는 점입니다. 이러한 불편함을 해소하기 위해 다음과 같이 별도의 뷰(X_$)를 생성한 후 해당 뷰에 권한을 부여하고, DB Link를 이용해서 RAC 모든 노드의 X_$ 뷰를 한번에 조회할 수 있는 GX$ 뷰를 생성합니다. 그리고 GX$ 뷰를 이용해서 오브젝트 및 블록의 마스터 노드 및 사용 노드 정보를 확인할 수 있는 스크립트를 생성합니다. (시노님과 DB Link를 public으로 설정한 점은 단순히 편의성 때문이므로 보안을 요하는 경우에는 private로 설정하시면 됩니다)


[수정사항. 2016.08.02]

테스트를 진행하다보니 스크립트가 꽤 많이 필요합니다. 따라서, 구글 사이트를 이용해서 스크립트를 관리하기로 했습니다. https://sites.google.com/site/siyeon70/sql-scripts 따라서, 아래의 스크립트는 사용하지 않습니다.


테스트 환경 : RAC 3 Node: 12.1.0.2 64bit


1) 1번 노드에서 SYS 유저로 X_$ 뷰 생성 및 시노님 생성

sqlplus / as sysdba
create or replace view x_$bh_1   as select 'OOW1' inst_name, a.* from x$bh   a;
create or replace view x_$le_1   as select 'OOW1' inst_name, a.* from x$le   a;
create or replace view x_$kjbl_1 as select 'OOW1' inst_name, a.* from x$kjbl a;


create public synonym x_$bh_1   for x_$bh_1;
create public synonym x_$le_1   for x_$le_1;
create public synonym x_$kjbl_1 for x_$kjbl_1;


grant all on x_$bh_1   to public;
grant all on x_$le_1   to public;
grant all on x_$kjbl_1 to public;

2) 2번 노드에서 SYS 유저로 X_$ 뷰 생성 및 시노님 생성

sqlplus / as sysdba
create or replace view x_$bh_2   as select 'OOW2' inst_name, a.* from x$bh   a;
create or replace view x_$le_2   as select 'OOW2' inst_name, a.* from x$le   a;
create or replace view x_$kjbl_2 as select 'OOW2' inst_name, a.* from x$kjbl a;

create public synonym x_$bh_2   for x_$bh_2;
create public synonym x_$le_2   for x_$le_2;
create public synonym x_$kjbl_2 for x_$kjbl_2;


grant all on x_$bh_2   to public;
grant all on x_$le_2   to public;
grant all on x_$kjbl_2 to public;


3) 3번 노드에서 SYS 유저로 X_$ 뷰 생성 및 시노님 생성

sqlplus / as sysdba
create or replace view x_$bh_3   as select 'OOW3' inst_name, a.* from x$bh   a;
create or replace view x_$le_3   as select 'OOW3' inst_name, a.* from x$le   a;
create or replace view x_$kjbl_3 as select 'OOW3' inst_name, a.* from x$kjbl a;

create public synonym x_$bh_3   for x_$bh_3;
create public synonym x_$le_3   for x_$le_3;
create public synonym x_$kjbl_3 for x_$kjbl_3;

grant all on x_$bh_3   to public;
grant all on x_$le_3   to public;
grant all on x_$kjbl_3 to public;


4) 1번 노드에서 SYS 유저로 DB Link 생성

TNSNAMES.ORA 보기

sqlplus / as sysdba

create public database link OOW1 using 'OOW1';
create public database link OOW2 using 'OOW2';
create public database link OOW3 using 'OOW3';


5) 1번 노드에서 SCOTT 유저로 GX$ 뷰 생성

create or replace view gx$bh as
select * from sys.x_$bh_1
union all
select * from sys.x_$bh_2@oow2
union all
select * from sys.x_$bh_3@oow3;

create or replace view gx$le as
select * from sys.x_$le_1
union all
select * from sys.x_$le_2@oow2
union all
select * from sys.x_$le_3@oow3;

create or replace view gx$kjbl as
select * from sys.x_$kjbl_1
union all
select * from sys.x_$kjbl_2@oow2
union all
select * from sys.x_$kjbl_3@oow3;


6) 스크립트 생성
-------------------------------------------------------------------
-- 파일명 : fnd_obj_master.sql
-- 목적  : 입력된 오브젝트명을 이용해서 해당 블록들의 마스터 노드 및 사용 노드 확인
-- 사용법 : @fnd_obj_master <오브젝트명>
-------------------------------------------------------------------

set  verify off linesize 1000  pages 1000

define __OBJECT_NAME=&1

select /*+ leading (a b c) */
       a.inst_name,
       a.class,
       a.dbablk,
       c.kjblname,
       c.kjblgrant,
       c.kjblrequest,
       c.kjblmaster,
       c.kjblowner
from   gx$bh   a,
       gx$le   b,
       gx$kjbl c
where  a.obj     = (select object_id from user_objects where object_name=&__OBJECT_NAME)
and    a.state  <> 3 -- exclude CR block
and    a.le_addr   = b.le_addr
and    b.le_kjbl   = c.kjbllockp
and    a.inst_name = b.inst_name
and    b.inst_name = c.inst_name
order by 1,3;


sselect /*+ leading (a b c) */
       a.inst_name,
       c.kjblmaster,
       c.kjblowner,
       count(*) cnt
from   gx$bh   a,
       gx$le   b,
       gx$kjbl c
where  a.obj     = (select object_id from user_objects where object_name=&__OBJECT_NAME)
and    a.state  <> 3 -- exclude CR block
and    a.le_addr   = b.le_addr
and    b.le_kjbl   = c.kjbllockp
and    a.inst_name = b.inst_name
and    b.inst_name = c.inst_name
group by a.inst_name, c.kjblmaster, c.kjblowner
order by 1;


-------------------------------------------------------------------
-- 파일명 : fnd_blk_master.sql
-- 목적  : 특정 블록 1개의 마스터 노드 및 사용 노드 확인
-- 사용법 : @fnd_blk_master <오브젝트명> <블록번호>
-------------------------------------------------------------------

set  verify off linesize 1000  pages 1000

define __OBJECT_NAME=&1
define __BLOCK_NO=&2

select /*+ leading (a b c) */
       a.inst_name,
       a.class,
       a.dbablk,
       c.kjblname,
       c.kjblname2,
       c.kjblgrant,
       c.kjblrequest,
       c.kjblmaster,
       c.kjblowner
from   gx$bh   a,
       gx$le   b,
       gx$kjbl c
where  a.obj     = (select object_id from user_objects where object_name='&__OBJECT_NAME')
and    a.dbablk  = &__BLOCK_NO           
and    a.state  <> 3 -- exclude CR block
and    a.le_addr   = b.le_addr
and    b.le_kjbl   = c.kjbllockp
and    a.inst_name = b.inst_name
and    b.inst_name = c.inst_name
order by 1,3;


제 경우, 연구의 편의성을 위해서 GX$ 뷰를 생성한 것이므로, GX$ 뷰 생성이 여의치 않은 경우에는 X$ 테이블을 이용해서 스크립트를 작성하셔도 됩니다. 단, 그럴 경우 모든 노드에서 각각 수행해야 하는 불편함이 있습니다. 앞으로 진행되는 연구에서는 위의 2개의 스크립트를 이용할 예정입니다.

저작자 표시 비영리 변경 금지
신고
크리에이티브 커먼즈 라이선스
Creative Commons License

[15] RAC Interconnect, HAIP에 대한 가벼운 정리

RAC 2016.07.26 22:19 Posted by 시연아카데미

들어가기에 앞서


이번 시간에 다룰 내용은 RAC 네트워크의 핵심 부분인 Interconnect와 관련된 몇 가지 내용입니다. 네트워크 분야는 제가 잘 모르는 분야이므로 학습한 내용을 바탕으로 DBA들이 알면 도움이 될 만한 몇 가지 내용들과 제가 궁금했던 몇 가지 내용을 정리하는 수준으로 글을 작성했습니다. 여기 나오는 대부분의 내용은 아래 책의 내용을 참고했습니다.



질문1. 인터커넥트용 NIC는 어떻게 확인할 수 있나요?


오라클은 다양한 방법으로 인터커넥트용 NIC를 확인할 수 있는 방법을 제공합니다.


1. $GRID_HOME/bin/oifcfg 명령어를 이용한 방법

[oracle@rac1 SS]$ oifcfg getif
eth0  192.168.56.0  global  public
eth1  192.168.10.0  global  cluster_interconnect


Note
명령어 수행 결과 eth1 NIC가 인터커넥트용임을 알 수 있습니다.


[oracle@rac1 SS]$ oifcfg iflist -p -n
eth0  192.168.56.0  PRIVATE  255.255.255.0
eth1  192.168.10.0  PRIVATE  255.255.255.0
eth1  169.254.0.0   UNKNOWN  255.255.0.0
eth2  10.0.4.0      PRIVATE  255.255.255.0


Note
명령어 수행 결과 eth1에는 2개의 IP 대역이 설정되어 있음을 알 수 있습니다. 169.254.0.0은 11gR2부터 제공되는 HAIP 대역대입니다. 따라서 명령어 수행결과 에 169.254.0.0이 출력된다면 해당 시스템은 HAIP를 사용하는 것입니다. (HAIP는 질문-2 참조)


2. X$KSXPIA fixed 테이블 및 GV$CLUSTER_INTERCONNECTS 뷰를 이용한 방법 select pub_ksxpia  as is_public,
       name_ksxpia as name,
       ip_ksxpia   as ip_address
from   x$ksxpia;

IS_PUBLIC  NAME            IP_ADDRESS
---------- --------------- ----------------
N          eth1:1          169.254.237.87


select inst_id,
       name,
       ip_address,
       is_public
from   gv$cluster_interconnects
order by inst_id;

   INST_ID NAME            IP_ADDRESS       IS_
---------- --------------- ---------------- ---
         1 eth1:1          169.254.237.87   NO
         2 eth1:1          169.254.240.162  NO


Note
쿼리 수행 결과를 통해 인터커넥트용 NIC는 eth1:1이며 실제 IP도 확인할 수 있습니다. 여기서 보이는 인터커넥트용 IP가 /etc/hosts 파일에 설정한 private ip와 다른 경우에는 11gR2부터 제공하는 HAIP를 사용하고 있다고 보시면 됩니다. (HAIP는 질문-2 참조)


3. ALERT LOG를 이용한 방법

LICENSE_MAX_SESSION = 0
LICENSE_SESSIONS_WARNING = 0
Initial number of CPU is 2
Number of processor cores in the system is 2
Number of processor sockets in the system is 1
Private Interface 'eth1:1' configured from GPnP for use as a private interconnect.
  [name='eth1:1', type=1, ip=169.254.237.87, mac=08-00-27-27-95-03, net=169.254.0.0/16, mask=255.255.0.0, use=haip:cluster_interconnect/62]
Picked latch-free SCN scheme 3


Note
Alert Log에서도 인터커텍트용 NIC, IP, HAIP 사용 여부등을 확인할 수 있습니다.



질문-2. HAIP란 무엇인가요?


HAIP (Highly Available IP)에 대한 설명은 아래의 2개의 문서를 참고하시면 좋습니다.

간단히 요약하면, 기존에는 NIC의 이중화를 위해 OS 레벨의 NIC 본딩과 같은 기법을 사용했으나, 11gR2부터는 이러한 이중화 역시 GI (Grid Infrastructure)에서 관리하겠다는 것입니다.예를 들어 1개의 private network을 설정했다면 (예 eth1: 192.168.10.1) 해당 NIC에 169.254로 시작되는 HAIP가 자동으로 설정됩니다. (예시-1 참조) HAIP는 최대 4개까지 설정이 가능하며 이를 통해 가용성과 성능 향상을 꾀함과 동시에 기존에 OS 의존적이던 부분들을 점차적으로 GI 안의 관리포인트로 끌어들인다는 의미로도 해석할 수 있습니다.


예시-1. HAIP 예제

[oracle@rac1 SS]$ ifconfig -a
eth1      Link encap:Ethernet  HWaddr 08:00:27:27:95:03
          inet addr:192.168.10.1  Bcast:192.168.10.255  Mask:255.255.255.0
          inet6 addr: fe80::a00:27ff:fe27:9503/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:7991199 errors:0 dropped:0 overruns:0 frame:0
          TX packets:7288897 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:5681272569 (5.2 GiB)  TX bytes:4967857149 (4.6 GiB)

eth1:1    Link encap:Ethernet  HWaddr 08:00:27:27:95:03
          inet addr:169.254.237.87  Bcast:169.254.255.255  Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1


[oracle@rac1 SS]$ cat /etc/hosts
127.0.0.1   localhost localhost.dbaora.com
#public
192.168.56.2    ap1         ap1.dbaora.com
192.168.56.71   rac1        rac1.dbaora.com
192.168.56.72   rac2        rac2.dbaora.com
#private
192.168.10.1    rac1-priv   rac1-priv.dbaora.com
192.168.10.2    rac2-priv   rac2-priv.dbaora.com



질문3. 인터커넥트용 NIC 속도는 어떻게 확인할 수 있을까요?


ethtool 명령어를 이용해서 NIC 속도를 확인할 수 있습니다. 명령어 수행 후에 Speed 부분을 확인하면 됩니다.


[oracle@rac1 SS]$ ethtool eth1
Settings for eth1:
        Supported ports: [ TP ]
        Supported link modes:   10baseT/Half 10baseT/Full
                                100baseT/Half 100baseT/Full
                                1000baseT/Full
        Supported pause frame use: No
        Supports auto-negotiation: Yes
        Advertised link modes:  10baseT/Half 10baseT/Full
                                100baseT/Half 100baseT/Full
                                1000baseT/Full
        Advertised pause frame use: No
        Advertised auto-negotiation: Yes
        Speed: 1000Mb/s
        Duplex: Full
        Port: Twisted Pair
        PHYAD: 0
        Transceiver: internal
        Auto-negotiation: on
        MDI-X: off (auto)
Cannot get wake-on-lan settings: Operation not permitted
        Current message level: 0x00000007 (7)
                               drv probe link
        Link detected: yes
  



질문-4. 네트워크 관련 주요 파라미터는 무엇이고 어떻게 확인할 수 있을까요?


인터커넥트의 성능을 위해서는 TCP 관련 파라미터인 net.core.rmem_max, net.core.wmem_max, net.ipv4.tcp_rmem, net.ipv4.tcp_wmem 설정이 매우 중요합니다. 해당 내용에 대해서는 아래의 블로그를 꼭 한번씩 보시기 바랍니다. 아주 자세하고 정확하게 기술되어 있습니다.

해당 설정 값들은 sysctl -p로 확인할 수 있으며, 아래와 같이 V$OSSTAT 뷰를 통해서도 확인이 가능합니다.


col "net.ipv4.tcp_wmem"  for a30
col "net.ipv4.tcp_rmem"  for a30
col "net.core.wmeme_max" for a10
col "net.core.rmeme_max" for a10
select
    max(decode(stat_name,'TCP_SEND_SIZE_MIN',       value))||' '||
    max(decode(stat_name,'TCP_SEND_SIZE_DEFAULT',   value))||' '||
    max(decode(stat_name,'TCP_SEND_SIZE_MAX',       value)) "net.ipv4.tcp_wmem",
    max(decode(stat_name,'TCP_RECEIVE_SIZE_MIN',    value))||' '||
    max(decode(stat_name,'TCP_RECEIVE_SIZE_DEFAULT',value))||' '||
    max(decode(stat_name,'TCP_RECEIVE_SIZE_MAX',    value)) "net.ipv4.tcp_rmem",
    max(decode(stat_name,'GLOBAL_SEND_SIZE_MAX',    value)) "net.core.wmem_max",
    max(decode(stat_name,'GLOBAL_RECEIVE_SIZE_MAX', value)) "net.core.rmem_max"
from v$osstat


net.ipv4.tcp_wmem  net.ipv4.tcp_rmem   net.core.wmem_max net.core.rmem_max
------------------ ------------------- ----------------- -----------------
4096 16384 4194304 4096 87380 6291456  1048576           4194304



질문-5. 특정 시점의 RAC 노드 간의 PING 속도를 확인할 수 있는 방법이 있을까요?


오라클은 11g부터 ping 프로세스를 이용해서 노드 간의 ping 속도 (500바이트, 8Kb)를 측정합니다. 조금 아쉬운 부분은 ping 프로세스가 주기적으로 (대략 10여초에 1회) 체크한 성능 정보는 실시간 뷰로는 제공되지 않으며 DBA_HIST_INTERCONNECT_PINGS 테이블을 통해서 집계된 정보만을 제공한다는 점입니다.



글을 마치며


이상으로 간단하게 RAC 네트워크 부분을 정리했습니다. 제가 하드웨어 적인 백그라운드 지식이 없다 보니 설치, 구성, HA, 서비스, ASM, 네트워크 부분의 학습에 오랜 시간이 걸렸습니다. 이제부터는 본격적으로 캐시 퓨전 동작원리 및 성능에 대해서 집중적으로 다룰 예정입니다. 기존 내용보다는 좀 더 흥미가 있으리라 생각됩니다.


저작자 표시 비영리 변경 금지
신고
크리에이티브 커먼즈 라이선스
Creative Commons License

들어가기에 앞서


ASM 자료 조사 시에 찾은 유용한 자료들을 먼저 소개합니다.

  • 굳어스 ASM 정리 자료 (기본 개념 정리부터 동작원리 및 테스트까지 정리가 잘 되어있습니다)
  • ASM FAQ 자료 (FAQ 형식으로 정리한 자료입니다. 아주 간단 명료하게 설명이 잘되어있습니다)
  • ASM 인터널 자료 : 구글에서 "A closer Look inside Oracle ASM - Luca Canali - CERN" 검색 후 나오는 첫 번째 PPT 자료

ASM 자료들은 대부분 오래된 자료들입니다. 하지만 ASM 아키텍처의 변화가 크지 않았다는 점을 고려하면 아직도 유용한 자료라고 생각됩니다. 따라서 ASM 학습 시에 숙지하면 좋은 내용들입니다. 이번 포스팅에서는 기존 자료의 내용을 중복해서 다루기보다는 제가 궁금했던 몇 가지 사항들을 정리해보려고 합니다. 
 
 


질문1. ASM 인스턴스는 무엇이고, 반드시 필요할까요?


ASM(Automatic Storage Management)을 처음 접할때 가장 당황스러운 부분은 "ASM을 사용하기 위해서 별도의 ASM 인스턴스가 필요하다"는 사실입니다. ASM의 용도가 볼륨 매니저라는 점을 놓고 볼때 "별도의 인스턴스까지 운영해야할까?" 라는 의문점을 갖게 되는건 엔지니어로서는 자연스러운 일일겁니다. 저 역시 이부분이 궁금해서 여러가지 자료를 찾아봤지만, 명확한 내용을 기술해놓은 자료를 찾아볼 수는 없었습니다. 그마다 "A closer Look inside Oracle ASM - Luca Canali - CERN" 문서에 어느 정도 설득력 있는 내용이 정리되어있습니다.

  • 가벼운 인스턴스를 이용한 관리 (ASM 인스턴스는 리두로그, 데이터파일 등이 존재하지 않음)
  • SQL 명령어를 이용해서 환경 설정 가능 (사용 편의성)
  • V$ 뷰들을 통해 메타 정보 및 ASM 디스크 성능 정보 제공 (모니터링 편의성)
  • udump 및 bdump에 로그 기록 (문제 추적의 편의성)

하지만, 아무리 가벼운 인스턴스라고 할지라도 11g까지는 1노드당 1개의 ASM 인스턴스가 필요하다는 점과 ASM 인스턴스가 다운될 경우 (이런 경우가 거의 없다고는 하지만) DB 인스턴스도 즉시 다운된다는 사실은 운영 입장에서 보면 민감한 사실임에 틀림없습니다.


Note
12c의 Flex ASM을 사용할 경우에 노드의 개수와 무관하게 일정 개수(ASM 카디날리티)의 ASM 인스턴스만을 사용하면 됩니다.




질문2. ASM 환경에서 IO처리를 위해 ASM 인스턴스를 경유할까요?


ASM 디스크의 extent map 은 ASM 인스턴스가 관리하므로, IO 시에 ASM 인스턴스를 경유할 것 같다는 생각을 할 수 있습니다. 하지만, ASM 인스턴스를 경유해서 IO를 처리한다면 성능 지연이 발생할 가능성이 높습니다. 따라서 오라클은 ASM 인스턴스를 경유하지 않고도 IO를 처리할 수 있도록, ASMB 프로세스를 이용해서 extent map 정보를 DB 인스턴스에게 제공합니다. ASMB 프로세스는 ASM 인스턴스, DB 인스턴스 각각 1개씩 구동되며, 각 ASMB 프로세스들은 오라클 쉐도우 프로세스를 각각 1개씩 fork 시켜 ASM 인스턴스에 접속합니다. (그림-1. 참조) 이러한 연결 고리(‘브릿지’)를 이용해서 DB 인스턴스와 ASM 인스턴스 간에 메타 정보를 전송하게 됩니다. Extent map 정보는 File Open 시에 전송 (10g는 전체 set 전송, 11g부터는 파일별로 n개의 정보만 전송한 후 필요 시에 전송)되므로, 이후의 DB IO는 ASM 인스턴스를 경유하지 않고도 처리가 가능하게 됩니다.


그림-1. DB 인스턴스와 ASM 인스턴스 메타 정보 전송 및 리밸런싱 수행 구성도

 

Note
Extent Map 정보는 ASM 인스턴스의 X$KFFXP Fixed 테이블을 통해서만 확인할 수 있습니다. (DB 인스턴스에도 동일한 이름의 테이블이 있지만 0건임)




질문3. ASM 환경에서 디스크 리밸런싱은 어떻게 처리될까요?


ASM의 장점 중의 하나는 자동으로 디스크 리밸런싱을 수행하므로 DBA가 별도의 IO 튜닝 작업을 하지 않아도 된다는 것입니다. 예를 들어, 디스크 그룹에 디스크가 추가된 경우에 자동으로 리밸런싱을 수행합니다. (수동 수행도 가능) 이를 위해 ASM 인스턴스는 RBAL (Rebalance Master) 프로세스를 이용해서 리밸런싱 작업을 코디네이트하고 1개 이상의 ARB 프로세스들을 이용해서 실제 리밸런싱 처리를 수행하도록 합니다. ARB 프로세스는 리밸런싱 업무 시에만 구동됩니다.




질문4. DB 인스턴스와 ASM 인스턴스에 존재하는 V$ASM_ 뷰들은 동일한 내용을 제공하나요?


DB 인스턴스와 ASM 인스턴스에서는 동일한 이름의 V$ASM_ 뷰들이 존재합니다. 그렇다면 "제공되는 내용도 동일할까?" 라는 궁금증이 생기게 됩니다. 결론부터 이야기하면 ASM 인스턴스는 ASM 디스크그룹을 제공하는 입장이고 DB 인스턴스는 ASM 디스크그룹을 사용하는 입장이라는 점을 제외하곤 거의 동일한 정보를 제공합니다. 예를 들면, ASM 인스턴스의 V$ASM_DISKGRUOP.STATE에는 'MOUNTED'로 표시되는 것에 비해서, DB 인스턴스에서는 'CONNECTED'라고 표시되는 정도의 차이점이 있습니다.

 

그리고 아래의 뷰들을 조회하면, ASMB 프로세스를 이용한 '브릿지'를 통해 ASM 인스턴스로부터 결과를 전송 받게 됩니다.  즉, ASM 구성정보, 디스크 정보 등 다이나믹하게 변경 가능한 정보들은 항상 ASM 인스턴스를 통해서 최신 정보를 전달 받는다고 보면 될 것 같습니다.


V$ASM_ATTRIBUTE;
V$ASM_DISK
V$ASM_DISK_STAT;
V$ASM_FILE;



글을 마치며


ASM은 다소 싱겁게 마무리된 측면이 있습니다. 일반적인 개념을 정리하기에는 이미 정리가 너무 잘 되어있고, "How"를 고민하기에는 그렇게 많은 고민 포인트가 없기 때문이기도 합니다. 다만, ASM을 사용하기 위해서는 ASM 인스턴스가 필요하고, ASM 인스턴스와 DB 인스턴스 간의 데이터 전송은 어떻게 이루어지고, 리밸런싱은 누가 수행하고, V$ASM 뷰들은 왜 동일한 내용을 각 인스턴스에서 제공하는지에 대한 가벼운 대답을 정리하는 수준으로 ASM을 마무리 하려고 합니다. 방문자가 많은 블로그도 아니고, 연재라고 해서 아직까지는 기다리는 독자가 있는 건 아니지만 늘 하나의 글을 마무리한 후에는 새로운 마음으로 다음 주제를 잡고 있습니다. 다음 주제는 "RAC 네트워크"입니다. 이 또한 정리할 내용이 많을지는 모르겠습니다. "RAC 네트워크"가 마무리되면 RAC 연재에서 가장 재미있을 만한 "캐시퓨전 및 RAC 옵타마이징"이라는 주제를 다룰 예정입니다.


저작자 표시 비영리 변경 금지
신고
크리에이티브 커먼즈 라이선스
Creative Commons License

[13] UCP 기반의 FCF (Fast Connection Failover) 설명

RAC 2016.07.14 00:37 Posted by 시연아카데미

이번 시간에는 UCP (Universal Connection Pool) 기반의 FCF (Fast Connection Failover)의 동작 방식에 대해서 설명하도록 하겠습니다.



 

13-1. FCF (Fast Connection Failover)란?


FCF는 말 그대로 빠른 커넥션 페일오버를 제공하는 기능입니다. UCP 기반의 FCF는 다음과 같이 동작합니다.

  1. 빠른 DB 장애 인지를 위해 ONS (Oracle Notification Service) 기반의 FAN 메세지를 이용한 push 방식을 통해 "INSTANCE down" 메세지를 전송 받습니다. (polling 방식이 아니므로 pooling interval 만큼의 delay도 발생하지 않습니다)
  2. 톰캣 서버는 "INSTANCE down" 메세지를 전송 받은 후, 기존 커넥션을 정리하고 Failover 노드에 신규 커넥션을 연결합니다. 
  3. 톰캣 서버는 "INSTANCE Up" 메세지를 전송 받은 후 일정 시간이 지나면, Failover 노드의 커넥션을 정리하고 기존 노드로 신규 커넥션을 연결합니다.
     

동작원리를 통해 알 수 있듯이 UCP 기반의 FCF는 JDBC Connection Pool에 비해 2가지 장점을 가집니다.

  • Failover 노드로의 커넥션 연결을 "Instance down" 메시지를 받은 즉시 수행 (JDBC Connection Pool은 사용자 요청 시점에 수행)
  • DB가 정상화된 후에 커넥션 자동 원복 (JDBC Connection Pool은 사용자의 수동 재시작 필요)
     


13-2. FCF 동작 원리


그림을 통해 FCF의 동작원리를 살펴보도록 하겠습니다.


CONTEXT.XML 보기



UCP로 첫 번째 요청이 처리된 이후에는 "그림-1"과 같이 minPoolSize 파라미터에 지정된 3개의 커넥션이 RAC1 인스턴스에 연결된 상태가 됩니다.


그림-1


Note
UCP에서 FCF를 사용하기 위해서는 fastConnectionFailoverEnabled 파라미터를 true로 설정하면 됩니다.  


RAC1 인스턴스의 장애가 발생하면 다음과 같은 일련의 일들이 발생합니다. (그림-2 참조)

  • RAC1에 연결된 세션 비정상 종료
  • RAC1 세션에 연결된 UCP 커넥션 객체들 상태가 Stale로 변경 
  • RAC1 노드의 ONS 프로세스는 "INSTANCE down" FAN 메세지를 톰캣 서버로 전달  

그림-2

 



FAN 메세지를 전달받은 톰캣 서버는 다음과 같은 일들을 수행합니다. (그림-3 참조)

  • Stale 커넥션 클린업
  • Failover노드로 minPoolSize에 정의된 개수만큼 커넥션 연결  

그림-3




RAC1 인스턴스가 복구된 직후에, ONS는 "INSTANCE up" FAN 메세지를 톰캣 서버로 전달합니다 (그림-4 참조)

그림-4





"INSTANCE up" FAN 메세지를 전달 받은 톰캣 서버는 inactiveConnectionTimeout 설정 시간 이후에 2번 노드의 idle 커넥션을 종료한 후, 1번 노드로 커넥션을 연결합니다. (그림-5 참조)

그림-5





13-3. inactiveConnectionTimeout 파라미터 동작 방식


테스트 결과, UCP는 inactiveConnectionTimeout 주기 마다 idle 커넥션을 종료하고 다시 커넥션을 생성하는 것으로 확인되었습니다. 예를 들어, inactiveConnectionTimeout=60, minPoolSize=10 으로 설정했고, 60초동안 아무 일도 없다면 10개의 커넥션이 Close된 후에 다시 생성됩니다. 주의할 점은, 이때 10개의 DB 세션 또한 릴리즈 된 후에 다시 생성(fork)된다는 점입니다. 이러한 동작 방식은 V$SESSION.LOGON_TIME의 변화 및 V$SYSSTATlogon cumulative 지표의 증가를 통해서 관찰할 수 있습니다. 따라서 UCP를 사용할 경우에는 시스템의 워크로드에 맞게 inactiveConnectionTimeout, minPoolSize 값을 적절히 설정해야 합니다.



참고 사이트


http://www.hhutzler.de/blog/testing-ucp-connections-with-fcf-against-a-rac-12-1-0-2-database/



글을 마치며


이 글을 끝으로 로드 밸런싱과 Failover에 대한 기본적인 설명은 마무리가 된 것 같습니다. 다음 시간에는 RAC 아키텍처 중에서 가장 중요한 부분 중의 하나인 ASM에 대해서 다룰 예정입니다.



저작자 표시 비영리 변경 금지
신고
크리에이티브 커먼즈 라이선스
Creative Commons License

이번 시간에는 톰캣 서버 + UCP + JSP + Jmeter를 이용해서 RLB 동작 방식을 파악해보도록 하겠습니다.



 

 

준비 사항


다음 사항을 준비합니다.


1. Jmeter 설치


Jmeter 설치는 여기를 참고하세요.
 
2. UCP 구성
지난 포스팅을 참고하세요.


3. 샘플 JSP 작성 (load.jsp)


load.jsp의 핵심은 노드에 따라서 쿼리 성능의 편차를 크게 하는 것입니다. 이를 위해, 인스턴스 명을 기준으로 쿼리를 분기해서 처리했습니다.

LOAD.JSP 보기


4. 성능 정보를 수집할 스크립트 생성 (save_load.sql)


save_table을 생성한 후, save_load.sql을 이용해서 서비스의 로드 및 시스템 상황을 저장합니다.

SAVE_LOAD.SQL 보기


이제 모든 준비가 끝났습니다. 그럼 테스트를 시작합니다.




12-1. UCP + CLB_GOAL=SHORT / RLB_GOAL=SERVICE_TIME 인 서비스 (ONLINE_UCP)를 이용한 부하 테스트


아래 순서대로 테스트를 진행합니다.


1. 톰캣 서버 기동


[root@ap1 ~]# service tomcat start
Using CATALINA_BASE:   /usr/local/tomcat
Using CATALINA_HOME:   /usr/local/tomcat
Using CATALINA_TMPDIR: /usr/local/tomcat/temp
Using JRE_HOME:        /usr/local/java
Using CLASSPATH:       /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar


2. 커넥션 풀 연결 확인


UCP는 톰캣 기동 시에 커넥션을 연결하지 않고, 첫 번째 요청이 들어오는 시점에 커넥션을 연결합니다. 따라서, 현재 시점에는 ONLINE_UCP 서비스로 연결된 세션은 없습니다.
select 'INST_1' as inst_id, count(*) total_cnt,
       sum(decode(service_name,'ONLINE_DBCP',1)) online_dbcp,
       sum(decode(service_name,'ONLINE_UCP' ,1)) online_ucp,
       sum(decode(service_name,'SHORT_SRV'  ,1)) short_srv,
       sum(decode(service_name,'LONG_SRV'   ,1)) long_srv
from gv$session where inst_id=1
union all
select 'INST_2' as inst_id, count(*) total_cnt,
       sum(decode(service_name,'ONLINE_DBCP',1)),
       sum(decode(service_name,'ONLINE_UCP' ,1)),
       sum(decode(service_name,'SHORT_SRV'  ,1)),
       sum(decode(service_name,'LONG_SRV'   ,1))
from gv$session where inst_id=2;


INST_I  TOTAL_CNT ONLINE_DBCP ONLINE_UCP  SHORT_SRV   LONG_SRV
------ ---------- ----------- ---------- ---------- ----------
INST_1         74           6                     6          6
INST_2         67           4                     4          4


3. UCP 연결


UCP는 최초 요청 직후에 커넥션을 연결합니다. 이전 포스팅에서 작성한 test.jsp를 수행한 후, 커넥션 연결 여부를 확인합니다.

INST_I  TOTAL_CNT ONLINE_DBCP ONLINE_UCP  SHORT_SRV   LONG_SRV
------ ---------- ----------- ---------- ---------- ----------
INST_1         87           6         13          6          6
INST_2         74           4          7          4          4


4. 로드 저장용 스크립트 수행


save_load.sql을 이용해서 5초에 1번씩 부하 상황을 저장합니다.

[oracle@rac1 ~]$ while true
> do
> sqlplus apps/apps @save_load.sql
> sleep 5
> done


5. Jmeter로 Run 테스트


다음과 같이 Jmeter를 설정한 후 실행합니다.





12-2. 결과 분석


테스트가 끝난 후에, 다음 쿼리를 이용해서 수행 결과를 분석합니다.


결과 분석용 쿼리 보기


결과-1. 아래 그래프와 같이, DBTIMEPERCALL 시간이 짧은 2번 노드로 커넥션 풀 세션이 이전하는 것을 알 수 있습니다. 즉, RLB가 정상적으로 이루어졌습니다. (그림-1, 그림-2. 참조)


그림-1. 노드 별 DBTIMEPERSEC 트렌드


그림-2. 노드 별 커넥션 풀 세션 수 트랜드



결과-2. RLB가 정상적으로 이루어짐에 따라서, 1번 노드의 active 세션 개수가 점차적으로 줄어드는 것을 확인할 수 있습니다. (그림-3. 참조)


그림-3. 노드 별 Active 세션 수 트랜드



결과-3. CPU 런-큐 및 CPU(%)은 RLB와는 무관한것으로 확인됩니다. (그림-4, 그림-5. 참조) 즉, 해당 값들 커넥션 시점의 로드 밸런싱(CLB)를 위해서만 사용됩니다. 그리고 커넥션 풀 세션들이 2번 노드로 이전함에 따라, 1번 노드의 CPU(%)이 점차적으로 감소하는 것을 확인할 수 있습니다.


그림-4. 노드 별 CPU Run-Queue 트렌드


그림-5. 노드 별 CPU(%) 트렌드



12-3 결과 요약


상기 예제를 통해 UCP 환경에서의 RLB 동작 방식을 확인했습니다. 나머지 3개의 서비스에 대한 테스트 겱는 지면 관계상 요약 정리만 하도록 하겠습니다. (표-1. 참조)


표-1. 서비스 유형 별 테스트 결과 요약

 서비스 명

 구성

 영향받는 항목

 RLB

여부

 GOODNESS

 DELTA

 LONG_SRV

CLB_GOAL=LONG
DBCP

 커넥션 시,

"해당 서비스의 세션 수"

 X

 세션 수

 1

 SHORT_SRV

 CLB_GOAL=SHORT
 RLB_GOAL=NONE

 DBCP

 커넥션 시,

"CPU 사용률(%)"

 X

 낮을수록 좋음
최대값

(CPU수*5000)

 가변적

 ONLINE_DBCP

 CLB_GOAL=SHORT

RLB_GOAL=SERVICE_TIME
DBCP

 커넥션 시,

"CPU 사용률(%)"

 X

 상동

 가변적

 ONLINE_UCP

 CLB_GOAL=SHORT
RLB_GOAL=SERVICE_TIME
UDP

 커넥션 시,

"CPU 사용률(%)"
런타임 시,

"콜당 수행 시간"

 O

 상동

 가변적


글을 마치며


4회의 연재를 통해 로드 밸런싱의 기본 개념 및 동작 원리를 살펴보았습니다. 테스트를 통해 원리를 검증 또는 역 추적한다는 것은 사실 굉장히 시간 소모적이고 위험할 수도 있는 (즉, 엉뚱한 결론에 이르는) 일입니다. 예를 들어, ONS.JAR 없이 UCP를 테스트했다면 지금과는 아주 상이한 결과가 나왔을 겁니다. 하지만, 다양한 역 추적 기법 (쿼리, 트레이스, OS 명령어 등)을 통해 원리를 이해해 나가는 과정은 재미있는 일임에 분명합니다. 다음 시간의 주제는 Failover 입니다. 다음 시간에 뵙겠습니다.

 


저작자 표시 비영리 변경 금지
신고
크리에이티브 커먼즈 라이선스
Creative Commons License

똘똘님. 톰캣 서버에 UCP를 구성한 후에도 RLB가 동작하지 않는 것 같습니다. 제 생각으로는 RLB가 정상적으로 동작한다면 부하가 적은 노드로 커넥션이 이전해야 할 것 같은데 그렇게 동작하지 않습니다. 이유를 알 수 있을까요?



네. UCP 구성의 핵심은 ONS.JAR를 설치해야 한다는 점입니다. 대부분의 문서에는 OJDBC7.JAR, UCP.JAR만 언급되어 있기 때문에 OJS.JAR를 설치해야 한다는 점을 놓치기 쉽습니다. RLB가 동작하기 위해서는 DB 서버의 ONS 프로세스와 AP 서버의 JAVA 프로세스 간의 통신이 필요하며, 이를 위해서는 AP 서버에 ONS.JAR가 필요합니다. 그럼 하나씩 살펴보도록 하겠습니다.

 

 



테스트 환경


  • 톰캣 버전: apache-tomcat-7.0.70
  • JDB 버전: jdk1.7.0_79
  • 오라클 12c



11-1. UCP를 위한 JAR 파일 복사


AP 서버의 $CATALINA_HOME/lib 디렉토리에 ojdbc7.jar, ucp.jar, ons.jar를 복사합니다. DB 서버에 알맞은 jar 버전을 복사하는 것이 중요하므로, 해당 파일들을 DB 서버에서 복사해서 사용하는 것이 좋습니다. 


DB 서버에서의 jar 파일의 위치

  • ojdbc7.jar : $ORACLE_HOME/jdbc/lib/ojdbc7.jar
  • ucp.jar    : $ORACLE_HOME/ucp/lib/ucp.jar
  • ons.jar    : $ORACLE_HOME/opmn/lib/ons.jar

  

Note
$ORACLE_HOME/oc4j/opmn/lib/ons.jar 파일을 사용할 경우 에러가 발생하니, 반드시 정확한 위치의 ons.jar 파일을 이용해야 합니다.




11-2. UCP 구성을 위한 context.xml 편집


다음과 같이 context.xml 파일을 편집합니다.
[root@ap1 ~]# cd $CATALINA_HOME/webapps
[root@ap1 webapps]# mkdir -p onlineucp/META-INF
[root@ap1 webapps]# cd onlineucp/META-INF
[root@ap1 META-INF]# vi context.xml

<?xml version='1.0' encoding='utf-8'?>
<Context>
    <WatchedResource>WEB-INF/web.xml</WatchedResource>
    <Manager pathname="" />
    <Valve className="org.apache.catalina.valves.CometConnectionManagerValve" />
      <Resource
       name="jdbc/online_ucp"
       auth="Container"
       factory="oracle.ucp.jdbc.PoolDataSourceImpl"
       type="oracle.ucp.jdbc.PoolDataSource"
       description="UCP Pool in Tomcat"
       connectionFactoryClassName="oracle.jdbc.pool.OracleDataSource"
       minPoolSize="20"
       maxPoolSize="100"
       initialPoolSize="50"
       autoCommit="false"
       inactiveConnectionTimeout="20"
       fastConnectionFailoverEnabled="true"
       user="apps"
       password="apps"
       url="jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)
            (HOST=rac-scan)(PORT=1521))(CONNECT_DATA=
            (SERVICE_NAME=ONLINE_UCP)))"
       connectionPoolName="UCPPool"
       validateConnectionOnBorrow="true"
       sqlForValidateConnection="select 1 from DUAL" />
</Context>




11-3. 샘플 JSP 생성


RLB 테스트를 위한 샘플 JSP를 생성합니다. 아래 코드 중에서 PoolDataSource를 이용해서 getConnection()을 수행하는 부분을 주의해서 보시면 됩니다. [root@ap1 ~]# cd $CATALINA_HOME/webapps/online_ucp
[root@ap1 online_ucp]# vi test.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"  pageEncoding="UTF-8"%>
<%@ page import="java.sql.*"%>
<%@ page import="javax.naming.*"%>
<%@ page import="javax.sql.*"%>
<%@ page import="oracle.ucp.jdbc.*"%>
<%@ page import="oracle.ucp.admin.*"%>
<html>
<head>
<body >
<%
        String   v1 = null;
        Connection conn=null;
        Statement st=null;
        ResultSet rs=null;<>
        try {
                Context ctx = new InitialContext();
                Context envContext  = (Context) ctx.lookup("java:/comp/env");
                javax.sql.DataSource ds = (javax.sql.DataSource) envContext.lookup("jdbc/online_ucp");
                PoolDataSource pds = (PoolDataSource) ds;
                conn = pds.getConnection();
               
                st=conn.createStatement();
                
                String sql = "select 'Welcome UCP' from dual";
                rs = st.executeQuery(sql);
                rs.next();
                v1 = rs.getString(1);
%>
                <%=v1 %>
<%
        } catch (Exception e){
                e.printStackTrace(System.out);
        }
        finally {
                st.close();
                rs.close();
                conn.close();
        }
%>
</body>
</html>




11-4. 톰캣 서버 기동 및 ONS 통신 여부 확인


톰캣 서버를 기동한 후에 DB 서버의 ONS 프로세스와의 통신 여부를 확인해보겠습니다. UCP는 초기 접속이 이루어진 후부터 커넥션이 연결되므로 다음 순서대로 진행합니다.
  • $ service tomcat start 
  • http://192.168.56.2:8080/online_ucp/test.jsp 수행


AP 서버에서 6200 포트 사용 여부 확인

root@ap1 ~]# lsof -i:6200
COMMAND   PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
java    15267 root  178u  IPv6  77093      0t0  TCP ap1:58530->rac-scan:lm-x (ESTABLISHED)
java    15267 root  179u  IPv6  77094      0t0  TCP ap1:13823->rac-scan:lm-x (ESTABLISHED)
java    15267 root  180u  IPv6  77095      0t0  TCP ap1:56756->rac-scan:lm-x (ESTABLISHED)


[root@ap1 ~]# ps -ef | grep 15267
root     15267     1 34 15:23 pts/0    00:00:13 /usr/local/java/bin/java -Djava.util.logging.config.file=/usr/local/tomcat/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -Djava.endorsed.dirs=/usr/local/tomcat/endorsed -classpath /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar -Dcatalina.base=/usr/local/tomcat -Dcatalina.home=/usr/local/tomcat -Djava.io.tmpdir=/usr/local/tomcat/temp org.apache.catalina.startup.Bootstrap start


DB 서버에서 6200 포트 사용 여부 확인

[oracle@rac1 ~]$ lsof -i:6200
COMMAND   PID   USER   FD   TYPE  DEVICE SIZE/OFF NODE NAME
ons     19022 oracle    8u  IPv6 5934984      0t0  TCP *:lm-x (LISTEN)
ons     19022 oracle   12u  IPv6 5948734      0t0  TCP rac1:lm-x->rac2:58878 (ESTABLISHED)
ons     19022 oracle   13u  IPv6 9863440      0t0  TCP rac-scan:lm-x->ap1:56756 (ESTABLISHED)


[oracle@rac1 SS]$ ps -ef | grep 19022
oracle   19022 19021  0 Jul08 ?        00:00:01 /ora01/app/grid/product/12.1.0/grid/opmn/bin/ons -d


[oracle@rac2 ~]$ lsof -i:6200
COMMAND  PID   USER   FD   TYPE   DEVICE SIZE/OFF NODE NAME
ons     3419 oracle    8u  IPv6 10175879      0t0  TCP *:lm-x (LISTEN)
ons     3419 oracle    9u  IPv4 10175881      0t0  TCP rac2:58878->rac1:lm-x (ESTABLISHED)
ons     3419 oracle   15u  IPv6 16250635      0t0  TCP rac-scan:lm-x->ap1:58530 (ESTABLISHED)
ons     3419 oracle   16u  IPv6 16250636      0t0  TCP rac-scan:lm-x->ap1:13823 (ESTABLISHED)


[oracle@rac2 ~]$ ps -ef | grep 3419
oracle    3419  3418  0 Jul08 ?        00:00:00 /ora01/app/grid/product/12.1.0/grid/opmn/bin/ons -d


Note
AP 서버의 java 프로세스와 DB 서버의 ons 프로세스가 6200 포트로 연결되어 있음을 알 수 있습니다. DB 서버에서 생성된 서비스 매트릭스 정보는 해당 포트를 이용해서 AP 서버의 java 프로세스에게 전달되고, java 프로세스는 해당 정보를 이용해서 RBL를 수행하게 되는 것입니다. (그림-1. 참조)


그림-1. ONS를 이용한 AP 서버와 DB 서버의 연결



참고 문헌


http://www.oracle.com/technetwork/database/application-development/planned-unplanned-rlb-ucp-tomcat-2265175.pdf


글을 마치며


이제 모든 환경 구성이 완료되었습니다. 다음 시간에는 Jmeter를 이용한 부하 테스트를 통해 RLB 동작 방식을 검증해보도록 하겠습니다.


[12] Jmeter + 톰캣 + UCP를 이용한 RLB (Runtime Load Balancing) 동작 방식 검증 바로가기

저작자 표시 비영리 변경 금지
신고
크리에이티브 커먼즈 라이선스
Creative Commons License

[10] CLB, RLB를 위한 서비스 매트릭스 정보의 흐름

RAC 2016.07.08 20:28 Posted by 시연아카데미

똘똘님! 이전 포스팅을 통해 CLB와 RLB의 기본 개념은 쉽게 이해했습니다. 이번 시간에는 로드 밸런싱을 위한 "서비스 매트릭스" 정보의 흐름에 대해서 알고 싶습니다. 




네 궁금님. 말씀하신 것처럼 오라클은 로드 밸런싱을 위해 "서비스 매트릭스" 정보를 이용합니다. 테스트를 통해서 살펴보겠습니다.




10-1. 리스너 설정


로드 밸런싱을 위해서는 로컬 리스너와 리모트 리스너를 설정해야 합니다. 리스너는 대부분 설치 시에 자동으로 설정되므로 설정 내용만 확인하면 될 것입니다. 제 경우에는 SCAN IP를 사용하므로 remote_listener 설정 값이 rac-scan:1521로 나타납니다. SCAN을 사용하지 않는 환경에서는 상대 노드(들)의 리스너 주소가 출력되면 됩니다.
1번 노드> show parameter _listener
NAME                 VALUE
-------------------- --------------------------------------------
local_listener       (ADDRESS=(PROTOCOL=TCP)(HOST=192.168.56.81)(PORT=1521))
remote_listener      rac-scan:1521

2번 노드> show parameter _listener
NAME                 VALUE
-------------------- --------------------------------------------
local_listener       (ADDRESS=(PROTOCOL=TCP)(HOST=192.168.56.82)(PORT=1521))
remote_listener      rac-scan:1521



10-2. 서비스 생성


CLB 옵션 (LONG, SHORT)의 차이를 확인하기 위해 2개의 서비스 (LONG_SRV, SHORT_SRV)를 생성합니다. 또한, UCP (Universal Connection Pool) 환경에서만 RLB가 동작하는 것을 검증하기 위해 2개의 서비스 (ONLINE_DBCP, ONLINE_UCP)를 생성합니다. (표-1. 참조)


표-1. 동작 차이 확인을 위한 4개의 서비스 목록

 서비스 명

 CLB_GOAL

 RLB_GOAL

 사용할 커넥션 풀

 LONG_SRV

 LONG

 n/a

 DBCP

 SHORT_SRV

 SHORT

 NONE

 DBCP

 ONLINE_DBCP

 SHORT

 SERVICE_TIME

 DBCP

 ONLINE_UCP

 SHORT

 SERVICE_TIME

 UCP


서비스 생성

srvctl add service -db ORA12C -service LONG_SRV -preferred ORA12C1,ORA12C2 \
-clbgoal LONG -notification true
srvctl add service -db ORA12C -service SHORT_SRV -preferred ORA12C1,ORA12C2 \
-clbgoal SHORT -rlbgoal NONE
srvctl add service -db ORA12C -service ONLINE_DBCP -preferred ORA12C1,ORA12C2 \
-clbgoal SHORT -rlbgoal SERVICE_TIME
srvctl add service -db ORA12C -service ONLINE_UCP -preferred ORA12C1,ORA12C2 \
-clbgoal SHORT -rlbgoal SERVICE_TIME



Note
RLB_GOAL이 THROUGHPUT인 경우는 테스트 대상에서 제외했습니다. 제 테스트 환경에서는 RLB_GOAL이 SERVICE_TIME인 경우와 THROUGHPUT인 경우의 차이점을 발견하지 못했기 때문입니다. 약간의 차이는 있지만, 두 개의 옵션 모두 "Call당 처리 시간" 기준으로 커넥션이 이전되었습니다.


서비스 시작

srvctl start service -db ORA12C -service LONG_SRV
srvctl start service -db ORA12C -service SHORT_SRV
srvctl start service -db ORA12C -service ONLINE_DBCP
srvctl start service -db ORA12C -service ONLINE_UCP


서비스 확인

srvctl status service -db ORA12C

Service LONG_SRV is running on instance(s) ORA12C1,ORA12C2
Service ONLINE_DBCP is running on instance(s) ORA12C1,ORA12C2
Service ONLINE_UCP is running on instance(s) ORA12C1,ORA12C2
Service SHORT_SRV is running on instance(s) ORA12C1,ORA12C2



10-3. 로드 밸런싱과 관련된 MMON, MMNL, LREG, 리스너 동작 방식


몇 가지 테스트를 통해 분석한 MMON, MMNL, LREG, 리스너의 동작 방식은 다음과 같습니다. (그림-1. 참조)

  1. MMON은 30초에 1번씩 RLB로 설정된 서비스들의 서비스 매트릭스 정보를 SYS.SYS$SERVICE_METRICS_TAB에 저장합니다.
  2. 각 노드의 MMNL은 5초에 1번씩 모든 서비스들의 서비스 매트릭스 정보를 V$SERVICEMETRIC에 저장합니다.
  3. LREG (11g까지는 PMON)는 서비스 매트릭스 정보를 리스너들에게 전달합니다.
  4. 리스너들은 LREG로부터 서비스 메트릭스 정보를 전달 받습니다.


그림-1. 서비스 매트릭스 전달 방식



10-4. 검증 방법 상세


사실, 이 부분은 엔지니어 적인 호기심으로 트레이싱을 해본 내용들입니다. 그냥 스킵해도 무방하며, 트레이스 방법에 대해서만 가볍게 리뷰하셔도 좋을 것 같습니다.



10-3의 1번 항목 검증


select to_char(ENQ_TIME, 'YYYY-MM-DD: HH:MI:SS') Enq_time, user_data
from   SYS.SYS$SERVICE_METRICS_TAB
order  by 1;

2016-07-08: 09:45:11  SYS$RLBTYP('ONLINE_UCP', 'VERSION=1.0 database=ORA12C servic
                      e=ONLINE_UCP { {instance=ORA12C1 percent=100 flag=UNKNOWN af
                      f=FALSE} } timestamp=2016-07-08 18:45:11')
2016-07-08: 09:45:11  SYS$RLBTYP('ONLINE_DBCP', 'VERSION=1.0 database=ORA12C servi
                      ce=ONLINE_DBCP { {instance=ORA12C1 percent=100 flag=UNKNOWN
                      aff=FALSE} } timestamp=2016-07-08 18:45:11')
2016-07-08: 09:45:41  SYS$RLBTYP('ONLINE_UCP', 'VERSION=1.0 database=ORA12C servic
                      e=ONLINE_UCP { {instance=ORA12C1 percent=100 flag=UNKNOWN af
                      f=FALSE} } timestamp=2016-07-08 18:45:41')
2016-07-08: 09:45:41  SYS$RLBTYP('ONLINE_DBCP', 'VERSION=1.0 database=ORA12C servi
                      ce=ONLINE_DBCP { {instance=ORA12C1 percent=100 flag=UNKNOWN
                      aff=FALSE} } timestamp=2016-07-08 18:45:41')


Note
SYS$SERVICE_METRICS_TAB 테이블에는 RLB와 관련된 서비스의 서비스 메트릭스 정보만 30초마다 저장됩니다. 해당 테이블에는 CLB 관련 서비스의 정보는 저장되지 않습니다.


다음과 같이, kill -stop 명령어로 MMON 프로세스를 STOP 시킨 후에는 SYS$SERVICE_METRICS_TAB 테이블에 서비스 매트릭스 정보가 입력되지 않는 것을 알 수 있습니다.

[oracle@rac2 SS]$ ps -ef | grep mmon
oracle    8474     1  0 18:43 ?        00:00:01 ora_mmon_ORA12C2
[oracle@rac2 SS]$ kill -stop 8474
[oracle@rac2 SS]$ su root
[root@rac2 SS]# strace -p 8474
Process 8474 attached
--- stopped by SIGSTOP ---



10-3의 2번 항목 검증


1번과 동일한 방법으로 MMNL 프로세스를 STOP 시키면 V$SERVICEMETRIC 테이블에 서비스 매트릭스 정보가 입력되지 않는 것을 알 수 있습니다. 
 

10-3의 3번 항목 검증


10257 트레이스를 이용하면 됩니다. 해당 트레이스를 활성화시키면 PMON 및 LREG의 수행 내용을 확인할 수 있습니다. SQL> alter system set events '10257 trace name context forever, level 16'; --트레이스 on
SQL> alter system set events '10257 trace name context off'; -- 트레이스 off


예시-1. LREG 프로세스 트레이스 결과

*** 2016-07-08 19:13:34.357
kmlwait: status: succ=4, wait=0, fail=0
kmmlrl: update for process drop delta: 107 106 72 74 299
kmmlrl: 72 processes
kmmlrl: node load 445
kmmlrl: instance load 4
kmmgdnu: LONG_SRV
         goodness=0, delta=1, pdb=1,
         flags=0x104:unblocked/not overloaded, update=0x6:G/D/-
kmmgdnu: ONLINE_DBCP
         goodness=100, delta=100, pdb=1,
         flags=0x104:unblocked/not overloaded, update=0x6:G/D/-
kmmgdnu: ONLINE_UCP
         goodness=100, delta=100, pdb=1,
         flags=0x104:unblocked/not overloaded, update=0x6:G/D/-
kmmgdnu: SHORT_SRV
         goodness=0, delta=100, pdb=1,
         flags=0x104:unblocked/not overloaded, update=0x6:G/D/-
kmmgdnu: ORA12CXDB
         goodness=0, delta=1, pdb=0,
         flags=0x105:unblocked/not overloaded, update=0x6:G/D/-
kmmgdnu: ORA12C
         goodness=0, delta=1, pdb=0,
         flags=0x104:unblocked/not overloaded, update=0x6:G/D/-



10-3의 4번 항목 검증


리스너 트레이스를 이용하면 됩니다.
  • 로컬 리스너 트레이스 방법: lsnrctl trace user
  • 스캔 리스너 트레이스 방법: lsnrctl trace user LISTENER_SCAN1

예시-2. 리스너 프로세스 트레이스 결과 
2016-07-08 19:13:34.358201 : nsglgrDoRegister:service:ONLINE_UCP what:4 value:100
2016-07-08 19:13:34.358209 : nsglgrDoRegister:service:ONLINE_UCP what:2 value:100
2016-07-08 19:13:34.358216 : nsglgrDoRegister:service:ONLINE_DBCP what:4 value:100
2016-07-08 19:13:34.358223 : nsglgrDoRegister:service:ONLINE_DBCP what:2 value:100
2016-07-08 19:13:34.358230 : nsglgrDoRegister:service:SHORT_SRV what:4 value:100
2016-07-08 19:13:34.358237 : nsglgrDoRegister:service:SHORT_SRV what:2 value:0
2016-07-08 19:13:34.358245 : nsglgrDoRegister:service:LONG_SRV what:4 value:1
2016-07-08 19:13:34.358253 : nsglgrDoRegister:service:LONG_SRV what:2 value:0
2016-07-08 19:13:34.358261 : nsglgrDoRegister:service:ORA12C what:4 value:1
2016-07-08 19:13:34.358269 : nsglgrDoRegister:service:ORA12C what:2 value:0


Note
두 개의 트레이스 파일을 비교함으로써 리스너 프로세스의 what:4=delta, what:2=goodness 임을 알 수 있습니다. 해당 값들은 V$SERVICEMETRIC의 DELTA 및 GOODNESS 칼럼 값과 동일합니다.



참고 문헌


http://www.slideshare.net/fullscreen/alexgorbachev/demistifying-oracle-rac-workload-management-by-alex-gorbachev-nocoug-2010-spring-conference/1


글을 마치며


이번 시간에는 RLB, CLB 서비스 생성 방법 및 로드 밸런싱을 위한 "서비스 매트릭스" 정보들이 흐름을 살펴보았습니다.


[11] 톰캣 서버에 UCP (Universal Connection Pool) 구성 및 JSP 샘플 코드 작성 바로가기


저작자 표시 비영리 변경 금지
신고
크리에이티브 커먼즈 라이선스
Creative Commons License

똘똘님. 자동으로 로드를 분산시킨다는 개념은 위험성이 내포되어 있긴 하지만, 원리를 잘 이해하고 적용한다면 관리 측면에서는 상당히 매력적인 기능인 것 같습니다. 공부를 하다 보니 CLB, RLB, CLB_GOAL, RLB_GOAL 등의 용어가 등장합니다. CLB의 개념은 그다지 어렵지 않은데, RLB 개념이 명확하지 않습니다. CLB와 RLB의 개념을 정립해주실 수 있을까요?




네. 간단한 질문이지만 상당히 어려운 질문입니다. 설명드릴 것이 많지만, 한번에 너무 많은 지식은 소화하기 힘드니 이번 시간에는 CLB와 RLB의 차이를 명확히 아는 것만을 목표로 진행해 보겠습니다.



들어가기에 앞서


로드 밸런싱 관련 내용은 설명할 내용이 많은 관계로 다음과 같이 4개의 연재로 진행할 예정입니다.


1) [09] Connection Load Balancing (CLB)과 Runtime Connection Load Balancing (RLB) 설명

2) [10] CLB, RLB를 위한 서비스 매트릭스 정보의 흐름

3) [11] 톰캣 서버에 UCP (Universal Connection Pool) 구성 및 JSP 샘플 코드 작성

4) [12] Jmeter + 톰캣 + UCP를 이용한 RLB (Runtime Load Balancing) 동작 방식 검증



9-1. 로드 밸런싱 개요


클러스터 환경에서 동시에 다수의 노드가 동일한 서비스를 수행하는 경우, 바꿔 말해 하나의 서비스가 여러 개의 노드에서 동시에 수행되는 환경이 있다고 가정해보겠습니다. 이때, 서비스 성능 수준을 높이기 위해서 로드 밸런싱은 반드시 필요한 요소입니다. 일반적으로 로드 밸런싱은 2가지로 구분할 수 있습니다.

  • 커넥션 로드 밸런싱
  • 런-타임 로드 밸런싱
Note
커넥션 로드 밸런싱은 "세션 수" 또는 "CPU 사용률(%)"을 기준으로 동작하고, 런-타임 로드 밸런싱은 "서비스 처리 시간"을 기준으로 동작합니다.



커넥션 로드 밸런싱의 한계점

  • 커넥션 시점에는 CPU 사용률(%)이 비슷했으나, 접속한 노드의 CPU(%)이 갑자기 높아지는 경우
  • 세션 수나 CPU 사용률(%)은 비슷하나, 노드 간의 서비스 처리 성능이 차이가 나는 경우  
이러한 문제를 해결하기 위해 "런-타임 로드 밸런싱"이 필요하다고 할 수 있습니다.



9-2. 오라클의 로드 밸런싱 방법


오라클은 커넥션 로드 밸런싱과 런-타임 로드 밸런싱을 모두 제공합니다. (표-1 및 그림-1 참조)
  • 커넥션 로드 밸런싱: Connection Load Balancing (CLB)이라고 하며, CLB_GOAL로 설정
  • 런-타임 밸런싱: Runtime Load Balancing (RLB)이라고 하며, RLB_GOAL로 설정 


그림-1. 로드 밸런싱 옵션


Note
RLB_GOAL을 설정하기 위해서는 CLB_GOAL을 SHORT로 지정해야 합니다.


표-1. CLB, RLB 비교 설명

 구분

 CLB (커넥션 로드 밸런싱)

 RLB (런-타임 로드 밸런싱)

 설정 방법

 서비스 생성 시, CLB_GOAL 설정

 서비스 생성 시, RLB_GOAL 설정

 옵션

 LONG
 "세션 수"가 적은 노드로 접속

 SERVICE_TIME
 UCP 사용 시, 서비스 처리 시간이 우수한 노드로 접속

 (OLTP 환경에 적합)

 SHORT
 "CPU(%)"이 낮은 노드로 접속

 THROUPUT
 UCP 사용 시, 서비스 처리 능력이 우수한 노드로 접속
 (BATCH 환경에 적합)


Note
LONG 옵션에서 말하는 "세션 수"는 "해당 서비스로 접속한 세션 수"를 의미합니다. 전체 세션 수가 아닌 점을 주의해야 합니다. 



9-3. RLB는 모든 환경에서 적용될까요?


"표-1"에서 언급한 것처럼 "RLB는 UCP (Unified Connection Pool) 환경에서만 동작"합니다. 간단하지만 가장 중요한 내용이라고 할 수 있겠습니다. DBCP, JDBC Connection Pool 및 SQL*Plus와 같은 클라이언트의 접속은 RLB가 적용되지 않습니다. 테스트 시, 모니터링을 해보면 DBCP나 SQL*Plus 접속에 대해서도 RBL가 적용되는 것 같은 착각을 할 수 있지만, 해당 접속들은 CLB로만 처리됩니다.

 

 



참고 문헌


http://oracleinaction.com/rac-load-balancing/



[10] CLB, RLB 동작을 위한 서비스 매트릭스 정보의 흐름 바로가기

저작자 표시 비영리 변경 금지
신고
크리에이티브 커먼즈 라이선스
Creative Commons License

똘똘님. 지난 포스팅에서 정리해주신 서비스 별 성능 통계를 제공해주는 다양한 뷰에 대해서 학습 중입니다. 다른 뷰들은 대부분 쉽게 이해가 되는데요. V$SERVICEMETRIC 뷰와 V$SERVICEMETRIC_HISTORY 뷰의 차이를 정확히 모르겠습니다. 그리고 CALLSPERSEC 칼럼의 수치가 실제 실행 횟수보다 크게 나오는 것 같습니다. 이에 대한 설명을 부탁드려도 될까요?



네. 공부할수록 궁금한 게 많아지는건 아주 당연하고도 좋은 현상입니다. 그럼 시작해볼까요?




8-1. V$SERVICEMETRIC 뷰와 V$SERVICEMETRIC_HISTORY 뷰의 차이점


뷰의 이름만으로 보면, 하나는 현재 데이터를 제공하고 다른 하나는 이력 데이터를 제공한다는 점은 쉽게 인지할 수 있으나, 조금 더 중요한 차이점이 있습니다. V$SERVICEMETRIC 뷰는 런타임 로드 밸런싱을 위해 사용되고, V$SERVICEMETRIC_HISTORY 뷰는 서비스 별 성능 관리를 위해 사용되다는 점입니다. (표-1 참조) [런타임 로드 밸런싱에 대해서는 별도 포스팅 예정입니다]


표-1. V$SERVICEMETRIC 뷰와 V$SERVICEMETRIC_HISTORY 뷰 비교

 

  V$SERVICEMETRIC

 V$SERVICEMETRIC_HISTORY

 주요 목적

 런타임 로드 밸런싱

 (RLB - Runtime Load Balancing)

 서비스 별 성능 관리

 RLB용 칼럼

 GOODNESS

 없음

 제공 데이터

 서비스 별로 2개의 성능 통계를 제공

 (1개는 최근 5초, 1개는 최근 1분)

 서비스 별로 5초 단위의 성능 통계 이력 (최근 2분) 및 1분 단위의 성능 통계 이력 (최근 1시간) 제공



8-2. 각 뷰에서 제공하는 성능 통계 데이터 구간


"표-1"에서는 최근 5초, 최근 1분이라고 기술했으나, 보다 정확한 구간은 "그림-1"과 같습니다.


그림-1. 각 뷰에서 제공하는 성능 통계 데이터 구간 설명



8-3. DBTIMEPERSEC 칼럼 시간 단위


대부분의 칼럼들은 매뉴얼에 정확히 기재되어 있으나 DBTIMEPERSEC 칼럼은 단위가 기재되어 있지 않습니다. 해당 칼럼의 단위는 1/100초 입니다 (참고로, 시간 관련 칼럼들의 단위를 "표-2"에 기술해 두었습니다)


표-2. 칼럼 별 시간 단위

 칼럼명 

 단위 

 INTSIZE_CSEC

 centi-Second (1/100초)

 ELAPSEDPERCALL

 micro-Second (1/1,000,000초)

 CPUPERCALL

 micro-Second (1/1,000,000초)

 DBTIMEPERCALL

 micro-Second (1/1,000,000초)

 DBTIMEPERSEC

 centi-Second (1/100초)



8-4. CALLSPERSEC 칼럼의 이해


매뉴얼에 보면 CALLSPERSEC 칼럼의 설명은 "Number of user calls per second", 즉, 초당 발생한 "user calls"라고 명시되어 있습니다. 다시 말해, 해당 칼럼에서 제공하는 수치는 SQL의 실행 횟수가 아닌 "user calls"라는 점을 주의해야 합니다. "user calls"는 아래와 같은 3가지 유형의 콜의 횟수를 합한 수치를 제공합니다.


  1. PARSE call
  2. EXEC call
  3. FETCH call

예를 들어, 1건을 fetch하는 SQL을 수행하면 3개의 call (각 단계별 1회)이 발생합니다. 만일, fetch 해야할 레코드가 많다면 그만큼 많은 FETCH call이 발생하게 됩니다. 예를 들어 설명하겠습니다. ONLINE_SRV 서비스에 속하는 online1.jsp는 1000건을 fetch하는 SQL을 수행합니다. 이때, ONLINE_SRV의 CALLSPERSEC 수치는 얼마일까요?

예시-1. online1.jsp 예제
<%@ page language="java" contentType="text/html; charset=UTF-8"  pageEncoding="UTF-8"%>
<%@ page import="java.sql.*"%>
<%@ page import="javax.naming.*"%>
<%@ page import="javax.sql.*"%>
<html>
<head>
<body >
<%
        Integer v1 = null;
        Connection conn=null;
        Statement st=null;
        ResultSet rs=null;
        try {
                Context initContext = new InitialContext();
                Context envContext  = (Context) initContext.lookup("java:/comp/env");
                DataSource datasource = (DataSource) envContext.lookup("jdbc/onlinesrv");
                conn = datasource.getConnection();
                st=conn.createStatement();
                String sql = "select c1 from t1 where rownum<=1000";
                rs = st.executeQuery(sql);
                while (rs.next()) {
                    v1 = rs.getInt(1);
%>
                    <%=v1 %>
<%
                }
        } catch (Exception e){
                e.printStackTrace(System.out);
        }
        finally {
                st.close();
                rs.close();
                conn.close();
        }
%>
</body>
</html>


예시-2. online1.jsp를 수행한 후에 V$SERVICEMETRIC 뷰 조회
select to_char(begin_time,'HH24:MI:SS') begin_time,
       to_char(end_time, 'HH24:MI:SS') end_time,
       intsize_csec interval,
       round(callspersec*intsize_csec/100,1) calls_in_interval, -- 구간동안 발생한 횟수
       callspersec -- 초당 발생 횟수
from   v$servicemetric
where  service_name='ONLINE_SRV';

BEGIN_TI END_TIME   INTERVAL CALLS_IN_INTERVAL CALLSPERSEC
-------- -------- ---------- ----------------- -----------
12:12:22 12:12:27        500               102        20.4


Note
CALLSPERSEC 칼럼 값은 초당 값 (Value/Sec)이므로, 구간 사이에 발생한 값 (Delta)으로 환산해서 설명하도록 하겠습니다. 조회 결과를 보면, CALLS_IN_INTERVAL 칼럼 값은 102입니다. 예상과 다르죠? 102인 이유는 PARSE call 1회, EXEC call 1회, FETCH call 100회를 수행했기 때문입니다. 또한, 1000건을 fetch하는데 FETCH call이 100회인 이유는 JDBC가 기본적으로 10개씩 레코드를 fetch(배열 크기=10)하기 때문입니다. 그렇다면 배열 크기를 증가시키면 CALLSPERSEC 칼럼 값에 변화가 있을까요?


8-5. Array 크기 변경 후 CALLSPERSEC 값의 변화 확인


setFetchSize 함수를 이용해서 배열 크기를 증가시킨 후 테스트를 수행해보겠습니다.


예시-3. 배열 크기 증가
st=conn.createStatement();
st.setFetchSize(100);


예시-4. 수행 결과 확인
select to_char(begin_time,'HH24:MI:SS') begin_time,
       to_char(end_time, 'HH24:MI:SS') end_time,
       intsize_csec interval,
       round(callspersec*intsize_csec/100,1) calls_in_interval, -- 구간동안 발생한 횟수
       callspersec -- 초당 발생 횟수
from   v$servicemetric
where  service_name='ONLINE_SRV';
BEGIN_TI END_TIME   INTERVAL CALLS_IN_INTERVAL CALLSPERSEC
-------- -------- ---------- ----------------- -----------
12:13:02 12:13:07        500                12         2.4


조회 결과를 보면, CALLS_IN_INTERVAL 칼럼 값이 12로 변경된 것을 알 수 있습니다. 즉, 배열 크기 증가에 따라 Fetch Call수가 100회에서 10회로 줄어든 것이 반영된 결과입니다.


8-6. 글을 마치며


서비스 별 응답 시간, CPU 사용 시간 및 Call 횟수를 분석하는데 있어서 V$SERVICEMETRIC_HISTORY 뷰는 아주 유용한 데이터를 제공합니다. 실시간 데이터와 함께 최근 1시간의 데이터를 제공하므로, 성능 이력 또한 분석할 수 있다는 장점을 가지고 있습니다. 따라서, 서비스 별 성능 분석 시에 매우 유용하게 활용할 수 있을 것입니다.





저작자 표시 비영리 변경 금지
신고
크리에이티브 커먼즈 라이선스
Creative Commons License

똘똘님 덕분에 톰캣 환경에서의 DBCP JDBC Connection Pool 구성은 쉽게 마무리했습니다. (이전 포스팅 참조) 새로운 미션은 커넥션 풀 별로 성능 현황을 모니터링하고 이력을 분석하는 것입니다. V$SESSION 뷰를 확인해보니 2개의 서비스 모두 PROGRAM 명은 'JDBC Thin Client'로 표시되고 SERVICE 명은 'SYS$USERS'로 표시되므로 구분이 되지 않습니다. DBMS_APPLICATION_INFO.SET_MODULE 패키지를 이용하면 "MODULE" 및 "ACTION" 설정이 가능하다고 알고 있습니다만, 소스 수정이 불가능한 상황입니다. 어떻게 하면 될까요?



오라클 서비스를 이용하면 아주 쉽게 이 문제를 풀 수 있습니다. 그럼 시작해볼까요?





7-1. 서비스 생성 및 시작


DB 서버에 로그인 한 후, 커넥션 풀을 위한 2개의 서비스를 생성한 후 서비스를 시작합니다. (테스트 환경은 "누구나 쉽게 따라할 수 있는 Oracle 12c RAC 설치 가이드" 참조)


SRVCTL을 이용한 서비스 생성

srvctl add service -d ORA12C -service ONLINE_SRV -preferred ORA12C1 -available ORA12C2 -failovermethod BASIC
srvctl add service -d ORA12C -service BATCH_SRV  -preferred ORA12C2 -available ORA12C1 -failovermethod BASIC


서비스 시작

srvctl start service -d ORA12C -s ONLINE_SRV
srvctl start service -d ORA12C -s BATCH_SRV


서비스 확인

srvctl status service -d ORA12C
Service BATCH_SRV  is running on instance(s) ORA12C2
Service ONLINE_SRV is running on instance(s) ORA12C1


Note
싱글 인스턴스에서 테스트를 하는 경우에는 DBMS_SERVICE 패키지를 이용해서 서비스를 생성하면 됩니다.



7-2. 커넥션 풀 별로 context.xml 파일 내의 url 변경


새로운 서비스로 접속할 수 있도록 context.xml 파일 내의 url을 변경합니다.


예시-1. 온라인 서비스용 url 변경 (/usr/local/tomcat/webapps/online/META-INF/context.xml)

<?xml version='1.0' encoding='utf-8'?>
<Context>
    <WatchedResource>WEB-INF/web.xml</WatchedResource>
    <Manager pathname="" />
    <Valve className="org.apache.catalina.valves.CometConnectionManagerValve" />
        <Resource
        name="jdbc/onlinesrv"
        auth="Container"
        type="javax.sql.DataSource"
        factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
        driverClassName="oracle.jdbc.OracleDriver"
        url="jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS_LIST=(FAILOVER=ON)
             (ADDRESS=(PROTOCOL=TCP)(HOST=192.168.56.81)(PORT=1521))
             (ADDRESS=(PROTOCOL=TCP)(HOST=192.168.56.82)(PORT=1521)))
             (CONNECT_DATA=(SERVICE_NAME=ONLINE_SRV)(FAILOVER_MODE=(METHOD=BASIC))))"
        username="apps"
        password="apps"
        maxActive="20"
        maxIdle="10"
        initialSize="10"
        connectionPoolName="onlinesrv_pool"
        maxWait="-1"/>
</Context>


예시-2. 배치 서비스용 url 변경 (/usr/local/tomcat/webapps/batch/META-INF/context.xml)

<?xml version='1.0' encoding='utf-8'?>
<Context>
    <WatchedResource>WEB-INF/web.xml</WatchedResource>
    <Manager pathname="" />
    <Valve className="org.apache.catalina.valves.CometConnectionManagerValve" />
        <Resource
        name="jdbc/batchsrv"
        auth="Container"
        type="javax.sql.DataSource"
        factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
        driverClassName="oracle.jdbc.OracleDriver"
        url="jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS_LIST=(FAILOVER=ON)
             (ADDRESS=(PROTOCOL=TCP)(HOST=192.168.56.82)(PORT=1521))
             (ADDRESS=(PROTOCOL=TCP)(HOST=192.168.56.81)(PORT=1521)))
             (CONNECT_DATA=(SERVICE_NAME=BATCH_SRV)(FAILOVER_MODE=(METHOD=BASIC))))"
        username="apps"
        password="apps"
        maxActive="20"
        maxIdle="10"
        initialSize="10"
        connectionPoolName="batchsrv_pool"
        maxWait="-1"/>
</Context>



7-3. 톰캣 재 시작 후 V$SESSION 뷰 확인


context.xml 설정이 완료된 후에는 톰캣을 재 시작합니다.


service tomcat stop
service tomcat start


V$SESSION 뷰를 확인해보겠습니다.


select inst_id, program, service_name from gv$session where program like 'JDBC%' order by 1;


   INST_ID PROGRAM                        SERVICE_NAME
---------- ------------------------------ ----------------------------------
         1 JDBC Thin Client               ONLINE_SRV
         1 JDBC Thin Client               ONLINE_SRV
         1 JDBC Thin Client               ONLINE_SRV
         1 JDBC Thin Client               ONLINE_SRV
         1 JDBC Thin Client               ONLINE_SRV
         1 JDBC Thin Client               ONLINE_SRV
         1 JDBC Thin Client               ONLINE_SRV
         1 JDBC Thin Client               ONLINE_SRV
         1 JDBC Thin Client               ONLINE_SRV
         1 JDBC Thin Client               ONLINE_SRV
         2 JDBC Thin Client               BATCH_SRV
         2 JDBC Thin Client               BATCH_SRV
         2 JDBC Thin Client               BATCH_SRV
         2 JDBC Thin Client               BATCH_SRV
         2 JDBC Thin Client               BATCH_SRV
         2 JDBC Thin Client               BATCH_SRV
         2 JDBC Thin Client               BATCH_SRV
         2 JDBC Thin Client               BATCH_SRV
         2 JDBC Thin Client               BATCH_SRV
         2 JDBC Thin Client               BATCH_SRV


결과에서 보듯이, 서비스 설정 후에는 service_name 칼럼에 각각의 "서비스명"이 출력되는 것을 알 수 있습니다. 즉, 이를 통해 세션 레벨에서의 서비스 구분이 가능한 것을 알 수 있습니다. 그렇다면 서비스 별로 다양한 성능 통계 정보는 어떻게 확인할 수 있을까요?



7-4. 서비스 별 성능 통계 정보를 제공하는 다양한 뷰들


오라클은 V$SESSION.SERVICE_NAME 이외에도 서비스 별로 다양한 성능 통계 정보를 제공하는 뷰들을 제공하고 있습니다. 이러한 뷰들을 이용하면 서비스 별 세션 뿐 아니라 SQL, 대기이벤트, 성능통계 및 대기 클래스등의 다양한 성능 정보를 확인할 수 있습니다.


  • V$SQL : SERVICE 칼럼을 통해 서비스 별 SQL 성능 통계 확인 가능
  • V$SERVICEMETRIC : 서비스 별로 2개의 성능 통계를 제공 (1개는 최근 5초, 1개는 최근 1분)
  • V$SERVICEMETRIC_HISTORY : 서비스 별로 5초 단위의 성능 통계 이력 (최근 2분) 및 1분 단위의 성능 통계 이력 (최근 1시간) 제공
  • V$SERVICE_EVENT : 서비스 별로 대기이벤트 정보 제공
  • V$SERVICE_STATS : 서비스 별로 성능통계 정보 제공 (AWR로도 제공: DBA_HIST_SERVICE_STAT)
  • V$SERVICE_WAIT_CLASS : 서비스 별로 대기클래스 정보 제공 (AWR로도 제공: DBA_HIST_SERVICE_WAIT_CLASS)  
     

글을 마치며


서비스 별 성능 통계를 제공하는 뷰중에서 V$SERVICEMETRICV$SERVICEMETRIC_HISTORY 뷰는 조금 더 학습이 필요할 것 같습니다. 다음 포스팅은 해당 뷰들에서 제공하는 데이터의 내용을 분석할 예정입니다.


[08] V$SERVICEMETRIC, V$SERVICEMETRIC_HISTORY 뷰를 이용한 서비스 성능관리 방안 으로바로가기



저작자 표시 비영리 변경 금지
신고
크리에이티브 커먼즈 라이선스
Creative Commons License

서비스를 이용해서 워크로드를 관리해보니 로드 밸런싱과 Failover 부분은 아주 좋은 것 같습니다. 그런데 문제점이 하나 있습니다. 노드가 복구된 후에도 Failover된 서비스들이 원래 노드로 이동하지 않습니다. 현재는 수동으로 서비스 stop/start를 수행해서 재배치를 하고 있습니다만 자동으로 서비스 재배치가 가능할까요?



네! 가능합니다. FAN 콜아웃 (Callouts)을 이용하면 서비스 자동 재배치가 가능합니다. 그럼 한번 살펴볼까요?




5-1. FAN 이벤트란?



Fast Application Notification (FAN)은 오라클 10g부터 제공되는 기능으로써 가용성을 향상시킬 목적으로 도입된 기능입니다. 가용성을 향상시키기 위해서는 클러스터 노드 내에 문제가 발생했는 때 아주 빠르게 문제 상황을 전파할 필요가 있습니다. 오라클은 이러한 문제가 발생했을 때 FAN 메시지를 클러스터 내에 신속하게 전파함으로써 문제 상황을 빠르게 응대할 수 있도록 합니다. FAN 메시지의 유형은 크게 3가지로 구분됩니다.


  1. 서비스 (애플리케이션, 인스턴스) up/down 관련 이벤트
  2. 노드 up/down 관련 이벤트
  3. 로드 밸런싱 관련 이벤트

이번 포스팅에서 다룰 내용은 인스턴스 up/down시에 발생하는 FAN 메시지를 활용한 콜아웃 수행 방법입니다.



5-2. FAN 콜아웃 (Callouts)이란?



이름이 다소 생소할 수 있는 FAN 콜아웃은 클러스터 내에서 FAN 메시지가 발생했을 때, 자동으로 수행되는 사용자 정의 스크립트 (및 프로그램)를 의미합니다. 콜아웃은 Shell 프로그램, Perl 프로그램, C Executable등, 실행할 수 있는 형태의 파일이면 모두 가능합니다. 콜아웃은 $GRID_HOME/racg/usrco 디렉토리에 저장하면 됩니다.



5-3. FAN 콜아웃은 누가 수행할까요?



테스트 결과, FAN 콜아웃은 oraagent.bin 프로세스가 수행합니다. (검증 방법은 테스트-1 참조)


테스트-1. FAN 콜아웃 수행 프로세스 확인방법

[oracle@racnode01h ~]$ cd /u01/app/12.1.0/grid/racg/usrco
[oracle@racnode01h usrco]$ vi sleep.sh
#!/bin/bash
sleep 120
exit
[oracle@racnode01h usrco]$ chmod 700 sleep.sh

[oracle@racnode01h usrco]$ ps -ef | grep pmon
oracle    1681     1  0 06:28 ?        00:00:00 asm_pmon_+ASM1
oracle    3359     1  0 06:35 ?        00:00:00 ora_pmon_OOW1


[oracle@racnode01h usrco]$ kill -9 3359


[oracle@racnode01h usrco]$ ps -ef | grep sleep
oracle    4404  1323  0 06:56 ?        00:00:00 /bin/bash /u01/app/12.1.0/grid/racg/usrco//sleep.sh INSTANCE VERSION=1.0 service=oow database=oow instance=OOW1 host=racnode01h status=up reason=USER timestamp=2016-06-26 09:56:28 timezone=-04:00 db_domain=
[oracle@racnode01h usrco]$ ps -ef | grep 1323
oracle    1323     1  0 06:27 ?        00:00:11 /u01/app/12.1.0/grid/bin/oraagent.bin



Note
참고로, FAN 메시지는 Oracle Notification Service (ONS)가 청취하는 것으로 알려져 있으나, 테스트 결과 ONS 데몬을 다운시킨 상태에서도 FAN 메시지는 oraagent.bin에게 전달되는 것을 확인했습니다. 이것이 "그림-1"에 ONS와 oraagent.bin 간의 관계를 "?"로 한 이유입니다.


그림-1. FAN 콜아웃 수행 구조도



5-4. FAN 메시지 구성 요소



FAN 메시지는 7개의 구성요소로 이루어집니다. FAN 메시지 유형 중에서 애플리케이션 up/down 및 인스턴스 up/down과 관련된 메시지는 다음과 같습니다.


예시-1. ONLINE_SRV 서비스가 up된 경우의 FAN 메시지 
아규먼트[0] SERVICE
아규먼트[1] VERSION=1.0
아규먼트[2] service=ONLINE_SRV
아규먼트[3] database=oow
아규먼트[4] instance=OOW2
아규먼트[5] host=racnode02h
아규먼트[6] status=up

아규먼트[0] SERVICEMEMBER
아규먼트[1] VERSION=1.0
아규먼트[2] service=ONLINE_SRV
아규먼트[3] database=oow
아규먼트[4] instance=OOW3
아규먼트[5] host=racnode03h
아규먼트[6] status=up


예시-2. OOW1 인스턴스가 up된 경우의 FAN 메시지
아규먼트[0] INSTANCE
아규먼트[1] VERSION=1.0
아규먼트[2] service=oow
아규먼트[3] database=oow
아규먼트[4] instance=OOW1
아규먼트[5] host=racnode01h
아규먼트[6] status=up



5-5. FAN 메시지를 이용한 자동 재배치(Auto Rebalancing) 콜아웃 설정



인스턴스가 기동 된 직후에 "예시-2"와 같은 FAN 메시지를 제공받게 되므로, 해당 FAN 메시지를 이용해서 자동 재배치 기능을 구현할 수 있습니다. 자동 재배치를 위한 auto_rebalance.sh를 $GRID_HOME/racg/usrco 에 저장한 후 파일 퍼미션을 700으로 변경합니다.


[oracle@racnode01h usrco]$ vi auto_rebalance.sh

#!/bin/bash
export LANG=C
export LOG=/u01/app/12.1.0/grid/racg/log/auto_rebalance.log
export ORACLE_HOME=/u01/app/12.1.0/grid/
export PATH=$PATH:$ORACLE_HOME/bin
export HOST=`hostname | cut -f 1 -d .`

touch $LOG

if [ "$1" = "INSTANCE" ]; then
argmts=($*)
INSTANCE_NAME=`echo ${argmts[4]}|cut -d '=' -f 2`
HOST_NAME=`echo ${argmts[5]}|cut -d '=' -f 2`
INSTANCE_STATUS=`echo ${argmts[6]}|cut -d '=' -f 2`

if [[ "$INSTANCE_STATUS" = "up" && "$HOST_NAME" = "$HOST" ]]; then
echo "[`date`] Starting the rebalance of services on Node $INSTANCE_NAME" >> $LOG

services=`srvctl config service -d OOW | egrep '(Service name|Preferred)' | awk '{print $NF}'| paste -s -d",\n" | grep $INSTANCE_NAME | cut -d ',' -f1`

for i in $services
do
echo $i
srvctl stop  service -s $i -d OOW
srvctl start service -s $i -d OOW
done

echo -e "The following services have been relocated to $INSTANCE_NAME:\n$services " >> $LOG
fi
fi

[oracle@racnode01h usrco]$ chmod 700 auto_rebalance.sh


Note
쉘 프로그램 출처: http://www.learnoracledba.com/auto-services-rebalancing-using-fan-cluster-callouts



5-6. 자동 재배치 콜아웃 설정 후 테스트 수행



자동 재배치 콜아웃 테스트 결과, OOW1 인스턴스가 시작한 직후에 3번 노드로 Failover된 ONLINE_SRV 서비스가 1번 노드로 자동으로 재배치 된 것을 확인할 수 있습니다. 이와 같이, FAN 콜아웃을 이용하면 자동 재배치 뿐 아니라, FAN 관련 이벤트에 대한 다양한 처리를 할 수 있습니다. RAC 운영 시에 한번쯤 생각해보면 좋은 기능인 것 같습니다.


[oracle@racnode01h usrco]$ srvctl status service -d OOW
Service BATCH_SRV  is running on instance(s) OOW3
Service ONLINE_SRV is running on instance(s) OOW2,OOW3

[oracle@racnode01h usrco]$ ps -ef | grep pmon
oracle    1681     1  0 06:28 ?        00:00:00 asm_pmon_+ASM1
oracle    1980     1  0 06:29 ?        00:00:00 ora_pmon_OOW1

[oracle@racnode01h usrco]$ kill -9 1980

[oracle@racnode01h usrco]$ srvctl status service -d OOW
Service BATCH_SRV  is running on instance(s) OOW3
Service ONLINE_SRV is running on instance(s) OOW2,OOW3

-- OOW1 인스턴스 up 직후에 ONLINE_SRV 서비스가 자동으로 재배치됨
[oracle@racnode01h usrco]$ ps -ef | grep pmon
oracle    1681     1  0 06:28 ?        00:00:00 asm_pmon_+ASM1
oracle    3359     1  0 06:35 ?        00:00:00 ora_pmon_OOW1

[oracle@racnode01h usrco]$ srvctl status service -d OOW
Service BATCH_SRV  is running on instance(s) OOW3
Service ONLINE_SRV is running on instance(s) OOW1,OOW2


글을 마치며


오라클 서비스를 이용한 워크로드 관리를 설명하다가 FAN 콜아웃까지 설명을 하게 되었습니다. 필드에서 "서비스"를 범용적으로 사용하는지는 잘 모르겠으나 꽤 좋은 기능인 것만은 확실합니다. "서비스"에 대한 학습을 한 김에 다음 포스팅은 "서비스"를 이용한 성능관리 방안에 대해서 정리할 예정입니다.


저작자 표시 비영리 변경 금지
신고
크리에이티브 커먼즈 라이선스
Creative Commons License

리눅스 관련된 자료를 찾다가 “열씨미와 게을러의 리눅스 개발 노하우 탐험기”란 책의 일부 내용을 접하게 됐습니다. 각 주제의 도입부가 문답법으로 진행되는 방식인데, 아주 재미있게 읽었습니다. 저도 이번 포스팅부터는 "궁금이"와 "똘똘이" 캐릭터를 이용해서 묻고 답하기 형태를 접목시켜 보려고 합니다. :)


똘똘님! 제가 이번에 RAC 3 노드 구축 프로젝트에 참여하게 됐습니다. :) 이번 구축 프로젝트에서 가장 중요하게 생각하는 부분 중의 하나는 워크로드 관리라고 할 수 있습니다. 온라인 서비스는 RAC 1, 2번 노드를 이용해서 골고루 부하를 분산 시키고 싶고, RAC 3번 노드는 배치 서비스용으로 사용하고 싶습니다. 배치 서비스는 대부분 새벽 시간대에만 수행되므로 업무 시간 (9~6)에는 Idle한 편입니다. 따라서, 만일 RAC 1 또는 2번 노드에 장애가 발생할 경우에는 온라인 서비스를 RAC 3번 노드로 Failover하고 싶고, RAC 3번 노드의 장애가 발생할 경우에는 배치 서비스를 RAC 1 또는 2번 노드로 Failover 하고 싶습니다. 어떻게 하면 좋을까요?


 


궁금님! 말씀하신 부분은 "서비스"를 이용하면 됩니다. 자! 그럼 "서비스"에 대해서 세부적으로 알아보도록 하겠습니다.



4-1. 서비스 사용 목적



서비스는 오라클 10g부터 제공되는 기능으로써, 크게 2가지 목적으로 사용됩니다.


  1. 효과적인 워크로드 관리를 위해 사용됩니다. 이를 위해, 서비스 별로 실행 가능한 노드를 설정하고, Failover 노드를 설정하고, 로드 밸런싱 설정등을 할 수 있는 기능을 제공합니다.
  2. 서비스 별 성능관리를 위해서 사용됩니다. (별도 포스팅 예정)


4-2. 서비스 생성 및 확인 방법



서비스는 DBMS_SERVICE 패키지, SRVCTL, EM을 이용해서 생성할 수 있습니다. 싱글 인스턴스에서는 DBMS_SERVICE 패키지를 이용해도 되지만, RAC 환경에서는 EM 또는 SRVCTL을 이용해서 생성해야 합니다. 우리는 SRVCTL을 이용해서 온라인 서비스 (ONLINE_SRV)와 배치 서비스 (BATCH_SRV)를 생성하도록 하겠습니다. (테스트 환경은 “[01] LAB 실 – 3 노드 RAC 설치하기” 참고)


SRVCTL을 이용한 서비스 생성

srvctl add service -d OOW -service ONLINE_SRV -preferred OOW1,OOW2 -available OOW3 -failovermethod BASIC
srvctl add service -d OOW -service BATCH_SRV  -preferred OOW3 -available OOW1,OOW2 -failovermethod BASIC


옵션 중에 주목해야할 부분은 preferredavailable입니다.


  • preferred: 서비스 시작 시, 해당 서비스가 수행되는 노드를 지정
  • available: 서비스가 Failover되는 노드를 지정

서비스 시작

srvctl start service -d OOW -s ONLINE_SRV
srvctl start service -d OOW -s BATCH_SRV


GV$ACTIVE_SERVICES 뷰를 이용한 서비스 확인

select inst_id, name
from gv$active_services
where name like '%SRV%'
order by 1,2;

   INST_ID NAME
---------- --------------------
         1 ONLINE_SRV
         2 ONLINE_SRV
         3 BATCH_SRV


SRVCTL를 이용한 서비스 확인

srvctl status service -d OOW

Service BATCH_SRV  is running on instance(s) OOW3
Service ONLINE_SRV is running on instance(s) OOW1,OOW2


서비스 시작 후의 상태를 확인해보면, ONLINE_SRV 서비스는 1, 2번 노드에서 수행되고 있고, BATCH_SRV 서비스는 3번 노드에서만 수행되고 있다는 것을 알 수 있습니다. (그림-1. 참조)


그림-1. 서비스 시작 후의 구성도




4-3. 클라이언트에서 서비스로 접속하는 방법



그렇다면 클라이언트에서는 어떻게 해당 서비스로 접속하는 것일까요? 이에 대한 답은 오라클 10g부터 변경된 TNSNAMES.ORA 파일의 내용에서 찾을 수 있습니다. 오라클 10g부터는 SID 대신 SERVICE_NAME을 사용합니다. (물론, SID도 사용 가능합니다) DB가 생성되면 DB명과 동일한 서비스가 생성되고, 해당 서비스명을 이용해서 DB에 접속할 수 있게 됩니다. 따라서, DB 생성 이후에 lsnrctl service 명령어를 수행하면 아래와 같은 결과를 확인할 수 있습니다.


[oracle@racnode01h dbs]$ lsnrctl service

LSNRCTL for Linux: Version 12.1.0.2.0 - Production on 25-JUN-2016 08:28:12
Copyright (c) 1991, 2014, Oracle.  All rights reserved.
Connecting to (ADDRESS=(PROTOCOL=tcp)(HOST=)(PORT=1521))
Services Summary...
Service "+ASM" has 1 instance(s).
  Instance "+ASM1", status READY, has 1 handler(s) for this service...
    Handler(s):
      "DEDICATED" established:0 refused:0 state:ready
         LOCAL SERVER
Service "OOW" has 1 instance(s).
  Instance "OOW1", status READY, has 1 handler(s) for this service...
    Handler(s):
      "DEDICATED" established:0 refused:0 state:ready
         LOCAL SERVER
Service "OOWXDB" has 1 instance(s).
  Instance "OOW1", status READY, has 1 handler(s) for this service...
    Handler(s):
      "D000" established:0 refused:0 current:0 max:1022 state:ready
         DISPATCHER <machine: racnode01h, pid: 10243>
         (ADDRESS=(PROTOCOL=tcp)(HOST=racnode01h.oow.local)(PORT=35560))
The command completed successfully


Note
서비스 등록 및 시작 후에는 다음과 같은 결과가 출력됩니다. 즉, OOW1번 노드의 로컬 리스너는 OOW (기본 서비스) 및 ONLINE_SRV 서비스에 대한 접속을 관리하게 됩니다.


[oracle@racnode01h dbs]$ lsnrctl service

LSNRCTL for Linux: Version 12.1.0.2.0 - Production on 25-JUN-2016 08:35:48
Copyright (c) 1991, 2014, Oracle.  All rights reserved. Connecting to (ADDRESS=(PROTOCOL=tcp)(HOST=)(PORT=1521))
Services Summary...
Service "+ASM" has 1 instance(s).
  Instance "+ASM1", status READY, has 1 handler(s) for this service...
    Handler(s):
      "DEDICATED" established:0 refused:0 state:ready
         LOCAL SERVER
Service "ONLINE_SRV" has 1 instance(s).
  Instance "OOW1", status READY, has 1 handler(s) for this service...
    Handler(s):
      "DEDICATED" established:0 refused:0 state:ready
         LOCAL SERVER
Service "OOW" has 1 instance(s).
  Instance "OOW1", status READY, has 1 handler(s) for this service...
    Handler(s):
      "DEDICATED" established:0 refused:0 state:ready
         LOCAL SERVER
Service "OOWXDB" has 1 instance(s).
  Instance "OOW1", status READY, has 1 handler(s) for this service...
    Handler(s):
      "D000" established:0 refused:0 current:0 max:1022 state:ready
         DISPATCHER <machine: racnode01h, pid: 10243>
         (ADDRESS=(PROTOCOL=tcp)(HOST=racnode01h.oow.local)(PORT=35560))
The command completed successfully


클라이언트의 TNSNAMEA.ORA 설정 방법은 다음과 같습니다.

ONLINE_SRV =
  (DESCRIPTION =  
   (LOAD_BALANCE=ON)
    (FAILOVER=ON)
    (ADDRESS_LIST=
     (ADDRESS = (PROTOCOL = TCP)(HOST = racnode01h-vip)(PORT = 1521))
     (ADDRESS = (PROTOCOL = TCP)(HOST = racnode02h-vip)(PORT = 1521))
     (ADDRESS = (PROTOCOL = TCP)(HOST = racnode03h-vip)(PORT = 1521))
    )
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = ONLINE_SRV)
    )
  )
BATCH_SRV =
  (DESCRIPTION =
   (LOAD_BALANCE=OFF)
    (FAILOVER=ON)
    (ADDRESS_LIST=
     (ADDRESS = (PROTOCOL = TCP)(HOST = racnode01h-vip)(PORT = 1521))
     (ADDRESS = (PROTOCOL = TCP)(HOST = racnode02h-vip)(PORT = 1521))
     (ADDRESS = (PROTOCOL = TCP)(HOST = racnode03h-vip)(PORT = 1521))
    )
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = BATCH_SRV)
    )



4-4. 서비스 Failover 동작 방식 테스트



1번 노드에 장애가 발생할 경우에, 1번 노드에서 수행 중인 ONLINE_SRV 서비스가 정상적으로 3번 노드로 Failover 되는지를 확인해 보도록 하겠습니다.


1번 노드 장애 발생 후 서비스 Failover 결과 확인

[oracle@racnode01h dbs]$ ps -ef | grep pmon
oracle   10177     1  0 08:23 ?        00:00:00 ora_pmon_OOW1
oracle   25979     1  0 Jun24 ?        00:00:05 asm_pmon_+ASM1

[oracle@racnode01h dbs]$ kill -9 10177

[oracle@racnode01h dbs]$ srvctl status service -d OOW

Service BATCH_SRV  is running on instance(s) OOW3
Service ONLINE_SRV is running on instance(s) OOW2, OOW3


Note
1번 노드의 장애 발생 직후에, ONLINE_SRV 서비스는 3번 노드로 Failover 된 것을 알 수 있습니다. (그림-2 참조)


그림-2. ONLINE_SRV 서비스 Failover 후의 구성도



1번 노드의 장애가 복구된 후에는 어떻게 될까요?


3번 노드로 Failover된 ONLINE_SRV 서비스는 1번 노드의 장애가 복구된 후에도 여전히 3번 노드에 존재하게 됩니다. (그림-3. 참조) 오라클은 “서비스”에 대해서는 자동 재배치 (Auto Rebalancing) 기능을 제공하지 않기 때문입니다.


그림-3. 1번 노드 장애 복구 후의 구성도



그렇다면, "자동 재배치 기능은 어떻게 구현할 수 있을까?" 하는 의문이 생깁니다.

만일, 자동 재배치를 수동으로 해야한다면 "서비스"를 업무에 적용하기에는 현실적인 어려움이 따르기 때문입니다. 이 문제를 해결하기 위해 오라클은 "FAN (Fast Application Notification) Callouts"을 이용한 자동 재배치 기능을 제공하고 있습니다. 


해당 내용에 대해서는 다음 포스팅에서 다루도록 하겠습니다.


"[05] FAN 콜아웃 (Callouts)을 이용한 서비스 자동 재배치 방법" 으로바로가기


저작자 표시 비영리 변경 금지
신고
크리에이티브 커먼즈 라이선스
Creative Commons License

[03] SCAN (Single Client Access Network) 동작원리

RAC 2016.06.22 16:57 Posted by 시연아카데미

오라클 12c RAC로 DB 서버를 신규 구축하려고 합니다. SCAN을 사용하는 것이 좋을까요?”


위와 같은 질문을 받았다고 가정해보겠습니다. 이에 대한 대답은 크게 3가지 정도로 나뉠 것 같습니다.


  1. 새로운 기능은 위험 부담이 있습니다. 기존처럼 VIP를 사용하는 것이 좋습니다
  2. SCAN이 좋다고 하던데, 한번 적용해 볼까요?
  3. SCAN의 특성은 이러합니다. 또한 SCAN의 장단점은 이러합니다. 따라서 우리 환경의 특성을 고려해볼 때 SCAN을 적용하는 것은 무리가 있을 것 같습니다. (또는, SCAN의 특성 상 우리 환경에 적합해 보입니다. 테스트 환경을 구축해서 검증해보도록 하겠습니다)  

아마 1번과 같은 답변이 꽤 많을 것 같습니다. 왜냐하면, IT가 최첨단의 기술을 접목시키는 분야이기도 하지만, 인프라가 잘 운영(또는 고착)되고 있는 상황에서는 어느 정도의 보수성을 가지기 때문입니다. 2번과 같은 반응은 두말할 나위 없이 위험합니다. 우리가 공부를 하는 이유는 3번과 같은 답을 위해서 입니다.


제가 며칠동안 SCAN을 학습하면서 내린 나름의 결론은 “SCAN은 고수준의 자동 로드 밸런싱이 필요한 환경에서만 적용하는 것이 좋다”입니다. 좀 더 풀어서 말하면


  • RAC 노드들이 꽤 많고
  • 애플리케이션 로드 밸런싱을 수행하며
  • 노드들의 추가 또는 삭제가 자주 발생하는 환경을 의미합니다.

(이런 환경이 많이 있을지 의문이 들긴 합니다)


조금 더 세부적인 이야기는 SCAN의 동작원리를 설명하면서 진행하도록 하겠습니다.


3. SCAN (Single Client Access Network) 동작원리


3-1. SCAN이란?


SCAN은 11gR2부터 제공되며, 하나의 이름으로 RAC의 모든 노드를 액세스할 수 있는 기능입니다. 기존에는 클라이언트마다 커넥션 스트링을 관리한 반면, SCAN을 사용하게 되면 DNS 레벨에서 중앙 집중적으로 커넥션 스트링을 관리할 수 있게 됩니다. SCAN을 이용한 TNS 설정 방법은 “예시-1”을 참고하시면 됩니다.


예시-1. TNSNAMES.ORA 예제

-- SCAN을 이용한 설정
ORA12C_SCAN =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = rac-scan)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = ORA12C)
    )
)
-- VIP를 이용한 설정 (기존 방식)
ORA12C_VIP =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = rac1-vip)(PORT = 1521))
    (ADDRESS = (PROTOCOL = TCP)(HOST = rac2-vip)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = ORA12C)
    )
  )


위의 예시에서 rac-scan이 SCAN 명이고 해당 명칭은 DNS에서 인식이 가능해야 합니다.


Note
테스트를 위해 DNS 서버를 구성하려는 분들은 “Dnsmasq를 이용해서 간단한 DNS 서버를 구성하는 방법”을 참고하세요.



3-2. SCAN의 장점


SCAN의 장점은 크게 2가지로 요약할 수 있습니다.


  1. 클라이언트마다 수행하던 커넥션 스트링 관리를 DNS 레벨에서 관리
  2. SCAN 리스너를 이용하여 기존보다 정확한 로드 밸런싱 수행

기존 방식을 사용할 경우에는 RAC 노드가 추가 또는 삭제될 경우에 클라이언트마다 커넥션 스트링 (TNSNAMES.ORA 및 JDBC Connection String)을 변경할 필요가 있습니다. 하지만 SCAN을 사용할 경우에는 DNS 서버에서 커넥션 스트링을 관리하므로 클라이언트들은 별도의 변경 작업이 필요 없다는 장점이 있습니다.


또한, 기존의 VIP 리스너는 워크로드를 정확하게 계산하지 못하므로 최적의 로드 밸런싱을 수행하지 못했던 문제가 존재했으나,, SCAN 리스너는 최적의 로드 밸런싱을 수행한다고 합니다.

이러한 2가지 장점이 큰 이득이 되는 환경에서는 SCAN 적용을 검토할 필요가 있습니다. 만일 그렇지 않다면 VIP를 이용하는 것이 좋습니다.



3-3. SCAN 구성도


SCAN 명은 DNS에서 관리되고, SCAN IP는 최대 3개를 사용합니다. SCAN IP 마다 1개의 SCAN 리스너가 할당되므로 SCAN 리스너 역시 최대 3개입니다. SCAN 리스너의 역할은 클라이언트의 접속 요청이 있는 경우에, DB 서버들의 부하를 체크한 후 최적의 노드를 선택하고 해당 노드의 Local 리스너에게 접속 요청을 전달하는 것입니다.


즉, 가벼운 역할 (부하 체크 & Local 리스너에게 접속 요청 재전송)만을 수행하므로 RAC 노드 수와 무관하게 (RAC 노드 수가 수십 개라도) 최대 3개만 제공합니다. SCAN를 적용한 RAC 구성도는 “그림-1”과 같습니다.


그림-1. SCAN을 적용한 RAC 구성도


Note
RAC 2 노드 환경에서 3개의 SCAN IP를 설정했다면 1개의 서버에 2개의 SCAN IP가 할당되고 나머지 1개의 서버에 1개의 SCAN IP가 할당됩니다.



3-4. Connection Pool 환경에서 SCAN 사용 시 주의 사항


WAS 환경에서는 일반적으로 Connection Pool을 사용하며, Connection Pool 별로 서로 다른 서비스를 제공합니다. “그림-2”는 VIP 환경에서 2개의 Connection Pool을 이용해서 2개의 서비스를 제공하는 예입니다.


그림-2. VIP 환경에서의 Connection Pool 예시



이러한 환경에서, “서비스” 설정 없이 SCAN을 사용할 경우에는 “그림-3”과 같은 문제가 발생하게 됩니다. 즉, 동일한 서비스에 대한 커넥션이 서로 다른 노드에 접속할 가능성이 높고, 이로 인해 불필요한 Interconnect 전송이 발생함으로써 성능 저하가 발생할 수 있습니다.


그림-3. SCAN 환경에서의 Connection Pool 예시



따라서, SCAN을 적용할 때는 커넥션 관리 부분을 신경 써야하고, 이를 위해서는 반드시 “서비스”를 적용하는 것이 좋습니다. “서비스”에 대해서는 다음 연재에서 다루도록 하겠습니다.


참고문헌


Expert Oracle RAC 12c [Apress – Syed Jaffar Hussain외 3명]
Oracle Single Client Access Network (SCAN) [June 2013 – An Oracle White Paper]



저작자 표시 비영리 변경 금지
신고
크리에이티브 커먼즈 라이선스
Creative Commons License

[02] 하드웨어 관점에서의 RAC 아키텍처

RAC 2016.06.16 02:39 Posted by 시연아카데미

RAC 아키텍처를 정확히 이해하기 위해서는 하드웨어 (및 OS)에 대한 지식이 필요합니다. 아키텍처와 관련된 자료들을 보면 NIC, VIP, Private Network, Interconnect Switch, NIC Bonding, SAN, Multipath IO, HBA 등의 용어들을 자주 접하게 됩니다. 영문으로 될 글을 읽을 때 단어를 잘 모르면 전반적인 맥락은 이해하더라도 정확한 해석이 힘든 것과 마찬가지로, RAC를 이해함에 있어서 이러한 용어들에 대한 이해는 반드시 필요하다고 할 수 있습니다. 하드웨어 관련된 구성에 있어서는 문외한에 가깝지만, 며칠 동안 여러가지 자료를 이용해서 학습한 내용을 바탕으로 하드웨어 관점에서의 RAC 아키텍처를 정리하도록 하겠습니다.


 

2. 하드웨어 관점에서의 RAC 아키텍처


2-1. 기본 구성도



엔터프라이즈 환경에서 단순하게(이중화 구성 없이) RAC를 구성하는 방법은 “그림-1”과 같습니다. 즉, 하드웨어 관점에서의 RAC 아키텍처는 2개의 DB 서버, 이더넷 스위치 1개, Gigabit 스위치 1개, SAN 스위치 1개, 공유 디스크용 스토리지 1개로 구성됩니다.


그림-1. RAC 기본 구성도





다음은 기본 구성도와 관련된 용어 설명입니다.


  • NIC (Network Interface Card): DB 서버를 이더넷 스위치에 연결하기 위한 케이블을 꼽는 장치
  • HBA (Host Bus Adapter): DB 서버를 SAN 스위치에 연결하기 위한 케이블을 꼽는 장치
  • Fast Ethernet 스위치: 초당 100 Mbps (12.5Mbyte)의 대여폭을 제공하는 스위치
  • Gigabit 스위치: 초당 1000 Mbps (125 Mbyte) 이상의 대여폭을 제공하는 스위치
  • SAN 스위치: SAN (Storage Arrary Network)에 액세스하기 위한 스위치



2.2 Public IP, Private IP, SCAN IP, VIP의 차이점



  • Public IP: 외부에서 접속 가능한 IP입니다. 주로 DBA 또는 시스템 관리자가 관리 목적으로 DB 서버에 접속할 때 사용합니다.
  • Private IP: DB 서버 간의 Interconnect 통신만을 위해서 사용되는 IP입니다.
  • VIP: DB 서버 장애 발생 시, Fail-Over 목적으로 사용되는 가상 IP입니다. Public IP가 할당된 NIC에 설정됩니다. Public IP가 할당된 NIC가 eth0이라면, VIP는 eth0:1로 설정됩니다.
  • SCAN (Single Client Access Name): VIP를 이용해서 클라이언트 쪽의 TNANAMES.ORA 파일을 설정하면, RAC 노드를 추가하거나 삭제할 때 마다 TNSNAMES.ORA 파일을 수정해야하는 문제점을 가지고 있었습니다. SCAN은 이러한 문제를 해결하기 위해서 11gR2부터 제공되는 기능이며, SCAN IP는 VIP와 마찬가지로 Public IP가 할당된 NIC에 설정됩니다. 


2.3 DB 서버 장애 시 VIP, SCAN IP Fail-Over



DB 서버(#1)에 장애가 발생할 경우, SCAN IP(1), SCAN IP(2) 및 VIP는 DB 서버(#2)의 NIC 0에 설정됩니다. 즉, "그림-2"와 같이 설정됩니다.


그림-2. DB 서버 장애 시, IP Fail-Over





이때 DB 서버(#2)에서 ifconfig 명령어를 수행하면 다음과 같은 결과가 출력됩니다.

# ifconfig
eth0      Link encap:Ethernet  HWaddr 08:00:27:15:D5:D0
          inet addr:192.168.56.72  Bcast:192.168.56.255  Mask:255.255.255.0
          inet6 addr: fe80::a00:27ff:fe15:d5d0/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:17574 errors:0 dropped:0 overruns:0 frame:0
          TX packets:8014 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:16092152 (15.3 MiB)  TX bytes:4412947 (4.2 MiB)
eth0:1    Link encap:Ethernet  HWaddr 08:00:27:15:D5:D0
          inet addr:192.168.56.82  Bcast:192.168.56.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
eth0:2    Link encap:Ethernet  HWaddr 08:00:27:15:D5:D0
          inet addr:192.168.56.91  Bcast:192.168.56.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
eth0:3    Link encap:Ethernet  HWaddr 08:00:27:15:D5:D0
          inet addr:192.168.56.81  Bcast:192.168.56.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
eth0:4    Link encap:Ethernet  HWaddr 08:00:27:15:D5:D0
          inet addr:192.168.56.92  Bcast:192.168.56.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
eth0:5    Link encap:Ethernet  HWaddr 08:00:27:15:D5:D0
          inet addr:192.168.56.93  Bcast:192.168.56.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
eth1      Link encap:Ethernet  HWaddr 08:00:27:27:95:03
          inet addr:192.168.10.2  Bcast:192.168.10.255  Mask:255.255.255.0
          inet6 addr: fe80::a00:27ff:fe27:9503/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:432318 errors:0 dropped:0 overruns:0 frame:0
          TX packets:522063 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:250003557 (238.4 MiB)  TX bytes:380719952 (363.0 MiB)
eth1:1    Link encap:Ethernet  HWaddr 08:00:27:27:95:03
          inet addr:169.254.240.162  Bcast:169.254.255.255  Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
eth2      Link encap:Ethernet  HWaddr 08:00:27:0C:B7:19
          inet addr:10.0.4.15  Bcast:10.0.4.255  Mask:255.255.255.0
          inet6 addr: fe80::a00:27ff:fe0c:b719/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:53 errors:0 dropped:0 overruns:0 frame:0
          TX packets:114 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:8652 (8.4 KiB)  TX bytes:17465 (17.0 KiB)


참고로 /etc/hosts 파일의 내용은 다음과 같습니다.

# cat /etc/hosts
127.0.0.1   localhost localhost.localdomain
::1         localhost localhost.localdomain <
#public
192.168.56.71   rac1        rac1.dbaora.com
192.168.56.72   rac2        rac2.dbaora.com
#private
192.168.10.1    rac1-priv   rac1-priv.dbaora.com
192.168.10.2    rac2-priv   rac2-priv.dbaora.com
#virtual
192.168.56.81   rac1-vip    rac1-vip.dbaora.com
192.168.56.82   rac2-vip    rac2-vip.dbaora.com
#scan
192.168.56.91   rac-scan    rac-scan.dbaora.com
192.168.56.92   rac-scan    rac-scan.dbaora.com
192.168.56.93   rac-scan    rac-scan.dbaora.com




2-4. 가용성을 높이기 위한 이중화 구성도



높은 가용성 (Availability)을 위해서는 SPOF (Single Point Of Failure)를 최대한 제거해야만 합니다.


SPOF란?
시스템 구성 요소 중에서, 동작하지 않으면 전체 시스템이 중단되는 요소를 의미합니다. (위키백과)
https://ko.wikipedia.org/wiki/%EB%8B%A8%EC%9D%BC_%EC%9E%A5%EC%95%A0%EC%A0%90


SPOF를 제거하기 위해서는 이중화가 필수적입니다. RAC에서의 이중화 방법은 “그림-3”과 같습니다. 즉, 스위치 장애를 대비하기 위해서 스위치를 이중화하고, 네트워크 케이블 불량에 대비하기 위해서 “NIC Bonding”을 구성하고, IO 채널 불량에 대비하기 위해서 “Multipath IO”를 구성합니다.


그림-3. 이중화를 적용한 RAC 구성도




NIC Bonding이란?
2개 이상의 NIC를 하나의 디바이스로 인식하게 하는 방법입니다. 대여폭을 확장하거나 Active / Standby 형태로 구성할 수 있습니다.


Multipath IO (MPIO)란?
공유 디스크용 스토리지를 액세스하기 위한 경로가 2개 이상인 것을 의미합니다. IO 채널 불량에 대한 fault-tolerance 및 로드 밸런싱을 통한 성능 향상을 목적으로 합니다.



글을 마치며



하드웨어 구성을 정리하다 보니, SCAN에 대해서 조금 더 자세히 정리할 필요성을 느꼈습니다. “RAC 연재”의 다음 주제는 “SCAN”으로 찾아 뵙겠습니다.



저작자 표시 비영리 변경 금지
신고
크리에이티브 커먼즈 라이선스
Creative Commons License

[01] LAB실 - 3 노드 RAC 설치하기

RAC 2016.06.08 15:24 Posted by 시연아카데미

1. LAB실 - 3 노드 RAC 설치하기



RAC 연재에 앞서, 3 노드 RAC 환경을 구축하기로 마음 먹었습니다. 2 노드 RAC 설치, EXADATA 설치 등, 설치로 인한 피로감이 있긴 하지만 제대로 된 3-Way 통신 테스트를 위해서는 3 노드 RAC 환경을 구축하는 것이 필요하기 때문입니다.


3 노드 RAC 설치를 위해 구글링한 결과, 오라클에서는 이미 OOW 행사 시의 LAB실 진행을 위해 3 노드 및 4 노드 RAC 생성을 위한 템플릿을 제공하고 있습니다. 해당 템플릿을 이용하면 3 노드, 4 노드 뿐 아니라 Flex ASM & Cluster 환경도 구성이 가능합니다. 


이번 LAB실은 표준 모드로 RAC 3 노드를 구축할 예정입니다. (Flex ASM & Cluster 환경 구성은 향후 진행 예정입니다). 대부분의 내용은 오라클에서 제공하는 문서대로 진행하시면 됩니다. 영문으로 된 문서이긴 하지만 정리가 잘되어 있으므로 문서대로만 따라하시면 설치가 완료될 것으로 확신합니다. 몇 가지 주의 사항은 아래 내용을 참고하세요.


  • 3 노드 RAC 환경 구축을 위해서는 최소 16 GB RAM이 필요합니다.
  • 16 GB RAM 인 경우에도, VM 메모리 설정을 적절히 잘 해야합니다. ("그림1" 참고)
  • Deploy시에는 Manager Server의 root 유저 홈 디렉토리에 있는 DBRACOVM-Deploycluster3-tool_HOL10471.zip을 이용하시면 됩니다.
  • 오라클에서 제공하는 템플릿은 Flex ASM & Cluster 환경 (2 HUB 노드, 1 LEAF 노드)이므로, 템플릿을 약간 수정해야 합니다 ("표1" 참고)

1-1. 오라클 설치 가이드 및 VM 이미지 다운로드 위치


아래의 사이트에서 2개의 ova (ovmm10471.oow.local.ova, ovs10471.oow.local.ova)를 다운로드하고 "Read the tab instructions here"를 클릭해서 설치 매뉴얼을 다운로드합니다.

http://www.oracle.com/technetwork/server-storage/vm/downloads/hol-oraclevm-2368799.html



1-2. VM 및 RAC 노드 메모리 설정


16 GB RAM 환경이더라도, PC에서 사용하는 기본 메모리등을 고려했을때 "그림1"과 같이 설정하는 것이 좋습니다.


  • OVMM10471.OOW.LOCAL VM 메모리는 3 GB로 설정 (기본 설정은 4 GB이므로, VM 환경 설정에서 변경)
  • OVS10471.OOW.LOCAL VM 메모리는 8 GB로 설정 (기본 설정은 9 GB이므로, VM 환경 설정에서 변경)
  • RACNODE0.1/0.2/0.3 3개의 RAC 노드의 메모리는 2400 MB로 설정 (기본 설정은 3 GB임. 변경 방법은 설치 매뉴얼 참고)

그림1. 3 노드 RAC 구성도



1-3. 빌드 스크립트 변경


Manager Server (192.168.56.30)의 /root/deploycluster3/utils/netconfig12cRAC3node.ini 파일 내용을 "표1" 내용으로 변경합니다.(##으로 된 부분이 표준 RAC 모드 설치를 위해 주석 처리한 부분입니다)


표1. 표준 모드 RAC 생성용 스크립트

# Node specific information
NODE1=racnode01h
NODE1IP=192.168.56.120
NODE1PRIV=racnode01h-priv
NODE1PRIVIP=10.10.10.230
NODE1VIP=racnode01h-vip
NODE1VIPIP=192.168.56.230
##NODE1ROLE=HUB
NODE2=racnode02h
NODE2IP=192.168.56.121
NODE2PRIV=racnode02h-priv
NODE2PRIVIP=10.10.10.231
NODE2VIP=racnode02h-vip
NODE2VIPIP=192.168.56.231
##NODE2ROLE=HUB
NODE3=racnode03h
NODE3IP=192.168.56.122
NODE3PRIV=racnode03h-priv
NODE3PRIVIP=10.10.10.232
NODE3VIP=racnode03h-vip
NODE3VIPIP=192.168.56.232
##NODE3ROLE=LEAF
# Common data
PUBADAP=eth0
PUBMASK=255.255.255.0
PUBGW=192.168.56.1
PRIVADAP=eth1
PRIVMASK=255.255.255.0
RACCLUSTERNAME=oow12c
DOMAINNAME=oow.local  # May be blank
DNSIP=  # Starting from 2013 Templates allows multi value
# Device used to transfer network information to second node
# in interview mode
##NETCONFIG_DEV=/dev/xvdc
# 11gR2 specific data
SCANNAME=oow12c-scan
SCANIP=192.168.56.235
##GNS_ADDRESS=192.168.56.236
# 12c Flex parameters (uncomment to take effect)
##FLEX_CLUSTER=yes  # If 'yes' implies Flex ASM as well
##FLEX_ASM=yes
##FLEX_ASM=yes
##ASMADAP=eth2  # Must be different than private/public
##ASMMASK=255.255.255.0
##NODE1ASMIP=10.11.0.230
##NODE2ASMIP=10.11.0.231
##NODE3ASMIP=10.11.0.232
# Single Instance (description in params.ini)
# CLONE_SINGLEINSTANCE=yes  # Setup Single Instance
#CLONE_SINGLEINSTANCE_HA=yes  # Setup Single Instance/HA (Oracnodele Restart)



마치며


"RAC 연재"의 다음 주제는 "그리드 인프라스트럭처에 대한 이해" "RAC 아키텍처" 입니다. 설치 환경을 기반으로 연구 및 테스트 후에 포스팅 예정입니다.




저작자 표시 비영리 변경 금지
신고
크리에이티브 커먼즈 라이선스
Creative Commons License


 

티스토리 툴바