서버 시간과 ms 단위 동기화 하기

작성일 : 2023년 09월 25일
  • #HTTP

새로운 과제를 해결해나가는 과정은 항상 흥미로운 것 같다. 요즘엔 서버시간을 ms 단위로 동기화 할 수 있는 방법에 대한 과제가 주어졌다. 이 과제를 풀어나가는 도중 서버 시간을 맞추기 어렵다는 내용의 영상을 접하게 되었다. 과연 서버시간을 ms 단위로 동기화 할 수 없을까? 이에 대한 내 의사 결정과 풀이 방법에 대한 내용을 작성 해본다.

요구사항

  1. 과다한 요청을 방지하기 위해 최대 초당 1번의 요청만 보내도록 한다.

  2. 요청 전송 시간을 고려해 네트워크 지연시간을 계산하지 않는다.

기반 사항

  1. HTTP 프로토콜을 을 사용하여 요청 서버에서 응답하는 Date 헤더를 동기화를 시도한다.

    • HTTP Date Header는 메시지 발생 시간과 근사한 서버 시간으로 설정 된다.

    RFC7231Hypertext Transfer Protocol (HTTP/1.1): Semantics and ContentSection 7.1.1.2 Date


    When a Date header field is generated, the sender SHOULD generate its

    field value as the best available approximation of the date and time

    of message generation. In theory, the date ought to represent the

    moment just before the payload is generated. In practice, the date

    can be generated at any time during message origination

  2. 상기 방법은 초 이하 단위를 알 수 없기 때문에 요청 간 초단위 시간 변화를 관찰하며 서버 시간의 SS.000을 찾는다.

  3. 로직 진행 중 지연을 최소화 하기 위해 java.time 패키지 대신 가능한 System 클래스를 사용하도록 한다.

    • System.currentTimeMillis()의 경우 평균 1600ns → 0.00000016s

    • ZonedDateTime.now()의 경우 평균 11000000ns → 0.0011s

    • 요청 헤더의 RFC1123 형식 날짜 변환을 위해선 java.time을 쓰긴 해야한다.

      → 소수점 3자리 이후의 지연은 고려하지 않도록 하는게 좋겠다.

구현 방법

image.png


서버는 1s의 텀을 가지고 시간이 변한다고 가정한다.

요청은 위 예시와 같이 1s ~ 2s 사이의 임의 값 1을 설정해 요청을 한다.

각 응답의 시간차는 1s의 텀을 가지나 Hit가 발생한 시간에 2s의 텀이 발생한다.

그렇다면 서버 시간을 최대 임의 값 1 만큼의 오차로 알 수 있게 된다.

네트워크 지연 등의 텀을 여유롭게 두어 Hit 당시 시간에서 임의 값 1 + a 만큼 요청할 시간을 당긴 후,

임의 값 1보다 낮은 임의 값 2로 위 과정을 반복한다.

위 과정을 통해 1ms까지의 오차로 줄여 나가면 서버 시간과 동기화 할 수 있다.

예외 사항 및 해결 방안

위 방법을 통한 동기화에서도 예외가 발생한다.


첫번째로 네트워크 혹은 서버 로직 동작 중 오차가 발생하는 경우다.

이런 오차가 발생 할 경우 서버 기준 시간이 아닌 경우에도 2s의 텀이 발생 할 수 있다.


이러한 오차를 줄이기 위해 지속적인 요청을 통해 각각의 동기화 시간의 평균을 내어 근사치로 맞출 수 있도록 한다.


두번째로 요청 후 응답 지연시간이 과도하게 길어질 경우다.

요청 시간을 고려한다면 적절한 값이 나올 수 있으나 요청 - 응답간 지연이 1초 이상인 경우 요청 시간이 지켜지지 않아 큰 오차가 발생한다.


timeout을 1초 이하로 설정해 1초 이상의 요청은 예외로 처리하도록 설정한다.


세번째로 요청 시간을 1초 이하로 설정해 시간을 맞추는 경우다.

1초 이상 설정한 것과 반대로 1초 미만으로 설정해 1초에 근접해가며 시간을 맞추는 방법도 생각 해 볼 수 있으나 특정 사이트에선 전혀 다른 결과를 가져오는 경우가 있었다.


시간은 1초 이상으로 설정해 1초에 근접해가며 맞추도록 한다.

거기에 더해 1초 미만으로 설정 할 경우 당초 요구사항인 최대 초당 한번의 요청을 넘어서게 되므로 이 방법은 사용하지 않는다.