Spring Gateway - `java.lang.Exception: ChannelOperation terminal stack` 트러블 슈팅

가오리·2024년 2월 9일
0

트러블 슈팅

목록 보기
15/16
post-thumbnail

원인

  1. spring gateway 에러 발생

    spring gateway 로 라우팅과 통신은 잘되는데 java.lang.Exception: ChannelOperation terminal stack 에러 로그가 계속 찍힘

    대략 reactor.netty 라면서 에러가 발생함.

java.lang.Exception: ChannelOperation terminal stack
	at reactor.netty.channel.ChannelOperations.terminate(ChannelOperations.java:470) ~[reactor-netty-core-1.0.27.jar!/:1.0.27]
	at reactor.netty.http.server.HttpServerOperations.cleanHandlerTerminate(HttpServerOperations.java:745) ~[reactor-netty-http-1.0.27.jar!/:1.0.27]
	at reactor.netty.http.server.HttpTrafficHandler.operationComplete(HttpTrafficHandler.java:434) ~[reactor-netty-http-1.0.27.jar!/:1.0.27]
	at reactor.netty.http.server.HttpTrafficHandler.operationComplete(HttpTrafficHandler.java:63) ~[reactor-netty-http-1.0.27.jar!/:1.0.27]
	at io.netty.util.concurrent.DefaultPromise.notifyListener0(DefaultPromise.java:590) ~[netty-common-4.1.87.Final.jar!/:4.1.87.Final]
	at io.netty.util.concurrent.DefaultPromise.notifyListenersNow(DefaultPromise.java:557) ~[netty-common-4.1.87.Final.jar!/:4.1.87.Final]
	at io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:492) ~[netty-common-4.1.87.Final.jar!/:4.1.87.Final]
	at io.netty.util.concurrent.DefaultPromise.setValue0(DefaultPromise.java:636) ~[netty-common-4.1.87.Final.jar!/:4.1.87.Final]
	at io.netty.util.concurrent.DefaultPromise.setSuccess0(DefaultPromise.java:625) ~[netty-common-4.1.87.Final.jar!/:4.1.87.Final]
	at io.netty.util.concurrent.DefaultPromise.trySuccess(DefaultPromise.java:105) ~[netty-common-4.1.87.Final.jar!/:4.1.87.Final]
	at io.netty.util.internal.PromiseNotificationUtil.trySuccess(PromiseNotificationUtil.java:48) ~[netty-common-4.1.87.Final.jar!/:4.1.87.Final]
	at io.netty.channel.ChannelOutboundBuffer.safeSuccess(ChannelOutboundBuffer.java:717) ~[netty-transport-4.1.87.Final.jar!/:4.1.87.Final]
	at io.netty.channel.ChannelOutboundBuffer.remove(ChannelOutboundBuffer.java:272) ~[netty-transport-4.1.87.Final.jar!/:4.1.87.Final]
	at io.netty.channel.ChannelOutboundBuffer.removeBytes(ChannelOutboundBuffer.java:352) ~[netty-transport-4.1.87.Final.jar!/:4.1.87.Final]
	at io.netty.channel.epoll.AbstractEpollChannel.doWriteBytes(AbstractEpollChannel.java:364) ~[netty-transport-classes-epoll-4.1.87.Final.jar!/:4.1.87.Final]
  1. 구글 검색 결과 spring-cloud-gateway 공식 깃허브에 있는 이슈 (경로) 발견

    이것은 TRACE 이며 에러가 아니라는 답변이 달리면서 코드를 보여줌

    /**
     * Final release/close (last packet)
     */
     protected final void terminate() {
     	if (rebind(connection)) {
      	if (log.isTraceEnabled()) {
          	log.trace(format(channel(), "Disposing ChannelOperation from a channel"),
              new Exception("ChannelOperation terminal stack"));
    		}
    
    		Operators.terminate(OUTBOUND_CLOSE, this);
      	// Do not call directly inbound.onInboundComplete()
      	// HttpClientOperations need to notify with error
      	// when there is no response state
      	onInboundComplete();
      	afterInboundComplete();
      	// EmitResult is ignored as it is guaranteed that this call happens in an event loop
      	// and it is guarded by rebind(connection), so tryEmitEmpty() should happen just once
        onTerminate.tryEmitEmpty();
        
        listener.onStateChange(this, ConnectionObserver.State.DISCONNECTING);
      }
    }

    코드를 살펴보니 log leveltrace 인 경우 출력하는 걸로 로직이 짜여있음. 즉, 위의 코드는 연결이 종료될 때 그 동안 발생했던 에러가 있으면 에러를 출력하는 로직이며 에러의 원인을 나타내지는 않고 에러의 스택 트레이스를 로그로 출력하도록 한 것일 뿐이다.

해결방법

spring gateway 서버 yml 파일 수정

reator.netty 의 로깅 레벨 INFO 변경

운영 환경에서 로깅 레벨을 trace 로 설정하는 것은 일반적으로 권장되지 않는다. trace 레벨은 로깅의 가장 높은 수준으로, 시스템의 모든 상세한 정보를 로그로 남긴다. 이는 디버깅이나 문제 해결에 매우 유용할 수 있지만, 로그의 양이 매우 많아져서 디스크 공간을 빠르게 소모하고 성능에 부담을 줄 수 있다.

운영 환경에서는 일반적으로 info 또는 error 와 같은 더 낮은 로깅 레벨을 사용한다. 이렇게 하면 중요한 정보나 에러만 로그로 남기므로, 디스크 공간을 절약하고 시스템의 성능을 유지하는 데 도움이 된다.

그러나 특정 문제를 해결하기 위해 잠시 trace 레벨로 설정할 필요가 있는 경우도 있다. 이 경우, 문제 해결 후에는 로깅 레벨을 다시 낮추는 것이 좋다.

또한, 로그를 효과적으로 관리하려면 로그 메시지를 정기적으로 회전하거나, 오래된 로그를 자동으로 삭제하는 등의 방법을 사용하는 것이 좋다. 이렇게 하면 로그의 양을 관리하고 디스크 공간을 효율적으로 사용할 수 있다.

    logging:
  		level:
    		org.springframework.cloud.gateway: INFO
    		reactor.netty: info
profile
가오리의 개발 이야기

0개의 댓글