国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Netty+SpringBoot+FastDFS+Html5實(shí)現(xiàn)聊天App詳解(一)

CNZPH / 1049人閱讀

摘要:線程切換效率低下單機(jī)核數(shù)固定,線程爆炸之后操作系統(tǒng)頻繁進(jìn)行線程切換,應(yīng)用性能急劇下降。線程切換效率低下由于模型中線程數(shù)量大大降低,線程切換效率因此也大幅度提高。將兩個(gè)線程優(yōu)雅地關(guān)閉。創(chuàng)建管道的子處理器,用于處理。

Netty+SpringBoot+FastDFS+Html5實(shí)現(xiàn)聊天App,項(xiàng)目介紹:https://segmentfault.com/a/11...

Netty+SpringBoot+FastDFS+Html5實(shí)現(xiàn)聊天App,項(xiàng)目github鏈接:https://github.com/ShimmerPig...

本章練習(xí)完整代碼鏈接:https://github.com/ShimmerPig...

Netty學(xué)習(xí) IO編程與NIO編程 傳統(tǒng)IO編程性能分析

IO編程模型在客戶端較少的情況下運(yùn)行良好,但是對(duì)于客戶端比較多的業(yè)務(wù)來說,單機(jī)服務(wù)端可能需要支撐成千上萬的連接,IO模型可能就不太合適了。這是因?yàn)樵趥鹘y(tǒng)的IO模型中,每個(gè)連接創(chuàng)建成功之后都需要一個(gè)線程來維護(hù),每個(gè)線程包含一個(gè)while死循環(huán),那么1w個(gè)連接對(duì)應(yīng)1w個(gè)線程,繼而1w個(gè)while死循環(huán),這就帶來如下幾個(gè)問題:

1.線程資源受限:線程是操作系統(tǒng)中非常寶貴的資源,同一時(shí)刻有大量的線程處于阻塞狀態(tài)是非常嚴(yán)重的資源浪費(fèi),操作系統(tǒng)耗不起。

2.線程切換效率低下:單機(jī)cpu核數(shù)固定,線程爆炸之后操作系統(tǒng)頻繁進(jìn)行線程切換,應(yīng)用性能急劇下降。

3.除了以上兩個(gè)問題,IO編程中,我們看到數(shù)據(jù)讀寫是以字節(jié)流為單位,效率不高。

為了解決這三個(gè)問題,JDK在1.4之后提出了NIO。下面簡單描述一下NIO是如何解決以上三個(gè)問題的。

線程資源受限

NIO編程模型中,新來一個(gè)連接不再創(chuàng)建一個(gè)新的線程,而是可以把這條連接直接綁定到某個(gè)固定的線程,然后這條連接所有的讀寫都由這個(gè)線程來負(fù)責(zé)。
這個(gè)過程的實(shí)現(xiàn)歸功于NIO模型中selector的作用,一條連接來了之后,現(xiàn)在不創(chuàng)建一個(gè)while死循環(huán)去監(jiān)聽是否有數(shù)據(jù)可讀了,而是直接把這條連接注冊(cè)到selector上,然后,通過檢查這個(gè)selector,就可以批量監(jiān)測(cè)出有數(shù)據(jù)可讀的連接,進(jìn)而讀取數(shù)據(jù)。

線程切換效率低下

由于NIO模型中線程數(shù)量大大降低,線程切換效率因此也大幅度提高。

IO讀寫以字節(jié)為單位

NIO解決這個(gè)問題的方式是數(shù)據(jù)讀寫不再以字節(jié)為單位,而是以字節(jié)塊為單位。IO模型中,每次都是從操作系統(tǒng)底層一個(gè)字節(jié)一個(gè)字節(jié)地讀取數(shù)據(jù),而NIO維護(hù)一個(gè)緩沖區(qū),每次可以從這個(gè)緩沖區(qū)里面讀取一塊的數(shù)據(jù)。




hello netty

完整代碼鏈接:https://github.com/ShimmerPig...

首先定義一對(duì)線程組——主線程bossGroup與從線程workerGroup。
bossGroup——用于接受客戶端的連接,但是不做任何處理,跟老板一樣,不做事。
workerGroup——bossGroup會(huì)將任務(wù)丟給他,讓workerGroup去處理。

//主線程
EventLoopGroup bossGroup = new NioEventLoopGroup();
//從線程
EventLoopGroup workerGroup = new NioEventLoopGroup();

定義服務(wù)端的啟動(dòng)類serverBootstrap,需要設(shè)置主從線程,NIO的雙向通道,與子處理器(用于處理workerGroup),這里的子處理器后面我們會(huì)手動(dòng)創(chuàng)建。

// netty服務(wù)器的創(chuàng)建, ServerBootstrap 是一個(gè)啟動(dòng)類
            ServerBootstrap serverBootstrap = new ServerBootstrap();
            serverBootstrap.group(bossGroup, workerGroup)            // 設(shè)置主從線程組
                            .channel(NioServerSocketChannel.class)    // 設(shè)置nio的雙向通道
                            .childHandler(new HelloServerInitializer()); // 子處理器,用于處理workerGroup

啟動(dòng)服務(wù)端,綁定8088端口,同時(shí)設(shè)置啟動(dòng)的方式為同步的,這樣我們的Netty就會(huì)一直等待,直到該端口啟動(dòng)完畢。

ChannelFuture channelFuture = serverBootstrap.bind(8088).sync();

監(jiān)聽關(guān)閉的通道channel,設(shè)置為同步方式。

channelFuture.channel().closeFuture().sync();

將兩個(gè)線程優(yōu)雅地關(guān)閉。

bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();

創(chuàng)建管道channel的子處理器HelloServerInitializer,用于處理workerGroup。
HelloServerInitializer里面只重寫了initChannel方法,是一個(gè)初始化器,channel注冊(cè)后,會(huì)執(zhí)行里面相應(yīng)的初始化方法。
在initChannel方法中通過SocketChannel獲得對(duì)應(yīng)的管道,通過該管道添加相關(guān)助手類handler。
HttpServerCodec是由netty自己提供的助手類,可以理解為攔截器,當(dāng)請(qǐng)求到服務(wù)端,我們需要做解碼,響應(yīng)到客戶端做編碼。
添加自定義的助手類customHandler,返回"hello netty~"

ChannelPipeline pipeline = channel.pipeline();
pipeline.addLast("HttpServerCodec", new HttpServerCodec());
pipeline.addLast("customHandler", new CustomHandler());

創(chuàng)建自定義的助手類CustomHandler繼承SimpleChannelInboundHandler,返回hello netty~
重寫channelRead0方法,首先通過傳入的上下文對(duì)象ChannelHandlerContext獲取channel,若消息類型為http請(qǐng)求,則構(gòu)建一個(gè)內(nèi)容為"hello netty~"的http響應(yīng),通過上下文對(duì)象的writeAndFlush方法將響應(yīng)刷到客戶端。

if (msg instanceof HttpRequest) {
    // 顯示客戶端的遠(yuǎn)程地址
    System.out.println(channel.remoteAddress());
    
    // 定義發(fā)送的數(shù)據(jù)消息
    ByteBuf content = Unpooled.copiedBuffer("Hello netty~", CharsetUtil.UTF_8);
    
    // 構(gòu)建一個(gè)http response
    FullHttpResponse response = 
        new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, 
                HttpResponseStatus.OK, 
                content);
    // 為響應(yīng)增加數(shù)據(jù)類型和長度
    response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/plain");
    response.headers().set(HttpHeaderNames.CONTENT_LENGTH, content.readableBytes());
    
    // 把響應(yīng)刷到客戶端
    ctx.writeAndFlush(response);
}

訪問8088端口,返回"hello netty~"




netty聊天小練習(xí)

完整代碼鏈接:https://github.com/ShimmerPig...

服務(wù)器

定義主從線程與服務(wù)端的啟動(dòng)類

public class WSServer {

    public static void main(String[] args) throws Exception {
        
        EventLoopGroup mainGroup = new NioEventLoopGroup();
        EventLoopGroup subGroup = new NioEventLoopGroup();
        
        try {
            ServerBootstrap server = new ServerBootstrap();
            server.group(mainGroup, subGroup)
                .channel(NioServerSocketChannel.class)
                .childHandler(new WSServerInitialzer());
            
            ChannelFuture future = server.bind(8088).sync();
            
            future.channel().closeFuture().sync();
        } finally {
            mainGroup.shutdownGracefully();
            subGroup.shutdownGracefully();
        }
    }
    
}

創(chuàng)建channel的子處理器WSServerInitialzer
加入相關(guān)的助手類handler

public class WSServerInitialzer extends ChannelInitializer {

    @Override
    protected void initChannel(SocketChannel ch) throws Exception {
        ChannelPipeline pipeline = ch.pipeline();
        
        // websocket 基于http協(xié)議,所以要有http編解碼器
        pipeline.addLast(new HttpServerCodec());
        // 對(duì)寫大數(shù)據(jù)流的支持 
        pipeline.addLast(new ChunkedWriteHandler());
        // 對(duì)httpMessage進(jìn)行聚合,聚合成FullHttpRequest或FullHttpResponse
        // 幾乎在netty中的編程,都會(huì)使用到此hanler
        pipeline.addLast(new HttpObjectAggregator(1024*64));
        
        // ====================== 以上是用于支持http協(xié)議    ======================
        
        // ====================== 以下是支持httpWebsocket ======================
        
        /**
         * websocket 服務(wù)器處理的協(xié)議,用于指定給客戶端連接訪問的路由 : /ws
         * 本handler會(huì)幫你處理一些繁重的復(fù)雜的事
         * 會(huì)幫你處理握手動(dòng)作: handshaking(close, ping, pong) ping + pong = 心跳
         * 對(duì)于websocket來講,都是以frames進(jìn)行傳輸?shù)模煌臄?shù)據(jù)類型對(duì)應(yīng)的frames也不同
         */
        pipeline.addLast(new WebSocketServerProtocolHandler("/ws"));
        
        // 自定義的handler
        pipeline.addLast(new ChatHandler());
    }

}

創(chuàng)建自定義的助手類ChatHandler,用于處理消息。
TextWebSocketFrame:在netty中,是用于為websocket專門處理文本的對(duì)象,frame是消息的載體。
創(chuàng)建管道組ChannelGroup,用于管理所有客戶端的管道channel。

private static ChannelGroup clients = 
    new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);

重寫channelRead0方法,通過傳入的TextWebSocketFrame獲取客戶端傳入的內(nèi)容。通過循環(huán)的方法對(duì)ChannelGroup中所有的channel進(jìn)行回復(fù)。

@Override
protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) 
throws Exception {
    // 獲取客戶端傳輸過來的消息
    String content = msg.text();
    System.out.println("接受到的數(shù)據(jù):" + content);

//        for (Channel channel: clients) {
//            channel.writeAndFlush(
//                new TextWebSocketFrame(
//                        "[服務(wù)器在]" + LocalDateTime.now() 
//                        + "接受到消息, 消息為:" + content));
//        }
    // 下面這個(gè)方法,和上面的for循環(huán),一致
    clients.writeAndFlush(
    new TextWebSocketFrame(
            "[服務(wù)器在]" + LocalDateTime.now() 
            + "接受到消息, 消息為:" + content));

}

重寫handlerAdded方法,當(dāng)客戶端連接服務(wù)端之后(打開連接),獲取客戶端的channle,并且放到ChannelGroup中去進(jìn)行管理。

@Override
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
    clients.add(ctx.channel());
}

重寫handlerRemoved方法,當(dāng)觸發(fā)handlerRemoved,ChannelGroup會(huì)自動(dòng)移除對(duì)應(yīng)客戶端的channel。

@Override
public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
    // 當(dāng)觸發(fā)handlerRemoved,ChannelGroup會(huì)自動(dòng)移除對(duì)應(yīng)客戶端的channel
    //        clients.remove(ctx.channel());
    System.out.println("客戶端斷開,channle對(duì)應(yīng)的長id為:" 
                + ctx.channel().id().asLongText());
    System.out.println("客戶端斷開,channle對(duì)應(yīng)的短id為:" 
                            + ctx.channel().id().asShortText());
}
客戶端


    
        
        
    
    
        
        
發(fā)送消息:
接受消息:




測(cè)試

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/73252.html

相關(guān)文章

  • Netty+SpringBoot+FastDFS+Html5實(shí)現(xiàn)聊天App詳解(四)

    Netty+SpringBoot+FastDFS+Html5實(shí)現(xiàn)聊天App,項(xiàng)目介紹。Netty+SpringBoot+FastDFS+Html5實(shí)現(xiàn)聊天App,項(xiàng)目github鏈接。本章完整代碼鏈接。 本章內(nèi)容 (1) 查詢好友列表的接口 (2)通過或忽略好友請(qǐng)求的接口 (3)添加好友功能展示 查詢好友列表的接口 /** * @Description: 查詢我的好友列表 ...

    why_rookie 評(píng)論0 收藏0
  • Netty+SpringBoot+FastDFS+Html5實(shí)現(xiàn)聊天App詳解(三)

    摘要:實(shí)現(xiàn)聊天,項(xiàng)目介紹。首先根據(jù)搜索的用戶的名稱查找是否存在這個(gè)用戶。如果搜索前置條件為成功,則向前端返回搜索用戶的信息。發(fā)送添加好友的請(qǐng)求判斷不能為空查詢用戶接受到的朋友申請(qǐng)最終實(shí)現(xiàn)效果 Netty+SpringBoot+FastDFS+Html5實(shí)現(xiàn)聊天App,項(xiàng)目介紹。Netty+SpringBoot+FastDFS+Html5實(shí)現(xiàn)聊天App,項(xiàng)目github鏈接。本章完整代碼鏈接。...

    isLishude 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<