成人午夜视频全免费观看高清-秋霞福利视频一区二区三区-国产精品久久久久电影小说-亚洲不卡区三一区三区一区

怎么關(guān)閉Tomcat服務(wù)

本文通過閱讀Tomcat啟動和關(guān)閉流程的源碼,深入分析不同的Tomcat關(guān)閉方式背后的原理,讓開發(fā)人員能夠了解在使用不同的關(guān)閉方式時需要注意的點,避免因JVM進程異常退出導(dǎo)致的各種非預(yù)見性錯誤。

創(chuàng)新互聯(lián)專業(yè)為企業(yè)提供東區(qū)網(wǎng)站建設(shè)、東區(qū)做網(wǎng)站、東區(qū)網(wǎng)站設(shè)計、東區(qū)網(wǎng)站制作等企業(yè)網(wǎng)站建設(shè)、網(wǎng)頁設(shè)計與制作、東區(qū)企業(yè)網(wǎng)站模板建站服務(wù),10年東區(qū)做網(wǎng)站經(jīng)驗,不只是建網(wǎng)站,更提供有價值的思路和整體網(wǎng)絡(luò)服務(wù)。

一、 Tomcat的啟動過程

要了解Tomcat關(guān)閉的原理,首先需要關(guān)注下Tomcat是如何啟動的。這里我們簡單介紹下。

Tomcat啟動的入口是Bootstrap類中的main方法,而后根據(jù)server.xml中的配置,對Server、Service、Enigin、Connector、Host、Context等組件進行初始化,之后便是啟動這些組件。我們重點來看下啟動之后,Tomcat做了哪些工作。

在Tomcat的各組件啟動完畢之后,main主線程會進入Catalina.out的await()方法,而此方法又是主要調(diào)用了Server組件的await()方法,從名字便可以看出,這個方法的目的是為了阻塞當(dāng)前線程(main主線程)。

分析await的源碼(源碼比較長,這里截取了部分,全部的可以自行拉取Tomcat源碼進行閱讀)。

怎么關(guān)閉Tomcat服務(wù)

(StandardServer.await())

我們發(fā)現(xiàn)await()方法主要是根據(jù)server.xml中Server節(jié)點port屬性的設(shè)置做了以下幾種工作:

  • port為-2時,函數(shù)直接退出,此時主線程不會阻塞。

  • port為-1時,將等待線程設(shè)置為當(dāng)前線程,并且進入while循環(huán),直到stopAwait標(biāo)志位置為true

  • port為其他時,則會新建一個socket服務(wù)端,該socket綁定了當(dāng)前服務(wù)器的ip以及port端口,隨后設(shè)置等待線程為當(dāng)前線程,并且socket進入阻塞監(jiān)聽狀態(tài),直到socket監(jiān)聽到server.xml中預(yù)置的關(guān)閉字符串(默認是"SHUTDOWN")

在主線程退出等待后,就會進入Tomcat的關(guān)閉流程,進行各個組件的stop和destroy操作。從上述分析可以看出,要想停止Tomcat,就是要中斷main主線程的等待狀態(tài)。

下圖為Tomcat的整個生命周期。

怎么關(guān)閉Tomcat服務(wù)

(Tomcat生命周期)

二、常見的關(guān)閉Tomcat的方式

1、我們下載的Tomcat壓縮包的bin目錄下,有一個由官方提供的腳本(shutdown.sh),可以用來結(jié)束Tomcat進程。

2、服務(wù)器上,我們還可以利用kill -x命令來結(jié)束Tomcat進程。

3、此外,代碼中的System.exit()以及OOM等異常情況的發(fā)生,也會導(dǎo)致Tomcat進程的關(guān)閉,但是這兩者都不是正常的運維手段,在此我們不做分析。

三、shutdown腳本

1、shutdown.sh的原理

查看分析官方的shutdown.sh腳本以及catalina.sh腳本,發(fā)現(xiàn)這兩個腳本最終是在調(diào)用Bootstrap類的main方法,和啟動Tomcat時調(diào)用的是同一個方法,差異在于傳入了"stop"作為main方法的參數(shù),而傳入了該參數(shù)的main方法,會調(diào)用Catalina類的stopServer()方法。在此我們抹去不需要關(guān)注的代碼,可以把整個stopServer()方法簡化為如下4步:

怎么關(guān)閉Tomcat服務(wù)

其主要做了兩件事:

  • 初始化Server組件,和Tomcat啟動時類似,這一步主要是解析server.xml文件,然后根據(jù)server.xml中的屬性初始化Tomcat組件的成員變量,這里主要關(guān)注Server組件的幾個成員變量:port、address、shutdown,默認值分別為8005、127.0.0.1、SHUTDOWN等,需要和啟動時讀取的server.xml保持一致。

  • 往address port所監(jiān)聽的Socket端口發(fā)生“SHUTDOWN”字符串。

至此,顯而易見的,這對應(yīng)了第一小節(jié)中的第三種阻塞情況,"SHUTDOWN"字符串讓main主線程結(jié)束了等待狀態(tài),并在接下來通過調(diào)用各組件的stop()和destroy()方法進行資源的釋放。

2、shutdown腳本的缺點

雖然shutdown腳本是由Tomcat官方出品,但是其在實際應(yīng)用中并不廣泛,主要是由于下面兩個缺點:

  • 從上述原理就可以分析出,shutdown腳本是基于啟動時監(jiān)聽了相應(yīng)的端口,這就允許任意人員,只要能夠發(fā)送"SHUTDOWN"字符串到相應(yīng)的端口,就可以對Tomcat進程進行關(guān)閉,這對于生產(chǎn)環(huán)境是相當(dāng)危險的。所以一般生產(chǎn)環(huán)境會將Server的port屬性設(shè)置為-1

  • shutdown腳本只是結(jié)束了main主線程的等待狀態(tài),讓其正常的走下去。我們知道,JVM中的線程分為守護線程和用戶線程兩種類型,守護線程會在所有用戶線程結(jié)束后,自動回收,進而導(dǎo)致JVM進程的退出。main主線程是一個用戶線程,但是隨著程序越來越復(fù)雜,可能會出現(xiàn)很多其他的用戶線程。比如我們平常開發(fā)過程中,常用的創(chuàng)建線程池的操作Executors.newFixedThreadPool(n) 便會創(chuàng)建n個用戶線程,這些線程在main主線程退出后,并不會自動回收,從而阻止了JVM的正常退出。所以經(jīng)常會發(fā)生調(diào)用了shutdown腳本,但是Tomcat進程無法退出的場景。

四、kill -x

1、kill -9 or kill -15

Linux中的kill -x操作是向目標(biāo)進程發(fā)送對應(yīng)的信號量??梢杂胟ill -l命令查看每個數(shù)值所代表的信號量的值。

怎么關(guān)閉Tomcat服務(wù)

(kill信號量)

這里面,我們經(jīng)常會使用kill-9這一命令,kill -9會立即強制結(jié)束當(dāng)前進程,這個操作既方便,但同時也極具破壞性。在實際的環(huán)境中,我們可能有在running的任務(wù),如果此時程序被強制關(guān)閉,便會導(dǎo)致當(dāng)前任務(wù)數(shù)據(jù)的丟失,特別是時間特別長的任務(wù),極有可能造成前功盡棄的局面。同時,如果程序設(shè)計不當(dāng),沒有相應(yīng)的冪等操作,還有可能會造成實際環(huán)境中數(shù)據(jù)缺失或者臟數(shù)據(jù)的產(chǎn)生,對生產(chǎn)環(huán)境造成致命的問題。

相比kill -9, kill -15(15只是一個例子,Linux中還有其他的中斷信號)會相對優(yōu)雅很多。kill -15是向進程發(fā)送一個TERM的中斷信號量,在JVM接收到該信號量后,會響應(yīng)中斷,進而結(jié)束當(dāng)前進程。而這一操作能夠優(yōu)雅關(guān)閉Tomcat的原因在于,JVM在結(jié)束當(dāng)前進程前,會啟動一系列名為shutdownhook(關(guān)閉鉤子)的線程,而這些線程就會成為我們進行風(fēng)險控制的工具。接下來我們首先看看Tomcat中的關(guān)閉鉤子。

2、shutdownhook關(guān)閉鉤子

Tomcat的關(guān)閉鉤子的定義是在Catalina類中,有一個名為CatalinaShutdownHook內(nèi)部類,繼承了Thread類。跟著這個線程類中的run()方法往下看,其調(diào)用了Catalina的stop()方法,而此處stop方法,除了正常去停止各組件外,還會去中斷并快速結(jié)束main主線程(如果主線程還存在的話),最后再調(diào)用各組件的destroy()方法進行資源釋放。

怎么關(guān)閉Tomcat服務(wù)

(Tomcat中的shutdownhook)

除了Tomcat會使用關(guān)閉鉤子外,很多中間件也會使用到這一非常重要的功能。

我們在平常的開發(fā)過程中也可以使用關(guān)閉鉤子,可以在程序啟動或者運行階段通過調(diào)用Runtime.getRuntime().addShutdownHook(shutdownHook)方法進行鉤子的添加,但要注意的是,需要在關(guān)閉的流程中加入移除鉤子的代碼。

Spring中當(dāng)然也有關(guān)閉鉤子的應(yīng)用,并且還為我們使用關(guān)閉鉤子提供了更為友好的編程體驗。

在Spring中,關(guān)閉鉤子是在AbstractApplicationContext.registerShutdownHook()方法中添加的(下圖中的代碼),而其關(guān)閉鉤子的run方法則會調(diào)用destroyBeans()方法,其對所有繼承了DisposableBean接口的類調(diào)用其destroy()方法。

讀到這里我們就明白了,在平時開發(fā)時,如果有使用關(guān)閉鉤子的需求,可以通過繼承DisposableBean,并實現(xiàn)其destroy(),很方便的來達到我們回收資源,打掃戰(zhàn)場的目的。

怎么關(guān)閉Tomcat服務(wù)

3、shutdownhook的使用注意點

shutdownhook在使用中也并不是可以隨意亂用的,需要注意以下幾點:

  • shutdownhook的調(diào)用是不保證順序的

  • shutdownhook是JVM結(jié)束前調(diào)用的線程,所以該線程中的方法應(yīng)盡量短,并且保證不能發(fā)生死鎖的情況,否則也會阻止JVM的正常退出

  • shutdownhook中不能執(zhí)行System.exit(),否則會導(dǎo)致虛擬機卡住,而不得不強行殺死進程

五、總結(jié)

本文對Tomcat兩種常用關(guān)閉方式的原理進行了解讀,從上述分析可以看出,用shutdown.sh腳本控制Tomcat關(guān)閉的方式存在權(quán)限的風(fēng)險,并且也會由于開發(fā)中的線程操作導(dǎo)致Tomcat無法關(guān)閉,所以這種方法在實際應(yīng)用中使用情況較少。

而kill -15則能夠安全的殺死Tomcat進程,并且由于JVM shutdownhook的存在,我們可以對整個程序關(guān)閉時進行更強有力的控制,退出過程也更為優(yōu)雅,所以使用較為廣泛。

本文題目:怎么關(guān)閉Tomcat服務(wù)
標(biāo)題路徑:http://jinyejixie.com/article8/podjop.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供移動網(wǎng)站建設(shè)、網(wǎng)站設(shè)計、營銷型網(wǎng)站建設(shè)、網(wǎng)站維護、做網(wǎng)站、云服務(wù)器

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

成都網(wǎng)頁設(shè)計公司
五台县| 北海市| 景洪市| 昭平县| 威海市| 齐河县| 五原县| 富民县| 衡阳市| 黑山县| 玛曲县| 吴旗县| 邵阳市| 巴林左旗| 南投县| 乐至县| 江源县| 普定县| 和顺县| 红安县| 天峻县| 襄垣县| 永安市| 湘阴县| 天等县| 云安县| 金阳县| 惠州市| 通山县| 芜湖县| 当涂县| 安丘市| 丽水市| 涟水县| 石嘴山市| 七台河市| 沭阳县| 阿克苏市| 宣化县| 龙里县| 怀来县|