Netty成长之路——初始Netty

Jayne ·
更新时间:2024-11-14
· 855 次阅读

前言
      初始Netty框架是在一家电商公司,开发微信应用小程序,解决客服聊天系统消息使用方案时用到的。在此之前,也仅仅是了解过它,写过一些demo而已,从未深入学习过。这次因为研发的产品需要,有幸再次学习它,索性我就搞个透。言规正传,我们这就开始。

1、Netty简介

Netty 是一个基于NIO的客户端、服务端的编程框架,使用Netty可以确保你快速和简单的开发出一个网络应用,Netty相当于简化和流线化了网络应用的编程开发过程,Netty提供异步的、事件驱动的网络应用程序框架和工具,用以快速开发高性能、高可靠性的网络服务器和客户端程序。它的体系结构图如下:

2、Netty特性

设计

各种传输类型的统一API——阻塞和非阻塞套接字 基于灵活和可扩展的事件模型,允许明确的关注点分离 高度可定制的线程模型——单个线程,一个或多个线程池,如SEDA 真正的无连接数据报套接字支持(从3.1开始)

易用性

文档良好的Javadoc、用户指南和示例 没有额外的依赖,JDK 5 (Netty 3.x)或6 (Netty 4.x)就足够了

性能

更好的吞吐量,更低的延迟 减少资源消耗 最小化不必要的内存拷贝

安全

支持SSL/TLS和StartTLS 3、Netty示例代码

 下面主要使用示例,演示Netty客户端和服务端使用效果。

  Netty服务端

public class NettyServer { /** * boss 线程组用于处理连接工作 */ private EventLoopGroup bossGroup = new NioEventLoopGroup(); /** * work 线程组用于数据处理 */ private EventLoopGroup workerGroup = new NioEventLoopGroup(); @Value("${nettyServer.port}") private int port; /*public NettyServer(int port) { this.port = port; }*/ @PostConstruct public void run() throws Exception { ServerBootstrap b = new ServerBootstrap(); // (2) b.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) // (3) .childHandler(new NettyServerInitializer()) //(4) .option(ChannelOption.SO_BACKLOG, 128) // (5) .childOption(ChannelOption.SO_KEEPALIVE, true); // (6) // 绑定端口,开始接收进来的连接 ChannelFuture f = b.bind(port).sync(); if (f.isSuccess()) { log.info("启动 Netty Server"); } //f.channel().closeFuture().sync(); } @PreDestroy public void destory() throws InterruptedException { bossGroup.shutdownGracefully().sync(); workerGroup.shutdownGracefully().sync(); log.info("关闭Netty"); }

NettyServerHandler.java

public class NettyServerHandler extends SimpleChannelInboundHandler { /** * A thread-safe Set Using ChannelGroup, you can categorize Channels into a meaningful group. * A closed Channel is automatically removed from the collection, */ public static ChannelGroup channels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE); @Override public void handlerAdded(ChannelHandlerContext ctx) throws Exception { Channel incoming = ctx.channel(); // Broadcast a message to multiple Channels channels.writeAndFlush("[SERVER] - " + incoming.remoteAddress() + " 加入\n"); channels.add(ctx.channel()); } @Override public void handlerRemoved(ChannelHandlerContext ctx) throws Exception { Channel incoming = ctx.channel(); // Broadcast a message to multiple Channels channels.writeAndFlush("[SERVER] - " + incoming.remoteAddress() + " 离开\n"); // A closed Channel is automatically removed from ChannelGroup, // so there is no need to do "channels.remove(ctx.channel());" } @Override protected void channelRead0(ChannelHandlerContext ctx, String s) throws Exception { log.info("接收到客户端消息:{}", s); try{ if (!StringUtils.isEmpty(s)) { PushNettyData jsonMsg = GsonUtils.fromJson(s, PushNettyData.class); if ("new-sample".equals(jsonMsg.getMsgType())) { log.info("样本编号:{}",jsonMsg.getSampleNo()); //保存ctx对象 NettyDataComponent nettyDataComponent = new NettyDataComponent(); nettyDataComponent.addNettyDataMap(jsonMsg.getSampleNo(), ctx); } } }finally { ReferenceCountUtil.release(s); } /* Channel incoming = ctx.channel(); for (Channel channel : channels) { if (channel != incoming) { channel.writeAndFlush("[" + incoming.remoteAddress() + "]" + s + "\n"); } else { BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); while (true) { channel.writeAndFlush("[server]" + in.readLine() + "\r\n"); } } }*/ } @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { Channel incoming = ctx.channel(); log.info("NettyClient:" + incoming.remoteAddress() + "在线"); } @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { Channel incoming = ctx.channel(); log.info("NettyClient:" + incoming.remoteAddress() + "掉线"); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { Channel incoming = ctx.channel(); log.info("NettyClient:" + incoming.remoteAddress() + "异常"); // 当出现异常就关闭连接 cause.printStackTrace(); ctx.close(); } } NettyServerInitializer.java public class NettyServerInitializer extends ChannelInitializer { @Override public void initChannel(SocketChannel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline(); pipeline.addLast("framer", new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter())); pipeline.addLast("decoder", new StringDecoder()); pipeline.addLast("encoder", new StringEncoder()); pipeline.addLast("handler", new NettyServerHandler()); log.info("NettyClient:" + ch.remoteAddress() + "连接上"); } }

Netty客户端

public class NettyClient { public static void main(String[] args) throws Exception { //new NettyClient("localhost", 8087).run(); String stitchUrl = "http://127.0.0.1:8088/img/stitch/thumb-AB0003-000011.png"; stitchUrl = stitchUrl.replace("//", "/"); System.out.println(stitchUrl); } private final String host; private final int port; public NettyClient(String host, int port) { this.host = host; this.port = port; } public void run() throws Exception { EventLoopGroup group = new NioEventLoopGroup(); try { Bootstrap bootstrap = new Bootstrap() .group(group) .channel(NioSocketChannel.class) .handler(new NettyClientInitializer()); Channel channel = bootstrap.connect(host, port).sync().channel(); BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); while (true) { channel.writeAndFlush("[client]" + in.readLine() + "\r\n"); } } catch (Exception e) { e.printStackTrace(); } finally { group.shutdownGracefully(); } } } NettyClientHandler.java public class NettyClientHandler extends SimpleChannelInboundHandler { @Override protected void channelRead0(ChannelHandlerContext ctx, String s) throws Exception { System.out.println("客户端消息:"+s); } } NettyClientInitializer.java public class NettyClientInitializer extends ChannelInitializer { @Override public void initChannel(SocketChannel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline(); pipeline.addLast("framer", new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter())); pipeline.addLast("decoder", new StringDecoder()); pipeline.addLast("encoder", new StringEncoder()); pipeline.addLast("handler", new NettyClientHandler()); } }

后续文章将对Netty框架各个模块进行详细分析等。敬请期待!

快马扬鞭 原创文章 1获赞 2访问量 35 关注 私信 展开阅读全文
作者:快马扬鞭



netty

需要 登录 后方可回复, 如果你还没有账号请 注册新账号