본문으로 바로가기 본문 바로가기
WIKI 기술 지식 베이스

Netty 컴포넌트

원문 보기 위키 갱신

Netty 컴포넌트 (Netty)

Netty 컴포넌트는 TCP와 UDP 소켓 통신을 Camel 라우트에서 바로 다룰 수 있게 해 주는 컴포넌트예요. producer와 consumer를 모두 지원하고, 버퍼 크기나 keepAlive 같은 통신 파라미터를 세밀하게 조정할 수 있으며, 코덱·SSL·스레드 풀 설정도 폭넓게 제어할 수 있어요.

출처: 문서

본문

Camel 2.14부터 지원

producer와 consumer를 모두 지원해요

Camel의 Netty 컴포넌트는 Netty 프로젝트 버전 4 기반의 소켓 통신 컴포넌트예요. Netty는 프로토콜 서버와 클라이언트 같은 networkServerInitializerFactory 애플리케이션을 빠르고 쉽게 개발할 수 있게 해 주는 NIO 클라이언트 서버 프레임워크예요. Netty는 TCP, UDP 소켓 서버 같은 네트워크 프로그래밍을 크게 단순화하고 깔끔하게 다듬어 줘요.

이 Camel 컴포넌트는 producer와 consumer 엔드포인트를 모두 지원해요.

Netty 컴포넌트는 여러 옵션을 갖고 있어서 버퍼 크기, keepAlive, tcpNoDelay 같은 TCP/UDP 통신 파라미터를 세밀하게 제어할 수 있고, Camel 라우트에서 In-Only와 In-Out 통신을 모두 지원해요.

Maven 사용자라면 이 컴포넌트를 쓰려고 pom.xml에 다음 의존성을 추가해야 해요:

<dependency>
    <groupId>org.apache.camel</groupId>
    <artifactId>camel-netty</artifactId>
    <version>x.x.x</version>
    <!-- use the same version as your Camel core version -->
</dependency>

URI 형식 (URI format)

netty 컴포넌트의 URI 스킴은 다음과 같아요

TCP

netty:tcp://0.0.0.0:99999[?options]

UDP

netty:udp://remotehost:99999/[?options]

이 컴포넌트는 TCP와 UDP 양쪽에 대해 producer와 consumer 엔드포인트를 지원해요.

옵션 설정 방법 (Configuring Options)

Camel 컴포넌트는 두 단계로 나눠 설정합니다:

  • 컴포넌트(component) 레벨

  • 엔드포인트(endpoint) 레벨

컴포넌트 옵션 설정 (Configuring Component Options)

컴포넌트 레벨에서는 엔드포인트들이 이어서 물려받는 일반적이고 공유되는 설정을 해요. 가장 상위의 설정 레벨이죠.

예를 들어 컴포넌트에는 보안 설정, 인증용 자격 증명, 네트워크 연결 URL 같은 것들이 있을 수 있어요.

컴포넌트에 따라 옵션이 몇 개뿐인 것도 있고 아주 많은 것도 있어요. 컴포넌트는 보통 널리 쓰이는 기본값이 미리 설정되어 있어서, 몇 가지 옵션만 설정하거나 아예 하나도 건드리지 않아도 되는 경우가 많아요.

컴포넌트는 다음 방법으로 설정할 수 있어요:

  • the Component DSL.

  • 설정 파일(application.properties, *.yaml 파일 등).

  • Java 코드에서 직접.

엔드포인트 옵션 설정 (Configuring Endpoint Options)

엔드포인트는 옵션이 많아서 설정에 시간을 더 쓰게 될 거예요. 이 옵션들이 엔드포인트가 원하는 일을 하도록 커스터마이즈해 줘요. 옵션은 엔드포인트가 consumer(from)로 쓰이는지, producer(to)로 쓰이는지, 둘 다인지에 따라 분류되기도 해요.

엔드포인트 설정은 대부분 엔드포인트 URI에 _path_와 query 파라미터로 바로 하는 경우가 많아요. Java에서 엔드포인트와 데이터 포맷을 _타입 세이프_하게 설정하려면 Endpoint DSL과 DataFormat DSL을 쓸 수도 있어요.

옵션을 설정할 때 좋은 습관은 Property Placeholders를 사용하는 거예요.

프로퍼티 플레이스홀더는 이런 장점이 있어요:

  • URL, 포트 번호, 민감한 정보 같은 설정을 하드코딩하는 걸 막아 줘요.

  • 설정을 코드 밖으로 분리할 수 있어요.

  • 코드가 더 유연해지고 재사용하기 좋아져요.

다음 두 섹션에서 모든 옵션을 나열해요. 먼저 컴포넌트 옵션, 그다음 엔드포인트 옵션 순서예요.

컴포넌트 옵션 (Component Options)

Netty 컴포넌트가 지원하는 옵션은 아래와 같아요.

Name Description Default Type
configuration (common) 엔드포인트를 만들 때 설정으로 NettyConfiguration을 사용해요. NettyConfiguration
disconnect (common) 사용 직후 Netty 채널에서 연결을 끊을지(close) 여부예요. false boolean
keepAlive (common) 활동이 없어서 소켓이 닫히지 않도록 보장하는 설정이에요. true boolean
reuseAddress (common) 소켓 멀티플렉싱을 돕는 설정이에요. true boolean
reuseChannel (common) 이 옵션은 producer와 consumer(클라이언트 모드)가 Exchange를 처리하는 라이프사이클 동안 같은 Netty 채널을 재사용할 수 있게 해 줘요. Camel 라우트에서 같은 서버를 여러 번 호출하면서 같은 네트워크 연결을 쓰고 싶을 때 유용해요. 이 옵션을 쓰면 Exchange가 끝나기 전까지는 채널이 연결 풀로 반환되지 않고, disconnect 옵션이 true로 설정돼 있으면 연결이 끊겨요. 재사용되는 채널은 CamelNettyChannel 키를 가진 exchange 프로퍼티로 Exchange에 저장돼서, 라우팅 중에 채널을 꺼내 쓸 수도 있어요. false boolean
sync (common) 엔드포인트를 one-way(false)로 쓸지 request-response(true)로 쓸지 정하는 설정이에요. true boolean
tcpNoDelay (common) TCP 프로토콜 성능을 개선하기 위한 설정이에요. true boolean
networkInterface (common (advanced)) UDP를 쓸 때 이 옵션으로 멀티캐스트 그룹에 조인할 네트워크 인터페이스를 eth0 같은 이름으로 지정할 수 있어요. String
bridgeErrorHandler (consumer) 컨슈머를 Camel 라우팅 에러 핸들러(Error Handler)에 브리지할 수 있게 해 줘요. 즉, Camel 컨슈머가 들어오는 메시지를 집어 올리는 동안 등에서 예외가 발생하면(가능한 경우), 그 예외를 메시지로 처리해서 라우팅 에러 핸들러가 다루게 돼요. 중요: 이것은 서드파티 컴포넌트가 예외가 던져졌을 때 Camel에 알릴 수 있도록 허용하는 경우에만 가능해요. 일부 컴포넌트는 내부에서만 처리하기 때문에 bridgeErrorHandler를 쓸 수 없어요. 다른 상황에서는 Camel 컴포넌트를 개선해서 서드파티 컴포넌트에 연결(hook)해 이를 가능하게 만들 수도 있어요. 기본으로 컨슈머는 org.apache.camel.spi.ExceptionHandler로 예외를 처리하는데, WARN 또는 ERROR 레벨로 로그를 남기고 무시해요. false boolean
clientMode (consumer) clientMode가 true이면 netty consumer가 주소에 TCP 클라이언트로 접속해요. false boolean
reconnect (consumer) consumer의 clientMode에서만 쓰는 옵션이에요. 활성화하면 연결이 끊겼을 때 consumer가 재접속을 시도해요. true boolean
reconnectInterval (consumer) reconnect와 clientMode가 활성화됐을 때 쓰여요. 재접속을 시도하는 간격(밀리초)이에요. 10000 int
backlog (consumer (advanced)) netty consumer(서버)의 백로그(backlog)를 설정할 수 있게 해 줘요. 백로그는 OS에 따라 다른 최선 노력(best effort)에 불과하다는 점에 유의하세요. 200, 500, 1000 같은 값을 설정하면 TCP 스택에 accept 큐의 길이를 알려 줘요. 이 옵션을 설정하지 않으면 백로그는 OS 설정에 따라요. int
bossCount (consumer (advanced)) netty가 nio 모드로 동작할 때는 Netty의 기본 bossCount 파라미터(1)를 써요. 이 옵션으로 Netty의 기본 bossCount를 재정의할 수 있어요. 1 int
bossGroup (consumer (advanced)) NettyEndpoint 전반에서 서버 측 새 연결을 처리하는 데 쓸 BossGroup을 설정해요. EventLoopGroup
broadcast (consumer (advanced)) UDP로 멀티캐스트(Multicast)를 선택하는 설정이에요. false boolean
disconnectOnNoReply (consumer (advanced)) sync가 활성화돼 있으면, 돌려줄 응답(reply)이 없을 때 NettyConsumer가 연결을 끊을지 이 옵션이 결정해요. true boolean
executorService (consumer (advanced)) 지정한 커스텀 EventExecutorGroup을 사용해요. EventExecutorGroup
maximumPoolSize (consumer (advanced)) netty consumer의 순차(ordered) 스레드 풀 최대 크기를 설정해요. 기본 크기는 2 x cpu_core + 1이에요. 예컨대 이 값을 10으로 설정하면 2 x cpu_core + 1이 더 큰 값이 아닌 한 10개 스레드를 써요. 더 크면 그 값이 우선해서 쓰여요. 예를 들어 코어가 8개면 consumer 스레드 풀은 17이 돼요. 이 스레드 풀은 Netty에서 받은 메시지를 Camel이 라우팅할 때 쓰여요. 메시지 순서를 보장하고, 일부 메시지가 블록되더라도 netty의 워커 스레드(event loop)가 영향을 받지 않도록 별도의 스레드 풀을 써요. int
nettyServerBootstrapFactory (consumer (advanced)) 커스텀 NettyServerBootstrapFactory를 사용해요. NettyServerBootstrapFactory
noReplyLogLevel (consumer (advanced))
sync가 활성화돼 있으면, 돌려줄 응답이 없음을 로그로 남길 때 NettyConsumer가 쓸 로깅 레벨을 이 옵션이 결정해요.

Enum values:

  • TRACE

  • DEBUG

  • INFO

  • WARN

  • ERROR

  • OFF

| WARN | LoggingLevel | | serverClosedChannelExceptionCaughtLogLevel (consumer (advanced)) |

서버(NettyConsumer)가 java.nio.channels.ClosedChannelException을 잡으면 이 로깅 레벨로 로그를 남겨요. 클라이언트가 갑자기 연결을 끊어서 Netty 서버에 closed 예외가 쏟아지는 상황에서 그 예외 로그를 피하려고 쓰는 옵션이에요.

Enum values:

  • TRACE

  • DEBUG

  • INFO

  • WARN

  • ERROR

  • OFF

| DEBUG | LoggingLevel | | serverExceptionCaughtLogLevel (consumer (advanced)) |

서버(NettyConsumer)가 예외를 잡으면 이 로깅 레벨로 로그를 남겨요.

Enum values:

  • TRACE

  • DEBUG

  • INFO

  • WARN

  • ERROR

  • OFF

| WARN | LoggingLevel | | serverInitializerFactory (consumer (advanced)) | 커스텀 ServerInitializerFactory를 사용해요. | | ServerInitializerFactory | | usingExecutorService (consumer (advanced)) | 같은 채널에서 이벤트가 순서대로 처리되도록 순차(ordered) 스레드 풀을 쓸지 여부예요. | true | boolean | | connectTimeout (producer) | 소켓 연결을 사용할 수 있을 때까지 기다리는 시간이에요. 값은 밀리초 단위예요. | 10000 | int | | lazyStartProducer (producer) | producer를 lazy(첫 메시지 시점)로 시작할지 여부예요. lazy 시작을 쓰면 producer가 시작 중 실패해서 라우트 시작이 실패하는 상황에서도 CamelContext와 라우트를 시작할 수 있고, 시작 실패 처리를 Camel의 라우팅 에러 핸들러로 넘길 수 있어요. 다만 첫 메시지를 처리하는 시점에 producer를 만들고 시작하는 데 시간이 조금 걸려서 전체 처리 시간이 길어질 수 있다는 점은 유의하세요. | false | boolean | | requestTimeout (producer) | 원격 서버를 호출할 때 Netty producer에 타임아웃을 둘 수 있게 해 줘요. 기본으로는 타임아웃을 쓰지 않아요. 값은 밀리초 단위라서 예컨대 30000은 30초예요. requestTimeout은 Netty의 ReadTimeoutHandler를 써서 타임아웃을 트리거해요. | | long | | clientInitializerFactory (producer (advanced)) | 커스텀 ClientInitializerFactory를 사용해요. | | ClientInitializerFactory | | correlationManager (producer (advanced)) | netty producer로 request/reply를 쓸 때 요청과 응답 메시지가 어떻게 매핑되는지 관리하는 커스텀 correlation manager를 사용해요. 요청과 응답 메시지 양쪽에 correlation id가 있는 것처럼 요청과 응답을 짝지을 방법이 있을 때만 써야 해요. netty에서 같은 채널(연결)로 동시 메시지를 멀티플렉싱하고 싶을 때 쓸 수 있어요. 이럴 때는 요청과 응답 메시지를 연결 지을 방법이 있어야 라우팅이 계속되기 전에 inflight Camel Exchange에 올바른 응답을 저장할 수 있어요. 커스텀 correlation manager를 만들 때는 TimeoutCorrelationManagerSupport를 확장하는 걸 권장해요. 타임아웃 등 직접 구현해야 하는 복잡한 부분을 대신 지원해 주거든요. 자세한 내용은 producerPoolEnabled 옵션도 참고하세요. | | NettyCamelStateCorrelationManager | | lazyChannelCreation (producer (advanced)) | Camel producer가 시작될 때 원격 서버가 아직 떠 있지 않아도 예외를 피하도록 채널을 lazy하게 만들 수 있어요. | true | boolean | | producerPoolBlockWhenExhausted (producer (advanced)) | blockWhenExhausted 설정 속성값을 지정해요. 풀이 고갈돼서(활성 객체의 최대 수에 도달해서) borrowObject() 메서드가 호출됐을 때 블록할지 결정해요. | true | boolean | | producerPoolEnabled (producer (advanced)) | producer 풀을 사용할지 여부예요. 중요: 이걸 끄면 request/reply를 하고 있을 때도 producer가 하나의 공유 연결을 써요. 그러면 응답이 순서대로 돌아오지 않을 때 응답이 뒤섞이는 잠재적 문제가 생겨요. 그래서 요청과 응답 메시지 양쪽에 correlation id를 담아서, Camel에서 메시지를 계속 처리하는 콜백에 응답을 제대로 연결 지을 수 있어야 해요. 이러려면 correlation manager로 NettyCamelStateCorrelationManager를 구현하고 correlationManager 옵션으로 설정해야 해요. 자세한 내용은 correlationManager 옵션도 참고하세요. | true | boolean | | producerPoolMaxIdle (producer (advanced)) | 풀에 둘 수 있는 idle 인스턴스 수의 상한을 설정해요. | 100 | int | | producerPoolMaxTotal (producer (advanced)) | 주어진 시점에 풀이 할당할 수 있는 객체 수(클라이언트에 대여 중이거나 대여를 기다리며 idle인)의 상한을 설정해요. 제한 없음은 음수로 설정해요. 재시도를 수행할 때처럼 producer를 만들 공간이 풀에 필요하니 이 값을 너무 낮게(예: 1) 잡지 않도록 주의하세요. producerPoolBlockWhenExhausted 옵션은 기본값이 true라서 공간이 없으면 풀이 블록하고, 그러면 애플리케이션이 멈출(hang) 수 있다는 점도 유의하세요. | -1 | int | | producerPoolMaxWait (producer (advanced)) | 풀이 고갈됐고 producerPoolBlockWhenExhausted가 true일 때 borrowObject() 메서드가 예외를 던지기 전까지 블록하는 최대 시간(밀리초)을 설정해요. 0보다 작으면 borrowObject() 메서드가 무기한 블록할 수 있어요. | -1 | long | | producerPoolMinEvictableIdle (producer (advanced)) | idle 객체 이벤터(evictor)의 제거 대상이 되기 전까지 객체가 풀에서 idle로 있어도 되는 최소 시간(밀리초)을 설정해요. | 300000 | long | | producerPoolMinIdle (producer (advanced)) | 이벤터 스레드(동작 중이라면)가 새 객체를 만들기 전에 producer 풀에 있어도 되는 최소 인스턴스 수를 설정해요. | | int | | udpConnectionlessSending (producer (advanced)) | 이 옵션은 진짜 fire-and-forget인 connectionless UDP 전송을 지원해요. 연결된(connected) UDP 전송은 수신 포트에서 아무도 listen하지 않으면 PortUnreachableException을 받아요. | false | boolean | | useByteBuf (producer (advanced)) | useByteBuf가 true이면 netty producer가 보내기 전에 메시지 본문을 ByteBuf로 바꿔요. | false | boolean | | allowSerializedHeaders (advanced) | transferExchange가 true일 때 TCP에서만 쓰여요. true로 설정하면 헤더와 프로퍼티의 직렬화 가능 객체가 exchange에 추가돼요. 그렇지 않으면 Camel이 직렬화 불가능 객체를 제외하고 WARN 레벨로 로그를 남겨요. | false | boolean | | autowiredEnabled (advanced) | autowiring을 사용할지 여부예요. 레지스트리에서 일치하는 타입의 인스턴스가 하나뿐인지 찾아 보고, 있으면 컴포넌트에 설정하는 자동 autowiring 옵션(옵션이 autowired로 표시돼 있어야 함)에 쓰여요. JDBC 데이터 소스, JMS 커넥션 팩토리, AWS 클라이언트 등의 자동 설정에 활용할 수 있어요. | true | boolean | | channelGroup (advanced) | 명시적인 ChannelGroup을 사용해요. | | ChannelGroup | | nativeTransport (advanced) | NIO 대신 네이티브 트랜스포트를 쓸지 여부예요. 네이티브 트랜스포트는 호스트 운영체제를 활용하고 일부 플랫폼에서만 지원돼요. 사용 중인 호스트 운영체제용 netty JAR을 추가해야 해요. 자세한 내용은 http://netty.io/wiki/native-transports.html를 참고하세요. | false | boolean | | options (advanced) | option. 접두어로 추가 netty 옵션을 설정할 수 있게 해 줘요. 예를 들면 option.child.keepAlive=false죠. 쓸 수 있는 옵션은 Netty 문서를 참고하세요. option. 접두어를 쓰는 멀티 밸류 옵션이에요. | | Map | | receiveBufferSize (advanced) | 인바운드 통신에 쓸 TCP/UDP 버퍼 크기예요. 단위는 바이트예요. | 65536 | int | | receiveBufferSizePredictor (advanced) | 버퍼 크기 예측기(predictor)를 설정해요. 자세한 내용은 Jetty 문서와 이 메일 스레드를 참고하세요. | | int | | sendBufferSize (advanced) | 아웃바운드 통신에 쓸 TCP/UDP 버퍼 크기예요. 단위는 바이트예요. | 65536 | int | | shutdownTimeout (advanced) | 종료 대기(shutdown await) 타임아웃(밀리초)이에요. | 100 | int | | transferExchange (advanced) | TCP에서만 쓰여요. 본문만이 아니라 exchange 전체를 와이어로 전송할 수 있어요. 전송되는 필드는 In body, Out body, fault body, In headers, Out headers, fault headers, exchange 프로퍼티, exchange 예외예요. 객체가 직렬화 가능해야 해요. Camel은 직렬화 불가능 객체를 제외하고 WARN 레벨로 로그를 남겨요. | false | boolean | | udpByteArrayCodec (advanced) | UDP 전용이에요. 활성화하면 Java 직렬화 프로토콜 대신 바이트 배열 코덱을 써요. | false | boolean | | unixDomainSocketPath (advanced) | inet 소켓 대신 쓸 유닉스 도메인 소켓 경로예요. host와 port 파라미터는 쓰이지 않지만 필수예요. 더미 값으로 채워도 괜찮아요. 반드시 nativeTransport=true, clientMode=false와 함께 써야 해요. | | String | | workerCount (advanced) | netty가 nio 모드로 동작할 때는 Netty의 기본 workerCount 파라미터(cpu_core_threads x 2)를 써요. 이 옵션으로 Netty의 기본 workerCount를 재정의할 수 있어요. | | int | | workerGroup (advanced) | boss 스레드 풀로 명시적인 EventLoopGroup을 사용해요. 예컨대 여러 consumer나 producer가 스레드 풀을 공유하게 할 때죠. 기본적으로 각 consumer와 producer는 2 x CPU 코어 수만큼의 스레드를 가진 자기만의 워커 풀을 가져요. | | EventLoopGroup | | allowDefaultCodec (codec) | encoder/decoder가 둘 다 null이고 textline이 false이면 netty 컴포넌트가 기본 코덱을 설치해요. allowDefaultCodec를 false로 설정하면 netty 컴포넌트가 필터 체인의 첫 요소로 기본 코덱을 설치하지 않아요. | true | boolean | | autoAppendDelimiter (codec) | textline 코덱으로 보낼 때 빠진 종료 구분자(end delimiter)를 자동으로 붙일지 여부예요. | true | boolean | | decoderMaxLineLength (codec) | textline 코덱에 쓸 최대 라인 길이예요. | 1024 | int | | decoders (codec) | 사용할 디코더 목록이에요. 콤마로 구분한 값을 가진 String을 쓸 수 있고, 그 값들은 레지스트리에서 찾아 보게 돼요. Camel이 찾아 보도록 하려면 값을 # 접두어로 시작해야 한다는 점만 기억하세요. | | String | | delimiter (codec) |

textline 코덱에 쓸 구분자(delimiter)예요. 가능한 값은 LINE과 NULL이에요.

Enum values:

  • LINE

  • NULL

| LINE | TextLineDelimiter | | encoders (codec) | 사용할 인코더 목록이에요. 콤마로 구분한 값을 가진 String을 쓸 수 있고, 그 값들은 레지스트리에서 찾아 보게 돼요. Camel이 찾아 보도록 하려면 값을 # 접두어로 시작해야 한다는 점만 기억하세요. | | String | | encoding (codec) | textline 코덱에 쓸 인코딩(문자셋 이름)이에요. 지정하지 않으면 Camel이 JVM 기본 Charset을 써요. | | String | | textline (codec) | TCP에서만 쓰여요. 코덱을 지정하지 않았다면 이 플래그로 텍스트 라인 기반 코덱을 쓴다고 표시할 수 있어요. 지정하지 않았거나 값이 false이면 TCP 위에서 객체 직렬화(Object Serialization)를 가정해요. 다만 기본적으로 String만 직렬화할 수 있어요. | false | boolean | | enabledProtocols (security) | SSL을 사용할 때 활성화할 프로토콜이에요. | TLSv1.2,TLSv1.3 | String | | hostnameVerification (security) | SSLEngine에서 호스트명 검증(hostname verification)을 켜거나 끕니다. | false | boolean | | keyStoreFormat (security) | 페이로드 암호화에 쓸 키스토어 포맷이에요. 설정하지 않으면 JKS가 기본값이에요. | | String | | keyStoreResource (security) | 암호화에 쓸 클라이언트 측 인증서 키스토어예요. 기본으로 classpath에서 불러오지만, classpath:, file:, http: 접두어를 붙여서 다른 시스템에서 리소스를 불러올 수 있어요. | | String | | needClientAuth (security) | SSL을 사용할 때 서버가 클라이언트 인증을 요구할지 설정해요. | false | boolean | | passphrase (security) | keyStore와 trustStore에 쓸 비밀번호예요. 두 리소스에 같은 비밀번호를 설정해야 해요. | | String | | securityProvider (security) | 페이로드 암호화에 쓸 보안 프로바이더예요. 설정하지 않으면 SunX509가 기본값이에요. | | String | | ssl (security) | 이 엔드포인트에 SSL 암호화를 적용할지 정하는 설정이에요. | false | boolean | | sslClientCertHeaders (security) | 활성화하고 SSL 모드일 때 Netty consumer가 subject 이름, issuer 이름, 일련번호, 유효 기간 같은 클라이언트 인증서 정보를 담은 헤더로 Camel 메시지를 풍부하게(enrich) 만들어요. | false | boolean | | sslContextParameters (security) | SSLContextParameters로 보안을 설정해요. | | SSLContextParameters | | sslHandler (security) | SSL 핸들러를 돌려주는 데 쓸 수 있는 클래스에 대한 참조예요. | | SslHandler | | trustStoreResource (security) | 암호화에 쓸 서버 측 인증서 키스토어예요. 기본으로 classpath에서 불러오지만, classpath:, file:, http: 접두어를 붙여서 다른 시스템에서 리소스를 불러올 수 있어요. | | String | | useGlobalSslContextParameters (security) | 전역 SSL 컨텍스트 파라미터 사용을 활성화해요. | false | boolean |

엔드포인트 옵션 (Endpoint Options)

Netty 엔드포인트는 다음 URI 문법으로 설정해요:

netty:protocol://host:port

다음 _path_와 query 파라미터를 씁니다:

경로 파라미터 (Path Parameters)

Name Description Default Type
protocol (common)
필수 사용할 프로토콜이에요. tcp 또는 udp예요.

Enum values:

  • tcp

  • udp

| | String | | host (common) | 필수 호스트명이에요. consumer의 호스트명은 localhost 또는 0.0.0.0이고, producer의 호스트명은 접속할 원격 호스트예요. | | String | | port (common) | 필수 호스트 포트 번호예요. | | int |

쿼리 파라미터 (Query Parameters)

Name Description Default Type
disconnect (common) 사용 직후 Netty 채널에서 연결을 끊을지(close) 여부예요. false boolean
keepAlive (common) 활동이 없어서 소켓이 닫히지 않도록 보장하는 설정이에요. true boolean
reuseAddress (common) 소켓 멀티플렉싱을 돕는 설정이에요. true boolean
reuseChannel (common) 이 옵션은 producer와 consumer(클라이언트 모드)가 Exchange를 처리하는 라이프사이클 동안 같은 Netty 채널을 재사용할 수 있게 해 줘요. Camel 라우트에서 같은 서버를 여러 번 호출하면서 같은 네트워크 연결을 쓰고 싶을 때 유용해요. 이 옵션을 쓰면 Exchange가 끝나기 전까지는 채널이 연결 풀로 반환되지 않고, disconnect 옵션이 true로 설정돼 있으면 연결이 끊겨요. 재사용되는 채널은 CamelNettyChannel 키를 가진 exchange 프로퍼티로 Exchange에 저장돼서, 라우팅 중에 채널을 꺼내 쓸 수도 있어요. false boolean
sync (common) 엔드포인트를 one-way(false)로 쓸지 request-response(true)로 쓸지 정하는 설정이에요. true boolean
tcpNoDelay (common) TCP 프로토콜 성능을 개선하기 위한 설정이에요. true boolean
networkInterface (common (advanced)) UDP를 쓸 때 이 옵션으로 멀티캐스트 그룹에 조인할 네트워크 인터페이스를 eth0 같은 이름으로 지정할 수 있어요. String
clientMode (consumer) clientMode가 true이면 netty consumer가 주소에 TCP 클라이언트로 접속해요. false boolean
reconnect (consumer) consumer의 clientMode에서만 쓰는 옵션이에요. 활성화하면 연결이 끊겼을 때 consumer가 재접속을 시도해요. true boolean
reconnectInterval (consumer) reconnect와 clientMode가 활성화됐을 때 쓰여요. 재접속을 시도하는 간격(밀리초)이에요. 10000 int
backlog (consumer (advanced)) netty consumer(서버)의 백로그(backlog)를 설정할 수 있게 해 줘요. 백로그는 OS에 따라 다른 최선 노력(best effort)에 불과하다는 점에 유의하세요. 200, 500, 1000 같은 값을 설정하면 TCP 스택에 accept 큐의 길이를 알려 줘요. 이 옵션을 설정하지 않으면 백로그는 OS 설정에 따라요. int
bootstrapConfiguration (consumer (advanced)) 이 엔드포인트를 설정하려고 커스텀으로 구성된 NettyServerBootstrapConfiguration을 사용해요. URI로 설정하면(예: \{code bootstrapConfiguration=#myBean}) 그 프로퍼티들이 NettyComponent.createEndpoint()에 의해 엔드포인트 설정으로 병합돼요. 참고: 이 파라미터는 컴포넌트가 URI로 해석하고, 이 세터로 프로그래밍 방식으로 설정하면 적용되지 않아요. NettyServerBootstrapConfiguration
bossCount (consumer (advanced)) netty가 nio 모드로 동작할 때는 Netty의 기본 bossCount 파라미터(1)를 써요. 이 옵션으로 Netty의 기본 bossCount를 재정의할 수 있어요. 1 int
bossGroup (consumer (advanced)) NettyEndpoint 전반에서 서버 측 새 연결을 처리하는 데 쓸 BossGroup을 설정해요. EventLoopGroup
bridgeErrorHandler (consumer (advanced)) 컨슈머를 Camel 라우팅 에러 핸들러(Error Handler)에 브리지할 수 있게 해 줘요. 즉, Camel 컨슈머가 들어오는 메시지를 집어 올리는 동안 등에서 예외가 발생하면(가능한 경우), 그 예외를 메시지로 처리해서 라우팅 에러 핸들러가 다루게 돼요. 중요: 이것은 서드파티 컴포넌트가 예외가 던져졌을 때 Camel에 알릴 수 있도록 허용하는 경우에만 가능해요. 일부 컴포넌트는 내부에서만 처리하기 때문에 bridgeErrorHandler를 쓸 수 없어요. 다른 상황에서는 Camel 컴포넌트를 개선해서 서드파티 컴포넌트에 연결(hook)해 이를 가능하게 만들 수도 있어요. 기본으로 컨슈머는 org.apache.camel.spi.ExceptionHandler로 예외를 처리하는데, WARN 또는 ERROR 레벨로 로그를 남기고 무시해요. false boolean
broadcast (consumer (advanced)) UDP로 멀티캐스트(Multicast)를 선택하는 설정이에요. false boolean
disconnectOnNoReply (consumer (advanced)) sync가 활성화돼 있으면, 돌려줄 응답(reply)이 없을 때 NettyConsumer가 연결을 끊을지 이 옵션이 결정해요. true boolean
exceptionHandler (consumer (advanced)) 컨슈머가 커스텀 ExceptionHandler를 쓰게 할 수 있어요. bridgeErrorHandler 옵션이 활성화되어 있으면 이 옵션은 사용되지 않는다는 점에 주의하세요. 기본으로 컨슈머는 예외를 처리하는데, WARN 또는 ERROR 레벨로 로그를 남기고 무시해요. ExceptionHandler
exchangePattern (consumer (advanced))
컨슈머가 교환(exchange)을 만들 때 교환 패턴을 설정해요.

Enum values:

  • InOnly

  • InOut

| | ExchangePattern | | nettyServerBootstrapFactory (consumer (advanced)) | 커스텀 NettyServerBootstrapFactory를 사용해요. | | NettyServerBootstrapFactory | | noReplyLogLevel (consumer (advanced)) |

sync가 활성화돼 있으면, 돌려줄 응답이 없음을 로그로 남길 때 NettyConsumer가 쓸 로깅 레벨을 이 옵션이 결정해요.

Enum values:

  • TRACE

  • DEBUG

  • INFO

  • WARN

  • ERROR

  • OFF

| WARN | LoggingLevel | | serverClosedChannelExceptionCaughtLogLevel (consumer (advanced)) |

서버(NettyConsumer)가 java.nio.channels.ClosedChannelException을 잡으면 이 로깅 레벨로 로그를 남겨요. 클라이언트가 갑자기 연결을 끊어서 Netty 서버에 closed 예외가 쏟아지는 상황에서 그 예외 로그를 피하려고 쓰는 옵션이에요.

Enum values:

  • TRACE

  • DEBUG

  • INFO

  • WARN

  • ERROR

  • OFF

| DEBUG | LoggingLevel | | serverExceptionCaughtLogLevel (consumer (advanced)) |

서버(NettyConsumer)가 예외를 잡으면 이 로깅 레벨로 로그를 남겨요.

Enum values:

  • TRACE

  • DEBUG

  • INFO

  • WARN

  • ERROR

  • OFF

| WARN | LoggingLevel | | serverInitializerFactory (consumer (advanced)) | 커스텀 ServerInitializerFactory를 사용해요. | | ServerInitializerFactory | | usingExecutorService (consumer (advanced)) | 같은 채널에서 이벤트가 순서대로 처리되도록 순차(ordered) 스레드 풀을 쓸지 여부예요. | true | boolean | | connectTimeout (producer) | 소켓 연결을 사용할 수 있을 때까지 기다리는 시간이에요. 값은 밀리초 단위예요. | 10000 | int | | requestTimeout (producer) | 원격 서버를 호출할 때 Netty producer에 타임아웃을 둘 수 있게 해 줘요. 기본으로는 타임아웃을 쓰지 않아요. 값은 밀리초 단위라서 예컨대 30000은 30초예요. requestTimeout은 Netty의 ReadTimeoutHandler를 써서 타임아웃을 트리거해요. | | long | | clientInitializerFactory (producer (advanced)) | 커스텀 ClientInitializerFactory를 사용해요. | | ClientInitializerFactory | | correlationManager (producer (advanced)) | netty producer로 request/reply를 쓸 때 요청과 응답 메시지가 어떻게 매핑되는지 관리하는 커스텀 correlation manager를 사용해요. 요청과 응답 메시지 양쪽에 correlation id가 있는 것처럼 요청과 응답을 짝지을 방법이 있을 때만 써야 해요. netty에서 같은 채널(연결)로 동시 메시지를 멀티플렉싱하고 싶을 때 쓸 수 있어요. 이럴 때는 요청과 응답 메시지를 연결 지을 방법이 있어야 라우팅이 계속되기 전에 inflight Camel Exchange에 올바른 응답을 저장할 수 있어요. 커스텀 correlation manager를 만들 때는 TimeoutCorrelationManagerSupport를 확장하는 걸 권장해요. 타임아웃 등 직접 구현해야 하는 복잡한 부분을 대신 지원해 주거든요. 자세한 내용은 producerPoolEnabled 옵션도 참고하세요. | | NettyCamelStateCorrelationManager | | lazyChannelCreation (producer (advanced)) | Camel producer가 시작될 때 원격 서버가 아직 떠 있지 않아도 예외를 피하도록 채널을 lazy하게 만들 수 있어요. | true | boolean | | lazyStartProducer (producer (advanced)) | producer를 lazy(첫 메시지 시점)로 시작할지 여부예요. lazy 시작을 쓰면 producer가 시작 중 실패해서 라우트 시작이 실패하는 상황에서도 CamelContext와 라우트를 시작할 수 있고, 시작 실패 처리를 Camel의 라우팅 에러 핸들러로 넘길 수 있어요. 다만 첫 메시지를 처리하는 시점에 producer를 만들고 시작하는 데 시간이 조금 걸려서 전체 처리 시간이 길어질 수 있다는 점은 유의하세요. | false | boolean | | producerPoolBlockWhenExhausted (producer (advanced)) | blockWhenExhausted 설정 속성값을 지정해요. 풀이 고갈돼서(활성 객체의 최대 수에 도달해서) borrowObject() 메서드가 호출됐을 때 블록할지 결정해요. | true | boolean | | producerPoolEnabled (producer (advanced)) | producer 풀을 사용할지 여부예요. 중요: 이걸 끄면 request/reply를 하고 있을 때도 producer가 하나의 공유 연결을 써요. 그러면 응답이 순서대로 돌아오지 않을 때 응답이 뒤섞이는 잠재적 문제가 생겨요. 그래서 요청과 응답 메시지 양쪽에 correlation id를 담아서, Camel에서 메시지를 계속 처리하는 콜백에 응답을 제대로 연결 지을 수 있어야 해요. 이러려면 correlation manager로 NettyCamelStateCorrelationManager를 구현하고 correlationManager 옵션으로 설정해야 해요. 자세한 내용은 correlationManager 옵션도 참고하세요. | true | boolean | | producerPoolMaxIdle (producer (advanced)) | 풀에 둘 수 있는 idle 인스턴스 수의 상한을 설정해요. | 100 | int | | producerPoolMaxTotal (producer (advanced)) | 주어진 시점에 풀이 할당할 수 있는 객체 수(클라이언트에 대여 중이거나 대여를 기다리며 idle인)의 상한을 설정해요. 제한 없음은 음수로 설정해요. 재시도를 수행할 때처럼 producer를 만들 공간이 풀에 필요하니 이 값을 너무 낮게(예: 1) 잡지 않도록 주의하세요. producerPoolBlockWhenExhausted 옵션은 기본값이 true라서 공간이 없으면 풀이 블록하고, 그러면 애플리케이션이 멈출(hang) 수 있다는 점도 유의하세요. | -1 | int | | producerPoolMaxWait (producer (advanced)) | 풀이 고갈됐고 producerPoolBlockWhenExhausted가 true일 때 borrowObject() 메서드가 예외를 던지기 전까지 블록하는 최대 시간(밀리초)을 설정해요. 0보다 작으면 borrowObject() 메서드가 무기한 블록할 수 있어요. | -1 | long | | producerPoolMinEvictableIdle (producer (advanced)) | idle 객체 이벤터(evictor)의 제거 대상이 되기 전까지 객체가 풀에서 idle로 있어도 되는 최소 시간(밀리초)을 설정해요. | 300000 | long | | producerPoolMinIdle (producer (advanced)) | 이벤터 스레드(동작 중이라면)가 새 객체를 만들기 전에 producer 풀에 있어도 되는 최소 인스턴스 수를 설정해요. | | int | | udpConnectionlessSending (producer (advanced)) | 이 옵션은 진짜 fire-and-forget인 connectionless UDP 전송을 지원해요. 연결된(connected) UDP 전송은 수신 포트에서 아무도 listen하지 않으면 PortUnreachableException을 받아요. | false | boolean | | useByteBuf (producer (advanced)) | useByteBuf가 true이면 netty producer가 보내기 전에 메시지 본문을 ByteBuf로 바꿔요. | false | boolean | | allowSerializedHeaders (advanced) | transferExchange가 true일 때 TCP에서만 쓰여요. true로 설정하면 헤더와 프로퍼티의 직렬화 가능 객체가 exchange에 추가돼요. 그렇지 않으면 Camel이 직렬화 불가능 객체를 제외하고 WARN 레벨로 로그를 남겨요. | false | boolean | | channelGroup (advanced) | 명시적인 ChannelGroup을 사용해요. | | ChannelGroup | | nativeTransport (advanced) | NIO 대신 네이티브 트랜스포트를 쓸지 여부예요. 네이티브 트랜스포트는 호스트 운영체제를 활용하고 일부 플랫폼에서만 지원돼요. 사용 중인 호스트 운영체제용 netty JAR을 추가해야 해요. 자세한 내용은 http://netty.io/wiki/native-transports.html를 참고하세요. | false | boolean | | options (advanced) | option. 접두어로 추가 netty 옵션을 설정할 수 있게 해 줘요. 예를 들면 option.child.keepAlive=false죠. 쓸 수 있는 옵션은 Netty 문서를 참고하세요. option. 접두어를 쓰는 멀티 밸류 옵션이에요. | | Map | | receiveBufferSize (advanced) | 인바운드 통신에 쓸 TCP/UDP 버퍼 크기예요. 단위는 바이트예요. | 65536 | int | | receiveBufferSizePredictor (advanced) | 버퍼 크기 예측기(predictor)를 설정해요. 자세한 내용은 Jetty 문서와 이 메일 스레드를 참고하세요. | | int | | sendBufferSize (advanced) | 아웃바운드 통신에 쓸 TCP/UDP 버퍼 크기예요. 단위는 바이트예요. | 65536 | int | | shutdownTimeout (advanced) | 종료 대기(shutdown await) 타임아웃(밀리초)이에요. | 100 | int | | synchronous (advanced) | 동기(synchronous) 처리를 엄격하게 쓸지 설정해요. | false | boolean | | transferExchange (advanced) | TCP에서만 쓰여요. 본문만이 아니라 exchange 전체를 와이어로 전송할 수 있어요. 전송되는 필드는 In body, Out body, fault body, In headers, Out headers, fault headers, exchange 프로퍼티, exchange 예외예요. 객체가 직렬화 가능해야 해요. Camel은 직렬화 불가능 객체를 제외하고 WARN 레벨로 로그를 남겨요. | false | boolean | | udpByteArrayCodec (advanced) | UDP 전용이에요. 활성화하면 Java 직렬화 프로토콜 대신 바이트 배열 코덱을 써요. | false | boolean | | unixDomainSocketPath (advanced) | inet 소켓 대신 쓸 유닉스 도메인 소켓 경로예요. host와 port 파라미터는 쓰이지 않지만 필수예요. 더미 값으로 채워도 괜찮아요. 반드시 nativeTransport=true, clientMode=false와 함께 써야 해요. | | String | | workerCount (advanced) | netty가 nio 모드로 동작할 때는 Netty의 기본 workerCount 파라미터(cpu_core_threads x 2)를 써요. 이 옵션으로 Netty의 기본 workerCount를 재정의할 수 있어요. | | int | | workerGroup (advanced) | boss 스레드 풀로 명시적인 EventLoopGroup을 사용해요. 예컨대 여러 consumer나 producer가 스레드 풀을 공유하게 할 때죠. 기본적으로 각 consumer와 producer는 2 x CPU 코어 수만큼의 스레드를 가진 자기만의 워커 풀을 가져요. | | EventLoopGroup | | allowDefaultCodec (codec) | encoder/decoder가 둘 다 null이고 textline이 false이면 netty 컴포넌트가 기본 코덱을 설치해요. allowDefaultCodec를 false로 설정하면 netty 컴포넌트가 필터 체인의 첫 요소로 기본 코덱을 설치하지 않아요. | true | boolean | | autoAppendDelimiter (codec) | textline 코덱으로 보낼 때 빠진 종료 구분자(end delimiter)를 자동으로 붙일지 여부예요. | true | boolean | | decoderMaxLineLength (codec) | textline 코덱에 쓸 최대 라인 길이예요. | 1024 | int | | decoders (codec) | 사용할 디코더 목록이에요. 콤마로 구분한 값을 가진 String을 쓸 수 있고, 그 값들은 레지스트리에서 찾아 보게 돼요. Camel이 찾아 보도록 하려면 값을 # 접두어로 시작해야 한다는 점만 기억하세요. | | String | | delimiter (codec) |

textline 코덱에 쓸 구분자(delimiter)예요. 가능한 값은 LINE과 NULL이에요.

Enum values:

  • LINE

  • NULL

| LINE | TextLineDelimiter | | encoders (codec) | 사용할 인코더 목록이에요. 콤마로 구분한 값을 가진 String을 쓸 수 있고, 그 값들은 레지스트리에서 찾아 보게 돼요. Camel이 찾아 보도록 하려면 값을 # 접두어로 시작해야 한다는 점만 기억하세요. | | String | | encoding (codec) | textline 코덱에 쓸 인코딩(문자셋 이름)이에요. 지정하지 않으면 Camel이 JVM 기본 Charset을 써요. | | String | | textline (codec) | TCP에서만 쓰여요. 코덱을 지정하지 않았다면 이 플래그로 텍스트 라인 기반 코덱을 쓴다고 표시할 수 있어요. 지정하지 않았거나 값이 false이면 TCP 위에서 객체 직렬화(Object Serialization)를 가정해요. 다만 기본적으로 String만 직렬화할 수 있어요. | false | boolean | | enabledProtocols (security) | SSL을 사용할 때 활성화할 프로토콜이에요. | TLSv1.2,TLSv1.3 | String | | hostnameVerification (security) | SSLEngine에서 호스트명 검증(hostname verification)을 켜거나 끕니다. | false | boolean | | keyStoreFormat (security) | 페이로드 암호화에 쓸 키스토어 포맷이에요. 설정하지 않으면 JKS가 기본값이에요. | | String | | keyStoreResource (security) | 암호화에 쓸 클라이언트 측 인증서 키스토어예요. 기본으로 classpath에서 불러오지만, classpath:, file:, http: 접두어를 붙여서 다른 시스템에서 리소스를 불러올 수 있어요. | | String | | needClientAuth (security) | SSL을 사용할 때 서버가 클라이언트 인증을 요구할지 설정해요. | false | boolean | | passphrase (security) | keyStore와 trustStore에 쓸 비밀번호예요. 두 리소스에 같은 비밀번호를 설정해야 해요. | | String | | securityProvider (security) | 페이로드 암호화에 쓸 보안 프로바이더예요. 설정하지 않으면 SunX509가 기본값이에요. | | String | | ssl (security) | 이 엔드포인트에 SSL 암호화를 적용할지 정하는 설정이에요. | false | boolean | | sslClientCertHeaders (security) | 활성화하고 SSL 모드일 때 Netty consumer가 subject 이름, issuer 이름, 일련번호, 유효 기간 같은 클라이언트 인증서 정보를 담은 헤더로 Camel 메시지를 풍부하게(enrich) 만들어요. | false | boolean | | sslContextParameters (security) | SSLContextParameters로 보안을 설정해요. | | SSLContextParameters | | sslHandler (security) | SSL 핸들러를 돌려주는 데 쓸 수 있는 클래스에 대한 참조예요. | | SslHandler | | trustStoreResource (security) | 암호화에 쓸 서버 측 인증서 키스토어예요. 기본으로 classpath에서 불러오지만, classpath:, file:, http: 접두어를 붙여서 다른 시스템에서 리소스를 불러올 수 있어요. | | String |

메시지 헤더 (Message Headers)

Netty 컴포넌트가 지원하는 메시지 헤더는 아래와 같아요:

Name Description Default Type
CamelNettyCloseChannelWhenComplete (common) Constant: NETTY_CLOSE_CHANNEL_WHEN_COMPLETE 처리가 끝난 뒤 채널을 닫아야 하는지 나타내요. Boolean
CamelNettyChannelHandlerContext (common) Constant: NETTY_CHANNEL_HANDLER_CONTEXT 채널 핸들러 컨텍스트예요. ChannelHandlerContext
CamelNettyRemoteAddress (common) Constant: NETTY_REMOTE_ADDRESS 원격 주소예요. SocketAddress
CamelNettyLocalAddress (common) Constant: NETTY_LOCAL_ADDRESS 로컬 주소예요. SocketAddress
CamelNettySSLSession (common) Constant: NETTY_SSL_SESSION SSL 세션이에요. SSLSession
CamelNettySSLClientCertSubjectName (common) Constant: NETTY_SSL_CLIENT_CERT_SUBJECT_NAME SSL 클라이언트 인증서의 subject 이름이에요. String
CamelNettySSLClientCertIssuerName (common) Constant: NETTY_SSL_CLIENT_CERT_ISSUER_NAME SSL 클라이언트 인증서의 issuer 이름이에요. String
CamelNettySSLClientCertSerialNumber (common) Constant: NETTY_SSL_CLIENT_CERT_SERIAL_NO SSL 클라이언트 인증서의 일련번호(serial number)예요. String
CamelNettySSLClientCertNotBefore (common) Constant: NETTY_SSL_CLIENT_CERT_NOT_BEFORE SSL 클라이언트 인증서의 not before(유효 시작) 날짜예요. Date
CamelNettySSLClientCertNotAfter (common) Constant: NETTY_SSL_CLIENT_CERT_NOT_AFTER SSL 클라이언트 인증서의 not after(유효 만료) 날짜예요. Date
CamelNettyRequestTimeout (common) Constant: NETTY_REQUEST_TIMEOUT 읽기 타임아웃이에요. Long
CamelNettyChannel (common) Constant: NETTY_CHANNEL Netty Channel 객체예요. Channel

사용법 (Usage)

레지스트리 기반 옵션 (Registry-based Options)

코덱 핸들러와 SSL 키스토어는 레지스트리에 등록할 수 있어요. 예컨대 Spring XML 파일에 등록하는 식이죠. 전달할 수 있는 값은 다음과 같아요:

Name Description
passphrase keyStore와 trustStore에 쓸 비밀번호예요. 두 리소스에 같은 비밀번호를 설정해야 해요.
keyStoreFormat 페이로드 암호화에 쓸 키스토어 포맷이에요. 설정하지 않으면 JKS가 기본값이에요
securityProvider 페이로드 암호화에 쓸 보안 프로바이더예요. 설정하지 않으면 SunX509가 기본값이에요.
keyStoreResource 암호화에 쓸 클라이언트 측 인증서 키스토어예요. 기본으로 classpath에서 불러오지만, "classpath:", "file:", "http:" 접두어를 붙여서 다른 시스템에서 리소스를 불러올 수 있어요.
trustStoreResource 암호화에 쓸 서버 측 인증서 키스토어예요. 기본으로 classpath에서 불러오지만, "classpath:", "file:", "http:" 접두어를 붙여서 다른 시스템에서 리소스를 불러올 수 있어요.
sslHandler SSL 핸들러를 돌려주는 데 쓸 수 있는 클래스에 대한 참조예요
encoder 아웃바운드 페이로드의 특별한 마샬링을 수행하는 데 쓸 수 있는 커스텀 ChannelHandler 클래스예요. 반드시 io.netty.channel.ChannelInboundHandlerAdapter를 오버라이드해야 해요.
encoders 사용할 인코더 목록이에요. 콤마로 구분한 값을 가진 문자열을 쓸 수 있고, 그 값들은 레지스트리에서 찾아 보게 돼요. Camel이 찾아 보도록 하려면 값을 # 접두어로 시작해야 한다는 점을 잊지 마세요.
decoder 인바운드 페이로드의 특별한 마샬링을 수행하는 데 쓸 수 있는 커스텀 ChannelHandler 클래스예요. 반드시 io.netty.channel.ChannelOutboundHandlerAdapter를 오버라이드해야 해요.
decoders 사용할 디코더 목록이에요. 콤마로 구분한 값을 가진 문자열을 쓸 수 있고, 그 값들은 레지스트리에서 찾아 보게 돼요. Camel이 찾아 보도록 하려면 값을 # 접두어로 시작해야 한다는 점을 잊지 마세요.

참고 non-shareable 인코더/디코더 사용법은 아래에서 읽어 보세요.

공유 불가(non-shareable) 인코더/디코더 다루기 (Using non-shareable encoders or decoders)

인코더나 디코더가 shareable하지 않다면(예: @Shareable 클래스 애노테이션이 없는 경우), 인코더/디코더가 org.apache.camel.component.netty.ChannelHandlerFactory 인터페이스를 구현하고 newChannelHandler 메서드에서 새 인스턴스를 돌려줘야 해요. 인코더/디코더를 안전하게 쓸 수 있도록 보장하기 위해서예요. 그렇지 않으면 Netty 컴포넌트가 엔드포인트를 만들 때 WARN 로그를 남겨요.

Netty 컴포넌트는 자주 쓰이는 메서드를 여럿 갖고 있는 org.apache.camel.component.netty.ChannelHandlerFactories 팩토리 클래스를 제공해요.

Netty 엔드포인트로 메시지 주고받기 (Sending Messages to/from a Netty endpoint)

Netty Producer

Producer 모드에서는 이 컴포넌트로 TCP나 UDP 프로토콜을 써서(선택적으로 SSL 지원) 소켓 엔드포인트에 페이로드를 보낼 수 있어요.

producer 모드는 one-way 방식과 request-response 방식 연산을 모두 지원해요.

Netty Consumer

Consumer 모드에서는 이 컴포넌트가 이런 능력을 제공해요:

  • TCP나 UDP 프로토콜을 써서(선택적으로 SSL 지원) 지정한 소켓을 listen하고,

  • 소켓에서 text/xml, 바이너리, 직렬화 객체 기반 페이로드로 요청을 받아서,

  • 메시지 교환으로 라우트를 따라 전달해요.

consumer 모드도 one-way 방식과 request-response 방식 연산을 모두 지원해요.

여러 개 코덱 쓰기 (Using Multiple Codecs)

경우에 따라서는 netty 파이프라인에 인코더와 디코더 체인을 추가해야 할 수 있어요. Camel netty 엔드포인트에 코덱을 여러 개 추가하려면 encoders와 decoders URI 파라미터를 써야 해요. encoder, decoder 파라미터와 마찬가지로 파이프라인에 추가할 참조(ChannelUpstreamHandlers, ChannelDownstreamHandlers 목록)를 공급하는 데 쓰여요.

encoders를 지정하면 encoder 파라미터는 무시된다는 점에 주의하세요. decoders와 decoder 파라미터도 마찬가지예요.

참고 non-shareable 인코더/디코더 사용법은 더 읽어 보세요.

코덱 목록은 엔드포인트를 만들 때 해석할 수 있도록 Camel 레지스트리에 추가해야 해요.

Java-only: Java 프로그래밍 방식 레지스트리 설정

ChannelHandlerFactory lengthDecoder = ChannelHandlerFactories.newLengthFieldBasedFrameDecoder(1048576, 0, 4, 0, 4);

StringDecoder stringDecoder = new StringDecoder();
registry.bind("length-decoder", lengthDecoder);
registry.bind("string-decoder", stringDecoder);

LengthFieldPrepender lengthEncoder = new LengthFieldPrepender(4);
StringEncoder stringEncoder = new StringEncoder();
registry.bind("length-encoder", lengthEncoder);
registry.bind("string-encoder", stringEncoder);

List<ChannelHandler> decoders = new ArrayList<ChannelHandler>();
decoders.add(lengthDecoder);
decoders.add(stringDecoder);

List<ChannelHandler> encoders = new ArrayList<ChannelHandler>();
encoders.add(lengthEncoder);
encoders.add(stringEncoder);

registry.bind("encoders", encoders);
registry.bind("decoders", decoders);

Spring 네이티브 컬렉션 지원을 쓰면 애플리케이션 컨텍스트에서 코덱 목록을 지정할 수 있어요

<util:list id="decoders" list-class="java.util.LinkedList">
        <bean class="org.apache.camel.component.netty.ChannelHandlerFactories" factory-method="newLengthFieldBasedFrameDecoder">
            <constructor-arg value="1048576"/>
            <constructor-arg value="0"/>
            <constructor-arg value="4"/>
            <constructor-arg value="0"/>
            <constructor-arg value="4"/>
        </bean>
        <bean class="io.netty.handler.codec.string.StringDecoder"/>
    </util:list>

    <util:list id="encoders" list-class="java.util.LinkedList">
        <bean class="io.netty.handler.codec.LengthFieldPrepender">
            <constructor-arg value="4"/>
        </bean>
        <bean class="io.netty.handler.codec.string.StringEncoder"/>
    </util:list>

    <bean id="length-encoder" class="io.netty.handler.codec.LengthFieldPrepender">
        <constructor-arg value="4"/>
    </bean>
    <bean id="string-encoder" class="io.netty.handler.codec.string.StringEncoder"/>

    <bean id="length-decoder" class="org.apache.camel.component.netty.ChannelHandlerFactories" factory-method="newLengthFieldBasedFrameDecoder">
        <constructor-arg value="1048576"/>
        <constructor-arg value="0"/>
        <constructor-arg value="4"/>
        <constructor-arg value="0"/>
        <constructor-arg value="4"/>
    </bean>
    <bean id="string-decoder" class="io.netty.handler.codec.string.StringDecoder"/>

이렇게 만든 빈 이름은 콤마로 구분한 목록이나 목록에 담은 형태로 netty 엔드포인트 정의에서 쓸 수 있어요. 예를 들면:

  • Java

  • XML

  • YAML

 from("direct:multiple-codec").to("netty:tcp://0.0.0.0:{{port}}?encoders=#encoders&sync=false");

 from("netty:tcp://0.0.0.0:{{port}}?decoders=#length-decoder,#string-decoder&sync=false").to("mock:multiple-codec");
<route>
    <from uri="direct:multiple-codec"/>
    <to uri="netty:tcp://0.0.0.0:5150?encoders=#encoders&amp;sync=false"/>
</route>
<route>
    <from uri="netty:tcp://0.0.0.0:5150?decoders=#length-decoder,#string-decoder&amp;sync=false"/>
    <to uri="mock:multiple-codec"/>
</route>
- route:
    from:
      uri: direct:multiple-codec
      steps:
        - to:
            uri: "netty:tcp://0.0.0.0:5150"
            parameters:
              encoders: "#encoders"
              sync: false
- route:
    from:
      uri: "netty:tcp://0.0.0.0:5150"
      parameters:
        decoders: "#length-decoder,#string-decoder"
        sync: false
      steps:
        - to:
            uri: mock:multiple-codec

처리가 끝나면 채널 닫기 (Closing Channel When Complete)

서버로 동작할 때는 클라이언트와의 대화가 끝났을 때 채널을 닫고 싶은 경우가 있어요. 이럴 때는 엔드포인트 옵션 disconnect=true만 설정하면 돼요.

하지만 메시지별로 Camel에 지시할 수도 있어요. Camel에게 채널을 닫으라고 지시하려면 CamelNettyCloseChannelWhenComplete 키를 가진 헤더를 boolean true 값으로 추가하면 돼요. 예컨대 아래 예제는 bye 메시지를 클라이언트에 쓰고 나서 채널을 닫아요:

  • Java

  • XML

  • YAML

from("netty:tcp://0.0.0.0:8080")
    .setBody(simple("Bye ${body}"))
    // set the CamelNettyCloseChannelWhenComplete header to true to close the channel
    .setHeader("CamelNettyCloseChannelWhenComplete", constant(true));
<route>
  <from uri="netty:tcp://0.0.0.0:8080"/>
  <setBody>
    <simple>Bye ${body}</simple>
  </setBody>
  <!-- set the CamelNettyCloseChannelWhenComplete header to true to close the channel -->
  <setHeader name="CamelNettyCloseChannelWhenComplete">
    <constant>true</constant>
  </setHeader>
</route>
# set the CamelNettyCloseChannelWhenComplete header to true to close the channel
- route:
    from:
      uri: netty:tcp://0.0.0.0:8080
      steps:
        - setBody:
            simple: "Bye ${body}"
        - setHeader:
            name: CamelNettyCloseChannelWhenComplete
            constant: true

커스텀 채널 파이프라인 팩토리를 추가하면 만들어지는 파이프라인을 완전히 제어할 수 있어요

커스텀 파이프라인 (Custom pipeline)

커스텀 채널 파이프라인은 커스텀 핸들러·인코더·디코더를 끼워 넣어 핸들러/인터셉터 체인을 사용자가 완전히 제어하게 해 줘요. Netty 엔드포인트 URL에 그런 것들을 복잡하게 지정할 필요가 없죠.

커스텀 파이프라인을 추가하려면 커스텀 채널 파이프라인 팩토리를 만들어서 컨텍스트 레지스트리(또는 camel-spring ApplicationContextRegistry 등)를 통해 컨텍스트에 등록해야 해요.

커스텀 파이프라인 팩토리는 다음처럼 만들어야 해요

  • producer에 연결되는 채널 파이프라인 팩토리는 추상 클래스 ClientInitializerFactory를 확장해야 해요.

  • consumer에 연결되는 채널 파이프라인 팩토리는 추상 클래스 ServerInitializerFactory를 확장해야 해요.

  • 클래스는 initChannel() 메서드를 오버라이드해서 커스텀 핸들러·인코더·디코더를 끼워 넣어야 해요. initChannel()을 오버라이드하지 않으면 핸들러, 인코더, 디코더가 하나도 연결되지 않은 파이프라인이 만들어져요.

아래 예제는 ServerInitializerFactory 팩토리를 만드는 방법을 보여 줘요

커스텀 파이프라인 팩토리 사용 (Using custom pipeline factory)

Java-only: Java 클래스 정의

public class SampleServerInitializerFactory extends ServerInitializerFactory {
    private int maxLineSize = 1024;

    protected void initChannel(Channel ch) throws Exception {
        ChannelPipeline channelPipeline = ch.pipeline();

        channelPipeline.addLast("encoder-SD", new StringEncoder(CharsetUtil.UTF_8));
        channelPipeline.addLast("decoder-DELIM", new DelimiterBasedFrameDecoder(maxLineSize, true, Delimiters.lineDelimiter()));
        channelPipeline.addLast("decoder-SD", new StringDecoder(CharsetUtil.UTF_8));
        // here we add the default Camel ServerChannelHandler for the consumer, to allow Camel to route the message, etc.
        channelPipeline.addLast("handler", new ServerChannelHandler(consumer));
    }
}

커스텀 채널 파이프라인 팩토리는 레지스트리에 추가한 뒤 다음처럼 Camel 라우트에서 인스턴스화해서 쓸 수 있어요

Java-only: Java 프로그래밍 방식 레지스트리·라우트 설정

Registry registry = camelContext.getRegistry();
ServerInitializerFactory factory = new TestServerInitializerFactory();
registry.bind("spf", factory);
from("netty:tcp://0.0.0.0:5150?serverInitializerFactory=#spf")
    .setBody(constant("When You Go Home, Tell Them Of Us And Say, For Your Tomorrow, We Gave Our Today."));

Netty boss/worker 스레드 풀 재사용 (Reusing Netty boss and worker thread pools)

Netty에는 boss와 worker 두 종류의 스레드 풀이 있어요. 기본적으로 각 Netty consumer와 producer는 자기만의 스레드 풀을 가져요. 여러 consumer나 producer가 이 스레드 풀을 재사용하려면 스레드 풀을 만들어서 레지스트리에 등록해야 해요.

예컨대 Spring XML을 쓰면 아래처럼 NettyWorkerPoolBuilder로 워커 스레드 2개짜리 공유 워커 스레드 풀을 만들 수 있어요:

<!-- use the worker pool builder to help create the shared thread pool -->
<bean id="poolBuilder" class="org.apache.camel.component.netty.NettyWorkerPoolBuilder">
  <property name="workerCount" value="2"/>
</bean>

<!-- the shared worker thread pool -->
<bean id="sharedPool" class="org.jboss.netty.channel.socket.nio.WorkerPool"
      factory-bean="poolBuilder" factory-method="build" destroy-method="shutdown">
</bean>

팁 boss 스레드 풀용으로는 Netty consumer를 위한 org.apache.camel.component.netty.NettyServerBossPoolBuilder 빌더와 Netty producer를 위한 org.apache.camel.component.netty.NettyClientBossPoolBuilder가 있어요.

그런 다음 Camel 라우트에서는 아래처럼 URI에 workerGroup 옵션을 설정해서 이 워커 풀을 참조할 수 있어요:

  • Java

  • XML

  • YAML

from("netty:tcp://0.0.0.0:5021?textline=true&sync=true&workerGroup=#sharedPool&usingExecutorService=false")
    .to("log:result");
<route>
  <from uri="netty:tcp://0.0.0.0:5021?textline=true&amp;sync=true&amp;workerGroup=#sharedPool&amp;usingExecutorService=false"/>
  <to uri="log:result"/>
</route>
- route:
    from:
      uri: netty:tcp://0.0.0.0:5021
      parameters:
        textline: true
        sync: true
        workerGroup: "#sharedPool"
        usingExecutorService: false
      steps:
        - to:
            uri: log:result

다른 라우트가 더 있다면 공유 워커 풀을 이렇게 참조하면 돼요:

  • Java

  • XML

  • YAML

from("netty:tcp://0.0.0.0:5022?textline=true&sync=true&workerGroup=#sharedPool&usingExecutorService=false")
    .to("log:result");
<route>
  <from uri="netty:tcp://0.0.0.0:5022?textline=true&amp;sync=true&amp;workerGroup=#sharedPool&amp;usingExecutorService=false"/>
  <to uri="log:result"/>
</route>
- route:
    from:
      uri: netty:tcp://0.0.0.0:5022
      parameters:
        textline: true
        sync: true
        workerGroup: "#sharedPool"
        usingExecutorService: false
      steps:
        - to:
            uri: log:result

이런 식으로 계속 돼요.

단일 연결에서 request/reply로 동시 메시지 멀티플렉싱 (Multiplexing concurrent messages over a single connection with request/reply)

netty producer로 request/reply 메시징을 할 때 기본적으로는 각 메시지가 공유하지 않는 연결(풀에서 꺼낸)로 전송돼요. 덕분에 응답이 자동으로 올바른 요청 스레드에 매핑돼서 Camel에서 이어서 라우팅될 수 있어요. 다시 말해 request/reply 메시지 사이의 상관관계(correlation)는 기본으로 동작하는데, 응답이 요청을 보낼 때 쓴 그 연결로 돌아오고, 그 연결은 다른 사람과 공유되지 않기 때문이에요. 응답이 돌아오면 연결은 연결 풀로 반환되고, 다른 쪽에서 재사용할 수 있게 돼요.

하지만 하나의 공유 연결에서 동시에 request/response를 멀티플렉싱하고 싶다면 producerPoolEnabled=false로 설정해서 연결 풀링을 꺼야 해요. 이렇게 하면 응답이 순서대로 돌아오지 않을 때 응답이 뒤섞이는 잠재적 문제가 생겨요. 그래서 요청과 응답 메시지 양쪽에 correlation id를 담아서, Camel에서 메시지를 계속 처리하는 콜백에 응답을 제대로 연결 지을 수 있어야 해요. 이러려면 NettyCamelStateCorrelationManager를 correlation manager로 구현하고 correlationManager=#myManager 옵션으로 설정해야 해요.

참고 커스텀 correlation manager를 만들 때는 TimeoutCorrelationManagerSupport를 확장하는 걸 권장해요. 타임아웃 등 직접 구현해야 하는 복잡한 부분을 대신 지원해 주거든요.

Apache Camel 소스 코드에는 camel-example-netty-custom-correlation 디렉터리 아래 examples 디렉터리에서 예제를 찾을 수 있어요.

네이티브 트랜스포트 (Native transport)

네이티브 트랜스포트를 켜려면 OS와 CPU 아키텍처에 따라 epoll이나 kqueue용 추가 의존성을 넣어야 해요. 더 쉽게 하려면 pom.xml의 build 섹션에 다음 확장을 추가하세요:

<extensions>
    <extension>
        <groupId>kr.motd.maven</groupId>
        <artifactId>os-maven-plugin</artifactId>
    </extension>
</extensions>

그런 다음 다음 의존성을 추가해야 해요:

  • Linux/Unix

  • MacOS/BSD

<dependency>
    <groupId>io.netty</groupId>
    <artifactId>netty-transport-native-epoll</artifactId>
    <classifier>${os.detected.classifier}</classifier>
</dependency>
<dependency>
    <groupId>io.netty</groupId>
    <artifactId>netty-transport-native-kqueue</artifactId>
    <classifier>${os.detected.classifier}</classifier>
</dependency>

예제 (Examples)

Request-Reply와 직렬화 객체 페이로드를 쓰는 UDP Netty 엔드포인트 (A UDP Netty endpoint using Request-Reply and serialized object payload)

객체 직렬화는 기본적으로 허용되지 않는다는 점에 주의하세요. 그래서 디코더를 설정해야 해요.

Java-only: Java 애노테이션과 클래스 정의

@BindToRegistry("decoder")
public ChannelHandler getDecoder() throws Exception {
    return new DefaultChannelHandlerFactory() {
        @Override
        public ChannelHandler newChannelHandler() {
            return new DatagramPacketObjectDecoder(ClassResolvers.weakCachingResolver(null));
        }
    };
}

from("netty:udp://0.0.0.0:5155?sync=true&decoders=#decoder")
    .to("bean:poetryProcessor");

참고 Camel 4.23부터는 안전하지 않은 Java 역직렬화에 대한 다계층 방어(defense-in-depth) 조치로, 디코딩하는 동안 ObjectDecoder와 DatagramPacketObjectDecoder가 항상 JEP-290 java.io.ObjectInputFilter를 설치해요. 명시적인 패턴을 넘기지 않으면 JVM 전역 jdk.serialFilter가 설정돼 있을 때 이를 존중하고, 설정돼 있지 않으면 Camel 기본 공유 allow-list를 적용해요(표준 Java와 Apache Camel 타입은 허용하고, java.net.**은 거부하며, JEP-290 그래프 형태 제한을 강제해요).

신뢰할 수 없는 피어에 노출되는 디코더는 두 인수 생성자에 필터 패턴(jdk.serialFilter와 같은 문법)을 넘겨서 더 엄격한 allow-list를 설정하세요.

return new DatagramPacketObjectDecoder(ClassResolvers.weakCachingResolver(null), "com.example.model.**;java.**;!*");

One-way 통신을 쓰는 TCP 기반 Netty consumer 엔드포인트 (A TCP-based Netty consumer endpoint using One-way communication)

  • Java

  • XML

  • YAML

from("netty:tcp://0.0.0.0:5150")
    .to("mock:result");
<route>
  <from uri="netty:tcp://0.0.0.0:5150"/>
  <to uri="mock:result"/>
</route>
- route:
    from:
      uri: netty:tcp://0.0.0.0:5150
      steps:
        - to:
            uri: mock:result

Request-Reply 통신을 쓰는 SSL/TCP 기반 Netty consumer 엔드포인트 (An SSL/TCP-based Netty consumer endpoint using Request-Reply communication)

JSSE 설정 유틸리티 사용하기

Netty 컴포넌트는 Camel JSSE 설정 유틸리티로 SSL/TLS 설정을 지원해요. 이 유틸리티는 컴포넌트별로 직접 작성해야 하는 코드 양을 크게 줄여 주고, 엔드포인트와 컴포넌트 레벨에서 설정할 수 있어요. 다음 예제는 Netty 컴포넌트에서 이 유틸리티를 쓰는 방법을 보여 줘요.

컴포넌트의 프로그래밍 방식 설정

Java-only: Java 프로그래밍 방식 SSL 설정

KeyStoreParameters ksp = new KeyStoreParameters();
ksp.setResource("/users/home/server/keystore.jks");
ksp.setPassword("keystorePassword");

KeyManagersParameters kmp = new KeyManagersParameters();
kmp.setKeyStore(ksp);
kmp.setKeyPassword("keyPassword");

SSLContextParameters scp = new SSLContextParameters();
scp.setKeyManagers(kmp);

NettyComponent nettyComponent = getContext().getComponent("netty", NettyComponent.class);
nettyComponent.getConfiguration().setSslContextParameters(scp);

Spring DSL 기반 엔드포인트 설정

...
  <camel:sslContextParameters
      id="sslContextParameters">
    <camel:keyManagers
        keyPassword="keyPassword">
      <camel:keyStore
          resource="/users/home/server/keystore.jks"
          password="keystorePassword"/>
    </camel:keyManagers>
  </camel:sslContextParameters>...
...
  <to uri="netty:tcp://0.0.0.0:5150?sync=true&amp;ssl=true&amp;sslContextParameters=#sslContextParameters"/>
...

Jetty 컴포넌트의 기본 SSL/TLS 설정 사용하기

Java-only: SSL 라우트 설정

from("netty:tcp://0.0.0.0:5150?sync=true&ssl=true&passphrase=changeit&keyStoreResource=file:src/test/resources/keystore.jks&trustStoreResource=file:src/test/resources/keystore.jks")
    .setBody(constant("When You Go Home, Tell Them Of Us And Say, For Your Tomorrow, We Gave Our Today."));

SSLSession과 클라이언트 인증서 접근하기

클라이언트 인증서의 상세 정보가 필요하다면 javax.net.ssl.SSLSession에 접근할 수 있어요. ssl=true이면 Netty 컴포넌트가 아래처럼 SSLSession을 Camel 메시지의 헤더로 저장해요:

Java-only: Java SSL 세션 API

SSLSession session = exchange.getIn().getHeader("CamelNettySSLSession", SSLSession.class);
// get the first certificate which is client certificate
javax.security.cert.X509Certificate cert = session.getPeerCertificateChain()[0];
Principal principal = cert.getSubjectDN();

클라이언트를 인증하려면 needClientAuth=true를 설정하는 걸 잊지 마세요. 그렇지 않으면 SSLSession이 클라이언트 인증서 정보에 접근할 수 없고, javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated 예외가 날 수 있어요. 클라이언트 인증서가 만료됐거나 유효하지 않은 경우 등에도 같은 예외가 날 수 있어요.

팁 sslClientCertHeaders 옵션을 true로 설정하면 클라이언트 인증서의 상세 정보를 담은 헤더로 Camel 메시지를 풍부하게(enrich) 만들어요. 예컨대 subject 이름은 CamelNettySSLClientCertSubjectName 헤더에서 바로 확인할 수 있어요.

더 알아보기 (Learn more)

Netty 컴포넌트의 최신 옵션 목록과 설정 예제는 공식 문서에서 확인할 수 있어요. 의존성 좌표는 본문 앞부분의 Maven 스니펫대로 org.apache.camel:camel-netty 아티팩트를 Camel 코어와 같은 버전으로 쓰면 되고, 네이티브 트랜스포트가 필요하면 Native transport 섹션의 epoll·kqueue 의존성 추가 방법을 참고하세요. 채널 파이프라인 구조 자체가 궁금하면 Netty 프로젝트 문서도 함께 보면 도움이 돼요.