웹사이트 검색

Ubuntu 14.04의 여러 Memcached 서버에서 PHP 세션을 공유하는 방법


소개

Memcached는 빠른 액세스를 위해 정보를 디스크가 아닌 메모리에 저장하는 분산 개체 캐싱 시스템입니다. PHP의 Memcache 모듈은 그렇지 않으면 파일 시스템에 저장되는 세션을 처리하는 데 사용할 수 있습니다. Memcached에 PHP 세션을 저장하면 세션 중복성을 유지하기 위해 Memcached를 실행하는 여러 클라우드 서버에 배포할 수 있다는 이점이 있습니다.

이 Memcached 설정이 없으면 애플리케이션이 여러 서버에서 로드 밸런싱되는 경우 로드 밸런서에서 세션 고정성을 구성해야 합니다. 이것은 사용자 경험을 유지하고 갑자기 로그오프되는 것을 방지합니다. 세션을 처리하도록 Memcached를 구성하면 Memcached 풀의 모든 클라우드 서버가 동일한 세션 데이터 집합을 갖게 되므로 세션을 보존하기 위해 한 서버에 고정할 필요가 없습니다.

전제 조건

이 튜토리얼은 여러분이 Ubuntu에서 LAMP 서버 설정에 익숙하다고 가정합니다.

물방울 1

  • 이름: lamp01
  • 공개 IP: 1.1.1.1
  • 비공개 IP: 10.1.1.1

물방울 2

  • 이름: lamp02
  • 공개 IP: 2.2.2.2
  • 비공개 IP: 10.2.2.2

물방울 3

  • 이름: lamp03
  • 공개 IP: 3.3.3.3
  • 비공개 IP: 10.3.3.3

Droplet을 생성할 때 Private Networking 확인란이 선택되어 있는지 확인하십시오. 또한 나중에 필요하므로 사설 IP 주소를 기록해 두십시오.

세 서버 모두에 LAMP를 설치합니다.

먼저 리포지토리를 업데이트하고 Apache를 설치합니다.

apt-get update
apt-get install apache2

PHP 및 Apache의 mod_php 확장을 설치합니다.

apt-get install php5 libapache2-mod-php5 php5-mcrypt

자세한 내용은 이 문서를 참조하십시오.

1단계 - Memcache 패키지 설치

lamp01에서 Memcached 데몬과 PHP의 Memcache 모듈을 설치합니다.

apt-get install php5-memcache memcached

PHP에는 php5-memcache와 php5-memcached의 두 가지 패키지가 있습니다(끝에 "d\가 있음). 첫 번째 패키지(memcache)는 의존성 없이 더 가볍기 때문에 사용할 것입니다. memcache와 memcached의 비교를 읽어보세요.

Memcached 서비스는 localhost(127.0.0.1)에서만 수신 대기합니다. 개인 네트워크에서 연결을 허용하도록 변경해야 합니다.

nano /etc/memcached.conf

다음 줄을 찾으십시오.

-l 127.0.0.1

이 서버의 사설 IP 주소에서 수신 대기하도록 변경하십시오.

-l 10.1.1.1

memcached 서비스를 다시 시작합니다.

service memcached restart

다른 두 서버에서 이 단계를 반복하여 127.0.0.1을 적절한 개인 IP 주소로 바꿉니다.

램프02

-l 10.2.2.2

램프03

-l 10.3.3.3

두 번째 두 서버에서 memcached 서비스를 다시 시작합니다.

2단계 - Memcache를 PHP의 세션 핸들러로 설정

lamp01에서 편집을 위해 php.ini 파일을 엽니다.

nano /etc/php5/apache2/php.ini

이 파일은 PHP-FPM 설치의 /etc/php5/fpm/php.ini에 있습니다.

다음 구성 지시문을 찾으십시오.

session.save_handler =
session.save_path =

다음과 같이 Memcache를 사용하도록 수정합니다. session.save_path에서 세 개인 IP 주소를 모두 사용하십시오.

session.save_handler = memcache
session.save_path = 'tcp://10.1.1.1:11211,tcp://10.2.2.2:11211,tcp://10.3.3.3:11211'

처음에 세미콜론을 제거하여 session.save_path의 주석 처리를 제거해야 할 수도 있습니다. Memcached는 이 포트에서 수신하므로 각 IP 주소 뒤에 포트 번호 11211을 입력해야 합니다.

다른 두 서버에 정확히 동일한 설정을 추가합니다.

lamp02에서:

session.save_handler = memcache
session.save_path = 'tcp://10.1.1.1:11211,tcp://10.2.2.2:11211,tcp://10.3.3.3:11211'

lamp03에서:

session.save_handler = memcache
session.save_path = 'tcp://10.1.1.1:11211,tcp://10.2.2.2:11211,tcp://10.3.3.3:11211'

세션 공유가 제대로 작동하려면 이 구성이 모든 Droplet에서 정확히 동일해야 합니다.

3단계 - 세션 중복성을 위한 Memcache 구성

lamp01에서 memcache.ini 파일을 편집합니다.

nano /etc/php5/mods-available/memcache.ini

이 파일 끝에 다음 구성 지시문을 추가합니다.

memcache.allow_failover=1
memcache.session_redundancy=4

세션 정보가 모든 서버에 복제되려면 memcache.session_redundancy 지시문이 memcached 서버 수 + 1이어야 합니다. 이것은 PHP의 버그 때문입니다.

이러한 지시문은 세션 장애 조치 및 중복성을 활성화하므로 PHP는 session.save_path에 지정된 모든 서버에 세션 정보를 기록합니다. RAID-1 설정과 유사합니다.

사용 중인 항목에 따라 웹 서버 또는 PHP FPM 데몬을 다시 시작합니다.

service apache2 reload

lamp02와 lamp03에서 이 단계를 정확히 반복합니다.

4단계 - 세션 중복성 테스트

이 설정을 테스트하려면 모든 Droplet에서 다음 PHP 스크립트를 만듭니다.

/var/www/html/session.php

<?php
    header('Content-Type: text/plain');
    session_start();
    if(!isset($_SESSION['visit']))
    {
    	echo "This is the first time you're visiting this server\n";
    	$_SESSION['visit'] = 0;
    }
    else
            echo "Your number of visits: ".$_SESSION['visit'] . "\n";

    $_SESSION['visit']++;

	echo "Server IP: ".$_SERVER['SERVER_ADDR'] . "\n";
	echo "Client IP: ".$_SERVER['REMOTE_ADDR'] . "\n";
	print_r($_COOKIE);
?>

이 스크립트는 테스트 전용이며 Droplet이 설정되면 제거할 수 있습니다.

curl을 사용하여 첫 번째 Droplet에서 이 파일에 액세스하고 쿠키 정보를 추출합니다.

curl -v -s http://1.1.1.1/session.php 2>&1 | grep 'Set-Cookie:'

그러면 다음과 유사한 출력이 반환됩니다.

< Set-Cookie: PHPSESSID=8lebte2dnqegtp1q3v9pau08k4; path=/

PHPSESSID 쿠키를 복사하고 이 쿠키를 사용하여 다른 Droplet에 요청을 보냅니다. 이 세션은 1440초 동안 요청이 없으면 PHP에 의해 제거되므로 이 시간 내에 테스트를 완료해야 합니다. 이에 대한 자세한 내용은 PHP의 session.gc-maxlifetime을 읽어보십시오.

curl --cookie "PHPSESSID=8lebte2dnqegtp1q3v9pau08k4" http://1.1.1.1/session.php http://2.2.2.2/session.php http://3.3.3.3/session.php

세션이 모든 Droplet에서 이월되고 있음을 알 수 있습니다.

Your number of visits: 1
Server IP: 1.1.1.1
Client IP: 117.193.121.130
Array
(
    [PHPSESSID] => 8lebte2dnqegtp1q3v9pau08k4
)
Your number of visits: 2
Server IP: 2.2.2.2
Client IP: 117.193.121.130
Array
(
    [PHPSESSID] => 8lebte2dnqegtp1q3v9pau08k4
)
Your number of visits: 3
Server IP: 3.3.3.3
Client IP: 117.193.121.130
Array
(
    [PHPSESSID] => 8lebte2dnqegtp1q3v9pau08k4
)

장애 조치를 테스트하려면 memcached 서비스를 중지하고 여기에서 이 파일에 액세스하십시오.

service memcached stop

Droplet은 다른 두 서버에 저장된 세션 정보를 투명하게 사용합니다.

curl --cookie "PHPSESSID=8lebte2dnqegtp1q3v9pau08k4" http://1.1.1.1/session.php

산출:

Your number of visits: 4
Server IP: 1.1.1.1
Client IP: 117.193.121.130
Array
(
    [PHPSESSID] => 8lebte2dnqegtp1q3v9pau08k4
)

이제 세션 고정을 구성하는 번거로움 없이 요청을 균등하게 분산하도록 로드 밸런서를 구성할 수 있습니다.

테스트가 완료되면 memcached를 다시 시작합니다.

service memcached start

5단계 - IPTables로 Memcached 보호

Memcached가 사설 네트워크를 사용하더라도 동일한 데이터 센터의 다른 DigitalOcean 사용자가 사설 IP를 알고 있으면 Droplet에 연결할 수 있습니다. 따라서 Memcached 풀의 클라우드 서버만 서로 통신할 수 있도록 IPTables 규칙을 설정할 것입니다.

잘못된 규칙이 적용될 경우 발생할 수 있는 문제를 더 쉽게 해결할 수 있도록 세션 중복성을 테스트한 후 이 단계를 수행합니다.

lamp02 및 lamp03의 개인 IP 주소를 사용하여 lamp01에 방화벽 규칙을 만듭니다.

iptables -A INPUT -s 10.2.2.2 -i eth1 -p tcp -m state --state NEW -m tcp --dport 11211 -j ACCEPT
iptables -A INPUT -s 10.3.3.3 -i eth1 -p tcp -m state --state NEW -m tcp --dport 11211 -j ACCEPT

일반적인 LAMP 서버에서 다음은 전체 규칙 세트입니다.

iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A INPUT -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp -m state --state NEW -m tcp --dport 443 -j ACCEPT
iptables -A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
iptables -A INPUT -s 10.2.2.2 -i eth1 -p tcp -m state --state NEW -m tcp --dport 11211 -j ACCEPT
iptables -A INPUT -s 10.3.3.3 -i eth1 -p tcp -m state --state NEW -m tcp --dport 11211 -j ACCEPT
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -p icmp -m icmp --icmp-type 8 -j ACCEPT
iptables -P INPUT DROP

lamp01 및 lamp03의 사설 IP 주소를 사용하여 lamp02에 방화벽 규칙을 입력합니다.

iptables -A INPUT -s 10.1.1.1 -i eth1 -p tcp -m state --state NEW -m tcp --dport 11211 -j ACCEPT
iptables -A INPUT -s 10.3.3.3 -i eth1 -p tcp -m state --state NEW -m tcp --dport 11211 -j ACCEPT

lamp01 및 lamp02의 개인 IP 주소를 사용하여 lamp03에서 동일한 작업을 수행합니다.

iptables -A INPUT -s 10.1.1.1 -i eth1 -p tcp -m state --state NEW -m tcp --dport 11211 -j ACCEPT
iptables -A INPUT -s 10.2.2.2 -i eth1 -p tcp -m state --state NEW -m tcp --dport 11211 -j ACCEPT

4단계의 테스트를 반복하여 방화벽이 트래픽을 차단하지 않는지 확인합니다.

추가 읽기

  • Ubuntu 14.04에 LAMP 스택을 설치하는 방법
  • IPTables를 사용하여 개인 네트워크 내에서 서버를 격리하는 방법
  • Memcached에 PHP 세션을 저장하는 방법