Installing NodeJS + NPM in a Build fleet (not Realtime Script)

0

Hi all, I have an existing game using Unity for the frontend, but NodeJS for the backend. I can't port my backend over to Unity any time soon, so I've managed to get it working on GameLift in its current state. But there's room for improvement. First I'll explain how I've set it up:

  1. Used an unofficial AWS GameLift NodeJS Server SDK (https://github.com/dplusic/GameLift-Nodejs-ServerSDK). (Apologies if it's against the rules to link to unofficial SDKs here - I'm happy to redact this, just thought it would add some context)
  2. Prepackaged a NodeJS v16 binary into the build zip that I upload to GameLift
  3. Prepackaged my node_modules folders (all of the dependencies) in the build zip
  4. My startup script (start.sh) sets up the NodeJS binary and executes Node within the calling process

Here's what my start.sh looks like:

#!/bin/bash

echo "Running 'node src/game-lift/GameLift.js' from Process ID $$"

echo "Setting up node"
PWD=`pwd`
PATH=$PATH:$PWD/deps/node-v16.16.0-linux-x64/bin

node --version

echo "Executing 'node dist/src/game-lift/GameLift.js'"
exec node dist/src/game-lift/GameLift.js

exec ensures that NodeJS is run within the same process as the calling script, so that GameLift can monitor the process for irregularities (I assume).

I launch the Fleet with the following command:

aws gamelift create-fleet \
  --name REDACTED-fleet-name \
  --build-id build-REDACTED \
  --ec2-instance-type m5.large \
  --ec2-inbound-permissions 'FromPort=1234,ToPort=1234,IpRange=0.0.0.0/0,Protocol=TCP' \
  --fleet-type ON_DEMAND \
  --runtime-configuration 'ServerProcesses=[{LaunchPath=/local/game/start.sh,ConcurrentExecutions=1}],MaxConcurrentGameSessionActivations=1,GameSessionActivationTimeoutSeconds=600'

Two concerns about this approach:

  1. Prepackaging NodeJS is not cool / sustainable. I'd rather install it in install.sh, using some platform independent method.
  2. Running exec to ensure Node doesn't break out into another process seems hacky and potentially problematic. I would rather set the launch path to simply node and add the script as a parameter. For example:
  --runtime-configuration 'ServerProcesses=[{LaunchPath=node,Parameters=dist/src/game-lift/GameLift.js,ConcurrentExecutions=1}],MaxConcurrentGameSessionActivations=1,GameSessionActivationTimeoutSeconds=600'

Maybe I'm overthinking item #2 - it might not be a problem as-is

But as for #1, I would love to take advantage of that install.sh script. Previously I was installing NodeJs in install.sh via N (https://github.com/mklement0/n-install). But I found that Node was not available in start.sh. I even SSH'd in and it seemed like NodeJS was not installed.

Question #1: Am I misunderstanding what install.sh does? Should I be able to use it to install NodeJS (or any dependency) and later on use that dependency in my launch script?

Question #2: Anyone got any tips on how to install Node in GameLift reliably? Yum? N? Nvm? etc.

I know NodeJS isn't officially supported, but I'm hoping to get just a general idea of what should and should not be possible in GameLift. Any help would be greatly appreciated.

profile picture
Jimmie
asked 2 years ago411 views
1 Answer
0

Update: FWIW to anyone who comes across this post, I've actually changed my thinking on Question 1, about prepackaging NodeJs and node_modules.

It's more reliable to have all the binaries/dependencies packaged in one build so that during installation, there's less that could go wrong. If I installed NVM, Node, and ran NPM from within install.sh, I'd have to consider:

  1. If Github.com is down, NVM's install script won't be unavailable
  2. If NVM's version changes, or the Github project gets hijacked, the NVM install is unreliable
  3. If Nodejs.org is down, NVM can't install Node
  4. If Npmjs.com is down, npm install won't work, no node_modules

Since these fleets scale dynamically, this chain of events happens at unpredictable times. It's not like I can just deploy once, verify everything worked, and sleep well. A scale-up event could randomly fail in the middle of the night due to a network hiccup on any of those websites.

Considering all of these factors, I've decided to leave my build + install scripts unchanged. All dependencies are pre-packaged ahead of time. This is probably obviously correct to those familiar with Docker, but since GameLift is not very Docker-friendly, I had forgotten some of its ideologies.

Re: Question 2, about using exec to start my Node process, I only have one concern. I'm running into an error about my game server processes not exiting cleanly within 30 seconds when they've been asked to. My code is listening for the ProcessTerminate event, calls ProcessEnding and, after that succeeds, calls process.exit() accordingly. The error might be related to exec, but I don't see how yet. Could just be a code bug I'm not seeing.

profile picture
Jimmie
answered 2 years ago

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.

Guidelines for Answering Questions