zookeeper

분류없음 2017.06.30 09:30 posted by dev.bistro


* 주키퍼의 Origin
 – Yahoo 에서 개발
 – Pig 처럼 많인 프로젝트가 동물 이름이었고, 이러한 시스템들은 동물원의 동물과 같다고 느낌 -> 사육사(Zookeeper)

* 주키퍼가 사용된 예
 – HBase : 클러스터 마스터 선출과 가용 서버들의 목록을 저장 / 클러스터 메타데이터 관리
 – Kafka : 장애 감지/ 토픽 발견/ 토픽 생성 소모 상태를 관리
 – Solr : 솔라클라우드에서 클러스터의 메타데이터 저장, 업데이트 관리
 – Facebook message : 샤딩/ 장애복구/ 서비스발견을 관리
– Druid :  내부 통신에 이용

* 주키퍼 모드
 – Standalone : 단독 서버, 복제 안됨
 – quorum(쿼럼)

* Znode
 – 용량제한 1MB
 – ACL(접근권한관리)를 할 수 있다
 – 주키퍼는 모든 데이터를 메모리에서 관리하기 때문에 Znode역시 메모리에 올라간다
 – child 또는 바이트 배열의 데이터를 저장한다

* Znode Mode
 – Persistent Node : 명시적인 삭제 명령(delete)이 있기 전까지 계속 유지되는 Node
 – Ephemeral Node : Node를 생성한 ‘세션’ 이 유효한 동안에만 유지되는 Node. Ephemeral 는 child znode를 가질수 없다.
 – Sequence Node : (위의 2개의 노드는 각각 이 타입을 사용 할 수 있다)
                   생성지 Sequence가 자동으로 붙는 Node (ex task-00000001) 유일한 이름을 보장 / 생성 순서 확인 가능

* Watch
 – 1회성 작업이다. 계속 노티를 받으려면 클라이언트에서 매번 새로운 watch를 설정해야한다.
   : so, 알림을 받고 새로운 watch를 등록하려는 순간에 새로운 변경사항이 발생 할 수 있다.
         이 다음 새로 watch를 등록하면서 값을 읽기 때문에 놓치지는 않는다.
 – 클라이언트가 감시하는 znode의 변경 사항의 ‘순서’를 보장해준다
 – 데이터 변경/ Child변경 등에 따라 다른 종류의 알림을 생성한다.

* 쿼럼의구성
 – 1. server.1=127.0.0.1:2222:2223
   server.n각 항목은 서버 n이 사용하는 주소, 포트를 지정한다.3개의 필드
   첫번째 필드는 서버 주소, 2,3번째 필드는 쿼럼 통신, 리더 선출에 사용하는 TCP포트이다.
 – 서버가 시작할때 주키퍼는 data 디렉토리의 myid 파일에 있는 내용을 읽어서 자신의 ID를 인식한다



[기본적인 설정]

* clientPort
– default 2181, 클라이언트가 서버로 연결하기 위해 사용하는 TCP port
– clientPort보다 clientPortAddress 가 우선한다.
* dataDir
– 만약 앙상블이라면 여기에 id 파일이 존재하게 된다 (name:myid)
QuorumPeerConfig 에서 File myIdFile = new File(dataDir, “myid”) 확인할 수 있다.
– 스냅샷(데이터 트리의 복사본)이 완료될때 까지 디스크와 동기화 되지 않는다.

* dataLogDir
– default dataDir 값을 사용
– 트랜잭션 로그를 쓰기 때문에 많이 사용된다.

* tickTime
– default 3000, tick은 주키퍼가 사용하는 ‘시간의 기본 단위’
– 가장 짧은 클라이언트 세션 타임아웃 = 2 tick
* snapCount
– default 100000, 스냅샷들 사이에 트랜잭션 개수(zookeeper.snapCount)
– 주키퍼 재시작 -> 스냅샷을 읽는다 -> 스냅샷 이후 트랜잭션을 적용한다

* fsync.warningthresholdms
– default 1000 저장소 동기화 시간이 이 보다 길면 경고 발생한다. (FileTxtLog 의 commit() 참고 )

* globalOutstandingLimit
– default 1000 수정할 일은 ‘거의’ 없을 것이다.
– 주키퍼 서버가 요청을 처리하는 것보다 클라이언트들은 request를 더 할수 있는데 globalOutstandingLimit 에 근접하면 요청을 안받음
– NettyServerCnxn.disableRecvNoWait 을 보면 ‘Throttling – disabling recv…’ 로그를 생성하는걸 볼 수 있다.(여기 맞나?)

* autopurge.snapRetainCount
– 데이터를 제거할 때 유지해야하는 스냅샷의 갯수와 트랜잭션 로그 갯수
– 주키퍼는 주기적으로 GC가 일어난다. 이 때 유지해야하는 스냅샷의 갯수를 말한다. 기본은 3

* autopurge.purgeInterval
– GC(퍼징)이 발생하는 시간의 간격. 0이 아닌 숫자로 설정하면 GC의 주기를 뜻한다.
– 0 이면 GC는 자동적으로 수행되는 않고, zkCleanup.sh을 통해 수동으로 실행 가능

[클러스터 설정]
ㅁ 앙상블에 속하는 모든 주키퍼 서버들은 동일한 변수.값을 가지고 있어야 한다.

* initLimit
– default 환경에 따라 다 달라서 기본값이 없다
– 팔로워가 리더와 초기에 연결하는 시간에 대한 타임아웃, 틱 갯수
– 팔로워가 훨씬 뒤쳐진 경우 처음 연결할때 많은 양의 데이터 전송이 발생할 수 있다. (이땐 좀 늘여야한다)
– ex) 데이터 양의 크거나, 네트워크 속도가 느릴 경우
* syncLimit
– default 기본값 없고, 바드시 설정해야하는 값이다.
– 팔로워가 리더와 동기화 하는데에 대한 타임아웃 틱갯수로 설정
– 이 틱 시간 안에 팔로워가 리더와 동기화가 되지 않는다면 제거된다.
– 데이터의 양은 상관없다. 네트워크 속도 & 처리량에 따라 설정해야한다.
* leaderServers
– default yes
– 리더가 클라에게 서비스를 할것인가?
* server.x=[hostname]:n:n[:observer]
– x : 서버의 ID (data/myId 파일 내용에서 이 x를 읽고 server.x를 찾아 적용한다)
– n : 첫번째 : 트랜잭션 송신, 두번째 : 리더선출 (일반적으로 2888:3888)
– observer : 있으면 해당 서버는 옵저버를 나타낸다.
* electionAlg
– 리더 선출 알고리즘. 이지만 3.4.0 이후로 1개만 남는다
– QuorumPeer.createElectionAlgorithm()를 확인 ( code : new FastLeaderElection(this, qcm) )
– 참고doc : https://zookeeper.apache.org/doc/r3.4.8/zookeeperAdmin.html
[로깅]
ㅁ SLF4J 와 Log4j를 사용한다. log4j.properties를 classpath에 포함시키면 된다.

[동적 설정 변경 or 무중단 설정 변경]
ㅁ 이 기능은 trunk 에만 존재하며 3.5.0알파 이후에 추가되었다.
ㅁ 이전버전에서 가장 안전한 방법은 ‘한번에 하나의 변경 사항만 만들고 매 변경 사항마다 앙상블을 올렸다가(리더 설정까지) 내리는 것’
ㅁ dynamicConfigFile 파라미터

[클라이언트의 연결 문자열 관리]
ㅁ host:port,host:port,host:port 의 사용법은 제한적이다. 추가/제거가 어렵다.
ㅁ DNS 리졸브.. (하지만 쓸일 없을듯)
[트랜잭션, 스냅샷 로그, 에퍽 파일 보기]
ㅁ 트랜잭션로그 보기 : java -cp zookeeper-3.4.8.jar:lib/log4j-1.2.16.jar:lib/slf4j-log4j12-1.6.1.jar:lib/slf4j-api-1.6.1.jar org.apache.zookeeper.server.LogFormatter z1/data/version-2/log.300000001
—-
ZooKeeper Transactional Log File with dbid 0 txnlog format version 2
16. 8. 8 오후 6시 13분 12초 session 0x356696bfcf20000 cxid 0x0 zxid 0x300000001 closeSession null
16. 8. 8 오후 6시 13분 12초 session 0x256696d24480000 cxid 0x0 zxid 0x300000002 createSession 15000
—-

ㅁ 스냅샷로그 보기 : java -cp zookeeper-3.4.8.jar:lib/log4j-1.2.16.jar:lib/slf4j-log4j12-1.6.1.jar:lib/slf4j-api-1.6.1.jar org.apache.zookeeper.server.SnapshotFormatter z1/data/version-2/snapshot.300000000
—-
/assign/worker1.example.com/task-00000000
cZxid = 0x00000100000017
ctime = Mon Aug 08 17:19:04 KST 2016
mZxid = 0x00000100000017
mtime = Mon Aug 08 17:19:04 KST 2016
pZxid = 0x00000100000017
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x00000000000000
dataLength = 0
—-
스냅샷로그에는 데이터와 ACL은 출력되지 않는다. 그래서 어떤 시점의 무슨일이 일어났는지를 보려면 2개 다 확인해야 한다.

ㅁ epoch file : acceptedEpoch, currentEpoch 파일은 주키퍼가 보고, 참여하는 에퍽 번호를 반영. 데이터의 일관성을 위해 반드시 필요한 파일( 즉 백업할때 데이터와 함께 해야한다)

[시스템의 캡처]
앙살블의 트랜잭션 로그, 스냅샷 파일을 랩탑의 주키퍼에 복사하면 동일한 서버 상태를 재현 할 수 있다.
이 것은 파일의 복사만으로 쉽게 백업할 수 있다는걸 뜻한다. 앙상블중 1대만 복사하면된다(주키퍼는 복제 서비스이다)

[포 레터 단어 for letter word]
ㅁ 원래 의미 4글자로 구성된 비속어를 뜻한다.
ㅁ 주요 목적은 telnet/nc 같은 간단한 툴로 시스템의 상태를 쉽게 체크할 수 있는 방법을 제공하는 것이다. 그래서 output은 사람이 읽을수 있는 형태이다.
ㅁ ruok, stat, srvr, dump 등등
ㅁ 하지만 주키퍼는 기본적으로 Dcom.sun.management.jmxremote 옵션이 있으므로 jconsole등으로 jmx를 보는게 더 유용하다.

스크린샷 2016-08-13 오후 12.19.32


ps. 1년전 정리한글 옮겨옴

신고
TAG zookeeper

SCALA TYPE ERASURE & TYPETAG

language/scala 2017.06.30 09:28 posted by dev.bistro

다른  JVM 언어처럼 Scala  역시  컴파일시점에 type 정보를 잃어버린다.

SCALA는 JVM의 type erasure issue 를  TypeTag(이전에는 Manifest)로 해결 할 수 있다

// TODO undeprecated until Scala reflection becomes non-experimental
// @deprecated("Use `scala.reflect.ClassTag` (to capture erasures) or scala.reflect.runtime.universe.TypeTag (to capture types) or both instead", "2.10.0")
type Manifest[T]      = scala.reflect.Manifest[T]
scala> def evenElems[T : ClassTag](xs: Vector[T]): Array[T] = {
| val arr = new Array[T]((xs.length + 1) / 2)
| for (i <- 0 until xs.length by 2)
| arr(i / 2) = xs(i)
| arr
| }
evenElems: [T](xs: Vector[T])(implicit evidence$1: scala.reflect.ClassTag[T])Array[T]

scala>

 

 

 

ClassTag는 최상위의 Class의 Type정보만을 생성해준다.
ex) ClassTag[List[String]] -> collection.immutable.List

실제로 Intellij에서 Debugging 화면에서 보면 implicit evidence 를 볼 수 있다

스크린샷 2016-06-19 오후 4.07.52

스크린샷 2016-06-19 오후 3.37.56



신고

'language > scala' 카테고리의 다른 글

SCALA TYPE ERASURE & TYPETAG  (0) 2017.06.30
SCALA UPPER/LOWER TYPE BOUND & VIEW BOUND  (0) 2017.06.28
Superseded by Akka HTTP  (0) 2017.05.01
FP 비엄격성  (1) 2015.05.18
scala package object  (0) 2014.11.05
scala의 lazy 비용  (0) 2014.10.21

SCALA UPPER/LOWER TYPE BOUND & VIEW BOUND

language/scala 2017.06.28 13:58 posted by dev.bistro

하나 이상의 타입인자가 있는 클래스는 ‘제네릭 클래스’이고  타입인자를 실제 타입으로 대체하면 일반 클래스이다.

1
2
3
4
class Pair[T,S](val first:T, val second:S) //제네릭 클래스
 
val p1 = new Pair(42, "String") //추론에 의해서 일반 클래스
val p2 = new Pair[Int, String](42, "String") //명시적 선언에 의해서 일반 클래스

 

함수,  메소드도 타입인자를 가질 수 있다.

1
2
3
4
5
def getMiddle[T](a: Array[T]) = a(a.length) / 2
 
ex)
getMiddle(Array("Mary", "had")) //추론의 의해서 getMiddle 호출
val f = getMiddle[String] _ //타입인자를 명시적으로 지정함

 

타입에 제한(bound)를 걸어야 할 필요가 있다. 다음의 예로 쉽게 이해 가능하다

1
2
3
4
5
6
7
8
9
10
11
class Pair[T](val first:T, val second:S) {
def smaller = if (first.compareTo(second) < 0 ) <<--여기
}
/* first가 compareTo를 가지고 있는지 확인 할 수 없기 때문에 오류가 발생한다.
이를 해결하기 위해서는 first가 'compareTo'를 항상 가지고 있으면 될 것이다. 아래처럼 */
 
class Pair[T <: Comparable[T]](val first: T, val second: T) {
def smaller = if (first.compareTo(second) < 0 )
}
/* 처럼 'T가 반드시 Comparable[T]의 sub-type'임을 지정하면 된다.
=> 그리고 'T의 상위 타입을 지정했거나, upper bound 지정,제약했다' 라고 표현 가능 */

 

그와 비슷하게 lower bound를 선언할 수도 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Queue[+T] (private val leading: List[T], val trail: List[T] ) {
def enqueue[U >: T] (x: U) = new Queue[U](leading, x :: trail)
}
// U >: T 를 이용해 T 를 U 의 하위 바운드로 지정했으니 U가 T의 슈퍼클래스여야 한다.
 
ex1)
/* Fruit 클래스에 2개의 서브 클래스 Apple, Orange가 있다.
Queue[Apple]에 Oragne를 추가할 수 있고 결과는 Queue[Fruit]가 된다. */
 
ex2)
class Animal
class Bird extends Animal
class Chicken extends Bird
 
val flock = List(new Bird, new Bird)
flock: List[Bird] = List(Bird@7e1ec70e, Bird@169ea8d2)
 
new Chicken :: flock
res53: List[Bird] = List(Chicken@56fbda05, Bird@7e1ec70e, Bird@169ea8d2)
 
// 처럼 공통적인 각기 다른 타입을 하나로 분류할 수 있는 이점이 생긴다.

 

upper , lower bound와 같은 상하위가 아니라 implicit의 암묵적 변환에도 그대로 사용하고 싶을 경우에는 <% 를 사용한다.

1
2
3
4
5
6
7
8
9
10
11
class Pair[T <: Comparable[T] ](val first:T, val second:T)
val p = new Pair(4,2)
 
output> Error:(6, 9) inferred type arguments [Int] do not conform to class Pair's type parameter bounds [T <: Comparable[T]]
// 4, 2같은 Int는 Comparable를 구현하지 않기 때문이다 하지만 RichInt에는 있다.
 
class Pair[T <% Comparable[T] ](val first:T, val second:T)
/* 처럼 수정하면 된다. 이를 다시 풀어보면
a. T가 Comparable[T]로 암묵적 변환이 가능하다 라는 의미이다.
b. T를 Comparable[T]로 다룰수 있는 모든 T type을 사용 할 수 있다.
c. class Pair[T ](..)(implicit imp: T => Comparable[T]) 의 축약형이다.


신고

'language > scala' 카테고리의 다른 글

SCALA TYPE ERASURE & TYPETAG  (0) 2017.06.30
SCALA UPPER/LOWER TYPE BOUND & VIEW BOUND  (0) 2017.06.28
Superseded by Akka HTTP  (0) 2017.05.01
FP 비엄격성  (1) 2015.05.18
scala package object  (0) 2014.11.05
scala의 lazy 비용  (0) 2014.10.21


티스토리 툴바