一,如何正确的关闭游戏服务器

1,最简单粗爆的方法

在Linux系统上,使用ps -aux|grep java 可以查到所有运行的java程序的pid,即进程号,然后使用kill - 9 进程号,杀死一个进程。

这样做虽然简单快速,但是会有一个问题,如果我们运行的服务器有缓存的数据,还没有来得及进行持久化存储,那么这样操作,内存中的数据就会丢失。kill - 9是一个必杀命令,不管进程处于什么状态,都是杀无赦,它不会给进程留下任何善后的机会。那么该如何正确的关闭游戏服务器吧?

2,优雅的关闭进程

优雅的关闭进程,就是在收到关闭进程的命令后,进程进行一些数据处理,比如:

1,不再接收连接

2,不再接收数据

3,把未持久化的数据进行持久化

4,清理一些临时文件等

5,执行一些已经提交到线程池中但未执行的任务

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

1,JVM 关闭钩子

关闭钩子本质上是一个线程(也称为Hook线程),用来监听JVM的关闭。通过使用Runtime的addShutdownHook(Thread hook)可以向JVM注册一个关闭钩子。Hook线程在JVM 正常关闭才会执行,在强制关闭时不会执行。

这个钩子可以在一下几种场景中被调用:

1. 程序正常退出

2. 使用System.exit()

3. 终端使用Ctrl+C触发的中断

4. 系统关闭

5. OutOfMemory宕机

6. 使用Kill pid命令干掉进程(注:在使用kill -9 pid时,是不会被调用的)

对于一个JVM中注册的多个关闭钩子它们将会并发执行,所以JVM并不能保证它的执行顺行。当所有的Hook线程执行完毕后,如果此时runFinalizersOnExit为true,那么JVM将先运行终结器,然后停止。Hook线程会延迟JVM的关闭时间,这就要求在编写钩子过程中必须要尽可能的减少Hook线程的执行时间。另外由于多个钩子是并发执行的,那么很可能因为代码不当导致出现竞态条件或死锁等问题,为了避免该问题,强烈建议在一个钩子中执行一系列操作。

另外在使用关闭钩子还要注意以下几点:

1. 不能在钩子调用System.exit(),否则卡住JVM的关闭过程,但是可以调用Runtime.halt()。

2. 不能再钩子中再进行钩子的添加和删掉操作,否则将会抛出IllegalStateException。

3. 在System.exit()之后添加的钩子无效。

4. 当JVM收到SIGTERM命令(比如操作系统在关闭时)后,如果钩子线程在一定时间没有完成,那么Hook线程可能在执行过程中被终止。

5. Hool线程中同样会抛出异常,如果抛出异常又不处理,那么钩子的执行序列就会被停止。

下面是一个简单的示例:

public class T {

@SuppressWarnings("deprecation")

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

//启用退出JVM时执行Finalizer

Runtime.runFinalizersOnExit(true);

MyHook hook1 = new MyHook("Hook1");

MyHook hook2 = new MyHook("Hook2");

MyHook hook3 = new MyHook("Hook3");

//注册关闭钩子

Runtime.getRuntime().addShutdownHook(hook1);

Runtime.getRuntime().addShutdownHook(hook2);

Runtime.getRuntime().addShutdownHook(hook3);

//移除关闭钩子

Runtime.getRuntime().removeShutdownHook(hook3);

//Main线程将在执行这句之后退出

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,将在关闭钩子后调用

protected void finalize() throws Throwable {

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

}

}

和(可能的)执行结果(因为JVM不保证关闭钩子的调用顺序,因此结果中的第二、三行可能出现相反的顺序):

Main Thread Ends.

Hook2 Ends.

Hook1 Ends.

Hook3 Finalize.

Hook2 Finalize.

Hook1 Finalize.

可以看到,main函数执行完成,首先输出的是Main Thread Ends,接下来执行关闭钩子,输出Hook2 Ends和Hook1 Ends。这两行也可以证实:JVM确实不是以注册的顺序来调用关闭钩子的。而由于hook3在调用了addShutdownHook后,接着对其调用了removeShutdownHook将其移除,于是hook3在JVM退出时没有执行,因此没有输出Hook3 Ends。

另外,由于MyHook类实现了finalize方法,而main函数中第一行又通过Runtime.runFinalizersOnExit(true)打开了退出JVM时执行Finalizer的开关,于是3个hook对象的finalize方法被调用,输出了3行Finalize。

注意,多次调用addShutdownHook来注册同一个关闭钩子将会抛出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关闭流程开始,就只能通过调用halt方法来停止该流程,也不可能再注册或移除关闭钩子了,这些操作将导致抛出IllegalStateException”。

如果在关闭钩子中关闭应用程序的公共的组件,如日志服务,或者数据库连接等,像下面这样:

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

public void run() {

try {

LogService.this.stop();

} catch (InterruptedException ignored){

//ignored

}

}

});

由于关闭钩子将并发执行,因此在关闭日志时可能导致其他需要日志服务的关闭钩子产生问题。为了避免这种情况,可以使关闭钩子不依赖那些可能被应用程序或其他关闭钩子关闭的服务。实现这种功能的一种方式是对所有服务使用同一个关闭钩子(而不是每个服务使用一个不同的关闭钩子),并且在该关闭钩子中执行一系列的关闭操作。这确保了关闭操作在单个线程中串行执行,从而避免了在关闭操作之前出现竞态条件或死锁等问题。

二,在游戏服务器中添加关闭钩子

public class ShutDownService {

private static CommonLog gameLogger = CommonLog.getInstance();

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

//注册需要在关闭钩子中执行的任务

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, "开始关闭服务器,正在清理资源.....");

for (IShutDown shutDown : shutDownList) {

if (shutDown != null) {

shutDown.shutDown();

while (!shutDown.isTerminated()) {

}

gameLogger.warn(0, "----关闭" + shutDown.getClass().getName() + "成功----");

}

}

gameLogger.warn(0, "###---服务器关闭成功---###");

}

});

}

}

三,Linux脚本根据端口杀死一个进程

#!/bin/bash

echo "重新启动服务"

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}进程关闭....."

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 "服务器启动完成"

更多游戏技术资料请参照:游戏技术网:http://www.youxijishu.com/

转载于:https://www.cnblogs.com/youxijishu/p/6404241.html

如何正确关闭游戏服务器相关推荐

  1. 微软服务器系统玩游戏,微软将于2020年1月22日关闭Windows7游戏服务器

    微软在官方微软Answers论坛的一篇论坛帖子中透露,它计划关闭游戏服务器,以满足其Windows 7,Windows XP和Windows ME操作系统需要互联网连接的游戏. 截图自微软社区 Win ...

  2. 【阅读笔记】Java游戏服务器架构实战

    [阅读笔记]Java游戏服务器架构实战 书籍链接:Java游戏服务器架构实战 作者提供的源码链接:kebukeYi / book-code 这里对书籍中比较重要的知识点(精华部分)进行摘录(总结) 文 ...

  3. 游戏服务器框架 Leaf/go

    Leaf/go 详细介绍 Leaf 是一个使用 Go 语言开发的开源游戏服务器框架,注重运行效率并追求极致的开发效率.Leaf 适用于几乎所有的游戏类型.其主要的特性: 良好的使用体验.Leaf 总是 ...

  4. golang Leaf 游戏服务器框架简介

    Leaf 是一个由 Go 语言(golang)编写的开发效率和执行效率并重的开源游戏服务器框架.Leaf 适用于各类游戏服务器的开发,包括 H5(HTML5)游戏服务器. Leaf 的关注点: 良好的 ...

  5. 游戏维护关闭服务器,游戏服务器正在维护中

    游戏服务器正在维护中 内容精选 换一换 用户创建裸金属服务器后,可以通过"申请状态"栏查看任务的创建状态.创建裸金属服务器的任务可以包括创建裸金属服务器资源.绑定弹性公网IP.挂载 ...

  6. 启动mysql 数据库服务器_启动及关闭MySQL服务器的正确方式

    启动及关闭 MySQL 服务器 Windows 系统下 在 Windows 系统下,打开命令窗口(cmd),进入 MySQL 安装目录的 bin 目录. 启动: cd c:/mysql/bin mys ...

  7. dnf打团显示服务器即将关闭,DNF:游戏服务器炸锅?当天在打团的小伙伴,你们还好吗...

    原标题:DNF:游戏服务器炸锅?当天在打团的小伙伴,你们还好吗 在2.23号这一天许多的DNF玩家都发现游戏是彻底的登不上去,变成了名副其实的掉线城与勇士.可在这一天,不单单是地下城变成了掉线城,就连 ...

  8. [转贴] 游戏服务器架构二

    为什么80%的码农都做不了架构师?>>>    来自:http://www.libing.net.cn/read.php/1724.htm 服务器公共组件实现 -- 环形缓冲区 消息 ...

  9. 教你从头写游戏服务器框架

    本文由云+社区发表 作者:韩伟 前言 大概已经有差不多一年没写技术文章了,原因是今年投入了一些具体游戏项目的开发.这些新的游戏项目,比较接近独立游戏的开发方式.我觉得公司的"祖传" ...

最新文章

  1. 前端开发新手,这些书千万不要看!
  2. Keepalived + LVS-NAT 实现高可用四层 TCP/UDP 负载均衡器
  3. micro-job 0.0.2 发布,分布式任务调度框架
  4. 如何让你的 Linux 系统干净整洁
  5. Apache虚拟目录和多端口多主机名配置
  6. JZOJ5944信标
  7. Flatten Binary Tree to Linked List (DFS)
  8. 单片机拼字程序怎么做_家装行业做小程序怎么样?
  9. [react] Mern和Yeoman脚手架有什么区别?
  10. (NO.00005)iOS实现炸弹人游戏(七):游戏数据的序列化表示
  11. 大数据城市规划 杨东_AI为智慧城市规划做建设
  12. 023、JVM实战总结:一步一图:那JVM老年代垃圾回收器CMS工作时,内部又干了些啥?
  13. docker load tar.gz包失败解决方法
  14. 微信小程序之设置背景图片
  15. windows驱动安装卸载的实用小工具-InstDrv.exe
  16. PDF中如何删除文字
  17. 华为荣耀手机录制视频 华为手机如何录制视频
  18. 利用Photoshop制作二寸照片
  19. 性能优化|一张图带你了解JVM是如何进行内存分配
  20. ubuntu16.04中 vim8 backspace键删除功能失效

热门文章

  1. 也谈TDD,以及三层架构、设计模式、ORM……没有免费的午餐,选择了,必付出代价...
  2. 11.swift 单例
  3. POPTEST老李谈JVM、JRE、JDK、java ee sdk with jdk区别
  4. 用frontpage制作网页,字体大小用PT做单位好还是用PX做单位好?
  5. ASP.NET 2.0中改变passwordrecovery发邮件时的信息
  6. OpenCV下三对点计算仿射变换实现图像的水平镜像(翻转)的详细说明和源程序
  7. mysql删除表命令_MySQL创建和删除表操作命令实例讲解
  8. 《FreeFlow: Software-based Virtual RDMA Networking for Containerized Clouds》
  9. leetcode算法题--最大平均值和的分组★
  10. php foreach 不等于_PHP中的7个模板引擎