关于netty
netty 是一个非阻塞IO框架,用于Java网络应用开发,特点是异步处理,并发处理能力,netty里面包含有reactor框架的实现,是一个非常高级的框架体系。
netty特性
netty 处理快,更少的资源需求,响应快,可以作为高并发场景服务器的一个选择
reactor 个人理解是 react:响应式, or :对象,就是响应式框架,netty 就是运用reactor 的核心设计思想编写的高性能高并发网络请求处理器框架。
以下来自维基百科,自由的百科全书
注意:本条目主题可能尚无中文译名,因而使用原文或其拉丁字母转写作为标题。如果您在可靠来源中找到本主题的中文名称,请勇于将其移动至中文标题。(2019年2月)
![]() | |
---|---|
开发者 | Netty项目社区 |
稳定版本 | 4.1.31.Final[1](2018年10月30日,2年前) |
预览版本 | 5.0.0.Alpha3(2016年1月14日,5年前) |
源代码库 | github.com/netty/netty![]() |
编程语言 | Java |
类型 | Enterprise Integration Patterns Message Oriented Middleware |
许可协议 | Apache许可证 2.0 |
网站 | netty.io ![]() |
Netty是一个非阻塞I/O客户端-服务器框架,主要用于开发Java网络应用程序,如协议服务器和客户端。异步事件驱动的网络应用程序框架和工具用于简化网络编程,例如TCP和UDP套接字服务器。[2]Netty包括了反应器编程模式的实现。Netty最初由JBoss开发,现在由Netty项目社区开发和维护。
除了作为异步网络应用程序框架,Netty还包括了对HTTP、HTTP2、DNS及其他协议的支持,涵盖了在Servlet容器内运行的能力、对WebSockets的支持、与Google Protocol Buffers的集成、对SSL/TLS的支持以及对用于SPDY协议和消息压缩的支持。自2004年以来,Netty一直在被积极开发。[3]
从版本4.0.0开始,Netty在支持NIO和阻塞Java套接字的同时,还支持使用NIO.2作为后端。
用netty写一个简单非阻塞请求响应服务器
简单示意代码
服务端
服务器 HttpServer
package net.narule.jnetty.httpdemo;
import io.netty.bootstrap.ServerBootstrap;import io.netty.channel.ChannelFuture;import io.netty.channel.EventLoopGroup;import io.netty.channel.nio.NioEventLoopGroup;import io.netty.channel.socket.nio.NioServerSocketChannel;import io.netty.handler.logging.LogLevel;import io.netty.handler.logging.LoggingHandler;
import java.net.InetSocketAddress;
/** * netty server */public class HttpServer {
int port ;
public HttpServer(int port){ this.port = port; }
public void start() throws Exception{ ServerBootstrap bootstrap = new ServerBootstrap(); // 事件监听相关对象配置 netty 循环监听是否有新事件 // 如果有 马上将事件交给处理器,处理器层层循环处理,会循环到自定义消息解析器 HttpRequestHandler EventLoopGroup boss = new NioEventLoopGroup(); EventLoopGroup work = new NioEventLoopGroup(); bootstrap.group(boss,work) .handler(new LoggingHandler(LogLevel.DEBUG)) .channel(NioServerSocketChannel.class) .childHandler(new HttpServerInitializer());
ChannelFuture f = bootstrap.bind(new InetSocketAddress(port)).sync(); System.out.println("server start... port : " + port); f.channel().closeFuture().sync();
}
}
请求处理器初始化 HttpServerInitializer
initChannel 处理器配置。可以配置多个
package net.narule.jnetty.httpdemo;
import io.netty.channel.ChannelInitializer;import io.netty.channel.ChannelPipeline;import io.netty.channel.socket.SocketChannel;import io.netty.handler.codec.http.HttpObjectAggregator;import io.netty.handler.codec.http.HttpServerCodec;
public class HttpServerInitializer extends ChannelInitializer<SocketChannel> {
@Override protected void initChannel(SocketChannel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline(); // http 编解码 pipeline.addLast(new HttpServerCodec()); // http 消息聚合器 512*1024为接收的最大contentlength pipeline.addLast("httpAggregator",new HttpObjectAggregator(512*1024)); // 请求处理器 pipeline.addLast(new HttpRequestHandler());
}}
消息处理器 HttpRequestHandler
重写channelRead0 方法处理请求的消息并返回
package net.narule.jnetty.httpdemo;
import java.util.Date;import java.util.HashMap;import java.util.Map;import java.util.Set;
import io.netty.buffer.Unpooled;import io.netty.channel.ChannelFutureListener;import io.netty.channel.ChannelHandlerContext;import io.netty.channel.SimpleChannelInboundHandler;import io.netty.handler.codec.http.DefaultFullHttpResponse;import io.netty.handler.codec.http.FullHttpRequest;import io.netty.handler.codec.http.FullHttpResponse;import io.netty.handler.codec.http.HttpHeaderNames;import io.netty.handler.codec.http.HttpResponseStatus;import io.netty.handler.codec.http.HttpVersion;import io.netty.util.CharsetUtil;
public class HttpRequestHandler extends SimpleChannelInboundHandler<FullHttpRequest> {
@Override public void channelReadComplete(ChannelHandlerContext ctx) { ctx.flush(); }
@Override protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest req) throws Exception { // 处理数据 Date date = new Date(System.currentTimeMillis()); String uri = req.uri(); Map<String,String> data = new HashMap<>(); String protocal = req.protocolVersion().text(); //获取HTTP协议版本 String content = req.content().toString(CharsetUtil.UTF_8); //获取HTTP协议版本 System.out.println("request uri:" + uri); System.out.println("request content:" + content); boolean match = false; if(uri.contains("J")) { match = true; } data.put("match", String.valueOf(match)); data.put("protocal", protocal); data.put("uri", uri); data.put("time", date.toString()); data.put("content", content); System.getProperty("HOST"); String responsedata = "{"; Set<String> keySet = data.keySet(); int size = data.size(); for (String key : keySet) { size --; responsedata = responsedata + "\"" + key + "\":" + "\"" + data.get(key) + (size == 0? "\"}" : "\","); }
// 创建http响应 FullHttpResponse response = new DefaultFullHttpResponse( HttpVersion.HTTP_1_1, HttpResponseStatus.OK, Unpooled.copiedBuffer(responsedata, CharsetUtil.UTF_8)); // 设置头信息 response.headers().set(HttpHeaderNames.CONTENT_TYPE, "application/json; charset=UTF-8"); // 将处理后的数据 write到客户端、 ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE); }
}
启动
main方法启动服务
public static void main(String[] args) throws Exception{ HttpServer server = new HttpServer(80);// 80为启动端口 server.start();}
server start... port : 80
客户端测试
浏览器发送请求
直接url栏输入get请求:
http://localhost/test?name=J&time=-1
返回结果
{ "match":"true", "time":"Sun Jul 11 21:52:22 CST 2021", "protocal":"HTTP/1.1", "uri":"/test?name=J&time=-1", "content":""}
发送请求
http://localhost/test?name=nos&time=-1
返回结果
{ "match":"false", "time":"Sun Jul 11 21:52:22 CST 2021", "protocal":"HTTP/1.1", "uri":"/test?name=nos&time=-1", "content":""}