SpringBoot は巨大な Python のようで、ゆっくりと私たちの周りを巻きつき、麻痺させます。 SpringBoot の使用によって確かに作業効率が向上しましたが、同時に多くのスキルを忘れてしまったことも認めざるを得ません。私がこの業界に入った当初は、Java Web プロジェクトを Tomcat 経由で手動でデプロイし、Tomcat のパフォーマンス チューニングを頻繁に行っていました。さらに、サービス起動例外を引き起こす可能性のある Jar の損失やバージョンの競合などの問題を回避するために、さまざまな Jar 間の関係を整理する必要もあります。現在、これらの面倒で反復的なタスクはすべて SpringBoot によって処理されており、ビジネス ロジックにさらに集中できます。ただし、Tomcat の動作原理とリクエスト処理フローを理解することは、Spring フレームワークのソース コードを分析することと同じくらい重要です。少なくとも面接官は、これらの基本原則や設計のアイデアについて特に質問したがります。この記事が少しでもお役に立てれば幸いです。 Tomcat の全体的なアーキテクチャ Tomcat は、無料のオープンソースの軽量 Web アプリケーション サーバーです。同時実行性がそれほど高くない中小企業のプロジェクトでの使用に適しています。 ファイルディレクトリ構造 以下はTomcat 8のメインディレクトリ構造です。
機能コンポーネント構造 Tomcat には、外部要求の受信と応答を担当するコネクタと、要求の処理を担当するコンテナという 2 つのコア機能があります。コネクタとコンテナは互いに補完し合い、基本的な Web サービスを構成します。各 Tomcat サーバーは複数のサービスを管理できます。
Tomcatコネクタの基本原理 Tomcat コネクタ フレームワーク - Coyote コネクタコア機能 1. ネットワーク ポートをリッスンし、ネットワーク要求を受信して応答します。 2. ネットワーク バイト ストリーム処理。受信したネットワーク バイト ストリームを Tomcat Request に変換し、次にコンテナへの標準 ServletRequest に変換します。同時に、コンテナから送信された ServletResponse を Tomcat Response に変換し、次にネットワーク バイト ストリームに変換します。 コネクタモジュール設計 コネクタの 2 つのコア機能を満たすには、ポートをリッスンする通信エンドポイント、ネットワーク バイト ストリームを処理するプロセッサ、そして最後に、処理された結果をコンテナーに必要な構造に変換するアダプタが必要です。
対応するソース パッケージ パスは Tomcatコンテナの基本原則 Tomcat コンテナ フレームワーク - Catalina コンテナ構造解析 各サービスにはコンテナが含まれます。コンテナ エンジンは複数の仮想ホストを管理できます。各仮想ホストは複数の Web アプリケーションを管理できます。各 Web アプリケーションには複数のサーブレット ラッパーがあります。エンジン、ホスト、コンテキスト、ラッパーの 4 つのコンテナーは親子関係にあります。
対応するソース パッケージ パスは コンテナ要求処理 コンテナのリクエスト処理プロセスは、エンジン、ホスト、コンテキスト、ラッパーの 4 つのコンテナをレイヤーごとに呼び出し、最後にサーブレット内の対応するビジネス ロジックを実行することです。各コンテナーにはチャネル パイプラインがあり、各チャネルにはリクエストとレスポンスの処理に使用されるゲートに似た基本バルブ (StandardEngineValve など) があります。フローチャートは以下のとおりです。 Tomcat リクエスト処理フロー 上記の知識ポイントでは、Tomcat がリクエストを処理する方法について少しずつ紹介しました。簡単に言えば、コネクタの処理フロー + コンテナの処理フロー = Tomcat の処理フローです。はっ!そこで疑問になるのが、Tomcat はどのようにしてリクエスト パスを通じて対応する仮想サイトを見つけるのかということです。対応するサーブレットを見つけるにはどうすればいいですか? マッパー関数の紹介 ここでは、上記で紹介されていないコンポーネント マッパーを紹介する必要があります。名前が示すように、その役割はリクエストパスのルーティング マッピングを提供することです。リクエスト URL が照合され、どのコンテナーが一致を処理するかが決定されます。各コンテナーには、MappedHost などの対応する Mapper がそれぞれあります。 Mapper クラスが見つからないことで支配される恐怖を思い出したことがあるでしょうか。以前は、完全な関数を記述するたびに、web.xml でマッピング ルールを構成する必要がありました。ファイルが大きくなるにつれて、さまざまな問題が発生していました。 HTTP リクエストプロセス tomcat/conf ディレクトリの server.xml ファイルを開き、http://localhost:8080/docs/api リクエストを分析します。 ステップ 1: コネクタはポート 8080 をリッスンします。要求されたポートとリスニング ポートが同じであるため、コネクタは要求を受け入れます。 ステップ 2: エンジンのデフォルトの仮想ホストは localhost であり、仮想ホストのディレクトリは webapps です。したがって、リクエストは tomcat/webapps ディレクトリを見つけました。 ステップ 3: 解析されたドキュメントは、Web プログラムのアプリケーション名 (コンテキスト) です。この時点で、リクエストは webapps ディレクトリの下の docs ディレクトリの検索を続行します。アプリケーション名を省略する場合もあります。 ステップ 4: 解析された API は、特定のビジネス ロジック アドレスです。このとき、docs/WEB-INF/web.xml からマッピング関係を見つけて、最終的に特定の関数を呼び出す必要があります。 <?xml バージョン="1.0" エンコーディング="UTF-8"?> <サーバーポート="8005" シャットダウン="シャットダウン"> <サービス名="Catalina"> <!-- コネクタのリスニング ポートは 8080 で、デフォルトの通信プロトコルは HTTP/1.1 です --> <コネクタ ポート="8080" プロトコル="HTTP/1.1" 接続タイムアウト = "20000" リダイレクトポート="8443" /> <!-- Catalina というエンジンのデフォルトの仮想ホストは localhost です --> <エンジン名="Catalina" defaultHost="localhost"> <!-- ディレクトリが webapps である localhost という名前の仮想ホスト --> <ホスト名="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true"> </ホスト> </エンジン> </サービス> </サーバー> SpringBoot に埋め込まれた Tomcat を起動する方法 SpringBoot のワンクリック サービス起動機能により、社会に出たばかりの多くの友人は Tomcat が何であるかを忘れてしまいます。ハードウェアの性能がますます高くなるにつれて、一般的な中小規模のプロジェクトは、組み込みの Tomcat を使用して直接開始できるようになります。ただし、一部の大規模なプロジェクトでは Tomcat のクラスタリングとチューニングが必要になる場合があり、組み込みの Tomcat ではニーズを満たせない可能性があります。 まず、ソース コードから SpringBoot が Tomcat を起動する方法を分析してみましょう。以下は SpringBoot 2.x のコードです。 コードは main メソッドから始まり、run メソッドを実行してプロジェクトを開始します。 SpringApplication.run 実行メソッドをクリックし、アプリケーション コンテキストを更新するメソッドを見つけます。 this.prepareContext(コンテキスト、環境、リスナー、アプリケーション引数、印刷されたバナー); this.refreshContext(コンテキスト); this.afterRefresh(コンテキスト、アプリケーション引数); refreshContext メソッドをクリックして、refresh メソッドを見つけます。そして、レイヤーごとに検索して、親クラスのメソッドを見つけます。 this.refresh(コンテキスト); AbstractApplicationContext クラスの refresh メソッドには、子コンテナーを呼び出して更新するロジック ラインがあります。 BeanFactory を postProcess します。 beanFactory を呼び出します。 BeanPostProcessors を登録します。 メッセージソースを初期化します。 アプリケーションイベントマルチキャスターを初期化します。 this.onRefresh(); リスナーを登録します。 beanFactory の初期化を終了します。 this.finishRefresh(); onRefresh メソッドをクリックし、ServletWebServerApplicationContext の実装メソッドを見つけます。ここでようやく希望が見えてきました。 保護されたvoid onRefresh() { スーパーのonRefresh(); 試す { この.createWebServer(); } キャッチ (Throwable var2) { throw new ApplicationContextException("Web サーバーを起動できません", var2); } } createWebServer メソッドをクリックし、ファクトリ クラスから WebServer を取得するためのコードを見つけます。 (webServer == null && servletContext == null)の場合{ ServletWebServerFactory ファクトリー = this.getWebServerFactory(); // Webサーバーを取得する this.webServer = factory.getWebServer(新しい ServletContextInitializer[]{this.getSelfInitializer()}); } そうでない場合 (servletContext != null) { 試す { // Webサーバーを起動する this.getSelfInitializer().onStartup(servletContext); } キャッチ (ServletException var4) { 新しい ApplicationContextException("サーブレット コンテキストを初期化できません", var4); をスローします。 } } getWebServer メソッドをクリックし、Jetty と Undertow も含まれる TomcatServletWebServerFactory の実装メソッドを見つけます。基本的なコネクタ、エンジン、仮想サイトなどがここで構成されます。 パブリック WebServer getWebServer(ServletContextInitializer... 初期化子) { Tomcat の tomcat = new Tomcat(); ファイル baseDir = this.baseDirectory != null ? this.baseDirectory : this.createTempDir("tomcat"); tomcat.setBaseDir(baseDir.getAbsolutePath()); コネクタ コネクタ = new Connector(this.protocol); tomcat.getService().addConnector(コネクタ); this.customizeConnector(コネクタ); tomcat.setConnector(コネクタ); tomcat.getHost().setAutoDeploy(false); tomcat のエンジンを設定します。 イテレータ var5 = this.additionalTomcatConnectors.iterator(); while(var5.hasNext()) { コネクタ additionalConnector = (Connector)var5.next(); tomcat.getService().addConnector(追加のコネクタ); } this.prepareContext(tomcat.getHost(), 初期化子); this.getTomcatWebServer(tomcat) を返します。 } サービスが開始されると、ログが印刷されます
終わり 記事はここで終わりです。もう我慢できません。週末に一日中書いていましたが、まだソースコード部分にたどり着いていません。次の章に載せるしかありません。もう一度書いても無駄になります。間違っているところがあれば指摘してください。 上記はTomcatの動作の詳細な内容です。Tomcatの動作原理の詳細については、123WORDPRESS.COMの他の関連記事に注目してください。 以下もご興味があるかもしれません:
|
<<: MySQL でデータを削除してもテーブル ファイルのサイズが変更されないのはなぜですか?
HTML構造 <本文> <div class="wrapper"...
目次1. はじめに1. 基本レイアウト2. 写真を自動的に切り替える3. コンテンツを追加する4. ...
目次序文:結果: 1.重合効果: 2. 散布効果:具体的な実装手順: 1. プロジェクトにOpenL...
目次1. ブロックスコープ1.1. let は var を置き換える1.2. グローバル定数とスレッ...
目次はじめにNginx Dockerファイル新しい会議もっと参考文献はじめに最近、アプリケーションの...
序文この記事で実装されている要件は、実際には非常に一般的です。たとえば、ユーザーが登録したチャネルを...
1. バックグラウンド実行一般的に、Linux 上のプログラムは .sh ファイル (./sh フ...
目次1. シナリオ2. サンドボックスの基本機能3. iframeの実装4. Webワーカーの実装5...
この記事では、JavaScriptで全選択と全選択解除の操作を実装するための具体的なコードを参考まで...
目次Webコンポーネントカスタム要素概要HTMLTemplateElement コンテンツ テンプレ...
目次vue - スワイパープラグインを使用してカルーセルを実装するカルーセルのバグを解決するには、w...
マウスをある領域の上に置くと、その領域に点線の境界線と線のアニメーションが表示されるというクールな効...
目次1 テストケース2 JS配列重複排除4種類2.1 要素の比較2.1.1 二重層 for ループ比...
一般的な CSS コードでは、UI レイアウトや互換性に関して軽微な問題が発生するだけです。しかし、...
序文: MySQL では、ビューはおそらく最も一般的に使用されるデータベース オブジェクトの 1 つ...