RPC 프레임워크 맨땅에서 헤딩하기 2탄

emptynote의 이미지

부재 : 나의 첫번째 서버 실패 이야기

제가 만든 첫번째로 서버는

"자바 IO & NIO 네트워크 프로그래밍" 라는 책에서 소개한 향상된 서버를 참고하였습니다.

저는 servlet/jsp 개발자로 시작했기에 입력 메시지를 받아 처리하는

비지니스 로직을 servet 과 유사하게 만들었고

servlet/jsp 처럼 동적 클래스 로더에 의해 로딩하여 실행시키는 구조였습니다.

웹 프로그래머가 처음부터 시스템 프로그램을 잘 만들리 없지요.

더구나 저는 그저 그런 개발자라 더욱 그렇습니다.

입력 메시지를 보낸후 딴짓을 할 수 있는 비동기식 메시지 처리 로직이 잘 동작해서 참 기뻐습니다.

사람들이 비동기 비동기 노래를 부르는 이유를 조금 알것 같았습니다.

하지만 딱 거기까지였습니다.

성능을 측정하는 첫단계로 저는 파일 송수신 부터 만들게 되었습니다.

동기식과 비동기식 2가지 버전으로 만들었습니다.

결론 부터 말하면 비동기는 완전히 망했습니다.

단 1개 연결로 CPU 100% 까지 올라 가더군요.

그리고 네트워크 전송양을 보면 거의 100% 까지 올라가더군요.

그 일이 있고 한동안 왜 CPU 100% 가 생기는지 원인을 잘 몰랐습니다.

그저 그런 개발자가 그렇지요. 뭐~

그러다가 입력/출력 메시지를 보내는 소켓 쓰기 로직에서 문제가 발생함을 알게 되었습니다.

while(데이터가 존재한다면) {
socket.write(데이터);
}

이런 로직이였거든요.

만약에 이 로직의 문제점을 즉각적으로 알지 못한다면

그렇습니다. java API 인 socket.write 에 대한 이해를 저처럼 못하고 계신겁니다.

socket.write 는 실질적으로 쓰여진 바이트를 반환하는 API 입니다.

이때 0을 반환할 수 있습니다.

API 문서 보면 설명이 잘 나왔지요. 그런데 말입니다~

0 을 리턴한다는 말은 무엇일까요?

"자바 IO & NIO 네트워크 프로그래밍" 라는 책에서는 다이렉트 버퍼에 대해서 설명을 할때 커널의 데이터 송수신 동작 방법에 대해서 대략적인 설명을 해주고 있습니다.

여기 내용을 보면 커널에서는 응용 어플에서 보낸 데이터를 송신 버퍼에 담아 네트워크 전송을 한다는것입니다.

이 내용으로 socket.write 동작을 재 구성을 하면 응용 어플이 socket.write 를 호출하여 실질적으로 커널의 송신 버퍼에 쓰여지는 양은 커널 송신 버퍼가 실질적 전송에 의해서 비워진 만큼의 양이라는것입니다.

하여 socket.write 의 반환되는 값을 로그로 추적해 보면 중구난방이고

데이터 송수신하는 시간이 필요하므로 버퍼가 꽉찬 상태에서 그 시간 동안은 0을 반환한다는것을 알 수 있습니다.

그 시간 동안 루프만 뺑뺑이 돌아가며 이것이 CPU 100% 주범이였던 겁니다.

이 문제를 해결 하기 위해서는 어떻게 하면 좋을까요?

그 이야기는 다음에 하도록 하겠습니다.

"자바 IO & NIO 네트워크 프로그래밍" 책에서 소개한 향상된 서버 : https://zeroit.tistory.com/entry/NIO-%ED%96%A5%EC%83%81%EB%90%9C-%EC%84%9C%EB%B2%84-%EB%A7%8C%EB%93%A4%EA%B8%B0

Hodong Kim@Google의 이미지

입출력 다중화라는게 있습니다.
http://www.apuebook.com/about3e.html 이 책 추천합니다.
입출력 다중화에 대한 아래 문서 추천합니다.
https://www.joinc.co.kr/w/Site/Network_Programing/Documents/Poll
자바에도 이렇게 있을 것 같고, 없으면 JNI 를 이용해서 만들어야겠죠.