成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

Netty3文檔翻譯(一)

sherlock221 / 935人閱讀

摘要:但是它不是自己創(chuàng)建線程,而是從調(diào)用構(gòu)造方法時(shí)指定的線程池中獲取線程。這就意味著,即使發(fā)送兩個(gè)獨(dú)立的消息,操作系統(tǒng)會(huì)把他們視為一個(gè)字節(jié)串。釋放過程很簡單,調(diào)用它的方法,所有相關(guān)的和線程池將會(huì)自動(dòng)關(guān)閉。

簡單找了下發(fā)現(xiàn)網(wǎng)上沒有關(guān)于Netty3比較完整的源碼解析的文章,于是我就去讀官方文檔,為了加強(qiáng)記憶,翻譯成了中文,有適當(dāng)?shù)暮喕?/p>

原文檔地址:Netty3文檔

Chapter 1 開始 1、開始之前

運(yùn)行demo的前提有兩個(gè):最新版本的Netty3和JDK1.5以上

2、寫一個(gè)Discard Server

最簡單的協(xié)議就是Discard協(xié)議——忽略所有接收到的數(shù)據(jù)并且不作任何響應(yīng)。我們從Netty處理I/O事件的handler實(shí)現(xiàn)開始:

public class DiscardServerHandler extends SimpleChannelHandler {

    @Override
    public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
        
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {

        e.getCause().printStackTrace();

        Channel ch = e.getChannel();
        ch.close();
    }
}

DiscardServerHandler 繼承SimpleChannelHandler——ChannelHandler的一個(gè)實(shí)現(xiàn);

messageReceived方法接收MessageEvent類型的參數(shù),它包含接收的客戶端數(shù)據(jù);

exceptionCaught方法在出現(xiàn)I/O錯(cuò)誤或者處理事件時(shí)拋出錯(cuò)誤時(shí)被調(diào)用,通常包含記錄錯(cuò)誤信息和關(guān)閉通道的動(dòng)作;

接下來寫一個(gè)main方法來開啟使用DiscardServerHandler的服務(wù):

public class DiscardServer {
    
    public static void main(String[] args) throws Exception {
        ChannelFactory factory =
                new NioServerSocketChannelFactory(
                        Executors.newCachedThreadPool(),
                        Executors.newCachedThreadPool());

        ServerBootstrap bootstrap = new ServerBootstrap(factory);

        bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
            public ChannelPipeline getPipeline() {
                return Channels.pipeline(new DiscardServerHandler());
            }
        });
        
        bootstrap.setOption("child.tcpNoDelay", true);
        bootstrap.setOption("child.keepAlive", true);

        bootstrap.bind(new InetSocketAddress(8080));
    }
}

ChannelFactory是創(chuàng)建和管理Channel及其關(guān)聯(lián)資源的工廠,它負(fù)責(zé)處理所有I/O請求并且執(zhí)行I/O生成ChannelEvent。但是它不是自己創(chuàng)建I/O線程,而是從調(diào)用構(gòu)造方法時(shí)指定的線程池中獲取線程。服務(wù)端應(yīng)用使用NioServerSocketChannelFactory;

ServerBootstrap是一個(gè)設(shè)置服務(wù)端的幫助類;

當(dāng)服務(wù)端接收到一個(gè)新的連接,指定的ChannelPipelineFactory就會(huì)創(chuàng)建一個(gè)新的ChannelPipeline,這個(gè)新的Pipeline包含一個(gè)DiscardServerHandler對象;

你可以給Channel實(shí)現(xiàn)設(shè)置具體的參數(shù),選項(xiàng)帶"child."前綴代表應(yīng)用在接收到的Channel上而不是服務(wù)端本身的ServerSocketChannel;

剩下的就是綁定端口啟動(dòng)服務(wù),可以綁定多個(gè)不同的端口。

3、處理接收到的數(shù)據(jù)

我們可以通過"telnet localhost 8080"命令去測試服務(wù),但因?yàn)槭荄iscard服務(wù),我們都不知道服務(wù)是否正常工作。所以我們修改下服務(wù),讓它打印出接收到的數(shù)據(jù)。

@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
    ChannelBuffer buf = (ChannelBuffer) e.getMessage();
    while(buf.readable()) {
        System.out.println((char) buf.readByte());
        System.out.flush();
    }
}

ChannelBuffer是Netty基本的存儲(chǔ)字節(jié)的數(shù)據(jù)結(jié)構(gòu),跟NIO的ByteBuffer類似,但是更容易使用更靈活。比如Netty允許你在盡量少的內(nèi)存復(fù)制次數(shù)的情況下把多個(gè)ChannelBuffer組合成一個(gè)。

4、寫一個(gè)Echo服務(wù)

一個(gè)服務(wù)通常對請求是有響應(yīng)的。接下來我們嘗試寫一個(gè)實(shí)現(xiàn)Echo協(xié)議——將接收的數(shù)據(jù)原路返回給客戶端的服務(wù):

@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
    Channel ch = e.getChannel();
    ch.write(e.getMessage());
}

MessageEvent繼承了ChannnelEvent,一個(gè)ChannnelEvent持有它相關(guān)的Channel的引用。我們可以獲取這個(gè)Channel然后調(diào)用寫方法寫入數(shù)據(jù)返回給客戶端。

5、寫一個(gè)時(shí)間服務(wù)

這次我們實(shí)現(xiàn)一個(gè)時(shí)間協(xié)議——在不需要任何請求數(shù)據(jù)的情況下返回一個(gè)32位整型數(shù)字并且在發(fā)送之后關(guān)閉連接。因?yàn)槲覀兒雎哉埱髷?shù)據(jù),只需要在連接建立的發(fā)送消息,所以這次不能使用messageReceived方法而是重寫channelConnected方法:

@Override
public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) {
    Channel ch = e.getChannel();

    ChannelBuffer time = ChannelBuffers.buffer(4);
    time.writeInt((int) (System.currentTimeMillis() / 1000L + 2208988800L));

    ChannelFuture f = ch.write(time);

    f.addListener(new ChannelFutureListener() {
        public void operationComplete(ChannelFuture future) {
            Channel ch = future.getChannel();
            ch.close();
        }
    });
}

channelConnected方法在連接建立的時(shí)間被調(diào)用,然后我們寫入一個(gè)32位整型數(shù)字代表以秒為單位的當(dāng)前時(shí)間;

我們使用ChannelBuffers工具類分配了一個(gè)容量為4字節(jié)的ChannelBuffer來存放這個(gè)32位整型數(shù)字;

然后我們把ChannelBuffer寫入Channel...等一下,flip方法哪里去了?在NIO中我們不是要在寫入通道前調(diào)用ByteBuffer的flip方法的嗎?ChannelBuffer沒有這個(gè)方法,因?yàn)樗袃蓚€(gè)指針,一個(gè)用于讀操作一個(gè)用于寫操作。當(dāng)數(shù)據(jù)寫入ChannelBuffer時(shí)寫索引增加而讀索引不變。讀索引和寫索引相互獨(dú)立。對比之下,Netty的ChannelBuffer比NIO的buffer更容易使用。

另外需要注意的一點(diǎn)是ChannelBuffer的write方法返回的是一個(gè)ChannelFuture對象。它表示一個(gè)還未發(fā)生的I/O操作,因?yàn)镹etty中所有操作都是異步的。所以我們必須在ChannelFuture收到操作完成的通知之后才能關(guān)閉Channel。哦,對了,close方法也是返回ChannelFuture...

那么問題來了,我們?nèi)绾蔚玫讲僮魍瓿傻耐ㄖ??只需要簡單得向返回的ChannelFuture對象中添加一個(gè)ChannelFutureListener,這里我們創(chuàng)建了一個(gè)ChannelFutureListener的匿名內(nèi)部類,它在操作完成的時(shí)候會(huì)關(guān)閉Channel。

6、寫一個(gè)時(shí)間客戶端

我們還需要一個(gè)遵守時(shí)間協(xié)議,即能把整型數(shù)字翻譯成日期的客戶端。Netty服務(wù)端和客戶端唯一的區(qū)別就是要求不同的Bootstrap和ChannelFactory:

public static void main(String[] args) throws Exception {
    String host = args[0];
    int port = Integer.parseInt(args[1]);

    ChannelFactory factory =
            new NioClientSocketChannelFactory(
                    Executors.newCachedThreadPool(),
                    Executors.newCachedThreadPool());

    ClientBootstrap bootstrap = new ClientBootstrap(factory);

    bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
        public ChannelPipeline getPipeline() {
            return Channels.pipeline(new TimeClientHandler());
        }
    });

    bootstrap.setOption("tcpNoDelay", true);
    bootstrap.setOption("keepAlive", true);

    bootstrap.connect(new InetSocketAddress(host, port));
}

NioClientSocketChannelFactory,用來創(chuàng)建一個(gè)客戶端Channel;

ClientBootstrap是ServerBootStrap在客戶端的對應(yīng)部分;

需要注意的是設(shè)置參數(shù)時(shí)不需要"child."前綴,客戶端SocketChannel沒有父Channel;

對應(yīng)服務(wù)端的bind方法,這里我們需要調(diào)用connect方法。

另外我們需要一個(gè)ChannelHandler實(shí)現(xiàn),負(fù)責(zé)把接收到服務(wù)端返回的32位整型數(shù)字翻譯成日期并打印出來,然后斷開連接:

public class TimeClientHandler extends SimpleChannelHandler {

    @Override
    public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
        ChannelBuffer buf = (ChannelBuffer) e.getMessage();
        long currentTimeMillis = buf.readInt() * 1000L;
        System.out.println(new Date(currentTimeMillis));
        e.getChannel().close();
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
        e.getCause().printStackTrace();
        e.getChannel().close();
    }
}

看上去很簡單是吧?但是實(shí)際運(yùn)行過程中這個(gè)handler有時(shí)會(huì)拋出一個(gè)IndexOutOfBoundsException。下一節(jié)我們會(huì)討論為什么會(huì)這樣。

7、處理基于流的傳輸 7.1、一個(gè)關(guān)于Socket Buffer的小警告

在像TCP/IP那樣基于流的傳輸中,接收數(shù)據(jù)保存在一個(gè)socket接收緩存中。但是這個(gè)緩存不是一個(gè)以包為單位的隊(duì)列,而是一個(gè)以字節(jié)為單位的隊(duì)列。這就意味著,即使發(fā)送兩個(gè)獨(dú)立的消息,操作系統(tǒng)會(huì)把他們視為一個(gè)字節(jié)串。因此,不能保證你讀到的和另一端寫入的一樣。所以,不管是客戶端還是服務(wù)端,對于接收到的數(shù)據(jù)都需要整理成符合應(yīng)用程序邏輯的結(jié)構(gòu)。

7.2、第一種解決方式

回到前面的時(shí)間客戶端的問題,32位整型數(shù)字很小,但是它也是可以拆分的,特別是當(dāng)流量上升的時(shí)候,被拆分的可能性也隨之上升。
一個(gè)簡單的處理方式就是內(nèi)部創(chuàng)建一個(gè)累計(jì)的緩存,直到接收滿4個(gè)字節(jié)才進(jìn)行處理。

private final ChannelBuffer buf = dynamicBuffer();

@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
    ChannelBuffer m = (ChannelBuffer) e.getMessage();
    buf.writeBytes(m);
    if (buf.readableBytes() >= 4) {
        long currentTimeMillis = buf.readInt() * 1000L;
        System.out.println(new Date(currentTimeMillis));
        e.getChannel().close();
    }
}

ChannelBuffers.dynamicBuffer()返回一個(gè)自動(dòng)擴(kuò)容的ChannelBuffer;

所有接收的數(shù)據(jù)都累積到這個(gè)動(dòng)態(tài)緩存中;

handler需要檢查緩存是否滿4個(gè)字節(jié),是的話才能繼續(xù)業(yè)務(wù)邏輯;否則,Netty會(huì)在數(shù)據(jù)繼續(xù)到達(dá)之后持續(xù)調(diào)用messageReceive。

7.3、第二種解決方案

第一種方案有很多問題,比如一個(gè)復(fù)雜的協(xié)議,由多個(gè)可變長度的域組成,這種情況下第一種方案的handler就無法支持了。
你會(huì)發(fā)現(xiàn)你可以添加多個(gè)ChannelHandler到ChannelPipeline中,利用這個(gè)特性,你可以把一個(gè)臃腫的ChannelHandler拆分到多個(gè)模塊化的ChannelHandler中,這樣可以降低應(yīng)用程序的復(fù)雜度。比如,你可以把TimeClientHandler拆分成兩個(gè)handler:

TimeDecoder,負(fù)責(zé)分段問題;

最初那個(gè)簡版的TimeClientHandler.

Netty提供了可擴(kuò)展的類幫助你實(shí)現(xiàn)TimeDecoder:

public class TimeDecoder extends FrameDecoder {

    @Override
    protected Object decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) {

        if (buffer.readableBytes() < 4) {
            return null;
        }

        return buffer.readBytes(4);
    }
}

FrameDecoder是ChannelHandler的一種實(shí)現(xiàn),專門用來處理分段問題;

FrameDecoder在每次接收到新的數(shù)據(jù)時(shí)調(diào)用decode方法,攜帶一個(gè)內(nèi)部維持的累積緩存;

如果返回null,說明目前數(shù)據(jù)接收的還不夠,當(dāng)數(shù)據(jù)量足夠時(shí)FrameDecoder會(huì)再次調(diào)用方法;

如果返回非null對象,代表解碼成功,F(xiàn)rameDecoder會(huì)丟棄累積緩存中剩余的數(shù)據(jù)。你無需提供批量解碼,F(xiàn)rameDecoder會(huì)繼續(xù)調(diào)用decode方法直到返回null。

拆分之后,我們需要修改TimeClient的ChannelPipelineFactory實(shí)現(xiàn):

bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
    public ChannelPipeline getPipeline() {
        return Channels.pipeline(
                new TimeDecoder(),
                new TimeClientHandler());
    }
});

Netty還提供了進(jìn)一步簡化解碼的ReplayingDecoder:

public class TimeDecoder extends ReplayingDecoder {
    @Override
    protected Object decode(
            ChannelHandlerContext ctx, Channel channel,
            ChannelBuffer buffer, VoidEnum state) {
        return buffer.readBytes(4);
    }
 }

此外,Netty提供了一批開箱即用的解碼器,讓你可以簡單得實(shí)現(xiàn)大多數(shù)協(xié)議:

org.jboss.netty.example.factorial 用于二進(jìn)制協(xié)議;

org.jboss.netty.example.telnet 用于基于行的文本協(xié)議.

8、用POJO替代ChannelBuffer

上面的demo我們都是用ChannelBuffer作為協(xié)議化消息的基本數(shù)據(jù)結(jié)構(gòu),這一節(jié)我們用POJO替代ChannelBuffer。將從ChannelBuffer提取信息的代碼跟handler分離開,會(huì)使handler變得更加可維護(hù)的和可重用的。從上面的demo里不容易看出這個(gè)優(yōu)勢,但是實(shí)際應(yīng)用中分離很有必要。
首先,我們定義一個(gè)類型UnixTime:

public class UnixTime {

    private final int value;

    public UnixTime(int value) {
        this.value = value;
    }

    public int getValue() {
        return value;
    }

    @Override
    public String toString() {
        return new Date(value * 1000L).toString();
    }
}

現(xiàn)在我們可以修改TimeDecoder讓它返回一個(gè)UnixTime而不是ChannelBuffer:

@Override
protected Object decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) {

    if (buffer.readableBytes() < 4) {
        return null;
    }

    return new UnixTime(buffer.readInt());
}

編碼器改了,那么相應(yīng)的TimeClientHandler就不會(huì)繼續(xù)使用ChannelBuffer:

@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
    UnixTime m = (UnixTime) e.getMessage();
    System.out.println(m);
    e.getChannel().close();
}

同樣的技術(shù)也可以應(yīng)用到服務(wù)端的TimeServerHandler上:

@Override
public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) {
    UnixTime time = new UnixTime((int)(System.currentTimeMillis() / 1000));
    ChannelFuture f = e.getChannel().write(time);
    f.addListener(ChannelFutureListener.CLOSE);
}

能這樣運(yùn)用的前提是有一個(gè)編碼器,可以把UnixTime對象翻譯成ChannelBuffer:

public class TimeEncoder extends SimpleChannelHandler {

    public void writeRequested(ChannelHandlerContext ctx, MessageEvent e) {
        UnixTime time = (UnixTime) e.getMessage();
        ChannelBuffer buf = buffer(4);
        buf.writeInt(time.getValue());
        Channels.write(ctx, e.getFuture(), buf);
    }
}

一個(gè)編碼器重寫writeRequested方法攔截一個(gè)寫請求。這里需要注意的一點(diǎn)是,盡管這里的writeRequested方法參數(shù)里也有一個(gè)MessageEvent對象,客戶端TimeClientHandler的messageReceived的參數(shù)里也有一個(gè),但是它們的解讀是完全不同的。一個(gè)ChannelEvent可以是upstream也可以是downstream事件,這取決于事件的流向。messageReceived方法里的MessageEvent是一個(gè)upstream事件,而writeRequested方法里的是downstream事件。

當(dāng)把POJO類轉(zhuǎn)化為ChannelBuffer后,你需要把ChannelBuffer轉(zhuǎn)發(fā)到之前在ChannelPipeline內(nèi)的ChannelDownstreamHandler,也就是TimeServerHandler。Channels提供了多個(gè)幫助方法創(chuàng)建和發(fā)送ChanenlEvent。

同樣,TimeEncoder也需要加入到服務(wù)端的ChannelPipeline中:

bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
    public ChannelPipeline getPipeline() {
        return Channels.pipeline(
                new TimeServerHandler(),
                new TimeEncoder());
    }
});
9、關(guān)閉你的應(yīng)用程序

為了關(guān)閉I/O線程讓應(yīng)用程序優(yōu)雅得退出,我們需要釋放ChannelFactory分配的資源。
一個(gè)典型網(wǎng)絡(luò)應(yīng)用程序的關(guān)閉過程分為三步:

關(guān)閉所有服務(wù)端socket連接;

關(guān)閉所有非服務(wù)端socket連接(包括客戶端socket和服務(wù)端接收到的socket);

釋放ChannelFactory使用的所有資源。

應(yīng)用到TimeClient上:

ChannelFuture future = bootstrap.connect(...);
future.awaitUninterruptibly();
if (!future.isSuccess()) {
    future.getCause().printStackTrace();
}
future.getChannel().getCloseFuture().awaitUninterruptibly();
factory.releaseExternalResources();

CilentBootStrap的connect方法返回一個(gè)ChannelFuture,當(dāng)連接嘗試成功或者失敗時(shí)會(huì)通知到ChannelFuture。它還持有連接嘗試關(guān)聯(lián)的Channel的引用;

ChannelFuture.awaitUninterruptibly()等待ChannelFuture確定連接是否嘗試成功;

如果連接失敗,我們打印出失敗的原因。ChannelFuture.getCause()會(huì)在連接即沒有成功也沒有取消的情況下返回失敗的原因;

連接嘗試的情況處理之后,我們還需要等待連接關(guān)閉。每個(gè)Channel有它自己的closeFuture,用來通知你連接關(guān)閉然后你可以針對關(guān)閉做一些動(dòng)作。即使連接嘗試失敗了,closeFuture仍然會(huì)被通知,因?yàn)镃hannel會(huì)在連接失敗后自動(dòng)關(guān)閉;

所有連接關(guān)閉之后,剩下的就是釋放ChannelFactory使用的資源了。釋放過程很簡單,調(diào)用它的releaseExternalResources方法,所有相關(guān)的NIO Selector和線程池將會(huì)自動(dòng)關(guān)閉。

關(guān)閉一個(gè)客戶端很簡單,那服務(wù)端呢?你需要從端口解綁并關(guān)閉所有接收到的連接。前提是你需要一個(gè)保持跟蹤活躍連接的數(shù)據(jù)結(jié)構(gòu),Netty提供了ChannelGroup。

ChannelGroup是Java集合API一個(gè)特殊的的擴(kuò)展,它代表一組打開的Channel。如果一個(gè)Channel被添加到ChannelGroup,然后這個(gè)Channel被關(guān)閉了,它會(huì)從ChannelGroup中自動(dòng)移除。你可以對同一ChannelGroup中的Channel做批量操作,比如在關(guān)閉服務(wù)的時(shí)候關(guān)閉所有Channel。

要跟蹤打開的socket,你需要修改TimeServerHandler,把新打開的Channel添加到全局的ChannelGroup變量中。ChannelGroup是線程安全的。

@Override
public void channelOpen(ChannelHandlerContext ctx, ChannelStateEvent e) {
    TimeServer.allChannels.add(e.getChannel());
}

現(xiàn)在我們自動(dòng)維持了一個(gè)包含所有活躍Channel的列表,關(guān)閉服務(wù)端就像關(guān)閉客戶端一樣容易了。

public class TimeServer {
    static final ChannelGroup allChannels = new DefaultChannelGroup("time-server");

    public static void main(String[] args) throws Exception {
        ...
        ChannelFactory factory = ...;
        ...
        ServerBootstrap bootstrap = ...;
        ...
        Channel channel = bootstrap.bind(new InetSocketAddress(8080));
        allChannels.add(channel);
        waitForShutdownCommand();
        ChannelGroupFuture future = allChannels.close();
        future.awaitUninterruptibly();
        factory.releaseExternalResources();
    }
}

DefaultChannelGroup構(gòu)造方法接收組名為參數(shù),組名是它的唯一標(biāo)識(shí);

ServerBootstrap的bind方法返回一個(gè)服務(wù)端的綁定指定本地地址的Channel,調(diào)用Channel的close方法將會(huì)使它與本地地址解綁;

所有Channel類型都可以被添加到ChannelGroup中,不管是客戶端、服務(wù)端或是服務(wù)端接收的。因?yàn)槟憧梢栽诜?wù)器關(guān)閉時(shí)同時(shí)關(guān)閉綁定的Channel和接收到的Channel;

waitForShutdownCommand()是一個(gè)等待關(guān)閉信號的虛構(gòu)方法。

我們可以對ChannelGroup中的Channel進(jìn)行統(tǒng)一操作,這里我們調(diào)用close方法,相當(dāng)于解綁服務(wù)端Channel并且異步關(guān)閉所有接收到的Channel。close方法返回一個(gè)功能和ChannelFuture相近的ChannelGroupFuture,在所有連接都成功關(guān)閉通知我們。

10、總結(jié)

這一節(jié)我們快速瀏覽了Netty,示范了如何用Netty寫一個(gè)能正常工作的網(wǎng)絡(luò)應(yīng)用。
下一節(jié)將介紹Netty的更多細(xì)節(jié)。

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

轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/74215.html

相關(guān)文章

  • Netty3文檔翻譯(二)

    摘要:豐富的緩存數(shù)據(jù)結(jié)構(gòu)使用它自己的緩存來表示字節(jié)序列而不是的。針對有一個(gè)定義良好的事件模型。有一些協(xié)議是多層的建立在其他低級協(xié)議基礎(chǔ)上。此外,甚至不是完全線程安全的。協(xié)議由標(biāo)準(zhǔn)化為。協(xié)議緩存整合是一個(gè)高效二進(jìn)制協(xié)議的快速實(shí)現(xiàn)。 Chapter 2、結(jié)構(gòu)概覽 這一節(jié)我們將確認(rèn)Netty提供的核心功能是什么,以及它們怎么構(gòu)成一個(gè)完整的網(wǎng)絡(luò)應(yīng)用開發(fā)堆棧。 1、豐富的緩存數(shù)據(jù)結(jié)構(gòu) Netty使用它...

    Zhuxy 評論0 收藏0
  • 少啰嗦!分鐘帶你讀懂Java的NIO和經(jīng)典IO的區(qū)別

    摘要:的選擇器允許單個(gè)線程監(jiān)視多個(gè)輸入通道。一旦執(zhí)行的線程已經(jīng)超過讀取代碼中的某個(gè)數(shù)據(jù)片段,該線程就不會(huì)在數(shù)據(jù)中向后移動(dòng)通常不會(huì)。 1、引言 很多初涉網(wǎng)絡(luò)編程的程序員,在研究Java NIO(即異步IO)和經(jīng)典IO(也就是常說的阻塞式IO)的API時(shí),很快就會(huì)發(fā)現(xiàn)一個(gè)問題:我什么時(shí)候應(yīng)該使用經(jīng)典IO,什么時(shí)候應(yīng)該使用NIO? 在本文中,將嘗試用簡明扼要的文字,闡明Java NIO和經(jīng)典IO之...

    Meils 評論0 收藏0
  • dubbo源碼解析()Hello,Dubbo

    摘要:英文全名為,也叫遠(yuǎn)程過程調(diào)用,其實(shí)就是一個(gè)計(jì)算機(jī)通信協(xié)議,它是一種通過網(wǎng)絡(luò)從遠(yuǎn)程計(jì)算機(jī)程序上請求服務(wù)而不需要了解底層網(wǎng)絡(luò)技術(shù)的協(xié)議。 Hello,Dubbo 你好,dubbo,初次見面,我想和你交個(gè)朋友。 Dubbo你到底是什么? 先給出一套官方的說法:Apache Dubbo是一款高性能、輕量級基于Java的RPC開源框架。 那么什么是RPC? 文檔地址:http://dubbo.a...

    evin2016 評論0 收藏0
  • HashedWheelTimer算法詳解

    摘要:算法序和年的論文提出了一種定時(shí)輪的方式來管理和維護(hù)大量的調(diào)度算法內(nèi)核中的定時(shí)器采用的就是這個(gè)方案。使用實(shí)例每一次的時(shí)間間隔每一次就會(huì)到達(dá)下一個(gè)槽位輪中的數(shù)源碼解讀之時(shí)間輪算法實(shí)現(xiàn)定時(shí)輪算法細(xì)說延時(shí)任務(wù)的處理定時(shí)器的實(shí)現(xiàn) HashedWheelTimer算法 序 George Varghese 和 Tony Lauck 1996 年的論文:Hashed and Hierarchical ...

    aervon 評論0 收藏0

發(fā)表評論

0條評論

閱讀需要支付1元查看
<