Jetty:Embedded Server起動プロセス-1
前言
本稿はJetty 8.1に基づく.xバージョンでは、Jetty Embedded Serverのコアコンセプト、スレッドモデル、起動プロセスについて簡単に説明します.次のコードクリップは、Jettyソースコードのexample-jetty-embeddedモジュールのOneServeretContextから抜粋されています.java
Embedded Jettyは使いやすく、数行のコードでhttp(サーブレット)インタフェースを実現できます.サーバオブジェクトを作成し、リスニングするポート8080 を設定します.サーブレットContextHandlerオブジェクト、サーブレットContextHandler"is-a"Handler(Request Handler)、サーブレットContext を作成するサーブレットContextHandlerをサーバ(server.setHandler) に関連付けるサーブレットContextHandlerにサーブレットを追加し、サーブレットHolderとして .サーバ を起動
コアコンセプト
LifeCycle
The lifecycle(ライフサイクル)interface for generic components、start(起動)、stop(停止)、isRunning、isStarted(クエリーステータス)の宣言などの方法
AbstractLifeCycle
LifeCycleインタフェースの抽象クラスを実装し、ライフサイクル管理のデフォルト実装を提供します.たとえば、_stateプロパティはコンポーネントステータスを保存し、start、stopのデフォルト実装を提供します.
AggregateLifeCycle
An AggregateLifeCycle is an LifeCycle implementation for a collection of contained beans AggregateLifeCycle AbstractLifeCycleから継承され、Beanのライフサイクルのセットを管理
Server
クラス階層
ServerクラスはJettyの「顔」クラスで、以下を含む.コネクタ、クライアント要求 を受信 Handler、クライアント要求 を処理する ThreadPool、タスクスケジューリングスレッドプール Serverクラスが提供する様々なset属性方法でConnector、ThreadPoolをカスタマイズできます.特に指定されていない場合、デフォルトのConnectorがSelectChannelConnector、デフォルトのThreadPoolがQueuedThreadPoolなどのデフォルトインプリメンテーションが作成されます.
Connector
(主な)クラス階層:
Connectorインタフェースとその実装クラスはクライアント要求を受信するために使用され、(HTTP/PDY)プロトコルは解析し、最終的にサーバの(Request)Handler処理要求を呼び出し、SelectChannelConnectorはサーバのデフォルトで使用されるConnectorである
Handler
クライアント要求を処理するためにHandlerまたはRequest Handlerと呼ばれる
handleメソッドの署名はすでにサーブレットサービスメソッドに近い.ここでtargetは通常、サーブレット構成ルールに基づいて特定のサーブレットを見つけてサービスメソッドを呼び出すために要求されたuriである.
スレッドモデル
Jetty Serverはスレッドプールを使用してクライアント要求を処理し、ThreadPoolインタフェースはスレッドプールの基本操作を定義し、ServerはデフォルトでQueuedThreadPoolクラスを使用し、必要に応じてServerを使用することができる.setThreadPoolメソッドスレッドプールの手動設定注意:Jetty 9.x線モデルは複雑だJetty 8.x比較的簡単で、コードが読みやすい~
QueuedThreadPool
QueuedThreadPoolクラス階層
スレッドプールのコア問題:スレッド管理:作成、破棄など を含むタスク割当:モデル をプッシュまたはプル
スレッド管理
最小スレッド数、最大スレッド数、スレッド最大アイドル時間による動的作成、スレッド破棄
スレッドプールの初期化
スレッド破棄
スレッドアイドル時間が設定したしきい値を超えるとmaxIdleTimeMs、スレッドプールのスレッド数が_より高いminThreadsの場合、スレッドはRunnable runメソッドから終了します.
タスクの割り当て
ブロックされたキューを使用すると、ワークスレッドはブロックされたキューからアクティブにタスク(job)を引き出し、QueuedThreadPoolはデフォルトでArrayBlockingQueueを使用します.必要に応じて、ブロックされたキューの具体的な実装を構築方法で手動で指定できます.
プロセスの開始
サーバの起動はstartメソッドの呼び出しから始まります.前述したように、サーバクラスはAggregateServerから継承され、親クラスのstartメソッドは最終的にサーバのdoStartメソッドを呼び出します.
Server start
本稿はJetty 8.1に基づく.xバージョンでは、Jetty Embedded Serverのコアコンセプト、スレッドモデル、起動プロセスについて簡単に説明します.次のコードクリップは、Jettyソースコードのexample-jetty-embeddedモジュールのOneServeretContextから抜粋されています.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は使いやすく、数行のコードでhttp(サーブレット)インタフェースを実現できます.
コアコンセプト
LifeCycle
The lifecycle(ライフサイクル)interface for generic components、start(起動)、stop(停止)、isRunning、isStarted(クエリーステータス)の宣言などの方法
AbstractLifeCycle
LifeCycleインタフェースの抽象クラスを実装し、ライフサイクル管理のデフォルト実装を提供します.たとえば、_stateプロパティはコンポーネントステータスを保存し、start、stopのデフォルト実装を提供します.
public final void start() throws Exception {
//
synchronized (_lock) {
try {
//
if (_state == _STARTED || _state == _STARTING) {
return;
}
setStarting();
// start
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 List _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();
}
}
Server
クラス階層
AbstractLifeCycle
AggregateLifeCycle
AbstractHandler
AbstractHandlerContainer
HandlerWrapper
Server
ServerクラスはJettyの「顔」クラスで、以下を含む.
Connector
(主な)クラス階層:
Connector
AbstractConnector
AbstractNIOConnector
SelectChannelConnector
Connectorインタフェースとその実装クラスはクライアント要求を受信するために使用され、(HTTP/PDY)プロトコルは解析し、最終的にサーバの(Request)Handler処理要求を呼び出し、SelectChannelConnectorはサーバのデフォルトで使用されるConnectorである
public Server(int port) {
setServer(this);
Connector connector = new SelectChannelConnector();
connector.setPort(port);
setConnectors(new Connector[]{ connector });
}
Handler
クライアント要求を処理するためにHandlerまたはRequest Handlerと呼ばれる
public interface Handler extends LifeCycle, Destroyable {
...
void handle(String target, Request baseRequest, HttpServletRequest request,
HttpServletResponse response);
...
}
handleメソッドの署名はすでにサーブレットサービスメソッドに近い.ここでtargetは通常、サーブレット構成ルールに基づいて特定のサーブレットを見つけてサービスメソッドを呼び出すために要求されたuriである.
スレッドモデル
Jetty Serverはスレッドプールを使用してクライアント要求を処理し、ThreadPoolインタフェースはスレッドプールの基本操作を定義し、ServerはデフォルトでQueuedThreadPoolクラスを使用し、必要に応じてServerを使用することができる.setThreadPoolメソッドスレッドプールの手動設定注意:Jetty 9.x線モデルは複雑だJetty 8.x比較的簡単で、コードが読みやすい~
QueuedThreadPool
QueuedThreadPoolクラス階層
ThreadPool
SizedThreadPool
QueuedThreadPool
スレッドプールのコア問題:
スレッド管理
最小スレッド数、最大スレッド数、スレッド最大アイドル時間による動的作成、スレッド破棄
スレッドプールの初期化
// QueuedThreadPool.java
public class QueuedThreadPool {
//
private int _maxThreads = 254;
//
private int _minThreads = 8;
...
@Override
protected void doStart() throws Exception {
...
int threads = _threadsStarted.get();
// _minThreads
while (isRunning() && threads < _minThreads) {
startThread(threads);
threads = _threadStarted.get();
}
}
}
スレッド破棄
スレッドアイドル時間が設定したしきい値を超えるとmaxIdleTimeMs、スレッドプールのスレッド数が_より高いminThreadsの場合、スレッドはRunnable runメソッドから終了します.
# QueuedThreadPool.java
private Runnable _runnable = new Runnable() {
public void run() {
boolean shrink = false;
...
try {
Runnable job = _jobs.poll()
while (isRunning()) {
// job loop: job
while (job != null && isRunning()) {
runJob(job);
job = _jobs.poll();
}
// idle loop
try {
_threadsIdle.incrementAndGet();
while (isRunning() && job == null) {
// _maxIdleTimeMs < 0 , job
if (_maxIdleTimeMs <= 0) {
job = _jobs.take();
} else {
final int size = _threadsStarted.get();
// _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 ,
return;
}
}
}
// timeout poll
job = idleJobPoll();
}
}
}
}
} catch (...) {
} finally {
}
}
}
タスクの割り当て
ブロックされたキューを使用すると、ワークスレッドはブロックされたキューからアクティブにタスク(job)を引き出し、QueuedThreadPoolはデフォルトでArrayBlockingQueueを使用します.必要に応じて、ブロックされたキューの具体的な実装を構築方法で手動で指定できます.
public class QueuedThreadPool {
public QueuedThreadPool(BlockingQueue jobQ) {
this();
_jobs = jobQ;
_jobs.clear();
}
public boolean dispatch(Runnable job) {
if (isRunning()) {
final int jobQ = _jobs.size();
final int idle = getIdleThreads();
// job
if (_jobs.offer(job)) {
// idle , job idle
if (idle == 0 || jobQ > idle) {
int threads = _threadsStarted.get();
if (threads < _maxThreads) {
startThread(threads);
}
}
return true;
}
}
return false;
}
}
プロセスの開始
サーバの起動はstartメソッドの呼び出しから始まります.前述したように、サーバクラスはAggregateServerから継承され、親クラスのstartメソッドは最終的にサーバのdoStartメソッドを呼び出します.
Server start
@Override
protected void doStart() throws Exception {
...
// ThreadPool
if (_threadPool == null) {
setThreadPool(new QueuedThreadPool())
}
try {
super.doStart();
} catch(Throwable e) {...}
// Connector, ,
if (_connectors != null && mex.size == 0) {
for (int i = 0; i < _connectors.length; i++) {
try {
_connectors[i].start();
} catch (Throwable e) {
mex.add(e);
}
}
}
...
}