피드로 돌아가기
Dev.toBackend
원문 읽기
cubic이 SFTP의 단일 요청 대기 방식을 SCP 프로토콜로 교체해 파일 전송 성능 병목 해결
Why Your SFTP Transfer Is Stuck at 2 MB/s (and the Fix Is a Protocol from 1983)
AI 요약
Context
cubic은 russh-sftp 크레이트를 사용해 파일 전송을 구현했으나, 274 MB 파일을 localhost로 복사하는 데 2분이 소요되는 성능 문제가 발생했다. russh-sftp의 AsyncWrite 구현은 매번 poll_write() 호출 시 일회용 채널을 생성한 후 서버 응답을 대기하는 방식으로 동작했다. 이로 인해 255 KB 기본 쓰기 크기로 274 MB 파일을 전송할 때 약 1,075개의 왕복 요청이 발생했으며, loopback 링크에서도 누적된 요청당 오버헤드가 전송 시간을 크게 늘렸다.
Technical Solution
- SFTP 파이프라이닝 미지원 근본 원인 파악: RFC 4253에서 지원하는 다중 미처리 요청(OpenSSH의 기본값 64개)을 russh-sftp가 구현하지 않아, 모든 Rust 프로젝트가 약 2 MB/s로 제한됨
- 단일 파일 전송용 SCP 프로토콜 구현: 새로운 scp.rs 모듈(약 170줄)을 추가해 SSH exec 채널 위에서 헤더 한 줄 후 원본 바이트 스트림 전송
- 전송 메커니즘 조건부 라우팅: host-to-guest 단일 파일 전송은 SCP로 처리하고, 디렉터리 복사와 guest-to-guest 전송은 기존 SFTP 유지
- guest-to-host 폴백 처리: SCP 시도 후 실패 시(디렉터리의 경우) SFTP로 자동 전환
- AsyncTransferView와 분리된 구조 설계: 진행률 표시 로직을 async_copy 함수에 통합하여 향후 전송 메커니즘 교체 용이성 확보
Impact
loopback 링크에서 약 2 MB/s 제한에서 벗어남(구체적 달성 속도 수치는 미제시).
Key Takeaway
프로토콜 설계의 파이프라이닝 지원 여부가 스트림 기반 데이터 전송 성능을 크게 좌우한다. 상위 프로토콜의 한계를 식별한 후 특정 사용 사례에 최적화된 하위 프로토콜로 대체하는 것이 효과적인 성능 개선 전략이 될 수 있다.
실천 포인트
Rust에서 SFTP를 통한 대용량 파일 전송이 필요한 경우, russh-sftp의 파이프라이닝 미지원으로 인한 2 MB/s 병목을 피하려면 SCP 프로토콜로 우회하거나 업스트림 이슈 #70의 해결을 기다려야 한다. 단일 파일 전송과 디렉터리 전송을 구분해 처리하면 성능 저하 없이 모든 시나리오를 지원할 수 있다.