2017-09-26 5 views
0

들어오는 요청 속도가 임계 값을 초과 할 때 CPU 사용을 줄이기 위해 SSL 핸드 셰이크 전에 채널을 닫아야하는 응용 프로그램에 스로틀 기능을 추가하고 있습니다. 이제 Netty SslHandler을 서버 모드와 함께 사용하여 핸드 셰이크를 수행합니다. 나의 현재 구현 SslHandler 전에 ChannelInboundHandlerAdapter 첨가하고 channelActive 방법 재기록된다Netty에서 ssl 핸드 셰이크 전에 채널을 정상적으로 종료하는 방법은 무엇입니까?

@Override 
public void channelActive(ChannelHandlerContext ctx) throws Exception { 
    if (!limiter.tryAcquire()) { 
     ctx.close(); 
     return; 
    } 

    ctx.pipeline().remove(this); 
    ctx.fireChannelActive(); 
} 

을가 활성화 될 때, 채널이 폐쇄 될 수있는 방법이있다. 그러나 핸드 셰이크가 실패한 SslHandshakeCompletionEvent을 받게됩니다. Netty SslHandler의 소스 코드를 읽었습니다. channelInactive 이벤트가 발생하면 channelInactive 메서드에서 핸드 셰이크 실패를 설정합니다. 따라서 핸드 쉐이크 실패 이벤트를 발생시키지 않고 채널을 종료하는 더 좋은 방법이 있는지 궁금합니다. 스로틀 링이 채널을 닫을 때 핸드 쉐이크 프로세스가 시작되지 않았기 때문입니다.

답변

0

잘못된 끝에서 문제를 공격하고 있습니다. 이 아이디어는 너무 빨리 받아 들여지는 채널을 닫지 않고 채널 처리기가 아닌 승인 처리기에서 너무 빠르게 받아들이지 않도록하는 것입니다.

+0

'ServerSocketChannel'을 수정 하시겠습니까? 나는 InboundHandler를'NioServerSocketChannel'에 추가하는 솔루션을 가지고있어서, 등록되고 활성화되기 전에 들어오는 채널을 닫을 수 있습니다. 그러나, 그것은'channel.unsafe(). closeForcibly()'를 사용해야한다는 것을 의미합니다. 일반적인'channel.close()'메서드를 사용하면, Netty는 등록되지 않은 채널 예외를 던집니다. 하지만 Netty 문서 [Unsafe] (https://netty.io/4.0/api/io/netty/channel/Channel.Unsafe.html)에 따르면 이는 내부 API로 보이며 사용해서는 안됩니다. –

+0

최대 연결 수를 유지하는 동안 연결 수락을 중단하거나 OP_ACCEPT에 대한 등록을 취소하는 것을 의미합니다. 그러나 Netty는이를 수행합니다. 연결을 닫고 싶지 않습니다. 이미 너무 늦었습니다. 'ServerSocketChannel'을 닫을 필요도 없습니다. 본질적으로'accept()'를 호출하지 마십시오. – EJP

+0

처음에는이 솔루션을 고려했습니다. 그러나 속도 제한 기능을 추가합니다. 즉, 초당 몇 가지 연결 요청을 받아 들여 나머지 요청을 거부해야한다는 의미입니다. 단순히'Netty'가 새로운 연결을 수락하지 않는다면 그것은 속도 제한의 목표가 아닙니다. 물론, 매초'OP_ACCEPT'를 수정하여'Netty'가 초당 받아들이는 연결 수를 제어 할 수는 있지만 좋은 해결책입니까? –

0

귀하의 접근 방식은 거의 맞지만 channelActive 대신 channelRegistered 메서드를 재정의하는 것이 맞습니다.

@Override 
public void channelRegistered(ChannelHandlerContext ctx) throws Exception { 
    if (isGlobalLimitReached()) { 
     ctx.close(); 
    } else { 
     ctx.pipeline().remove(this); 
     ctx.pipeline().addFirst(sslCtx.newHandler(ctx.alloc())); 
     ctx.fireChannelRegistered(); 
    } 
} 

또한, 당신은 비행과 조건이 충족되는 경우에만 (제한에 도달하지 않음)에 파이프 라인의 시작 부분에 SslHandler를 추가해야합니다.

그런 경우 SslHandshakeCompletionEvent이 표시되지 않습니다. 핸드 셰이크는 SslHandler이 파이프 라인에 추가되고 channel.isActive()이 true (위 코드의 경우)를 반환 할 때 시작됩니다.

channelRegistered은 연결을 거부하거나 닫을 수있는 가장 최근의 지점입니다.

+0

그것은 나를 혼란스럽게 만든다.나는 디버그 모드를 사용하여'SslHandler'가 핸드 쉐이크를 시작할시기를 알아 낸다. 클라이언트 모드의 핸들러는 채널이 활성화되어있을 때 핸드 셰이크를 시작하는 것 같습니다. 'SslHandler'가 서버 모드에 있으면 채널을 읽을 때 핸드 셰이 킹을 시작합니다 ('SslHandler' 소스 코드에서'readDuringHandshake' 플래그가 있습니다). 가장 혼란스러운 것은 채널이 활성화되어있을 때 핸드 쉐이킹을 시작한다고해도, 핸들러가'SslHandler' 전에 추가되고,'channelInactive' 메소드는 핸드 쉐이킹 전에 실행되어 채널을 닫아야한다는 것입니다. 왜 여전히 'SslHandshakeCompletionEvent'를 제공합니까? –

+0

또는 "SslHandler"가 파이프 라인에 추가되면 핸드 셰이크가 시작되지만 채널이 활성화되기 전에 즉시 시작됩니다. –

+0

업데이트 : 메소드를'channelRegistered'로 수정하고 테스트하십시오.'Netty'는 여전히'SslHandshakeCompletionEvent'를 제공합니다. –