PlayerSessionIds only accepted sometimes by gamelift server

Hi all,

I have a fleet with one instance and 4 “Concurrent processes” (available game sessions) running. The client requests a match from flexmatch and gets the correct ip, port, playerid, and playersessionid back. The client then attempts to connect to the server with the ip, port and playersessionid.
I can see that the Player Session gets reserved and weirdly only some of the connections are accepted by AcceptPlayerSession(). 14/16 player sessions were correctly connected on one game session and 0/16 on the other 3 game sessions. Tested by requesting a match on 2 separate clients at the same time, check if they are “Active” or “TimedOut” in the aws browser, then repeat consistently.

Obviously we want the players to be connected to the server after a successful match the vast majority of the time. I was rdp’ed into the instance and the Unreal logs from the server are showing that the correct playersessionid is being passed to the server every time. Seems like AcceptPlayerSession() just rejects it most the time.

Any help would be appreciated.

Sorry that you are having problems here.

Some basic troubleshooting, I would confirm:

  • You are calling with the correct player session id. Ensure you don’t have duplicates and that the player session ids are being passed to the right game session (ie the game session used in the CreatePlayerSession calls)
  • You are calling Accept within 60s of the CreatePlayerSession call. Otherwise player session will timeout.

Other things to look at:

  • What error codes/messages are you actually getting from AcceptPlayerSession?
Aws::GameLift::GenericOutcome acceptResult = Aws::GameLift::Server::AcceptPlayerSession(playerSessionId);

             if (acceptResult .IsSuccess())
             {
                 // handle accept
             }
             else
             {
                 // not accepting session - do nothing.
                GameLiftError& error = acceptResult.GetError()
                 log.error("[Server] Error calling AcceptPlayerSession %s:%s", error.GetErrorName(), error.GetErrorMessage());
             }

I can get the GameLift service team to take a look if you are still having problems, if you can provide me:

  • A fleet id / region and/or player session ids
    • If fleet id, approximate time of failures.
  • Which version of the Server SDK are you using? If you are using the Unreal pluging, which version?

Hi @Pip!

The error I am getting is this error on the concurrent processes that are not accepting the player sessions: Internal service exception : GameLift failed to process the request

If I only spin up 1 concurrent process on the instance it seems to work fine and the player session ids are being accepted at a good rate. It’s just if I spin up multiple concurrent processes then only one of the processes will accept playerSessionIds, the others timeout.

I am reasonably confident that accept is being called within 60 seconds of at least the match as when they are accepted it occurs within a few seconds after the game client receives the match details.

Your query:
You are calling with the correct player session id. Ensure you don’t have duplicates and that the player session ids are being passed to the right game session (ie the game session used in the CreatePlayerSession calls)

This maybe the problem but I’m not sure how to address it. I am not calling CreatePlayerSession() anywhere. I am currently using a serverless architecture for flexmatch similar to this blog post where the PlayerId is generated and StartMatchmaking() is called on a lambda call. The resulting match details (including the playerSessionId) are sent back to the game client. The game client then connects with a game session using the IP, port, and playerSessionId it received. However I believe the instance has the same IP and port for all its game sessions (concurrent processes) so it is likely that the connection request it just being processed by a random game session not necessarily the right game session.
So 2 questions:

  1. If the CreatePlayerSession() is being called somehow, somewhere under the hood of StartMatchmaking() on a random game session, how do I know which game session that is? I assume its probably the same game session that is returned with the playerSessionId from the lambda?
  2. If the game client knows which game session the playerSessionId came from, how does it connect to that specific game session? Is it just the ugly matter of re-requesting every time its rejected until it finally is accepted by the correct game session? Or is there a way to connect to a specific game session running on an instance with multiple game sessions?

Do you need the fleet to be running when you investigate?
I am using GameLiftServerSDK version 3.3.0 with Unreal 4.21.2. No gamelift client plugin. Gamelift is hooked up to the lambda to act as the client service.

  1. The matchmaking results sent back has all the connection data required (https://docs.aws.amazon.com/gamelift/latest/apireference/API_GameSessionConnectionInfo.html) including a map of player id -> playersession ids
  • This information should also be in the events if you are using SNS here

Then you need to:

  • Find the playersession created for your player
  • Provide that on connect to your server (ie send after a connection has been established)
  • Accept the player session on the server
  1. If you are using multi-processes per server you need a way to of assigning port ranges, each process launched by GameLift should be running on its own port and reporting that port via ProcessReady(); that port is then associated with the game session associated to it. Each game session hosted by process should then have a unique port (the console should show ports assigned to a game session).

ie
process A -> port 9000 (free for a Game Session)
process B -> port 9001 (has GameSession A)
process C -> port 9002 (has GameSession B)

Ports will need to be unique per process otherwise players will attempt to connect to wrong game session (as players connect to the process via ip and port). Player sessions are created for specific gamesessions, so using a player session id from a server host a different game session would be expected to fail.

Two typical patterns for assigning ports:

  • Provide a runtime config per process, with pre-defined port numbers during fleet-creation ie
--runtime-configuration ServerProcesses="[{LaunchPath="/local/game/MyAwesomeServer",Parameters="port:1935",ConcurrentExecutions=1}, \
{LaunchPath="/local/game/MyAwesomeServer",Parameters="port:2401",ConcurrentExecutions=1}, \
{LaunchPath="/local/game/MyAwesomeServer",Parameters="port:5999",ConcurrentExecutions=1}, \
{LaunchPath="/local/game/MyAwesomeServer",Parameters="port:6251",ConcurrentExecutions=1},

** Port should just be passed as per any other parameter to your game server.
** Simple but verbose

  • Dynamically config the ports at runtime by finding suitable open port and reporting it in via ProcessReady() calls
    ** More complex and processes need a sane strategy to avoid port conflicts at startup (ie backoff, randomize range etc)

You don’t need to leave the fleet up for GameLift to debug. You should be able to provide some game session ids/player session ids (and ideally approx time range) and the GameLift team should be able to take it from there.

It is odd that you are seeing InternalServer errors; would have expected more useful error message here.

1 Like

Ok that makes sense. Thank you so much for the in depth answer.
I’ll try providing a unique port per process and hopefully that will sort it.

I’ll dig up some of the ids too so ya’ll can investigate the ambiguous error message.

Thanks again @Pip