日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

如何正确关闭游戏服务器

發(fā)布時間:2025/7/25 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 如何正确关闭游戏服务器 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

一,如何正確的關(guān)閉游戲服務(wù)器

1,最簡單粗爆的方法

在Linux系統(tǒng)上,使用ps -aux|grep java?可以查到所有運行的java程序的pid,即進程號,然后使用kill - 9?進程號,殺死一個進程。

這樣做雖然簡單快速,但是會有一個問題,如果我們運行的服務(wù)器有緩存的數(shù)據(jù),還沒有來得及進行持久化存儲,那么這樣操作,內(nèi)存中的數(shù)據(jù)就會丟失。kill - 9是一個必殺命令,不管進程處于什么狀態(tài),都是殺無赦,它不會給進程留下任何善后的機會。那么該如何正確的關(guān)閉游戲服務(wù)器吧?

2,優(yōu)雅的關(guān)閉進程

優(yōu)雅的關(guān)閉進程,就是在收到關(guān)閉進程的命令后,進程進行一些數(shù)據(jù)處理,比如:

1,不再接收連接

2,不再接收數(shù)據(jù)

3,把未持久化的數(shù)據(jù)進行持久化

4,清理一些臨時文件等

5,執(zhí)行一些已經(jīng)提交到線程池中但未執(zhí)行的任務(wù)

? 3,Java進程如何接收進程停止命令

1,JVM?關(guān)閉鉤子

關(guān)閉鉤子本質(zhì)上是一個線程(也稱為Hook線程),用來監(jiān)聽JVM的關(guān)閉。通過使用Runtime的addShutdownHook(Thread hook)可以向JVM注冊一個關(guān)閉鉤子。Hook線程在JVM?正常關(guān)閉才會執(zhí)行,在強制關(guān)閉時不會執(zhí)行。

這個鉤子可以在一下幾種場景中被調(diào)用:

1.?程序正常退出

2.?使用System.exit()

3.?終端使用Ctrl+C觸發(fā)的中斷

4.?系統(tǒng)關(guān)閉

5.?OutOfMemory宕機

6.?使用Kill pid命令干掉進程(注:在使用kill -9 pid時,是不會被調(diào)用的)

對于一個JVM中注冊的多個關(guān)閉鉤子它們將會并發(fā)執(zhí)行,所以JVM并不能保證它的執(zhí)行順行。當(dāng)所有的Hook線程執(zhí)行完畢后,如果此時runFinalizersOnExit為true,那么JVM將先運行終結(jié)器,然后停止。Hook線程會延遲JVM的關(guān)閉時間,這就要求在編寫鉤子過程中必須要盡可能的減少Hook線程的執(zhí)行時間。另外由于多個鉤子是并發(fā)執(zhí)行的,那么很可能因為代碼不當(dāng)導(dǎo)致出現(xiàn)競態(tài)條件或死鎖等問題,為了避免該問題,強烈建議在一個鉤子中執(zhí)行一系列操作。

?

另外在使用關(guān)閉鉤子還要注意以下幾點:

1.?不能在鉤子調(diào)用System.exit(),否則卡住JVM的關(guān)閉過程,但是可以調(diào)用Runtime.halt()。

2.?不能再鉤子中再進行鉤子的添加和刪掉操作,否則將會拋出IllegalStateException。

3.?在System.exit()之后添加的鉤子無效。

4.?當(dāng)JVM收到SIGTERM命令(比如操作系統(tǒng)在關(guān)閉時)后,如果鉤子線程在一定時間沒有完成,那么Hook線程可能在執(zhí)行過程中被終止。

5. Hool線程中同樣會拋出異常,如果拋出異常又不處理,那么鉤子的執(zhí)行序列就會被停止。

?

下面是一個簡單的示例:

?

public class T {

@SuppressWarnings("deprecation")

public static void main(String[] args) throws Exception {

//啟用退出JVM時執(zhí)行Finalizer

Runtime.runFinalizersOnExit(true);

MyHook hook1 = new MyHook("Hook1");

MyHook hook2 = new MyHook("Hook2");

MyHook hook3 = new MyHook("Hook3");

?

//注冊關(guān)閉鉤子

Runtime.getRuntime().addShutdownHook(hook1);

Runtime.getRuntime().addShutdownHook(hook2);

Runtime.getRuntime().addShutdownHook(hook3);

?

//移除關(guān)閉鉤子

Runtime.getRuntime().removeShutdownHook(hook3);

?

//Main線程將在執(zhí)行這句之后退出

System.out.println("Main Thread Ends.");

}

}

?

class MyHook extends Thread {

private String name;

public MyHook (String name) {

this.name = name;

setName(name);

}

public void run() {

System.out.println(name + " Ends.");

}

//重寫Finalizer,將在關(guān)閉鉤子后調(diào)用

protected void finalize() throws Throwable {

System.out.println(name + " Finalize.");

}

}

?

和(可能的)執(zhí)行結(jié)果(因為JVM不保證關(guān)閉鉤子的調(diào)用順序,因此結(jié)果中的第二、三行可能出現(xiàn)相反的順序):

?

Main Thread Ends.

Hook2 Ends.

Hook1 Ends.

Hook3 Finalize.

Hook2 Finalize.

Hook1 Finalize.

可以看到,main函數(shù)執(zhí)行完成,首先輸出的是Main Thread Ends,接下來執(zhí)行關(guān)閉鉤子,輸出Hook2 Ends和Hook1 Ends。這兩行也可以證實:JVM確實不是以注冊的順序來調(diào)用關(guān)閉鉤子的。而由于hook3在調(diào)用了addShutdownHook后,接著對其調(diào)用了removeShutdownHook將其移除,于是hook3在JVM退出時沒有執(zhí)行,因此沒有輸出Hook3 Ends。

另外,由于MyHook類實現(xiàn)了finalize方法,而main函數(shù)中第一行又通過Runtime.runFinalizersOnExit(true)打開了退出JVM時執(zhí)行Finalizer的開關(guān),于是3個hook對象的finalize方法被調(diào)用,輸出了3行Finalize。

注意,多次調(diào)用addShutdownHook來注冊同一個關(guān)閉鉤子將會拋出IllegalArgumentException:

Exception in thread "main" java.lang.IllegalArgumentException: Hook previously registered

at java.lang.ApplicationShutdownHooks.add(ApplicationShutdownHooks.java:72)

at java.lang.Runtime.addShutdownHook(Runtime.java:211)

at T.main(T.java:12)

?

另外,從JavaDoc中得知:

?

? ?Once the shutdown sequence has begun it can be stopped only by invoking the halt method, which forcibly terminates the virtual machine.

? ?Once the shutdown sequence has begun it is impossible to register a new shutdown hook or de-register a previously-registered hook. Attempting either of these operations will cause an IllegalStateException to be thrown.

?

“一旦JVM關(guān)閉流程開始,就只能通過調(diào)用halt方法來停止該流程,也不可能再注冊或移除關(guān)閉鉤子了,這些操作將導(dǎo)致拋出IllegalStateException”。

?

如果在關(guān)閉鉤子中關(guān)閉應(yīng)用程序的公共的組件,如日志服務(wù),或者數(shù)據(jù)庫連接等,像下面這樣:

?

Runtime.getRuntime().addShutdownHook(new Thread() {

public void run() {

try {

LogService.this.stop();

} catch (InterruptedException ignored){

//ignored

}

}

});

?

由于關(guān)閉鉤子將并發(fā)執(zhí)行,因此在關(guān)閉日志時可能導(dǎo)致其他需要日志服務(wù)的關(guān)閉鉤子產(chǎn)生問題。為了避免這種情況,可以使關(guān)閉鉤子不依賴那些可能被應(yīng)用程序或其他關(guān)閉鉤子關(guān)閉的服務(wù)。實現(xiàn)這種功能的一種方式是對所有服務(wù)使用同一個關(guān)閉鉤子(而不是每個服務(wù)使用一個不同的關(guān)閉鉤子),并且在該關(guān)閉鉤子中執(zhí)行一系列的關(guān)閉操作。這確保了關(guān)閉操作在單個線程中串行執(zhí)行,從而避免了在關(guān)閉操作之前出現(xiàn)競態(tài)條件或死鎖等問題。

二,在游戲服務(wù)器中添加關(guān)閉鉤子

?

public class ShutDownService {

private static CommonLog gameLogger = CommonLog.getInstance();

private static List<IShutDown> shutDownList = new ArrayList<>();

//注冊需要在關(guān)閉鉤子中執(zhí)行的任務(wù)

public static void registShutDown(IShutDown shutDownServer) {

shutDownList.add(shutDownServer);

}

public static void startShutDownHook() {

?

Runtime.getRuntime().addShutdownHook(new Thread() {

@Override

public void run() {

gameLogger.warn(0, "開始關(guān)閉服務(wù)器,正在清理資源.....");

for (IShutDown shutDown : shutDownList) {

if (shutDown != null) {

shutDown.shutDown();

while (!shutDown.isTerminated()) {

?

}

gameLogger.warn(0, "----關(guān)閉" + shutDown.getClass().getName() + "成功----");

}

}

gameLogger.warn(0, "###---服務(wù)器關(guān)閉成功---###");

}

});

}

}

?

三,Linux腳本根據(jù)端口殺死一個進程

?

#!/bin/bash

echo "重新啟動服務(wù)"

jar_name=GameLogicServer.jar

PROCESS=`ps -ef|grep ${jar_name} |grep -v grep|grep -v PPID|awk '{ print $2}'`

for i in $PROCESS

do

?echo "######Kill the ${jar_name} process [ $i ] ########"

?

?kill -15 $i

done

?

?

while true

?do

OLD_PROCESS=`ps -ef|grep ${jar_name} |grep -v grep|grep -v PPID|awk '{ print $2}'`

if [ "${OLD_PROCESS}" = "" ]

then

echo "${PROCESS}進程已殺死成功,開始啟動新的進程"

break

else

echo "正在等待${PROCESS}進程關(guān)閉....."

sleep 1s

fi

?

?

?done

?

nohup java -server -agentpath:/usr/jprofiler9/jprofiler9/bin/linux-x64/libjprofilerti.so=port=8849,nowait -jar ${jar_name} > console.out 2>&1 &

echo "服務(wù)器啟動完成"

更多游戲技術(shù)資料請參照:游戲技術(shù)網(wǎng):http://www.youxijishu.com/

轉(zhuǎn)載于:https://www.cnblogs.com/youxijishu/p/6404241.html

《新程序員》:云原生和全面數(shù)字化實踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀

總結(jié)

以上是生活随笔為你收集整理的如何正确关闭游戏服务器的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。