본문 바로가기
-----ETC-----/C++ 네트워크 프로그래밍 시리즈

[C++ 네트워크 프로그래밍] Day 20: 로드 밸런싱과 스케일링

by cogito21_cpp 2024. 8. 1.
반응형

로드 밸런싱과 스케일링

로드 밸런싱과 스케일링은 네트워크 애플리케이션의 성능과 확장성을 향상시키기 위한 중요한 기법입니다. 이 기법들은 트래픽을 여러 서버에 분산시켜 부하를 고르게 분배하고, 애플리케이션이 더 많은 요청을 처리할 수 있도록 합니다.

로드 밸런싱 (Load Balancing)

로드 밸런싱은 클라이언트 요청을 여러 서버에 분산시켜 서버의 부하를 고르게 유지하는 기술입니다. 이를 통해 단일 서버의 과부하를 방지하고, 시스템 전체의 가용성을 높일 수 있습니다.

로드 밸런서의 유형

  1. 소프트웨어 로드 밸런서: HAProxy, Nginx 등과 같은 소프트웨어 솔루션을 사용하여 로드 밸런싱을 구현합니다.
  2. 하드웨어 로드 밸런서: F5, Citrix 등의 하드웨어 장비를 사용하여 로드 밸런싱을 구현합니다.
  3. 클라우드 로드 밸런서: AWS ELB, Google Cloud Load Balancing 등과 같은 클라우드 서비스 제공업체의 로드 밸런싱 서비스를 사용합니다.

로드 밸런싱 알고리즘

  1. 라운드 로빈 (Round Robin): 각 서버에 순차적으로 요청을 분산합니다.
  2. 가중치 라운드 로빈 (Weighted Round Robin): 서버의 가중치에 따라 요청을 분산합니다.
  3. 최소 연결 (Least Connections): 현재 연결 수가 가장 적은 서버에 요청을 분산합니다.
  4. IP 해시 (IP Hash): 클라이언트 IP 주소를 해싱하여 특정 서버에 요청을 분산합니다.

스케일링 (Scaling)

스케일링은 시스템의 처리 능력을 확장하는 방법입니다. 스케일링에는 두 가지 유형이 있습니다.

수직 스케일링 (Vertical Scaling)

수직 스케일링은 단일 서버의 자원을 증설하여 처리 능력을 확장하는 방법입니다. CPU, 메모리, 디스크 등의 자원을 추가하여 성능을 향상시킵니다.

수평 스케일링 (Horizontal Scaling)

수평 스케일링은 여러 서버를 추가하여 처리 능력을 확장하는 방법입니다. 로드 밸런서를 사용하여 트래픽을 여러 서버에 분산시켜 부하를 고르게 분배합니다. 수평 스케일링은 높은 가용성과 확장성을 제공하며, 장애 발생 시에도 시스템의 지속성을 보장할 수 있습니다.

로드 밸런서 설정 예제 (HAProxy)

HAProxy는 고성능 TCP/HTTP 로드 밸런서입니다. 이를 사용하여 간단한 로드 밸런싱 설정을 해보겠습니다.

HAProxy 설치

  • Debian/Ubuntu:
  • sudo apt-get install haproxy
  • CentOS/RHEL:
  • sudo yum install haproxy

HAProxy 설정 파일 예제

haproxy.cfg 파일을 편집하여 로드 밸런서를 설정합니다.

global
    log /dev/log    local0
    log /dev/log    local1 notice
    chroot /var/lib/haproxy
    stats socket /run/haproxy/admin.sock mode 660 level admin
    stats timeout 30s
    user haproxy
    group haproxy
    daemon

defaults
    log     global
    mode    http
    option  httplog
    option  dontlognull
    timeout connect 5000
    timeout client  50000
    timeout server  50000

frontend http_front
    bind *:80
    default_backend http_back

backend http_back
    balance roundrobin
    server server1 192.168.1.101:80 check
    server server2 192.168.1.102:80 check
    server server3 192.168.1.103:80 check

 

이 설정 파일은 HAProxy를 HTTP 모드로 설정하고, 포트 80에서 요청을 수신하여 3개의 백엔드 서버에 라운드 로빈 방식으로 요청을 분산시킵니다.

C++ 클라이언트/서버 예제

Boost.Asio를 사용하여 간단한 클라이언트와 서버를 구현하고, HAProxy를 통해 로드 밸런싱을 적용해보겠습니다.

서버 코드

SimpleServer.h

#ifndef SIMPLESERVER_H
#define SIMPLESERVER_H

#include <boost/asio.hpp>
#include <memory>
#include <iostream>

namespace net = boost::asio;
using tcp = net::ip::tcp;

class Session : public std::enable_shared_from_this<Session> {
public:
    explicit Session(tcp::socket socket)
        : socket_(std::move(socket)) {}

    void start() {
        do_read();
    }

private:
    void do_read() {
        auto self(shared_from_this());
        socket_.async_read_some(net::buffer(data_),
            [this, self](boost::system::error_code ec, std::size_t length) {
                if (!ec) {
                    do_write(length);
                }
            });
    }

    void do_write(std::size_t length) {
        auto self(shared_from_this());
        net::async_write(socket_, net::buffer(data_, length),
            [this, self](boost::system::error_code ec, std::size_t /*length*/) {
                if (!ec) {
                    do_read();
                }
            });
    }

    tcp::socket socket_;
    char data_[1024];
};

class Server {
public:
    Server(net::io_context& io_context, short port)
        : acceptor_(io_context, tcp::endpoint(tcp::v4(), port)) {
        do_accept();
    }

private:
    void do_accept() {
        acceptor_.async_accept(
            [this](boost::system::error_code ec, tcp::socket socket) {
                if (!ec) {
                    std::make_shared<Session>(std::move(socket))->start();
                }
                do_accept();
            });
    }

    tcp::acceptor acceptor_;
};

#endif // SIMPLESERVER_H

 

main.cpp

#include <iostream>
#include <boost/asio.hpp>
#include "SimpleServer.h"

int main() {
    try {
        net::io_context io_context;

        Server server1(io_context, 8081);
        Server server2(io_context, 8082);
        Server server3(io_context, 8083);

        io_context.run();
    } catch (std::exception& e) {
        std::cerr << "Exception: " << e.what() << std::endl;
    }

    return 0;
}

 

설명

위의 코드는 Boost.Asio를 사용하여 간단한 TCP 에코 서버를 구현한 예제입니다. 3개의 서버 인스턴스를 실행하여 HAProxy를 통해 로드 밸런싱을 적용할 수 있습니다.

  • Session 클래스:
    • 클라이언트와의 세션을 관리합니다. 클라이언트와 데이터를 주고받습니다.
    • do_read() 함수는 클라이언트로부터 데이터를 비동기적으로 읽습니다.
    • do_write() 함수는 클라이언트에게 데이터를 비동기적으로 씁니다.
  • Server 클래스:
    • 클라이언트의 연결을 수락합니다. TCP 수신자를 사용하여 연결을 수락하고, 새로운 Session 객체를 생성합니다.
    • do_accept() 함수는 비동기적으로 클라이언트의 연결을 수락합니다.

 

이제 스무 번째 날의 학습을 마쳤습니다. 로드 밸런싱과 스케일링의 기본 개념과 HAProxy를 사용하여 로드 밸런싱을 설정하고, Boost.Asio를 사용하여 간단한 TCP 에코 서버를 구현하는 방법을 학습했습니다.

질문이나 피드백이 있으면 언제든지 댓글로 남겨 주세요. 내일은 "네트워크 모니터링과 로깅"에 대해 학습하겠습니다.

반응형