ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 블록체인 모니터링 시스템 개발기
    Architect 2023. 9. 27. 22:20

     

    이더리움, 바이낸스 스마트 체인(현재는 BNB 스마트 체인), 폴리곤의 블록체인 이벤트 추적기를 개발했었는데, 셋 다 EVM 계열이라 다른 점은 없었다.

     

    이 포스팅에서는 개발하면서 겪었던 문제와 해결을 위해 적용한 방법, 전체적인 아키텍처를 설명하고자 한다.

     

    초기 아키텍처

    굉장히 굉장히 간단하게 Point-to-Point로 구성했다.

     

     

    개발한 계기가 이더리움에 존재하는 자사의 토큰을 바이낸스 스마트 체인으로 브릿징 하는 것이었고 이외의 니즈는 존재하지 않았다.

     

    메시지 큐와 같은 일반적으로 데이터를 서빙할 때 주로 사용하는 시스템은 도입하지 않았다.

    단순 토큰 브릿징 이벤트를 모니터링 하는데에 과한 시스템이었고, 소비 형태가 하나로 정해져있어 메시지 시스템 없이 재처리를 구현하기가 간단했기 때문이다.

     

    아키텍처든 코드든 필요에 의해서 구성되어야 하고 간단할 수록 좋다고 생각한다.

     

     

    메시징 시스템 도입

    중앙화로 개발된 서비스를 점점 탈중앙화로 옮기게 되며 블록체인에서 비즈니스 로직을 계산하는 작업이 점점 많아지게 되었다.

     

    따라서 데이터가 우리 DB에 있는 것이 아니라 블록체인 노드가 들고 있는 경우가 많았는데, 블록체인에서 데이터를 조회하기에는 느릴 때도 있고, 제약도 굉장히 많았다.

     

    유저들에게 원활한 서비스를 제공하려면 블록체인의 데이터를 실시간으로 모니터링해서 우리 DB와 동기화를 시켜야 했다.

    이제는 하나의 이벤트만 존재하는 것이 아니었기에 특정 이벤트에 대한 처리가 되지 않더라도 다른 이벤트에 지장이 있으면 안 되었다.

     

    그래서 초기 아키텍처에서 메시지 시스템을 추가하고, 각각의 컨슈머가 필요한 이벤트를 처리하고 컨슘하는 방식으로 구조를 변경했다.

     

    메시지 시스템은 AWS의 Full Managed 서비스인 Kinesis를, 컨슈머는 AWS Lambda를 사용했다.

     

     

    데이터 누락의 발생

    점점 트래픽이 많아지면서 간헐적으로 데이터가 누락되는 현상이 발생했다.

    원인을 분석해 보니 위 그림의 Block Reader나 메시지 서빙 과정에서 누락되는 것이 아닌, 블록체인에서의 누락이었다.

     

    예를 들어, 유저가 블록체인에서 10번 블록에 트랜잭션을 발생시켰다.

    Block Reader는 실시간으로 이전에 처리했던 블록의 다음 블록부터 현재 블록까지의 모든 데이터를 조회하는데, 우리가 조회하는 블록체인 노드에서 10번 블록이 비었다는 데이터를 준 것이었다. (Infura와 퀵노드를 이중화해서 이용하고 있었다.)

     

    재미있는 점은 현재 10번 블록까지 데이터가 존재한다고 알림을 준 것도 해당 블록체인 노드라는 것이다.

     

    외부 업체에서 발생한 버그이므로 정확한 사유는 알 수 없으나, 한 가지 가설을 세웠다.

    당연히 업체도 대용량 트래픽을 감당해야 하는 만큼, 데이터를 Replication 하여 읽기 노드를 몇 개 올려두었을 것이다.

     

     

    아마 우리에게 최신 데이터를 전달해 주었으나, 간헐적으로 읽기 레플리카에 데이터 복제가 되기 전에 우리의 요청을 복제가 되기 전 읽기 레플리카에서 요청하여 데이터가 없다고 결과를 주지 않았을까 추측했다.

     

     

     

    데이터 누락을 어떻게 해결했나?

    업체에 버그 리포팅을 했었고 고치겠다는 답변을 받았지만 글을 쓰는 현재까지도 해결이 되지 않은 것으로 알고 있다.

    당시, 기다릴 수만은 없었기에 고민 끝에 TCP 프로토콜에서 사용되기도 하는 슬라이딩 윈도우 알고리즘을 응용하여 적용하기로 했다.

     

    TCP 프로토콜이 어떻게 패킷 청크 송수신에 대한 안전성을 보장하느냐 하면 두 가지 방식이 있다.

     

    하나는 송신자는 수신자에게 동기식으로 패킷을 끊어서 보내고, 수신자가 송신자에게 패킷을 받았다고 응답(ACK)하면 송신자가 다음 패킷을 보내는 Stop-And-Wait 방식이다.

     

    두 번째가 TCP 프로토콜을 사용하는 대부분이 이용하는 방식이고, 우리도 사용한 알고리즘인데 바로 슬라이딩 윈도우이다.

    송신자는 수신자가 받을 수 있는(여유분의 버퍼) 패킷 사이즈만큼 청크를 나눠서 보내는데, 수신자는 받은 패킷에 대한 ACK를 보내면 송신자는 ACK 패킷의 다음부터 또 사이즈만큼 청크를 나눠서 보내게 된다.

     

     

    슬라이딩 윈도우 중에서도 패킷을 관리하는 방법에 따라 방식이 세부적으로 나뉘는데 이 글에서는 다루지 않는다.

     

    위 예시에서 블록체인에서 조회할 범위를 넓혀서 이전에 처리된 데이터이더라도 재조회 했으며, 설정한 범위를 크게 넘어가게 되면 정말 데이터가 없었던 것으로 간주하고 ACK로 처리했다.

     

     

    정리

    메시지 시스템 도입과 슬라이딩 윈도우 알고리즘 적용만으로 잘 서비스 할 수 있었다.

     

    블록체인 노드 이중화는 필요에 따라 진행하면 되지만 솔직히 한 업체만 써도 된다. 장애가 많지도 않고, 빠르게 복구되기도 한다.

    정 하고 싶다면 위 아키텍처의 Block Reader에서 통신 ms가 느려지거나 불안정하면 노드를 갈아끼우는 예외 코드를 넣으면 된다.

     

    팁을 조금 더 적자면, 위 알고리즘의 범위는 넓으면 넓을 수록 좋다.

    생각보다 몇백 단위로 잡아도 노드 업체의 상태가 안 좋을 때에는 누락이 될 때도 있다..

     

    데이터의 구조와 발생하는 이벤트 파라미터는 거의 있는 그대로 인덱싱 가능하도록 설계하는 것이 좋다. 생각보다 현재 데이터는 들어왔음에도 과거 데이터가 누락되는 경우도 있다.

    물론, 이벤트를 받으면 그 때에 블록체인 state를 실시간으로 조회해서 갱신하는 것이 베스트이다.

     

    그리고, Transaction Hash와 Log Index를 고유 아이디로 잡으면 안 되는 경우들이 있을 수 있다.

    BNB 체인과 같이 폐쇄적인 블록체인이라면 괜찮겠으나, 다른 퍼블릭 체인들은 블록 재정렬(Block Reorganization)이 발생할 수 있는데, 이 경우 Transaction Hash는 동일하지만 Log Index는 높은 확률으로 변경된다.

     

    따라서, 되도록이면 트랜잭션 내에 고유한 값을 가질 수 있는 다른 값을 도출해내어 구성하는 것이 좋다.

    'Architect' 카테고리의 다른 글

    보안 초보의 라이브 게임 보안 설계 이야기  (0) 2023.09.26
Designed by Tistory.