Networking Netty BufferSizePredictor截断UDP数据报
我正在尝试开发自定义Flume源,它可以接收自定义UDP数据包。 这是我的密码:Networking Netty BufferSizePredictor截断UDP数据报,networking,udp,netty,Networking,Udp,Netty,我正在尝试开发自定义Flume源,它可以接收自定义UDP数据包。 这是我的密码: public class XvlrUdpSource extends AbstractSource implements EventDrivenSource, Configurable { private static final Logger LOG = LoggerFactory.getLogger(XvlrUdpSource.class); private int por
public class XvlrUdpSource extends AbstractSource
implements EventDrivenSource, Configurable {
private static final Logger LOG = LoggerFactory.getLogger(XvlrUdpSource.class);
private int port;
private String host;
private Channel nettyChannel;
private static final Logger logger = LoggerFactory.getLogger(XvlrUdpSource.class);
private CounterGroup counterGroup = new CounterGroup();
public class XvlrUpdHander extends SimpleChannelHandler {
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent mEvent) {
try {
System.out.println("class: "+ mEvent.getMessage().getClass());
/** ChannelBuffer holds just first 768 bytes of the whole input UDP packet*/
ChannelBuffer channelBuffer = (ChannelBuffer)mEvent.getMessage();
Event xvlrPacketEvent = EventBuilder.withBody( ((ChannelBuffer)mEvent.getMessage()).array());
System.out.println("Length is:["+xvlrPacketEvent.getBody().length+"]");
//Event e = syslogUtils.extractEvent((ChannelBuffer)mEvent.getMessage());
if(xvlrPacketEvent == null){
return;
}
getChannelProcessor().processEvent(xvlrPacketEvent);
counterGroup.incrementAndGet("events.success");
} catch (ChannelException ex) {
counterGroup.incrementAndGet("events.dropped");
logger.error("Error writting to channel", ex);
return;
}
}
}
@Override
public void start() {
ConnectionlessBootstrap serverBootstrap = new ConnectionlessBootstrap
(new OioDatagramChannelFactory(Executors.newCachedThreadPool()));
final XvlrUpdHander handler = new XvlrUpdHander();
serverBootstrap.setPipelineFactory(new ChannelPipelineFactory() {
@Override
public ChannelPipeline getPipeline() {
return Channels.pipeline(handler);
}
});
if (host == null) {
nettyChannel = serverBootstrap.bind(new InetSocketAddress(port));
} else {
nettyChannel = serverBootstrap.bind(new InetSocketAddress(host, port));
}
super.start();
}
@Override
public void stop() {
logger.info("Syslog UDP Source stopping...");
logger.info("Metrics:{}", counterGroup);
if (nettyChannel != null) {
nettyChannel.close();
try {
nettyChannel.getCloseFuture().await(60, TimeUnit.SECONDS);
} catch (InterruptedException e) {
logger.warn("netty server stop interrupted", e);
} finally {
nettyChannel = null;
}
}
super.stop();
}
@Override
public void configure(Context context) {
Configurables.ensureRequiredNonNull(
context, "port");//SyslogSourceConfigurationConstants.CONFIG_PORT);
port = context.getInteger("port");//SyslogSourceConfigurationConstants.CONFIG_PORT);
host = context.getString("host");//SyslogSourceConfigurationConstants.CONFIG_HOST);
//formaterProp = context.getSubProperties("PROP");//SyslogSourceConfigurationConstants.CONFIG_FORMAT_PREFIX);
}
}
我在MessageReceived上进行了调试,并在stacktrace中看到:
/**
* Sends a {@code "messageReceived"} event to the first
* {@link ChannelUpstreamHandler} in the {@link ChannelPipeline} of
* the specified {@link Channel} belongs.
*
* @param message the received message
* @param remoteAddress the remote address where the received message
* came from
*/
public static void fireMessageReceived(Channel channel, Object message, SocketAddress remoteAddress) {
channel.getPipeline().sendUpstream(
new UpstreamMessageEvent(channel, message, remoteAddress));
}
我的对象消息的长度已经是768字节
根目录在这里org.jboss.netty.channel.socket.oio.OioDatagramWorker:
byte[] buf = new byte[predictor.nextReceiveBufferSize()];
DatagramPacket packet = new DatagramPacket(buf, buf.length);
预测器将缓冲区大小设置为768
然后:
我只得到前768个字节。
是否有机会改变预测者的行为 要么发送768字节,要么接收缓冲区只有768字节长。它当然与回车无关,除非代码中对回车的处理有问题。要么发送768字节,要么接收缓冲区只有768字节长。这当然与回车无关,除非您的代码中有一些错误处理。我发现了以下主题: 可以使用特殊属性“注入”具有所需行为的预测器。 因此,完整的解决方案是:
public class XvlrUdpSource extends AbstractSource
implements EventDrivenSource, Configurable {
private static final Logger LOG = LoggerFactory.getLogger(XvlrUdpSource.class);
private int port;
private String host;
private Channel nettyChannel;
private CounterGroup counterGroup = new CounterGroup();
public class XvlrUpdHander extends SimpleChannelHandler {
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent mEvent) {
try {
ChannelBuffer channelBuffer = (ChannelBuffer)mEvent.getMessage();
int actualSizeOfUdpPacket = channelBuffer.readableBytes();
byte[] body = Arrays.copyOf(channelBuffer.array(), actualSizeOfUdpPacket);
Event xvlrPacketEvent = EventBuilder.withBody(body);
LOG.debug("Event.body length is: {} ", xvlrPacketEvent.getBody().length);
if(xvlrPacketEvent == null){
return;
}
getChannelProcessor().processEvent(xvlrPacketEvent);
counterGroup.incrementAndGet("events.success");
} catch (ChannelException ex) {
counterGroup.incrementAndGet("events.dropped");
LOG.error("Error writting to channel", ex);
return;
}
}
}
@Override
public void start() {
OioDatagramChannelFactory oioDatagramChannelFactory = new OioDatagramChannelFactory( Executors.newCachedThreadPool());
ConnectionlessBootstrap serverBootstrap = new ConnectionlessBootstrap(oioDatagramChannelFactory);
serverBootstrap.setOption("sendBufferSize", 65536);
serverBootstrap.setOption("receiveBufferSize", 65536);
serverBootstrap.setOption("receiveBufferSizePredictorFactory",
new AdaptiveReceiveBufferSizePredictorFactory(8192, 8192, 16384));
final XvlrUpdHander handler = new XvlrUpdHander();
serverBootstrap.setPipelineFactory(new ChannelPipelineFactory() {
@Override
public ChannelPipeline getPipeline() {
return Channels.pipeline(handler);
}
});
if (host == null) {
nettyChannel = serverBootstrap.bind(new InetSocketAddress(port));
} else {
nettyChannel = serverBootstrap.bind(new InetSocketAddress(host, port));
}
}
@Override
public void stop() {
LOG.info("Syslog UDP Source stopping...");
LOG.info("Metrics:{}", counterGroup);
if (nettyChannel != null) {
nettyChannel.close();
try {
nettyChannel.getCloseFuture().await(60, TimeUnit.SECONDS);
} catch (InterruptedException e) {
LOG.warn("netty server stop interrupted", e);
} finally {
nettyChannel = null;
}
}
super.stop();
}
@Override
public void configure(Context context) {
Configurables.ensureRequiredNonNull(context, "port");
port = context.getInteger("port");
host = context.getString("host");
}
}
我发现了这个话题:
可以使用特殊属性“注入”具有所需行为的预测器。
因此,完整的解决方案是:
public class XvlrUdpSource extends AbstractSource
implements EventDrivenSource, Configurable {
private static final Logger LOG = LoggerFactory.getLogger(XvlrUdpSource.class);
private int port;
private String host;
private Channel nettyChannel;
private CounterGroup counterGroup = new CounterGroup();
public class XvlrUpdHander extends SimpleChannelHandler {
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent mEvent) {
try {
ChannelBuffer channelBuffer = (ChannelBuffer)mEvent.getMessage();
int actualSizeOfUdpPacket = channelBuffer.readableBytes();
byte[] body = Arrays.copyOf(channelBuffer.array(), actualSizeOfUdpPacket);
Event xvlrPacketEvent = EventBuilder.withBody(body);
LOG.debug("Event.body length is: {} ", xvlrPacketEvent.getBody().length);
if(xvlrPacketEvent == null){
return;
}
getChannelProcessor().processEvent(xvlrPacketEvent);
counterGroup.incrementAndGet("events.success");
} catch (ChannelException ex) {
counterGroup.incrementAndGet("events.dropped");
LOG.error("Error writting to channel", ex);
return;
}
}
}
@Override
public void start() {
OioDatagramChannelFactory oioDatagramChannelFactory = new OioDatagramChannelFactory( Executors.newCachedThreadPool());
ConnectionlessBootstrap serverBootstrap = new ConnectionlessBootstrap(oioDatagramChannelFactory);
serverBootstrap.setOption("sendBufferSize", 65536);
serverBootstrap.setOption("receiveBufferSize", 65536);
serverBootstrap.setOption("receiveBufferSizePredictorFactory",
new AdaptiveReceiveBufferSizePredictorFactory(8192, 8192, 16384));
final XvlrUpdHander handler = new XvlrUpdHander();
serverBootstrap.setPipelineFactory(new ChannelPipelineFactory() {
@Override
public ChannelPipeline getPipeline() {
return Channels.pipeline(handler);
}
});
if (host == null) {
nettyChannel = serverBootstrap.bind(new InetSocketAddress(port));
} else {
nettyChannel = serverBootstrap.bind(new InetSocketAddress(host, port));
}
}
@Override
public void stop() {
LOG.info("Syslog UDP Source stopping...");
LOG.info("Metrics:{}", counterGroup);
if (nettyChannel != null) {
nettyChannel.close();
try {
nettyChannel.getCloseFuture().await(60, TimeUnit.SECONDS);
} catch (InterruptedException e) {
LOG.warn("netty server stop interrupted", e);
} finally {
nettyChannel = null;
}
}
super.stop();
}
@Override
public void configure(Context context) {
Configurables.ensureRequiredNonNull(context, "port");
port = context.getInteger("port");
host = context.getString("host");
}
}
好的,我将尝试在发送方添加调试。我没有100%的证据证明它将整个数据包准确地发送到这个特定的Flume源中。我确实在基于ApacheMina的客户端中添加了调试。当将相同的数据传输到手工制作的UDP服务器时,它可以正常工作。我的目标是用Flume UDP源组件替换它。好的,我将尝试在发送方添加调试。我没有100%的证据证明它将整个数据包准确地发送到这个特定的Flume源中。我确实在基于ApacheMina的客户端中添加了调试。当将相同的数据传输到手工制作的UDP服务器时,它可以正常工作。我的目标是用Flume UDP源组件替换它。