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

資訊專欄INFORMATION COLUMN

Jetty : Embedded Server 啟動流程 - 2

phpmatt / 1184人閱讀

摘要:前言本文接著啟動流程往下講,上回說到調(diào)用方法,開始接收和處理請求,默認(rèn)使用的子類,所以我們重點來看看的具體實現(xiàn)類層次,我們上文提到過,這里有兩個新面孔抽象實現(xiàn)類上文講過方法最終會調(diào)用方法,使用模板方法模式在方法中實現(xiàn)了的基本流程子類方法,

前言

本文接著 Jetty : Embedded Server 啟動流程 - 1往下講,上回說到 Server.start 調(diào)用 Connector.start 方法,開始接收和處理請求,Server 默認(rèn)使用 Connector 的子類 SelectChannelConnector,所以我們重點來看看 SelectChannelConnector 的具體實現(xiàn)

類層次
AbstractLifeCycle
    AggregateLifeCycle
        AbstractConnector
            AbstractNIOConnector
                SelectChannelConnector

AbstractLifeCycle,AggregateLifeCycle 我們上文提到過,這里有兩個新面孔:

AbstractConnector:Connector 抽象實現(xiàn)類

AbstractNIOConnector

AbstractConnector

上文講過 Server.start 方法最終會調(diào)用 Connector.start 方法,AbstractConnector 使用《模板方法》模式在 doStart 方法中實現(xiàn)了 start 的基本流程

@Override
protected void doStart() throws Exception {
    if (_server == null) {
        throw new IllegalStateException("No server");
    }
    
    // 子類 override open 方法,打開 server socket
    open();

    // 如果沒有指定 ThreadPool,默認(rèn)使用 Server 的 ThreadPool
    if (_threadPool == null) {
        _threadPool = _server.getThreadPool();
        addBean(_threadPool, false);
    }
    ...
    synchronized (this) {
        _acceptorThreads = new Thread[getAcceptors()];
        for (int i = 0; i < _acceptorThreads.length; i++) {
            // 啟動 acceptor 線程監(jiān)聽客戶端連接
            if (!_threadPool.dispatch(new Acceptor(i))) {
                throw new IllegalStateException("!accepting");
            }
            ...
        }
    }
    ...
}

幾個關(guān)鍵點:

子類通過 override(覆蓋)open 方法初始化 server socket

通過 setAcceptors 方法可以設(shè)置 acceptor 線程數(shù)量

如果沒有特殊指定,acceptor 線程 和 請求處理線程在(Server)同一個線程池里頭

Acceptor 類(實現(xiàn)了 Runnable 接口)實現(xiàn)了具體的 accept 方法

Acceptor

Acceptor 類是 AbstractConnector 類的內(nèi)部類,它在 Run 方法里頭調(diào)用 AbstractConnector.accept 方法接收客戶端連接

private class Acceptor implements Runnable {
    public void run() {
        Thread current = Thread.currentThread();
        ...
        accept(_acceptor);
        ...
    }
}

accept 方法是個抽象方法,由 AbstractConnector 的子類提供具體實現(xiàn)

SelectChannelConnector

我們重點關(guān)注和啟動流程相關(guān)的三個方法:open,doStart,accept 以及一個類 SelectorManager

open

上文提到 AbstractConnector 在 start 方法中調(diào)用 open 方法,子類 override open 方法打開 server socket

    public void open() throws IOException {
        synchronized(this) {
            if (_acceptChannel == null) {
                // Create a new server socket
                _acceptChannel = ServerSocketChannel.open();
                // Set to blocking mode,阻塞接收連接請求
                _acceptChannel.configureBlocking(true);

                // Bind the server socket to the local host and port
                _acceptChannel.socket().setReuseAddress(getReuseAddress());
                InetSocketAddress addr = getHost()==null ?
                    new InetSocketAddress(getPort()) :
                    new InetSocketAddress(getHost(), getPort());
                _acceptChannel.socket().bind(addr,getAcceptQueueSize());

                _localPort=_acceptChannel.socket().getLocalPort();
                if (_localPort<=0)
                    throw new IOException("Server channel not bound");

                addBean(_acceptChannel);
            }
        }
    }
accept
@Override
public void accept(int acceptorID) throws IOException {
    ServerSocketChannel server;
    synchronized(this) {
        server = _acceptChannel;
    }

    if (server!=null && server.isOpen() && _manager.isStarted()) {
        // 獲取客戶端 SocketChannel
        SocketChannel channel = server.accept();
        // 設(shè)置非阻塞模式(NIO)
        channel.configureBlocking(false);
        Socket socket = channel.socket();
        configure(socket);
        // 將 channel 注冊到 SelectorManager(見下文)
        _manager.register(channel);
    }
}

通過 server.accept 獲取到客戶端 SocketChannel,并將它注冊到 _manager(SelectorManager),這個 _manager 是啥?

SelectorManager

The Selector Manager manages and number of SelectSets to allow NIO Scheduling to scale to large numbers of connections
注意 SelectChannelConnector 在構(gòu)造方法里將 _manager 作為 managed bean 添加到 bean registry 里,這樣在 SelectChannelConnector 啟動(start 方法被調(diào)用)的時候 SelectManager 也會跟著啟動(參考上文)

public class SelectChannelConnector extends AbstractNIOConnector {
    private final SelectorManager _manager = new ConnectorSelectorManager();

    public SelectChannelConnector() {
        _manager.setMaxIdleTime(getMaxIdleTime());
        addBean(_manager, true);
        ...
    }
}

SelectManager doStart 方法,這里只保留方法主要邏輯

@Override
protected void doStart() throws Exception {
    _selectSet = new SelectSet[_selectSets];
    for (int i = 0; i < _select.length; i++) {
        _selectSet[i] = new SelectSet(i);
    }
    super.doStart();
    // start a thread to select
    for (int i = 0; i < getSelectSets(); i++) {
        final int id = i;
        // 提交 select runnable 到線程池
        boolean selecting = dispatch(new Runnalbe() {
            public void run() {
                ...
                LOG.debug("Starting {} on {}", Thread.currentThread(), this);
                while (isRunning()) {
                    try {
                        // 對注冊的 channel 進(jìn)行多路選擇(select)
                        set.doSelect();
                    } catch (...) {
                        ...
                    }
                }
            }
        });
    }
}

doStart 方法啟動 _selectSet 個線程監(jiān)聽 channel select 事件,我們回過頭來看 SelectManager 的 register 方法

public void register(SocketChannel acceptChannel) {
    int s=_set++;
    if (s<0) {
        s=-s;
    }
    s=s%_selectSets;
    SelectSet set=_selectSet[s];
    set.addChange(acceptChannel);
    set.wakeup();
}

acceptChannel 被均勻分配(addChange)給 SelectSet

總結(jié)

到目前為止我們總結(jié)一下:

Server 啟動 N 個 Accept 線程接收客戶端連接

Server 啟動 N 個 Select 線程對 SocketChannel 進(jìn)行多路IO選擇,每個線程執(zhí)行 SelectSet 的 doSelect 方法

Server 接收到客戶端連接后將 SocketChannel 注冊到 SelectorManager

SelectorManager 將注冊的 SocketChannel 均勻分配給各個 SelectSet,同時喚醒 Select 線程迎接新的客戶端請求

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

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

相關(guān)文章

  • Jetty : Embedded Server 啟動流程 - 1

    前言 本文基于 Jetty 8.1.x 版本簡單介紹 Jetty Embedded Server 核心概念,線程模型,啟動流程。以下代碼片段摘自 Jetty 源代碼 中的 example-jetty-embedded 模塊的 OneServletContext.java public class OneServletContext { public static void main(Str...

    everfly 評論0 收藏0
  • Spring MVC實現(xiàn)Spring Security,Spring Stomp websocket

    摘要:使用框架各個組件實現(xiàn)一個在線聊天網(wǎng)頁,當(dāng)有用戶連接,服務(wù)器監(jiān)聽到用戶連接會使用推送最新用戶列表,有用戶斷開刷新在線列表,實時推送用戶聊天信息。根據(jù)請求頭是否等于判斷是否是。 使用Spring框架各個組件實現(xiàn)一個在線聊天網(wǎng)頁,當(dāng)有用戶連接WebSocket,服務(wù)器監(jiān)聽到用戶連接會使用Stomp推送最新用戶列表,有用戶斷開刷新在線列表,實時推送用戶聊天信息。引入Jetty服務(wù)器,直接嵌入整...

    shuibo 評論0 收藏0
  • 《Spring Boot 編程思想 - 核心篇》勘誤匯總

    摘要:如果您在閱讀編程思想核心篇或示例練習(xí)的過程中發(fā)現(xiàn)了其中錯誤或提出建議,請將內(nèi)容提交至勘誤匯,小馬哥將勘誤或建議內(nèi)容匯總到此,修正后的內(nèi)容將在后續(xù)的書籍發(fā)行中體現(xiàn),并刊登勘誤貢獻(xiàn)者。筆者水平有限,行文的過程中錯誤無法避免,為此深表歉意。 如果您在閱讀《Spring Boot 編程思想 - 核心篇》或示例練習(xí)的過程中發(fā)現(xiàn)了其中錯誤或提出建議,請將內(nèi)容提交至【勘誤匯】,小馬哥將勘誤或建議內(nèi)容...

    trilever 評論0 收藏0
  • Spring Boot 2 快速教程:WebFlux 快速入門(二)

    摘要:響應(yīng)式編程是基于異步和事件驅(qū)動的非阻塞程序,只是垂直通過在內(nèi)啟動少量線程擴(kuò)展,而不是水平通過集群擴(kuò)展。三特性常用的生產(chǎn)的特性如下響應(yīng)式編程模型適用性內(nèi)嵌容器組件還有對日志消息測試及擴(kuò)展等支持。 摘要: 原創(chuàng)出處 https://www.bysocket.com 「公眾號:泥瓦匠BYSocket 」歡迎關(guān)注和轉(zhuǎn)載,保留摘要,謝謝! 02:WebFlux 快速入門實踐 文章工程: JDK...

    gaara 評論0 收藏0
  • ActiveMQ+ZooKeeper 偽集群整合

    摘要:前言本案例使用的是偽集群方式,即在一臺主機(jī)上部署個服務(wù)端口不同個服務(wù)端口不同。要想保證負(fù)載均衡得再結(jié)合部署方案,配置網(wǎng)絡(luò)連接器。編碼時,端消費者通過協(xié)議來連接集群。只需使用進(jìn)行配置即可,默認(rèn)端口為。 前言 本案例使用的是偽集群方式,即在一臺主機(jī)上部署3個activemq服務(wù)(端口不同)+3個zookeeper服務(wù)(端口不同)。 真集群部署請看:ActiveMQ+ZooKeeper集群整...

    Honwhy 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<