프록시 서버
- 클라이언트가 서버와 소통할 때, 서버에 바로 접근하지 않고 자신을 통해 서버에 접근할 수 있도록 해주는 일종의 대리 서버
클라이언트에 가까이 위치한 프록시 서버
캐싱을 통해 빠른 서비스 이용 가능
보안
서버에 가까이 위치한 프록시 서버
분산처리
보안
결국 위 두가지 프록시 서버 모두 사용자 - 프록시서버 - 서버
구조로 비슷해 보일 수 있지만 Forward Proxy의 경우 서버에게 받은 응답들을 캐싱해 가지고 있으면서 사용자에게 나눠주는거고 Reverse Proxy의 경우 사용자의 요청을 여러 서버에게 나눠준다고 생각하면 될 것 같다.
클라이언트의 요청 증가에 따라 서버를 업그레이드 하는 두가지 방법
Scale-Up
Scale-Out
Scale-Out방법으로 여러대의 서버로 부하를 나눠 처리할 때 교통정리 역할을 해주는 기술
로드 밸런서는 클라이언트의 요청을 어떤 것을 기준으로 분산시키냐에 따라 네 가지의 종류로 나뉜다.
로드 밸런서의 종류 | 로드밸런싱의 기준 |
---|---|
L2 | 데이터 전송 계층에서 Mac 주소를 바탕으로 로드 밸런싱 |
L3 | 네트워크 계층에서 IP 주소를 바탕으로 로드 밸런싱 |
L4 | 전송 계층에서 IP주소와 Port를 바탕으로 로드 밸런싱 |
L7 | 응용 계층에서 클라이언트의 요청을 바탕으로 로드 밸런싱 (ex. 엔드포인트) |
aws에서 제공하는 자동 서버 증설(Auto Scaling) 기능
- 서버의 처리 요구량이 증가하면 새 리소스를 자동으로 추가
- 처리 요구량이 줄어들면 리소스를 감소시켜 적절한 분산 환경을 만들어줌
- 클라우드 서비스 종류마다 기능의 이름이나 방식이 조금 다름
서버 플릿
- 일련의 EC2 서버 집합
- 여러 대의 서버 인스턴스를 관리하기 위한 그룹
Auto Scaling
은 EC2 인스턴스 뿐만 아니라 다른 인스턴스와도 결합 가능하다.
EC2 Auto Scaling
은 오직 EC2 서버라는 리소스만 대상으로 한다.
Auto Scaling으로 인스턴스를 확장 또는 축소하려면 어떤 서버를 사용할지 결정해야 한다. 이걸 시작 템플릿을 통해 결정한다.
시작 템플릿은 AMI 상세 정보, 인스턴스 타입, 키 페어, 시큐리티 그룹 등 인스턴스에 대한 모든 정보를 담고 있다.
만약 시작 템플릿을 사용하고 있지 않고 시작 템플릿을 생성하지 않으려는 경우에는 시작 템플릿(Launch Configuration)
대신 시작 구성
을 생성할 수 있다.
Auto Scaling 그룹
- 스케일업 및 스케인 다운 규칙의 모음
- EC2 인스턴스 시작부터 삭제까지의 모든 동작에 대한 규칙과 정책을 담고 있다.
인스턴스 레벨 유지
수동 스케일링
일정별 스케일링
동적 스케일링
Apache사에서 개발한 서블릿 컨테이너만 있는 오픈소스 웹 애플리케이션 서버
이클립스 재단의 HTTP 서버이자 자바 서블릿 컨테이너
- Tomcat과 마찬가지로 자바 서블릿 컨테이너이자 서버로 사용할 수 있기 때문에 개발자는 원하는 서버(Tomcat or Jetty)를 선택하여 프로젝트를 구성할 수 있다.
아래와 같이 build.gradle
파일에서 Tomcat을 제외시키고 Jetty를 추가해주면 된다.
dependencies {
implementation ('org.springframework.boot:spring-boot-starter-web') {
exclude module: 'spring-boot-starter-tomcat' // Tomcat 제외시키기
}
implementation ('org.springframework.boot:spring-boot-starter-jetty') // Jetty 적용
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
같은 방식으로 Tomcat, Jetty를 제외하고도 Netty, Undertow등 다양한 서버로 변경할 수 있다.
NginX
- 가볍고 높은 성능을 보이는 오픈소스 웹 서버 소프트웨어
Nginx는 클라이언트에게 정적 리소스를 빠르게 응답하기 위한 웹 서버로 사용할 수 있다.
(Tomcat과 Jetty는 자바 서블릿 컨테이너 혹은 웹 애플리케이션 서버다.)
웹 브라우저에서 http://localhost
를 입력하면 기본적으로 80 포트로 접속된다.
nginx를 사용하여 80 포트에서 들어오는 요청을 가로채서 8080 포트로 전달해 보았다.
nginx.exe
실행 -> 추가 정보 -> 실행4.Nginx 설정 파일 수정
nginx-1.22.1\nginx-1.22.1\conf
경로에서 nginx.conf
파일 확인 가능
(압축해제한 폴더 확인)
설정에서 포트 번호를 80으로 변경하고 리버스 프록시 서버로서 Spring Boot 프로젝트에 연동
server {
listen 80; # (Mac OS의 경우) 8080 포트에서 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 실행 파일이 있는 폴더(압축 해제한 폴더)로 이동하여 다음 명령어를 실행
nginx -s reload
그런데 nginx: [error] invalid PID number "" in "D:\AAWonJong\Program File\nginx-1.22.1\nginx-1.22.1/logs/nginx.pid"
와 같이 잘못된 PID 번호라고 오류가 발생했다. (nginx 종료가 제대로 안되는 것 같다.)
아래와 같이 80 포트를 사용하는 프로세스를 찾아 중지시키고 다시 실행시켰다.
D:\AAWonJong\Program File\nginx-1.22.1\nginx-1.22.1>netstat -aon | findstr ":80"
TCP 0.0.0.0:80 0.0.0.0:0 LISTENING 20952
TCP 192.168.0.177:57096 211.47.61.158:80 TIME_WAIT 0
TCP 192.168.0.177:57097 104.76.70.102:80 TIME_WAIT 0
TCP 192.168.0.177:57098 104.76.70.102:80 TIME_WAIT 0
TCP 192.168.0.177:57099 23.67.53.11:80 TIME_WAIT 0
TCP [::]:80 [::]:0 LISTENING 20952
D:\AAWonJong\Program File\nginx-1.22.1\nginx-1.22.1>tasklist /fi "pid eq 20952"
이미지 이름 PID 세션 이름 세션# 메모리 사용
========================= ======== ================ =========== ============
httpd.exe 20952 Services 0 8,212 K
D:\AAWonJong\Program File\nginx-1.22.1\nginx-1.22.1>taskkill /pid 20952 /f
성공: 프로세스(PID 20952)가 종료되었습니다.
D:\AAWonJong\Program File\nginx-1.22.1\nginx-1.22.1>nginx -s reload
nginx: [error] invalid PID number "" in "D:\AAWonJong\Program File\nginx-1.22.1\nginx-1.22.1/logs/nginx.pid"
D:\AAWonJong\Program File\nginx-1.22.1\nginx-1.22.1>nginx.exe
Nginx 재시작 후 localhost (80번 포트는 생략 가능)에 접속하면 아래와 같이 에러문을 확인할 수 있다. (8080번 포트를 사용하지 않았기 때문)
애플리케이션 실행 후 다시 localhost에 접속하면 정상적으로 화면이 출력된다.
nginx -s stop
이 명령어로 nginx 종료 가능
NGINX를 이용하여 로컬 환경에서 로드밸런싱을 구성해 봤다.
빌드 후 아래 두 명령어를 이용해 하나는 8080번 포트, 다른 하나는 8081번 포트를 사용해서 실행
java -jar sample-0.0.1-SNAPSHOT.jar
java -Dserver.port=8081 -jar sample-0.0.1-SNAPSHOT.jar //8081 포트에서 실행
@RestController
public class HelloController {
@GetMapping("/")
public String hello() {
long pid = ProcessHandle.current().pid();
return String.format("Hello World, Hello BE Bootcamp! @PID : %d", pid);
}
}
위와 같이 PID(프로세스 식별자=Process Identifier)를 확인하기 편하게 코드를 짜뒀다.
http {
~~~
upstream backend {
server localhost:8080;
server localhost:8081;
}
server{
~~~
location / {
proxy_pass http://backend;
}
}
}
위의 코드는 backend라는 서버 그룹을 만든 뒤 그룹 자체로 전달을 하는 구조다. 서버 그룹의 이름은 다른 이름으로 변경 가능하다.
location의 proxy_pass 값을 위에서 만든 서버 그룹으로 설정했다.
NGINX의 포트는 80번으로 설정되어있기 때문에 포트를 생략한 localhost 로 접속시 8080번 포트와 8081번 포트가 번갈아 연결된다.
NGINX 실행 후 http://localhost/
에 접속시 아래와 같이 두 프로세스가 번갈아 나오는걸 확인 가능했다.
VPC(Virtual Private Cloud 서비스)
- 클라우드 내 프라이빗 공간을 제공함으로써, 클라우드를 퍼블릭과 프라이빗 영역으로 논리적으로 분리할 수 있게 하는 기능
- VPC를 통해 클라우드에 있는 리소스를 격리해 각 리소스별 의존도를 낮춰 확장성을 가질 수 있다.
IP는 컴퓨터 네트워크에서 장치들이 서로를 인식하고 통신을 하기 위해서 사용하는 특수한 번호로, IPv4, IPv6로 나뉘어 있으며 혼용하여 사용하고 있다.
IPv4를 기준으로 예를 들면, 아래와 같은 형식인 172.16.0.0
의 모습으로 이루어져 있다.
172. | 16. | 0. | 0 |
---|---|---|---|
10101100. | 00010000. | 00000000. | 00000000 |
하지만 표에서 보이는 십진수의 형태는 보기 편하도록 변형한 것이고, 실제의 형태는 2진수 8자리의 형태, 즉 각 8bit(비트)씩 총 32bit로 구성되어 있다. 이때 각 8bit를 Octet이라고 부르며, .
으로 구분한다. 그러므로 IPv4는 4개의 Octet(옥텟)으로 이루어져 있다고 할 수 있다.
이전에는 IPv4 주소에서 호스트가 연결되어 있는 특정 네트워크를 가리키는 8비트의 네트워크 영역(Network Address)과 해당 네트워크 내에서 호스트의 주소(Host Address)를 가리키는 나머지 영역을 구분하기 위해서 클래스(Class)를 사용했다. 클래스는 총 5가지(A, B, C, D, E) 클래스로 나누어져 있다. 하지만 D와 E 클래스는 멀티캐스트용, 연구 개발을 위한 예약 IP이므로 보통 사용되지 않는다.
Network Address | Host Address | Host Address | Host Address |
---|---|---|---|
0-127 | 0-255 | 0-255 | 0-255 |
단, 0.0.0.0
의 경우는 자체 네트워크를 의미하기 때문에 제외되고, 127.0.0.0 ~ 127.255.255.255는 자기 자신을 가리키기 위한 목적으로 예약된 IP주소이기 때문에 사용할 수 없다.
Network Address | Network Address | Host Address | Host Address |
---|---|---|---|
128-191 | 0-255 | 0-255 | 0-255 |
Network Address | Network Address | Network Address | Host Address |
---|---|---|---|
192-223 | 0-255 | 0-255 | 0-255 |
CIDR은 사이더라고 불리며, 클래스 없는 도메인 간 라우팅 기법으로 1993년 도입되기 시작한 국제 표준의 IP주소 할당 방법이며, 위의 IP 클래스 방식을 대체한 방식이다.
기존에는 클래스에 따라 정해진 Network Address와 Host Address를 사용해야 했다면, CIDR은 원하는 블록만큼 Network Address를 지정하여 운용할 수 있다.
위의 예시에 따르면, /16
은 첫 16bit를 Network Address로 사용한다는 의미로, 총 2^16인 65,536개의 IP주소를 사용할 수 있는 커다란 네트워크 블록을 이러한 방식으로 표시한다.
CIDR 블록 | IP 주소의 수 |
---|---|
/28 | 16 |
/24 | 254 |
/20 | 4094 |
/18 | 16,382 |
/16 | 65,536 |
서브넷 서브네트워크(Subnetwork)
- IP 네트워크의 논리적인 하위 부분을 가리킨다.
서브넷을 통해 하나의 네트워크를 여러 개로 나눌 수 있다.
VPC를 사용하면 퍼블릭 서브넷, 프라이빗 서브넷, VPN only 서브넷 등, 필요에 따라 다양한 서브넷을 생성할 수 있다.
서브넷은 VPC의 CIDR 블록을 이용해 정의되며, 최소 크기의 서브넷은 /28 다. 이때 주의 할 점은 서브넷은 AZ당 최소 하나를 사용할 수 있고, 여러 개의 AZ에 연결되는 서브넷은 만들 수 없다.
Tips ) AWS가 확보한 서브넷 중 처음 네 개의 IP주소와 마지막 IP주소는 인터넷 네트워킹을 위해 예약되어 있다. 서브넷에서 가용 IP주소를 계산할 때는 항상 이 부분을 기억하고 있어야 한다. 예를 들어, 10.0.0.0/24 체계의 CIDR 블록이 있는 서브넷에서 10.0.0.0, 10.0.0.1, 10.0.02, 10.0.0.3, 10.0.0.255 등 5개의 IP주소는 예약 되어 있다.
라우팅 테이블
- 하나의 지점에서 또 다른 지점으로 가기 위한 모든 정보를 제공하기 위한 테이블
- 트래픽의 전송 방향을 결정하는 라우트와 관련된 규칙을 담은 테이블로 목적지를 향한 최적의 경로로 데이터 패킷을 전송하기 위한 모든 정보를 담고 있다.
모든 서브넷은 라우팅 테이블을 갖고 있다.
예를 들어 아래의 캡처본과 같이 특정 VPC의 서브넷이 라우팅 테이블에 인터넷 게이트웨이(VPC와 인터넷 간 통신을 가능하게 하는 구성요소)를 포함하고 있다면, 해당 서브넷은 인터넷 액세스 권한 및 정보를 가진다.
각각의 서브넷은 항상 라우팅 테이블을 가지고 있어야 하며, 하나의 라우팅 테이블 규칙을 여러 개의 서브넷에 연결하는 것도 가능하다. 서브넷을 생성하고 별도의 라우팅 테이블을 생성하지 않으면 클라우드가 자동으로 VPC의 메인 라우팅 테이블을 연결한다.