Apache camel Camel和Netty:客户端-中间应用程序-服务器

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

我正在使用Camel和Netty设置一个场景,其中客户端连接到服务器,中间有一个应用程序(只是一个名为Router的虚拟应用程序)

SocketClient连接到路由器(端口53379),路由器连接到服务器(端口53383)。问题是数据包从未到达服务器(但它确实到达路由器,我用处理器调试了它)

如果我将SocketClient连接到服务器,它就可以正常工作

感谢您的帮助

完全来源 路由器:

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文档,因为他们在配置端点时提到了一些重要的选项。