조금 더 설계에 대해 고민하다가.. 완전 말림..
//서버단
1.하나의 스레드가 하나의 셀렉터(set자료구조)를 관리하게한다.
1.1 하나의 셀렉터는 최대 63개의 클라와 통신채널, 1개의 서버 어셉용채널을 커버 (숫자가 맞는진 모르겠다)
1.2 셀렉터와 어셉용 서버채널, 클라의 전송을 read할 채널, 연결된 클라들에 write할 채널 각각의 독립적인
작업을 분리한후, 하나의 추상개념으로 캡슐화할 필요가 있다. (ex)채팅룸
=> 셀렉터 = 하나의 스레드로 여러개의 소켓 채널을 관리한다는 의미가 맞을듯?
(etc)-셀렉션키= 셀렉터(이벤트 감시자&발행자)와 연결된 채널(이벤트 수신자)간 중간에서 .. 특정 이벤트
와 특정 채널간의 관계를 의미(한마디로 셋 컨테이너에서 iterator의 개념)
-소켓채널의 blocking 여부는 채널 단위에서 세팅하고 그 후에 셀렉터에 등록하는 것이다.
- 채널이란 외부의 이벤트에 대해 반응(대응)할수 있는 범위 개념. 여러 종류의 채널별로 대응할수 있는 외부
(네트워크) 이벤트가 정의되어 있다.
2.동접 5000명이면.. 셀렉터 약 100개 필요? 셀렉터 풀을 만든다.;; (스레드 100개니?)
3.셀렉터에게 배정할 채널(소켓)을 미리 만들어두고 풀에 관리한다. (셀렉터.open() 해서 생성 안하게)
4.온갖 작업을 할수 있게끔 워크 스레드풀을 활용한다.
4.1 서버측은 어셉 작업용 스레드 배정(3~5개쯤?)
4.2 리드 작업용 스레드 배정(몇개쯤? 좀 많이?)
내가 패킷(헤더+바디)을 사용하려 하고 + 거기다가 그제,어제 공부했던 보안 패키지 클래스를 사용하려 하다
보니.. 패킷 헤더 해석 작업이 들어가고 그 해석에 따라서 클라들에게 전송or 기타 작업을 하게 될듯하다.
4.3 위의 클라들에게 전송 작업용 스레드 배정(음.. 이건 4.2에 순차적 의존 관계가 있으니.. 따로 스레드 처리 안될듯)
4.4 서버에 로그or콘솔창에 뿌려줘야 하니까 이 용도로 스레드 배정(이것도 과연 필요할지.. 한글자 한글자 출력할게
아니면.. 4.2의 리드작업을 통해 모든 데이터를 가져온후, 그에 따른 해석에 따라 콘솔에 뿌리던지.. 로그를 찍던지
할것 임으로.. 스레드의 생성이 과연 필요할지..)
=>서버 측에서 중요한건.. accept , read 에서 blocking이 되는 현상이다. 이걸 일단 nio패키지의 셀렉터, 다이렉트
버퍼를 이용해 해결이 된다 하지만.. 내가 멀티스레드를 적극적으로 활용하려는 이유는 서버 컴퓨터의 성능(cpu갯수)
을 전부 활용하고 싶기 때문이다. 한마디로 순차적 의존성(데이터든 연산이던)이 없는 비지니스에 대해서 스레드들
을 적극적으로 사용하고 싶다. 솔직히 까놓고 얘기해서 어셉을 담당하는 스레드가 1개일 경우와 5개일 경우.. 동시접속
요청이 1000건 발생했을때.. 1개의 스레드로는 요청1개씩 처리를 하게 되기에.. 사용자가 열이 받을 것이다.
4.5 클라측도 장난이 아니다;; 소켓에서 읽기 작업용 스레드 배정
4.6 패킷을 해석하는 스레드 ?? 4.5에서 처리해야 할지..(일단, 헤더만 읽으면 명령을 생성할수 있고. 흠.. 근데 바디
데이터가 반드시 필요한 명령이라면?)
4.7 패킷의 분석 결과가 채팅 관련 데이터라면.. 콘솔이던 사운드 재생이던 동영상 재생이던.. 작업용 스레드 배정;;
4.8 사용자의 입력을 처리하는 스레드 1명
4.9 입력한 값을 해석해 패킷을 구성하는 스레드.(파일 전송이면;; 파일 로드용 스레드?)
5.0 만들어진 패킷을 서버로 발송하는 스레드 (마찬가지로 4.9와 5.0은 4.8에 순차적 의존 관계에 있다. 왜냐하면 4.8
에서 사용자의 엔터키or 다른 입력 완료 메세지가 발생해야 사용자의 비지니스 하나가 만들어지기 때문이다.)
=>클라측에서 중요한건.. 사용자 입력 -> 서버로 전송 작업은 순차적 의존 관계에 있기 때문에 싱글 스레드면 족하지만,
지난 글에서 고민했듯.. 사용자 입력중에도 서버가 전달해주는 다른 채팅자들의 데이터는 읽어와서 유저의 화면에
갱신(추가)을 해줘야 한다. 즉 두개의 작업이 병렬처리됨과 동시에.. 추가로 고려할 점은 유저가 채팅중에 이미지,
동영상 등을 전달했을때.. 이것을 처리하기 위해 새로운 작업 스레드가 필요할 것이다.
(물론 송수신 데이터패킷을 가볍게 하기 위해 가급적 채팅 화면에 동영상 추가, 파일 전송등의 비지니스를 요청할
경우 서버측에서는 다른 채팅자에게 수락/거절 등의 메세지를 전달하고 다른 채팅자가 수락을 했을 경우에
직접 파일 전송이 아닌, 동영상등 파일의 소유자와 수락을 한 요청자간 둘이서 직접 파일을 주고 받게끔 클라프로
그램에 명령을 전달하는것이 옳을 것이다. 서버측은 채팅 서비스를 제공함에 있어서 관리자의 입장에서 필요한
데이터의 추출, 관리적 비지니스를 처리해야 하기 때문에.. 서버는 중계의 역할만 하는 것이 옳을 것이다)
=>결국 위의 여러 고민들은 스레드를 통한 병렬처리의 도입이다.(순차적 의존이 불필요한 동작들을 독립적으로 처리시
킴)
(etc) 소켓채널의 경우 기본적으로 하나의 통로로서 readable,writeable 혼용이다. 즉 읽는 도중 쓰기가 있으면
기존 읽기 작업이 멈추게 된다. (-1리턴 식으로) 이는 blocking이 된것이다. 소켓 채널이 비동기화에 대해 안전하다
는 것은 예를 들어 하나의 스레드가 읽기 작업 도중 다른 스레드에게 제어가 넘어가 입력을 끊었을때.. 기존 읽기를
취소하고 -1을 리턴하며, 기존 중단된 스레드 객체는 AsynchronousException을 전달 받으면서 깨어나기 때문에..
catch 블럭에서 적절하게 핸들링이 가능할 것이다.
5.DirectByteBuffer 풀을 활용한다.(미리 왕창 만들어두고 재활용하기)
5.1 non blocking 상태에선 read작업을 100% 성공한다고 확신해선 안된다. 네트워크의 사정에 따라, 네트워크 디바이
스의 성능에 따라 .. 일부만 읽어올수 있다. 그럼으로 패킷의 헤더에 전체 패킷의 길이를 심고, 완전히 얻었을때 까지
스레드를 반복문에서 sleep or blocking 할필요가 있다. 단 주의해야 할점은.. 네트워크 종료등의 상황이 발생시 스레
드가 lock을 걸고 나갔다면.. deadLock 현상이 발생할수 있다. 그럼으로 스레드 작업 사용시.. 제한시간의 개념을 추가
해줘서 위와 같은 위험을 방지한다.
5.2 다이렉트 버퍼는 object단위를 표현 못한다. (한마디로 일반 io의 readObject 단위가 불가능) 그럼으로 gatherring/sc
atteringByteBuffer 인터페이스의 필요성이 발생한다.(이게 없으면 개발자가 일일히 모든 패킷에 따라 readInt , readChar
,length 식으로 처리를 해야한다. 아참.. 버퍼를 사용할때 flip()을 주의할것!
위의 게더링,스케틀링 인터페이스를 이용해 바이트 버퍼를 개념단위로 생성후 객체의 데이터 구조처럼 묶어서 관리가
가능해진다. (참고로 socketChannel 클래스에 구현이 되어있었다. 어제 이것땜에 고민한것 생각하면 -_- +)
6.한글 깨질수 있다. 안그래도 복잡해서 nio패키지중 charset인가를 외면했는데.. 장착해야 한다 ㅠ.ㅠ
6.1 이 문제는 채팅 프로그램의 로컬라이제이션에도 걸리게 된다. 그럼으로 적절하고 유연한 처리가 필요하다.
6.2 그럼으로 java.nio.chrset + charBuffer(2byte 유니코드 단위 다이렉트) 를 이용하면 풀리지 않을까 생각하는데..
6.3 한글 완성형의 코드 포인트 범위는 U+AC00~U+D7AF이므로, (44032 ~ 55215 = 11183개)
UTF-8 인코딩에서 한글은 무조건 3바이트 인코딩이다.
그래서 URL에 파라미터 값이 %ED%95%9C%EA%B8%80과 같이 표시된다면 UTF-8 인코딩일 확률이 높다(ISO8859,
EUC-KR, UTF-8 인코딩 중 하나라면 말이다). (왜냐하면 4비트 6개 = 3바이트)
7.셀렉터의 register()의 3번째 메개변수로 Object를 등록할수 있는데.. (한마디로 해당 소켓의 op_read 이벤트에
대해 특정 객체or연산을 수행가능..) 이걸 이용해 클라와 세션, 명령에 따른 비지니스 로직.. command 패턴으로
구현하려 고민햇었지만, 패킷 헤더에 정보를 심는 작업으로 변경.
=>음.. 3번째 요 정보를.. 셀렉션키에 설정할수 있었지.. read입력 발생시마다 워크스레드 사동 수행 시키게 가능할
까? 말이 되나?
8.아참.. 아까 설계상 엄청 고민했었는데.. 내 경운 서버에서 리드 작업용 객체와 브로드 캐스트 작업용 객체를 구분하려
했고, 패킷(헤더,보디)를 사용하기로 결정했기에.. 스캐플링 바이트 버퍼 채널 인터페이스, 개더링 바이트버러 채널 인터
페이스, 소켓 채널 클래스를 도대체 내 리드 작업용 클래스와 브로드 캐스트 작업용 클래스가 상속받고 구현할 것인지..
이리저리 고쳐가며 오랫동안 고민했었는데.. 소켓 채널 클래스 도큐 문서를 다시 확인하면서.. 소켓 채널 클래스가 이미
개더링,스캐플링,기타 비동기화(인터럽티블),읽기,쓰기등의 인터페이스를 구현했다는 것을 확인하고 쇼크받았다.
=> 난 지금까지 도큐문서에서 클래스 정보를 볼때.. 클래스 명세,메서드 동작, 클래스 계층구조만 살폈지.. 구현한 인터페이
스까지(조립제품) 꼼꼼히 살펴보지 않았다. 그 클래스가 도대체 무엇을 처리하기 위해 상속 계층 구조에 포함이 되었으며,
어떠한 인터페이스로서 조립이 되었는지.. (하다못해 자바에선 스레드를 클래스로도 제공하고, runable이란 인터페이스
로도 제공을 한다;;)
9.패킷(전송용 데이터의 크기및 구성 단위)의 크기를 가급적 작게 유지해야한다. header부분은 4byte 정도 배정해서
메세지의 형태를 표현하고, 하나의 패킷의 총 길이를 담아야 할것이다. body 부분의 데이터는 최대한 줄여야 하기 때문에
압축 알고리즘을 사용하고 수신및,송신한 클라이언트 측에서 encode decode 할수 있게끔 하는 방법도 필요하다.
아까 생각해본 유저간 파일 전송등의 기능이 필요할 경운.. 클라이언트 간에 p2p로 데이터 전송하게끔 클라이언트 프로그램
을 작성해두면 될것이다.
9.1 네트워크를 이용한다는 측면.. 내 시스템을 외부의 공격에 노출을 시키는 것임으로.. 보안의 개념(인증,권한 설정, 데이터
암호화의 개념을 적용시켜야 하는 것은 선택이 아닌, 필수라 생각한다)
9.2 위의 문제들중 몇몇은 tcp layer 에서 잡아주지 않을까 싶다? udp와 다른 tcp는 신뢰 가능한 전송 데이터니까..
네트워크 레이어에 대한 개념이 제대로 안잡혔다. 네트워크 디바이스 단부터..(다이렉트 바이트 버퍼의 개념이
디바이스 메모리에 대한 직접 접근및 제어니까..) 몇 계층이 있었는데.. 흠..
10. 서버의 메모리 부족을 대비해 FileChannel을 통해 파일(hdd)을 메모리로 사용하게 할 수 있다.
11. 실제 카톡에서 어떤식으로 서비스를 제공하나 봤는데.. 대단한건 안보였다. 다른 작업(동영상 시청중)중 동시에
카톡 프로세스도 실행되는건.. 휴대폰os 차원에서 지원해줄 일이고.. 실제 카톡 내부에서 함께 동영상 보기, 파일
전송등은 없고.. 링크 표시(문자열 + 링크 엑세스 지원만 해주면 간단) , 몇몇 이모티콘류(이건 클라이언트 배포할때
패키징 하면되고.. 추가시마다 업데이트 해주면 되니까..) 정도이다. 채팅 룸의 개념을 이미지로 표시함으로서 인터
페이스가 괜찮고.. 사용하기 쉽다.
12. 채팅 클라,서버의 뼈대를 화면처리(view)에 대해 독립적으로 구성시키고.. 각종 컨트롤(비지니스)에 대한 설계적
고민이 필요할 것이다. (글고 역시나. 채팅이기에 udp = datagram 의 사용도 고려해 볼만하다)
13.결국 서비스 하면서 발생할 각종 예외 상황들에 대해 미리 시뮬레이션을 통해 감지한후 처리 로직을 만들어야 한다.
이부분은 실무 경험에 크게 좌우되리라 생각한다. (실제 서비스를 해봐야 해당 서비스에 맞는 여러가지 예외가 발생
할테니.. 중국 해커들은 대단하다..)
하여튼 관건은.. 스레드풀및 각종 풀의 구현이었다 -_-;;
분명히 풀을 지원하는 클래스 or 패키지가 있을거라 생각해서 뒤져보았다.
(랭 패키지의 스레드 그룹 , 유틸패키지의 큐 자료구조를 이용해 직접 구현은 말이 안되고 -_-;
더 뒤져보니 유틸패키지.콘커렌트 패키지에.. 스레드 풀 익스큐터;; 익스큐터란.. 말도 안되는 팩토리의 팩토리 클래스..
스레드 팩토리까지 제공.. 익스큐터.캐쉬드스레드풀인가 느낌이 좋더만;;)
일단 풀링을 사용할 경우의 코드 형태 checkout() checkIn() 마음에 드네 하.하.하 (일단 풀에서는 맵계열vs셋계열
vs큐vs스택vs리스트계열vs어레이계열vs트리계열 과연~ 정답은? ㅋㅋ )
오늘은 설계한답시고 깝죽대고.. 코드 몇줄 구현하고.. 나머진 온갖 새로운 지식 습득하려 삽질을 하다가.. 좌절중..이다..
스레드를 100%이해를 못하는데, 어찌 스레드 팩토리, 요청 폴링, 스레드 풀링을 구현할 것인가? 완전한 비동기식 i/o, 멀티
스레딩처리, 폴링, 풀링 개념.. 자잘하게.. 패킷 구조 설계와 확장성 고민.. 각종 디자인 패턴들.. 암호처리..
결국 내 정신은 안드로메다로 떠나버렸고.. 심각하게 의욕이 감퇴되고.. 우울해졌다.
애초 계획대로 초 심플하게 다자간 채팅 + nio 방식의 i/o + 병렬 처리 가능한 작업 하나당 스레드 한개씩 사용 ...
이것조차 구현할 수 있을지 걱정이 태산이다. 이것저것 벌려놓고 제대로 하는게 없어서 속상.. ㅠㅠ 내일은 한결 낫길!
요2일동안.. jsp 진도 전혀 못나갔다. (보안관련,j2ee 프레임워크 관련,EJB3.0관련,스프링 관련,이번 채팅 프로젝트 설계
고민, 온갖 잡다한 정보들 찾기..)
etc)자바소켓 프로그래밍 참고 블로그
Class NIOServerCnxnFactory
RECENT COMMENT