Sentinel 개요
Sentinel은 Alibaba에서 개발한 분산 시스템의 유량 제어 도구로, 유량 제어, 회로 차단, 시스템 부하 보호 등 여러 차원에서 서비스 안정성을 유지합니다.
설치 및 실행
릴리즈 페이지에서 JAR 파일 다운로드: 다운로드 링크
java -jar sentinel-dashboard-1.8.5.jar
실행 후 브라우저에서 http://192.168.56.102:8080/#/login 접속
- 사용자명: sentinel
- 비밀번호: sentinel
- 주의: 기본 포트는 8080이며, 사용 전 해당 포트가 점유되지 않았는지 확인해야 합니다.
프로젝트 통합
Nacos 시작
먼저 Nacos 서버를 시작합니다.
Maven 의존성 설정
Spring Cloud 프로젝트에 다음 의존성을 추가합니다:
<!-- Sentinel Core -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!-- Nacos 데이터 소스 -->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
애플리케이션 속성 구성
# Sentinel 대시보드 주소
spring.cloud.sentinel.transport.dashboard=localhost:8080
# 클라이언트 통신 포트 (기본값: 8719)
spring.cloud.sentinel.transport.port=8719
샘플 컨트롤러 작성
@RestController
public class GameCharacterController {
@GetMapping("/hero/yase")
public String yaseHero(){
return "야스오 영웅 정보...";
}
@GetMapping("/hero/daji")
public String dajiHero(){
return "다지 영웅 정보...";
}
}
유량 제어 규칙
QPS 기반 제어
"/hero/yase" 엔드포인트에 대해 초당 최대 1회 요청만 허용하는 규칙을 설정합니다.
스레드 수 제한
@GetMapping("/hero/yase")
public String yaseHero() throws InterruptedException {
System.out.println(Thread.currentThread().getName() + " 처리 중 - " + LocalDateTime.now());
Thread.sleep(5000); // 5초 지연
return "야스오 영웅 정보...";
}
이 경우 스레드 수를 1로 제한하면 동시 접근이 불가능해집니다.
관련 리소스 모드
"/hero/daji" 리소스의 QPS가 임계치를 초과할 때 "/hero/yase" 리소스에 대한 접근을 제한합니다.
링크 모드
@Service
public class HeroService {
@SentinelResource("acquireHero")
public void acquireHero(){
System.out.println("영웅 획득 로직");
}
}
@RestController
public class GameController {
@Autowired
private HeroService heroService;
@GetMapping("/game/battle")
public String startBattle() {
heroService.acquireHero();
return "전투 시작";
}
@GetMapping("/game/shop")
public String visitShop() {
heroService.acquireHero();
return "상점 방문";
}
}
워밍업(Warm Up)
시스템이 장시간 저부하 상태일 때 갑작스러운 트래픽 증가를 부드럽게 처리하기 위한 방식입니다.
- 임계치: 10
- 워밍업 시간: 5초
- 초기 임계치: 10/3 ≈ 3
대기열 큐
고르게 요청을 처리하도록 하여 시스템 과부하를 방지합니다.
규칙 영속화
Nacos 연동 설정
# Nacos 서버 주소
spring.cloud.sentinel.datasource.ds1.nacos.server-addr=localhost:8848
spring.cloud.sentinel.datasource.ds1.nacos.data-id=game-sentinel-rules
spring.cloud.sentinel.datasource.ds1.nacos.group-id=SENTINEL_GROUP
spring.cloud.sentinel.datasource.ds1.nacos.data-type=json
spring.cloud.sentinel.datasource.ds1.nacos.rule-type=flow
Nacos 데이터 예시
[
{
"resource":"/hero/yase",
"limitApp":"default",
"grade":1,
"count":1,
"strategy":0,
"controlBehavior":0,
"clusterMode":false
}
]
서킷브레이커 규칙
느린 호출 비율
@GetMapping("/hero/yase")
public String yaseHero() throws InterruptedException {
Thread.sleep(300); // 300ms 지연
return "야스오 정보";
}
예외 발생 비율
private static int errorCounter = 0;
@GetMapping("/hero/yase")
public String yaseHero() {
if(errorCounter++ < 3) {
throw new RuntimeException("임시 오류");
}
return "야스오 정보";
}
@GetMapping("/reset")
public String resetError() {
errorCounter = 0;
return "카운터 초기화";
}
핫스팟 규칙
@GetMapping("/hero/detail")
@SentinelResource("heroDetail")
public String getHeroDetail(@RequestParam int heroId) {
return "영웅 ID: " + heroId + " 상세 정보";
}
특정 파라미터(heroId)에 대해 유량 제어를 적용할 수 있습니다.
사용자 정의 예외 처리
@SentinelResource 활용
@GetMapping("/hero/detail")
@SentinelResource(value = "heroDetail", blockHandler = "handleBlockedRequest")
public String getHeroDetail(@RequestParam int heroId) {
return "영웅 ID: " + heroId + " 상세 정보";
}
public String handleBlockedRequest(int heroId, BlockException ex) {
return "요청이 너무 많습니다. 잠시 후 다시 시도해주세요. (ID: " + heroId + ")";
}
전역 예외 핸들러
@Component
public class GlobalSentinelExceptionHandler implements BlockExceptionHandler {
@Override
public void handle(HttpServletRequest request, HttpServletResponse response, BlockException e) throws Exception {
response.setContentType("application/json;charset=UTF-8");
String jsonResponse = "{\"status\":429,\"message\":\"서비스 과부하. 잠시 후 재시도 바랍니다.\"}";
response.getWriter().write(jsonResponse);
}
}