ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Zookeeper Watch Mechanism 알아보기
    Hadoop 2023. 12. 19. 04:44
    728x90
    반응형

    - 목차

     

    소개.

    Zookeeper 의 Watch Mechanism 은 클라이언트와 주키퍼의 양방향 통신을 가능하게 합니다.
    클라이언트는 znode 를 생성/수정/삭제/조회를 할 수 있습니다.
    주키퍼는 이러한 클라이언트의 read/write 요청을 처리합니다.
    그리고 주키퍼 또한 클라이언트에게 znode 의 상태를 공유할 수 있는데요.
    이러한 방식으로 znode 상태 변경에 대한 이벤트를 주키퍼는 클라이언트에게 전달합니다.
    카프카나 하둡의 네임노드와 같이 HA 를 구성해야하는 환경에서 주키퍼는 사용되는데요.
    이번 글에서 주키퍼의 watch mechanism 에 대해서 알아보겠습니다.


    어떤 방식으로 소통하게 될까?


    클라이언트가 서버로부터 데이터를 받는 방식은 크게 2가지가 있습니다.
    첫번째는 Polling 방식입니다.
    클라이언트의 서버 상태의 변경을 체크하기 위해서 주기적으로 요청을 보낼 수 있습니다.
    두번째는 TCP 커넥션을 맺는 방식입니다.
    Socket, Bind, Listen 등과 같은 시스템콜을 통해서 클라이언-서버의 TCP 소켓을 연결할 수 있죠.
    주키퍼의 Watch Mechanism 은 TCP 소켓 방식으로 구현됩니다.
    그리고 이러한 네트워크 연결을 세션이라고 부릅니다.
    이 세션은 Ephemeral Znode 의 저장 기간과도 같습니다.

    만약 생성된 znode 의 변경이 생긴다면,
    주키퍼는 특정 znode 를 watch 하겠다고 신청한 클라이언트들에게 znode 의 상태 변경을 보고합니다.
    즉, znode event 를 위한 TCP Connection 을 맺은 모든 client 에게 네트워크 트래픽이 전달되죠.


    Kafka 의 사례.


    카프카와 주키퍼의 관계에 대해서 설명하고자 합니다.
    카프카는 크게 3가지 Znode 를 생성합니다.
    Broker Znode
    Topic Znode
    Controller Znode

    Broker Znode 는 /brokers/ids/[brokerId] 와 같은 형식으로 znode 를 구성합니다.
    그리고 각각의 znode 의 값은 브로커의 상태, 브로커 아이디, 브로커 ip & port 로 구성됩니다.

    두번째로 Topic Znode 는 /brokers/topics/[topic]/partitions/[partitionId] 와 같은 구조를 취합니다.
    토픽과 그 내부의 파티션들이 저장되죠.

    세번째로 Controller Znode 는 현재 각 파티션의 리더 브로커들의 정보가 기록됩니다.
    Controller Znode 는 Ephemeral Znode 로 구성이 되며,
    카프카 브로커와 그 생명주기를 같이 합니다.
    만약에 한 브로커에 문제가 생겨 inactive 한 상태가 한동안 지속되었다고 가정하겠습니다.
    그렇게 되면, 주키퍼와 문제의 브로커 간의 세션이 종료되고 Ephemeral Znode 인 Controller Znode 의 상태는 변경됩니다.
    이때 Watch Mechanism 에 의해서 모든 브로커들은 하나의 브로커가 Inactive 상태임을 알 수 있습니다.
    이러한 방식으로 HA 가 구현됩니다.

    Watch Mechanism 실습해보기.

    먼저 Zookeeper 를 생성합니다.

    docker run -d --name zookeeper \
    -e ZOO_SERVERS=server.1=zookeeper1:2888:3888 \
    -e ZOO_MY_ID=1 \
    -p 2181:2181 \
    wurstmeister/zookeeper:3.4.6

     

    그리고 Zookeeper 와 통신할 Client 하나를 생성합니다.

     

    docker run -it \
    --link zookeeper:zookeeper \
    --name zookeeper-client1 wurstmeister/zookeeper:3.4.6 sh

     

    zookeeper-client1 컨테이너 내부에서 zkCli.sh 를 실행합니다.

    /opt/zookeeper-3.4.6/bin/zkCli.sh -server zookeeper:2181

     

    Connecting to zookeeper:2181
    2023-12-18 21:41:06,955 [myid:] - INFO  [main:Environment@100] - Client environment:zookeeper.version=3.4.6-1569965, built on 02/20/2014 09:09 GMT
    2023-12-18 21:41:06,968 [myid:] - INFO  [main:Environment@100] - Client environment:host.name=2b5a5fe40279
    2023-12-18 21:41:06,968 [myid:] - INFO  [main:Environment@100] - Client environment:java.version=1.7.0_65
    2023-12-18 21:41:06,976 [myid:] - INFO  [main:Environment@100] - Client environment:java.vendor=Oracle Corporation
    2023-12-18 21:41:06,977 [myid:] - INFO  [main:Environment@100] - Client environment:java.home=/usr/lib/jvm/java-7-openjdk-amd64/jre
    2023-12-18 21:41:06,977 [myid:] - INFO  [main:Environment@100] - Client environment:java.class.path=/opt/zookeeper-3.4.6/bin/../build/classes:/opt/zookeeper-3.4.6/bin/../build/lib/*.jar:/opt/zookeeper-3.4.6/bin/../lib/slf4j-log4j12-1.6.1.jar:/opt/zookeeper-3.4.6/bin/../lib/slf4j-api-1.6.1.jar:/opt/zookeeper-3.4.6/bin/../lib/netty-3.7.0.Final.jar:/opt/zookeeper-3.4.6/bin/../lib/log4j-1.2.16.jar:/opt/zookeeper-3.4.6/bin/../lib/jline-0.9.94.jar:/opt/zookeeper-3.4.6/bin/../zookeeper-3.4.6.jar:/opt/zookeeper-3.4.6/bin/../src/java/lib/*.jar:/opt/zookeeper-3.4.6/bin/../conf:
    2023-12-18 21:41:06,977 [myid:] - INFO  [main:Environment@100] - Client environment:java.library.path=/usr/java/packages/lib/amd64:/usr/lib/x86_64-linux-gnu/jni:/lib/x86_64-linux-gnu:/usr/lib/x86_64-linux-gnu:/usr/lib/jni:/lib:/usr/lib
    2023-12-18 21:41:06,978 [myid:] - INFO  [main:Environment@100] - Client environment:java.io.tmpdir=/tmp
    2023-12-18 21:41:06,978 [myid:] - INFO  [main:Environment@100] - Client environment:java.compiler=<NA>
    2023-12-18 21:41:06,981 [myid:] - INFO  [main:Environment@100] - Client environment:os.name=Linux
    2023-12-18 21:41:06,981 [myid:] - INFO  [main:Environment@100] - Client environment:os.arch=amd64
    2023-12-18 21:41:06,981 [myid:] - INFO  [main:Environment@100] - Client environment:os.version=6.4.16-linuxkit
    2023-12-18 21:41:06,982 [myid:] - INFO  [main:Environment@100] - Client environment:user.name=root
    2023-12-18 21:41:06,982 [myid:] - INFO  [main:Environment@100] - Client environment:user.home=/root
    2023-12-18 21:41:06,982 [myid:] - INFO  [main:Environment@100] - Client environment:user.dir=/opt/zookeeper-3.4.6
    2023-12-18 21:41:06,986 [myid:] - INFO  [main:ZooKeeper@438] - Initiating client connection, connectString=zookeeper:2181 sessionTimeout=30000 watcher=org.apache.zookeeper.ZooKeeperMain$MyWatcher@3aa0f03e
    Welcome to ZooKeeper!
    2023-12-18 21:41:07,071 [myid:] - INFO  [main-SendThread(zookeeper:2181):ClientCnxn$SendThread@975] - Opening socket connection to server zookeeper/172.17.0.2:2181. Will not attempt to authenticate using SASL (unknown error)
    JLine support is enabled
    2023-12-18 21:41:07,089 [myid:] - INFO  [main-SendThread(zookeeper:2181):ClientCnxn$SendThread@852] - Socket connection established to zookeeper/172.17.0.2:2181, initiating session
    2023-12-18 21:41:07,167 [myid:] - INFO  [main-SendThread(zookeeper:2181):ClientCnxn$SendThread@1235] - Session establishment complete on server zookeeper/172.17.0.2:2181, sessionid = 0x18c7edf2a6a0000, negotiated timeout = 30000
    
    WATCHER::
    
    WatchedEvent state:SyncConnected type:None path:null

     

    그리고 하나의 znode 를 생성하고 본격적으로 watch 과정을 수행해보겠습니다.

    create /testZnode "hiZnode"

     

    2개의 Zookeeper Client 가 필요합니다.

    하나는 Znode 를 수정할 Client, 다른 하나는 Watch Mechanism 을 수행할 Client 입니다.

    docker run -it \
    --link zookeeper:zookeeper \
    --name zookeeper-client2 wurstmeister/zookeeper:3.4.6 sh
    get /testZnode watch

     

    아래 이미지처럼 testZnode 의 데이터를 변경하고, 삭제를 하게 되면 Znode Watch Client 에서 알림을 받을 수 있습니다.

     

    반응형
Designed by Tistory.