Apache camel Camel和Netty:客户端-中间应用程序-服务器
我正在使用Camel和Netty设置一个场景,其中客户端连接到服务器,中间有一个应用程序(只是一个名为Router的虚拟应用程序) SocketClient连接到路由器(端口53379),路由器连接到服务器(端口53383)。问题是数据包从未到达服务器(但它确实到达路由器,我用处理器调试了它) 如果我将SocketClient连接到服务器,它就可以正常工作 感谢您的帮助 完全来源 路由器:Apache camel Camel和Netty:客户端-中间应用程序-服务器,apache-camel,netty,Apache Camel,Netty,我正在使用Camel和Netty设置一个场景,其中客户端连接到服务器,中间有一个应用程序(只是一个名为Router的虚拟应用程序) SocketClient连接到路由器(端口53379),路由器连接到服务器(端口53383)。问题是数据包从未到达服务器(但它确实到达路由器,我用处理器调试了它) 如果我将SocketClient连接到服务器,它就可以正常工作 感谢您的帮助 完全来源 路由器: public class Router { public static void main(Str
public class Router {
public static void main(String[] args) throws Exception {
SimpleRegistry registry = new SimpleRegistry();
registry.put("ByteArrayEncoder", new ByteArrayEncoder());
registry.put("ByteArrayDecoder", new ByteArrayDecoder());
CamelContext context = new DefaultCamelContext(registry);
context.addRoutes(new RouteBuilder() {
@Override
public void configure() throws Exception {
from("netty4:tcp://localhost:53379?encoders=#ByteArrayEncoder&"
+ "decoders=#ByteArrayDecoder"
+ "&sync=true"
+ "&keepAlive=true")
.to("netty4:tcp://localhost:53383?encoders=#ByteArrayEncoder&"
+ "decoders=#ByteArrayDecoder"
+ "&sync=true"
+ "&keepAlive=true");
}
});
context.start();
while(true) {
Thread.sleep(1000);
}
}
}
服务器:
public class Server {
public static void main(String[] args) throws Exception {
SimpleRegistry registry = new SimpleRegistry();
registry.put("ByteArrayEncoder", new ByteArrayEncoder());
registry.put("ByteArrayDecoder", new ByteArrayDecoder());
CamelContext context = new DefaultCamelContext(registry);
context.addRoutes(new RouteBuilder() {
@Override
public void configure() throws Exception {
from("netty4:tcp://localhost:53383?encoders=#ByteArrayEncoder&"
+ "decoders=#ByteArrayDecoder"
+ "&sync=true"
+ "&keepAlive=true")
.process(new Processor() {
public void process(Exchange exchange) throws Exception {
Message message = exchange.getIn();
System.out.println("from este_stub: " + message.getBody());
exchange.setOut(message);
}
});
}
});
context.start();
while(true) {
Thread.sleep(1000);
}
}
}
客户:
public class SocketClient {
public static void main(String[] args) throws UnknownHostException, IOException {
Socket socket = new Socket("localhost", 53379);
OutputStream simOutStream = socket.getOutputStream();
BufferedInputStream simInStream = new BufferedInputStream(socket.getInputStream());
byte[] arr = new byte[] {1, 2, 3, 4, 5};
simOutStream.write(arr, 0, arr.length);
simOutStream.flush();
byte[] resp = new byte[5];
simInStream.read(resp, 0, resp.length);
for(byte ar : resp)
System.out.print(ar);
socket.close();
}
}
运行您共享的代码会在路由器类中出现以下错误:
io.netty.channel.ChannelPipelineException:io.netty.handler.codec.bytes.ByteArrayDecoder不是@Sharable处理程序,因此无法多次添加或删除。
如例外情况所述,ByteArrayCoder以及ByteArrayEncoder都不是可共享的处理程序,因此是错误的原因。从Sharable的javadoc中可以清楚地看出
指示可以将带注释的ChannelHandler的同一实例多次添加到一个或多个ChannelPipeline中,而无竞争条件。如果未指定此注释,则每次将其添加到管道时都必须创建新的处理程序实例,因为它具有非共享状态,例如成员变量
netty4的camel文档也说明了这一点
详情如下:
如果编码器或解码器不可共享(例如它们具有@shareable类注释),则编码器/解码器必须实现org.apache.camel.component.netty.ChannelHandlerFactory接口,并在newChannelHandler方法中返回一个新实例。这是为了确保编码器/解码器可以安全使用。如果情况并非如此,则Netty组件将在以下情况下记录警告:
将创建一个端点。
Netty组件提供了一个org.apache.camel.component.Netty.channelHandlerFactorys工厂类,该类具有许多常用方法
因此,通过使用一些实现ChannelHandlerFactory并重写newChannelHandler的自定义编码器和解码器,您的问题得到了解决,如下所示:
公共类CustomByteArrayCoder实现ChannelHandlerFactory{
@Override
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
}
@Override
public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
}
@Override
public ChannelHandler newChannelHandler() {
return new ByteArrayDecoder();
}
编码器也是如此。然后对路由器和服务器进行适当更改,如下所示:
SimpleRegistry registry = new SimpleRegistry();
registry.put("ByteArrayEncoder", new CustomByteArrayEncoder());
registry.put("ByteArrayDecoder", new CustomByteArrayDecoder());
运行您共享的代码会在路由器类中出现以下错误:
io.netty.channel.ChannelPipelineException:io.netty.handler.codec.bytes.ByteArrayDecoder不是@Sharable处理程序,因此无法多次添加或删除。
如例外情况所述,ByteArrayCoder以及ByteArrayEncoder都不是可共享的处理程序,因此是错误的原因
指示可以多次将带注释的ChannelHandler的同一实例添加到一个或多个ChannelPipeline中,而无需竞争条件。如果未指定此注释,则每次将其添加到管道时都必须创建新的处理程序实例,因为它具有非共享状态(如成员变量)
netty4的camel文档也说明了这一点
详情如下:
如果您的编码器或解码器不可共享(例如,它们具有@shareable类注释),则编码器/解码器必须实现org.apache.camel.component.netty.ChannelHandlerFactory接口,并在newChannelHandler方法中返回一个新实例。这是为了确保编码器/解码器可以安全使用。如果不是这样,则netty组件将在
将创建一个端点。
Netty组件提供了一个org.apache.camel.component.Netty.channelHandlerFactorys工厂类,该类具有许多常用方法
因此,通过使用一些实现ChannelHandlerFactory并重写newChannelHandler的自定义编码器和解码器,您的问题得到了解决,如下所示:
公共类CustomByteArrayCoder实现ChannelHandlerFactory{
@Override
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
}
@Override
public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
}
@Override
public ChannelHandler newChannelHandler() {
return new ByteArrayDecoder();
}
编码器也是如此。然后对路由器和服务器进行适当更改,如下所示:
SimpleRegistry registry = new SimpleRegistry();
registry.put("ByteArrayEncoder", new CustomByteArrayEncoder());
registry.put("ByteArrayDecoder", new CustomByteArrayDecoder());
谢谢!您一提到exception,我就注意到我忘了设置log4j.properties文件。顺便说一句,实现ChannelFactory只需要newChannelHandler()方法。那太好了。还要检查Camel netty4文档,因为他们在配置端点时提到了一些重要的选项。谢谢!您一提到异常,我就注意到我忘了设置log4j.properties文件。顺便说一句,实现ChannelFactory只需要newChannelHandler()方法。那太好了。还要检查Camel netty4文档,因为他们在配置端点时提到了一些重要的选项。