[입 개발] 로미오와 줄리엣 버그?

해당 블로그는 KT UCloud의 지원을 받고 있습니다.

 

얼마전에 “프라우드넷”의 개발자이자 CEO 로 유명하신 고수 배현직(@imays)님께서 다음과 같은 트윗을 하셨습니다.

[tweet https://twitter.com/imays/status/236734302409351168]

바로 해결 방법까지 달아주셨습니다.

[tweet https://twitter.com/imays/status/236735146672402432]

 

고수분들은 이 얘기만 들어도 무슨 뜻인지 다 아시겠지만, 좀 더 이해를 돕기 위해서 제 경험담과 함께 썰을 풀어보려고 합니다. 제가 백수가 아닐때의 일입니다. A와 B 서버가 있고, A 서버에서는 항상 B 서버에 특정 정보를 저장하는 작업을 했습니다. 그런데, 에러 로그를 확인해보면 가끔씩 A 서버에서는 Timeout으로 인해서 작업 실패가 일어나서 Retry 된 기록이 있는데, B 서버에서는 그런 기록이 존재하지 않는 것이었습니다. 그리고 B 서버에는 특정 정보가 2번씩 저장이 -_-;

 

이것의 원인이 위의 @imays 님이 말씀하신 로미오와 줄리엣 버그였습니다. 이 때 A 서버와 B 서버는 각각 Timeout은 5초로 설정되어 있었고(일반적으로 개발자들은 Timeout을 그냥 동일하게 설정하는 케이스가 많습니다.) 특정 이유로 인해서 B서버에서 응답이 거의 Timeout에 맞추어서 발송되고(성공한) A 서버에서는 이미 Timeout으로 실패 처리하고, 뒤에 들어온 응답을 무시하게 되는 것입니다.

 

결론부터 말씀드리자면 가장 간단한 해결책은 A 서버의 Timeout을 B 서버보다 조금 길게 가져가는 방법으로 해결할 수 있습니다. 그런데, 이 것은 꽁수고, 조금 문제가 있습니다. 다음 제 트윗을 보시면 저는 이렇게 해결했다라고 했습니다만…

[tweet https://twitter.com/charsyam/status/236737384476192768]

 

그렇다면 무슨 문제가 있을까요? 단순히 A – B 서버의 경우에는 한 쪽을 느린다거나 하면 해결이 되지만, 이것도 완벽한 해결책은 아닙니다. Latency가 큰 네트웍에서는 아주 약간의 차이는 같은 문제가 여전히 발생할 수 있습니다. 또한 여러 대의 서버가 있어서 연쇄적으로 호출을 한다면, A -> B -> C -> D -> E 가 된다면 A는 결국 E의 Timeout 보다 꽤 큰 값을 Timeout으로 잡아야 할 것입니다. 이러면 DDOS 등의 문제가 발생할 수 도 있습니다.

 

그럼 뭔가 다른 해결책이 있을까요? 솔직하게 말씀드리면, 특별히 생각나는 방법은 저는 없습니다. T.T(저희는 호출 depth가 길지 않아서 Timeout 변경으로 해결이 쉽게 되었던 케이스라서요.) 뭐, 실패/성공에 대한 Ack을 하나 더 보내는 방법도 있을 듯 한데, 이것 또한 여러가지 이슈가 추가로 발생하게 될 것 같습니다. 오늘은 그냥 고민거리만 던져드리고 도망가도록 하겠습니다. 후다닭~~~~