Can I set services.concurrency for UDP servers? For TCP servers it refers to concurrent connections, but is it interpreted as e.g. packets/s for UDP servers?
Given a UDP server might have a lot of UDP traffic and relatively little TCP traffic (e.g., DNS), I’d like to set a scaling threshold based purely/primarily on the UDP traffic.
This is something we haven’t quite figured out how to expose yet. How would you want to scale instances doing UDP? Would you want to use some packets per second metric, or prefer something like system load?
Packets per second would be great. Ideally that would also be configurable to include a time period (e.g., > 500 queries/s over 30 seconds) to ignore short bursts.
Nice. The plan is to enable scaling on any metric we’re tracking, so once we get that going you should be set.
We do a lot of work to enforce connection limits on VMs through our load balancers, but UDP bypasses all that. We haven’t decided what to do about that yet.
Has there been any update on UDP metrics? I notice they’re not available for the edge (or even instance, although I think they’re tracked in instance data throughput).
@kurt is scaling based on UDP traffic still on the roadmap? I’ve been getting my feet wet on Fly by running a Factorio server on Fly. I’d love to be able to scale down to 0 when no one is using it. But I can’t currently find a way to autoscale based on the UDP traffic.
Thanks for the recommendation! I got it partially doing what I want on the Machines service. I’ve got it scaling down to zero when all users leave. But it’s not waking up when a user tries to join. I’m not super well versed in the factorio netcode, but I think it’s just sending a UDP packet to the server to signal that it wants to connect. It seems that lone packet isn’t waking up my machine though. Any ideas on what I should look for to get the machine to turn back on at the right time?
I haven’t used UDP with Machines myself, but previously, Thomas (eng at Fly) did say that UDP should wake Machines up: Machines first impressions - #3 by thomas … If it isn’t, it is likely a bug.
It’s very likely I just have something configured incorrectly. I do have a dedicated ipv4 provisioned. I can connect to the game server and it works great. Scales down when everyone leaves as desired. I just can’t get it to wake back up without manually issuing a command through flyctl or the machines HTTP API.
I did not My final solution ended up being to write a very small HTTP service that worked as a Discord bot. The bot would listen for wake commands in a discord room, and then issue a Fly API call to wake up the machine.
@willcosgrove I’m interested in trying this, haven’t had luck getting a machine up and running with the latest headless 1.100 though. Would you mind sharing you config?
I’ll give you what I can. My repo is not very clean or organized and it has a bunch of environment secrets in there, so I can’t make it public. But I can share the main parts of my Dockerfile and fly.toml.
I haven’t included anything about the discord bot I mentioned in the last post, as I couldn’t remember how it’s even working. Best of luck!
#!/bin/bash
set -eoux pipefail
FACTORIO_VOL=/factorio
LOAD_LATEST_SAVE="${LOAD_LATEST_SAVE:-true}"
GENERATE_NEW_SAVE="${GENERATE_NEW_SAVE:-false}"
SAVE_NAME="${SAVE_NAME:-""}"
BIND="${BIND:-""}"
mkdir -p "$FACTORIO_VOL"
mkdir -p "$SAVES"
mkdir -p "$CONFIG"
mkdir -p "$MODS"
mkdir -p "$SCENARIOS"
mkdir -p "$SCRIPTOUTPUT"
if [[ ! -f $CONFIG/rconpw ]]; then
# Generate a new RCON password if none exists
pwgen 15 1 >"$CONFIG/rconpw"
fi
if [[ ! -f $CONFIG/server-settings.json ]]; then
# Copy default settings if server-settings.json doesn't exist
cp /opt/factorio/data/server-settings.example.json "$CONFIG/server-settings.json"
fi
if [[ ! -f $CONFIG/map-gen-settings.json ]]; then
cp /opt/factorio/data/map-gen-settings.example.json "$CONFIG/map-gen-settings.json"
fi
if [[ ! -f $CONFIG/map-settings.json ]]; then
cp /opt/factorio/data/map-settings.example.json "$CONFIG/map-settings.json"
fi
NRTMPSAVES=$( find -L "$SAVES" -iname \*.tmp.zip -mindepth 1 | wc -l )
if [[ $NRTMPSAVES -gt 0 ]]; then
# Delete incomplete saves (such as after a forced exit)
rm -f "$SAVES"/*.tmp.zip
fi
if [[ ${UPDATE_MODS_ON_START:-} == "true" ]]; then
./docker-update-mods.sh
fi
if [[ $(id -u) = 0 ]]; then
# Update the User and Group ID based on the PUID/PGID variables
usermod -o -u "$PUID" factorio
groupmod -o -g "$PGID" factorio
# Take ownership of factorio data if running as root
chown -R factorio:factorio "$FACTORIO_VOL"
# Drop to the factorio user
SU_EXEC="su-exec factorio"
else
SU_EXEC=""
fi
sed -i '/write-data=/c\write-data=\/factorio/' /opt/factorio/config/config.ini
NRSAVES=$(find -L "$SAVES" -iname \*.zip -mindepth 1 | wc -l)
if [[ $GENERATE_NEW_SAVE != true && $NRSAVES == 0 ]]; then
GENERATE_NEW_SAVE=true
SAVE_NAME=_autosave1
fi
if [[ $GENERATE_NEW_SAVE == true ]]; then
if [[ -z "$SAVE_NAME" ]]; then
echo "If \$GENERATE_NEW_SAVE is true, you must specify \$SAVE_NAME"
exit 1
fi
if [[ -f "$SAVES/$SAVE_NAME.zip" ]]; then
echo "Map $SAVES/$SAVE_NAME.zip already exists, skipping map generation"
else
$SU_EXEC /opt/factorio/bin/x64/factorio \
--create "$SAVES/$SAVE_NAME.zip" \
--map-gen-settings "$CONFIG/map-gen-settings.json" \
--map-settings "$CONFIG/map-settings.json"
fi
fi
FLAGS=(\
--port "$PORT" \
--server-settings "$CONFIG/server-settings.json" \
--server-banlist "$CONFIG/server-banlist.json" \
--rcon-bind "$RCON_BIND" \
--server-whitelist "$CONFIG/server-whitelist.json" \
--use-server-whitelist \
--server-adminlist "$CONFIG/server-adminlist.json" \
--rcon-password "$RCON_PASSWORD" \
--server-id /factorio/config/server-id.json \
)
if [ -n "$BIND" ]; then
FLAGS+=( --bind "$BIND" )
fi
if [[ $LOAD_LATEST_SAVE == true ]]; then
FLAGS+=( --start-server-load-latest )
else
FLAGS+=( --start-server "$SAVE_NAME" )
fi
# shellcheck disable=SC2086
exec $SU_EXEC /opt/factorio/bin/x64/factorio "${FLAGS[@]}" "$@"