본문 바로가기
Programming/JAVA

[JAVA] Netty 클라이언트 재접속 연결 오류 (isRegistered)

by Pendine 2021. 10. 8.
728x90

어이가 없다.

 

테스트 환경에서는 미친것처럼 해놔도 재현이 안되는데

현장에서 가끔 발생되는문제 때문에 재접속이 안되는 현상이 발생하고있었다.

 

재접속 문제는

https://pendine.tistory.com/23

 

[JAVA] Netty 클라이언트 재접속 연결 오류 (BlockingOperationException)

Exception log : io.netty.util.concurrent.BlockingOperationException: DefaultChannelPromise@45bfd093(incomplete) at io.netty.util.concurrent.DefaultPromise.checkDeadLock(DefaultPromise.java:395)..

pendine.tistory.com

이걸로 해결한줄 알았는데 예상외의 문제가 더있었다.

 

이벤트 루프를 이용해서 재접속 구현중 이벤트 루프가 등록이 안되는 경우가 있다는거다

왜 등록이 안되는지, 등록이 안된 원인을 확인할 수 있나, 어떻게하면 사전에 확인하고 예방할 수 있는지 

네티 API를 들어가서 확인을 해봐도, 한국 Netty Group을 들어가서 물어봐도 답이 안나온다.

 

현재 구현된 방법은

 

연결객체 Callable<Object>

연결객체 implements Callable<Object>
{

	생성자( String 아이피, int 포트번호 , 부트스트랩_팩토리 )
    {
    	부트스트랩_팩토리 로부터 부트스트랩을 생성;
    }
    
    Object call()
    {
    	InetSocketAddress addr = new InetSocketAddress( 아이피 , 포트번호 );
        채널퓨처 = 부트스트랩.connect(addr);
        
        채널 = 채널퓨처.channel();
        
        연결리스너  = new 연결리스너(this);
        연결종료리스너 = new 연결종료리스너(this);

        채널 = 채널퓨처.addListener( 연결리스너 ).sync().channel()
        			  .closeFuture().addListener( 연결종료리스너 ).sync().channel();
			
			
    }


}

연결리스너를 정리하다보면서 적다보니 뭔가 전제를 상세하게 나눠주고 시도해봐야 될것같다는 생각이 들었다.

일단 여기서 글 적는걸 중지한다.

 

 

 

그저 매번 등록된 클라이언트들의 채널상태를 확인하고

채널을  isActive메소드와 isRegistered 메소드를 이용해서 확인하고

둘다 반환값이 False 일 때 새로운 연결을 생성해주는것으로 변경을 했는데

해당 객체를 저장한 맵에서 다시 불러온뒤 call() 메소드를 불러주게끔 해줘야겠다.

 

1. ChannelFutureListenner Class 를 상속받아 만든 연결, 연결종료 리스너를 생성하는데

연결 리스너에서 연결시 재접속 조건을 추가할 것이다.

  Channel.isActive() && Channel.isRegistered() 정상적임.

  Channel.isActive() && !Channel.isRegistered() 등록안됨

  !Channel.isActive() && Channel.isRegistered() 등록은 됐으나 연결안됨

  !Channel.isActive() && !Channel.isRegistered() 망함. 연결 객체를 맵에서 불러와 새로운 객체에 할당, 

                                                        ExecutorService 리스트에서 제외시킨뒤 다시 추가하여 run 시킬것.

 

ChannelFuture에서도 isDone, isSuccess, isCancellable, isCancelled, isCause등을 이용해서 알수 있긴한데

 

계속 파고들면서 내가 API설명문구를 통해서 확인하여 알고있는 개념이 맞나? 의심스러움

왜 똑같은 현상이 나오는거지?  똑같은 오류가 맞나?

원인이 다 다른가?

게슈탈트 붕괴

 

 

 

테스트 환경에서 똑같은 현상을 유발시키는 방법도 모르겠고

모르니까 한번 코드 바꾸면 한참을 기다려야하고 진짜 잘모르겠다.

 

연결 리스너의 isActive() 의 반환값이 false일때 재접속 시도하도록, 분명 조건을 걸어놨는데

로그 확인해보니 

isRegistered의 반환값이 false 일때 재접속이 안되는 현상을 발견해서

연결된 서버의 채널 속성중 isRegistered 의 반환값이 false 일때 새로운 연결을 시도하도록 했는데 제대로 안된게

무슨이유일까.

다시 차근차근 봐야겠다.

 

----------------------------------------------------------------------------------

20211027 확인

iswriteable 이 동작하지 않는 경우로 인해

데이터 송신이 안되는 경우가 있다.

이번 확인 사항과 이전 확인한 결과를 통해

우선순위를 다시 파악하여 접속시 사용하는 리스너클래스의 재접속 조건을 바꾸었다.

1. 등록됬는지 isRegistered

2. 전송 가능한지 isWriteable

3. 열렸는지 isOpen

4. 동작중인지 isActive 

을 작성한순서대로 확인하고 ( if, else if )

하나라도 반환값이 false 라면 재접속 하도록 변경하였다.

 

그래도 접속이 되지 않는 경우를 확인 하기위해서

주기적으로 스케줄러를 통해 채널 객체가 null인것과

null이 아닌것중 마지막으로 수신데이터의 시간과 현재 시간을 비교하여

설정된 응답 대기시간을 초과한 경우 재접속 하도록 로직을 추가하였다.

 

 

 

--- 해결

이때 이미 해결 할 수 있었는데..

이벤트 루프가 등록될때까지 단순하게 반복시키면 됐었던것을...  

https://pendine.tistory.com/71

 

[JAVA / Netty] 클라이언트 재접속 오류 해결

https://pendine.tistory.com/42 [JAVA / Netty] 클라이언트 오류 해결 뭔가 찜찜하긴한데 해결된것같음 기존 소스코드에서 바꾼건 하나도 없음 일주일 이상을 테스트했고 어떤 상황에서도 문제없이 돌아갔

pendine.tistory.com

 

728x90

댓글