Proxy Server

프록시 서버는 클라이언트가 서버와 소통할 때
서버에 바로 접근하지 않고 자신을 통해 서버에 접근할 수 있도록
해주는 대리 서버라고 생각하면 간단하다.

1). Forward Proxy

클라이언트 가까이에 위치한 프록시 서버다.
클라이언트를 대신해 서버에 요청을 전달해준다.

image

장점

  • 캐싱을 통해 빠른 서비스 이용이 가능하다
  • 보안 (서버에서 프록시서버 IP를 받기때문에 클라이언트 IP를 숨길 수 있다)


2). Reverse Proxy

서버 가까이에 위치한 프록시 서버다.
서버를 대신해서 클라이언트에 응답을 제공해준다.

image

  • 분산처리 (여러대의 서버로 요청을 나누어 전달 후 처리, ex) 로드밸랜서)
  • 보안 (클라이언트에게 서버 IP가 노출되지 않는다)


Load Balancer

로드 밸런서는 서버에 가해지는 부하(Load)를 분산(Balance) 해주는
장치 또는 기술을 통칭한다.

하나의 서버에 클라이언트의 잦은 요청이 있으면
서버의 과부하가 온다. 과부하로 인해서 서버가 원할하게 서비스를 제공하지
못하는 경우가 발생하기 때문에, 이와 같은 문제를 해결하기 위한
로드 밸린스 방식으로는 크게 2가지가 존재한다.


✅ 로드 밸런서 방식

1). Scale up
물리적으로 서버의 사양을 높이는 하드웨어적 방법이다.
서버 수를 늘리지 않고 프로그램 구현있어 변화가 필요없다는 장점이 있다.

하지만 굉장히 높은 비용이 발생하고, 하드웨어의 업그레이드는
한계가 있다는 단점이 있다.

2). Scale out
서버의 갯수를 늘려 서버의 줄 부하를 분산시키는 방법이다.
많은 요청이 오더라도 여러대의 서버가 나눠서 처리를 하기 떄문에
서버의 사양을 높이지 않고도 비교적 저렴한 방법으로 부하를 처리할 수 있다.


✅ 로드 밸런서 알고리즘

1). 라운드로빈 방식 (Round Robin Method)
서버에 들어온 요청을 순서대로 돌아가며 배정하는 방식

2). 가중 라운드로빈 방식 (Weighted Round Robin Method)
각각의 서버마다 가중치를 매기고 가중치가 높은 서버에 클라이언트 요청을 우선 배분하는 방식이다.

3). IP 해시 방식 (IP Hash Method)
클라이언트의 IP 주소를 특정 서버로 매핑하여 요청을 처리하는 방식이다.

4). 최소 연결 방식 (Least Connection Method)
요청이 들어온 시점에 가장 적은 연결상태를 보이는 서버에 우선적으로 트래픽을 배분하는 방식이다.

5). 최소 리스폰타임 (Least Response Time Method)
서버에 현재 연결 상태와 응답시긴을 모두 고려하여 트래픽을 배분하는 방식이다.


✅ 로드 밸런서 종류

로드 벨런서는 클라이언트의 요청을 어떤 것을 기준으로
분산시키느냐에 따라 종류가 나눠진다.

로드 밸런서 종류 로드 밸런싱의 기준
L2 데이터 전송 계층에서 Mac 주소를 바탕으로 로드 밸런싱을 한다.
L3 네트워크 계층에서 IP 주소를 바탕으로 로드 밸런싱을 한다.
L4 전송 계층에서 IP주소와 Port를 바탕으로 로드 밸런싱을 한다.
L7 응용 계층에서 클라이언트의 요청을 바탕으로 로드 밸런싱을 한다.


✅ Auto Scaling

오토 스케일링은 Scale out 방식으로 서버를 증설할 때
자동으로 서버를 관리해주는 기능이다.
클라이언트의 요청이 많아져 서버의 처리 요구량이 증가하면 새 리소스를
자동으로 추하고 반대로 처리 요구량이 줄어들면 리소스를 감소시켜
적절한 분산 환경을 만들어준다.


Web Server

Tomcat

톰캣은 스프링 학습하면서도 많이 보았을 것이다.
Apache 회사에서 개발한 서블릿 컨테이너만 있는 오픈소스 웹 애플리케이션 서비이다.

우리가 흔히 spring-boot-starter-web 의존라이브러리를 설정해주면

image

외부 라이브러리에 추가된 모습을 볼 수 있다.


Jetty

제티는 이클립스 재단의 HTTP 서버이자 자바 서블릿 컨테이너이다.
우리는 스프링 웹에 내장되어 있는 톰켓을 사용했지만
Jetty 서버로 변경하여 사용하는 것도 가능하다.

dependencies {
	implementation ('org.springframework.boot:spring-boot-starter-web') {
		exclude module: 'spring-boot-starter-tomcat'
	}
	implementation ('org.springframework.boot:spring-boot-starter-jetty')
}

기존의 톰켓 서버를 제외시키고, Jetty의 의존라이브러리를 추가해주면된다.

image

gradle 리로드완료하면 외부라이브러리에서 Tomcat은 없어지고
jetty가 추가된 모습을 확인할 수가 있다.

마찬가지로 애플리케이션을 로컬에서 실행하면
콘솔에 Jetty started on port(s) 8080를 확인할 수 있다.


NginX (Proxy Server)

NginX는 가볍고 높은 성능을 보이는 오픈소스 웹 서버 소프트웨어이다.
Tomcat과 Jetty가 Java 서블릿 컨테이너 혹은 웹 애플리케이션 서버였다면
NginX는 웹 서버로 클라이언트에게 정적 리소스를 빠르게 응답하기 위한 웹서버로 사용할 수 있다.

image

위와 같은 구조를 만든다고 가정하고 로컬환경에서 테스트를 해보자

MacOs 기준으로 설명해본다.

brew install nginx

homebrew를 이용해 nginx를 설치해준다.
설치가 완료되면 brew list 명령어로 설치리스트를 확인할 수 있다.

NginX 서버를 실행시키는 방법은

brew services start nginx

해당 명령어를 입력하면 서버가 실행된다.
MacOS기준으로 기본 포트는 localhost:8080로 접속이 가능하다. 접속 성공 시에는 콘솔에
==> Successfully started nginx (label: homebrew.mxcl.nginx)
해당 문구를 확인할 수 있다.

만약 서버를 종료하고 싶다면

brew services stop nginx

해당 명령어를 입력해주면 된다.

당연하게도 포트 변경도 가능하다.
nginx.conf파일을 찾아서 변경해주면 된다.
homebrew로 설치하였다면 /opt/homebrew/etc/nginx/nginx.conf
해당 경로에 존재할 확률이 높다.

image

해당 파일을 vi, nano 편집기로 수정하여도 되고
직접 열어 수정해도 된다.

파일에서 http > server > listen의 포트번호가
8080으로 되어있을 텐데 해당 포트를 바꿔주면 된다.
나는 80으로 변경하여 사용했다.

그리고 location에서 proxy_pass 관련 내용을 추가해주면 된다.

server {
		listen       80; # 포트 변경
...
		location / {
				...
				proxy_pass http://localhost:8080; # 요청을 8080 포트로 넘깁니다.
				proxy_set_header X-Real-IP $remote_addr;
				proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
				proxy_set_header Host $http_host;
		}
}

다시 nginx를 실행 시키고, 스프링 부트를 실행시킨다음
localhost:80에 접속 요청을 하면
SpringBoot로 서버를 띄운 화면으로 넘어가는 것을 확인할 수 있을 것이다.


NginX (Load Balancer)

위에서 NginX로 프록시 서버를 만들어서 Spring Web 서버와 연결해보는 것 까지 해보았다.
NginX를 이용해 로컬환경에서 로드 벨런싱을 구성할 수 있다.

image

해당 구성도 nginx.conf 파일의 설정을 변경해서
로드벨런싱이 되도록 구성할 수 있다.
NginX 로드벨런싱 레퍼런스를 참고해서 작성해보자


http {
    ...
    
    # 로드 벨런싱 테스트를 위한 추가 (22.12.09)
    upstream backend {
        server localhost:8080;
        server localhost:8081;
    }
    # 여기 위까지 추가

    server {
        listen       80;
        server_name  localhost;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {
            root   html;
            index  index.html index.htm;
	    
	    # 로드 밸런싱 테스트를 위한 추가 (22.12.09)
	    proxy_pass http://backend;    
	    
        }
        ...
    }
    ...
}

로드 벨런싱을 위한 추가라고 붙은 주석이 달린 곳을 보면된다.
스프링 톰켓 서버를 8080, 8081로 애플리케이션으로 실행 시켜둔 다음에
nginx 서버를 80으로 실행 시키고 접속 요청을 하였을 경우

image

이렇게 작성한 화면이 띄워지게 된다.
여기서 화면을 구분하기 위해 PID값을 추가해 줬다.
보면 알 수 있듯이 2개의 서버중 33861 PID 값을 가진 화면을 불러왔다.

여러번 새로고침을 반복하면

image

이번엔 33818 PID 값을 가진 화면을 불러왔다.
이렇게 클라이언트에서 nginx 서버에 요청 시
로드 벨런싱이 적용되어 동작하는걸 눈으로 확인해 볼 수 있다.



이렇게 오늘은 클라우드 운영 전략에 대해 간단하게 알아보았다.
백엔드 공부를 시작하면서 늘 걱정이었던게
서버가 터지는 것을 어떻게 방지하지? 라는 의문이 있었고
환경적으로 이렇게 설정할 수 있구나라는걸 많이 배운 것 같다.

이러한 전략들 외에 실제로 웹 요청이 많을때 프로그램 코드적으로는
어떻게 해야 잘 짤 수 있을까도 많이 고민해보면 좋을 것 같다. (WebFlux라든가..)


오늘의 커피량: ☕️ ☕️
오늘의 점심: 간장계란밥, 김치찌개