TCP 소켓을 행복하게 만들기

[JA] Making TCPSocket.new "Happy"! / Misaki Shioi @coe401_

작성자
RubyKaigi
발행일
2025년 05월 27일

핵심 요약

  • 1 Ruby 3.4에 Happy Eyeballs Version 2 알고리즘이 도입되어 `Socket.tcp` 및 `TCPSocket.new`의 네트워크 연결 효율성이 크게 향상되었습니다.
  • 2 초기 `Socket.tcp` 구현의 상태 관리 복잡성과 `TCPSocket.new`의 `FD_SETSIZE` 한계 문제를 `rb_fd_select` 활용으로 해결하며 견고성을 확보했습니다.
  • 3 Happy Eyeballs 도입으로 특정 최악의 시나리오에서 연결 시간이 132배 단축되었으나, 미미한 성능 오버헤드가 관찰되어 필요시 비활성화 기능이 제공됩니다.

도입

본 발표는 Ruby의 네트워크 라이브러리에 Happy Eyeballs Version 2 알고리즘을 도입하는 과정을 상세히 설명합니다. 기존 Ruby의 `Socket.tcp` 및 `TCPSocket.new` 메서드는 IPv6와 IPv4 주소를 순차적으로 처리하여, 한쪽 주소의 이름 확인이나 연결이 지연될 경우 전체 연결 과정이 불필요하게 길어지는 문제가 있었습니다. Happy Eyeballs Version 2는 이러한 비효율성을 극복하고, 여러 주소 패밀리에 대한 이름 확인 및 연결 시도를 병렬로 수행하여 더 빠르고 효율적인 네트워크 연결을 목표로 합니다. 이는 2024년 RubyKaigi에서 발표된 `Socket.tcp` 구현의 후속 작업으로, C로 구현된 `TCPSocket.new`에도 동일한 개선을 적용하는 과정을 다룹니다.

Happy Eyeballs Version 2 알고리즘은 Ruby의 Socket.tcp 메서드에 먼저 적용되었습니다.

Socket.tcp 구현 개선

  • 초기 문제점: Socket.tcp의 초기 상태 머신 구현은 이름 확인 동시 완료 시에도 순차 처리하여 IO.select의 불필요한 호출과 복잡성을 야기했습니다.
  • 개선: 명시적 상태 관리를 제거하고, IO.select 호출을 중앙 집중화했습니다. 모든 이전 연결 시도가 실패한 경우 다음 연결 시도를 즉시 진행하도록 connection_attempt_expires를 리셋하는 로직이 추가되었습니다. 이 개선된 Socket.tcp는 2024년 7월 30일 Ruby 3.4 마스터에 병합되었습니다.

TCPSocket.new 통합 과정

C로 구현된 TCPSocket.new에 Happy Eyeballs를 적용하는 과정은 기존 C 라이브러리의 제약에 직면했습니다. * 이름 확인 제약: 기존 이름 확인 함수는 병렬 처리 및 파이프/select를 통한 연결 대기에 부적합했습니다. * 전용 메커니즘: init_fast_fallback_inet_sock_internal 함수를 통해 주소 패밀리별 스레드를 생성하고, 파이프와 select 시스템 호출로 이름 확인 및 연결 완료를 동시에 모니터링하는 새로운 메커니즘을 구축했습니다.

주요 결함 및 해결책

  • CI 타임아웃: TCPSocket.new 병합 후 Net::HTTP 테스트에서 IPv6 연결 실패 후 connection_attempt_delay로 인한 타임아웃이 발생했습니다. 실패한 연결 시도 후 connection_attempt_expires를 즉시 리셋하여 해결했습니다.
  • FD_SETSIZE 한계: select 시스템 호출의 FD_SETSIZE 제한으로 파일 디스크립터 수가 많아질 때 세그멘테이션 폴트가 발생했습니다. Ruby의 IO.selectrb_fd_select 함수를 통해 동적으로 fd_set 비트맵을 확장하여 이 문제를 해결하는 것을 확인하고, TCPSocket.new 또한 해당 래퍼 함수를 사용하여 문제를 성공적으로 해결했습니다.

결론

이러한 광범위한 개선 작업을 통해 Happy Eyeballs Version 2는 2024년 12월 25일 Ruby 3.4.0 및 3.4.1 릴리스와 함께 Ruby의 소켓 라이브러리에 성공적으로 통합되었습니다. 성능 측정 결과, IPv6 이름 확인 지연과 같은 최악의 시나리오에서 연결 시간이 약 132배 단축되는 극적인 개선을 보였습니다. 다만, Happy Eyeballs 활성화 시 약간의 성능 오버헤드가 관찰될 수 있으며, 특정 서버 환경(예: 다중 연결 제한)에서는 문제가 발생할 수 있으므로, 필요에 따라 비활성화할 수 있는 API가 제공됩니다. 본 프로젝트는 커뮤니티의 지속적인 피드백과 협력을 통해 발전했으며, 발표자가 Ruby 커미터가 되는 계기가 되기도 했습니다. 이는 Ruby 커뮤니티의 활발한 참여가 Ruby 언어의 지속적인 발전에 기여함을 보여주는 사례입니다.

댓글 0

댓글 작성

0/1000
정중하고 건설적인 댓글을 작성해 주세요.

아직 댓글이 없습니다

첫 번째 댓글을 작성해보세요!