46.7. 예
46.7.1. Request-Reply 및 직렬화된 오브젝트 페이로드를 사용하는 UDP Netty 끝점 링크 복사링크가 클립보드에 복사되었습니다!
개체 직렬화는 기본적으로 허용되지 않으므로 디코더를 구성해야 합니다.
@BindToRegistry("decoder")
public ChannelHandler getDecoder() throws Exception {
return new DefaultChannelHandlerFactory() {
@Override
public ChannelHandler newChannelHandler() {
return new DatagramPacketObjectDecoder(ClassResolvers.weakCachingResolver(null));
}
};
}
RouteBuilder builder = new RouteBuilder() {
public void configure() {
from("netty:udp://0.0.0.0:5155?sync=true&decoders=#decoder")
.process(new Processor() {
public void process(Exchange exchange) throws Exception {
Poetry poetry = (Poetry) exchange.getIn().getBody();
// Process poetry in some way
exchange.getOut().setBody("Message received);
}
}
}
};
46.7.2. 단방향 통신을 사용하는 TCP 기반 Netty 소비자 끝점 링크 복사링크가 클립보드에 복사되었습니다!
RouteBuilder builder = new RouteBuilder() {
public void configure() {
from("netty:tcp://0.0.0.0:5150")
.to("mock:result");
}
};
46.7.3. Request-Reply 통신을 사용하는 SSL/TCP 기반 Netty 소비자 끝점 링크 복사링크가 클립보드에 복사되었습니다!
JSSE 설정 utility 사용
Netty 구성 요소는 Camel JSSE 구성 utility 를 통해 SSL/TLS 구성을 지원합니다. 이 유틸리티를 사용하면 작성하는데 필요한 구성 요소별 코드의 양이 크게 감소하고 끝점 및 구성 요소 수준에서 구성할 수 있습니다. 다음 예제에서는 Netty 구성 요소에서 유틸리티를 사용하는 방법을 보여줍니다.
구성 요소의 프로그래밍 방식 구성
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.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&ssl=true&sslContextParameters=#sslContextParameters"/>
...
>-<ty Component에서 기본 SSL/TLS 구성 사용
Registry registry = context.getRegistry();
registry.bind("password", "changeit");
registry.bind("ksf", new File("src/test/resources/keystore.jks"));
registry.bind("tsf", new File("src/test/resources/keystore.jks"));
context.addRoutes(new RouteBuilder() {
public void configure() {
String netty_ssl_endpoint =
"netty:tcp://0.0.0.0:5150?sync=true&ssl=true&passphrase=#password"
+ "&keyStoreFile=#ksf&trustStoreFile=#tsf";
String return_string =
"When You Go Home, Tell Them Of Us And Say,"
+ "For Your Tomorrow, We Gave Our Today.";
from(netty_ssl_endpoint)
.process(new Processor() {
public void process(Exchange exchange) throws Exception {
exchange.getOut().setBody(return_string);
}
}
}
});
SSLSession 및 클라이언트 인증서에 대한 액세스 권한 얻기
클라이언트 인증서에 대한 세부 정보를 가져와야 하는 경우 javax.net.ssl.SSLSession 에 액세스할 수 있습니다. ssl=true 인 경우 Netty 구성 요소는 다음과 같이 Camel Message에 헤더로 SSLSession 을 저장합니다.
SSLSession session = exchange.getIn().getHeader(NettyConstants.NETTY_SSL_SESSION, 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 Message를 보강할 수 있습니다. 예를 들어 제목 이름은 CamelNettySSLClientCertSubjectName 헤더에서 쉽게 사용할 수 있습니다.
46.7.4. 다중 코드 사용 링크 복사링크가 클립보드에 복사되었습니다!
어떤 경우에는 인코더 및 디코더의 체인을 netty 파이프라인에 추가해야 할 수도 있습니다. camel netty 엔드포인트에 multpile codecs를 추가하려면 'encoders' 및 'decoders' uri 매개변수를 사용해야 합니다. 'encoder' 및 'decoder' 매개변수는 파이프라인에 추가해야 하는 참조(채널Up스트림 처리기 및 ChannelDownstreamHandler 목록)를 제공하는 데 사용됩니다. 인코더가 지정된 경우 디코더 및 디코더 매개 변수에 대해 인코더 매개 변수가 무시됩니다.
공유할 수 없는 인코더/디코더 사용에 대해 자세히 알아보십시오.
엔드포인트가 생성될 때 해결될 수 있도록 Camel의 레지스트리에 codecs 목록을 추가해야 합니다.
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의 네이티브 컬렉션 지원을 사용하여 애플리케이션 컨텍스트에서 codec 목록을 지정할 수 있습니다.
<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"/>
그런 다음 빈 이름을 쉼표로 구분된 목록으로 지정하거나 목록에 포함된 순 엔드포인트 정의에 사용할 수 있습니다.
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");
또는 XML을 통해
<camelContext id="multiple-netty-codecs-context" xmlns="http://camel.apache.org/schema/spring">
<route>
<from uri="direct:multiple-codec"/>
<to uri="netty:tcp://0.0.0.0:5150?encoders=#encoders&sync=false"/>
</route>
<route>
<from uri="netty:tcp://0.0.0.0:5150?decoders=#length-decoder,#string-decoder&sync=false"/>
<to uri="mock:multiple-codec"/>
</route>
</camelContext>