twemproxy(트웸프록시)에 대한 예시이다.
redis나 memcached 프로토콜을 지원하며, consistent hashing을 지원하는 툴로서, 많이 사용하고 있다.
트웸프록시 tar 압축 파일을 다운받으려면, https://github.com/twitter/twemproxy에 방문하여 “To build twemproxy from distribution tarball”를 찾은 후, distribution tarball 링크를 클릭하면 tar 압축 파일을 구글 드라이브로 볼 수 있다. 구글 드라이브에서 다운받을 수 있는 tar 압축 파일을 다운받는다.
$ tar -zxf nutcracker-0.4.1.tar.gz
$ cd nutcracker-0.4.1
$ ./configure
$ make
트웸프록시의 binary인 nutcracker이 정상적으로 실행되는지 확인한다.
$ ./src/nutcracker --help
This is nutcracker-0.4.1
Usage: nutcracker [-?hVdDt] [-v verbosity level] [-o output file]
[-c conf file] [-s stats port] [-a stats addr]
[-i stats interval] [-p pid file] [-m mbuf size]
Options:
-h, --help : this help
-V, --version : show version and exit
-t, --test-conf : test configuration for syntax errors and exit
-d, --daemonize : run as a daemon
-D, --describe-stats : print stats description and exit
-v, --verbose=N : set logging level (default: 5, min: 0, max: 11)
-o, --output=S : set logging file (default: stderr)
-c, --conf-file=S : set configuration file (default: conf/nutcracker.yml)
-s, --stats-port=N : set stats monitoring port (default: 22222)
-a, --stats-addr=S : set stats monitoring ip (default: 0.0.0.0)
-i, --stats-interval=N : set stats aggregation interval in msec (default: 30000 msec)
-p, --pid-file=S : set pid file (default: off)
-m, --mbuf-size=N : set size of mbuf chunk in bytes (default: 16384 bytes)
설정 파일은 conf/nutcracker.yml이고, 야믈(yaml) 파일이다.
$ cat conf/nutcracker.yml
alpha:
listen: 127.0.0.1:22121
hash: fnv1a_64
distribution: ketama
auto_eject_hosts: true
redis: true
server_retry_timeout: 2000
server_failure_limit: 1
servers:
- 127.0.0.1:6379:1
beta:
listen: 127.0.0.1:22122
hash: fnv1a_64
hash_tag: "{}"
distribution: ketama
auto_eject_hosts: false
timeout: 400
redis: true
servers:
- 127.0.0.1:6380:1 server1
- 127.0.0.1:6381:1 server2
- 127.0.0.1:6382:1 server3
- 127.0.0.1:6383:1 server4
gamma:
listen: 127.0.0.1:22123
hash: fnv1a_64
distribution: ketama
timeout: 400
backlog: 1024
preconnect: true
auto_eject_hosts: true
server_retry_timeout: 2000
server_failure_limit: 3
servers:
- 127.0.0.1:11212:1
- 127.0.0.1:11213:1
delta:
listen: 127.0.0.1:22124
hash: fnv1a_64
distribution: ketama
timeout: 100
auto_eject_hosts: true
server_retry_timeout: 2000
server_failure_limit: 1
servers:
- 127.0.0.1:11214:1
- 127.0.0.1:11215:1
- 127.0.0.1:11216:1
- 127.0.0.1:11217:1
- 127.0.0.1:11218:1
- 127.0.0.1:11219:1
- 127.0.0.1:11220:1
- 127.0.0.1:11221:1
- 127.0.0.1:11222:1
- 127.0.0.1:11223:1
omega:
listen: /tmp/gamma
hash: hsieh
distribution: ketama
auto_eject_hosts: false
servers:
- 127.0.0.1:11214:100000
- 127.0.0.1:11215:1
distribution: ketama는 consistent hashing을 쓰겠다는 의미이다.
설정은 alpha부터 omega까지 있다. 다중 레디스를 쓰는지에 대한 설정을 가진다. 분산방법, timeout 등 설정이 있다.
설정 파일이 정상인지 체크하려면 -t를 추가한다.
$ ./src/nutcracker -t -c conf/nutcracker.yml
nutcracker: configuration file 'conf/nutcracker.yml' syntax is ok
만약 아래 에러가 발생해도 이슈는 없다. 디폴트로 22121 포트이다.
nc_connection.c:374 recv on sd 6 failed: Connection refused
nc_connection.c:374 recv on sd 7 failed: Connection refused
데몬으로 실행하려면 -d를 커맨드 라인에 추가한다.
그리고, pid 파일이나 로그 파일도 지정할 수 있다.
이제, alpha 버전인 기준으로 6379 포트만 띄운 redis만 테스트해본다.
창 하나를 띄워 redis 데몬을 실행한다.
127.0.0.1:6379> monitor
OK
nutcracker의 22121 포트로 데이터를 보낸다.
$ redis-cli -p 22121 set key value
OK
이미 띄워놓은 MONITOR 창에서 정상적으로 결과를 확인한다.
1455010283.355070 [0 127.0.0.1:55737] "set" "key" "value"
다음은 redis 인스턴스를 여러 대를 잘 처리하는지 살펴본다.
레디스 서버를 3 개의 포트로 띄운다. flushdb로 깔끔히 데이터를 정리한다.
$ ./src/redis-server --port 6379 --daemonize yes
$ ./src/redis-server --port 6380 --daemonize yes
$ ./src/redis-server --port 6381 --daemonize yes
conf/nutcracker.yml 파일에서 alpha 설정 밑에 6380과 6381을 추가한 후 재시작한다.
$ vi conf/nutcracker.yml
alpha:
listen: 127.0.0.1:22121
hash: fnv1a_64
distribution: ketama
auto_eject_hosts: true
redis: true
server_retry_timeout: 2000
server_failure_limit: 1
servers:
- 127.0.0.1:6379:1
- 127.0.0.1:6380:1
- 127.0.0.1:6381:1
...
$ ./src/nutcracker -c conf/nutcracker.yml
트웸프록시 설정이 제대로 되었는지 확인한다.
$ telnet 127.0.0.1 22222 2> /dev/null | tail -n 1 | jq '.'
{
"alpha": {
"client_eof": 0,
"client_err": 0,
"client_connections": 0,
"server_ejects": 0,
"forward_error": 0,
"fragments": 0,
"127.0.0.1:6379": {
"server_eof": 0,
"server_err": 0,
"server_timedout": 0,
"server_connections": 0,
"server_ejected_at": 0,
"requests": 0,
"request_bytes": 0,
"responses": 0,
"response_bytes": 0,
"in_queue": 0,
"in_queue_bytes": 0,
"out_queue": 0,
"out_queue_bytes": 0
},
"127.0.0.1:6380": {
"server_eof": 0,
"server_err": 0,
"server_timedout": 0,
"server_connections": 0,
"server_ejected_at": 0,
"requests": 0,
"request_bytes": 0,
"responses": 0,
"response_bytes": 0,
"in_queue": 0,
"in_queue_bytes": 0,
"out_queue": 0,
"out_queue_bytes": 0
},
"127.0.0.1:6381": {
"server_eof": 0,
"server_err": 0,
"server_timedout": 0,
"server_connections": 0,
"server_ejected_at": 0,
"requests": 0,
"request_bytes": 0,
"responses": 0,
"response_bytes": 0,
"in_queue": 0,
"in_queue_bytes": 0,
"out_queue": 0,
"out_queue_bytes": 0
}
},
트웸프록시 포트로 데이터를 저장해본다.
$ redis-cli -p 22121 set key value
$ redis-cli -p 22121 set key1 value
$ redis-cli -p 22121 set key2 value
$ redis-cli -p 22121 set akey yvalue
결과는 다음과 같다.
6379 포트 위의 레디스
127.0.0.1:6379>
127.0.0.1:6379> keys *
(empty list or set)
127.0.0.1:6379> monitor
OK
1455030738.382162 [0 127.0.0.1:56016] "set" "akey" "yvalue"
6380 포트 위의 레디스
127.0.0.1:6380> keys *
(empty list or set)
127.0.0.1:6380> monitor
OK
6381 포트 위의 레디스
127.0.0.1:6381> keys *
(empty list or set)
127.0.0.1:6381> monitor
OK
1455030017.397192 [0 127.0.0.1:55987] "set" "key" "value"
1455030688.255451 [0 127.0.0.1:55987] "set" "key1" "value"
1455030690.631344 [0 127.0.0.1:55987] "set" "key2" "value"
제대로 읽기도 잘한다.
$ redis-cli -p 22121 get key2
"value"
트웸프록시를 통해 다양하게 저장한다.
트웸프록시가 SPOF 가 될 수 있으니, L4나 HA_PROXY를 이용해서 여러 대의 트웸프록시를 바인딩할 수 있다.
참고로, info 커맨드를 이용하면 연결이 종료된다.
$ redis-cli -p 22121 info
Error: Server closed the connection
twemproxy의 해싱 알고리즘은 다양하다. libmemcached가 사실상 consistent hashing의 대표적인 알고리즘이므로 crc32로 써도 무관하다.
hash: The name of the hash function. Possible values are:
- one_at_a_time
- md5
- crc16
- crc32 (crc32 implementation compatible with libmemcached)
- crc32a (correct crc32 implementation as per the spec)
- fnv1_64
- fnv1a_64
- fnv1_32
- fnv1a_32
- hsieh
- murmur
- jenkins
그리고, 배포방식은 3가지가 존재한다.
distribution: The key distribution mode. Possible values are:
자세한 내용은 아래를 참조한다.
https://github.com/twitter/twemproxy
https://github.com/twitter/twemproxy/blob/master/notes/recommendation.md