mirror of
https://gitlab.com/2009scape/2009scape.git
synced 2025-12-09 16:45:44 -07:00
Halt tick processing if the server isn't able to reach the internet when watchdog is enabled (configurable via server config options connectivity_check_url and connectivity_timeout)
This commit is contained in:
parent
53357d20f3
commit
806680517b
6 changed files with 71 additions and 13 deletions
|
|
@ -3,20 +3,21 @@ package core
|
||||||
import core.api.log
|
import core.api.log
|
||||||
import core.game.system.SystemManager
|
import core.game.system.SystemManager
|
||||||
import core.game.system.SystemState
|
import core.game.system.SystemState
|
||||||
import core.net.NioReactor
|
|
||||||
import core.tools.TimeStamp
|
|
||||||
import kotlinx.coroutines.*
|
|
||||||
import core.tools.SystemLogger
|
|
||||||
import core.game.system.config.ServerConfigParser
|
import core.game.system.config.ServerConfigParser
|
||||||
import core.game.world.GameWorld
|
import core.game.world.GameWorld
|
||||||
import core.game.world.repository.Repository
|
import core.net.NioReactor
|
||||||
import core.tools.Log
|
import core.tools.Log
|
||||||
|
import core.tools.NetworkReachability
|
||||||
|
import core.tools.TimeStamp
|
||||||
|
import kotlinx.coroutines.*
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.FileWriter
|
import java.io.FileWriter
|
||||||
import java.lang.management.ManagementFactory
|
import java.lang.management.ManagementFactory
|
||||||
import java.lang.management.ThreadMXBean
|
import java.lang.management.ThreadMXBean
|
||||||
import java.net.BindException
|
import java.net.BindException
|
||||||
|
import java.net.URL
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
import kotlin.math.max
|
||||||
import kotlin.system.exitProcess
|
import kotlin.system.exitProcess
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -43,6 +44,8 @@ object Server {
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
var reactor: NioReactor? = null
|
var reactor: NioReactor? = null
|
||||||
|
|
||||||
|
var networkReachability = NetworkReachability.Reachable
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The main method, in this method we load background utilities such as
|
* The main method, in this method we load background utilities such as
|
||||||
* cache and our world, then end with starting networking.
|
* cache and our world, then end with starting networking.
|
||||||
|
|
@ -95,6 +98,11 @@ object Server {
|
||||||
GlobalScope.launch {
|
GlobalScope.launch {
|
||||||
delay(20000)
|
delay(20000)
|
||||||
while (running) {
|
while (running) {
|
||||||
|
val timeStart = System.currentTimeMillis()
|
||||||
|
if (!checkConnectivity())
|
||||||
|
networkReachability = NetworkReachability.Unreachable
|
||||||
|
else
|
||||||
|
networkReachability = NetworkReachability.Reachable
|
||||||
if (System.currentTimeMillis() - lastHeartbeat > 7200 && running) {
|
if (System.currentTimeMillis() - lastHeartbeat > 7200 && running) {
|
||||||
log(this::class.java, Log.ERR, "Triggering reboot due to heartbeat timeout")
|
log(this::class.java, Log.ERR, "Triggering reboot due to heartbeat timeout")
|
||||||
log(this::class.java, Log.ERR, "Creating thread dump...")
|
log(this::class.java, Log.ERR, "Creating thread dump...")
|
||||||
|
|
@ -115,12 +123,36 @@ object Server {
|
||||||
if (!SystemManager.isTerminated())
|
if (!SystemManager.isTerminated())
|
||||||
exitProcess(0)
|
exitProcess(0)
|
||||||
}
|
}
|
||||||
delay(625)
|
val timeNow = System.currentTimeMillis()
|
||||||
|
delay(max(0L, 625 - (timeNow - timeStart)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun checkConnectivity(): Boolean
|
||||||
|
{
|
||||||
|
//Has to be done this way because you can't actually ping in Java unless you run the whole thing as root
|
||||||
|
val urls = ServerConstants.CONNECTIVITY_CHECK_URL.split(",")
|
||||||
|
var timeout = ServerConstants.CONNECTIVITY_TIMEOUT
|
||||||
|
if (timeout * urls.size > 5000) //Limit timeout down to 5000ms so other watchdog functions continue as expected.
|
||||||
|
timeout = 5000 / urls.size
|
||||||
|
for (targetUrl in urls) {
|
||||||
|
try {
|
||||||
|
val url = URL(targetUrl)
|
||||||
|
val conn = url.openConnection()
|
||||||
|
conn.connectTimeout = timeout
|
||||||
|
conn.connect()
|
||||||
|
conn.getInputStream().close()
|
||||||
|
return true
|
||||||
|
} catch (e: Exception) {
|
||||||
|
log(this::class.java, Log.WARN, "${targetUrl} failed to respond. Are we offline?")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun heartbeat() {
|
fun heartbeat() {
|
||||||
lastHeartbeat = System.currentTimeMillis()
|
lastHeartbeat = System.currentTimeMillis()
|
||||||
|
|
|
||||||
|
|
@ -338,5 +338,11 @@ class ServerConstants {
|
||||||
|
|
||||||
@JvmField
|
@JvmField
|
||||||
var STARTUP_MOMENT = Calendar.getInstance()
|
var STARTUP_MOMENT = Calendar.getInstance()
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
var CONNECTIVITY_CHECK_URL = "https://google.com,https://2009scape.org"
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
var CONNECTIVITY_TIMEOUT = 500
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -166,6 +166,8 @@ object ServerConfigParser {
|
||||||
ServerConstants.FORCE_EASTER_EVENTS = data.getBoolean("world.force_easter_randoms", false)
|
ServerConstants.FORCE_EASTER_EVENTS = data.getBoolean("world.force_easter_randoms", false)
|
||||||
ServerConstants.RUNECRAFTING_FORMULA_REVISION = data.getLong("world.runecrafting_formula_revision", 581).toInt()
|
ServerConstants.RUNECRAFTING_FORMULA_REVISION = data.getLong("world.runecrafting_formula_revision", 581).toInt()
|
||||||
ServerConstants.ENHANCED_DEEP_WILDERNESS = data.getBoolean("world.enhanced_deep_wilderness", false)
|
ServerConstants.ENHANCED_DEEP_WILDERNESS = data.getBoolean("world.enhanced_deep_wilderness", false)
|
||||||
|
ServerConstants.CONNECTIVITY_CHECK_URL = data.getString("server.connectivity_check_url", "https://google.com,https://2009scape.org")
|
||||||
|
ServerConstants.CONNECTIVITY_TIMEOUT = data.getLong("server.connectivity_timeout", 500L).toInt()
|
||||||
|
|
||||||
val logLevel = data.getString("server.log_level", "VERBOSE").uppercase()
|
val logLevel = data.getString("server.log_level", "VERBOSE").uppercase()
|
||||||
ServerConstants.LOG_LEVEL = parseEnumEntry<LogLevel>(logLevel) ?: LogLevel.VERBOSE
|
ServerConstants.LOG_LEVEL = parseEnumEntry<LogLevel>(logLevel) ?: LogLevel.VERBOSE
|
||||||
|
|
|
||||||
6
Server/src/main/core/tools/NetworkReachability.kt
Normal file
6
Server/src/main/core/tools/NetworkReachability.kt
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
package core.tools
|
||||||
|
|
||||||
|
enum class NetworkReachability {
|
||||||
|
Reachable,
|
||||||
|
Unreachable
|
||||||
|
}
|
||||||
|
|
@ -1,25 +1,25 @@
|
||||||
package core.worker
|
package core.worker
|
||||||
|
|
||||||
import core.api.submitWorldPulse
|
|
||||||
import core.game.system.task.Pulse
|
|
||||||
import core.plugin.CorePluginTypes.Managers
|
|
||||||
import core.Server
|
import core.Server
|
||||||
import core.ServerConstants
|
import core.ServerConstants
|
||||||
import core.ServerStore
|
import core.ServerStore
|
||||||
import core.api.log
|
import core.api.log
|
||||||
import core.tools.SystemLogger
|
import core.api.submitWorldPulse
|
||||||
|
import core.game.system.task.Pulse
|
||||||
import core.game.world.GameWorld
|
import core.game.world.GameWorld
|
||||||
import core.game.world.repository.Repository
|
import core.game.world.repository.Repository
|
||||||
import core.game.world.update.UpdateSequence
|
import core.game.world.update.UpdateSequence
|
||||||
|
import core.integrations.grafana.Grafana
|
||||||
import core.net.packet.PacketProcessor
|
import core.net.packet.PacketProcessor
|
||||||
import core.net.packet.PacketWriteQueue
|
import core.net.packet.PacketWriteQueue
|
||||||
|
import core.plugin.CorePluginTypes.Managers
|
||||||
import core.tools.Log
|
import core.tools.Log
|
||||||
|
import core.tools.NetworkReachability
|
||||||
import core.tools.colorize
|
import core.tools.colorize
|
||||||
import java.lang.Long.max
|
import java.lang.Long.max
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.system.exitProcess
|
import kotlin.system.exitProcess
|
||||||
import core.integrations.grafana.*
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles the running of pulses and writing of masks, etc
|
* Handles the running of pulses and writing of masks, etc
|
||||||
|
|
@ -38,7 +38,11 @@ class MajorUpdateWorker {
|
||||||
Grafana.startTick()
|
Grafana.startTick()
|
||||||
val start = System.currentTimeMillis()
|
val start = System.currentTimeMillis()
|
||||||
Server.heartbeat()
|
Server.heartbeat()
|
||||||
handleTickActions()
|
|
||||||
|
if (Server.networkReachability == NetworkReachability.Reachable)
|
||||||
|
handleTickActions()
|
||||||
|
else
|
||||||
|
tickOffline()
|
||||||
|
|
||||||
for (player in Repository.players.filter { !it.isArtificial }) {
|
for (player in Repository.players.filter { !it.isArtificial }) {
|
||||||
if (System.currentTimeMillis() - player.session.lastPing > 20000L) {
|
if (System.currentTimeMillis() - player.session.lastPing > 20000L) {
|
||||||
|
|
@ -89,6 +93,12 @@ class MajorUpdateWorker {
|
||||||
log(this::class.java, Log.FINE, "Update worker stopped.")
|
log(this::class.java, Log.FINE, "Update worker stopped.")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun tickOffline()
|
||||||
|
{
|
||||||
|
Repository.disconnectionQueue.update() //continue processing disconnection queue
|
||||||
|
GameWorld.pulse() //continue incrementing the global tick count
|
||||||
|
}
|
||||||
|
|
||||||
fun handleTickActions(skipPulseUpdate: Boolean = false) {
|
fun handleTickActions(skipPulseUpdate: Boolean = false) {
|
||||||
try {
|
try {
|
||||||
var packetStart = System.currentTimeMillis()
|
var packetStart = System.currentTimeMillis()
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,9 @@ noauth_default_admin = true #NOTE: If we are not using auth, this determines whe
|
||||||
#------------------------------------------------------------------------------------------------------
|
#------------------------------------------------------------------------------------------------------
|
||||||
#The limit on how many different accounts a player can log into per day.
|
#The limit on how many different accounts a player can log into per day.
|
||||||
daily_accounts_per_ip = 3
|
daily_accounts_per_ip = 3
|
||||||
watchdog_enabled = false
|
watchdog_enabled = true
|
||||||
|
connectivity_check_url = "https://google.com,https://2009scape.org"
|
||||||
|
connectivity_timeout = 500
|
||||||
|
|
||||||
[database]
|
[database]
|
||||||
database_name = "global"
|
database_name = "global"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue