์ฝ˜ํ…์ธ  ๋Œ€ํ‘œ ์ด๋ฏธ์ง€ - ๐Ÿš€ PHP์™€ HAProxy๋กœ ๋งŒ๋“œ๋Š” ๋ฌด์ค‘๋‹จ ์›น ์„œ๋ฒ„

๐Ÿš€ PHP์™€ HAProxy๋กœ ๋งŒ๋“œ๋Š” ๋ฌด์ค‘๋‹จ ์›น ์„œ๋ฒ„

์นœ๊ตฌ์•ผ, ์„œ๋ฒ„ ๋‹ค์šด ๊ฑฑ์ • ์—†๋Š” ๊ณ ๊ฐ€์šฉ์„ฑ ์‹œ์Šคํ…œ ๊ตฌ์ถ•๋ฒ•์„ ์•Œ๋ ค์ค„๊ฒŒ!

๐ŸŽฏ ์™œ ๊ณ ๊ฐ€์šฉ์„ฑ์ด ํ•„์š”ํ• ๊นŒ?

์•ผ, ์†”์งํžˆ ๋งํ•ด์„œ ์›น ์„œ๋ฒ„ ํ•˜๋‚˜ ๋„์šฐ๋Š” ๊ฑด ์–ด๋ ต์ง€ ์•Š์ž–์•„? ๐Ÿค”
๊ทผ๋ฐ ์ง„์งœ ๋ฌธ์ œ๋Š” ๊ทธ ์„œ๋ฒ„๊ฐ€ ๊ฐ‘์ž๊ธฐ ๋ป—์—ˆ์„ ๋•Œ์•ผ. ์‚ฌ์šฉ์ž๋“ค์€ "์‚ฌ์ดํŠธ ์•ˆ ๋“ค์–ด๊ฐ€์š”!" ํ•˜๋ฉด์„œ ๋‚œ๋ฆฌ๊ฐ€ ๋‚˜๊ณ , ๋„ˆ๋Š” ์ƒˆ๋ฒฝ 3์‹œ์— ๊ธ‰ํ•˜๊ฒŒ ์„œ๋ฒ„์‹ค๋กœ ๋‹ฌ๋ ค๊ฐ€๋Š” ์ƒํ™ฉ...

์ด๋Ÿฐ ์•…๋ชฝ ๊ฐ™์€ ์‹œ๋‚˜๋ฆฌ์˜ค๋ฅผ ํ”ผํ•˜๋ ค๋ฉด ๊ณ ๊ฐ€์šฉ์„ฑ(High Availability, HA) ์‹œ์Šคํ…œ์ด ํ•„์ˆ˜์•ผ!

๊ณ ๊ฐ€์šฉ์„ฑ์ด๋ž€ ์‰ฝ๊ฒŒ ๋งํ•ด์„œ "์„œ๋ฒ„ ํ•˜๋‚˜๊ฐ€ ์ฃฝ์–ด๋„ ์„œ๋น„์Šค๋Š” ๊ณ„์† ๋Œ์•„๊ฐ„๋‹ค"๋Š” ๊ฐœ๋…์ด์•ผ. ๋งˆ์น˜ ์˜ˆ๋น„ ํƒ€์ด์–ด๋ฅผ ๊ฐ€์ง€๊ณ  ๋‹ค๋‹ˆ๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ง์ด์ง€! ๐Ÿš—๐Ÿ’จ

์‹ค์ œ๋กœ ์•„๋งˆ์กด, ๋„ทํ”Œ๋ฆญ์Šค ๊ฐ™์€ ๋Œ€ํ˜• ์„œ๋น„์Šค๋“ค์€ 99.99% ์ด์ƒ์˜ ๊ฐ€๋™๋ฅ ์„ ์ž๋ž‘ํ•˜๋Š”๋ฐ, ์ด๊ฒŒ ๋ฐ”๋กœ ๊ณ ๊ฐ€์šฉ์„ฑ ์•„ํ‚คํ…์ฒ˜ ๋•๋ถ„์ด์•ผ. 1๋…„์— ๋‹จ 52๋ถ„๋งŒ ๋‹ค์šดํƒ€์ž„์ด ํ—ˆ์šฉ๋˜๋Š” ์ˆ˜์ค€์ด๋ผ๋‹ˆ... ๋Œ€๋‹จํ•˜์ง€? ๐Ÿ˜ฒ
๊ณ ๊ฐ€์šฉ์„ฑ ์›น ์„œ๋ฒ„ ์•„ํ‚คํ…์ฒ˜ HAProxy ๋กœ๋“œ ๋ฐธ๋Ÿฐ์„œ PHP Server 1 192.168.1.10 PHP Server 2 192.168.1.11 PHP Server 3 192.168.1.12 ์„œ๋ฒ„ ๋‹ค์šด! ๐Ÿ‘ค ์‚ฌ์šฉ์ž ํŠธ๋ž˜ํ”ฝ์ด ์ •์ƒ ์„œ๋ฒ„๋กœ๋งŒ ๋ถ„์‚ฐ๋ฉ๋‹ˆ๋‹ค

๐Ÿ”ง HAProxy๊ฐ€ ๋ญ”๋ฐ?

HAProxy๋Š” High Availability Proxy์˜ ์•ฝ์ž๋กœ, ์˜คํ”ˆ์†Œ์Šค ๋กœ๋“œ ๋ฐธ๋Ÿฐ์„œ์ด์ž ํ”„๋ก์‹œ ์„œ๋ฒ„์•ผ. ๐ŸŽช

์‰ฝ๊ฒŒ ๋น„์œ ํ•˜์ž๋ฉด, HAProxy๋Š” ๋ ˆ์Šคํ† ๋ž‘์˜ ์›จ์ดํŒ… ๋งค๋‹ˆ์ € ๊ฐ™์€ ์กด์žฌ์•ผ. ์†๋‹˜(์‚ฌ์šฉ์ž ์š”์ฒญ)์ด ๋“ค์–ด์˜ค๋ฉด ์–ด๋А ํ…Œ์ด๋ธ”(์„œ๋ฒ„)์ด ๋น„์–ด์žˆ๋Š”์ง€ ํ™•์ธํ•˜๊ณ , ๊ฐ€์žฅ ์ ์ ˆํ•œ ๊ณณ์œผ๋กœ ์•ˆ๋‚ดํ•ด์ฃผ๋Š” ๊ฑฐ์ง€!

HAProxy์˜ ํ•ต์‹ฌ ๊ธฐ๋Šฅ๋“ค:

โœ… ๋กœ๋“œ ๋ฐธ๋Ÿฐ์‹ฑ: ์—ฌ๋Ÿฌ ์„œ๋ฒ„์— ํŠธ๋ž˜ํ”ฝ์„ ๊ณจ๊ณ ๋ฃจ ๋ถ„์‚ฐ
โœ… ํ—ฌ์Šค ์ฒดํฌ: ์„œ๋ฒ„๊ฐ€ ์‚ด์•„์žˆ๋Š”์ง€ ์ฃผ๊ธฐ์ ์œผ๋กœ ํ™•์ธ
โœ… ์„ธ์…˜ ์œ ์ง€: ๊ฐ™์€ ์‚ฌ์šฉ์ž๋Š” ๊ฐ™์€ ์„œ๋ฒ„๋กœ ์—ฐ๊ฒฐ
โœ… SSL ํ„ฐ๋ฏธ๋„ค์ด์…˜: HTTPS ์•”ํ˜ธํ™” ์ฒ˜๋ฆฌ
โœ… ๊ณ ์„ฑ๋Šฅ: ์ดˆ๋‹น ์ˆ˜๋งŒ ๊ฑด์˜ ์š”์ฒญ ์ฒ˜๋ฆฌ ๊ฐ€๋Šฅ

ํŠนํžˆ PHP ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜๊ณผ ๊ถํ•ฉ์ด ์ •๋ง ์ข‹์•„! PHP-FPM๊ณผ ์กฐํ•ฉํ•˜๋ฉด ์—„์ฒญ๋‚œ ์„ฑ๋Šฅ์„ ๋‚ผ ์ˆ˜ ์žˆ๊ฑฐ๋“ . ๐Ÿ’ช
๐Ÿ’ก ์žฌ๋Šฅ๋„ท ํŒ

HAProxy ์„ค์ •์ด ๋ณต์žกํ•˜๊ฒŒ ๋А๊ปด์ง„๋‹ค๋ฉด, ์žฌ๋Šฅ๋„ท์—์„œ ์„œ๋ฒ„ ๊ตฌ์ถ• ์ „๋ฌธ๊ฐ€๋ฅผ ์ฐพ์•„๋ณด๋Š” ๊ฒƒ๋„ ์ข‹์€ ๋ฐฉ๋ฒ•์ด์•ผ! ์‹ค๋ฌด ๊ฒฝํ—˜์ด ํ’๋ถ€ํ•œ ๊ฐœ๋ฐœ์ž๋“ค์ด ๋„ˆ์˜ ํ”„๋กœ์ ํŠธ์— ๋งž๋Š” ์ตœ์ ์˜ ์•„ํ‚คํ…์ฒ˜๋ฅผ ์„ค๊ณ„ํ•ด์ค„ ์ˆ˜ ์žˆ์–ด. ๐Ÿš€

๐Ÿ—๏ธ ์‹œ์Šคํ…œ ์•„ํ‚คํ…์ฒ˜ ์„ค๊ณ„

์ž, ์ด์ œ ๋ณธ๊ฒฉ์ ์œผ๋กœ ์šฐ๋ฆฌ๊ฐ€ ๋งŒ๋“ค ์‹œ์Šคํ…œ์˜ ๊ตฌ์กฐ๋ฅผ ์‚ดํŽด๋ณผ๊นŒ? ๐Ÿ“

๊ธฐ๋ณธ ๊ตฌ์„ฑ:

๊ตฌ์„ฑ ์š”์†Œ ์—ญํ•  ์ˆ˜๋Ÿ‰
HAProxy ์„œ๋ฒ„ ๋กœ๋“œ ๋ฐธ๋Ÿฐ์„œ (ํ”„๋ก ํŠธ์—”๋“œ) 1๋Œ€ (๋˜๋Š” 2๋Œ€๋กœ ์ด์ค‘ํ™”)
PHP ์›น ์„œ๋ฒ„ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์„œ๋ฒ„ (๋ฐฑ์—”๋“œ) 2๋Œ€ ์ด์ƒ
MySQL/MariaDB ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค 1๋Œ€ (๋˜๋Š” Master-Slave ๊ตฌ์„ฑ)
Redis/Memcached ์„ธ์…˜ ์ €์žฅ์†Œ (์„ ํƒ์‚ฌํ•ญ) 1๋Œ€

๋„คํŠธ์›Œํฌ ๊ตฌ์„ฑ ์˜ˆ์‹œ:

HAProxy: 192.168.1.100 (๊ณต์ธ IP ์—ฐ๊ฒฐ)
PHP Server 1: 192.168.1.10
PHP Server 2: 192.168.1.11
PHP Server 3: 192.168.1.12
MySQL Server: 192.168.1.20
Redis Server: 192.168.1.30

์ด๋ ‡๊ฒŒ ๊ตฌ์„ฑํ•˜๋ฉด HAProxy๋งŒ ์™ธ๋ถ€์— ๋…ธ์ถœ๋˜๊ณ , ์‹ค์ œ PHP ์„œ๋ฒ„๋“ค์€ ๋‚ด๋ถ€ ๋„คํŠธ์›Œํฌ์—์„œ ์•ˆ์ „ํ•˜๊ฒŒ ๋ณดํ˜ธ๋ผ! ๐Ÿ›ก๏ธ

โš™๏ธ HAProxy ์„ค์น˜ ๋ฐ ๊ธฐ๋ณธ ์„ค์ •

์ž, ์ด์ œ ์‹ค์ „์ด์•ผ! ๋จผ์ € HAProxy๋ฅผ ์„ค์น˜ํ•ด๋ณด์ž. ๐Ÿ”จ

1
Ubuntu/Debian ๊ธฐ๋ฐ˜ ์‹œ์Šคํ…œ์—์„œ ์„ค์น˜:

sudo apt update
sudo apt install haproxy -y

# ๋ฒ„์ „ ํ™•์ธ
haproxy -v
2
CentOS/RHEL ๊ธฐ๋ฐ˜ ์‹œ์Šคํ…œ์—์„œ ์„ค์น˜:

sudo yum install haproxy -y

# ๋˜๋Š” ์ตœ์‹  ๋ฒ„์ „์„ ์›ํ•œ๋‹ค๋ฉด
sudo yum install epel-release -y
sudo yum install haproxy -y

์„ค์น˜๊ฐ€ ์™„๋ฃŒ๋˜๋ฉด HAProxy์˜ ๋ฉ”์ธ ์„ค์ • ํŒŒ์ผ์€ /etc/haproxy/haproxy.cfg์— ์œ„์น˜ํ•ด ์žˆ์–ด.

๊ธฐ๋ณธ ์„ค์ • ํŒŒ์ผ ๊ตฌ์กฐ:

global
    # ์ „์—ญ ์„ค์ • (๋กœ๊ทธ, ์„ฑ๋Šฅ ํŠœ๋‹ ๋“ฑ)
    
defaults
    # ๊ธฐ๋ณธ๊ฐ’ ์„ค์ • (ํƒ€์ž„์•„์›ƒ, ๋กœ๊ทธ ํฌ๋งท ๋“ฑ)
    
frontend
    # ํด๋ผ์ด์–ธํŠธ ์ ‘์†์„ ๋ฐ›๋Š” ๋ถ€๋ถ„
    
backend
    # ์‹ค์ œ ์„œ๋ฒ„๋“ค์„ ์ •์˜ํ•˜๋Š” ๋ถ€๋ถ„
    
listen
    # frontend + backend๋ฅผ ํ•ฉ์นœ ๊ฐ„๋‹จํ•œ ์„ค์ •

์ด์ œ ์‹ค์ œ๋กœ ์‚ฌ์šฉํ•  ์„ค์ • ํŒŒ์ผ์„ ๋งŒ๋“ค์–ด๋ณผ๊นŒ? ๐Ÿ˜Ž

๐Ÿ“ HAProxy ์„ค์ • ํŒŒ์ผ ์ž‘์„ฑ

์ž, ์ด์ œ ์ง„์งœ ํ•ต์‹ฌ์ด์•ผ! HAProxy ์„ค์ • ํŒŒ์ผ์„ ์ œ๋Œ€๋กœ ์ž‘์„ฑํ•ด๋ณด์ž. ๐Ÿ’ป

/etc/haproxy/haproxy.cfg ํŒŒ์ผ์„ ์—ด์–ด์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ž‘์„ฑํ•ด:

#---------------------------------------------------------------------
# Global settings
#---------------------------------------------------------------------
global
    log         127.0.0.1 local2
    chroot      /var/lib/haproxy
    pidfile     /var/run/haproxy.pid
    maxconn     4000
    user        haproxy
    group       haproxy
    daemon
    
    # SSL ์„ค์ • (ํ•„์š”์‹œ)
    tune.ssl.default-dh-param 2048

#---------------------------------------------------------------------
# Defaults settings
#---------------------------------------------------------------------
defaults
    mode                    http
    log                     global
    option                  httplog
    option                  dontlognull
    option                  http-server-close
    option                  forwardfor except 127.0.0.0/8
    option                  redispatch
    retries                 3
    timeout http-request    10s
    timeout queue           1m
    timeout connect         10s
    timeout client          1m
    timeout server          1m
    timeout http-keep-alive 10s
    timeout check           10s
    maxconn                 3000

#---------------------------------------------------------------------
# Frontend configuration
#---------------------------------------------------------------------
frontend php_frontend
    bind *:80
    # HTTPS๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด
    # bind *:443 ssl crt /etc/haproxy/certs/server.pem
    
    default_backend php_backend
    
    # ACL ์„ค์ • ์˜ˆ์‹œ (ํŠน์ • ๊ฒฝ๋กœ ๋ถ„๊ธฐ)
    acl is_api path_beg /api
    use_backend api_backend if is_api

#---------------------------------------------------------------------
# Backend configuration
#---------------------------------------------------------------------
backend php_backend
    balance     roundrobin
    option      httpchk GET /health.php
    
    # PHP ์„œ๋ฒ„๋“ค ์ •์˜
    server php1 192.168.1.10:80 check inter 3000 rise 2 fall 3
    server php2 192.168.1.11:80 check inter 3000 rise 2 fall 3
    server php3 192.168.1.12:80 check inter 3000 rise 2 fall 3 backup

#---------------------------------------------------------------------
# Stats page (๋ชจ๋‹ˆํ„ฐ๋ง์šฉ)
#---------------------------------------------------------------------
listen stats
    bind *:8080
    stats enable
    stats uri /haproxy-stats
    stats refresh 30s
    stats auth admin:your_secure_password_here

์„ค์ • ํŒŒ์ผ ์ฃผ์š” ํ•ญ๋ชฉ ์„ค๋ช…:

๐Ÿ”น maxconn: ์ตœ๋Œ€ ๋™์‹œ ์ ‘์†์ž ์ˆ˜
๐Ÿ”น balance roundrobin: ๋ผ์šด๋“œ๋กœ๋นˆ ๋ฐฉ์‹์œผ๋กœ ํŠธ๋ž˜ํ”ฝ ๋ถ„์‚ฐ
๐Ÿ”น option httpchk: ํ—ฌ์Šค ์ฒดํฌ ๋ฐฉ๋ฒ• (GET /health.php ์š”์ฒญ)
๐Ÿ”น check inter 3000: 3์ดˆ๋งˆ๋‹ค ํ—ฌ์Šค ์ฒดํฌ
๐Ÿ”น rise 2: 2๋ฒˆ ์—ฐ์† ์„ฑ๊ณตํ•˜๋ฉด ์„œ๋ฒ„ ํ™œ์„ฑํ™”
๐Ÿ”น fall 3: 3๋ฒˆ ์—ฐ์† ์‹คํŒจํ•˜๋ฉด ์„œ๋ฒ„ ๋น„ํ™œ์„ฑํ™”
๐Ÿ”น backup: ๋ฐฑ์—… ์„œ๋ฒ„ (๋‹ค๋ฅธ ์„œ๋ฒ„๊ฐ€ ๋ชจ๋‘ ๋‹ค์šด๋˜๋ฉด ์‚ฌ์šฉ)

๐Ÿ’š Pro Tip

backup ์˜ต์…˜์„ ์‚ฌ์šฉํ•˜๋ฉด ํ‰์†Œ์—๋Š” ๋Œ€๊ธฐํ•˜๋‹ค๊ฐ€ ๋ฉ”์ธ ์„œ๋ฒ„๋“ค์ด ๋ชจ๋‘ ๋‹ค์šด๋˜์—ˆ์„ ๋•Œ๋งŒ ํ™œ์„ฑํ™”๋˜๋Š” ์˜ˆ๋น„ ์„œ๋ฒ„๋ฅผ ๋‘˜ ์ˆ˜ ์žˆ์–ด. ๋น„์šฉ ํšจ์œจ์ ์ด๋ฉด์„œ๋„ ์•ˆ์ „ํ•œ ๊ตฌ์„ฑ์ด์ง€! ๐ŸŽฏ

๐Ÿฅ ํ—ฌ์Šค ์ฒดํฌ PHP ํŒŒ์ผ ์ž‘์„ฑ

HAProxy๊ฐ€ ์„œ๋ฒ„ ์ƒํƒœ๋ฅผ ํ™•์ธํ•˜๋ ค๋ฉด ํ—ฌ์Šค ์ฒดํฌ์šฉ PHP ํŒŒ์ผ์ด ํ•„์š”ํ•ด.
๊ฐ PHP ์„œ๋ฒ„์˜ ์›น ๋ฃจํŠธ ๋””๋ ‰ํ† ๋ฆฌ์— health.php ํŒŒ์ผ์„ ๋งŒ๋“ค์–ด๋ณด์ž! ๐Ÿฉบ

๊ฐ„๋‹จํ•œ ๋ฒ„์ „:

<?php
// ๊ธฐ๋ณธ ํ—ฌ์Šค ์ฒดํฌ
http_response_code(200);
echo "OK";
?>

๊ณ ๊ธ‰ ๋ฒ„์ „ (๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ ํ™•์ธ ํฌํ•จ):

<?php
header('Content-Type: application/json');

$health = [
    'status' => 'healthy',
    'timestamp' => date('Y-m-d H:i:s'),
    'server' => gethostname(),
    'checks' => []
];

// PHP ๋ฒ„์ „ ์ฒดํฌ
$health['checks']['php_version'] = [
    'status' => 'ok',
    'version' => PHP_VERSION
];

// ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰ ์ฒดํฌ
$memory_usage = memory_get_usage(true);
$memory_limit = ini_get('memory_limit');
$health['checks']['memory'] = [
    'status' => 'ok',
    'usage' => round($memory_usage / 1024 / 1024, 2) . ' MB',
    'limit' => $memory_limit
];

// ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ ์ฒดํฌ
try {
    $pdo = new PDO(
        'mysql:host=192.168.1.20;dbname=myapp',
        'dbuser',
        'dbpassword',
        [PDO::ATTR_TIMEOUT => 3]
    );
    $health['checks']['database'] = [
        'status' => 'ok',
        'message' => 'Connected'
    ];
} catch (PDOException $e) {
    $health['status'] = 'unhealthy';
    $health['checks']['database'] = [
        'status' => 'error',
        'message' => 'Connection failed'
    ];
    http_response_code(503);
}

// Redis ์—ฐ๊ฒฐ ์ฒดํฌ (์„ ํƒ์‚ฌํ•ญ)
if (class_exists('Redis')) {
    try {
        $redis = new Redis();
        $redis->connect('192.168.1.30', 6379, 2);
        $redis->ping();
        $health['checks']['redis'] = [
            'status' => 'ok',
            'message' => 'Connected'
        ];
    } catch (Exception $e) {
        $health['checks']['redis'] = [
            'status' => 'warning',
            'message' => 'Not available'
        ];
    }
}

// ๋””์Šคํฌ ๊ณต๊ฐ„ ์ฒดํฌ
$disk_free = disk_free_space('/');
$disk_total = disk_total_space('/');
$disk_usage_percent = round((1 - $disk_free / $disk_total) * 100, 2);

if ($disk_usage_percent > 90) {
    $health['status'] = 'unhealthy';
    $health['checks']['disk'] = [
        'status' => 'critical',
        'usage' => $disk_usage_percent . '%'
    ];
    http_response_code(503);
} else {
    $health['checks']['disk'] = [
        'status' => 'ok',
        'usage' => $disk_usage_percent . '%'
    ];
}

echo json_encode($health, JSON_PRETTY_PRINT);
?>

์ด ํ—ฌ์Šค ์ฒดํฌ ํŒŒ์ผ์€ ๋‹จ์ˆœํžˆ "์‚ด์•„์žˆ์–ด์š”!"๋งŒ ์•Œ๋ ค์ฃผ๋Š” ๊ฒŒ ์•„๋‹ˆ๋ผ, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ, ๋ฉ”๋ชจ๋ฆฌ ์ƒํƒœ, ๋””์Šคํฌ ๊ณต๊ฐ„๊นŒ์ง€ ์ฒดํฌํ•ด์„œ ์ง„์งœ ์„œ๋น„์Šค๊ฐ€ ๊ฐ€๋Šฅํ•œ ์ƒํƒœ์ธ์ง€ ํ™•์ธํ•ด์ค˜! ๐Ÿ”

๋งŒ์•ฝ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ์ด ๋Š์–ด์กŒ๋‹ค๋ฉด HTTP 503 ์ƒํƒœ ์ฝ”๋“œ๋ฅผ ๋ฐ˜ํ™˜ํ•ด์„œ HAProxy๊ฐ€ ํ•ด๋‹น ์„œ๋ฒ„๋ฅผ ์ž๋™์œผ๋กœ ์ œ์™ธ์‹œํ‚ค๊ฒŒ ๋งŒ๋“œ๋Š” ๊ฑฐ์ง€. ๋˜‘๋˜‘ํ•˜์ง€? ๐Ÿง 

๐ŸŽ›๏ธ ๋กœ๋“œ ๋ฐธ๋Ÿฐ์‹ฑ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ์„ ํƒ

HAProxy๋Š” ๋‹ค์–‘ํ•œ ๋กœ๋“œ ๋ฐธ๋Ÿฐ์‹ฑ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์ œ๊ณตํ•ด. ์ƒํ™ฉ์— ๋งž๋Š” ๊ฑธ ์„ ํƒํ•˜๋Š” ๊ฒŒ ์ค‘์š”ํ•ด! ๐ŸŽฒ

์ฃผ์š” ์•Œ๊ณ ๋ฆฌ์ฆ˜๋“ค:

1๏ธโƒฃ roundrobin (๋ผ์šด๋“œ๋กœ๋นˆ)
๊ฐ€์žฅ ๊ธฐ๋ณธ์ ์ธ ๋ฐฉ์‹. ์„œ๋ฒ„๋“ค์„ ์ˆœ์„œ๋Œ€๋กœ ๋Œ์•„๊ฐ€๋ฉด์„œ ์š”์ฒญ์„ ๋ถ„๋ฐฐํ•ด.

backend php_backend
    balance roundrobin
    server php1 192.168.1.10:80 check
    server php2 192.168.1.11:80 check

์žฅ์ : ๊ฐ„๋‹จํ•˜๊ณ  ๊ณตํ‰ํ•จ
๋‹จ์ : ์„œ๋ฒ„ ์„ฑ๋Šฅ ์ฐจ์ด๋ฅผ ๊ณ ๋ คํ•˜์ง€ ์•Š์Œ
์ถ”์ฒœ ์ƒํ™ฉ: ๋ชจ๋“  ์„œ๋ฒ„ ์ŠคํŽ™์ด ๋™์ผํ•  ๋•Œ

2๏ธโƒฃ leastconn (์ตœ์†Œ ์—ฐ๊ฒฐ)
ํ˜„์žฌ ์—ฐ๊ฒฐ ์ˆ˜๊ฐ€ ๊ฐ€์žฅ ์ ์€ ์„œ๋ฒ„๋กœ ์š”์ฒญ์„ ๋ณด๋‚ด.

backend php_backend
    balance leastconn
    server php1 192.168.1.10:80 check
    server php2 192.168.1.11:80 check

์žฅ์ : ์„œ๋ฒ„ ๋ถ€ํ•˜๋ฅผ ์‹ค์‹œ๊ฐ„์œผ๋กœ ๊ณ ๋ ค
๋‹จ์ : ์•ฝ๊ฐ„์˜ ์˜ค๋ฒ„ํ—ค๋“œ ๋ฐœ์ƒ
์ถ”์ฒœ ์ƒํ™ฉ: ์š”์ฒญ ์ฒ˜๋ฆฌ ์‹œ๊ฐ„์ด ๋“ค์ญ‰๋‚ ์ญ‰ํ•  ๋•Œ

3๏ธโƒฃ source (์†Œ์Šค IP ํ•ด์‹ฑ)
ํด๋ผ์ด์–ธํŠธ IP๋ฅผ ๊ธฐ์ค€์œผ๋กœ ํ•ญ์ƒ ๊ฐ™์€ ์„œ๋ฒ„๋กœ ์—ฐ๊ฒฐํ•ด.

backend php_backend
    balance source
    hash-type consistent
    server php1 192.168.1.10:80 check
    server php2 192.168.1.11:80 check

์žฅ์ : ์„ธ์…˜ ์œ ์ง€๊ฐ€ ์ž๋™์œผ๋กœ ๋จ
๋‹จ์ : ํŠน์ • ์„œ๋ฒ„์— ๋ถ€ํ•˜๊ฐ€ ๋ชฐ๋ฆด ์ˆ˜ ์žˆ์Œ
์ถ”์ฒœ ์ƒํ™ฉ: ์„ธ์…˜ ๊ณต์œ ๊ฐ€ ์–ด๋ ค์šด ๋ ˆ๊ฑฐ์‹œ ์‹œ์Šคํ…œ

4๏ธโƒฃ uri (URI ํ•ด์‹ฑ)
์š”์ฒญ URL์„ ๊ธฐ์ค€์œผ๋กœ ์„œ๋ฒ„๋ฅผ ์„ ํƒํ•ด.

backend php_backend
    balance uri
    hash-type consistent
    server php1 192.168.1.10:80 check
    server php2 192.168.1.11:80 check

์žฅ์ : ์บ์‹œ ํšจ์œจ์ด ๋†’์•„์ง
๋‹จ์ : ํŠน์ • URL์— ํŠธ๋ž˜ํ”ฝ์ด ๋ชฐ๋ฆฌ๋ฉด ๋ถˆ๊ท ํ˜•
์ถ”์ฒœ ์ƒํ™ฉ: ์ •์  ํŒŒ์ผ ์„œ๋น™์ด๋‚˜ ์บ์‹œ ์„œ๋ฒ„ ๊ตฌ์„ฑ

5๏ธโƒฃ ๊ฐ€์ค‘์น˜ ๊ธฐ๋ฐ˜ ๋ถ„๋ฐฐ
์„œ๋ฒ„ ์„ฑ๋Šฅ์— ๋”ฐ๋ผ ๊ฐ€์ค‘์น˜๋ฅผ ์ค„ ์ˆ˜ ์žˆ์–ด!

backend php_backend
    balance roundrobin
    server php1 192.168.1.10:80 check weight 100
    server php2 192.168.1.11:80 check weight 50
    server php3 192.168.1.12:80 check weight 150

์ด ๊ฒฝ์šฐ php3๊ฐ€ ๊ฐ€์žฅ ๋งŽ์€ ์š”์ฒญ์„ ๋ฐ›๊ณ , php2๊ฐ€ ๊ฐ€์žฅ ์ ๊ฒŒ ๋ฐ›์•„. ์„œ๋ฒ„ ์ŠคํŽ™์ด ๋‹ค๋ฅผ ๋•Œ ์œ ์šฉํ•˜์ง€! ๐Ÿ’ช
โš ๏ธ ์ฃผ์˜์‚ฌํ•ญ

์„ธ์…˜ ๊ธฐ๋ฐ˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ๋Š” source ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜, Redis ๊ฐ™์€ ์ค‘์•™ ์„ธ์…˜ ์ €์žฅ์†Œ๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•ด. ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ์‚ฌ์šฉ์ž๊ฐ€ ๋กœ๊ทธ์ธํ–ˆ๋‹ค๊ฐ€ ๋‹ค๋ฅธ ์„œ๋ฒ„๋กœ ์—ฐ๊ฒฐ๋˜๋ฉด์„œ ๋กœ๊ทธ์•„์›ƒ๋˜๋Š” ํ™ฉ๋‹นํ•œ ์ƒํ™ฉ์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์–ด! ๐Ÿ˜ฑ

๐Ÿ” ์„ธ์…˜ ๊ด€๋ฆฌ ์ „๋žต

๊ณ ๊ฐ€์šฉ์„ฑ ํ™˜๊ฒฝ์—์„œ ๊ฐ€์žฅ ๊นŒ๋‹ค๋กœ์šด ๋ถ€๋ถ„์ด ๋ฐ”๋กœ ์„ธ์…˜ ๊ด€๋ฆฌ์•ผ. ๐ŸŽญ
์‚ฌ์šฉ์ž๊ฐ€ ์„œ๋ฒ„ A์— ๋กœ๊ทธ์ธํ–ˆ๋Š”๋ฐ, ๋‹ค์Œ ์š”์ฒญ์ด ์„œ๋ฒ„ B๋กœ ๊ฐ€๋ฉด? ์„ธ์…˜ ์ •๋ณด๊ฐ€ ์—†์–ด์„œ ๋กœ๊ทธ์•„์›ƒ๋˜๋Š” ๊ฑฐ์ง€!

ํ•ด๊ฒฐ ๋ฐฉ๋ฒ• 3๊ฐ€์ง€:

๋ฐฉ๋ฒ• 1: Sticky Session (์„ธ์…˜ ๊ณ ์ •)

HAProxy ์„ค์ •์— ์ฟ ํ‚ค ๊ธฐ๋ฐ˜ ์„ธ์…˜ ๊ณ ์ •์„ ์ถ”๊ฐ€ํ•ด:

backend php_backend
    balance roundrobin
    cookie SERVERID insert indirect nocache
    server php1 192.168.1.10:80 check cookie php1
    server php2 192.168.1.11:80 check cookie php2
    server php3 192.168.1.12:80 check cookie php3

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด HAProxy๊ฐ€ ์ž๋™์œผ๋กœ ์ฟ ํ‚ค๋ฅผ ์‹ฌ์–ด์„œ ๊ฐ™์€ ์‚ฌ์šฉ์ž๋Š” ํ•ญ์ƒ ๊ฐ™์€ ์„œ๋ฒ„๋กœ ์—ฐ๊ฒฐ๋ผ!

์žฅ์ : ์„ค์ •์ด ๊ฐ„๋‹จํ•จ, ๊ธฐ์กด ์ฝ”๋“œ ์ˆ˜์ • ๋ถˆํ•„์š”
๋‹จ์ : ์„œ๋ฒ„๊ฐ€ ๋‹ค์šด๋˜๋ฉด ์„ธ์…˜ ์†์‹ค, ๋ถ€ํ•˜ ๋ถ„์‚ฐ์ด ์™„๋ฒฝํ•˜์ง€ ์•Š์Œ

๋ฐฉ๋ฒ• 2: Redis๋ฅผ ์ด์šฉํ•œ ์ค‘์•™ ์„ธ์…˜ ์ €์žฅ์†Œ

์ด๊ฒŒ ์ง„์งœ ํ”„๋กœ๋“ค์ด ์“ฐ๋Š” ๋ฐฉ๋ฒ•์ด์•ผ! ๐Ÿ†

๋จผ์ € Redis๋ฅผ ์„ค์น˜ํ•˜๊ณ :

sudo apt install redis-server -y
sudo systemctl start redis
sudo systemctl enable redis

PHP์—์„œ Redis๋ฅผ ์„ธ์…˜ ํ•ธ๋“ค๋Ÿฌ๋กœ ์„ค์ •:

<?php
// php.ini ํŒŒ์ผ ์ˆ˜์ •
// session.save_handler = redis
// session.save_path = "tcp://192.168.1.30:6379"

// ๋˜๋Š” ์ฝ”๋“œ์—์„œ ์ง์ ‘ ์„ค์ •
ini_set('session.save_handler', 'redis');
ini_set('session.save_path', 'tcp://192.168.1.30:6379');

session_start();
$_SESSION['user_id'] = 12345;
?>

์žฅ์ : ์™„๋ฒฝํ•œ ์„ธ์…˜ ๊ณต์œ , ์„œ๋ฒ„ ๋‹ค์šด๋˜์–ด๋„ ์„ธ์…˜ ์œ ์ง€
๋‹จ์ : Redis ์„œ๋ฒ„๊ฐ€ SPOF(๋‹จ์ผ ์žฅ์• ์ )๊ฐ€ ๋  ์ˆ˜ ์žˆ์Œ

๋ฐฉ๋ฒ• 3: JWT ํ† ํฐ ๊ธฐ๋ฐ˜ ์ธ์ฆ

์š”์ฆ˜ ํŠธ๋ Œ๋“œ๋Š” ์„œ๋ฒ„์— ์„ธ์…˜์„ ์ €์žฅํ•˜์ง€ ์•Š๋Š” ๊ฑฐ์•ผ! ๐Ÿ˜Ž

<?php
// JWT ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์‚ฌ์šฉ (composer require firebase/php-jwt)
use Firebase\JWT\JWT;
use Firebase\JWT\Key;

// ๋กœ๊ทธ์ธ ์‹œ ํ† ํฐ ๋ฐœ๊ธ‰
function generateToken($userId) {
    $secret_key = "your-secret-key-here";
    $payload = [
        'user_id' => $userId,
        'exp' => time() + 3600, // 1์‹œ๊ฐ„ ์œ ํšจ
        'iat' => time()
    ];
    
    return JWT::encode($payload, $secret_key, 'HS256');
}

// ํ† ํฐ ๊ฒ€์ฆ
function verifyToken($token) {
    $secret_key = "your-secret-key-here";
    try {
        $decoded = JWT::decode($token, new Key($secret_key, 'HS256'));
        return $decoded;
    } catch (Exception $e) {
        return false;
    }
}

// ์‚ฌ์šฉ ์˜ˆ์‹œ
$token = generateToken(12345);
// ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ํ† ํฐ ์ „๋‹ฌ (์ฟ ํ‚ค ๋˜๋Š” ํ—ค๋”)

// ๋‹ค์Œ ์š”์ฒญ์—์„œ ํ† ํฐ ๊ฒ€์ฆ
$user_data = verifyToken($_COOKIE['auth_token']);
if ($user_data) {
    echo "Welcome, User ID: " . $user_data->user_id;
}
?>

์žฅ์ : ์„œ๋ฒ„ ๋ถ€๋‹ด ์—†์Œ, ํ™•์žฅ์„ฑ ์ตœ๊ณ 
๋‹จ์ : ํ† ํฐ ๋ฌดํšจํ™”๊ฐ€ ์–ด๋ ค์›€, ๋ณด์•ˆ ๊ด€๋ฆฌ ์ค‘์š”

๊ฐœ์ธ์ ์œผ๋กœ๋Š” Redis ๋ฐฉ์‹์„ ์ถ”์ฒœํ•ด! ์•ˆ์ •์ ์ด๊ณ  ๊ด€๋ฆฌํ•˜๊ธฐ๋„ ํŽธํ•˜๊ฑฐ๋“ . ๐ŸŽฏ
์„ธ์…˜ ๊ด€๋ฆฌ ์•„ํ‚คํ…์ฒ˜ PHP Server 1 PHP Server 2 PHP Server 3 Redis ์ค‘์•™ ์„ธ์…˜ ์ €์žฅ์†Œ ์„ธ์…˜ ์ฝ๊ธฐ/์“ฐ๊ธฐ ์„ธ์…˜ ์ฝ๊ธฐ/์“ฐ๊ธฐ ์„ธ์…˜ ์ฝ๊ธฐ/์“ฐ๊ธฐ โœ“ ๋ชจ๋“  ์„œ๋ฒ„๊ฐ€ ์„ธ์…˜ ๊ณต์œ  โœ“ ์„œ๋ฒ„ ์žฅ์• ์‹œ์—๋„ ์„ธ์…˜ ์œ ์ง€

๐Ÿš€ PHP-FPM ์ตœ์ ํ™”

HAProxy๋งŒ ์ž˜ ์„ค์ •ํ•œ๋‹ค๊ณ  ๋์ด ์•„๋‹ˆ์•ผ! PHP-FPM๋„ ์ œ๋Œ€๋กœ ํŠœ๋‹ํ•ด์•ผ ์ง„์งœ ๊ณ ์„ฑ๋Šฅ ์‹œ์Šคํ…œ์ด ์™„์„ฑ๋ผ. ๐Ÿ’จ

PHP-FPM ์„ค์ • ํŒŒ์ผ ์œ„์น˜:
/etc/php/8.2/fpm/pool.d/www.conf (๋ฒ„์ „์— ๋”ฐ๋ผ ๋‹ค๋ฅผ ์ˆ˜ ์žˆ์Œ)

ํ•ต์‹ฌ ์„ค์ • ํ•ญ๋ชฉ๋“ค:

[www]
; ํ”„๋กœ์„ธ์Šค ๊ด€๋ฆฌ ๋ฐฉ์‹
pm = dynamic

; ์ตœ์†Œ ์œ ์ง€ ํ”„๋กœ์„ธ์Šค ์ˆ˜
pm.start_servers = 5

; ์ตœ์†Œ ๋Œ€๊ธฐ ํ”„๋กœ์„ธ์Šค ์ˆ˜
pm.min_spare_servers = 5

; ์ตœ๋Œ€ ๋Œ€๊ธฐ ํ”„๋กœ์„ธ์Šค ์ˆ˜
pm.max_spare_servers = 10

; ์ตœ๋Œ€ ํ”„๋กœ์„ธ์Šค ์ˆ˜ (์ค‘์š”!)
pm.max_children = 50

; ๊ฐ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์ฒ˜๋ฆฌํ•  ์ตœ๋Œ€ ์š”์ฒญ ์ˆ˜
pm.max_requests = 500

; ํ”„๋กœ์„ธ์Šค ์šฐ์„ ์ˆœ์œ„
process_priority = -10

; ๋А๋ฆฐ ์š”์ฒญ ๋กœ๊น…
request_slowlog_timeout = 5s
slowlog = /var/log/php-fpm/slow.log

; ํƒ€์ž„์•„์›ƒ ์„ค์ •
request_terminate_timeout = 30s

pm.max_children ๊ณ„์‚ฐ ๊ณต์‹:

์„œ๋ฒ„ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ 8GB์ด๊ณ , PHP ํ”„๋กœ์„ธ์Šค ํ•˜๋‚˜๊ฐ€ ํ‰๊ท  50MB๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด:

pm.max_children = (8GB - 2GB) / 50MB = 120

2GB๋Š” OS์™€ ๋‹ค๋ฅธ ํ”„๋กœ์„ธ์Šค๋ฅผ ์œ„ํ•ด ๋‚จ๊ฒจ๋‘๋Š” ๊ฑฐ์•ผ. ๋„ˆ๋ฌด ๋นก๋นกํ•˜๊ฒŒ ์„ค์ •ํ•˜๋ฉด OOM(Out of Memory) ํ‚ฌ๋Ÿฌ๊ฐ€ ํ”„๋กœ์„ธ์Šค๋ฅผ ์ฃฝ์ผ ์ˆ˜ ์žˆ์–ด! ๐Ÿ’€

์„ฑ๋Šฅ ๋ชจ๋‹ˆํ„ฐ๋ง ํ™œ์„ฑํ™”:

; PHP-FPM ์ƒํƒœ ํŽ˜์ด์ง€ ํ™œ์„ฑํ™”
pm.status_path = /fpm-status

; Ping ํŽ˜์ด์ง€ ํ™œ์„ฑํ™”
ping.path = /fpm-ping
ping.response = pong

Nginx ์„ค์ •์—์„œ ์ด ๊ฒฝ๋กœ๋“ค์„ ์ถ”๊ฐ€ํ•˜๋ฉด ์‹ค์‹œ๊ฐ„์œผ๋กœ PHP-FPM ์ƒํƒœ๋ฅผ ๋ชจ๋‹ˆํ„ฐ๋งํ•  ์ˆ˜ ์žˆ์–ด:

location ~ ^/(fpm-status|fpm-ping)$ {
    access_log off;
    allow 127.0.0.1;
    deny all;
    include fastcgi_params;
    fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;
}

๊ทธ๋Ÿผ http://your-server/fpm-status๋กœ ์ ‘์†ํ•˜๋ฉด ํ˜„์žฌ ์ƒํƒœ๋ฅผ ๋ณผ ์ˆ˜ ์žˆ์ง€! ๐Ÿ“Š

๐Ÿ“Š ๋ชจ๋‹ˆํ„ฐ๋ง ๋ฐ ๋กœ๊น…

์‹œ์Šคํ…œ์„ ๊ตฌ์ถ•ํ–ˆ์œผ๋ฉด ์ด์ œ ์ œ๋Œ€๋กœ ๋Œ์•„๊ฐ€๋Š”์ง€ ๊ฐ์‹œํ•ด์•ผ์ง€! ๐Ÿ‘€

1. HAProxy ํ†ต๊ณ„ ํŽ˜์ด์ง€

์•„๊นŒ ์„ค์ •ํ•œ stats ํŽ˜์ด์ง€๋ฅผ ํ™œ์„ฑํ™”ํ–ˆ๋‹ค๋ฉด, http://your-server:8080/haproxy-stats๋กœ ์ ‘์†ํ•ด๋ด!

์—ฌ๊ธฐ์„œ ๋ณผ ์ˆ˜ ์žˆ๋Š” ์ •๋ณด๋“ค:

โœ… ๊ฐ ์„œ๋ฒ„์˜ ์ƒํƒœ (UP/DOWN)
โœ… ํ˜„์žฌ ์„ธ์…˜ ์ˆ˜
โœ… ์ด ์ฒ˜๋ฆฌํ•œ ์š”์ฒญ ์ˆ˜
โœ… ์‘๋‹ต ์‹œ๊ฐ„
โœ… ์—๋Ÿฌ ๋ฐœ์ƒ ํšŸ์ˆ˜
โœ… ์„œ๋ฒ„๋ณ„ ํŠธ๋ž˜ํ”ฝ ๋ถ„๋ฐฐ ๋น„์œจ

์‹ค์‹œ๊ฐ„์œผ๋กœ ์„œ๋ฒ„ ์ƒํƒœ๋ฅผ ํ•œ๋ˆˆ์— ๋ณผ ์ˆ˜ ์žˆ์–ด์„œ ์ •๋ง ์œ ์šฉํ•ด! ๐ŸŽฏ

2. ๋กœ๊ทธ ๋ถ„์„

HAProxy ๋กœ๊ทธ๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ syslog๋กœ ์ „์†ก๋ผ. /var/log/haproxy.log ํŒŒ์ผ์„ ํ™•์ธํ•ด๋ด:

# ์‹ค์‹œ๊ฐ„ ๋กœ๊ทธ ํ™•์ธ
sudo tail -f /var/log/haproxy.log

# ์—๋Ÿฌ๋งŒ ํ•„ํ„ฐ๋ง
sudo grep "error" /var/log/haproxy.log

# ํŠน์ • IP์˜ ์š”์ฒญ ์ถ”์ 
sudo grep "192.168.1.100" /var/log/haproxy.log

3. ์ปค์Šคํ…€ ๋กœ๊ทธ ํฌ๋งท

๋” ์ž์„ธํ•œ ์ •๋ณด๋ฅผ ๋กœ๊น…ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ์ปค์Šคํ…€ ๋กœ๊ทธ ํฌ๋งท์„ ๋งŒ๋“ค์–ด:

defaults
    log-format "%ci:%cp [%tr] %ft %b/%s %TR/%Tw/%Tc/%Tr/%Ta %ST %B %CC %CS %tsc %ac/%fc/%bc/%sc/%rc %sq/%bq %hr %hs %{+Q}r"

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ํด๋ผ์ด์–ธํŠธ IP, ํฌํŠธ, ํƒ€์ด๋ฐ ์ •๋ณด, ์ฟ ํ‚ค, ํ—ค๋” ๋“ฑ ๋ชจ๋“  ์ •๋ณด๋ฅผ ๋กœ๊น…ํ•  ์ˆ˜ ์žˆ์–ด!

4. ์™ธ๋ถ€ ๋ชจ๋‹ˆํ„ฐ๋ง ๋„๊ตฌ ์—ฐ๋™

ํ”„๋กœ๋•์…˜ ํ™˜๊ฒฝ์—์„œ๋Š” ์ „๋ฌธ ๋ชจ๋‹ˆํ„ฐ๋ง ๋„๊ตฌ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒŒ ์ข‹์•„:

๐Ÿ”น Prometheus + Grafana: ์˜คํ”ˆ์†Œ์Šค ๋ชจ๋‹ˆํ„ฐ๋ง ์Šคํƒ
๐Ÿ”น Datadog: ํด๋ผ์šฐ๋“œ ๊ธฐ๋ฐ˜ ๋ชจ๋‹ˆํ„ฐ๋ง ์„œ๋น„์Šค
๐Ÿ”น New Relic: APM(Application Performance Monitoring)
๐Ÿ”น Zabbix: ์—”ํ„ฐํ”„๋ผ์ด์ฆˆ๊ธ‰ ๋ชจ๋‹ˆํ„ฐ๋ง

HAProxy๋Š” Prometheus ๋ฉ”ํŠธ๋ฆญ์„ ๊ธฐ๋ณธ ์ง€์›ํ•ด์„œ ์—ฐ๋™์ด ์‰ฌ์›Œ:

frontend stats
    bind *:8404
    http-request use-service prometheus-exporter if { path /metrics }
    stats enable
    stats uri /stats
    stats refresh 10s

์ด์ œ Prometheus๊ฐ€ http://your-server:8404/metrics์—์„œ ๋ฉ”ํŠธ๋ฆญ์„ ์ˆ˜์ง‘ํ•  ์ˆ˜ ์žˆ์–ด! ๐Ÿ“ˆ
๐Ÿ’ก ์žฌ๋Šฅ๋„ท์—์„œ ์ „๋ฌธ๊ฐ€ ์ฐพ๊ธฐ

๋ชจ๋‹ˆํ„ฐ๋ง ์‹œ์Šคํ…œ ๊ตฌ์ถ•์ด ๋ณต์žกํ•˜๊ฒŒ ๋А๊ปด์ง„๋‹ค๋ฉด? ์žฌ๋Šฅ๋„ท์—์„œ DevOps ์ „๋ฌธ๊ฐ€๋ฅผ ์ฐพ์•„๋ณด๋Š” ๊ฒƒ๋„ ์ข‹์€ ์„ ํƒ์ด์•ผ! Prometheus, Grafana ๋Œ€์‹œ๋ณด๋“œ ๊ตฌ์ถ•๋ถ€ํ„ฐ ์•Œ๋ฆผ ์„ค์ •๊นŒ์ง€ ์ „๋ฌธ๊ฐ€์˜ ๋„์›€์„ ๋ฐ›์œผ๋ฉด ํ›จ์”ฌ ๋น ๋ฅด๊ณ  ์•ˆ์ •์ ์œผ๋กœ ์‹œ์Šคํ…œ์„ ๊ตฌ์ถ•ํ•  ์ˆ˜ ์žˆ์–ด. ๐ŸŽจ

๐Ÿ”’ ๋ณด์•ˆ ๊ฐ•ํ™” ์ „๋žต

๊ณ ๊ฐ€์šฉ์„ฑ๋„ ์ค‘์š”ํ•˜์ง€๋งŒ, ๋ณด์•ˆ์ด ๋šซ๋ฆฌ๋ฉด ๋ง์งฑ ๋„๋ฃจ๋ฌต์ด์•ผ! ๐Ÿ›ก๏ธ

1. SSL/TLS ์„ค์ •

HTTPS๋Š” ์ด์ œ ์„ ํƒ์ด ์•„๋‹ˆ๋ผ ํ•„์ˆ˜์•ผ! HAProxy์—์„œ SSL์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•:

frontend https_frontend
    bind *:443 ssl crt /etc/haproxy/certs/server.pem
    
    # HTTP๋ฅผ HTTPS๋กœ ๋ฆฌ๋‹ค์ด๋ ‰ํŠธ
    redirect scheme https code 301 if !{ ssl_fc }
    
    # ๋ณด์•ˆ ํ—ค๋” ์ถ”๊ฐ€
    http-response set-header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
    http-response set-header X-Frame-Options "SAMEORIGIN"
    http-response set-header X-Content-Type-Options "nosniff"
    http-response set-header X-XSS-Protection "1; mode=block"
    
    default_backend php_backend

SSL ์ธ์ฆ์„œ๋Š” Let's Encrypt๋กœ ๋ฌด๋ฃŒ๋กœ ๋ฐœ๊ธ‰๋ฐ›์„ ์ˆ˜ ์žˆ์–ด:

sudo apt install certbot -y
sudo certbot certonly --standalone -d yourdomain.com

# ์ธ์ฆ์„œ์™€ ํ‚ค๋ฅผ ํ•˜๋‚˜์˜ ํŒŒ์ผ๋กœ ํ•ฉ์น˜๊ธฐ
sudo cat /etc/letsencrypt/live/yourdomain.com/fullchain.pem \
     /etc/letsencrypt/live/yourdomain.com/privkey.pem \
     > /etc/haproxy/certs/server.pem

2. DDoS ๋ฐฉ์–ด

HAProxy์—๋Š” ๊ธฐ๋ณธ์ ์ธ DDoS ๋ฐฉ์–ด ๊ธฐ๋Šฅ์ด ์žˆ์–ด:

frontend php_frontend
    # ์—ฐ๊ฒฐ ์†๋„ ์ œํ•œ
    stick-table type ip size 100k expire 30s store conn_rate(3s)
    tcp-request connection track-sc0 src
    tcp-request connection reject if { sc_conn_rate(0) gt 20 }
    
    # ์š”์ฒญ ์†๋„ ์ œํ•œ
    stick-table type ip size 100k expire 30s store http_req_rate(10s)
    http-request track-sc1 src
    http-request deny if { sc_http_req_rate(1) gt 100 }
    
    # ๋™์‹œ ์—ฐ๊ฒฐ ์ˆ˜ ์ œํ•œ
    acl too_many_connections src_conn_cur gt 10
    http-request deny if too_many_connections

์ด ์„ค์ •์€:
- 3์ดˆ ๋™์•ˆ 20๊ฐœ ์ด์ƒ์˜ ์—ฐ๊ฒฐ ์‹œ๋„๋ฅผ ์ฐจ๋‹จ
- 10์ดˆ ๋™์•ˆ 100๊ฐœ ์ด์ƒ์˜ HTTP ์š”์ฒญ์„ ์ฐจ๋‹จ
- ๋™์‹œ ์—ฐ๊ฒฐ 10๊ฐœ ์ด์ƒ์„ ์ฐจ๋‹จ

3. IP ํ™”์ดํŠธ๋ฆฌ์ŠคํŠธ/๋ธ”๋ž™๋ฆฌ์ŠคํŠธ

ํŠน์ • IP๋งŒ ์ ‘๊ทผ์„ ํ—ˆ์šฉํ•˜๊ฑฐ๋‚˜ ์ฐจ๋‹จํ•  ์ˆ˜ ์žˆ์–ด:

frontend php_frontend
    # ACL ์ •์˜
    acl whitelist src 192.168.1.0/24 10.0.0.0/8
    acl blacklist src 1.2.3.4 5.6.7.8
    
    # ๋ธ”๋ž™๋ฆฌ์ŠคํŠธ ์ฐจ๋‹จ
    http-request deny if blacklist
    
    # ๊ด€๋ฆฌ์ž ํŽ˜์ด์ง€๋Š” ํ™”์ดํŠธ๋ฆฌ์ŠคํŠธ๋งŒ ํ—ˆ์šฉ
    acl is_admin path_beg /admin
    http-request deny if is_admin !whitelist

4. ๋ฐฑ์—”๋“œ ์„œ๋ฒ„ ๋ณดํ˜ธ

PHP ์„œ๋ฒ„๋“ค์€ ์™ธ๋ถ€์—์„œ ์ง์ ‘ ์ ‘๊ทผํ•  ์ˆ˜ ์—†๋„๋ก ๋ฐฉํ™”๋ฒฝ ์„ค์ •์„ ํ•ด์•ผ ํ•ด:

# UFW ๋ฐฉํ™”๋ฒฝ ์„ค์ • (Ubuntu)
sudo ufw default deny incoming
sudo ufw default allow outgoing

# HAProxy ์„œ๋ฒ„์—์„œ๋งŒ ์ ‘๊ทผ ํ—ˆ์šฉ
sudo ufw allow from 192.168.1.100 to any port 80
sudo ufw allow from 192.168.1.100 to any port 443

# SSH๋Š” ํŠน์ • IP์—์„œ๋งŒ ํ—ˆ์šฉ
sudo ufw allow from 203.0.113.0/24 to any port 22

sudo ufw enable

5. ์ •๊ธฐ์ ์ธ ๋ณด์•ˆ ์—…๋ฐ์ดํŠธ

# ์ž๋™ ๋ณด์•ˆ ์—…๋ฐ์ดํŠธ ์„ค์ •
sudo apt install unattended-upgrades -y
sudo dpkg-reconfigure -plow unattended-upgrades

# ์ˆ˜๋™ ์—…๋ฐ์ดํŠธ
sudo apt update
sudo apt upgrade -y
sudo systemctl restart haproxy
sudo systemctl restart php8.2-fpm

๋ณด์•ˆ์€ ํ•œ ๋ฒˆ ์„ค์ •ํ•˜๊ณ  ๋์ด ์•„๋‹ˆ์•ผ. ์ง€์†์ ์œผ๋กœ ๋ชจ๋‹ˆํ„ฐ๋งํ•˜๊ณ  ์—…๋ฐ์ดํŠธํ•ด์•ผ ํ•ด! ๐Ÿ”

๐Ÿงช ์žฅ์•  ์‹œ๋‚˜๋ฆฌ์˜ค ํ…Œ์ŠคํŠธ

์‹œ์Šคํ…œ์„ ๊ตฌ์ถ•ํ–ˆ์œผ๋ฉด ์ด์ œ ์ง„์งœ๋กœ ๊ณ ๊ฐ€์šฉ์„ฑ์ด ์ž‘๋™ํ•˜๋Š”์ง€ ํ…Œ์ŠคํŠธํ•ด๋ด์•ผ์ง€! ๐ŸŽฌ

ํ…Œ์ŠคํŠธ 1: ์„œ๋ฒ„ ํ•œ ๋Œ€ ๋‹ค์šด

PHP ์„œ๋ฒ„ ํ•˜๋‚˜๋ฅผ ๊ฐ•์ œ๋กœ ์ค‘๋‹จ์‹œ์ผœ๋ด:

# PHP Server 1์—์„œ ์‹คํ–‰
sudo systemctl stop nginx
sudo systemctl stop php8.2-fpm

๊ทธ๋ฆฌ๊ณ  HAProxy ํ†ต๊ณ„ ํŽ˜์ด์ง€๋ฅผ ํ™•์ธํ•ด๋ด. php1 ์„œ๋ฒ„๊ฐ€ ๋นจ๊ฐ„์ƒ‰์œผ๋กœ ํ‘œ์‹œ๋˜๊ณ , ํŠธ๋ž˜ํ”ฝ์ด ์ž๋™์œผ๋กœ php2์™€ php3๋กœ๋งŒ ๋ถ„์‚ฐ๋˜๋Š” ๊ฑธ ๋ณผ ์ˆ˜ ์žˆ์„ ๊ฑฐ์•ผ! โœ…

์‚ฌ์šฉ์ž ์ž…์žฅ์—์„œ๋Š” ์•„๋ฌด ๋ฌธ์ œ ์—†์ด ์„œ๋น„์Šค๊ฐ€ ๊ณ„์† ์ž‘๋™ํ•˜๋Š” ๊ฑฐ์ง€. ์ด๊ฒŒ ๋ฐ”๋กœ ๊ณ ๊ฐ€์šฉ์„ฑ์˜ ํž˜์ด์•ผ! ๐Ÿ’ช

ํ…Œ์ŠคํŠธ 2: ๋ถ€ํ•˜ ํ…Œ์ŠคํŠธ

Apache Bench๋‚˜ wrk ๊ฐ™์€ ๋„๊ตฌ๋กœ ๋ถ€ํ•˜ ํ…Œ์ŠคํŠธ๋ฅผ ํ•ด๋ด:

# Apache Bench ์„ค์น˜
sudo apt install apache2-utils -y

# ๋™์‹œ ์ ‘์† 100๋ช…, ์ด 10000๋ฒˆ ์š”์ฒญ
ab -n 10000 -c 100 http://your-server/

# wrk ์‚ฌ์šฉ (๋” ๊ฐ•๋ ฅํ•จ)
sudo apt install wrk -y
wrk -t12 -c400 -d30s http://your-server/

๊ฒฐ๊ณผ๋ฅผ ๋ณด๋ฉด์„œ ๋‹ค์Œ์„ ํ™•์ธํ•ด:

๐Ÿ“Œ ์ดˆ๋‹น ์ฒ˜๋ฆฌ ์š”์ฒญ ์ˆ˜ (Requests per second)
๐Ÿ“Œ ํ‰๊ท  ์‘๋‹ต ์‹œ๊ฐ„
๐Ÿ“Œ ์—๋Ÿฌ ๋ฐœ์ƒ๋ฅ 
๐Ÿ“Œ ๊ฐ ์„œ๋ฒ„์˜ ๋ถ€ํ•˜ ๋ถ„์‚ฐ ๋น„์œจ

ํ…Œ์ŠคํŠธ 3: ๋„คํŠธ์›Œํฌ ์ง€์—ฐ ์‹œ๋ฎฌ๋ ˆ์ด์…˜

tc ๋ช…๋ น์–ด๋กœ ๋„คํŠธ์›Œํฌ ์ง€์—ฐ์„ ์ธ์œ„์ ์œผ๋กœ ๋งŒ๋“ค์–ด๋ด:

# PHP Server 1์— 100ms ์ง€์—ฐ ์ถ”๊ฐ€
sudo tc qdisc add dev eth0 root netem delay 100ms

# ํ™•์ธ
ping 192.168.1.10

# ์ œ๊ฑฐ
sudo tc qdisc del dev eth0 root

HAProxy๊ฐ€ ๋А๋ฆฐ ์„œ๋ฒ„๋ฅผ ๊ฐ์ง€ํ•˜๊ณ  ๋‹ค๋ฅธ ์„œ๋ฒ„๋กœ ๋” ๋งŽ์€ ํŠธ๋ž˜ํ”ฝ์„ ๋ณด๋‚ด๋Š”์ง€ ํ™•์ธํ•ด๋ด!

ํ…Œ์ŠคํŠธ 4: ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ ๋Š๊น€

MySQL ์„œ๋ฒ„๋ฅผ ์ž ์‹œ ์ค‘๋‹จ์‹œ์ผœ๋ด:

sudo systemctl stop mysql

ํ—ฌ์Šค ์ฒดํฌ ํŒŒ์ผ์ด ์ œ๋Œ€๋กœ ์ž‘๋™ํ•œ๋‹ค๋ฉด, ๋ชจ๋“  PHP ์„œ๋ฒ„๊ฐ€ unhealthy ์ƒํƒœ๊ฐ€ ๋˜๋ฉด์„œ HAProxy๊ฐ€ 503 ์—๋Ÿฌ๋ฅผ ๋ฐ˜ํ™˜ํ•  ๊ฑฐ์•ผ.

MySQL์„ ๋‹ค์‹œ ์‹œ์ž‘ํ•˜๋ฉด:

sudo systemctl start mysql

๋ช‡ ์ดˆ ์•ˆ์— ์„œ๋ฒ„๋“ค์ด ์ž๋™์œผ๋กœ ๋ณต๊ตฌ๋˜๋Š” ๊ฑธ ๋ณผ ์ˆ˜ ์žˆ์–ด! ๐ŸŽ‰
๐Ÿ’š ํ…Œ์ŠคํŠธ ์ž๋™ํ™” ํŒ

์ด๋Ÿฐ ํ…Œ์ŠคํŠธ๋“ค์„ ์Šคํฌ๋ฆฝํŠธ๋กœ ๋งŒ๋“ค์–ด์„œ ์ •๊ธฐ์ ์œผ๋กœ ์‹คํ–‰ํ•˜๋ฉด ์ข‹์•„. Chaos Engineering์ด๋ผ๊ณ  ํ•ด์„œ, ์ผ๋ถ€๋Ÿฌ ์žฅ์• ๋ฅผ ์ผ์œผ์ผœ์„œ ์‹œ์Šคํ…œ์˜ ๋ณต์›๋ ฅ์„ ํ…Œ์ŠคํŠธํ•˜๋Š” ๋ฐฉ๋ฒ•๋ก ์ด์•ผ. Netflix์˜ Chaos Monkey๊ฐ€ ์œ ๋ช…ํ•˜์ง€! ๐Ÿ’

โšก ์„ฑ๋Šฅ ์ตœ์ ํ™” ๊ณ ๊ธ‰ ํŒ

๊ธฐ๋ณธ ์„ค์ •๋งŒ์œผ๋กœ๋„ ์ถฉ๋ถ„ํ•˜์ง€๋งŒ, ๋” ๋†’์€ ์„ฑ๋Šฅ์„ ์›ํ•œ๋‹ค๋ฉด ์ด๋Ÿฐ ๊ฒƒ๋“ค๋„ ์‹œ๋„ํ•ด๋ด! ๐Ÿš€

1. HTTP/2 ํ™œ์„ฑํ™”

HTTP/2๋Š” HTTP/1.1๋ณด๋‹ค ํ›จ์”ฌ ๋น ๋ฅด๊ณ  ํšจ์œจ์ ์ด์•ผ:

frontend https_frontend
    bind *:443 ssl crt /etc/haproxy/certs/server.pem alpn h2,http/1.1
    
    # HTTP/2 ์ตœ์ ํ™”
    tune.h2.initial-window-size 65535
    tune.h2.max-concurrent-streams 100

2. ์••์ถ• ํ™œ์„ฑํ™”

ํ…์ŠคํŠธ ๊ธฐ๋ฐ˜ ์ฝ˜ํ…์ธ ๋ฅผ ์••์ถ•ํ•˜๋ฉด ๋Œ€์—ญํญ์„ ํฌ๊ฒŒ ์ ˆ์•ฝํ•  ์ˆ˜ ์žˆ์–ด:

backend php_backend
    compression algo gzip
    compression type text/html text/plain text/css text/javascript application/javascript application/json

3. ์บ์‹ฑ ์ „๋žต

์ •์  ํŒŒ์ผ์€ HAProxy์—์„œ ์ง์ ‘ ์บ์‹ฑํ•  ์ˆ˜ ์žˆ์–ด:

frontend php_frontend
    # ์ •์  ํŒŒ์ผ ACL
    acl is_static path_end .jpg .jpeg .png .gif .css .js .ico .woff .woff2
    
    # ์ •์  ํŒŒ์ผ์€ ์บ์‹œ ๋ฐฑ์—”๋“œ๋กœ
    use_backend static_backend if is_static

backend static_backend
    balance roundrobin
    http-request cache-use static-cache
    http-response cache-store static-cache
    server static1 192.168.1.10:80 check
    server static2 192.168.1.11:80 check

cache static-cache
    total-max-size 256
    max-object-size 10000
    max-age 3600

4. ์ปค๋„ฅ์…˜ ํ’€๋ง

๋ฐฑ์—”๋“œ ์„œ๋ฒ„์™€์˜ ์—ฐ๊ฒฐ์„ ์žฌ์‚ฌ์šฉํ•˜๋ฉด ์„ฑ๋Šฅ์ด ํ–ฅ์ƒ๋ผ:

backend php_backend
    option http-keep-alive
    option prefer-last-server
    timeout http-keep-alive 10s
    
    # ์„œ๋ฒ„๋‹น ์ตœ๋Œ€ ์œ ์ง€ ์—ฐ๊ฒฐ ์ˆ˜
    server php1 192.168.1.10:80 check maxconn 100
    server php2 192.168.1.11:80 check maxconn 100

5. CPU ์นœํ™”์„ฑ ์„ค์ •

๋ฉ€ํ‹ฐ์ฝ”์–ด CPU๋ฅผ ํšจ์œจ์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๋ ค๋ฉด:

global
    # CPU ์ฝ”์–ด ์ˆ˜๋งŒํผ ํ”„๋กœ์„ธ์Šค ์ƒ์„ฑ
    nbproc 4
    
    # CPU ์นœํ™”์„ฑ ์„ค์ • (๊ฐ ํ”„๋กœ์„ธ์Šค๋ฅผ ํŠน์ • ์ฝ”์–ด์— ๋ฐ”์ธ๋”ฉ)
    cpu-map 1 0
    cpu-map 2 1
    cpu-map 3 2
    cpu-map 4 3

6. ๋ฒ„ํผ ํฌ๊ธฐ ์กฐ์ •

global
    tune.bufsize 32768
    tune.maxrewrite 8192
    tune.ssl.default-dh-param 2048

์ด๋Ÿฐ ์ตœ์ ํ™”๋“ค์„ ์ ์šฉํ•˜๋ฉด ์ฒ˜๋ฆฌ๋Ÿ‰์ด 30-50% ์ •๋„ ํ–ฅ์ƒ๋  ์ˆ˜ ์žˆ์–ด! ๐Ÿ“Š

๐Ÿ”„ ๋ฌด์ค‘๋‹จ ๋ฐฐํฌ ์ „๋žต

๊ณ ๊ฐ€์šฉ์„ฑ ์‹œ์Šคํ…œ์˜ ์ง„์งœ ์žฅ์ ์€ ์„œ๋น„์Šค ์ค‘๋‹จ ์—†์ด ์—…๋ฐ์ดํŠธํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฑฐ์•ผ! ๐ŸŽฏ

Rolling Update ๋ฐฉ์‹:

Step 1: HAProxy์—์„œ php1 ์„œ๋ฒ„๋ฅผ drain ๋ชจ๋“œ๋กœ ์ „ํ™˜

# HAProxy ์†Œ์ผ“ ๋ช…๋ น์–ด ์‚ฌ์šฉ
echo "set server php_backend/php1 state drain" | sudo socat stdio /var/run/haproxy.sock

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์ƒˆ๋กœ์šด ์—ฐ๊ฒฐ์€ ๋ฐ›์ง€ ์•Š์ง€๋งŒ, ๊ธฐ์กด ์—ฐ๊ฒฐ์€ ์™„๋ฃŒ๋  ๋•Œ๊นŒ์ง€ ์œ ์ง€๋ผ.

Step 2: ๋ชจ๋“  ์—ฐ๊ฒฐ์ด ์ข…๋ฃŒ๋  ๋•Œ๊นŒ์ง€ ๋Œ€๊ธฐ (๋ณดํ†ต 30์ดˆ~1๋ถ„)

# ์—ฐ๊ฒฐ ์ˆ˜ ํ™•์ธ
echo "show stat" | sudo socat stdio /var/run/haproxy.sock | grep php1

Step 3: php1 ์„œ๋ฒ„ ์—…๋ฐ์ดํŠธ

# PHP Server 1์—์„œ ์‹คํ–‰
git pull origin main
composer install --no-dev --optimize-autoloader
php artisan migrate --force
php artisan cache:clear
sudo systemctl restart php8.2-fpm

Step 4: ํ—ฌ์Šค ์ฒดํฌ ํ™•์ธ ํ›„ ์„œ๋ฒ„ ํ™œ์„ฑํ™”

# ์ˆ˜๋™์œผ๋กœ ํ™œ์„ฑํ™”
echo "set server php_backend/php1 state ready" | sudo socat stdio /var/run/haproxy.sock

# ๋˜๋Š” ์ž๋™์œผ๋กœ ํ—ฌ์Šค ์ฒดํฌ๊ฐ€ ํ†ต๊ณผ๋˜๋ฉด ํ™œ์„ฑํ™”๋จ

Step 5: php2, php3๋„ ๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ ์ˆœ์ฐจ์ ์œผ๋กœ ์—…๋ฐ์ดํŠธ

์ด ๊ณผ์ •์„ ์ž๋™ํ™”ํ•˜๋Š” ์Šคํฌ๋ฆฝํŠธ๋ฅผ ๋งŒ๋“ค๋ฉด ํŽธํ•ด:

#!/bin/bash

SERVERS=("php1" "php2" "php3")
BACKEND="php_backend"

for SERVER in "${SERVERS[@]}"; do
    echo "Updating $SERVER..."
    
    # Drain ๋ชจ๋“œ๋กœ ์ „ํ™˜
    echo "set server $BACKEND/$SERVER state drain" | socat stdio /var/run/haproxy.sock
    
    # 30์ดˆ ๋Œ€๊ธฐ
    sleep 30
    
    # ์„œ๋ฒ„ ์—…๋ฐ์ดํŠธ (SSH๋กœ ์›๊ฒฉ ์‹คํ–‰)
    ssh $SERVER "cd /var/www/html && git pull && composer install && php artisan migrate --force"
    
    # ์„œ๋น„์Šค ์žฌ์‹œ์ž‘
    ssh $SERVER "sudo systemctl restart php8.2-fpm"
    
    # 10์ดˆ ๋Œ€๊ธฐ (ํ—ฌ์Šค ์ฒดํฌ ํ†ต๊ณผ ๋Œ€๊ธฐ)
    sleep 10
    
    # Ready ์ƒํƒœ๋กœ ์ „ํ™˜
    echo "set server $BACKEND/$SERVER state ready" | socat stdio /var/run/haproxy.sock
    
    echo "$SERVER updated successfully!"
done

echo "All servers updated!"

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์‚ฌ์šฉ์ž๋Š” ์ „ํ˜€ ๋ˆˆ์น˜์ฑ„์ง€ ๋ชปํ•˜๊ณ  ์„œ๋น„์Šค๊ฐ€ ๊ณ„์† ๋Œ์•„๊ฐ€๋Š” ๊ฑฐ์ง€! ๐ŸŽ‰

๐ŸŒ ๋ฉ€ํ‹ฐ ๋ฐ์ดํ„ฐ์„ผํ„ฐ ๊ตฌ์„ฑ

์ง„์งœ ์—”ํ„ฐํ”„๋ผ์ด์ฆˆ๊ธ‰ ๊ณ ๊ฐ€์šฉ์„ฑ์„ ์›ํ•œ๋‹ค๋ฉด, ์—ฌ๋Ÿฌ ๋ฐ์ดํ„ฐ์„ผํ„ฐ์— ์„œ๋ฒ„๋ฅผ ๋ถ„์‚ฐ์‹œ์ผœ์•ผ ํ•ด! ๐Ÿ—บ๏ธ

์ง€๋ฆฌ์  ๋ถ„์‚ฐ ์•„ํ‚คํ…์ฒ˜:

๋ฐ์ดํ„ฐ์„ผํ„ฐ A (์„œ์šธ):
- HAProxy 1: 203.0.113.10
- PHP Servers: 3๋Œ€
- MySQL Master

๋ฐ์ดํ„ฐ์„ผํ„ฐ B (๋ถ€์‚ฐ):
- HAProxy 2: 203.0.113.20
- PHP Servers: 3๋Œ€
- MySQL Slave

๊ธ€๋กœ๋ฒŒ ๋กœ๋“œ ๋ฐธ๋Ÿฐ์„œ (DNS ๊ธฐ๋ฐ˜):

AWS Route 53์ด๋‚˜ Cloudflare ๊ฐ™์€ ์„œ๋น„์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ง€๋ฆฌ์ ์œผ๋กœ ๊ฐ€๊นŒ์šด ๋ฐ์ดํ„ฐ์„ผํ„ฐ๋กœ ์ž๋™ ๋ผ์šฐํŒ…ํ•  ์ˆ˜ ์žˆ์–ด:

# Route 53 Geolocation Routing ์˜ˆ์‹œ
- ํ•œ๊ตญ ์‚ฌ์šฉ์ž โ†’ ์„œ์šธ ๋ฐ์ดํ„ฐ์„ผํ„ฐ (203.0.113.10)
- ์ผ๋ณธ ์‚ฌ์šฉ์ž โ†’ ๋„์ฟ„ ๋ฐ์ดํ„ฐ์„ผํ„ฐ (203.0.113.30)
- ๊ธฐํƒ€ ์ง€์—ญ โ†’ ์„œ์šธ ๋ฐ์ดํ„ฐ์„ผํ„ฐ (๊ธฐ๋ณธ๊ฐ’)

๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋ณต์ œ:

MySQL Master-Slave ๋ณต์ œ๋ฅผ ์„ค์ •ํ•ด์„œ ๋ฐ์ดํ„ฐ ๋™๊ธฐํ™”:

# Master ์„œ๋ฒ„ (์„œ์šธ)
[mysqld]
server-id = 1
log_bin = /var/log/mysql/mysql-bin.log
binlog_do_db = myapp

# Slave ์„œ๋ฒ„ (๋ถ€์‚ฐ)
[mysqld]
server-id = 2
relay-log = /var/log/mysql/mysql-relay-bin.log
log_bin = /var/log/mysql/mysql-bin.log
read_only = 1

์ด๋ ‡๊ฒŒ ๊ตฌ์„ฑํ•˜๋ฉด:
โœ… ํ•œ ๋ฐ์ดํ„ฐ์„ผํ„ฐ๊ฐ€ ํ†ต์งธ๋กœ ๋‹ค์šด๋˜์–ด๋„ ์„œ๋น„์Šค ๊ณ„์† ๊ฐ€๋Šฅ
โœ… ์ง€์—ญ๋ณ„๋กœ ๋น ๋ฅธ ์‘๋‹ต ์†๋„
โœ… ์žฌํ•ด ๋ณต๊ตฌ(DR) ๋Œ€๋น„

๋ฌผ๋ก  ๋น„์šฉ์ด ๋งŽ์ด ๋“ค์ง€๋งŒ, ๋Œ€๊ทœ๋ชจ ์„œ๋น„์Šค์—์„œ๋Š” ํ•„์ˆ˜์•ผ! ๐Ÿ’ฐ
๋ฉ€ํ‹ฐ ๋ฐ์ดํ„ฐ์„ผํ„ฐ ์•„ํ‚คํ…์ฒ˜ ๋ฐ์ดํ„ฐ์„ผํ„ฐ A (์„œ์šธ) HAProxy 1 PHP Srv 1 PHP Srv 2 MySQL Master ๋ฐ์ดํ„ฐ์„ผํ„ฐ B (๋ถ€์‚ฐ) HAProxy 2 PHP Srv 3 PHP Srv 4 MySQL Slave DB ๋ณต์ œ Global DNS ์ง€๋ฆฌ์  ๋ผ์šฐํŒ… ๐Ÿ‘ค ์„œ์šธ ์‚ฌ์šฉ์ž ๐Ÿ‘ค ๋ถ€์‚ฐ ์‚ฌ์šฉ์ž

๐Ÿ› ํŠธ๋Ÿฌ๋ธ”์ŠˆํŒ… ๊ฐ€์ด๋“œ

์‹ค์ „์—์„œ ์ž์ฃผ ๋งŒ๋‚˜๋Š” ๋ฌธ์ œ๋“ค๊ณผ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์„ ์ •๋ฆฌํ•ด๋ดค์–ด! ๐Ÿ”ง

๋ฌธ์ œ 1: ํŠน์ • ์„œ๋ฒ„๋งŒ ๊ณ„์† DOWN ์ƒํƒœ

์ฆ์ƒ: HAProxy ํ†ต๊ณ„ ํŽ˜์ด์ง€์—์„œ ํ•œ ์„œ๋ฒ„๊ฐ€ ๋นจ๊ฐ„์ƒ‰์œผ๋กœ ํ‘œ์‹œ๋จ

์›์ธ:
- ํ—ฌ์Šค ์ฒดํฌ ํŒŒ์ผ์ด ์—†๊ฑฐ๋‚˜ ์—๋Ÿฌ ๋ฐœ์ƒ
- ๋ฐฉํ™”๋ฒฝ์ด HAProxy์˜ ์š”์ฒญ์„ ์ฐจ๋‹จ
- PHP-FPM์ด ์ฃฝ์–ด์žˆ์Œ

ํ•ด๊ฒฐ:

# 1. ํ—ฌ์Šค ์ฒดํฌ URL ์ง์ ‘ ํ…Œ์ŠคํŠธ
curl http://192.168.1.10/health.php

# 2. PHP-FPM ์ƒํƒœ ํ™•์ธ
sudo systemctl status php8.2-fpm

# 3. ๋กœ๊ทธ ํ™•์ธ
sudo tail -f /var/log/php8.2-fpm.log

# 4. ๋ฐฉํ™”๋ฒฝ ๊ทœ์น™ ํ™•์ธ
sudo ufw status

๋ฌธ์ œ 2: ์„ธ์…˜์ด ๊ณ„์† ๋Š๊น€

์ฆ์ƒ: ์‚ฌ์šฉ์ž๊ฐ€ ๋กœ๊ทธ์ธํ–ˆ๋‹ค๊ฐ€ ๋‹ค์Œ ํŽ˜์ด์ง€์—์„œ ๋กœ๊ทธ์•„์›ƒ๋จ

์›์ธ:
- Sticky Session์ด ์„ค์ •๋˜์ง€ ์•Š์Œ
- ์„ธ์…˜ ์ €์žฅ์†Œ๊ฐ€ ๊ฐ ์„œ๋ฒ„์˜ ๋กœ์ปฌ ํŒŒ์ผ์‹œ์Šคํ…œ

ํ•ด๊ฒฐ:

# HAProxy์— Sticky Session ์ถ”๊ฐ€
backend php_backend
    cookie SERVERID insert indirect nocache
    server php1 192.168.1.10:80 check cookie php1
    server php2 192.168.1.11:80 check cookie php2

# ๋˜๋Š” Redis ์„ธ์…˜ ์ €์žฅ์†Œ ์‚ฌ์šฉ
# php.ini
session.save_handler = redis
session.save_path = "tcp://192.168.1.30:6379"

๋ฌธ์ œ 3: 502 Bad Gateway ์—๋Ÿฌ

์ฆ์ƒ: ๊ฐ„ํ—์ ์œผ๋กœ 502 ์—๋Ÿฌ ๋ฐœ์ƒ

์›์ธ:
- PHP-FPM ํ”„๋กœ์„ธ์Šค ๋ถ€์กฑ
- ํƒ€์ž„์•„์›ƒ ์„ค์ •์ด ๋„ˆ๋ฌด ์งง์Œ
- ๋ฐฑ์—”๋“œ ์„œ๋ฒ„ ๊ณผ๋ถ€ํ•˜

ํ•ด๊ฒฐ:

# PHP-FPM ํ”„๋กœ์„ธ์Šค ์ˆ˜ ์ฆ๊ฐ€
# /etc/php/8.2/fpm/pool.d/www.conf
pm.max_children = 100

# HAProxy ํƒ€์ž„์•„์›ƒ ์ฆ๊ฐ€
timeout server 60s
timeout connect 10s

# ์„œ๋ฒ„ ์ถ”๊ฐ€ ๋˜๋Š” ์Šค์ผ€์ผ ์—…

๋ฌธ์ œ 4: ๋ฉ”๋ชจ๋ฆฌ ๋ถ€์กฑ (OOM Killer)

์ฆ์ƒ: ์„œ๋ฒ„๊ฐ€ ๊ฐ‘์ž๊ธฐ ์ฃฝ๊ณ  ๋กœ๊ทธ์— "Out of memory" ๋ฉ”์‹œ์ง€

์›์ธ:
- PHP-FPM ํ”„๋กœ์„ธ์Šค๊ฐ€ ๋„ˆ๋ฌด ๋งŽ์Œ
- ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜

ํ•ด๊ฒฐ:

# ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰ ๋ชจ๋‹ˆํ„ฐ๋ง
free -h
ps aux --sort=-%mem | head -10

# PHP-FPM ํ”„๋กœ์„ธ์Šค ์ˆ˜ ์กฐ์ •
pm.max_children = (์ด ๋ฉ”๋ชจ๋ฆฌ - 2GB) / ํ‰๊ท  ํ”„๋กœ์„ธ์Šค ๋ฉ”๋ชจ๋ฆฌ

# ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜ ์ฐพ๊ธฐ
php artisan route:cache
php artisan config:cache
composer dump-autoload --optimize

๋ฌธ์ œ 5: SSL ์ธ์ฆ์„œ ์—๋Ÿฌ

์ฆ์ƒ: HTTPS ์ ‘์† ์‹œ ์ธ์ฆ์„œ ๊ฒฝ๊ณ 

์›์ธ:
- ์ธ์ฆ์„œ ํŒŒ์ผ ๊ฒฝ๋กœ ์˜ค๋ฅ˜
- ์ธ์ฆ์„œ ๋งŒ๋ฃŒ
- ์ค‘๊ฐ„ ์ธ์ฆ์„œ ๋ˆ„๋ฝ

ํ•ด๊ฒฐ:

# ์ธ์ฆ์„œ ํ™•์ธ
openssl x509 -in /etc/haproxy/certs/server.pem -text -noout

# ์ธ์ฆ์„œ ๊ฐฑ์‹  (Let's Encrypt)
sudo certbot renew
sudo cat /etc/letsencrypt/live/yourdomain.com/fullchain.pem \
     /etc/letsencrypt/live/yourdomain.com/privkey.pem \
     > /etc/haproxy/certs/server.pem
sudo systemctl reload haproxy
โš ๏ธ ์ค‘์š”ํ•œ ํŒ

๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ๋‹นํ™ฉํ•˜์ง€ ๋ง๊ณ  ๋กœ๊ทธ๋ฅผ ๋จผ์ € ํ™•์ธํ•ด! HAProxy ๋กœ๊ทธ(/var/log/haproxy.log), PHP-FPM ๋กœ๊ทธ(/var/log/php-fpm/), ์‹œ์Šคํ…œ ๋กœ๊ทธ(/var/log/syslog)๋ฅผ ์ˆœ์„œ๋Œ€๋กœ ์ฒดํฌํ•˜๋ฉด ๋Œ€๋ถ€๋ถ„์˜ ๋ฌธ์ œ๋ฅผ ์ฐพ์„ ์ˆ˜ ์žˆ์–ด. ๐Ÿ”

๐Ÿ“š ์‹ค์ „ ์ฒดํฌ๋ฆฌ์ŠคํŠธ

๊ณ ๊ฐ€์šฉ์„ฑ ์›น ์„œ๋ฒ„๋ฅผ ํ”„๋กœ๋•์…˜์— ๋ฐฐํฌํ•˜๊ธฐ ์ „์— ๊ผญ ํ™•์ธํ•ด์•ผ ํ•  ํ•ญ๋ชฉ๋“ค์ด์•ผ! โœ…

๐Ÿ”น ์ธํ”„๋ผ ์ฒดํฌ๋ฆฌ์ŠคํŠธ

โ˜‘๏ธ HAProxy ์„œ๋ฒ„ ์ตœ์†Œ 2๋Œ€ ๊ตฌ์„ฑ (์ด์ค‘ํ™”)
โ˜‘๏ธ PHP ๋ฐฑ์—”๋“œ ์„œ๋ฒ„ ์ตœ์†Œ 3๋Œ€ ๊ตฌ์„ฑ
โ˜‘๏ธ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค Master-Slave ๋ณต์ œ ์„ค์ •
โ˜‘๏ธ Redis/Memcached ์„ธ์…˜ ์ €์žฅ์†Œ ๊ตฌ์„ฑ
โ˜‘๏ธ ๋ฐฑ์—… ์„œ๋ฒ„ ์ค€๋น„ (backup ์˜ต์…˜)
โ˜‘๏ธ ๋ชจ๋‹ˆํ„ฐ๋ง ์‹œ์Šคํ…œ ๊ตฌ์ถ•
โ˜‘๏ธ ๋กœ๊ทธ ์ˆ˜์ง‘ ๋ฐ ๋ถ„์„ ์‹œ์Šคํ…œ

๐Ÿ”น ๋ณด์•ˆ ์ฒดํฌ๋ฆฌ์ŠคํŠธ

โ˜‘๏ธ SSL/TLS ์ธ์ฆ์„œ ์„ค์น˜ ๋ฐ ์ž๋™ ๊ฐฑ์‹  ์„ค์ •
โ˜‘๏ธ ๋ฐฉํ™”๋ฒฝ ๊ทœ์น™ ์„ค์ • (UFW/iptables)
โ˜‘๏ธ DDoS ๋ฐฉ์–ด ์„ค์ •
โ˜‘๏ธ ๋ณด์•ˆ ํ—ค๋” ์ถ”๊ฐ€ (HSTS, X-Frame-Options ๋“ฑ)
โ˜‘๏ธ ๋ฐฑ์—”๋“œ ์„œ๋ฒ„ ์ง์ ‘ ์ ‘๊ทผ ์ฐจ๋‹จ
โ˜‘๏ธ SSH ํ‚ค ๊ธฐ๋ฐ˜ ์ธ์ฆ ์„ค์ •
โ˜‘๏ธ ์ •๊ธฐ์ ์ธ ๋ณด์•ˆ ์—…๋ฐ์ดํŠธ ์ž๋™ํ™”

๐Ÿ”น ์„ฑ๋Šฅ ์ฒดํฌ๋ฆฌ์ŠคํŠธ

โ˜‘๏ธ PHP-FPM ํ”„๋กœ์„ธ์Šค ์ˆ˜ ์ตœ์ ํ™”
โ˜‘๏ธ HAProxy ํƒ€์ž„์•„์›ƒ ์„ค์ • ์กฐ์ •
โ˜‘๏ธ HTTP/2 ํ™œ์„ฑํ™”
โ˜‘๏ธ Gzip ์••์ถ• ํ™œ์„ฑํ™”
โ˜‘๏ธ ์ •์  ํŒŒ์ผ ์บ์‹ฑ ์„ค์ •
โ˜‘๏ธ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ฟผ๋ฆฌ ์ตœ์ ํ™”
โ˜‘๏ธ OPcache ํ™œ์„ฑํ™”

๐Ÿ”น ๋ชจ๋‹ˆํ„ฐ๋ง ์ฒดํฌ๋ฆฌ์ŠคํŠธ

โ˜‘๏ธ HAProxy ํ†ต๊ณ„ ํŽ˜์ด์ง€ ํ™œ์„ฑํ™”
โ˜‘๏ธ ํ—ฌ์Šค ์ฒดํฌ ์—”๋“œํฌ์ธํŠธ ๊ตฌํ˜„
โ˜‘๏ธ ๋กœ๊ทธ ๋กœํ…Œ์ด์…˜ ์„ค์ •
โ˜‘๏ธ ์•Œ๋ฆผ ์‹œ์Šคํ…œ ๊ตฌ์ถ• (์ด๋ฉ”์ผ/Slack)
โ˜‘๏ธ ์„ฑ๋Šฅ ๋ฉ”ํŠธ๋ฆญ ์ˆ˜์ง‘ (Prometheus/Grafana)
โ˜‘๏ธ ์—๋Ÿฌ ์ถ”์  ์‹œ์Šคํ…œ (Sentry)
โ˜‘๏ธ ์—…ํƒ€์ž„ ๋ชจ๋‹ˆํ„ฐ๋ง (UptimeRobot)

๐Ÿ”น ์šด์˜ ์ฒดํฌ๋ฆฌ์ŠคํŠธ

โ˜‘๏ธ ๋ฌด์ค‘๋‹จ ๋ฐฐํฌ ์Šคํฌ๋ฆฝํŠธ ์ž‘์„ฑ
โ˜‘๏ธ ๋กค๋ฐฑ ์ ˆ์ฐจ ๋ฌธ์„œํ™”
โ˜‘๏ธ ์žฅ์•  ๋Œ€์‘ ๋งค๋‰ด์–ผ ์ž‘์„ฑ
โ˜‘๏ธ ์ •๊ธฐ ๋ฐฑ์—… ์ž๋™ํ™”
โ˜‘๏ธ ์žฌํ•ด ๋ณต๊ตฌ(DR) ๊ณ„ํš ์ˆ˜๋ฆฝ
โ˜‘๏ธ ๋ถ€ํ•˜ ํ…Œ์ŠคํŠธ ์ •๊ธฐ ์‹คํ–‰
โ˜‘๏ธ ์˜จ์ฝœ(On-call) ๋‹ด๋‹น์ž ์ง€์ •

์ด ์ฒดํฌ๋ฆฌ์ŠคํŠธ๋ฅผ ํ•˜๋‚˜์”ฉ ์ฒดํฌํ•˜๋ฉด์„œ ์ค€๋น„ํ•˜๋ฉด ์•ˆ์ •์ ์ธ ์„œ๋น„์Šค ์šด์˜์ด ๊ฐ€๋Šฅํ•ด! ๐Ÿ“‹

๐ŸŽ“ ํ•™์Šต ๋ฆฌ์†Œ์Šค ๋ฐ ๋‹ค์Œ ๋‹จ๊ณ„

์—ฌ๊ธฐ๊นŒ์ง€ ๋”ฐ๋ผ์™”๋‹ค๋ฉด ์ •๋ง ๋Œ€๋‹จํ•ด! ๐Ÿ‘
ํ•˜์ง€๋งŒ ๊ณ ๊ฐ€์šฉ์„ฑ ์‹œ์Šคํ…œ์€ ๋์—†์ด ๋ฐฐ์šฐ๊ณ  ๊ฐœ์„ ํ•ด์•ผ ํ•˜๋Š” ๋ถ„์•ผ์•ผ.

์ถ”์ฒœ ํ•™์Šต ์ž๋ฃŒ:

๐Ÿ“– ๊ณต์‹ ๋ฌธ์„œ
- HAProxy Documentation: https://www.haproxy.org/documentation.html
- PHP-FPM Configuration: https://www.php.net/manual/en/install.fpm.configuration.php

๐Ÿ“š ์ฑ…
- "Site Reliability Engineering" by Google
- "The Phoenix Project" (DevOps ์ฒ ํ•™)
- "Designing Data-Intensive Applications"

๐ŸŽฅ ์˜จ๋ผ์ธ ๊ฐ•์˜
- Udemy: "Load Balancing with HAProxy"
- Coursera: "Site Reliability Engineering"
- YouTube: HAProxy Technologies ์ฑ„๋„

๋‹ค์Œ ๋‹จ๊ณ„๋กœ ๋‚˜์•„๊ฐ€๊ธฐ:

๐Ÿš€ Level 2: ์ปจํ…Œ์ด๋„ˆํ™”
Docker์™€ Kubernetes๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๋” ์œ ์—ฐํ•œ ์ธํ”„๋ผ ๊ตฌ์ถ•

๐Ÿš€ Level 3: ํด๋ผ์šฐ๋“œ ๋„ค์ดํ‹ฐ๋ธŒ
AWS ELB, Google Cloud Load Balancer ๊ฐ™์€ ๊ด€๋ฆฌํ˜• ์„œ๋น„์Šค ํ™œ์šฉ

๐Ÿš€ Level 4: ๋งˆ์ดํฌ๋กœ์„œ๋น„์Šค
์„œ๋น„์Šค ๋ฉ”์‹œ(Service Mesh)์™€ API ๊ฒŒ์ดํŠธ์›จ์ด ๋„์ž…

๐Ÿš€ Level 5: ๊ธ€๋กœ๋ฒŒ ์Šค์ผ€์ผ
CDN, Edge Computing, Multi-Region ๋ฐฐํฌ

ํ•œ ๋‹จ๊ณ„์”ฉ ์ฐจ๊ทผ์ฐจ๊ทผ ์˜ฌ๋ผ๊ฐ€๋‹ค ๋ณด๋ฉด ์–ด๋А์ƒˆ ์‹œ๋‹ˆ์–ด ์—”์ง€๋‹ˆ์–ด๊ฐ€ ๋˜์–ด ์žˆ์„ ๊ฑฐ์•ผ! ๐Ÿ’ช

๐ŸŽฏ ๋งˆ๋ฌด๋ฆฌํ•˜๋ฉฐ

์ž, ์—ฌ๊ธฐ๊นŒ์ง€ PHP์™€ HAProxy๋ฅผ ์ด์šฉํ•œ ๊ณ ๊ฐ€์šฉ์„ฑ ์›น ์„œ๋ฒ„ ๊ตฌ์ถ•์— ๋Œ€ํ•ด ์•Œ์•„๋ดค์–ด! ๐ŸŽ‰

์ฒ˜์Œ์—๋Š” ๋ณต์žกํ•ด ๋ณด์˜€๊ฒ ์ง€๋งŒ, ํ•˜๋‚˜์”ฉ ๋”ฐ๋ผํ•˜๋‹ค ๋ณด๋ฉด ์ƒ๊ฐ๋ณด๋‹ค ์–ด๋ ต์ง€ ์•Š๋‹ค๋Š” ๊ฑธ ๋А๊ผˆ์„ ๊ฑฐ์•ผ.

ํ•ต์‹ฌ ์š”์•ฝ:

โœจ ๊ณ ๊ฐ€์šฉ์„ฑ์€ ์„œ๋ฒ„ ํ•˜๋‚˜๊ฐ€ ์ฃฝ์–ด๋„ ์„œ๋น„์Šค๊ฐ€ ๊ณ„์†๋˜๋Š” ๊ฒƒ
โœจ HAProxy๋Š” ๊ฐ•๋ ฅํ•˜๊ณ  ์œ ์—ฐํ•œ ์˜คํ”ˆ์†Œ์Šค ๋กœ๋“œ ๋ฐธ๋Ÿฐ์„œ
โœจ ํ—ฌ์Šค ์ฒดํฌ๋กœ ์ž๋™์œผ๋กœ ์žฅ์•  ์„œ๋ฒ„๋ฅผ ๊ฐ์ง€ํ•˜๊ณ  ์ œ์™ธ
โœจ ์„ธ์…˜ ๊ด€๋ฆฌ๋Š” Redis ๊ฐ™์€ ์ค‘์•™ ์ €์žฅ์†Œ ์‚ฌ์šฉ ์ถ”์ฒœ
โœจ ๋ฌด์ค‘๋‹จ ๋ฐฐํฌ๋กœ ์‚ฌ์šฉ์ž ๊ฒฝํ—˜ ์ €ํ•˜ ์—†์ด ์—…๋ฐ์ดํŠธ
โœจ ๋ชจ๋‹ˆํ„ฐ๋ง๊ณผ ๋กœ๊น…์€ ํ•„์ˆ˜!
โœจ ๋ณด์•ˆ์€ ์ฒ˜์Œ๋ถ€ํ„ฐ ๊ณ ๋ คํ•ด์•ผ ํ•จ

์ด์ œ ๋„ˆ๋„ 99.99% ๊ฐ€๋™๋ฅ ์„ ์ž๋ž‘ํ•˜๋Š” ์•ˆ์ •์ ์ธ ์„œ๋น„์Šค๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์–ด! ๐Ÿš€

๋ฌผ๋ก  ์‹ค์ „์—์„œ๋Š” ์˜ˆ์ƒ์น˜ ๋ชปํ•œ ๋ฌธ์ œ๋“ค์ด ๊ณ„์† ๋ฐœ์ƒํ•  ๊ฑฐ์•ผ. ํ•˜์ง€๋งŒ ๊ทธ๊ฒŒ ๋ฐ”๋กœ ์„ฑ์žฅ์˜ ๊ธฐํšŒ์ง€!
๋ฌธ์ œ๋ฅผ ํ•˜๋‚˜์”ฉ ํ•ด๊ฒฐํ•˜๋ฉด์„œ ์ง„์งœ ์‹ค๋ ฅ์ด ์Œ“์ด๋Š” ๊ฑฐ๋‹ˆ๊นŒ. ๐Ÿ’ช

ํ˜น์‹œ ํ˜ผ์ž ํ•˜๊ธฐ ์–ด๋ ต๊ฑฐ๋‚˜ ์ „๋ฌธ๊ฐ€์˜ ๋„์›€์ด ํ•„์š”ํ•˜๋‹ค๋ฉด, ์–ธ์ œ๋“  ์žฌ๋Šฅ๋„ท์—์„œ ๊ฒฝํ—˜ ๋งŽ์€ ๊ฐœ๋ฐœ์ž๋“ค์„ ์ฐพ์•„๋ด.
์‹ค๋ฌด ๊ฒฝํ—˜์ด ํ’๋ถ€ํ•œ ์ „๋ฌธ๊ฐ€๋“ค์ด ๋„ˆ์˜ ํ”„๋กœ์ ํŠธ๋ฅผ ์„ฑ๊ณต์œผ๋กœ ์ด๋Œ์–ด์ค„ ๊ฑฐ์•ผ! ๐ŸŽฏ

์ž, ์ด์ œ ์ง์ ‘ ์„œ๋ฒ„๋ฅผ ๊ตฌ์ถ•ํ•ด๋ณด๋ฉด์„œ ๋ฐฐ์šด ๋‚ด์šฉ์„ ์‹ค์ „์— ์ ์šฉํ•ด๋ด!
์ฒ˜์Œ์—๋Š” ํ…Œ์ŠคํŠธ ํ™˜๊ฒฝ์—์„œ ์ถฉ๋ถ„ํžˆ ์—ฐ์Šตํ•˜๊ณ , ์ž์‹ ๊ฐ์ด ์ƒ๊ธฐ๋ฉด ํ”„๋กœ๋•์…˜์— ์ ์šฉํ•˜๋Š” ๊ฑฐ์•ผ.

ํ™”์ดํŒ…! ๋„ˆ๋Š” ํ•  ์ˆ˜ ์žˆ์–ด! ๐Ÿ”ฅ

์งˆ๋ฌธ์ด๋‚˜ ํ”ผ๋“œ๋ฐฑ์ด ์žˆ๋‹ค๋ฉด ์–ธ์ œ๋“  ๋Œ“๊ธ€๋กœ ๋‚จ๊ฒจ์ค˜.
ํ•จ๊ป˜ ์„ฑ์žฅํ•˜๋Š” ๊ฐœ๋ฐœ์ž ์ปค๋ฎค๋‹ˆํ‹ฐ๋ฅผ ๋งŒ๋“ค์–ด๊ฐ€์ž! ๐Ÿค

Happy Coding! ๐Ÿ˜Šโœจ
๋Œ“๊ธ€ ์ž‘์„ฑ

์ด ๊ธ€์— ๋Œ€ํ•œ ์—ฌ๋Ÿฌ๋ถ„์˜ ์ƒ๊ฐ์„ ๋“ค๋ ค์ฃผ์„ธ์š”

๋Œ“๊ธ€ 0