Server/Etc

웹서버 부하 분산을 위한 허접한 로드밸런싱 ^^;

체리필터 2006. 11. 13. 14:19
728x90
반응형
웹서버가 그렇게 성능(Xeon 2.4, 스카시HDD, 1G RAM)이 떨어지는 것도 아닌데... 60만명이 넘는 회원을 가진다음카페 회원들한테 메일한번 쏜 이후로 엄청난 접속에 거의 서버가 멎을 뻔 하였던 경험을 하였습니다.
그래서 생각한 것이 로드밸런싱인데... 허접한 제 실력에 로드밸런싱이란 것은 하기 힘든 작업이었죠.^^
그래도 어디서 들어본 것은 있는지 문득 생각난 것이 rsync와 Round-Robin이였습니다.^^
하지만 들어보기만 했지 직접 해 본적은 없어서... 어떻게 해야 할 지 난감하더군요..^^
어째든 맨땅에 헤딩은 그렇게 시작이 되었습니다.^^
여기서 많은 분들께 질문도 하고... 여기 저기 문서도 많이 찾아 봤습니다.^^

아직 완벽하지는 않은 듯 하니... 참고로 보시고..
물론 더 뛰어난 실력을 갖추신 분들은 더 좋은 로드밸런싱을 사용하시기 바랍니다. (skip... ^^)

그럼 하나 하나 제가 한 방법을 적어보도록 하겠습니다. 이하 존댓말 생략입니다.^^;


기존의 웹서버 A와 새롭게 추가하고자 하는 웹서버 B가 있다고 보자.

A서버의 아이피 : 192.168.1.1
B서버의 아이피 : 192.168.1.2

우선은 두 서버가 하나의 서버로 인식하기 위해서는 두 서버 모두 하나의 도메인을 가지고 있어야 한다. 따라서 DNS의 설정은 필수적이다.


1. DNS 설정(Round-Robin)

$TTL 86400
@ IN SOA ns.localhost.com. root.localhost.com. (
2003052901
21600
1800
1209600
86400)
IN NS ns.localhost.com.
IN A 192.168.1.1
www IN A 192.168.1.1
www IN A 192.168.1.2
www1 IN A 192.168.1.1
www2 IN A 192.168.1.2


위와 같이 zone 파일을 설정한다. 물론 named는 restart 해야 한다. 그러면 www.localhost.com이란도메인은 192.168.1.1과 192.168.1.2 두개의 아이피를 가지게 된다. 이 상태에서 nslookupwww.localhost.com이라고 하면... 다음과 같이 나온다.


Server: 168.126.63.1 --> 질의한 서버 아이피
Address: 168.126.63.1#53

Name: www.localhost.com
Address: 192.168.1.1 --> 결과값1
Name: www.localhost.com
Address: 192.168.1.2 --> 결과값2

이와 같이 나온다면 네임서버는 잘 설정한 것이다.^^


2. 웹서버의 설정

우선 두대 모두다 apache의 httpd.conf파일에 www.localhost.com 도메인을 설정해 두어야 한다. 만일이미 다른 것으로 사용하고 있다면 apache의 가성서버 설정을 이용해야 한다.(물론 여기서 가상호스트 설정까지 살펴보지는않겠다.^^) 기본적으로 두 서버의 DocumentRoot가 틀려도 되지만, 손 쉬운 관리를 위해서 경로를 같게 두는 것이 좋을것이다.

ex)
A서버의 DocumentRoot - /usr/local/localhostSource
B서버의 DocumentRoot - /usr/local/localhostSource


3. rsync의 설정

이제 두대의 서버가 갖춰지고 두대 모두 동일한 도메인을 가지게 되었다면 두 서버의 소스가 동일하도록 할 차례이다. 이러한 것을위해서 바로 rsync가 필요하다. rsync와 관련된 많은 참고문헌들을 뒤졌는데 결론적으로 '질주본능'님의 조언으로 성공하게되었다. 이 자리를 빌어 감사하다는 말씀을 전한다. '질주본능'님이 쓰신 rsync 관련 내용을 보시고 싶으신 분은http://www.phpschool.com/bbs2/inc_view.html?id=9985&code=tnt2&start=0&mode=search&field=title&search_name=&operator=and&period=all&category_id=&s_que=rsync를 참고하기 바란다.

우선 rsync 는 ssh를 이용한 방법과 873 포트를 이용한 방법이 있다. ssh를 이용한 방법이 조금더 안정성 면에서 좋을것이라는 생각에 시도하였지만 번번히 실패하게 되었고 결국에는 873포트를 이용한 rsync를 성공하게 되었다. ssh를 이용한rsync에는 비밀번호를 물어보게 되는데 파일을 이용하여 비밀번호를 자동으로 입력할 수 있다고 하는데 잘 되지 않았다.(성공한분은 비결좀 알려주시길...^^)


그럼 873포트를 이용한 rsync 설정 방법을 알아보도록 하자.

우선은 xinetd를 이용하여 rsync가 구동되므로 다음과 같이 설정을 해 줘야 한다.

#vi /etc/xinetd.d/rsync

# default: off
# description: The rsync server is a good addition to an ftp server, as it \
# allows crc checksumming etc.
service rsync
{
disable = no
socket_type = stream
wait = no
user = root
server = /usr/bin/rsync
server_args = --daemon
log_on_failure += USERID
}


그 다음 rsync의 설정파일을 수정해 줘야 한다. rsync의 설정 파일은 rsyncd.conf 파일이다. 물론 이 파일은원래 존재하지 않는다.(원래 존재하는데 필자만 없었을 수도 있다.) 한가지 주의할 것은 설정파일 이름이 rsync.conf가아니라 rsyncd.conf란 것이다. 일부 tip에서 rsync.conf라고 하는데 이렇게 할 경우에는 rsync가 되지않았다.

#vi /etc/rsyncd.conf

[www]
path = /usr/local/localSource
comment = webservice-dir
uid = root
gid = root
use chroot = yes
read only = yes
hosts allow = 192.168.1.2
max connections = 1
timeout = 300

여기서 [www] 은 닉네임이다. 즉 아래 설정 내용을 한번에 호칭하기 위해 사용하는 것이다. path는 rsync를 받고자 하는 소스가 존재하는 디렉토리를 정해주면 된다.
uid와 gid는 root로 하는 것이 좋다. nobody로 할 경우에는 일부 기능을 사용하지 못하는 경우가 발생했다.^^(정확한 이유는 모르겠다.^^)
hosts allow는 어느 아이피에서 rsync 서버에 붙어 소스를 가져가도록 허락할 것인지 설정해 주는 것이다.


rsync의 설정을 모두 마쳤다면 xinetd 데몬을 재 시작한다.

/etc/rc.d/init.d/xinetd restart


설정을 마치고 xinetd도 재시작했다면 873 포트가 열려 있는지 테스트 해보자.

#telnet localhost 873
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
@RSYNCD: 26
Localhost rsync server
sysadmin = root@localhost.com

위와 같이 나온다면 정상적으로 설정이 된 것이다. 물론 2번째로 소스를 받아갈 B서버에서도 테스트를 해 봐야 한다.


#telnet 192.168.1.1 873
Trying 192.168.1.1...
Connected to 192.168.1.1.
Escape character is '^]'.
@RSYNCD: 26
Localhost rsync server
sysadmin = root@localhost.com


이렇게 되었다면 이제 rsync는 완전히 성공한 거나 다름 없다.
다음과 같이 테스트 해보자...^^

rsync -avzrt --delete 192.168.1.1::www /usr/local/localSource/


-a는 아카이브 모드. 심볼릭 링크, 속성, 퍼미션, 소유권 등 보존
-v 전송 상태를 보여줌
-z 전송시 압축을 함.
-r recursive (하위 디렉토리까지 포함)
-t 변경시간 전송 (이것이 없으면 전송한 시간으로 바뀜)

--delete A서버에는 없는데 B서버에 있다면 지우라는 명령

::는 873포트를 이용한 rsync에서 사용하며 ssh나 rsh를 사용할 경우에는 : 라고 써야 한다. 우리는 873 포트를 이용하므로 :: 라고 써야 한다.
www는 rsync 서버의 /etc/rsyncd.conf 파일에서 준 닉 이다. 바로 그 곳에서 설정한 path의 소스들을 /usr/local/localSource/ 디렉토리 밑으로 가져온다는 의미이다.

이해를 다 하셨다면 'Enter'를 힘차게 눌러보자.. 화면이 주르륵 하면서 소스를 가져오는 것이 보일 것이다.(안보이면 대략 낭패..-.-;)
처음에는 모든 파일을 다 가져오기에 조금 시간이 걸릴 것이다. 하지만 그 다음부터는 변경된 파일만 가져올 것이므로 그다지 부하는 걸리지 않을 것이다.^^ (예상하건데...)

이 명령어를 수동으로 매번 타이핑할 수 없으므로 /etc/cron.hourly/ 밑에 shell script 파일 하나를 만들자.

#vi rsync.sh

rsync -avzrt --delete 192.168.1.1::www /usr/local/localSource/

그리고 나서 chmod 700 rsync.sh 하면...^^ rsync 완료...


4. nfs의 설정

사이트에 소스만 있다면 이것으로 끝날 수 있다. 하지만 어찌 소스만 있으랴... nobody 권한으로 생성되는 각종 파일들(로그기록, 그림파일, 업로드 되는 파일들... 기타 등등)을 어떻게 두 서버에서 공유할 수 있단 말인가?
사용자가 운좋게 Round-Robin에서 잘 걸려서 A서버로 붙은 후 파일을 업로드 했다면 rsync로 샥~~ 파일을 가져오면되는데... B서버에 붙어서 파일을 올렸다면 어찌 해 볼 도리가 없다. 그렇다고 B서버에 rsync 서버를 설치하고 거꾸로 다시가져오는 것도 바보같은 짓이다.^^(설마 이렇게 하는 분들은 안계시겠죠?)

그래서 나온 것이 nfs이다. Network File System의 약자로 원격지에 있는 하드디스크를 마치 자신의 하드디스크인양 mount 해서 쓸 수 있는 것이다.
따라서 A서버에 있는 디렉토리를 B서버에서 마운트 한다면 어느 서버에서 파일을 올리던 한곳에 파일이 기록되게 되는 것이다. 물론파일서버를 하나 더 두고 A, B 서버 모두 마운트 해서 사용해도 될 것이다(이렇게는 해 보지 않았다^^)

한가지 주의할 사항은 파일이 쌓이는 곳이 DocumentRoot 밖에 있어야 한다는 것이다. 그래야지만 rsync와 상관없이 실시간으로 파일을 공유할 수 있기 때문이다.

필자는 /localData 란 디렉토리를 하나 만들고 이곳에 nobody 권한으로 생기는 모든 파일을 잘 정리해서 사용하고 있었다.
그럼 nfs의 설정을 하나하나 살펴보도록 하자.


우선은 rsync와 마찬가지로 어느 디렉토리를 어떤 아이피와 공유할 것인지를 설정해야 한다. 따라서 A서버에서 다음과 같이 설정해 줘야 한다.

#vi /etc/exports

/localData 192.168.1.2(rw,no_root_squash)


여기서 /localData란 마운트 당할(?) 디렉토리명... 192.168.1.2는 접근 허용할 아이피, rw는 일고 쓰기가능토록 권한을 주는 것..., no_root_squash는 B서버의 root도 해당 디렉토리에서 A서버의 루트 권한을 주는것(맞나?)이다. 참고로 아이피는 도메인으로 설정해 줘도 되는데... 우리는 A서버와 B서버의 도메인이 같으므로 아이피로 하도록한다.
이렇게 설정을 한 다음... nfs 데몬을 재시작 한다.

#/etc/rc.d/init.d/nfs restart

이렇게 하면 5개인가의 데몬이 주르륵 재시작된다.(stop, start 합치면 10개의 ok 사인이 떨어진다.^^)

이상태에서 바로 B 서버에서 mount를 하면 대략 난감이다. ^^(이거때문에 몇일을 헤메었는지 모른다.^^;;)
이렇게 다 했다면 가장 중요한 데몬 하나를 죽여줘야 한다.^^

#/etc/rc.d/init.d/nfslock stop

이놈이 뭐하는 놈인지 모르겠는데, 이 데몬이 살아 있다면 죽어도 B서버에서 A서버의 /localData를 mount 하지 못할 것이다.(하는 분이 나타난다면... 안되는데..^^;;)
어째든 여기까지 했다면 거의 다 성공한 것이다.

하지만 B서버에서도 설정해 줘야 할 것이 몇개 있다.^^

다음과 같이 dns에 질의하지 않고 바로 연결할 수 있도록 hosts파일을 편집해 줘야 한다.(성능상 좋다고 한다^^, hosts파일의 역할을 모르시는 분은 검색..^^)

#vi /etc/hosts

192.168.1.1 localhost.com localhost.com


그다음 마운트!!!

#mount -t nfs localhost.com:/localData /localData/

한번 마운트가 잘 되었는지 확인해 보자...^^

#cd /localData
#ls -al
drwxr-xr-x 8 nobody nobody 4096 2월 23 17:57 .
drwxr-xr-x 20 nobody nobody 4096 2월 24 13:10 ..
drwxr-xr-x 2 nobody nobody 4096 2월 25 10:44 adminCharge
drwxr-xr-x 2 nobody nobody 4096 2월 26 16:48 cafeConn
drwxr-xr-x 38 nobody nobody 4096 2월 11 13:23 history
drwxr-xr-x 38 nobody nobody 4096 7월 22 2003 ipLog
drwxr-xr-x 2 nobody nobody 8192 2월 27 2004 joinWord
drwxr-xr-x 2 nobody nobody 4096 1월 2 00:06 userAgent

이 다음 B서버에서 접속한 경우 nobody 권한으로 기록되는 파일들이 /localData에 제대로 기록되는지 테스트만 해 보면 된다.


마침...

현재 이런 셋팅에서 테스트 해본 결과 잘 되고 있습니. 다만 로드밸런싱을 하는 프로그램이 따로 없고 네임서버를 이용한Round-Robin을 이용하다 보니 A, B 서버의 사양에 상관없이 균등하게 배분이 되며 한번 A서버에 붙은 사람은 B 서버로잘 옮겨오지 못하는 경우가 발생합니다.
그렇게 큰 문제는 아니라고 생각되지만, 불편하신 분들은 더 좋은 로드밸런싱 프로그램을 사용하길 바랍니다. 아마도 돈을 조금 지불해야 되지 않을까 십네요^^
그리고 더 좋은 무료 로드밸런싱 제품이 있다면 저한테도 좀 알려주시기 바랍니다.^^


참고로 이 글은 제가 직접 쓴 글이므로(물론 많은 분들의 도움이 있었지만..^^) 옮겨가실 때에는 출처를 밝혀 주시고... 이대로 따라 하시다가 서버가 맛이 간다거나 해도 저의 책임이 없음을 미리 밝히는 바입니다.^^;

그럼 즐프하시고...
좋은 시간 되세요.
728x90
반응형

'Server > Etc' 카테고리의 다른 글

[Redis] redis 정리  (0) 2014.12.01
왜 리눅스에선 조각 모음이 필요 없는가?  (2) 2006.11.28
리눅스에서 ntfs 하드 mount 하기... ^^  (0) 2006.11.13