'OpenSource'에 해당되는 글 17건
- [번역] Redis Sentinel Documentation 2013.04.09
- HBase에서 사용하는 hash function 2012.10.05
- lucene & nutch 2012.09.16
- Java SE 7 Features and Enhancements 2011.08.05
- zookeeper inside 2011.04.20
- [Hadoop] Secondary name-node, Checkpoint node, Backup node 2011.04.06
- Thrift 소개 2010.11.12
- boost 설치하기 2010.09.13
- activemq-cpp 설치하기 2010.09.13
- ActiveMQ 메모 2010.09.10
[번역] Redis Sentinel Documentation[번역] Redis Sentinel Documentation
Posted at 2013. 4. 9. 16:43 | Posted in OpenSourceRedis HA 구성을 위해 Sentinel을 사용해보기로 했다.
제대로 알고 진행하도록 문서를 번역해봤다.
※ 잘못 번역된 부분은 댓글로 알려주세요.
<정리>
- 2013.04.28 현재 Redis stable 버전은 2.6.12임. |
- Monitoring: redis master, slave가 제대로 동작하는지 항상 검사한다.
- Notification: sentinel은 뭔가 잘못된 Redis 인스턴스의 상태를 API를 통해 시스템 운영자나 다른 컴퓨터 프로그램에 알릴 수 있다.
- Automatic failover: 마스터가 예상대로 동작하지 않으면, sentinel은 slave 하나를 master로 승격시키는 failover process를 시작할 수 있다. 다른 남은 slave들은 새로운 master에 붙도록 reconfigured되고, Redis를 사용하는 어플리케이션들은 접속시(Sentinel에게 접속시?) 새로운 주소를 통지 받는다.
redis-sentinel /path/to/sentinel.conf
redis-server /path/to/sentinel.conf --sentinel
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 60000
sentinel failover-timeout mymaster 900000
sentinel can-failover mymaster yes
sentinel parallel-syncs mymaster 1
sentinel monitor resque 192.168.1.3 6380 4
sentinel down-after-milliseconds resque 10000
sentinel failover-timeout resque 900000
sentinel can-failover resque yes
sentinel parallel-syncs resque 5
sentinel <option_name> <master_name> <option_value>
- down-after-millisecons 는 sentinel이 master가 다운됐다고 판단하는 millisecond 시간값이다(다운됐다는 것은 PING 명령에 대한 응답이 없거나, 응답에 에러가 있는 경우이다). 이 시간이 지난 후 sentinel은 주관적 다운(subjectivel down(SDOWN))상태로 만들며, 이 상태는 자동 failover를 시작하기에는 불충분한 상태이다. 그러나 sentinel들이 충분히 SDOWN 상태로 인지하면(역주: 첫째줄 설정에서 2 만큼의 Sentinel들이 SDOWN을 인지하면), 해당 master는 객관적 다운(objectively down(ODOWN)) 상태가 된다. 이 sentinel수는 master에 대해 설정된 sentinel 합의 수에 의존한다.
- can-failover 는 이 sentinel이 ODOWN이 감지되었을 때 failover를 할 수 있는지를 말한다. 필요하다면 모든 sentinel들에 대해서 failover를 수행하도록 구성할 수 있다. 또는, 몇 개의 sentinel만 합의할 수 있게 하고 failover 수행에 참여할 sentinel은 좀 더 둘 수도 있다.
- parallel-syncs 은 failover된 후 동시에 새 master를 사용하도록 재설정될(역주: recongiured라고 돼 있으나, resync가 문맥상 맞는 듯) 수 있는 slave수를 지정한다. 이 수치가 낮으면, failover 절차를 완료하는데 더 많은 시간이 걸릴 것이다. 그러나 slave들이 old data를 제공하도록 설정돼 있다면, 모든 slave들이 새 master로부터 동시에 resync 받기를 원치 않을 수도 있다. 복제(replication/resync) 절차가 slave에게 non-blocking이라고 할지라도, master로부터 resync하는 동안 bulk data를 요청하는 것이 redis(master)를 멈추게 하는 순간이 있다. 한번에 한 slave가 not reachable이 되는지 이 옵션을 1로 설정해서 확인할 수 있다.
- +PONG 으로 응답을 받은 경우
- -LOADING 에러로 응답을 받은 경우
- -MASTERDOWN 에러로 응답을 받은 경우
down-after-milliseconds
초 이내에 못받았다면, 그 인스턴스는 SDOWN상태가 된다. 유효한 PING 응답은 +PONG, -LOADING, -MASTERDOWN 이다.(sentinel port=22001) redis 127.0.0.1:22001> info # Server redis_version:2.6.10 redis_git_sha1:00000000 redis_git_dirty:0 redis_mode:sentinel os:Linux 2.6.18-308.11.1.el5xen x86_64 arch_bits:64 multiplexing_api:epoll gcc_version:4.1.2 process_id:21513 run_id:8c1735bdd62a2cfdc9ffc20f742470995a913b2c tcp_port:22001 (master port=21001) redis 127.0.0.1:21001> subscribe __sentinel__:hello Reading messages... (press Ctrl-C to quit) 1) "subscribe" 2) "__sentinel__:hello" 3) (integer) 1 1) "message" 2) "__sentinel__:hello" 3) "10.101.58.67:22001:b7c8f61ff3d1963c7bd14b018c3dd86364885406:1" 1) "message" 2) "__sentinel__:hello" 3) "10.101.56.87:22001:8c1735bdd62a2cfdc9ffc20f742470995a913b2c:1" sentinel(22001)이 master(21001)을 감시하도록 한 후, master(21001)에 접속하여 'subscribe __sentinel__:hello' 를 치면, sentinel들이 보내오는 메시지를 볼 수 있다. |
- PING: 단순하게 PONG을 반환한다.
- SENTINEL masters: 모니터링하고 있는 master의 리스트와 그것들의 상태를 보여준다.
- SENTINEL slaves
<master name>
: master의 slave들의 리스트와 그것들의 상태를 보여준다. - SENTINEL is-master-down-by-addr
<ip> <port>
: 두개의 multi bulk reply를 반환한다. 첫번째는 0 또는 1이다(ip:port가 master의 주소가 맞고 SDOWN상태이면 0, 그 외는 1). 두번째는 이 master의 주관적 리더(subjective leader)이다. 이것은 조회된 master에 대해 failover를 수행해야 하는 sentinel 인스턴스의 runid이다. ( The second element of the reply is the subjective leader for this master, that is, therunid
of the Redis Sentinel instance that should perform the failover accordingly to the queried instance.) - SENTINEL get-master-addr-by-name
<master name>
: master name에 해당하는 ip와 port를 반환한다. 만약 failover가 진행중이거나 성공적으로 완료됐으면, promote 된 slave의 ip와 port가 반환된다. - SENTINEL reset
<pattern>
: 이 명령은 모든 매칭되는 이름의 master들을 reset한다. 패턴 인자는 glob-style 패턴이다. reset 프로세스는 master의 모든 이전 상태(failover in progress 상태를 포함하여)를 clear시키고, 해당 master와 통신하여 얻은 모든 slave와 sentinel 정보를 삭제한다.( The reset process clears any previous state in a master (including a failover in progress), and removes every slave and sentinel already discovered and associated with the master.) (역주: 어떤 상황이 되는지 테스트 해보자)
<instance-type> <name> <ip> <port> @ <master-name> <master-ip> <master-port>
- +reset-master <instance details> -- master가 reset 됐다.
- +slave <instance details> -- 새로운 slave가 감지됐고, 추가(attached)됐다.
- +failover-state-reconf-slaves <instance details> -- failover 상태가 reconf-slaves 상태로 변경됐다.
- +failover-detected <instance details> -- 다른 Sentinel에 의해 failover 상태가 시작됐거나, 외부의 다른 entity(slave가 master로 변경됨)가 감지되었다.(역주: entity는 관리대상 또는 master/slave shard 한 셋트를 의미)
- +slave-reconf-sent <instance details> -- 리더 Sentinel이 새 slave를 재설정(reconfigure)하기 위해 SLAVEOF 명령을 이 인스턴스에게 보냈다.
- +slave-reconf-inprog <instance details> -- 재설정되고 있는 slave가 새 master의 slave가 되고 있음을 보여준다. 그러나 동기화 작업은 아직 완료되지 않았다.
- +slave-reconf-done <instance details> -- slave가 새 master와 동기화 되었다.
- -dup-sentinel <instance details> -- 파라미터로 받은 master를 감시하는 하나 또는 그 이상의 sentinel이 중복되어 제거되었다.(이 이벤트는 Sentinel 중 하나가 재시작 되었을 때 발생한다.)
- +sentinel <instance details> -- 이 master를 위한 새로운 Sentinel이 감지되었고 추가되었다.
- +sdown <instance details> -- 인스턴스가 SDOWN 상태가 되었다.
- -sdown <instance details> -- 인스턴스는 이제 SDOWN 상태가 아니다.(역주: SDOWN 해제)
- +odown <instance details> -- 인스턴스가 ODOWN 상태가 되었다.
- -odown <instance details> -- 인스턴스는 이제 ODOWN 상태가 아니다.(역주: ODOWN 해제)
- +failover-takedown <instance details> -- 설정된 failover-timeout 시간의 25%가 지났다. 그러나 이 Sentinel은 진행 상태는 볼 수 없고 새 리더가 된다(역주:이 이벤트가 뜨는 Sentinel이 리더란 의미인 듯). 남은 slave들이 새 master로부터 복제되도록 새 리더로써 행동을 시작한다.
- +failover-triggered <instance details> -- 리더 Sentinel로써 failover를 시작하고 있다. (역주: 리더 Sentinel에만 이 이벤트가 발생한다.)
- +failover-state-wait-start <instance details> -- failover 상태가 "wait-start" 이다: failover를 시작하기 전에 { fixed seconds + random seconds } 동안 기다린다.
- +failover-state-select-slave <instance details> -- failover 상태가 "select-slave" 이다: promote할 적절한 slave를 찾고 있다.
- +no-good-slave <instance details> -- promote할 적절한 slave가 없다. 이 상태에서 얼마 후 재시도 하겠지만, 아마도 failover는 정지될 것이다.
- +selected-slave <instance details> -- promote시킬 적절한 slave를 찾았다.
- +failover-state-send-slaveof-noone <instance details> -- master로 promote될 slave를 재설정하고 있고, 변경되기를 기다리고 있다. (역주: master로 만들 slave에 "slaveof nonone" 명령을 보내 role이 master가 되도록 한다.)
- +failover-end-for-timeout <instance details> -- failover가 timeout으로 종료되었다. 만약 리더 Sentinel에서 발생했으면, 아직 재설정되지 않은 나머지 slave들에게 최선의 방법으로 SLAVEOF를 보낸다(보냈다).
- +failover-end <instance details> -- failover가 성공적으로 끝났다. 모든 slave들이 새 master에 붙었으며 복제되도록 설정되었음을 나타낸다. (역주: 복제는 master-slave간에 진행중이며, 별도 프로세스가 fork되어 진행된다.)
- +switch-master <master name> <oldIp> <oldPort> <newIp> <newPort> -- 예전과 같은 이름으로 새 master의 모니터링을 시작한다. old master는 관리 테이블에서 완전히 삭제될 것이다.
- +failover-abort-x-sdown <instance details> -- promote될 slave가 extended SDOWN 상태가 되어 failover는 중지(undoed/aborted)되었다.
- -slave-reconf-undo <instance details> -- failover가 중지(aborted)되었고, 그래서 파라미터로 받은 인스턴스에게 원래 master를 바라보도록 SLAVEOF 명령을 보냈다.
- +tilt -- tilt 모드로 들어갔다.
- -tilt -- tilt 모드에서 나왔다.
- master가 ODOWN 상태가 되는 것을 인지.
- 어떤 Sentinel이 failover를 시작시킬지 알게된다. 이 Sentinel을 리더(Leader)라고 부르며 다른 Sentinel들은 옵저버(Observer)가 된다.
- 리더는 master로 promote시킬 slave를 선택한다.
- promote될 slave는 SLAVEOF NO ONE 명령으로 master가 된다.
- 옵저버들은 한 slave가 master로 바뀌는 것을 보게되고, failover가 시작되는 것을 알게 된다. Note: 이것은 옵저버들에 의해 모니터링 되는 master의 slave 중 하나가 master가 된다는 것을 failover 과정이 시작됨으로써 알게 된다.
- 원래 master에 붙어 있던 다른 모든 slave들은 새로운 master로부터 복제되도록 SLAVEOF 명령으로 재설정된다.
- 모든 slave들이 재설정되면 리더는 failover 과정을 끝낸다. 관리 테이블에서 old master를 제거하고 new master를 추가한다. 이 때 원래 master의 이름을 사용한다. (역주: master name은 변경되지 않고 master 정보(주소)만 바뀜을 의미)
- 모든 slave들이 재설정되면 옵저버들은 failover가 끝났음을 감지한다. 리더가 했던 것과 동일하게 관리 테이블에서 old master를 제거하고 new master를 감시하기 시작한다.
- failover를 할 수 없도록 설정된 Sentinel들은 제외한다.(이 정보는 Hello 채널을 통해서 모든 Sentinel들에게 전파된다.)
- SDOWN 상태인 Sentinel, 또는 SENTINEL_INFO_VALIDITY_TIME 밀리초(5초) 내에 ping 응답을 받지 못한 Sentinel들은 제외한다.
- 남은 Sentinel들 중에서, 사전순서상(lexicographically) runid가 가장 낮은 것을 선택한다.(모든 Redis 인스턴스는 runid를 가지며, 모든 실행의 식별자로 사용된다.)
- 자기가 주관적 리더(Subjective Leader)인지 확인한다.
- 다른 Sentinel들로부터 리더가 맞는지에 대한 동의(acknowledges)를 받는다: 적어도 51%의 Sentinel들이 SENTINEL is-master-down-by-addr 의 응답으로 리더에 동의한다는 정보를 줄 수 있었고, failover를 하려고 하는 master에 설정된 정족수(quorum)에 만족해야 한다. (역주: sentinel.conf에 설정된 각 master(redis shard 또는 cluster)의 odown감지 정족수를 의미하며, SENTINEL is-master-down-by-addr는 sentinel간에 주고 받는 명령이다.)
- promote된 slave가 SDOWN 상태가 아니다.
- 한 slave가 새로운 master로 승격(promoted)되었다.
- 다른 모든 slave가 새 master를 바라보도록 설정 되었다.
- promote된 slave는 SDOWN 상태가 아니다.
- 한 slave가 새로운 master로 승격(promoted)되었다.
- 마지막 과정 이후로 적어도 failover-timeout 밀리초가 지났다.
failover-timeout
configuration option.)- 리더 Sentinel 또는 옵저버의 관점에서 failover가 시작된 이후에 old master는 new master의 slave 목록에 추가된다. 이 때 특수한 DEMOTE 플래그라는 것을 달고 추가된다(이 것은 SENTINEL SLAVES 명령의 결과로 확인할 수 있다).
- old master가 되살아났고 다시 접속할 수 있을 때, 이 old master가 자신이 master라고 알려오면(INFO의 결과로 안다), Sentinel은 재설정 하기 위해 SLAVEOF 명령을 보낸다. 이 인스턴스가 slave라고 다시 알려오면 DEMOTE 플래그는 클리어시킨다.
(역주: Redis instance를 시작시키면 stand-alone master 롤로 뜨는데, 이 경우 Sentinel이 DEMOTE 플래그를 달고 관리 목록에 넣어뒀다가 다시 해당 인스턴스가 접속하면 재설정한다는 이야기인데, DEMOTE 플래그가 꺼진 상황에서 다시 재시작되면 또 다시 stand-alone master로 뜨게 된다. 이 때 Sentinel이 재시작하게 되면 대형 장애로 이어질 수 있다. sentinel.conf 에는 old master가 master로 설정돼 있기 때문이다. 이 경우 sentinel을 여러개 운영해서 sentinel이 재시작할 때 다른 sentinel의 상태를 conf파일로 덤프 받아 시작하는 방법이 안전하다, 또는 sentinel network에 처음 추가된 경우 sentinel.conf가 아니라 network에서 redis 인스턴스 정보를 받아오도록 보완되어야 할 것으로 보인다.)
- TODO: SENTINEL FAILOVER 로 failover 수동 시작.
- TODO: SENTINEL PAUSE, RESUME으로 Sentinel 일시정지, 재시작 시키기.
- TODO: Sentinel은 자동 failback은 수행하지 않는다.
- TODO: failback을 위한 단계를 문서화하기.
- 모든 행동을 멈춘다.
- SENTINEL ismaster-down-by-addr 요청에 대해 부적격(negatively) 응답을 보내 사용할 수 없는 상태임을 알린다.
HBase에서 사용하는 hash functionHBase에서 사용하는 hash function
Posted at 2012. 10. 5. 23:22 | Posted in OpenSource/** * This utility method converts String representation of hash function name * to a symbolic constant. Currently two function types are supported, * "jenkins" and "murmur". * @param name hash function name * @return one of the predefined constants */ public static int parseHashType(String name) { if ("jenkins".equalsIgnoreCase(name)) { return JENKINS_HASH; } else if ("murmur".equalsIgnoreCase(name)) { return MURMUR_HASH; } else { return INVALID_HASH; } }
lucene & nutchlucene & nutch
Posted at 2012. 9. 16. 13:55 | Posted in OpenSourcelucene (검색엔진)
Apache Lucene(TM) is a high-performance, full-featured text search engine library written entirely in Java.
http://lucene.egloos.com/1386072
http://www.ibm.com/developerworks/kr/library/tutorial/os-apachelucene/section2.html
nutch (크롤링)
Apache Nutch is an open source web-search software project.
http://www.joinc.co.kr/modules/moniwiki/wiki.php/Site/Search/Document/nutch/Crawling
Java SE 7 Features and EnhancementsJava SE 7 Features and Enhancements
Posted at 2011. 8. 5. 10:37 | Posted in OpenSourcezookeeper insidezookeeper inside
Posted at 2011. 4. 20. 10:12 | Posted in OpenSource-> zoo_wget(): sync_completion을 사용해서 blocking 모드로 결과 반환.
-> zoo_awget()
-> wait_sync_completion
(1) (ref_counter == 0)
-> destroy()
-> cleanup_bufs()
-> free_completions()
-> notify_sync_completion() -> broadcast to all waiting sync_completion thread
-> cleanup_bufs() -> free_completions() -> ...
-> adaptor_finish()
-> pthread_join(io), pthread_join(completion)
-> api_epilog() -> ref_counter - 1
-> zookeeper_close()
-> (1)
async류 함수(zoo_awget)를 호출하더라도 zookeeper_close()를 호출하면 모두 정리하고 나간다.
zookeeper_close() ==> zookeeper join 이라고 봐도 되겠다.
[Hadoop] Secondary name-node, Checkpoint node, Backup node[Hadoop] Secondary name-node, Checkpoint node, Backup node
Posted at 2011. 4. 6. 10:14 | Posted in OpenSourceSecondary NameNode는 이름으로 추측할때 Standby-NameNode로 보이는 문제로 인해 Checkpoint Node 또는 Backup Node로 이름이 변경된 것 같습니다.
(하둡 wiki에서 다음과 같이 말하고 있습니다.
http://hadoop.apache.org/hdfs/docs/current/hdfs_user_guide.html#Secondary+NameNode
- Checkpoint: 네임스페이스는 네임노드의 메모리 및 디스크에 그 이미지가 저장되는데 이 이미지를 FsImage라고 부릅니다.
네임노드에서 디스크의 FsImage는 변경되지 않으며, 운영하는 동안 변경된 네임스페이스 정보는 edits log에 기록이 됩니다.
이 FsImage가 변경되는 시점은 네임노드가 시작할 때 뿐이며, 네임노드가 시작될 때 edits log를 디스크의 FsImage에 병합하고 이 이미지를 메모리에 올리게 됩니다. 이런 과정을 checkpoint라고 합니다.
- Checkpoint Node(또는 Backup Node, Secondary NameNode):
따라서, 네임노드의 FsImage는 네임노드가 시작될 때만 editLog를 머지하고 새롭게 생성되므로, edits log를 주기적으로 FsImage에 병합해주는 것을 자동으로 해주는 것이 필요했고 그것이 Checkpoint Node라고 보시면 됩니다.
즉, Checkpoint Node(Secondary NameNode)는 주기적으로 네임노드의 FsImage와 edits log를 다운로드 받아 이들을 병합(join)하고, 새롭게 만들어진 FsImage를 네임노드에 돌려(upload)줍니다.
Checkpoint Node(Secondary NameNode)는 네임노드가 죽었을 때 백업용이 아니라 FsImage를 주기적으로 갱신(checkpoint)시켜주는 역할만 합니다.
이런 역할을 하는 노드가 필요한 이유는 네임스페이스에 많은 변경이 발생한 경우 edits log가 엄청나게 쌓일 것이고, 네임노드를 재시작 시켜주지 않는 한(checkpoint가 일어나지 않는 한) edits log는 삭제되지 않고, 삭제되어서도 안됩니다.
이 edits log가 많이 쌓이면 네임노드 시작시 시간이 엄청나게 길어지고 메모리도 실제 이미지보다 많이 필요하게 되어 네임노드가 시작되지 않는 문제 등을 유발하게 됩니다. 따라서 Checkpoint Node가 주기적으로 edits log를 FsImage에 병합시켜서 네임노드의 FsImage를 수정시켜주는 것입니다.
http://wiki.apache.org/hadoop/FAQ 에 Secondary NameNode의 목적에 대해 나와 있습니다.
The only purpose of the
secondary name-node is to perform periodic checkpoints. The
secondary name-node periodically downloads current name-node image
and edits log files, joins them into new image and uploads the new
image back to the (primary and the only)
name-node.
--> Secondary NameNode는 네임노드의 FsImage와 edits log를 다운로드하여
병합(join)하여 네임노드로 upload 하는 일을 주기적으로 합니다.
--> 위 내용에 따르면 Secondary NameNode가 없어도 동작할 것 같네요.
--> 테스트 결과 동작합니다.
Thrift 소개Thrift 소개
Posted at 2010. 11. 12. 19:37 | Posted in OpenSourceboost 설치하기boost 설치하기
Posted at 2010. 9. 13. 23:26 | Posted in OpenSourceactivemq-cpp 설치하기activemq-cpp 설치하기
Posted at 2010. 9. 13. 22:20 | Posted in OpenSourceActiveMQ 메모ActiveMQ 메모
Posted at 2010. 9. 10. 16:08 | Posted in OpenSource- queue 최대값(the maximum number of matched messages)을 지정해 놓았을 때, 최대값에 다다르면 오래된 것이 discard 된다?
- prefetch size, pending limit 등 조절하여 메시지 discard가 있는지 확인해 보자. 위의 글로는 메시지가 discard되는 것으로 보이나, 문맥상 consumer에 prefetch될 메시지를 discard한다는 뜻 같기도 함.(영어 실력이 딸려서..)
- PendingMessageLimitStrategy를 사용할 수 있으며, 다음과 같이 설명하고 있다.
You can configure the PendingMessageLimitStrategy implementation class on the destination map so that different regions of your topic namespace can have different strategies for dealing with slow consumers. For example you may want to use this strategy for prices which are very high volume but for orders and trades which are lower volume you might not wish to discard old messages.
The strategy calculates the maximum number of pending messages to be kept in RAM for a consumer (above its prefetch size). A value of zero means keep no messages around other than the prefetch amount. A value greater than zero will keep up to that amount of messages around, discarding the older messages as new messages come in. A value of -1 disables the discarding of messages.
So ActiveMQ uses a prefetch limit on how many messages can be streamed to a consumer at any point in time. Once the prefetch limit is reached, no more messages are dispatched to the consumer until the consumer starts sending back acknowledgements of messages (to indicate that the message has been processed). The actual prefetch limit value can be specified on a per consumer basis.
Its a good idea to have large values of the prefetch limit if you want high performance and if you have high message volumes. If you have very few messages and each message takes a very long time to process you might want to set the prefetch value to 1 so that a consumer is given one message at a time. Specifying a prefetch limit of zero means the consumer will poll for more messages, one at a time, instead of the message being pushed to the consumer.
Pooled Connections and prefetch
Consuming messages from a connection pool can be problematic due to prefetch. Unconsumed prefetched messages are only released when a connection is closed, but with a pooled connection the connection close is deferred (for reuse) till the connection pool closes. This leaves prefetched messages unconsumed till the connection is reused. This feature can present as missing or out-of-sequence messages when there is more than one connection in the pool.
One solution is to use pooled connections for producers and a non-pooled connection for consumers. This might have performance impacts on the consumer side, if multiple threads try to consume messages at a fast rate. Alternatively, reduce the pool size to 1 for consumers. A third alternative is to reduce the prefetchSize to 1 or 0 with the pooled connection factory. When using Spring JMS and MessageDrivenPojo, you cannot use a prefetch of 0, so use 1 instead.
- The ActiveMQ broker auto-creates the physical resources associated with a destination on demand.
- broker가 시작할 때 미리 만들어 둘 수도 있다. http://activemq.apache.org/configure-startup-destinations.html
- 클라이언트에서 destination을 만들었다고 해서 서버에 만들어 지는 것은 아니다. 해당 큐 또는 토픽으로 메시지가 들어오면 만들어진다. 따라서 클라이언트가 destination 객체를 많이 만들었다고 해서 서버의 리소스를 사용하지 않는다.
- Exclusive Consumer - http://activemq.apache.org/exclusive-consumer.html
- 요약하면 queue에 하나의 consumer만 붙게하는 것.
- queue:consumer=1:1 을 broker가 보장해준다.
- Message Group - http://activemq.apache.org/message-groups.html
- Parallel Exclusive Consumer 같은 것.
- 메시지가 어떤 그룹에 속하지는 구분하기 위해 표준 JMS 헤더는 JMSXGroupID 를 사용.
- 같은 그룹은 같은 consumer에게 가는 것을 보장한다. consumer fail시 다른 consumer가 선택된다.
- 그룹 ID를 HTTP session ID에 비유하면 broker는 HTTP load balancer가 된다.
- broker는 메시지가 들어오면 그룹 ID를 검사하고, 해당 그룹에 연결된 consumer가 있는지 확인하여 전달.
- hash를 사용하므로 많은 수의 그룹을 사용할 수 있다. (Since there could be a massive number of individual message groups we use hash buckets rather than the actual JMSXGroupID string)
- consumer는 자신이 close되거나 외부에서 그룹을 close할때까지 메시지를 받는다.
- Getting notified of ownership changes of message groups: 네트워크 오류 등으로 failover처리가 되는 경우 consumer가 변경될 수 있는데, 이 때 consumer는 특정 메시지 그룹의 메시지를 처음 받는 것인지 확인 할 수가 있다. JMSXGroupFirstForConsumer boolean값을 확인하면 된다. consumer가 가진 캐시나 자원을 초기화 하는 작업 등을 할 수 있다.
- Adding new consumers: consumer들이 모두 연결되지 않은 상태에서는 첫번째 consumer가 모든 그룹의 메시지를 처리하려고 할 것이다. 이 상황을 피하기 위해 destination policy에서 consumersBeforeDispatchStarts 와 timeBeforeDispatchStarts 를 사용할 수 있다. 모든 consumer가 연결될 때까지 dispatching을 지연시킨다.
☞ consumer는 메시지 그룹별로 타이머를 걸어 특정 시간 이후로 메시지가 없을 때 그룹 close를 시키면 부드럽게 load balancing이 될 것이다.