亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Netty實戰(zhàn)入門教程之?什么是Netty

 更新時間:2022年02月23日 10:31:33   作者:Bug?終結(jié)者  
Java中支持三種網(wǎng)絡(luò)編程IO模型,BIO、NIO、AIO,Netty對NIO又做了一層封裝,本文帶領(lǐng)我們了解Netty到底是什么,Netty入門案例,感興趣的朋友跟隨小編一起看看吧

一、BIO、NIO、AIO

學(xué)習(xí)Netty需要了解BIO、NIO、AIO,具體可參考

Java網(wǎng)絡(luò)編程IO模型 — BIO、NIO、AIO詳解

二、什么是Netty?

官網(wǎng)介紹

Netty is an asynchronous event-driven network application framework
for rapid development of maintainable high performance protocol servers & clients.

Netty 是 一個異步事件驅(qū)動的網(wǎng)絡(luò)應(yīng)用程序框架
,用于快速開發(fā)可維護的高性能協(xié)議服務(wù)器和客戶端。

Netty 是一個 NIO 客戶端服務(wù)器框架,可以快速輕松地開發(fā)協(xié)議服務(wù)器和客戶端等網(wǎng)絡(luò)應(yīng)用程序。它極大地簡化和流線了網(wǎng)絡(luò)編程,例如 TCP 和 UDP 套接字服務(wù)器。

“快速和簡單”并不意味著生成的應(yīng)用程序會受到可維護性或性能問題的影響。Netty 是經(jīng)過精心設(shè)計的,它借鑒了許多協(xié)議(如 FTP、SMTP、HTTP 以及各種基于二進制和基于文本的遺留協(xié)議)的實現(xiàn)經(jīng)驗。因此,Netty 成功地找到了一種方法,可以在不妥協(xié)的情況下實現(xiàn)易于開發(fā)、性能、穩(wěn)定性和靈活性。

三、為什么學(xué)習(xí)Netty?

Netty在NIO的基礎(chǔ)上進行了封裝,比NIO強大,Netty使用很廣泛,用的企業(yè)多,所以需要去學(xué)習(xí),Netty支持高并發(fā),在高并發(fā)的情況下具有良好的吞吐量,是網(wǎng)絡(luò)通訊的首選框架

四、原生NIO存在的問題

  1. NIO的類庫和API繁雜,使用麻煩,需要熟練掌握Selector、ServerSocketChannel、SocketChannel、ByteBuffer等
  2. 需要具備其他額外技能,要熟悉Java多線程編程,因為NIO編程涉及到Reactor模式,你必須對多線程和網(wǎng)絡(luò)編程非常熟悉,才能編寫出高質(zhì)量的NIO程序
  3. 開發(fā)工作量和難度都非常大,例如客戶端面臨斷連重連、網(wǎng)絡(luò)閃斷、半包讀寫,失敗緩存、網(wǎng)絡(luò)擁塞和異常流的處理等
  4. JDK NIO的Bug:例如臭名昭著的 Epoll Bug,它會導(dǎo)致Selector空輪詢,最終導(dǎo)致CPU100%,直到JDK1.7版本該問題仍舊存在,沒有被根本解決

五、Netty有什么好處

Netty對JDK自帶的NIO的API進行了封裝,解決了上述問題

  • 設(shè)計優(yōu)雅,適用于各種傳輸類型的統(tǒng)一API阻塞和非阻塞Socket,基于靈活且可擴展的事件模型,可以清晰地分離關(guān)注點,高度可定制的線程模型 - 單線程,一個或多個線程池
  • 使用方便,詳細記錄的JavaDoc,用戶指南和示例,沒有其它依賴項,JDK5(Netty3.x)或6(Netty4.x)就可以
  • 安全,完整的SSL/TLS和StartTLS支持
  • 社區(qū)活躍,不斷更新;版本迭代周期短,發(fā)現(xiàn)的Bug可以被及時修復(fù),同時,更多的新功能會被加入
  1. 更高的吞吐量,更低的延遲
  2. 更少的資源消耗
  3. 最小化不必要的內(nèi)存拷貝

Netty模型圖

在這里插入圖片描述

六、那些領(lǐng)域用到了Netty

Netty在互聯(lián)網(wǎng)領(lǐng)域、大數(shù)據(jù)分布式計算領(lǐng)域、游戲行業(yè)、通信行業(yè)等獲得了廣泛的應(yīng)用,一些業(yè)界著名的開源組件也基于Netty的NIO框架構(gòu)建 (文章尾有詳細介紹)。 2.Netty的特點 高并發(fā) Netty是一款基于NIO(Nonblocking IO,非阻塞 IO)開發(fā)的網(wǎng)絡(luò)通信框架,對比于BIO(Blocking IO,阻塞IO),他的并發(fā)性能得到了很大提高 。

七、Netty模型

??簡單版本

工作原理示意圖-簡單版

Netty主要基于主從Reactor多線程模型,做了一定的改進,其中主從Reactor多線程有多個Reactor

在這里插入圖片描述

對上圖說明

  • BoosGroup線程維護Selector,只關(guān)注Accept
  • 當(dāng)接受到Accept事件,獲取到對應(yīng)的SocketChannel,封裝成NIOSocketChannel并注冊到Worker線程(事件循環(huán)),并進行維護
  • 當(dāng)Worker線程監(jiān)聽到selector 中通道發(fā)生自己感興趣的事件后,就進行處理(就由Handler),注意handler已經(jīng)加入通道。

??進階版本

Netty主要基于主從Reactor多線程模型,做了一定的改進,其中主從Reactor多線程模型有多個Reactor

在這里插入圖片描述

??詳細版本

在這里插入圖片描述

對上圖的說明

  1. Netty抽象出兩組線程池, BossGroup專門負責(zé)客戶端的連接,WorkerGroup專門負責(zé)網(wǎng)絡(luò)的讀寫
  2. BossGroup和WorkerGroup類型都是NIOEventLoopGroup
  3. NIOEventLoopGroup相當(dāng)于**一個事件循環(huán)組,**這個組中有多個事件循環(huán),每一個事件循環(huán)是NIOEventLoop
  4. NIOEventLoop表示一個不斷循環(huán)的執(zhí)行處理任務(wù)的線程,每個NIOEventLoop都有一個Selector,用于監(jiān)聽綁定在其上的Socket網(wǎng)絡(luò)通訊
  5. NIOEventLoopGroup 可以有多個線程,即可以含有多個NIOEventLoop
  6. 每個Boss NIOEventLoop 循環(huán)執(zhí)行的步驟有3步
  • 輪詢accept事件
  • 處理accept事件,與client建立連接,生成NIoSocketChannel,并將其注冊到某個Worker NIOEventLoop 上的selector
  • 處理任務(wù)隊列的任務(wù),即runAllTasks

7.每個Worker NIOEventLoop 循環(huán)執(zhí)行的步驟

  • 輪詢read,write事件
  • 處理i/o事件,在對應(yīng)的NIOSocketChannel處理
  • 處理任務(wù)隊列的任務(wù),即runAllTasks

8.每個Worker NIoEventLoop 處理業(yè)務(wù)時,會使用pipeline(管道)pipeline中包含了channel,即通過了pipelien可以獲取到對應(yīng)通道,管道中維護了很多的處理器

八、Netty入門案例 — TCP服務(wù)

? 需求說明

Netty服務(wù)器在6666端口監(jiān)聽,客戶端發(fā)送消息給服務(wù)器 “Hello,服務(wù)器”

服務(wù)器可以回復(fù)消息給客戶端 “hello 客戶端”

? 效果圖

在這里插入圖片描述

? 核心源碼

NettyServer

服務(wù)器,監(jiān)聽6666端口

package com.wanshi.netty.simple;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
public class NettyServer {
    public static void main(String[] args) throws Exception {
        // 創(chuàng)建BossGroup 和 WorkerGroup
        //說明
        //1.創(chuàng)建2個線程組,分別是boosGroup和workerGroup
        //2.boosGroup只是處理連接請求,真正的與客戶端業(yè)務(wù)處理,會交給workerGroup完成
        //3.兩個都是無限循環(huán)
        //4. boosGroup 和 workerGroup 含有的子線程(NioEventLoop)的個數(shù)
        // 默認(rèn)實際 CPU核數(shù)*2
        EventLoopGroup boosGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            //創(chuàng)建服務(wù)器端的啟動的對象,配置參數(shù)
            ServerBootstrap bootstrap = new ServerBootstrap();
            //使用鏈?zhǔn)骄幊虂磉M行設(shè)置
            bootstrap.group(boosGroup, workerGroup) // 設(shè)置兩個線程組
                    .channel(NioServerSocketChannel.class) //使用NioServerSocketChannel作為服務(wù)器的通道實現(xiàn)
                    .option(ChannelOption.SO_BACKLOG, 128) // 設(shè)置線程隊列等待連接個數(shù)
                    .childOption(ChannelOption.SO_KEEPALIVE, true) // 設(shè)置保持活動連接狀態(tài)
                    .childHandler(new ChannelInitializer<SocketChannel>() { // 創(chuàng)建一個通道初始化對象(匿名對象)
                        //給pipeline 設(shè)置處理器
                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            //可以使用一個集合管理SocketChannel,再推送消息時,可以將業(yè)務(wù)加入到各個channel對應(yīng)的NioEventLoop的taskQueue
                            //或者 scheduleTaskQueue
                            System.out.println("客戶 SocketChannel:" + socketChannel.hashCode());
                            socketChannel.pipeline().addLast(new NettyServerHandler());
                        }
                    }); //給我們的workerGroup的某一個EventLoop的對應(yīng)的管道設(shè)置處理器
            System.out.println("服務(wù)器 is ready...");
            //綁定一個端口并且同步,生成了一個ChannelFuture對象
            //啟動服務(wù)器并綁定端口
            ChannelFuture channelFuture = bootstrap.bind(6668).sync();
            channelFuture.addListener(new ChannelFutureListener() {
                @Override
                public void operationComplete(ChannelFuture future) throws Exception {
                    if (channelFuture.isSuccess()) {
                        System.out.println("監(jiān)聽端口 6668 成功");
                    } else {
                        System.out.println("監(jiān)聽端口 6668 失敗");
                    }
                }
            });
            //對關(guān)閉通道進行監(jiān)聽
            channelFuture.channel().closeFuture().sync();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //優(yōu)雅關(guān)閉
            boosGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
}

NettyServerHandler

服務(wù)器處理器,處理客戶端發(fā)送的消息并輸出到控制臺,并向服務(wù)端發(fā)送消息

package com.wanshi.netty.simple;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.CharsetUtil;
import java.util.concurrent.TimeUnit;
/**
 * 自定義一個Handler,需要繼承netty規(guī)定好的某個HandlerAdapter
 * 這時我們自定義的handler才能稱為一個handler
 */
public class NettyServerHandler extends ChannelInboundHandlerAdapter {
    //讀取數(shù)據(jù)事件(這里我們可以讀取客戶端發(fā)送的消息)
    /**
     * 1.ChannelHandlerContext ctx: 上下文對象,含有 管道pipeline,通道channel,地址
     * 2.Object msg:就是客戶端發(fā)送的數(shù)據(jù),默認(rèn)Object
     * @param ctx
     * @param msg
     * @throws Exception
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        System.out.println("server ctx =" + ctx);
        //將 msg 轉(zhuǎn)成一個ByteBuf
//        ByteBuf buf = (ByteBuf) msg;
//        System.out.println("客戶端發(fā)送消息是:" + buf.toString(CharsetUtil.UTF_8));
//        System.out.println("客戶端地址:" + ctx.channel().remoteAddress());
        //自定義普通任務(wù)隊列,將耗時長的任務(wù)加入隊列,定義到NioEventLoop --> taskQueue
        ctx.channel().eventLoop().execute(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.currentThread().sleep(10 * 1000);
                    ctx.writeAndFlush(Unpooled.copiedBuffer("hello,客戶端:喵2~", CharsetUtil.UTF_8));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
                    Thread.currentThread().sleep(20 * 1000);
                    ctx.writeAndFlush(Unpooled.copiedBuffer("hello,客戶端:喵3~", CharsetUtil.UTF_8));
        //用戶自定義定時任務(wù) --》 該任務(wù)是提交到 scheduleQueue中
        ctx.channel().eventLoop().schedule(new Runnable() {
                    Thread.currentThread().sleep(5 * 1000);
                    ctx.writeAndFlush(Unpooled.copiedBuffer("hello,客戶端:喵4~", CharsetUtil.UTF_8));
        }, 5, TimeUnit.SECONDS);
        System.out.println("go ~");
    }
     * 數(shù)據(jù)讀取完畢
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        //writeAndFlush 是 write+flush
        //將數(shù)據(jù)寫入到緩存,并刷新
        //一般講,需要對發(fā)送的數(shù)據(jù)進行編碼
        ctx.writeAndFlush(Unpooled.copiedBuffer("hello,客戶端:喵1~", CharsetUtil.UTF_8));
    //處理異常,一般是需要關(guān)閉通道
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        ctx.close();
}

NettyClient

客戶端,用于連接服務(wù)器

package com.wanshi.netty.simple;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
public class NettyClient {
    public static void main(String[] args) throws Exception {
        //客戶端需要一個事件循環(huán)組
        EventLoopGroup eventExecutors = new NioEventLoopGroup();
        try {
            //創(chuàng)建一個客戶端啟動對象
            //客戶端使用的不是ServerGroup 而是Bootstrap
            Bootstrap bootstrap = new Bootstrap();
            //設(shè)置相關(guān)參數(shù)
            bootstrap.group(eventExecutors) //設(shè)置線程組
                    .channel(NioSocketChannel.class) //設(shè)置客戶端通道的實現(xiàn)類(反射)
                    .handler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            socketChannel.pipeline().addLast(new NettyClientHandler()); //加入自己的處理器
                        }
                    });
            System.out.println("客戶端 is ok...");
            //啟動客戶端去連接服務(wù)器端, netty異步模型ChannelFuture
            ChannelFuture channelFuture = bootstrap.connect("127.0.0.1", 6668).sync();
            //給關(guān)閉通道進行監(jiān)聽
            channelFuture.channel().closeFuture().sync();
        } finally {
            //優(yōu)雅關(guān)閉線程池
            eventExecutors.shutdownGracefully();
        }
    }
}

NettyClientHandler

客戶端處理器,處理服務(wù)器發(fā)送的消息輸出到控制臺,并向服務(wù)器發(fā)送消息

package com.wanshi.netty.simple;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.CharsetUtil;
public class NettyClientHandler extends ChannelInboundHandlerAdapter {
    /**
     * 當(dāng)通道就緒就會觸發(fā)該方法
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        System.out.println("client " + ctx);
        ctx.writeAndFlush(Unpooled.copiedBuffer("hello,服務(wù)端Server:喵~", CharsetUtil.UTF_8));
    }
     * 當(dāng)通道有讀取事件時,會觸發(fā)
     * @param msg
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        //將msg轉(zhuǎn)成buf
        ByteBuf buf = (ByteBuf) msg;
        System.out.println("服務(wù)器回復(fù)的消息:" + buf.toString(CharsetUtil.UTF_8));
        System.out.println("服務(wù)器的地址:" + ctx.channel().remoteAddress());
	// 當(dāng)通道發(fā)生異常時執(zhí)行此方法    
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        ctx.close();
}

?小結(jié)

以上就是【Bug 終結(jié)者】對Netty入門簡單的理解,小編認(rèn)為Java中支持三種網(wǎng)絡(luò)編程IO模型,BIO、NIO、AIO,Netty對NIO又做了一層封裝,本文我們已大致了解Netty到底是什么,Netty入門案例還需多敲,多練,方可掌握,通過本文能加固你對Netty的理解

到此這篇關(guān)于Netty實戰(zhàn)入門教程之 什么是Netty的文章就介紹到這了,更多相關(guān)Netty入門內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • springboot 整合druid數(shù)據(jù)庫密碼加密功能的實現(xiàn)代碼

    springboot 整合druid數(shù)據(jù)庫密碼加密功能的實現(xiàn)代碼

    這篇文章主要介紹了springboot 整合druid數(shù)據(jù)庫密碼加密功能的實現(xiàn)代碼,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-01-01
  • Java中比較運算符compareTo()、equals()與==的區(qū)別及應(yīng)用總結(jié)

    Java中比較運算符compareTo()、equals()與==的區(qū)別及應(yīng)用總結(jié)

    這篇文章主要給大家介紹了關(guān)于Java中比較運算符compareTo()、equals()與==的區(qū)別及應(yīng)用的相關(guān)資料,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考借鑒,下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-09-09
  • Java如何將int型數(shù)組轉(zhuǎn)為String型數(shù)組

    Java如何將int型數(shù)組轉(zhuǎn)為String型數(shù)組

    這篇文章主要介紹了Java如何將int型數(shù)組轉(zhuǎn)為String型數(shù)組,本文給大家分享具體實現(xiàn)思路結(jié)合實例代碼給大家介紹的非常詳細,感興趣的朋友跟隨小編一起看看吧
    2024-03-03
  • Java跨session實現(xiàn)token接口測試過程圖解

    Java跨session實現(xiàn)token接口測試過程圖解

    這篇文章主要介紹了Java跨session實現(xiàn)token接口測試過程圖解,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-04-04
  • SpringBoot+Websocket實現(xiàn)一個簡單的網(wǎng)頁聊天功能代碼

    SpringBoot+Websocket實現(xiàn)一個簡單的網(wǎng)頁聊天功能代碼

    本篇文章主要介紹了SpringBoot+Websocket實現(xiàn)一個簡單的網(wǎng)頁聊天功能代碼,具有一定的參考價值,有需要的可以了解一下
    2017-08-08
  • Java 凍結(jié)或解除凍結(jié)Excel中的行和列的方法

    Java 凍結(jié)或解除凍結(jié)Excel中的行和列的方法

    這篇文章主要介紹了Java 凍結(jié)或解除凍結(jié)Excel中的行和列的方法,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-03-03
  • Java模擬實現(xiàn)HashMap算法流程詳解

    Java模擬實現(xiàn)HashMap算法流程詳解

    在java開發(fā)中,HashMap是最常用、最常見的集合容器類之一,文中通過示例代碼介紹HashMap為啥要二次Hash,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧
    2023-02-02
  • 詳解JAVA 原型模式

    詳解JAVA 原型模式

    這篇文章主要介紹了JAVA 原型模式的的相關(guān)資料,文中講解非常細致,實例幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下
    2020-06-06
  • 淺析Java中print、printf、println的區(qū)別

    淺析Java中print、printf、println的區(qū)別

    以下是對Java中print、printf、println的區(qū)別進行了詳細的分析介紹,需要的朋友可以過來參考下
    2013-08-08
  • Java?Mybatis框架由淺入深全解析中篇

    Java?Mybatis框架由淺入深全解析中篇

    MyBatis是一個優(yōu)秀的持久層框架,它對jdbc的操作數(shù)據(jù)庫的過程進行封裝,使開發(fā)者只需要關(guān)注SQL本身,而不需要花費精力去處理例如注冊驅(qū)動、創(chuàng)建connection、創(chuàng)建statement、手動設(shè)置參數(shù)、結(jié)果集檢索等jdbc繁雜的過程代碼本文將為大家深入的介紹一下MyBatis的使用
    2022-07-07

最新評論