關於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":""
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章