{"id":1190,"date":"2019-10-09T14:05:19","date_gmt":"2019-10-09T14:05:19","guid":{"rendered":"http:\/\/smartfoxserver.com\/blog\/?p=1190"},"modified":"2019-10-09T14:06:15","modified_gmt":"2019-10-09T14:06:15","slug":"handling-the-server-shutdown","status":"publish","type":"post","link":"https:\/\/smartfoxserver.com\/blog\/handling-the-server-shutdown\/","title":{"rendered":"Handling the server shutdown"},"content":{"rendered":"<p>In today&#8217;s article we&#8217;re going to discuss\u00a0how to detect a server shut down, be it intentional or unexpected, and what tools can we use to exit cleanly without loosing precious data.<\/p>\n<p><!--more--><\/p>\n<h2><img loading=\"lazy\" class=\"wp-image-1191 alignright noShadow\" src=\"http:\/\/smartfoxserver.com\/blog\/wp-content\/uploads\/2019\/10\/iconfinder_exit_17902.png\" alt=\"\" width=\"120\" height=\"120\" srcset=\"https:\/\/smartfoxserver.com\/blog\/wp-content\/uploads\/2019\/10\/iconfinder_exit_17902.png 256w, https:\/\/smartfoxserver.com\/blog\/wp-content\/uploads\/2019\/10\/iconfinder_exit_17902-150x150.png 150w\" sizes=\"(max-width: 120px) 100vw, 120px\" \/>\u00bb Exit strategies<\/h2>\n<p>There are\u00a0many ways in which SmartFoxServer can be shut down: via the AdminTool, a service manager, using a termination signal from the OS,\u00a0issuing\u00a0a System.exit() from code, a process crash\u00a0etc.<\/p>\n<p>In order to detect when the server process is shutting down, and react to it, we can use a native mechanism in Java called a <a href=\"https:\/\/docs.oracle.com\/javase\/7\/docs\/api\/java\/lang\/Runtime.html#addShutdownHook(java.lang.Thread)\" target=\"_blank\" rel=\"noopener noreferrer\">shutdown hook<\/a>, which allows to spawn a custom thread\u00a0that will run right before the JVM shuts down.<\/p>\n<p>This is a basic example of how to setup a shutdown hook:<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\nRuntime.getRuntime().addShutdownHook\r\n(\r\n\tnew Thread() \r\n\t{ \r\n  \t\tpublic void run() \r\n  \t\t{ \r\n\t\t\tSystem.out.println(&quot;Shutdown Hook is running !&quot;); \r\n  \t\t} \r\n\t}\r\n);\r\n<\/pre>\n<p>The code is very straightforward and in theory the system allows us to register multiple hooks in the same application. However, because shutdown hooks run concurrently when the JVM is exiting, we would not recommend to use more than one unless you&#8217;ve good reasons to do so.<\/p>\n<p>Also there are\u00a0a few\u00a0situations\u00a0in which the mechanism will not trigger:<\/p>\n<ul>\n<li>a crash of the JVM due to some native error<\/li>\n<li>an OutOfMemoryError<\/li>\n<li>a termination signal from the OS (such as\u00a0SIGKILL in Unix, or equivalent in Windows)<\/li>\n<\/ul>\n<p>Even though\u00a0shutdown hooks are not guaranteed to run 100% of the times they are still a valid tool to deal with\u00a0most common situations.<\/p>\n<h2>\u00bb\u00a0Additional\u00a0strategies<\/h2>\n<p>Now you might be asking, what about those cases that are not supported such as a system hard crash or a sudden process death? If your game\u00a0maintains lots of critical in-memory data there are additional strategies you could employ to minimize, and possibly neutralize, the risk of data loss.<\/p>\n<p><strong>1) Frequent auto-saves<\/strong><\/p>\n<p>As simple as it may sound a basic auto-saving mechanism based on the server&#8217;s <a href=\"https:\/\/smartfoxserver.com\/blog\/how-to-schedule-timed-tasks-in-an-extension\/\" target=\"_blank\" rel=\"noopener noreferrer\">Task Scheduler <\/a>would be sufficient to ensure that data is saved at regular intervals. In case of a server shutdown you can still rely on the shutdown hook mechanism to take care of the final save, and in case this doesn&#8217;t work you would have just lost a minimal amount of data.<\/p>\n<p><strong>2) Distributed in-memory database<\/strong><\/p>\n<p>A more radical approach to the problem\u00a0is\u00a0to use a distributed in-memory database. With this solution you would be physically running multiple copies of your in-memory data and if the main\u00a0SmartFoxServer process (or the machine) dies, the\u00a0data\u00a0would be\u00a0safe and sound, as it resides on more than one machine. <\/p>\n<p>A good\u00a0candidate for this scenario would be using something like <a href=\"https:\/\/smartfoxserver.com\/blog\/white-paper-smartfoxserver-2x-and-hazelcast-integration\/\" target=\"_blank\" rel=\"noopener noreferrer\">Hazelcast<\/a>.<\/p>\n<p><img loading=\"lazy\" class=\"wp-image-1194 aligncenter\" src=\"http:\/\/smartfoxserver.com\/blog\/wp-content\/uploads\/2019\/10\/hazel-in-memory.png\" alt=\"\" width=\"539\" height=\"352\" \/><\/p>\n<p>This\u00a0is a diagram from the white-paper linked above that shows how one or more SmartFoxServer instances interact with the distributed datastore. Essentially the datastore is made of two ore more nodes (servers) running Hazelcast and SmartFoxServer plugging into it via integrating Hazelcast in a server Extension. The beauty of this system is that you can work with regular <a href=\"https:\/\/it.wikipedia.org\/wiki\/Plain_Old_Java_Object\" target=\"_blank\" rel=\"noopener noreferrer\">POJOs<\/a> and let the system deal with the complexity of distributing the copies in the shared memory.<\/p>\n<p>Also notice the presence of an additional database as a secondary storage for further data security.<\/p>\n<h2>\u00bb Conclusions<\/h2>\n<p>Based on how critical is your in-memory game state you can choose\u00a0and combine these different strategies to avoid loosing important data. If you want to learn more make sure to follow all the linked resources in this article and,\u00a0if you want to discuss\u00a0this topic further, join us on our <a href=\"https:\/\/www.smartfoxserver.com\/forums\/\" target=\"_blank\" rel=\"noopener noreferrer\">support forum<\/a>.<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In today&#8217;s article we&#8217;re going to discuss\u00a0how to detect a server shut down, be it intentional or unexpected, and what tools can we use to exit cleanly without loosing precious data.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[23],"tags":[110,7,109,111],"_links":{"self":[{"href":"https:\/\/smartfoxserver.com\/blog\/wp-json\/wp\/v2\/posts\/1190"}],"collection":[{"href":"https:\/\/smartfoxserver.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/smartfoxserver.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/smartfoxserver.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/smartfoxserver.com\/blog\/wp-json\/wp\/v2\/comments?post=1190"}],"version-history":[{"count":13,"href":"https:\/\/smartfoxserver.com\/blog\/wp-json\/wp\/v2\/posts\/1190\/revisions"}],"predecessor-version":[{"id":1406,"href":"https:\/\/smartfoxserver.com\/blog\/wp-json\/wp\/v2\/posts\/1190\/revisions\/1406"}],"wp:attachment":[{"href":"https:\/\/smartfoxserver.com\/blog\/wp-json\/wp\/v2\/media?parent=1190"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/smartfoxserver.com\/blog\/wp-json\/wp\/v2\/categories?post=1190"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/smartfoxserver.com\/blog\/wp-json\/wp\/v2\/tags?post=1190"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}