http://cxytiandi.com/blog/detail/17345

Netty介绍

Netty是由JBOSS提供的一个java开源框架。Netty提供异步的、事件驱动的网络应用程序框架和工具,用以快速开发高性能、高可靠性的网络服务器和客户端程序。

也就是说,Netty 是一个基于NIO的客户、服务器端编程框架,使用Netty 可以确保你快速和简单的开发出一个网络应用,例如实现了某种协议的客户,服务端应用。Netty相当简化和流线化了网络应用的编程开发过程,例如,TCP和UDP的socket服务开发。

官网地址:http://netty.io/

使用场景

Netty之所以能成为主流的NIO框架,是因为它有下面的优点:

  • NIO的类库和API使用难度较高,Netty进行了封装,容易上手
  • 高性能,功能强大,支持多种编解码功能,支持多种主流协议
  • 成熟,稳定,已经在多个大型框架中使用(dubbo,RocketMQ,Hadoop,mycat,Spring5)
  • …..

在几年之前我上家公司用的是Mina来开发一个IM的系统,Mina也是一个很好的框架(http://mina.apache.org/)。
如今很多的框架都改成用Netty来做底层通讯了,我司现在还有一个代理框架用Mina写的,等把Netty玩遛了可以重构了。

不知道大家看完了上面的介绍是不是已经知道Netty能用在什么场景了,下面我结合一个我之前做过的事情来进行详细的说明,当然只是使用场景的一方面而已。

之前做抓取的时候,有一些小型的网站,页面结构比较复杂,还需要登录等操作,这种就不能用统一的抓取系统去抓取,只能通过写脚本的方式针对具体的网站做抓取,抓取必备的一个条件就是代理IP,为了方便抓取,特意封装了一个抓取的SDK,提供了抓取的方法,内置了切换代理。

我们有一个代理池服务,通过一个网址去获取能使用的代理IP,在刚开始用的Http请求去获取代理IP,由于抓取量比较大,通过Http请求去获取代理IP效率不行,后面用Netty改造了获取IP这部分,通过Netty来获取数据,解决了实时获取的性能问题。

通过长连接的方式,避免了Http请求每次都要建立连接带来的性能消耗问题,通过二进制的数据传输减少网络开销,性能更高。

简单入门

我们编写一个服务端和客户端,客户端往服务端发送一条消息,消息传输先用字符串进行传递,服务端收到客户端发送的消息,然后回复一条消息。

首先编写服务端代码:

  1. public class ImServer {
  2. public void run(int port) {
  3. EventLoopGroup bossGroup = new NioEventLoopGroup();
  4. EventLoopGroup workerGroup = new NioEventLoopGroup();
  5. ServerBootstrap bootstrap = new ServerBootstrap();
  6. bootstrap.group(bossGroup, workerGroup)
  7. .channel(NioServerSocketChannel.class)
  8. .childHandler(new ChannelInitializer<SocketChannel>() {
  9. @Override
  10. public void initChannel(SocketChannel ch) throws Exception {
  11. ch.pipeline().addLast("decoder", new StringDecoder());
  12. ch.pipeline().addLast("encoder", new StringEncoder());
  13. ch.pipeline().addLast(new ServerStringHandler());
  14. }
  15. })
  16. .option(ChannelOption.SO_BACKLOG, 128)
  17. .childOption(ChannelOption.SO_KEEPALIVE, true);
  18. try {
  19. ChannelFuture f = bootstrap.bind(port).sync();
  20. f.channel().closeFuture().sync();
  21. } catch (InterruptedException e) {
  22. e.printStackTrace();
  23. } finally {
  24. workerGroup.shutdownGracefully();
  25. bossGroup.shutdownGracefully();
  26. }
  27. }
  28. }
  • 通过ServerBootstrap 进行服务的配置,和socket的参数可以通过ServerBootstrap进行设置。
  • 通过group方法关联了两个线程组,NioEventLoopGroup是用来处理I/O操作的线程池,第一个称为“boss”,用来accept客户端连接,第二个称为“worker”,处理客户端数据的读写操作。当然你也可以只用一个NioEventLoopGroup同时来处理连接和读写,bootstrap.group()方法支持一个参数。
  • channel指定NIO方式
  • childHandler用来配置具体的数据处理方式 ,可以指定编解码器,处理数据的Handler
  • 绑定端口启动服务

消息处理:

  1. /**
  2. * 消息处理
  3. * @author yinjihuan
  4. *
  5. */
  6. public class ServerStringHandler extends ChannelInboundHandlerAdapter {
  7. @Override
  8. public void channelRead(ChannelHandlerContext ctx, Object msg) {
  9. System.err.println("server:" + msg.toString());
  10. ctx.writeAndFlush(msg.toString() + "你好");
  11. }
  12. @Override
  13. public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
  14. cause.printStackTrace();
  15. ctx.close();
  16. }
  17. }

启动服务,指定端口为2222:

  1. public static void main(String[] args) {
  2. int port = 2222;
  3. new Thread(() -> {
  4. new ImServer().run(port);
  5. }).start();
  6. }

编写客户端连接逻辑:

  1. public class ImConnection {
  2. private Channel channel;
  3. public Channel connect(String host, int port) {
  4. doConnect(host, port);
  5. return this.channel;
  6. }
  7. private void doConnect(String host, int port) {
  8. EventLoopGroup workerGroup = new NioEventLoopGroup();
  9. try {
  10. Bootstrap b = new Bootstrap();
  11. b.group(workerGroup);
  12. b.channel(NioSocketChannel.class);
  13. b.option(ChannelOption.SO_KEEPALIVE, true);
  14. b.handler(new ChannelInitializer<SocketChannel>() {
  15. @Override
  16. public void initChannel(SocketChannel ch) throws Exception {
  17. ch.pipeline().addLast("decoder", new StringDecoder());
  18. ch.pipeline().addLast("encoder", new StringEncoder());
  19. ch.pipeline().addLast(new ClientStringHandler());
  20. }
  21. });
  22. ChannelFuture f = b.connect(host, port).sync();
  23. channel = f.channel();
  24. } catch(Exception e) {
  25. e.printStackTrace();
  26. }
  27. }
  28. }

客户端消息处理:

  1. /**
  2. * 当编解码器为字符串时用来接收数据
  3. * @author yinjihuan
  4. *
  5. */
  6. public class ClientStringHandler extends ChannelInboundHandlerAdapter {
  7. @Override
  8. public void channelRead(ChannelHandlerContext ctx, Object msg) {
  9. System.out.println("client:" + msg.toString());
  10. }
  11. @Override
  12. public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
  13. cause.printStackTrace();
  14. ctx.close();
  15. }
  16. }

客户端启动入口,然后发送消息给服务端:

  1. public static void main(String[] args) {
  2. String host = "127.0.0.1";
  3. int port = 2222;
  4. Channel channel = new ImConnection().connect(host, port);
  5. channel.writeAndFlush("yinjihuan");
  6. }

测试步骤如下:

  1. 首先启动服务端
  2. 启动客户端,发送消息
  3. 服务端收到消息,控制台有输出server:yinjihuan
  4. 客户端收到服务端回复的消息,控制台有输出client:yinjihuan你好

源码参考:https://github.com/yinjihuan/netty-im

更多技术分享请关注微信公众号:猿天地

高性能NIO框架Netty入门篇的更多相关文章

  1. 【Netty】NIO框架Netty入门

    Netty介绍 Netty是由JBOSS提供的一个java开源框架.Netty提供异步的.事件驱动的网络应用程序框架和工具,用以快速开发高性能.高可靠性的网络服务器和客户端程序. 也就是说,Netty ...

  2. 6.高性能NIO框架netty

    1.Netty简介: Netty是基于Java NIO的网络应用框架 Netty是一个NIO client-server(客户端服务器)框架,使用Netty可以快速开发网络应用,例如服务器和客户端协议 ...

  3. 高性能NIO框架Netty-对象传输

    http://cxytiandi.com/blog/detail/17403 上篇文章高性能NIO框架Netty入门篇我们对Netty做了一个简单的介绍,并且写了一个入门的Demo,客户端往服务端发送 ...

  4. 分布式服务框架介绍:最成熟的开源NIO框架Netty

    尽管JDK提供了丰富的NIO类库,网上也有很多NIO学习例程,但是直接使用Java NIO类库想要开发出稳定可靠的通信框架却并非易事,原因如下: 1)NIO的类库和API繁杂,使用麻烦,你需要熟练掌握 ...

  5. Google C++测试框架系列入门篇:第三章 基本概念

    上一篇:Google C++测试框架系列入门篇:第二章 开始一个新项目 原始链接:Basic Concepts 词汇表 版本号:v_0.1 基本概念 使用GTest你肯定会接触到断言这个概念.断言是用 ...

  6. Google C++测试框架系列入门篇:第二章 开始一个新项目

    上一篇:Google C++测试框架系列入门篇:第一章 介绍:为什么使用GTest? 原始链接:Setting up a New Test Project 词汇表 版本号:v_0.1 开始一个新项目 ...

  7. Java异步NIO框架Netty实现高性能高并发

    原文地址:http://blog.csdn.net/opengl_es/article/details/40979371?utm_source=tuicool&utm_medium=refer ...

  8. netty入门篇(1)

    上一篇 nio简介  下一篇 netty中级篇(2) 一.为什么选择Netty Netty是最流行的框架之一.健壮性.功能.性能.可定制性和可扩展性在同类框架中首屈一指,因此被大规模使用,例如ROCK ...

  9. 如何在Visual Studio 2017中使用C# 7+语法 构建NetCore应用框架之实战篇(二):BitAdminCore框架定位及架构 构建NetCore应用框架之实战篇系列 构建NetCore应用框架之实战篇(一):什么是框架,如何设计一个框架 NetCore入门篇:(十二)在IIS中部署Net Core程序

    如何在Visual Studio 2017中使用C# 7+语法   前言 之前不知看过哪位前辈的博文有点印象C# 7控制台开始支持执行异步方法,然后闲来无事,搞着,搞着没搞出来,然后就写了这篇博文,不 ...

随机推荐

  1. 晨枫U盘启动盘制作工具V4.0-安装原版XP的方法

    [1]进入第一个PE后找到我们事先准备好的xp光盘iso镜像,右键点击加载虚拟磁盘(也可以利用虚拟光驱来加载或者直接用右键里的RAR解压到本地硬盘分区) [2]打开桌面上的windows安装工具,wi ...

  2. 云锁-安全,易用,灵活的许可-Virbox许可管理平台

    云许可,助力开发者保护软件财富 Virbox 云锁提供高强度加密及软件许可管理功能 安全,易用,灵活 防破解 云许可安全性体验与硬件锁一致,避免盗版导致损失 加密保护技术:反黑引擎/碎片代码执行/虚拟 ...

  3. ul+li水平居中的几种方法

    一.posotion:relative; 代码: <!DOCTYPE html> <html> <head> <meta charset="UTF- ...

  4. WebStrom2018注册码

    2RRJMBXW33-eyJsaWNlbnNlSWQiOiIyUlJKTUJYVzMzIiwibGljZW5zZWVOYW1lIjoi5b285bK4IHNvZnR3YXJlMiIsImFzc2lnb ...

  5. 编辑文件 vi,vim的基本操作

    vim   文件名字进入文件后   按i  进行编辑编辑确认后   按 Esc  停止编辑然后              按:   输入  wq     (是root权限时才行:若是强制修改 需要  ...

  6. (转)Thread的中断机制(interrupt)

    先看收集了别人的文章,全面的了解下java的中断: 中断线程 线程的thread.interrupt()方法是中断线程,将会设置该线程的中断状态位,即设置为true,中断的结果线程是死亡.还是等待新的 ...

  7. 开启Laravel之旅的标准姿势

    1.github下载最新的laravel https://github.com/laravel/laravel 2.下载到本地,改名,composer install,安装项目的依赖包 compose ...

  8. 用Partimage创建或恢复分区备份

    1 Preliminary Note Partimage is part of the system rescue CD found on http://www.sysresccd.org which ...

  9. linux 标准输入输出 重定向

    背景: 屏幕打印不一定都是从标准输出来的,也包括标准错误输出流stderr中的信息 文件描述符定义(系统定义了12个) 0 标准输入 1 标准输出 2 标准错误   0 默认键盘输入 1,2默认从屏幕 ...

  10. cocos2d-x JS 开启远程代码调试

    为了方便服务端与测试部门的工作需要,把客户端的写的程序可以在其他电脑上运行,方便他人工作与测试. 下面是cocos2d-x JS WebStorm 的设置方法.