欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

netty入门小程序

程序员文章站 2024-01-24 18:09:16
...

Netty的特性

  1. 设计统一的API,适用于不同的协议(阻塞和非阻塞)基于灵活、可扩展的事件驱动模型高度可定制的线程模型可靠的无连接数据Socket支持(UDP)
  2. 性能更好的吞吐量,低延迟更省资源尽量减少不必要的内存拷贝
  3. 安全完整的SSL/TLS和STARTTLS的支持能在Applet与Android的限制环境运行良好
  4. 健壮性不再因过快、过慢或超负载连接导致OutOfMemoryError不再有在高速网络环境下NIO读写频率不一致的问题
  5. 易用完善的JavaDoc,用户指南和样例简洁简单仅信赖于JDK1.5

Netty 在哪些行业得到了应用?

互联网行业

随着网站规模的不断扩大,系统并发访问量也越来越高,传统基于 Tomcat 等 Web 容器的垂直架构已经无法满足需求,需要拆分应用进行服务化,以提高开发和维护效率。从组网情况看,垂直的架构拆分之后,系统采用分布式部署,各个节点之间需要远程服务调用,高性能的 RPC 框架必不可少,Netty 作为异步高性能的通信框架,往往作为基础通信组件被这些 RPC 框架使用。  

典型的应用有

阿里分布式服务框架 Dubbo 的 RPC 框架使用 Dubbo 协议进行节点间通信,Dubbo 协议默认使用 Netty 作为基础通信组件,用于实现各进程节点之间的内部通信。它的架构图如下:

netty入门小程序

其中,服务提供者和服务消费者之间,服务提供者、服务消费者和性能统计节点之间使用 Netty 进行异步/同步通信。 

除了 Dubbo 之外,淘宝的消息中间件 RocketMQ 的消息生产者和消息消费者之间,也采用 Netty 进行高性能、异步通信。  

除了阿里系和淘宝系之外,很多其它的大型互联网公司或者电商内部也已经大量使用 Netty 构建高性能、分布式的网络服务器。

游戏行业

无论是手游服务端、还是大型的网络游戏,Java 语言得到了越来越广泛的应用。Netty 作为高性能的基础通信组件,它本身提供了 TCP/UDP 和 HTTP 协议栈,非常方便定制和开发私有协议栈。账号登陆服务器、地图服务器之间可以方便的通过 Netty 进行高性能的通信,架构示意图如下:

netty入门小程序

大数据领域

经典的 Hadoop 的高性能通信和序列化组件 Avro 的 RPC 框架,默认采用 Netty 进行跨节点通信,它的 Netty Service 基于 Netty 框架二次封装实现。  
大数据计算往往采用多个计算节点和一个/N个汇总节点进行分布式部署,各节点之间存在海量的数据交换。由于 Netty 的综合性能是目前各个成熟 NIO 框架中最高的,因此,往往会被选中用作大数据各节点间的通信。

企业软件

企业和 IT 集成需要 ESB,Netty 对多协议支持、私有协议定制的简洁性和高性能是 ESB RPC 框架的首选通信组件。事实上,很多企业总线厂商会选择 Netty 作为基础通信组件,用于企业的 IT 集成。

通信行业

Netty 的异步高性能、高可靠性和高成熟度的优点,使它在通信行业得到了大量的应用。

简单实现服务器端和客户端

NettyServer.java

package netty;

import org.jboss.netty.bootstrap.ServerBootstrap;    
import org.jboss.netty.channel.*;    
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;    
import org.jboss.netty.handler.codec.string.StringDecoder;    
import org.jboss.netty.handler.codec.string.StringEncoder;    

import java.net.InetSocketAddress;    
import java.util.concurrent.Executors;    

/**  
 * Author: yexx
 * 
 */    
public class NettyServer {    
    public static void main(String[] args) {    
        ServerBootstrap bootstrap = new ServerBootstrap(new NioServerSocketChannelFactory(Executors.newCachedThreadPool(), Executors.newCachedThreadPool()));    

        // Set up the default event pipeline.    
        bootstrap.setPipelineFactory(new ChannelPipelineFactory() {    
            @Override    
            public ChannelPipeline getPipeline() throws Exception {    
                return Channels.pipeline(new StringDecoder(), new StringEncoder(), new ServerHandler());    
            }    
        });    

        // Bind and start to accept incoming connections.    
        Channel bind = bootstrap.bind(new InetSocketAddress(8000));    
        System.out.println("Server已经启动,监听端口: " + bind.getLocalAddress() + ", 等待客户端注册。。。");    
    }    

    private static class ServerHandler extends SimpleChannelHandler {    
        @Override    
        public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {    
            if (e.getMessage() instanceof String) {    
                String message = (String) e.getMessage();    
                System.out.println("Client发来:" + message);    

                e.getChannel().write("Server已收到刚发送的:" + message);    

                System.out.println("\n等待客户端输入。。。");    
            }    

            super.messageReceived(ctx, e);    
        }    

        @Override    
        public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {    
            super.exceptionCaught(ctx, e);    
        }    

        @Override    
        public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {    
            System.out.println("有一个客户端注册上来了。。。");    
            System.out.println("Client:" + e.getChannel().getRemoteAddress());    
            System.out.println("Server:" + e.getChannel().getLocalAddress());    
            System.out.println("\n等待客户端输入。。。");    
            super.channelConnected(ctx, e);    
        }    
    }    
}   

NettyClient.java

package netty;

import org.jboss.netty.bootstrap.ClientBootstrap;    
import org.jboss.netty.channel.*;    
import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;    
import org.jboss.netty.handler.codec.string.StringDecoder;    
import org.jboss.netty.handler.codec.string.StringEncoder;    

import java.io.BufferedReader;    
import java.io.InputStreamReader;    
import java.net.InetSocketAddress;    
import java.util.concurrent.Executors;    

/**  
 * Author: yexx
 * 
 */    
public class NettyClient {    

    public static void main(String[] args) {    
        // Configure the client.    
        ClientBootstrap bootstrap = new ClientBootstrap(new NioClientSocketChannelFactory(Executors.newCachedThreadPool(), Executors.newCachedThreadPool()));    

        // Set up the default event pipeline.    
        bootstrap.setPipelineFactory(new ChannelPipelineFactory() {    
            @Override    
            public ChannelPipeline getPipeline() throws Exception {    
                return Channels.pipeline(new StringDecoder(), new StringEncoder(), new ClientHandler());    
            }    
        });    

        // Start the connection attempt.    
        ChannelFuture future = bootstrap.connect(new InetSocketAddress("localhost", 8000));    

        // Wait until the connection is closed or the connection attempt fails.    
        future.getChannel().getCloseFuture().awaitUninterruptibly();    

        // Shut down thread pools to exit.    
        bootstrap.releaseExternalResources();    
    }    

    private static class ClientHandler extends SimpleChannelHandler {    
        private BufferedReader sin = new BufferedReader(new InputStreamReader(System.in));    

        @Override    
        public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {    
            if (e.getMessage() instanceof String) {    
                String message = (String) e.getMessage();    
                System.out.println(message);    

                e.getChannel().write(sin.readLine());    

                System.out.println("\n等待客户端输入。。。");    
            }    

            super.messageReceived(ctx, e);    
        }    

        @Override    
        public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {    
            System.out.println("已经与Server建立连接。。。。");    
            System.out.println("\n请输入要发送的信息:");    
            super.channelConnected(ctx, e);    

            e.getChannel().write(sin.readLine());    
        }    
    }    
}   

运行可以自己试一试

需要jar包

netty jar包