개발 중 발생했던 골치 아팠던 이슈 복기용으로 적는다.
발단
Node.js에서 aws sdk를 이용해 S3에 파일을 업로드 할 일이 생겼다. 적당히 개발 후 돌려보는데 Node.js단에서 자꾸 크래시가 나는 일이 계속되었다.
[1] /Users/mango/.nvm/versions/node/v16.9.0/bin/node[56951]: ../src/node_http_parser.cc:517:static void node::(anonymous namespace)::Parser::Execute(const FunctionCallbackInfo<v8::Value> &): Assertion `parser->current_buffer_.IsEmpty()' failed.
Assertion 'parser->current_buffer_.IsEmpty()' failed.
???
이게 웬 에러야
대체 이게 무슨 에러지 하고 찾아보았는데, 다음과 같은 Opened Issue가 있었다. Opened Issue만 보면 머리가 지끈거리기 시작하면서 어지러워진다. 심지어 만들어진 지 1년이 넘은 이슈다. 대체 무슨 문제길래? 여튼 한 번 내용을 보자.
S3로 대용량 파일을 올리려다 발생한 에러라고 한다. 로컬 머신에서는 잘 작동하는데, EKS로 올린 EC2에서는 data size 관계 없이 항상 발생한다고 한다. 대체 왜 그럴까?
밑의 의견들을 보니, 파일 사이즈를 정확히 5MB으로 올렸을 때, Multipart Upload chunk를 2개를 만드는데, 첫번째 chunk에 데이터가 5MB 다 들어가고 두번째 chunk가 텅텅 빈 채로 body에 들어가게 되면서 문제가 생긴다는 주장이 있다. 그런데 왜 0 byte body를 받는다고 죽는 걸까?
더 자세한 문제를 보기 위해 Node.js쪽을 보자. 여기에도 관련 이슈가 올라와 있다.
Basically the AWS server sends first a HTTP/1.1 100 Continue as requested and then the HTTP 200 OK.
If the two messages are received too closely (less than 5ms away) then the execute is somehow called on the same parser before the previous call even returns.
Node.js가 100 Continue
와 200 OK
를 짧은 시간(5ms) 이내에 동시에 받게 되면 제대로 파싱하지 못하고 죽기 때문이다.
이제 5MB 파일을 업로드하며 테스트했던 사람의 케이스가 이해가 되기 시작한다.
용량이 0인 chunk라면 처리 속도가 매우 빠를 테니 짧은 시간 내에 두 개 이상의 chunk response를 받게 될 가능성이 올라가고,
한 번이라도 그런 문제가 발생하는 순간 Assertion crash.
경험상 어떤 크기의 파일이라도 여러번 시도하다 보면 한 번씩 터졌기 때문에, 무조건 터질 가능성이 있다고 봐야 했다.
고쳐주세요
AWS SDK쪽에선 고칠 생각이 없었고(생각해보면 당연하다. Node.js의 버그인데 AWS쪽에서 고칠 이유가?), 다행히도 Node.js쪽에서 패치를 했기 때문에, 해당 버전 이상(v18.6.0+, v16.17.0+)의 Node.js에서는 위 버그가 일어나지 않는다.
생각해보면 꽤 위험한 서버 취약점이 될 수도 있는 버그같다. 사용자 입력 주소로 요청을 보내는 서버라면, 그 서버를 죽일 수 있는 것 아닌가? 지금은 고쳐져서 정말 다행이다.
Reference
https://github.com/aws/aws-sdk-js-v3/issues/2843