前言
本文基于 Jetty 8.1.x 版本簡(jiǎn)單介紹 Jetty Embedded Server 核心概念,線程模型,啟動(dòng)流程。以下代碼片段摘自 Jetty 源代碼 中的 example-jetty-embedded 模塊的 OneServletContext.java
public class OneServletContext { public static void main(String[] args) throws Exception { Server server = new Server(8080); ServletContextHandler context = new ServletContextHandler( ServletContextHandler.SESSIONS); context.setContextPath("/"); server.setHandler(context); ... // Serve some hello world servlets context.addServlet(new ServletHolder(new HelloServlet()),"/*"); context.addServlet(new ServletHolder( new HelloServlet("Buongiorno Mondo")),"/it/*"); context.addServlet(new ServletHolder( new HelloServlet("Bonjour le Monde")),"/fr/*"); server.start(); server.join(); } }
Embedded Jetty 使用起來(lái)很方便,少數(shù)幾行代碼就可以實(shí)現(xiàn)一個(gè) http (Servlet)接口
創(chuàng)建 Server 對(duì)象,設(shè)置要監(jiān)聽(tīng)的端口 8080
創(chuàng)建 ServletContextHandler 對(duì)象,ServletContextHandler "is-a" Handler(Request Handler),提供 ServletContext
將 ServletContextHandler 關(guān)聯(lián)到 Server(即 server.setHandler(context))
向 ServletContextHandler 中添加 Servlet,以 ServletHolder 的形式
啟動(dòng) Server
核心概念 LifeCycleThe lifecycle(生命周期) interface for generic components,聲明 start(啟動(dòng)),stop(停止),isRunning,isStarted(查詢(xún)狀態(tài))等方法
AbstractLifeCycle實(shí)現(xiàn) LifeCycle 接口的抽象類(lèi),提供生命周期管理默認(rèn)實(shí)現(xiàn):例如通過(guò) _state 屬性保存組件狀態(tài),提供 start,stop 默認(rèn)實(shí)現(xiàn)
public final void start() throws Exception { // 線程安全 synchronized (_lock) { try { // 狀態(tài)保護(hù) if (_state == _STARTED || _state == _STARTING) { return; } setStarting(); // 將具體的 start 邏輯推遲到具體的子類(lèi)實(shí)現(xiàn) doStart(); setStarted(); } catch (...) { ... } } }AggregateLifeCycle
An AggregateLifeCycle is an LifeCycle implementation for a collection of contained beans
AggregateLifeCycle 繼承自 AbstractLifeCycle,管理一組 Bean 的生命周期
public class AggregateLifeCycle extends AbstractLifeCycle implements Destroyable, Dumpable { private final ListServer_beans = new CopyOnWriteArrayList<>(); private boolean _started = false; @Override protected void doStart() throws Exception { for (Bean b: beans) { if (b._managed && b._bean instanceof LifeCycle) { LifeCycle l = (LefeCycle) b._bean; if (!l.isRunning()) { // start managed bean l.start(); } } } _started =true; super.doStart(); } }
類(lèi)層次
AbstractLifeCycle AggregateLifeCycle AbstractHandler AbstractHandlerContainer HandlerWrapper Server
Server 類(lèi)是 Jetty 的《門(mén)面》類(lèi),包含:
Connector,接收客戶(hù)端請(qǐng)求
Handler,處理客戶(hù)端請(qǐng)求
ThreadPool,任務(wù)調(diào)度線程池
通過(guò) Server 類(lèi)提供的各種 set 屬性方法可以定制 Connector, ThreadPool,如果沒(méi)有特殊指定 Server 類(lèi)會(huì)創(chuàng)建默認(rèn)實(shí)現(xiàn),比如默認(rèn)的 Connector 為 SelectChannelConnector,默認(rèn)的 ThreadPool 為 QueuedThreadPool
Connector(主要)類(lèi)層次:
Connector AbstractConnector AbstractNIOConnector SelectChannelConnector
Connector 接口及其實(shí)現(xiàn)類(lèi)用于 接收客戶(hù)端請(qǐng)求,(HTTP/SPDY)協(xié)議解析,最終調(diào)用 Server 中的(Request)Handler 處理請(qǐng)求,SelectChannelConnector 是 Server 默認(rèn)使用的 Connector
public Server(int port) { setServer(this); Connector connector = new SelectChannelConnector(); connector.setPort(port); setConnectors(new Connector[]{ connector }); }Handler
Handler 或者叫作 Request Handler,用于處理客戶(hù)端請(qǐng)求
public interface Handler extends LifeCycle, Destroyable { ... void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response); ... }
handle 方法的簽名已經(jīng)很接近 Servlet service 方法,這里的 target 通常是請(qǐng)求的 uri,用于根據(jù) Servlet 配置規(guī)則找到具體的 Servlet 并調(diào)用其 service 方法
線程模型Jetty Server 使用線程池來(lái)處理客戶(hù)端請(qǐng)求,ThreadPool 接口定義了線程池基本操作,Server 默認(rèn)使用 QueuedThreadPool 類(lèi),如果需要,可以通過(guò) Server.setThreadPool 方法手動(dòng)設(shè)置線程池
注:Jetty 9.x 線程模型比較復(fù)雜,Jetty 8.x 比較簡(jiǎn)單,代碼好讀一些~
QueuedThreadPool 類(lèi)層次結(jié)構(gòu)
ThreadPool SizedThreadPool QueuedThreadPool
線程池核心問(wèn)題:
線程管理:包括創(chuàng)建,銷(xiāo)毀等
任務(wù)分派:推或拉模型
線程管理通過(guò)最小線程個(gè)數(shù),最大線程個(gè)數(shù),線程最大空閑時(shí)間 來(lái)動(dòng)態(tài)創(chuàng)建,銷(xiāo)毀線程
線程池初始化// QueuedThreadPool.java public class QueuedThreadPool { // 默認(rèn)最大線程數(shù) private int _maxThreads = 254; // 默認(rèn)最小線程數(shù) private int _minThreads = 8; ... @Override protected void doStart() throws Exception { ... int threads = _threadsStarted.get(); // 啟動(dòng) _minThreads 個(gè)線程 while (isRunning() && threads < _minThreads) { startThread(threads); threads = _threadStarted.get(); } } }線程銷(xiāo)毀
當(dāng)線程空閑時(shí)間超過(guò)設(shè)定的閾值 _maxIdleTimeMs 而且線程池的線程個(gè)數(shù)高于 _minThreads 時(shí),線程將從 Runnable run 方法中退出
# QueuedThreadPool.java private Runnable _runnable = new Runnable() { public void run() { boolean shrink = false; ... try { Runnable job = _jobs.poll() while (isRunning()) { // job loop:從隊(duì)列中拉取 job 并執(zhí)行直到隊(duì)列為空 while (job != null && isRunning()) { runJob(job); job = _jobs.poll(); } // idle loop try { _threadsIdle.incrementAndGet(); while (isRunning() && job == null) { // 如果 _maxIdleTimeMs < 0 就進(jìn)入阻塞模式,直到成功拉取到 job if (_maxIdleTimeMs <= 0) { job = _jobs.take(); } else { final int size = _threadsStarted.get(); // 如果線程個(gè)數(shù)少于 _minThreads 那么不需要回收線程 if (size > _minThreads) { long last = _lastShrink.get(); long now = System.currentTimeMillis(); if (last == 0 || (now - last) > _maxIdleTimeMs) { shrink = _lastShrink.compareAndSet(last, now) && _threadsStarted.compareAndSet(size, size - 1); if (shringk) { // 退出 while 循環(huán),即終止線程 return; } } } // 帶 timeout 的 poll job = idleJobPoll(); } } } } } catch (...) { } finally { } } }任務(wù)分派
使用阻塞隊(duì)列,工作線程從阻塞隊(duì)列中主動(dòng)拉?。╬oll)任務(wù)(job),QueuedThreadPool 默認(rèn)使用 ArrayBlockingQueue,如果需要可以通過(guò)構(gòu)造方法手動(dòng)指定阻塞隊(duì)列的具體實(shí)現(xiàn)
public class QueuedThreadPool { public QueuedThreadPool(BlockingQueue啟動(dòng)流程jobQ) { this(); _jobs = jobQ; _jobs.clear(); } public boolean dispatch(Runnable job) { if (isRunning()) { final int jobQ = _jobs.size(); final int idle = getIdleThreads(); // 將 job 放入隊(duì)列中 if (_jobs.offer(job)) { // 如果當(dāng)前沒(méi)有 idle 的線程,或者 隊(duì)列中堆積的 job 比 idle 線程多那么嘗試啟動(dòng)新的線程 if (idle == 0 || jobQ > idle) { int threads = _threadsStarted.get(); if (threads < _maxThreads) { startThread(threads); } } return true; } } return false; } }
Server 的啟動(dòng)開(kāi)始于 start 方法的調(diào)用,如上文所述,Server 類(lèi)繼承自 AggregateServer,父類(lèi)的 start 方法最終調(diào)用 Server 的 doStart 方法
Server start@Override protected void doStart() throws Exception { ... // 創(chuàng)建默認(rèn)的 ThreadPool if (_threadPool == null) { setThreadPool(new QueuedThreadPool()) } try { super.doStart(); } catch(Throwable e) {...} // 啟動(dòng) Connector,接收,處理請(qǐng)求 if (_connectors != null && mex.size == 0) { for (int i = 0; i < _connectors.length; i++) { try { _connectors[i].start(); } catch (Throwable e) { mex.add(e); } } } ... }
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/71172.html
摘要:前言本文接著啟動(dòng)流程往下講,上回說(shuō)到調(diào)用方法,開(kāi)始接收和處理請(qǐng)求,默認(rèn)使用的子類(lèi),所以我們重點(diǎn)來(lái)看看的具體實(shí)現(xiàn)類(lèi)層次,我們上文提到過(guò),這里有兩個(gè)新面孔抽象實(shí)現(xiàn)類(lèi)上文講過(guò)方法最終會(huì)調(diào)用方法,使用模板方法模式在方法中實(shí)現(xiàn)了的基本流程子類(lèi)方法, 前言 本文接著 Jetty : Embedded Server 啟動(dòng)流程 - 1往下講,上回說(shuō)到 Server.start 調(diào)用 Connector...
摘要:使用框架各個(gè)組件實(shí)現(xiàn)一個(gè)在線聊天網(wǎng)頁(yè),當(dāng)有用戶(hù)連接,服務(wù)器監(jiān)聽(tīng)到用戶(hù)連接會(huì)使用推送最新用戶(hù)列表,有用戶(hù)斷開(kāi)刷新在線列表,實(shí)時(shí)推送用戶(hù)聊天信息。根據(jù)請(qǐng)求頭是否等于判斷是否是。 使用Spring框架各個(gè)組件實(shí)現(xiàn)一個(gè)在線聊天網(wǎng)頁(yè),當(dāng)有用戶(hù)連接WebSocket,服務(wù)器監(jiān)聽(tīng)到用戶(hù)連接會(huì)使用Stomp推送最新用戶(hù)列表,有用戶(hù)斷開(kāi)刷新在線列表,實(shí)時(shí)推送用戶(hù)聊天信息。引入Jetty服務(wù)器,直接嵌入整...
摘要:如果您在閱讀編程思想核心篇或示例練習(xí)的過(guò)程中發(fā)現(xiàn)了其中錯(cuò)誤或提出建議,請(qǐng)將內(nèi)容提交至勘誤匯,小馬哥將勘誤或建議內(nèi)容匯總到此,修正后的內(nèi)容將在后續(xù)的書(shū)籍發(fā)行中體現(xiàn),并刊登勘誤貢獻(xiàn)者。筆者水平有限,行文的過(guò)程中錯(cuò)誤無(wú)法避免,為此深表歉意。 如果您在閱讀《Spring Boot 編程思想 - 核心篇》或示例練習(xí)的過(guò)程中發(fā)現(xiàn)了其中錯(cuò)誤或提出建議,請(qǐng)將內(nèi)容提交至【勘誤匯】,小馬哥將勘誤或建議內(nèi)容...
摘要:響應(yīng)式編程是基于異步和事件驅(qū)動(dòng)的非阻塞程序,只是垂直通過(guò)在內(nèi)啟動(dòng)少量線程擴(kuò)展,而不是水平通過(guò)集群擴(kuò)展。三特性常用的生產(chǎn)的特性如下響應(yīng)式編程模型適用性?xún)?nèi)嵌容器組件還有對(duì)日志消息測(cè)試及擴(kuò)展等支持。 摘要: 原創(chuàng)出處 https://www.bysocket.com 「公眾號(hào):泥瓦匠BYSocket 」歡迎關(guān)注和轉(zhuǎn)載,保留摘要,謝謝! 02:WebFlux 快速入門(mén)實(shí)踐 文章工程: JDK...
摘要:實(shí)現(xiàn)為,即模式上一個(gè)依賴(lài)于下一個(gè)的調(diào)用,比如常見(jiàn)的就是這種模式。啟動(dòng)實(shí)例化和設(shè)置運(yùn)行時(shí)處理流程通常會(huì)實(shí)例化一個(gè),注意的構(gòu)造方法最終會(huì)調(diào)用依次將構(gòu)成責(zé)任鏈因?yàn)檫@個(gè)連同都是類(lèi)型。內(nèi)部所有等執(zhí)行即。 showImg(https://segmentfault.com/img/bV3OIg?w=326&h=314); showImg(https://segmentfault.com/img/bV...
閱讀 1715·2021-09-22 15:52
閱讀 3576·2021-09-22 14:59
閱讀 3000·2021-09-02 15:12
閱讀 1112·2021-08-20 09:35
閱讀 1652·2019-08-30 14:09
閱讀 2777·2019-08-30 13:56
閱讀 1755·2019-08-26 18:27
閱讀 3445·2019-08-26 13:37