高性能NIO框架Netty入门篇
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请求每次都要建立连接带来的性能消耗问题,通过二进制的数据传输减少网络开销,性能更高。
简单入门
我们编写一个服务端和客户端,客户端往服务端发送一条消息,消息传输先用字符串进行传递,服务端收到客户端发送的消息,然后回复一条消息。
首先编写服务端代码:
public class ImServer {public void run(int port) {EventLoopGroup bossGroup = new NioEventLoopGroup();EventLoopGroup workerGroup = new NioEventLoopGroup();ServerBootstrap bootstrap = new ServerBootstrap();bootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer<SocketChannel>() {@Overridepublic void initChannel(SocketChannel ch) throws Exception {ch.pipeline().addLast("decoder", new StringDecoder());ch.pipeline().addLast("encoder", new StringEncoder());ch.pipeline().addLast(new ServerStringHandler());}}).option(ChannelOption.SO_BACKLOG, 128).childOption(ChannelOption.SO_KEEPALIVE, true);try {ChannelFuture f = bootstrap.bind(port).sync();f.channel().closeFuture().sync();} catch (InterruptedException e) {e.printStackTrace();} finally {workerGroup.shutdownGracefully();bossGroup.shutdownGracefully();}}}
- 通过ServerBootstrap 进行服务的配置,和socket的参数可以通过ServerBootstrap进行设置。
- 通过group方法关联了两个线程组,NioEventLoopGroup是用来处理I/O操作的线程池,第一个称为“boss”,用来accept客户端连接,第二个称为“worker”,处理客户端数据的读写操作。当然你也可以只用一个NioEventLoopGroup同时来处理连接和读写,bootstrap.group()方法支持一个参数。
- channel指定NIO方式
- childHandler用来配置具体的数据处理方式 ,可以指定编解码器,处理数据的Handler
- 绑定端口启动服务
消息处理:
/*** 消息处理* @author yinjihuan**/public class ServerStringHandler extends ChannelInboundHandlerAdapter {@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) {System.err.println("server:" + msg.toString());ctx.writeAndFlush(msg.toString() + "你好");}@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {cause.printStackTrace();ctx.close();}}
启动服务,指定端口为2222:
public static void main(String[] args) {int port = 2222;new Thread(() -> {new ImServer().run(port);}).start();}
编写客户端连接逻辑:
public class ImConnection {private Channel channel;public Channel connect(String host, int port) {doConnect(host, port);return this.channel;}private void doConnect(String host, int port) {EventLoopGroup workerGroup = new NioEventLoopGroup();try {Bootstrap b = new Bootstrap();b.group(workerGroup);b.channel(NioSocketChannel.class);b.option(ChannelOption.SO_KEEPALIVE, true);b.handler(new ChannelInitializer<SocketChannel>() {@Overridepublic void initChannel(SocketChannel ch) throws Exception {ch.pipeline().addLast("decoder", new StringDecoder());ch.pipeline().addLast("encoder", new StringEncoder());ch.pipeline().addLast(new ClientStringHandler());}});ChannelFuture f = b.connect(host, port).sync();channel = f.channel();} catch(Exception e) {e.printStackTrace();}}}
客户端消息处理:
/*** 当编解码器为字符串时用来接收数据* @author yinjihuan**/public class ClientStringHandler extends ChannelInboundHandlerAdapter {@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) {System.out.println("client:" + msg.toString());}@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {cause.printStackTrace();ctx.close();}}
客户端启动入口,然后发送消息给服务端:
public static void main(String[] args) {String host = "127.0.0.1";int port = 2222;Channel channel = new ImConnection().connect(host, port);channel.writeAndFlush("yinjihuan");}
测试步骤如下:
- 首先启动服务端
- 启动客户端,发送消息
- 服务端收到消息,控制台有输出
server:yinjihuan - 客户端收到服务端回复的消息,控制台有输出
client:yinjihuan你好
源码参考:https://github.com/yinjihuan/netty-im
更多技术分享请关注微信公众号:猿天地
高性能NIO框架Netty入门篇的更多相关文章
- 【Netty】NIO框架Netty入门
Netty介绍 Netty是由JBOSS提供的一个java开源框架.Netty提供异步的.事件驱动的网络应用程序框架和工具,用以快速开发高性能.高可靠性的网络服务器和客户端程序. 也就是说,Netty ...
- 6.高性能NIO框架netty
1.Netty简介: Netty是基于Java NIO的网络应用框架 Netty是一个NIO client-server(客户端服务器)框架,使用Netty可以快速开发网络应用,例如服务器和客户端协议 ...
- 高性能NIO框架Netty-对象传输
http://cxytiandi.com/blog/detail/17403 上篇文章高性能NIO框架Netty入门篇我们对Netty做了一个简单的介绍,并且写了一个入门的Demo,客户端往服务端发送 ...
- 分布式服务框架介绍:最成熟的开源NIO框架Netty
尽管JDK提供了丰富的NIO类库,网上也有很多NIO学习例程,但是直接使用Java NIO类库想要开发出稳定可靠的通信框架却并非易事,原因如下: 1)NIO的类库和API繁杂,使用麻烦,你需要熟练掌握 ...
- Google C++测试框架系列入门篇:第三章 基本概念
上一篇:Google C++测试框架系列入门篇:第二章 开始一个新项目 原始链接:Basic Concepts 词汇表 版本号:v_0.1 基本概念 使用GTest你肯定会接触到断言这个概念.断言是用 ...
- Google C++测试框架系列入门篇:第二章 开始一个新项目
上一篇:Google C++测试框架系列入门篇:第一章 介绍:为什么使用GTest? 原始链接:Setting up a New Test Project 词汇表 版本号:v_0.1 开始一个新项目 ...
- Java异步NIO框架Netty实现高性能高并发
原文地址:http://blog.csdn.net/opengl_es/article/details/40979371?utm_source=tuicool&utm_medium=refer ...
- netty入门篇(1)
上一篇 nio简介 下一篇 netty中级篇(2) 一.为什么选择Netty Netty是最流行的框架之一.健壮性.功能.性能.可定制性和可扩展性在同类框架中首屈一指,因此被大规模使用,例如ROCK ...
- 如何在Visual Studio 2017中使用C# 7+语法 构建NetCore应用框架之实战篇(二):BitAdminCore框架定位及架构 构建NetCore应用框架之实战篇系列 构建NetCore应用框架之实战篇(一):什么是框架,如何设计一个框架 NetCore入门篇:(十二)在IIS中部署Net Core程序
如何在Visual Studio 2017中使用C# 7+语法 前言 之前不知看过哪位前辈的博文有点印象C# 7控制台开始支持执行异步方法,然后闲来无事,搞着,搞着没搞出来,然后就写了这篇博文,不 ...
随机推荐
- win10安装pycharm及汉化包
PyCharm 是一款功能强大的 Python 编辑器,带有一整套可以帮助用户在使用Python语言开发时提高其效率的工具,那么如何安装pycharm呢?都是英文看不懂有没有汉化版呢?跟ytkah一起 ...
- 运行python文件时出错SyntaxError: Non-UTF-8 code starting with '\xb5' in file, but no encoding declared;
今天ytkah在运行python文件时出现错误,提示如下,很明显这是没有定义python文件编码引起的问题,那么要怎么解决呢?很简单,在文件头部定义一下就可以了. File "hello.p ...
- finecms如何批量替换文章中的关键词?
Finecms批量替换文章关键词要怎么操作呢,比如把关键词A换为B?Finecms是免费开源无商业限制的内容管理系统,个人在维护,但二次开发很灵活,我们可以通过开发插件或数据库sql语句来操作,下面就 ...
- RN导航栏使用
import PropTypes from 'prop-types'; import React, { Component } from 'react'; import { NavigatorIOS, ...
- Java基础知识(JAVA集合框架之List与Set)
List和Set概述数组必须存放同一种元素.StringBuffer必须转换成字符串才能使用,如果想拿出单独的一个元素几乎不可能.数据有很多使用对象存,对象有很多,使用集合存. 集合容器因为内部的数据 ...
- 下载pywin32
下载pywin32 链接:sourceforge.net/projects/pywin32/files/ 1.找到一个pywin32的文件夹 2.下一级目录里面有多个文件夹. 3.打开Build222 ...
- 20165236 2017-2018-2 《Java程序设计》第八周学习总结
20165236 2017-2018-2 <Java程序设计>第八周学习总结 一.第十二章教材内容总结: 1.Java的多线程机制: 多线程是指一个应用程序中同时存在几个执行体,按几条不同 ...
- 浪潮IOT知识点
1 新增身份定义 以及 身份定义的属性表 要注意增加路由 2 '@trident/core'; 飘红,解决办法 import { TableSearchComponent } from '@t ...
- GlusterFS 配置及使用
GlusterFS集群创建 一.简介 GlusterFS概述 Glusterfs是一个开源的分布式文件系统,是Scale存储的核心,能够处理千数量级的客户端.在传统的解决 方案中Glusterfs能够 ...
- vbox 相关
1.虚拟机vbox 安装mac os 10.12 图文教程: https://www.cnblogs.com/liming2017/p/7566953.html