Menu

문서정보

목차

분산 운영체제 구현

내가 관심있는 분야는 인프라 관점에서는 SaaS및 PaaS이며, 애플리케이션 관점에서는 메시징 플랫폼으로 메시징 플랫폼 구성 관점에서 살펴보려 한다. 보통 분산 운영체제가 애플리케이션의 실행을 목적으로 하기 때문에, 약간은 다른 내용이 될 수 있다.

분산 메시징 플랫폼

내가 구상중인 분산 메시징에 대한 아이디어는 Consistent hash 기반의 메시징 인프라를 참고하기 바란다. 여기에서는 메시징 인프라를 실제 구현하기 위한 소프트웨어적인 측면을 살펴보기로 하겠다.

플랫폼으로 이름을 붙인 이유는 채팅, 센서, 제어, 로그 수집 등 메시지를 기반으로 하는 다양한 서비스를 개발 할 수 있는 기반 소프트웨어를 목표로 하고 있기 때문이다.

구성

구성은 아래와 같다.

 분산 메시징 인프라 기본 구성

Distributed kernel(이하 커널)은 가용성과 안정성을 위해서 3개 이상의 노드로 구성된다. 이 노드들은 zookeeper로 관리한다. 이중 하나가 리더(Leader)가 되며, 나머지는 팔로워(Follower)로 작동한다. 리더가 실패 할 경우 팔로워 중 하나가 리더 선출 알고리즘을 따라서 리더가 된다. 처리를 분산하지 않고 리더로 집중하는 이유는 데이터의 분산을 막기 위함이다. 커널은 스케쥴러의 역할을 하는데, 모니터링 데이터등이 분산될 경우, 스케쥴 알고리즘을 돌리기가 어려워진다. 불가능 한 것은 아니나, 데이터 관리와 알고리즘이 복잡해 질 것이다. 스케쥴러는 특성상 요청이 많지 않기 때문에, 리더에 모두 맡겨도 별 문제는 없다.

Slave는 메시지 채널이 위치하는 노드들이다. 디바이스와 서비스들은 Hash(key, node_num)에 의해서, 적당한 Slave 노드에 연결된다.

Slave는 스케쥴링을 위해서 필요한 모니터링 정보를 커널에 전송한다. 커널은 레포팅된 모니터링 정보를 이용해서 스케쥴링을 한다. 애플리케이션을 실행하는 일반적인 분산 운영체제에서는 CPU, 메모리, 네트워크 사용율이 가장 낮은 노드를 찾아서 프로세스를 실행 할 것이다. 메시지 플랫폼의 경우에는 좀 다른 방식으로 스케쥴링 알고리즘이 만들어 질 거다. 따로 자세히 다뤄봐야 겠다.

리더 선출

Bully, Chand and Roberts algoritm, Hs algoritm 등 몇 가지 리더 선출 알고리즘들이 있다. 알고리즘들의 컨셉은 단순하지만 실제 분산환경에서 안전하게 써먹을 수준으로 구현하려면 상당히 머리가 아플 것이다. 그냥 주키퍼를 이용해서 구현하면 된다.

주키퍼는 분산 잠금을 이용한 Sequence타입의 노드를 지원한다. Sequence 타입의 노드는 계속 증가하는 일련번호를 노드이름에 할당한다. 예를 들어서 NodeA, NodeB, NodeC 3개의 노드를 등록했다면 각 노드 이름뒤에 NodeA0000001, NodeA0000002, NodeC000003과 같은 번호가 붙는다. 이 번호는 항상증가하며 주키퍼 quroum 내에서 유일하다는 것을 보장한다. 따라서 노드들 중에서 번호가 가장 낮은(가장 오래된) 노드를 리더로 선출하면 된다. 알고리즘은 단순하다. 아래는 의사코드다.
func Watcher() {
    myid := CreateNodeInZookeeper(SequenceType)
    for {
        WaitWatchKernelGroup(kernelNode)
        LeaderElect("/kernel", myid)
    }
}
func LeaderElect(kernelNode string,myid int) {
    ids := ReadKernelGroupChild(kernelNode)
    ids.Sort()
    if myid == ids[0] {
        "Im Leader"
    } else {
        "Im Follower. Leader is ids[0]"
    }
}
  1. 노드를 SequenceType으로 등록한다. 등록하면 일련번호가 할당되는데, 이 번호를 myid로 저장한다.
  2. 커널노드를 watch하면서, 새로운 노드의 추가 혹은 삭제가 있는지를 모니터링 한다.
  3. 만약 Watch가 되면, LeaderElect 함수를 실행한다.
  4. 커널노드의 자식(child)노드를 모두 읽는다.
  5. 자식노드들은 sequence 번호를 가지고 있는데, 이 번호를 정렬한다.
  6. 만약 myid가 가장 낮은 sequence 번호라면 내가 리더가 된다.
  7. 그렇지 않다면 Follower가 된다.

스케쥴러

Auto Scaling

Fault tolereance