Home 서비스 장애가 발생하는 다양한 상황과 대응 방법: timeout
Post
Cancel

서비스 장애가 발생하는 다양한 상황과 대응 방법: timeout

🙋: 서비스 지연이 발생하고 있습니다

timeout

어느 주말 저녁, 서비스 지연이 발생하고 있다는 알림이 뜬다. 개발자는 뭘 할 수 있을까??

서비스에서 담당하는 모듈에서 어떻게 노출되는지 보고 모니터링 사이트에 들어가본다.

“일시적인 문제가 발생했습니다. 잠시 후 다시 시도해 주세요”

이미 서비스는 불가능한 상황이다. 다음 단계에 따라 장애를 대응한다. (정답은 아니다.. 🙃)

  1. 모니터링 페이지에서 장애가 나는 모듈, 트래픽을 확인한다.
  2. 에러 및 지연이 발생하는 부분 api 요청과 응답을 확인한다.
  3. 지연이 발생하는 api 모듈에 상황 전파 후 담당 모듈의 에러를 분류한다.
  4. 고객이 어떤 응답을 받을지, 서비스의 영향도를 파악하며 팀내 상황을 전파한다.
  5. 장애 복구 방법이 결정되고, 정상 상태를 회복할 때까지 모니터링 한다.

몇 번의 지연에서 위와 같은 방법으로 장애를 대응했다. 타 모듈 api 호출이 많아 항상 어떻게 개선해야 할지 고민이 많았는데 이번 글에서 서비스 지연, 장애 발생 시 볼 수 있는 timeout의 종류와 발생 원인을 알아보고 장애 전파를 막기 위한 방법을 알아본다.

Timeout 의 종류

Timeout정의
Connection Timeout서버에 연결하는 동안 시간 초과
Socket Timeout소켓 통신 중 데이터 송수신 시간 초과
Read Timeout요청에 의한 응답을 받기까지의 시간 초과

서비스에서 많이 발생하는 Timeout의 세 가지이다. 서버에서 충분히 발생할 수 있는 에러이고, Timeout 설정값 관리와 다양한 상황을 고려하여 개발한다면 지연이 발생해도 장애 전파를 막고 신뢰성과 안정성이 높은 서비스를 유지할 수 있을 것이다. 각 에러의 발생 가능한 경우와 개발 시 고려할 점을 알아본다.

Connection Timeout

Http 통신, DB 연결, 외부 api 호출 등에서 연결 시간이 초과할 경우 발생할 수 있는 connection timeout이다. 몇 가지 경험한 예를 들어보면 다음과 같다.

  • FTP 연결 시 잘못된 인증키로 인한 문제
  • schema registry 인스턴스의 방화벽으로 인한 consumer 메세지 처리 문제
  • DB connection pool이 모두 사용 중으로 발생한 문제
  • 클라이언트의 connection timeout이 짧아 발생한 문제

인증키 문제나 방화벽 문제는 운영 환경을 충분히 확인한다면 방지할 수 있다. 이외에 서버나 DB 연결 시간 초과 문제는 연결을 위한 설정값을 적절히 세팅해야 한다. 또한 DB 연결의 경우 쿼리 최적화나 DB 서버의 자원을 고려해서 connection pool을 설정해야 한다.

Feign client config

1
2
3
4
5
6
7
8
9
feign:
  client:
    config:
      default:
        connect-timeout: 5000 # Connection Timeout (ms)
        read-timeout: 10000 # Read Timeout (ms)
      memberClientService:
        connect-timeout: 3000
        read-timeout: 7000
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@FeignClient(name = "memberClientService", url = "${endpoint.url}")
public interface MemberClientService {

    @GetMapping(
            consumes = MediaType.APPLICATION_JSON_VALUE,
            produces = MediaType.APPLICATION_JSON_VALUE,
            path = "/v1/member/info"
    )
    @CircuitBreaker(name = "getMemberInformation", fallbackMethod = "getMemberInformationFallBack")
    ResponseEntity<MemberInformation> getMemberInformation();

    default ResponseEntity<MemberInformation> getMemberInformationFallBack() {
        return ResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE)
                .body(MemberInformation.emptyBody());
    }

Spring Cloud OpenFeign을 사용할 때 application.yml에 설정값이다. connection timeout과 read timeout을 설정할 수 있고 에러가 발생 했을 경우 fallback 메서드를 두어 실패에 대한 적절한 처리를 하도록 설정할 수 있다.

Socket Timeout 과 Read Timeout

socket timeout과 read timeout은 유사한 특징을 가지고 있어 묶어서 정리해 보았다. 아래 두 가지 특성을 비교해 보았다.

특성Socket TimeoutRead Timeout
정의데이터 송수신을 포함한 네트워크 작업의 타임아웃서버에서 응답 데이터를 읽는 작업의 타임아웃
적용 범위읽기와 쓰기를 포함하는 네트워크 작업 전체읽기 작업에 한정
적용되는 단계연결 이후 데이터 송수신 작업 전반연결 후 응답 데이터를 읽는 단계에서만 적용
발생 위치소켓(네트워크 계층)에서 발생자원 읽기 작업에서 발생

Socket timeout

얼마전 서버에서 schema registry 인스턴스로의 방화벽이 열려 있지 않아 Socket Timeout이 발생한 경험이 있다. Kafka broker의 메세지를 역직렬화 하기 위해 필요한 동작이었는데 registry에 접근을 요청 했지만, 방화벽에 의해 네트워크 연결이 불가했던 이슈이다.

1
jdbc:mysql://localhost:3306/mydb?socketTimeout=5000

DB 연결 설정에서도 socketTimeout을 설정하는 것을 볼 수 있다. 쿼리 실행 중 대기 시간을 socketTimeout으로 제어하게 되는데, 위 설정으로 보면 쿼리 실행 후 5초 내에 응답을 받아야 에러가 발생하지 않는다.

Read timeout

Read timeout은 다양한 상황에서 발생할 수 있다. 비즈니스 로직에서 데이터 처리, DB 읽기, 외부 모듈 api 호출 등이 있다. 위 내용에 OpenFeign 예시에서도 볼 수 있듯이 read timeout을 설정하고 설정한 시간을 초과하거나 에러가 발생할 경우 fallBack 메서드로 처리해서 안정성을 높일 수 있다.

Timeout 제어하기

예상하지 못한 timeout을 예방하려면 몇 가지 방법을 고려해 볼 수 있다.

적절한 timeout 값 설정

너무 짧은 값은 정상 응답이어도 timeout을 발생할 수 있고, 너무 긴 설정 값은 늦은 장애 감지와 더 심각한 지연을 초래할 수 있다.

Fallback 처리

OpenFeign, WebClient 등을 사용해서 외부 모듈과 통신을 할 때 fallback 처리를 해서 예외 상황에도 유연하게 처리할 수 있다. Fallback 처리를 통해 사용자에게 상황에 따른 적절한 응답을 제공할 수 있고, 장애 전파를 피할 수 있다.

네트워크 및 성능(서버 or 쿼리) 최적화

네트워크에서 문제가 있다면 해결하고 DB 쿼리 최적화를 하거나 캐싱을 통해 응답 시간을 줄일 수 있다.

정리

이번 글에서는 장애 상황에서 발생한 timeout들에 대해 정리해 보았고, 어떤 상황에서 발생하는지 좀 더 확실히 알게 되었고, 유사한 장애가 발생했을 때 원인 분석에 도움이 될 것 같다.

MSA 환경에서 신뢰성과 안정성이 높은 서비스를 제공하기 위해서는 장애를 빠르게 회복하는 것이 가장 중요하다고 생각한다. 최근 서버의 처리율에 대해 관심을 가지고 있는데 다음 글에서는 요청을 하는 쪽과 요청을 받는 쪽에서 안정성 높은 처리 방법에 대해 정리해 볼 예정이다.

This post is licensed under CC BY 4.0 by the author.

서비스에서 실패에 대한 다양한 처리 방법

-