Netty1:初识Netty
为什么使用Netty
Netty是业界最流行的NIO框架之一,它的健壮性、功能、性能、可定制性、可扩展性在同类框架中都是首屈一指的,它已经得到了成百上千的商用项目的证明。对于为什么使用Netty这个话题,我们先看一下使用原生的NIO有什么缺点:
- NIO的类库和API繁杂,使用麻烦,需要熟练掌握Selector、ServerSocketChannel、SocketChannel、ByteBuffer等,这就像我们会使用Hibernate、MyBatis这些ORM框架而不会直接使用Connection、Statement一样
- 需要其他额外技能作为铺垫,必须对多线程和网络编程非常熟悉才能写出高质量的NIO程序
- 可靠性能力补齐,工作量和难度都非常大,例如客户端面临断线重连、网络闪断、半包读写、失败缓存、网络拥塞、异常码流等问题的处理
- JDK NIO的BUG,例如著名的epoll bug,该问题会导致Selector空轮训,最终导致CPU 100%
也正是因为有种种缺点,因此不建议使用原生的NIO而是建议使用一些比较成熟的NIO框架例如Netty、Mina,这一系列文章讲的是Netty,Netty作为一款高性能NIO框架,其优点总结有:
- API使用简单、开发门槛低
- 功能强大,预置了多种编码解码功能,支持多种主流协议
- 定制能力强,可以通过ChannelHandler对通信框架进行灵活扩展
- 性能高,与业界其他主流NIO框架对比,Netty性能最优
- 成熟、稳定,Netty修复了已经发现的所有JDK NIO的BUG,业务开发人员不需要再为NIO的BUG而烦恼
- 社区活跃、版本迭代周期短,发现的BUG可以被及时修复,同时,更多的新功能会被加入
- 经历了大规模的商业应用考验,质量得到验证
正因为这些优点,Netty逐渐成为了Java NIO变成的首选框架。
Netty入门Demo
下面演示一下Netty的Demo(注:Demo来自Netty权威指南第三章),本文只写代码与演示结果,不做讲解,对Netty的使用基本讲解放在下一篇文章中,循序渐进,先感性地认识Netty,再理性地认识Netty中的东西。
提一下,本文及之后的文章Netty基于5.0.0.Alpha1这个版本,贴一下我自己的Maven配置吧:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <groupId>org.xrq.netty</groupId>
<artifactId>netty-test</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging> <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties> <dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>5.0.0.Alpha1</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
</dependencies> </project>
首先从服务端代码开始,定义一个TimeServer:
public class TimeServer {
public void bind(int port) throws Exception {
// NIO线程组
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.option(ChannelOption.SO_BACKLOG, 1024)
.childHandler(new ChildChannelHandler());
// 绑定端口,同步等待成功
ChannelFuture f = b.bind(port).sync();
// 等待服务端监听端口关闭
f.channel().closeFuture().sync();
} finally {
// 优雅退出,释放线程池资源
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
private class ChildChannelHandler extends ChannelInitializer<SocketChannel> {
@Override
protected void initChannel(SocketChannel arg0) throws Exception {
arg0.pipeline().addLast(new TimeServerHandler());
}
}
}
TimeServerHandler这么定义:
public class TimeServerHandler extends ChannelHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ByteBuf buf = (ByteBuf)msg;
byte[] req = new byte[buf.readableBytes()];
buf.readBytes(req);
String body = new String(req, "UTF-8");
System.out.println("The time server receive order:" + body);
String currentTime = "QUERY TIME ORDER".equalsIgnoreCase(body) ? new Date(System.currentTimeMillis()).toString() : "BAD ORDER";
ByteBuf resp = Unpooled.copiedBuffer(currentTime.getBytes());
ctx.write(resp);
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
ctx.flush();
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
ctx.close();
}
}
即读取来自客户端的数据,如果是"QUERY TIME ORDER",则把当前时间写到Channel中去。至此,Netty服务端代码已经开发完毕。接下来是Netty客户端代码,首先还是TimeClient:
public class TimeClient {
public void connect(int port, String host) throws Exception {
EventLoopGroup group = new NioEventLoopGroup();
try {
Bootstrap b = new Bootstrap();
b.group(group)
.channel(NioSocketChannel.class)
.option(ChannelOption.TCP_NODELAY, true)
.handler(new ChannelInitializer<SocketChannel>() {
protected void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new TimeClientHandler());
};
});
// 发起异步连接操作
ChannelFuture f = b.connect(host, port).sync();
// 等待客户端连接关闭
f.channel().closeFuture().sync();
} finally {
// 优雅退出,释放NIO线程组
group.shutdownGracefully();
}
}
}
同样的,定义一个TimeClientHandler:
public class TimeClientHandler extends ChannelHandlerAdapter {
private static final Logger LOGGER = LoggerFactory.getLogger(TimeClientHandler.class);
private final ByteBuf firstMessage;
public TimeClientHandler() {
byte[] req = "QUERY TIME ORDER".getBytes();
firstMessage = Unpooled.buffer(req.length);
firstMessage.writeBytes(req);
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
ctx.writeAndFlush(firstMessage);
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ByteBuf buf = (ByteBuf)msg;
byte[] req = new byte[buf.readableBytes()];
buf.readBytes(req);
String body = new String(req, "UTF-8");
System.out.println("Now is:" + body);
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
LOGGER.warn("Unexcepted exception from downstream:" + cause.getMessage());
ctx.close();
}
}
客户端的操作为打印来自服务端的数据,这样,整个Netty Demo代码就写完了,结构比较清楚,都是一个Server+一个Handler的模式,Handler用于处理读取到的信息。
运行Demo
上面写完了Demo,接着写一下测试代码,很简单,分别运行bind方法和connect方法即可:
public class CoreTest {
@Test
public void timeServerTest() throws Exception {
new TimeServer().bind(8080);
}
@Test
public void timeClientTest() throws Exception {
new TimeClient().connect(8080, "127.0.0.1");
}
}
先运行timeServerTest让服务端先启动,再运行timeClientServer让客户端后启动,运行结果服务端的打印为:
The time server receive order:QUERY TIME ORDER
结合代码可以看到,服务端读取到了来自客户端的数据,数据内容为"QUERY TIME ORDER",接着服务端取自己的时间,传输给客户端,看一下客户端的打印:
Now is:Thu Apr 05 21:07:39 CST 2018
打印了来自服务端的时间,这样,利用Netty进行服务端+客户端的相互通信的Demo完成,有了这个Demo,对Netty有了感性上的认识,接着我们一点一点深入去学习Netty。
Netty1:初识Netty的更多相关文章
- DotNetty网络通信框架学习之初识Netty
p{ text-align:center; } blockquote > p > span{ text-align:center; font-size: 18px; color: #ff0 ...
- [Netty 1] 初识Netty
1. 简介 最早接触netty是在阅读Zookeeper源码的时候,后来看到Storm的消息传输层也由ZMQ转为Netty,所以决心好好来研究和学习一下netty这个框架. Netty项目地址:htt ...
- Netty 学习 一、初识Netty【原创】
在过去几年的工作和学习中,比较关注高层次的应用开发,对底层探究较少.实现Web应用的开发,主要依赖Tomcat.Apache等应用服务器,程序员无需了解底层协议,但同样限制了应用的性能和效率.现在开始 ...
- 初识Netty
我们已经了解了Socket通信/IO/NIO/AIO编程,对于通信模型已经有了一个初步的认识,其实我们之前所学习的仅仅是一个模型,如果想把这些真正的用于实际工作中去,其实我们之前所学习的仅仅是一个模型 ...
- Netty(一):初识Netty
Netty是什么? Netty是由JBOSS提供的一个java开源框架. Netty提供异步的.事件驱动的网络应用程序框架和工具,用以快速开发高性能.高可靠性的网络服务器和客户端程序. 封装了JDK底 ...
- 【Netty】初识Netty
一.为什么会出现Netty 之前我们使用通用的应用程序或库来相互通信.例如,我们经常使用HTTP客户机库从web服务器检索信息,并通过web服务调用远程过程调用.然而,通用协议或其实现有时伸缩性不是很 ...
- Netty:初识Netty
前文总结了NIO的内容,有了NIO的一些基础之后,我们就可以来看下Netty.Netty是Java领域的高性能网络传输框架,RPC的技术核心就是网络传输和序列化,所以Netty给予了RPC在网络传输领 ...
- 2、Netty基础
一.前言 主要包含下面内容: 初识 Netty: 使用 Java NIO 搭建简单的客户端与服务端实现网络通讯: 使用 Netty 搭建简单的客户端与服务端实现网络通讯: Netty 底层操作与 Ja ...
- Netty与NIO
初识Netty Netty是由JBoss提供的一个Java的开源框架,是GitHub上的独立项目. Netty是一个异步的,基于事件驱动的网络应用框架,用于快速开发高性能.高可靠的网络IO程序. Ne ...
随机推荐
- SSM-Spring-18:Spring中aspectJ的XML版
------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥------------- aspectJ的xml版是开发中最常用的: 下面直接已案例入手,毕竟繁琐的日子不多了 案例:两个接口,俩个实现 ...
- Spring 数据处理框架的演变
欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 定量分析的成败在很大程度上取决于采集,存储和处理数据的能力.若能及时地向业务决策者提供深刻并可靠的数据解读,大数据项目就会有更多机会取得成功 ...
- Debian9安装vim编辑器
本文由荒原之梦原创,原文链接:http://zhaokaifeng.com/?p=669 前言: Debian 9默认没有安装vim,但是使用Linux怎么能没有vim呢?下面就来安装一下vim吧. ...
- 使用Spring Session实现Spring Boot水平扩展
小编说:本文使用Spring Session实现了Spring Boot水平扩展,每个Spring Boot应用与其他水平扩展的Spring Boot一样,都能处理用户请求.如果宕机,Nginx会将请 ...
- 使用OAuth2的SSO分析
参考:https://github.com/spring-guides/tut-spring-security-and-angular-js/blob/master/oauth2-vanilla/RE ...
- SQL注入简单介绍
一.SQL注入概念 1.sql注入是一种将sql代码添加到输入参数中 2.传递到sql服务器解析并执行的一种攻击手法 举例:某个网站的用户名为name=‘admin’.执行时为select ...
- Ordering犀利的比较器
Ordering是Guava类库提供的一个犀利强大的比较器工具,Guava的Ordering和JDK Comparator相比功能更强.它非常容易扩展,可以轻松构造复杂的comparator,然后用在 ...
- 【bzoj 2916】[Poi1997]Monochromatic Triangles
题目描述 空间中有n个点,任意3个点不共线.每两个点用红线或者蓝线连接,如果一个三角形的三边颜色相同,那么称为同色三角形.给你一组数据,计算同色三角形的总数. 输入 第 ...
- HEOI2018 游记
day0早上没有跑操,收拾了点东西,带了点吃的,老妈打电话说要给送点厚衣服,好像确实有点冷.上午有考试,说自愿考,然后开到一半就没了,根本没人打啊,打了一道小园丁和老司机,一个一个部分分打,最后T了一 ...
- luoguP4231_三步必杀_差分
luoguP4231_三步必杀_差分 题意:N 个柱子排成一排,一开始每个柱子损伤度为0.接下来勇仪会进行M 次攻击,每次攻击可以用4个参数l,r ,s ,e 来描述: 表示这次攻击作用范围为第l个到 ...