대용량 트래픽 처리 경험
- 대용량 트래픽을 처리하기 위해서 필수적으로 사용기능이 기능이 캐싱이다
먼저 SQL튜닝을 해야 한다
- SQL 튜닝
- 캐싱 서버 활용 (Redis 등)
- 레플리케이션 (Master/Slave 구조)
- 샤딩
- DB 스케일업 (CPU, Memory, SSD 등 하드웨어 업그레이드)
위 5가지 중에서 SQL을 먼저 고려해야한다
- SQL튜닝을 제외한 나머지방법은 추가적인 시스템을 구축해야 한다. 비용이 추가적으로 발생
- 근본적인 문제를 해결하는 방법은 SQL 튜닝일 가능성이 높다
- 가장 가성비가 좋은 방법이 SQL 튜닝이다
1. 설정
1). 환경설정
@Configuration
@EnableCaching
public class RedisCacheConfig {
@Bean
public CacheManager boardCacheManager(RedisConnectionFactory redisConnectionFactory) {
RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration
.defaultCacheConfig()
.serializeKeysWith(
RedisSerializationContext.SerializationPair.fromSerializer(
new StringRedisSerializer()))
.serializeValuesWith(
RedisSerializationContext.SerializationPair.fromSerializer(
new Jackson2JsonRedisSerializer<Object>(Object.class)
)
)
.entryTtl(Duration.ofMinutes(1L));
return RedisCacheManager
.RedisCacheManagerBuilder
.fromConnectionFactory(redisConnectionFactory)
.cacheDefaults(redisCacheConfiguration)
.build();
}
}
2). 캐시등록
cacheName: 그냥 캐시 이름을 설정한것 (의미는 없음)
key: Redisdp 저장할 key의 이름을 설정
cacheManager: 사용할 캐시매니저의 Bean이름을 지정
- boards:page:1:size:10이라는 키로 등록될 수 있도록 설정
@Service
public class BoardService {
private BoardRepository boardRepository;
private Pageable pageable;
public BoardService(BoardRepository boardRepository) {
this.boardRepository = boardRepository;
}
@Cacheable(cacheNames = "getBoards", key = "'boards:page:' + #page + ':size:' + #size", cacheManager = "boardCacheManager")
public List<Board> getBoards(int page, int size) {
Pageable pageable = PageRequest.of(page - 1, size);
Page<Board> pageOfBoards = boardRepository.findAllByOrderByCreatedAtDesc(pageable);
return pageOfBoards.getContent();
}
}
2. 부하테스트
- Thorughtpuh: 서비스가 1초당 처리할 수 있는 작업량
- TPS(Transaction PerSeconds): 단위
- 1초에 최대 100개의 API 요청을 처리할 수 있다면 Throughput은 100 TPS라고 얘기한다
1). 부하테스트 툴
- ngrinder, jmeter, ab, locust 등 다양한 툴이 있다
- 그 중에서 간단하고 빠르게 테스트 해볼 수 있는 툴인 k6를 사용해보겠다
- k6를 다운받고 js작성한다음
k6 run --vus 30 --duration 10ps script.js
-> 10초 동안 30명의 유저가 요청을 보내는 것처럼 해보겠다
-> http_reqs를 보면 숫자가 나오는데 뒤에 색깔 연한 숫자를 보면
-> 1초 그 숫자만큼 처리했다는 소리이다. // 1초 최대 처리숫자
import http from 'k6/http';
import { sleep } from 'k6';
export default function () {
http.get('http://{EC2 IP 주소}:8080/boards');
}
3. ElastiCache
- 일일이 Redis를 설치하고 세팅하고 관리하면서 확장까지 하려면 신경쓸 게 많다
- 하지만 ElastiCache를 사용하면 셋팅도 쉽게할 수 있고 확장도 쉽다
- 모니터링 기능도 제공해주고 장애날 가능성도 훨씬 적기 때문에 사용
1). 클러스터
- 여러 캐시서버를 어우르는 한 단위의 그룹
- 하나의 캐시서버를 노드라고 부르는데 여러개의 노드를 합친 그룹을 클러스터라고 한다
- 클러스터 안에있는 하나 하나는 캐시서버를 뜻하는 거다
- 하지만 어지간한 트래픽이 발생하는 서비스가 아니면 클러스터 모드까지 쓸 일이 없다

2). 환경설정
spring:
datasource:
url: jdbc:mysql://instagram-db.coseefawhrzc.ap-northeast-2.rds.amazonaws.com:3306/mydb
username: admin
password: password
data:
redis:
host: [ElastiCache 엔드포인트]
port: 6379
참고) https://developer-nyong.tistory.com/21