53
ソケット接続をApache Camelに統合する 日本Apache Camelユーザ会 @ssogabe

Netty & Apache Camel

  • Upload
    ssogabe

  • View
    691

  • Download
    5

Embed Size (px)

DESCRIPTION

Netty 3.Xベースの概略とApache Camel Nettyコンポーネントの簡単な説明です

Citation preview

Page 1: Netty & Apache Camel

ソケット接続をApache Camelに統合する

日本Apache Camelユーザ会@ssogabe

Page 2: Netty & Apache Camel

Netty

Page 3: Netty & Apache Camel

Javaで非同期、イベント駆動のサーバ・クライアントアプリケーションを構築するためのフレームワーク

高パフォーマンス、高スケーラビリティo NIOをラッピング

o 処理をレイヤーごとに分離

TCP、UDP以外にも、HTTP、WebSocket、RTSPなどもサポート

Akka、Play!、HornetQなどで使用されている

Page 4: Netty & Apache Camel

Nettyでは、以下のバージョンを開発中

o Netty 3.9.3

o Netty 4.0.21

o Netty 4.1.0 Beta1

o Netty 5.0 alpha

Apache Camel 2.10.6では、Netty 3.2.10を使用

ここでは、3.Xベースを対象とする

Page 5: Netty & Apache Camel

アーキテクチャ

Page 6: Netty & Apache Camel

発生したイベントを、Handlerが処理を行う

Nettyでは、22個のイベントをサポート

主なイベント

No. イベント 説明

1 channelOpen チャネルがオープンしたが、まだ、ポートにバインドも、接続もしていない

2 channelConnected 接続先とのコネクションが確立した

3 writeComplete チャネルに何か書き込まれた

4 messageReceived メッセージを受信した

5 channelDisconnected 接続先とのコネクションが切断された

6 channelClosed チャネルがクローズした

7 exceptionCaught I/OスレッドやChannelHandlerが例外をスローした

8 channelIdle チャネルが一定期間アイドル状態になった

Page 7: Netty & Apache Camel

メッセージをHandlerを組み合わせたChannelPipelineで処理

o “データ受信”などのイベントが、ChannelPipelineを流れる

o Handlerが処理するイベントを受け取り、イベントからデータを取得

o Nettyが提供する、ロギング、メッセージのフレーム処理などのHandlerや、メッセージの処理を行うユーザ実装のHandlerを組み合わせて処理を実装

o サーバ、クライアントいずれも同じ仕組み

Page 8: Netty & Apache Camel

実際には1つのライン上に配置

Page 9: Netty & Apache Camel

大きく分けて5種類のHandlerをサポート

送信用、受信用、送受信共用の3種類

No. カテゴリ 説明 代表的なHandler

1 フレーム ストリームからメッセージを切り出しや、電文長の追加を行う

LengthFieldBasedFrameDecoderLengthFieldPrepender

2 変換 メッセージ⇔文字列、オブジェクトや、SSL、暗号化処理を行う

StringDecoder/EncoderZlibDecoder/EncoderOneToOneDecoder/Encoder

3 イベント メッセージ受信などイベントに対するユーザ実装の処理を行う

SimpleChannelHandlerIdleStateAwareChannelHandler

4 アイドル・タイムアウト

無通信時の処理や、タイムアウトを検出する

IdleStateHandlerRead/WriteTimeoutHandler

5 その他 ロギングなどの処理 LoggingHandler

Page 10: Netty & Apache Camel

スレッドセーフではないHandlerがあるので注意o スレッドセーフなHandlerには、クラスに@Sharableを付与

o スレッドセーフの場合は、インスタンスを共有可能

Handler 送受信 スレッドセーフ

フレーム処理

DelimiterBasedFrameDecoder 受信

FixedLengthFrameDecoder 受信

LengthFieldBasedFrameDecoder 受信

LengthFieldPrepender 送信 ○

変換処理

Base64Decoder 受信 ○

Base64Encoder 送信 ○

ZliDecoder 受信

ZlibEncoder 送信

StringDecoder 受信 ○

StringEncoder 送信 ○

ObjectDecoder 受信

ObjectEncoder 送信 ○

SslHandler 送受信

Handler 送受信 スレッドセーフ

イベント処理

SimpleChannelHandler 送受信

IdleStateAwareChannelHandler 送受信

アイドル・タイムアウト処理

IdelStateHandler 受信 ○

ReadTimeoutHandler 受信 ○

WriteTimeoutHandler 送信 ○

その他

ExecutionHandler 送受信 ○

LoggingHandler 送受信 △

BlockingHandler 受信

BufferedWriteHandler 送受信

ChunkedWriteHandler 送受信

Page 11: Netty & Apache Camel

多くの場合、次の順序でHandlerを設定

Network

フレーム(ストリーム⇒メッセージ)

変換(メッセージ⇒オブジェクト)

変換(オブジェクト⇒メッセージ)

フレーム(電文長の追加)

イベント(業務処理、レスポンス作成)

UpStream(受信) DownStream(送信)

Page 12: Netty & Apache Camel

実装例

ServerBootstrap bootstrap = new ServerBootstrap(factory);bootstrap.setPipelineFactory(new ChannelPipelineFactory() {

@Overridepublic ChannelPipeline getPipeline() throws Exception {

ChannelPipeline pipeline = Channels.pipeline();

// 送信pipeline.addLast("frameEncoder", LENGTH_FIELD_PREPENDER);// UserInfoを電文に変換pipeline.addLast("userInfoEncoder", USER_INFO_ENCODER);

// 受信pipeline.addLast("frameDecoder", new LengthFieldBasedFrameDecoder(8192, 0, 4, 0, 4));// 電文をUserInfoに変換。pipeline.addLast("userInfoDecoder", USER_INFO_DECODER);

// ハンドラー追加pipeline.addLast("handler", USER_INFO_SERVER_HANDLER);

return pipeline;}

});

Page 13: Netty & Apache Camel

ChannelPipelineでは、受信したバイト列をChannelBufferで受け取る

ChannelBufferを操作して、オブジェクト⇔メッセージ変換を行う

JavaのNIOが提供するByteBufferより使い勝手が良い

o ByteBufferは、position()/limit()/flip()などを使用して、書き込み位置を正確に把握する必要がある

o 多くの場合、ByteBufferより高速に動作

デフォルトのバイトオーダーは、ビッグエンディアン

Page 14: Netty & Apache Camel

読み込み位置と書き込み位置を管理する

readXXX()でバイト列を取得、writeXXX()でバイト列を書き込むと、readerIndex/writerIndexが増加

getXXX()、setXXX()は、reader/writerIndexは増加しないので注意が必要

基本は、readXX()、writeXX()を使用

0 readerIndex writerIndex

読み書き不可バイト列 読み込み可能バイト列 書き込み可能バイト列

capacity

Page 15: Netty & Apache Camel

Handler

フレーム処理

Page 16: Netty & Apache Camel

TCP/IPのストリームベースの通信では、2つのメッセージを送信した場合、OSは2つのメッセージではなく、1つのバイト列として扱う(UDPは不要)

受信APでは、バイト列をフレーム分けする必要がある

ObjectDecoder/Encoderを使用する場合は不要

ABC

DEストリーム通信 AB CD E

ABC

DEフレーム処理

送信AP 受信AP

TCP/IP

Page 17: Netty & Apache Camel

3つのクラスを標準で提供、独自実装も可o DelimiterBasedFrameDecoder

• NUL(0x00)や改行文字などの1つ以上のデリミタで分ける

o FixedLengthFrameDecoder

• 固定のバイト長で分ける

o LengthFieldBasedFrameDecoder

• メッセージのあるフィールドから電文長を取得し分ける

動的にバイト長を算出し、先頭に付加するクラスも提供o LengthFieldPrepender

• LengthFieldBasedFrameDecoderと組み合わせることが多い

o 先頭以外にバイト長を設定する場合は、自前で行う

Page 18: Netty & Apache Camel

ServerBootstrap bootstrap = new ServerBootstrap(factory);bootstrap.setPipelineFactory(new ChannelPipelineFactory() {

@Overridepublic ChannelPipeline getPipeline() throws Exception {

ChannelPipeline pipeline = Channels.pipeline();

(snip)// 受信 (改行 ‘¥r’, ¥’n’で切り出す)pipeline.addLast("DelimiterDecoder", new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter());

(snip)

// 受信 (3バイト固定で切り出す)pipeline.addLast("FixedLengthDecoder", new FixedLengthFrameDecoder(3);

(snip)

return pipeline;}

});

Page 19: Netty & Apache Camel

メッセージに含まれるあるフィールドから電文長を取得し、必要な部分をフレーム分けするo 電文長が、ペイロードのみの場合、ヘッダ長も含む場合も対応

o フレーム分けする位置も指定可能

HDR1 電文長 HDR2 Payload

00 C0 00 00 00 04 0A 00 C0 11 FF EF

HDR1 電文長 HDR2 Payload

00 C0 00 00 00 04 0A 00 C0 11 FF EF

HDR1 電文長 HDR2 Payload

00 C0 00 00 00 0C 0A 00 C0 11 FF EF

HDR2 Payload

0A 00 C0 11 FF EF

電文長がペイロードのバイト長で、HDR1~ペイロードフレーム分けする

電文長がメッセージ全体のバイト長で、HDR2~ペイロードをフレーム分けする

Page 20: Netty & Apache Camel

5つのパラメータで、フレーム分けする範囲を指定

No. パラメータ 説明

1 maxFrameLength 最大電文長。8192など十分大きい値。この値を超えると例外が発生

2 lengthFieldOffset 電文長を表すフィールドの開始位置

3 lengthFieldLength 電文長を表すフィールドのバイト長

4 lengthAdjustment メッセージを切り出す際の補正値

5 initialBytesToStrip メッセージを切り出す開始位置

HDR1 電文長 HDR2 Payload

00 C0 00 00 00 04 0A 00 C0 11 FF EF

lengthFieldOffset(=2)

lengthFieldLength(=4)

initialBytesToStrip(=8)

lengthAdjustment(=2)

Payload

C0 11 FF EF

Page 21: Netty & Apache Camel

電文長は、ペイロードのみの場合、メッセージ全体の場合があるため、何らかの補正が必要

算出例1

HDR1 電文長 HDR2 Payload

00 C0 00 00 00 04 0A 00 C0 11 FF EF

lengthFieldOffset(=2) initialBytesToStrip(=8)

バイト長=

電文長フィールドの値

4バイト 2ba2バイト足すとメッセージ長

lengthAdjustment=2

Page 22: Netty & Apache Camel

算出例2

HDR1 電文長 HDR2 Payload

00 C0 00 00 00 0C 0A 00 C0 11 FF EF

lengthFieldOffset(=2)

initialBytesToStrip(=0)

12バイト

2ba6バイト削除するとメッセージ長 lengthAdjustment=-6

バイト長=電文長フィールドの値

Page 23: Netty & Apache Camel

フレーム処理を実装する場合は、FrameDecoderを拡張

1. 必要なバイト列を読めない場合は、nullを返す。

• nullを返すと、再度decode()が呼ばれる

2. bufferから必要なバイト列を取得

public class TimeDecoder extends FrameDecoder{

@Overrideprotected Object decode(

ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) {

if (buffer.readableBytes() < 4) { ・・・ (1)return null;

}

return buffer.readBytes(4); ・・・ (2)}

}

Page 24: Netty & Apache Camel

Handler

変換処理

Page 25: Netty & Apache Camel

フレーム処理で切り出されたChannelBufferを変換

よく使われるSSL、圧縮などを標準で提供

イベント処理で扱いやすいように、ChannelBuffer(バイト列)を、文字列やユーザ定義のオブジェクトに変換

o イベント処理では、バイト列を意識しないようにする

Page 26: Netty & Apache Camel

標準で提供する変換処理

o ObjectEncoder/Decoder以外は、フレーム処理が必要

ChannelBufferとユーザ定義オブジェクトの変換は、OneToOneEncoder/Decoderを拡張する

No. クラス 説明

1 Base64Encoder/Decoder Base64でエンコード/デコード

2 ZlibEncoder/Decoder Defalteアルゴリズムで圧縮、展開

3 StringEncoder/Decoder 文字列との変換

4 ObjectEncoder/Decoder オブジェクトのシリアライズ、デシリアライズ

5 SslHandler SSL、TLSおよびStartTLSをサポート

Page 27: Netty & Apache Camel

public class UserInfoEncoder extends OneToOneEncoder {

@Overrideprotected Object encode(ChannelHandlerContext ctx, Channel channel, Object msg)

throws Exception {if (!(msg instanceof UserInfo)) {

return msg;}UserInfo info = (UserInfo) msg;

// 可変サイズのバッファを用意ChannelBuffer buffer = ChannelBuffers.dynamicBuffer();

// Nameのバイト長とName本体byte[] byteName = info.getName().getBytes(StandardCharsets.UTF_8);buffer.writeInt(byteName.length);buffer.writeBytes(byteName);// Agebuffer.writeInt(info.getAge());

return buffer;}

}

Page 28: Netty & Apache Camel

public class UserInfoDecoder extends OneToOneDecoder {

@Overrideprotected Object decode(ChannelHandlerContext ctx, Channel channel, Object msg)

throws Exception {if (!(msg instanceof ChannelBuffer)) {

return msg;}ChannelBuffer buffer = (ChannelBuffer) msg;

// Nameのバイト長とName本体int length = buffer.readInt();byte[] byteName = new byte[length];buffer.readBytes(byteName);String name = new String(byteName, StandardCharsets.UTF_8);// ageint age = buffer.readInt();

return new UserInfo(name, age);}

}

Page 29: Netty & Apache Camel

Handler

イベント処理

Page 30: Netty & Apache Camel

発生したイベントに対するユーザ処理の実装

o メッセージを受信時にレスポンスを返す

o 例外が発生したら、コネクションを切断する など

SimpleChannelHandlerか、IdleStateAwareChannelHandlerを拡張

o 通常は前者を使用

o アイドル時の処理も実装する場合は後者

Page 31: Netty & Apache Camel

public class UserInfoServerHandler extends SimpleChannelHandler {

private final Logger log = LoggerFactory.getLogger(UserInfoServerHandler.class);

@Overridepublic void messageReceived(ChannelHandlerContext ctx, MessageEvent e)

throws Exception {UserInfo info = (UserInfo) e.getMessage();log.debug("電文を受信しました {}", info.toString());log.debug("電文を送信します");e.getChannel().write(info);

}

@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e)

throws Exception {log.warn("例外が発生しました", e.getCause());log.debug("コネクションを切断します");e.getChannel().close();

} }

Page 32: Netty & Apache Camel

Camel Netty

Page 33: Netty & Apache Camel

Camelでは、Netty、Netty4およびNetty HTTPの3種類コンポーネントをサポート

o Camel Netty:Netty 3.Xベース

o Camel Nett4:Netty 4.Xベース。Camel 2.14でリリース

o Camel Netty Http: ここでは対象外

コンポーネントのURL形式

o netty:tcp://host:port[?options]

o netty:udp://host:port[?options]

Page 34: Netty & Apache Camel

Camel Nettyコンポーネントが、メッセージを受信し、Exchangeを生成、ルート実行o messageReceivedイベントのみ実装するため、他のイベント発生時の処理は実装不可

イベント処理以外のHandlerは、オプションで設定

NetworkCamelNetty

Component

Component

Component

オプションで設定 ユーザ実装

Page 35: Netty & Apache Camel

request-replyタイプ、one-wayタイプをサポート

o request-reply

• Out Bodyに設定されたオブジェクトをレスポンスとして返す

o one-way

• レスポンスは返さない

syncオプションで設定

o デフォルトはRequest-Reply

Page 36: Netty & Apache Camel

次のオプションのいずれかでHandlerを指定

o encode/decoder

o encoders/decoders

o serverPipelineFactory/clientPipelineFactory

encoder/decoder、encoders/decodersを使用する場合、sslは別オプションで指定

encoders/decodersを推奨o encoder/decoderは、1つしか指定できない

o serverPipelineFactory/clientPipelineFactoryは、オプションの一部が使えなくなる可能性 ⇒ 詳細は「おまけ」参照

Page 37: Netty & Apache Camel

Handlerをbeanタグで定義

o ChannelHandlerFactoriesのHandler生成メソッドで定義

• newStringDecoder()/newStringEncoder()

• newObjectDecoder()/newObjectEncoder()

• newDelimiterBasedFrameDecoder()

• newLengthFieldBasedFrameDecoder

o Handlerがスレッドセーフかどうか意識する必要がなくなる

<bean id="length-decoder" class="org.apache.camel.component.netty.ChannelHandlerFactories" factory-method="newLengthFieldBasedFrameDecoder">

(snip)</bean>

すべてのHandlerが

用意されているわけではない

Page 38: Netty & Apache Camel

Handlerを独自実装した場合は、ChannelHandleFactoryを返すクラスを実装

public final class MyHandlerFactories {

private MyHandlerFactories() {}

public static ChannelHandlerFactory newUserInfoEncoder() {return new ShareableChannelHandlerFactory(new UserInfoEncoder());

}

public static ChannelHandlerFactory newUserInfoEncoder() {return new ChannelHandlerFactory() {

@Overridepublic ChannelHandler newChannelHandler() {

return new UserInfoEncoder();}

};}

}

スレッドセーフの場合

スレッドセーフでない場合

Page 39: Netty & Apache Camel

Handlerをカンマ区切りで複数設定

<camelContext xmlns="http://camel.apache.org/schema/spring"><route>

<from uri="netty:tcp://localhost:5150?decoders=#length-decoder,#string-decoder&amp;sync=false"/>

<to uri="mock:multiple-codec"/></route>

</camelContext><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="org.apache.camel.component.netty.ChannelHandlerFactories" factory-method="newStringDecoder"><constructor-arg value="UTF-8" />

</bean>

順番が重要!

Page 40: Netty & Apache Camel

Handlerをutil:listで設定

<camelContext xmlns="http://camel.apache.org/schema/spring"><route>

<from uri="netty:tcp://localhost:5150?decoders=#decoders&amp;sync=false"/><to uri="mock:multiple-codec"/>

</route></camelContext>

<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="org.jboss.netty.handler.codec.string.StringDecoder"/>

</util:list>

Page 41: Netty & Apache Camel

ネットワークに近いHandlerから順番に記載

decoders=#frame-decoder,#userinfo-decoder

Network

encoders=#frame-encoder,#userinfo-encoder

","の前後にスペースは不要

Page 42: Netty & Apache Camel

Camelのルートでは、Exchangeから受信したオブジェクトを取得し、業務処理を行う。

レスポンスを返す場合は、オブジェクトをBODYに設定する。

public class UpdateUserInfoProcessor implements Processor {

@Overridepublic void process(Exchange exchange) throws Exception {

// メッセージをオブジェクトに変換したものを取得UserInfo info = (UserInfo) exchange.getIn().getBody(UserInfo.class);

// 業務処理UserInfo modified = updateUserInfo(info);

// 送信するオブジェクトをBODYに設定exchange.getOut().setBody(modified);

} (snip) }

Page 43: Netty & Apache Camel

オプション

Page 44: Netty & Apache Camel

sync (default: TRUE)

o one-way(false)、request-replay(true)

disconnect (default: FALSE)

o 送受信後、Channelを切断する場合はTRUE

transferExchange (default: FALSE) TCPのみo ExchangeのBODY、ヘッダ、プロパティなどをシリアライズして送受信

noReplyLogLevel (default: WARN)

o Producerで送信するメッセージがない場合や、sync=TRUEでレスポンスを返さない場合に出力するログレベル

orderedThreadPoolExecutor (default: TRUE)

o 同一Channelでの送受信をシーケンシャルに行う

Page 45: Netty & Apache Camel

textline (default: FALSE) TCPのみo ExchangeのBODYにあるオブジェクトを文字列に変換する

delimiter (default: LINE) TCPのみo textlineがTRUEの場合のみ有効。デリミタ(LINE、NULL)

decoderMaxLineLength (default: 1000) TCPのみo textlineがTRUEの場合のみ有効。1行の最大バイト数

autoAppendDelimiter (default: TRUE) TCPのみo textlineがTRUEの場合のみ有効。デリミタを自動でつけるかどうか。

encoding (default: null)

o Exchangeのエンコーディング。textlineがTRUEの場合は、文字列

生成時のエンコーディングとして使用される。指定されていない場合は、UTF-8。

Page 46: Netty & Apache Camel

allowDefaultCodec (default: TRUE)

o encoder(s)/decoder(s)が指定されていない場合、デフォルトのencoder/decoderを使用

o textlineがTRUEの場合

• stringDecoder/Encoder、DelimiterBasedFrameDecoder

o textlineがFALSEの場合

• ObjectDecoder/Encoder

Page 47: Netty & Apache Camel

reuseAddress (default: TRUE)o TCPの場合、ポートがTIME_WAITでも再利用可能とする

o UDPかつマルチキャストの場合に有効にする

keepAlive (default: TRUE) TCPのみo 確立したコネクションを保持

tcpNoDelay (default: TRUE) TCPのみo 連続する小さいパケットを即時に送信(TRUE)

backlog (default: OS依存) TCPのみo 接続待ちのコネクションの最大保持数

broadcast (default:FALSE)UDPのみo マルチキャストを許可

synchronous (default: FALSE)o Camelのルートを同期起動

Page 48: Netty & Apache Camel

connectTimeout (default: 10,000)

lazyChannelCreation (default: TRUE)o Producerが起動時に、接続先が立ち上がっていない場合に例外が発生する事象を避けるために、Channelを遅延起動する

producerPoolEnabled (default: TRUE)o producerのプールを有効にするかどうか。

producerPoolMaxActive (default: -1)o プールで保持するproducerのインスタンスの上限。-1は無制限。

producerPoolMin/MaxIdle (default: 0)o プールで保持するアイドル状態のproducerの最小/最大インスタンス数

producerMinEvictableIdle (default: 30,000)o プールでアイドル状態で存在可能な時間(ms)

Page 49: Netty & Apache Camel

おまけ

Page 50: Netty & Apache Camel

Spring XMLではなく、Nettyと同様にJavaコードでChannelPipelineを組み立てる

Camelが提供する抽象クラスを継承o ServerPipelineFactory

o ClientPipelineFactory

上記クラスを使用しない場合は、CamelはデフォルトのDefaultServerpipelineFactory/DefaultClientPipelineFactoryを使用

継承すると、sslなどの一部プ

ロパティが使用できなくなるので注意が必要

Page 51: Netty & Apache Camel

public class MyServerPipelineFactory extends ServerPipelineFactory {

private NettyConsumer consumer;

public MyServlerPipelineFactory() {//

}

public MyServlerPipelineFactory(NettyConsumer consumer) {this.consumer = consumer;

}

@Overridepublic ChannelPipeline getPipeline() throws Exception {

(snip)}

@Overridepublic ServerPipelineFactory createPipelineFactory(NettyConsumer consumer) {

return new MyServlerPipelineFactory(consumer);}

}

デフォルトコンストラクタ

ChannelPipelineの生成

インスタンスの生成

Page 52: Netty & Apache Camel

// スレッドセーフなHandlerはインスタンス変数として使いまわすprivate StringEncoder stringEncoder = new StringEncoder(CharsetUtil.UTF-8);private StringDecoder stringDecoder = new StringDecoder(CharsetUtil.UTF-8);

public ChannelPipeline getPipeline() throws Exception {ChannelPipeline channelPipeline = Channels.pipeline();// 送信channelPipeline.addLast("encoder-SD", stringEncoder);channelPipeline.addLast("decoder-DELIM",

new DelimiterBasedFrameDecoder(maxLineSize, true, Delimiters.lineDelimiter()));

// 受信channelPipeline.addLast("decoder-SD", stringDecoder);

// このHandlerでCamelのルートを実行channelPipeline.addLast("handler", new ServerChannelHandler(consumer));

return channelPipeline;}

これを追加しないとルートは実行されない

Page 53: Netty & Apache Camel

bean定義し、オプションに設定

<camelContext xmlns="http://camel.apache.org/schema/spring"><route>

<from uri="netty:tcp://localhost:5150?serverPipelineFactory=#myPipeline"/><to uri="mock:multiple-codec"/>

</route></camelContext>

<bean id=“myPipeline" class="com.buildria.netty.MyServerPipelineFactory" />