쉽게 말해..서비스에 걸리는 부하를 분산해주는 로드 밸런서입니다.

 

ALB나 기타 로드밸런서들은  서비스의 부하를 줄여 안정성과 가용성을 기대할 수 있습니다.

그중 ALB는 아래와 같은 장점을 가지고 있습니다. 

  -  고가용성 지원
  -  사용자 인증과 같은 보안 향상
  -  다양한 레벨의 부하에 대한 유연한 응답
  -  애플리케이션 밀착 모니터링 및 검수

 

AWS ALB vs. ELB: 로드 밸런서 비교

AWS에서 제공하는 로드 밸런서에는 여러 종류가 있지만, 특히 **Application Load Balancer (ALB)**와 **Elastic Load Balancer (ELB)**가 많이 사용됩니다. 이 두 로드 밸런서는 각기 다른 기능과 용도로 설계되었으며, 이 포스트에서는 그 차이점을 알아보겠습니다.

ELB (Elastic Load Balancer)

  • 정의: ELB는 AWS의 전반적인 로드 밸런싱 솔루션의 총칭으로, Classic Load Balancer를 포함합니다.
  • 기능:
    • TCP 및 HTTP/HTTPS 트래픽 지원
    • EC2 인스턴스 간의 트래픽 분산
  • 용도: 단순한 레이어 4(전송 계층) 로드 밸런싱이 필요할 때 적합
  • 설정: 간단한 설정, 기본적인 로드 밸런싱 기능 제공

ALB (Application Load Balancer)

  • 정의: ALB는 ELB의 한 종류로, 애플리케이션 계층에 최적화된 로드 밸런서입니다.
  • 기능:
    • 레이어 7(애플리케이션 계층)에서 작동
    • URL 기반 및 호스트 기반 라우팅 지원
    • WebSocket 및 HTTP/2 지원
  • 용도: 마이크로서비스 아키텍처와 복잡한 웹 애플리케이션에 적합
  • 설정: 다양한 라우팅 옵션과 고급 기능 제공, 설정이 다소 복잡할 수 있음

주요 차이점 요약

기능/특징ELBALB

계층 레이어 4 레이어 7
지원하는 트래픽 TCP, HTTP/HTTPS HTTP/HTTPS
라우팅 기능 기본적인 로드 밸런싱 복잡한 라우팅 규칙 가능
용도 간단한 트래픽 분산 마이크로서비스 및 복잡한 웹 애플리케이션

 

이러한 차이점을 바탕으로, 애플리케이션의 필요에 따라 적절한 로드 밸런서를 선택하는 것이 중요합니다.

1.환경

ALB(Application Load Balancer) 사용

SSL 인증서 적용

HTTPS 통신만 허용

ALB -> Tomcat 형태의 인프라 구성

 

2.현상

Request Header에 Content-Type을 포함한 여러 해더정보를 전송하였고 Method는 POST를 이용했다.

그러나 서버에 수신된 Request Header는 Content-Type이 Null이고 Method도 GET으로 수신이 되었다.

 

파일업로드 처리를 위해 httpservletrequest 를 multiparthttpservletrequest 로 캐스팅 하는과정에 Cast Exception이 발생하였다.

 

Request Body또한 비어 있어 inputstream을이용하여 강제로 꺼내보려 했지만 꺼낼 수 없었다.

 

3.원인 및 해결방법

클라이언트에서 http를 이용하여 요청이 올경우 ALB에서 https로 포워딩 해주게 된다.

그 과정에 Content-Type을 잃어버리고 Method도 Get으로 변경되며 Request Body도 유실되는 상황이 발생함.

Spring framework의 @Requestbody 어노테이션도 당연히 안되었다.

 

3-1. 해결방법 #1

http로밖에 전송할 수 없는 상황인경우 ALB의 특정URL 패턴에 예외를 두어 http 통신이 될 수 있도록 조치한다.

 

3-2 해결방법 #2

당연한 소리겠지만 스펙에 맞게 https로 request요청을 송신한다.

 

 

4.잡설

나는 서버에 request를 송신하는 주체가 브라우저가 아닌 다른 CS 프로그램으로 해당 프로그램에서 http로만 전송이 가능하도록 개발되어 있었고.. http로 통신가능하도록 ALB에 요청을 한뒤 테스트하여 해결방안에 대한 방향성을 찾을 수 있었다.

스프링을 사용한다면 MultipartResolver를 설정하고,  전송되는 form Tag에 enctype="multipart/form-data" 옵션을 추가하고 등등 여러가지 글이 있지만 해결되지 않아서 고생을 했지만.....

 

 

import javax.sql.DataSource;

import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;

@Configuration
@PropertySource("classpath:/application.properties")
public class DatasourceConfiguration {
	@Autowired
	private ApplicationContext applicationContext;
	
	@Bean
	@ConfigurationProperties(prefix="spring.datasource.hikari")
	public HikariConfig hikariConfig() {
		return new HikariConfig();
	}
	
	@Bean
	public DataSource dataSource() throws Exception {
		DataSource dataSource = new HikariDataSource(hikariConfig());
		return dataSource;
	}
	
	@Bean
	public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
		SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
		sqlSessionFactoryBean.setDataSource(dataSource);
		
		sqlSessionFactoryBean.setConfigLocation(applicationContext.getResource("classpath:mybatis-config.xml"));
		sqlSessionFactoryBean.setMapperLocations(applicationContext.getResources("classpath:/mapper/**/*Mapper.xml"));
		return sqlSessionFactoryBean.getObject();
	}

	
	@Bean(name="batchSqlSessionTemplate") 
	public SqlSessionTemplate batchSqlSessionTemplate(SqlSessionFactory sqlSessionFactory) { 
		 return new SqlSessionTemplate(sqlSessionFactory, ExecutorType.BATCH); 
	}
	
	@Bean(name="sqlSessionTemplate") 
	public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
		return new SqlSessionTemplate(sqlSessionFactory);
	}
	
	
	/**
	 * 트렌젝션 관리
	 * @param dataSource
	 * @return
	 */
	@Bean
	public PlatformTransactionManager transactionManager(DataSource dataSource) {
		return new DataSourceTransactionManager(dataSource);
	}
	

	
}

 

 

 

 

아래와같이 적용

	/**
	 * DB컨넥션 후 Connection객체를 반환한다.
	 * @return
	 * @throws SQLException
	 */
	private Connection getConnection() throws Exception{

		ApplicationContext ctx = ApplicationContextAwareExtends.getApplicationContext();
		DataSource dataSource =  ctx.getBean(DatasourceConfiguration.class).dataSource();
		
		return dataSource.getConnection();
	}

+ Recent posts