美文网首页
关于Netty的一些理解、实践与陷阱

关于Netty的一些理解、实践与陷阱

作者: MMoooooon | 来源:发表于2017-11-26 16:21 被阅读0次

核心概念的理解

Netty对于网络层进行了自己的抽象,用Channel表示连接,读写就是Channel上发生的事件,ChannelHandler用来处理这些事件,ChannelPipeline基于unix哲学提供了一种优雅的组织ChannelHandler的方式,用管道解耦不同层面的处理。现在回过头来看看,真的是非常天才和优雅的设计,是我心中API设计的典范之一了。

TCP半包、粘包

使用Netty内置的LineBasedFrameDecoder或者LengthFieldBasedFrameDecoder,我们只要在pipeline中添加,就解决了这个问题。

Writtable问题

有时候,由于TCP的send buffer满了,向channel的写入会失败。我们需要检查channel().isWritable()标记来确定是否执行写入。

处理耗时任务

Netty In Action以及网上的一些资料中,都没有很直接的展示如何在Netty中去处理耗时任务。其实也很简单,只要给handler指定一个事件循环就可以,例如

public class MyChannelInitializer extends ChannelInitializer<Channel> {
    private static EventExecutorGroup longTaskGroup = new DefaultEventExecutorGroup(5);

    protected void initChannel(Channel channel) throws Exception {
        ChannelPipeline pipeline = channel.pipeline();
        ...
        pipeline.addLast(longTaskGroup, new PrintHandler());

    }
}

Pitfall

Netty的ChannelPipeline只有一条双向链,消息入站,经过一串InBoundHandler之后,以相反的顺序再经过OutBoundHandler出站.因此,我们自定义的handler一般会处于pipeline的末尾!

举个例子,当以如下顺序添加handler时,如果调用ChannelHandlerContext上的writeAndFlush方法,出站消息是无法经过StringEncoder的

public class MyChannelInitializer extends ChannelInitializer<Channel> {
    private static EventExecutorGroup longTaskGroup = new DefaultEventExecutorGroup(5);

    protected void initChannel(Channel channel) throws Exception {
        ChannelPipeline pipeline = channel.pipeline();
        pipeline.addLast(new LineBasedFrameDecoder(64 * 1024));
        pipeline.addLast(new StringDecoder(CharsetUtil.UTF_8));
        pipeline.addLast(longTaskGroup, new PrintHandler());
        pipeline.addLast(new StringEncoder(CharsetUtil.UTF_8));
    }
}

这个问题有两个解决方式

  1. 调整handler的顺序
  2. 调用channel上的writeAndFlush方法,强制使消息在整个pipeline上流动

调整handler的顺序

public class MyChannelInitializer extends ChannelInitializer<Channel> {
    private static EventExecutorGroup longTaskGroup = new DefaultEventExecutorGroup(5);

    protected void initChannel(Channel channel) throws Exception {
        ChannelPipeline pipeline = channel.pipeline();
        pipeline.addLast(new LineBasedFrameDecoder(64 * 1024));
        pipeline.addLast(new StringDecoder(CharsetUtil.UTF_8));
        pipeline.addLast(new StringEncoder(CharsetUtil.UTF_8));
        pipeline.addLast(longTaskGroup, new PrintHandler());
    }
}

调用Channel上的writeAndFlush方法

public class PrintHandler extends SimpleChannelInboundHandler<String> {
    protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
//        ctx.writeAndFlush(msg);
        ctx.channel().writeAndFlush(msg);
        System.out.println(msg);
    }
}

参考

http://www.voidcn.com/article/p-yhpuvvkx-mm.html
https://stackoverflow.com/questions/37474482/dealing-with-long-time-task-such-as-sql-query-in-netty
《Netty In Action》

相关文章

  • 关于Netty的一些理解、实践与陷阱

    核心概念的理解 Netty对于网络层进行了自己的抽象,用Channel表示连接,读写就是Channel上发生的事件...

  • Netty源码笔记(一)Netty服务端处理流程

    最近开始了解Netty源码。此系列文章在于对Netty设计思想的个人理解做一些整理,以及关于网络通信延伸的一些思考...

  • 关于Netty的初步理解

    本文转载,用于学习,如有问题,欢迎交流指正 有了Netty,你可以实现自己的HTTP服务器,FTP服务器,UDP服...

  • Netty粘包与拆包以及解决方式

    本文内容都是学习Netty权威指南一书所写, 主要是为了加深对Netty内容的理解。 Netty 粘包与拆包 TC...

  • Netty 编码解码

    参考来源 Netty实践 Netty 4.x学习笔记 - Channel和Pipeline Netty 编码器和解...

  • Netty 源码之 FastThreadLocal

    近期由于浏览Netty 的源码,想把Netty中一些编程技巧与优化的东西记录下来!来了解Netty中一些编程思想!...

  • Netty入门实践

    Netty基础概念 欢迎访问微信原文:Netty入门实践 Bootstrap 和 ServerBootstrap:...

  • Netty的高性能设计

    基于不断的对Netty框架和系统底层知识的理解过程,总结Netty采用的高性能技术与设计,构建自己的认知体系。不断...

  • Futuer研究

    Future是什么? 最近写了一些关于netty的相关代码,发现类似netty 的这种异步框架大量的使用一个Fut...

  • 第一章

    c陷阱与缺陷的读后总结第一章 关于词法“陷阱”(主要讲符号和组成符号的字符间的关系以及一些常见错误)新定义符...

网友评论

      本文标题:关于Netty的一些理解、实践与陷阱

      本文链接:https://www.haomeiwen.com/subject/iubkbxtx.html