最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

深入理解tomcat中的BIO、NIO、AIO、ARP

 更新時(shí)間:2025年04月16日 08:46:34   作者:isyues  
tomcat作為springboot中默認(rèn)的web容器,了解tomcat的運(yùn)轉(zhuǎn)可以幫助我們更好的去調(diào)整tomcat的參數(shù)達(dá)到更好的性能,這篇文章主要介紹了理解tomcat中的BIO、NIO、AIO、ARP,需要的朋友可以參考下

tomcat作為springboot中默認(rèn)的web容器,了解tomcat的運(yùn)轉(zhuǎn)可以幫助我們更好的去調(diào)整tomcat的參數(shù)達(dá)到更好的性能

1. 前置知識(shí)

  • I/O就是Input/Output,收別人的數(shù)據(jù)到本機(jī)叫Input,本級(jí)發(fā)數(shù)據(jù)出去叫Output
  • 網(wǎng)絡(luò)I/O請求會(huì)先到網(wǎng)卡然后到內(nèi)核態(tài)再到用戶態(tài)
  • CPU比內(nèi)存快、內(nèi)存比硬盤、網(wǎng)卡等外設(shè)快
  • 所有I/O操作需要被加載到用戶態(tài)內(nèi)存,用戶態(tài)程序才能直接操作
  • 想要效果高,必須讓所有的資源都不閑置
  • tomcat不處理請求,會(huì)接受請求,轉(zhuǎn)發(fā)到具體的容器中
  • 一個(gè)socket連接代表一個(gè)客戶端,一個(gè)socket可以發(fā)送多份請求不斷開

2. scoket測試工具

啟動(dòng)程序是jar包,必須要有jre環(huán)境
鏈接:https://sockettest.sourceforge.net

3. BIO 同步阻塞IO

每一個(gè)socket連接后,tomcat都會(huì)有一個(gè)線程去全程去陪伴,把請求轉(zhuǎn)發(fā)到具體的容器中后,這個(gè)線程還在阻塞,等待容器返回?cái)?shù)據(jù),只有socket連接斷開了,才會(huì)回收這個(gè)線程。tomcat7或以下默認(rèn),比較簡單、穩(wěn)定,適合連接數(shù)比較少的

模擬代碼如下:

public class BioServer {
    static ExecutorService executorService = Executors.newCachedThreadPool();
    public static void main(String[] args) {
        try {
            // 啟動(dòng)服務(wù),綁定8080端口
            ServerSocket serverSocket = new ServerSocket();
            serverSocket.bind(new InetSocketAddress(8080));
            System.out.println("開啟服務(wù)");
            while (true){
                System.out.println("等待客戶端建立連接");
                // 監(jiān)聽8080端口,獲取客戶端連接
                Socket socket = serverSocket.accept(); //阻塞
                System.out.println("建立連接:"+socket);
                executorService.submit(()->{
                    //業(yè)務(wù)處理
                    try {
                        handler(socket);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                });
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //TODO 資源回收
        }
    }
    private static void handler(Socket socket) throws IOException {
        byte[] bytes = new byte[1024];
        System.out.println("等待讀取數(shù)據(jù)");
        int read = socket.getInputStream().read(bytes); // 阻塞
        if(read !=-1) {
            System.out.println("讀取客戶端發(fā)送的數(shù)據(jù):" +
                    new String(bytes, 0, read));
        }
    }
}

4. NIO 同步非阻塞

一個(gè)socket連接過來,會(huì)經(jīng)歷以下步驟

  • LimitLatch:連接控制器,負(fù)責(zé)維護(hù)連接數(shù)計(jì)算,連接數(shù)默認(rèn)是 8192,達(dá)到這個(gè)閥值后,就會(huì)拒絕連接請求。如果要調(diào)整修改配置文件server.tomcat.max-connections屬性
  • Acceptor:Acceptor 跑在一個(gè)單獨(dú)的線程里,它在一個(gè)死循環(huán)里調(diào)用 accept 方法來接收新連接,一旦有新的連接請求到來,accept 方法返回一個(gè) Channel 對象,接著把 Channel 對象交給 Poller 去處理
  • Poller:Poller 的本質(zhì)是一個(gè) Selector,也跑在單獨(dú)線程里。Poller 在內(nèi)部維護(hù)一個(gè) Channel 數(shù)組,它在一個(gè)死循環(huán)里不斷檢測 Channel 的數(shù)據(jù)就緒狀態(tài),一旦有 Channel 可讀,就生成一個(gè) SocketProcessor 任務(wù)對象扔給Executor 去處理
  • Executor: Executor 就是線程池,負(fù)責(zé)運(yùn)行 SocketProcessor 任務(wù)類,SocketProcessor 的 run 方法會(huì)調(diào)用Http11Processor 來讀取和解析請求數(shù)據(jù)。Http11Processor 是應(yīng)用層協(xié)議的封裝,它會(huì)調(diào)用容器獲得響應(yīng),再把響應(yīng)通過 Channel 寫出

tomcat8及以上默認(rèn), springboot2.3.12.RELEASE內(nèi)嵌tomcat是9.0.46版本默認(rèn)也是這個(gè)
模擬代碼:

public class NioServer {
    public static void main(String[] args)  {
        List<SocketChannel> list = new ArrayList<>();  // 緩存所有的socket
        ByteBuffer byteBuffer = ByteBuffer.allocate(1024); // 緩存區(qū)的大小
        try {
            ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
            // 監(jiān)聽8080
            serverSocketChannel.bind(new InetSocketAddress(8080));
            // channel非阻塞
            serverSocketChannel.configureBlocking(false);
            System.out.println("NioServer 啟動(dòng)....");
            while (true){
                // 非阻塞
                SocketChannel socketChannel = serverSocketChannel.accept();
                Thread.sleep(1000);
                if(socketChannel == null){
                    System.out.println("沒有新的客戶端建立連接");
                }else {
                    System.out.println("新的客戶端建立連接");
                    // channel非阻塞
                    socketChannel.configureBlocking(false);
                    // 將新的socket添加到 list
                    list.add(socketChannel);
                }
                //遍歷所有的socket
                for(SocketChannel channel:list){
                    //非阻塞
                    int read = channel.read(byteBuffer);
                    if(read >0) {
                        //讀模式
                        byteBuffer.flip();
                        System.out.println("讀取客戶端發(fā)送的數(shù)據(jù):" +new String(byteBuffer.array(),0,read));
                        byteBuffer.clear();
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

5. AIO異步非阻塞

NIO 和 AIO(NIO2) 最大的區(qū)別是,一個(gè)是同步一個(gè)是異步。異步最大的特點(diǎn)是,應(yīng)用程序不需要自己去觸發(fā)數(shù)據(jù)從內(nèi)核空間到用戶空間的拷貝。


沒有 Poller 組件,也就是沒有 Selector。在異步 I/O 模式下,Selector 的工作交給
內(nèi)核來做了。

Linux 內(nèi)核沒有很完善地支持異步 I/O 模型,因此 JVM 并沒有采用原生的 Linux 異步 I/O,而是在應(yīng)用層面通過 epoll 模擬了異步 I/O 模型。因此在 Linux 平臺(tái)上,Java NIO 和 Java NIO2 底層都是通過 epoll 來實(shí)現(xiàn)的,但是 Java NIO 更加簡單高效。如果你的 Tomcat 跑在 Linux 平臺(tái)上,建議不使用NIO2

模擬代碼:

public class AioServer {
    public AsynchronousServerSocketChannel serverSocketChannel;
    public static void main(String[] args) throws Exception {
        new AioServer().listen();
        Thread.sleep(Integer.MAX_VALUE);
    }
    private void listen() throws IOException {
        //1. 創(chuàng)建一個(gè)線程池
        ExecutorService es = Executors.newCachedThreadPool();
        //2. 創(chuàng)建異步通道群組
        AsynchronousChannelGroup acg = AsynchronousChannelGroup.withCachedThreadPool(es, 1);
        //3. 創(chuàng)建服務(wù)端異步通道
        serverSocketChannel = AsynchronousServerSocketChannel.open(acg);
        //4. 綁定監(jiān)聽端口
        serverSocketChannel.bind(new InetSocketAddress(8080));
        System.out.println("AioServer 啟動(dòng)....");
        //5. 監(jiān)聽連接,傳入回調(diào)類處理連接請求
        serverSocketChannel.accept(this, new CompletionHandler<AsynchronousSocketChannel, AioServer>() {
            //
            //            //具體處理連接請求的就是completed方法,它有兩個(gè)參數(shù):第一個(gè)是異步通道,第二個(gè)就是上面?zhèn)魅氲腁ioServer對象
            @Override
            public void completed(AsynchronousSocketChannel socketChannel, AioServer attachment) {
                try {
                    if (socketChannel.isOpen()) {
                        System.out.println("接收到新的客戶端的連接,地址:"
                                + socketChannel.getRemoteAddress());
                        final ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
                        //調(diào)用 read 函數(shù)讀取客戶端發(fā)送的數(shù)據(jù)
                        socketChannel.read(byteBuffer, socketChannel,
                                        new CompletionHandler<Integer, AsynchronousSocketChannel>() {
                                            @Override
                            public void completed(Integer result, AsynchronousSocketChannel attachment) {
                                try {
                                    //讀取請求,處理客戶端發(fā)送的數(shù)據(jù)
                                    byteBuffer.flip();
                                    String content = Charset.defaultCharset()
                                            .newDecoder().decode(byteBuffer).toString();
                                    System.out.println("服務(wù)端接受到客戶端發(fā)來的數(shù)據(jù):" + content);
                                } catch (CharacterCodingException e) {
                                    e.printStackTrace();
                                }
                            }
                            @Override
                            public void failed(Throwable exc, AsynchronousSocketChannel attachment) {
                                exc.printStackTrace();
                                try {
                                    attachment.close();
                                } catch (IOException e) {
                                    e.printStackTrace();
                                }
                            }
                        });
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }finally {
                    //當(dāng)有新的客戶端接入的時(shí)候,直接調(diào)用accept的方法
                    attachment.serverSocketChannel.accept(attachment, this);
                }
            }
            @Override
            public void failed(Throwable exc, AioServer attachment) {
                exc.printStackTrace();
            }
        });
    }
}

6. APR異步非阻塞

APR方式全名叫Apache Portable Runtime,需要額外去下載安裝配置,NIO2是調(diào)用java庫去實(shí)現(xiàn)異步的,而ARP是直接通過JNI (Java Native Interface)去操作系統(tǒng)是實(shí)現(xiàn)異步,APR 能夠使用高級(jí) IO 功能 (如sendfile, epoll, OpenSSL),sendfile主要是對靜態(tài)文件提升很大,換APR也主要是這個(gè)原因其他的提升也不是特別大

附上對比圖

springboot配置apr教程:http://m.fzitv.net/program/339686ch2.htm

到此這篇關(guān)于理解tomcat中的BIO、NIO、AIO、ARP的文章就介紹到這了,更多相關(guān)tomcat BIO、NIO、AIO、ARP內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Tomcat中實(shí)現(xiàn)Session小結(jié)

    Tomcat中實(shí)現(xiàn)Session小結(jié)

    本篇文章主要介紹了Tomcat中實(shí)現(xiàn)Session小結(jié) ,Session的主要目的就是為了彌補(bǔ)Http的無狀態(tài)特性。簡單的說,就是服務(wù)器可以利用session存儲(chǔ)客戶端在同一個(gè)會(huì)話期間的一些操作記錄。
    2017-01-01
  • Tomcat解決catalina.out文件過大的問題

    Tomcat解決catalina.out文件過大的問題

    本文主要介紹了Tomcat解決catalina.out文件過大的問題,文件過大,不僅占系統(tǒng)的存儲(chǔ),我們還將無法使用過常規(guī)的編輯工具進(jìn)行查看,感興趣的可以了解一下
    2022-02-02
  • 解決Tomcat的maxPostSize屬性的配置需要注意的問題

    解決Tomcat的maxPostSize屬性的配置需要注意的問題

    這篇文章主要介紹了解決Tomcat的maxPostSize屬性的配置需要注意的問題,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-07-07
  • idea中沒有tomcat選項(xiàng)如何配置添加tomcat

    idea中沒有tomcat選項(xiàng)如何配置添加tomcat

    多的工程用IDEA打開調(diào)試,如果用到 tomcat服務(wù),都要配置一下,本文主要介紹了idea中沒有tomcat選項(xiàng)如何配置添加tomcat,下面就來具體介紹一下,感興趣的可以了解一下
    2024-05-05
  • 圖解Linux下安裝Tomcat服務(wù)器

    圖解Linux下安裝Tomcat服務(wù)器

    這篇文章主要以圖文結(jié)合的方式為大家詳細(xì)介紹了Linux下安裝Tomcat服務(wù)器的詳細(xì)過程,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-10-10
  • Tomcat9使用免費(fèi)的Https證書加密網(wǎng)站的方法

    Tomcat9使用免費(fèi)的Https證書加密網(wǎng)站的方法

    這篇文章主要介紹了Tomcat9使用免費(fèi)的Https證書加密網(wǎng)站的方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-05-05
  • tomcat簡介_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    tomcat簡介_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    這篇文章主要介紹了tomcat簡介,詳細(xì)的介紹了tomcat和Tomcat基本配置,具有一定的參考價(jià)值,有興趣的可以了解一下
    2017-07-07
  • Tomcat服務(wù)器搭建教程

    Tomcat服務(wù)器搭建教程

    這篇文章主要為大家詳細(xì)介紹了Tomcat服務(wù)器搭建教程,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-05-05
  • Tomcat開啟JMX服務(wù)方法介紹

    Tomcat開啟JMX服務(wù)方法介紹

    這篇文章主要介紹了Tomcat開啟JMX服務(wù)方法的相關(guān)內(nèi)容,小編覺得挺不錯(cuò)的,在這里給大家分享一下,需要的朋友可以參考。
    2017-10-10
  • 簡單實(shí)現(xiàn)nginx+tomcat的反向代理與動(dòng)靜分離

    簡單實(shí)現(xiàn)nginx+tomcat的反向代理與動(dòng)靜分離

    這篇文章主要介紹了簡單實(shí)現(xiàn)nginx+tomcat的反向代理與動(dòng)靜分離,需要的朋友可以參考下
    2016-05-05

最新評論

武穴市| 德惠市| 兴和县| 定远县| 平邑县| 股票| 中西区| 辽宁省| 衡山县| 连南| 屯昌县| 和龙市| 张北县| 宝清县| 利津县| 新田县| 汉源县| 高邑县| 兰溪市| 吉林省| 安丘市| 常山县| 湘西| 志丹县| 张北县| 龙山县| 青海省| 治多县| 南开区| 桃江县| 商河县| 阳泉市| 呼图壁县| 福泉市| 定州市| 前郭尔| 读书| 龙南县| 桂平市| 翁牛特旗| 南京市|