zoukankan      html  css  js  c++  java
  • 关于netty

    关于netty

    netty 是一个非阻塞IO框架,用于Java网络应用开发,特点是异步处理,并发处理能力,netty里面包含有reactor框架的实现,是一个非常高级的框架体系。

    netty特性

    netty 处理快,更少的资源需求,响应快,可以作为高并发场景服务器的一个选择

    reactor 个人理解是 react:响应式, or :对象,就是响应式框架,netty 就是运用reactor 的核心设计思想编写的高性能高并发网络请求处理器框架。

    以下来自维基百科,自由的百科全书

    跳到导航跳到搜索

    注意:本条目主题可能尚无中文译名,因而使用原文或其拉丁字母转写作为标题。如果您在可靠来源中找到本主题的中文名称,请勇于将其移动至中文标题。(2019年2月)

    JBoss-Netty-logo.png
    开发者 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网络应用程序,如协议服务器和客户端。异步事件驱动的网络应用程序框架和工具用于简化网络编程,例如TCPUDP套接字服务器。[2]Netty包括了反应器编程模式的实现。Netty最初由JBoss开发,现在由Netty项目社区开发和维护。

    除了作为异步网络应用程序框架,Netty还包括了对HTTPHTTP2DNS及其他协议的支持,涵盖了在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":""
    }
    
  • 相关阅读:
    jQuery-1.9.1源码分析系列(十六)ajax——ajax框架
    js基础篇——encodeURI 和encodeURIComponent
    apache分析之三、配置文件解析
    apache分析之二、post-commit后台运行
    apache分析之一、svn:Could not open the requested SVN filesystem
    从例子看git的内部实现
    stl中容器的end指向哪里
    使用dependency walker定位windows下程序启动失败原因
    lvs中的保活、persistent及DR
    当磁盘空间满之后,为什么文件依然可以被创建
  • 原文地址:https://www.cnblogs.com/Narule/p/14999938.html
Copyright © 2011-2022 走看看