in the tutorials I found the matchmaking is always done with a long-polling lambda request and within the lambda function there is short-polling against the flexmatch-service, to retrieve the state of current player matchmaking.
Since this should not be done in production, I tried to implement it in an event-based way. But how?
In my case the game should run on different devices/platforms like Android/Windows. The matchmaking does not have to be confirmed by the player -also it should be fast, cheap & scalable.
If I don’t want to make short-polling on the player-client (like calling lambda every second, which would be very expensive I guess), I have only 2 options with aws afaik, to get the ip-address+port from flexmatch:
- Long polling with lambda (and an event-based strategy within lambda)
- Using push notification service, to make usage of e.g. SNS (which would be connected to flexmatch)
I liked the 1. way, because it seems to be the simplest solution. But I have no idea how to get data from a queue.
- E.g. I cannot subscribe within lambda-function to SNS. I would still be fine with like a every-second short-polling, but it seems I only have write-access there (yes, you can let lambda functions getting executed by SNS, but this does not help me here)
- Maybe emitting SNS messages to SQS, since I can read SQS within lambda. But I cannot filter SQS, so every waiting player lambda-function would get “all” flex-match messages. Can’t imagine that this would be the right way.
- Then there is also this EVENT-BRIDGE service, but it seems I also cannot not read from it within lambda.
Then there would be only the 2nd solution.
- I could imagine the workflow, like player-client makes a lambda-call, which will start matchmaking and returns the ticket-id. Then the player-client would try to connect to SNS via push notification service and provides the ticket-id as filter for SNS.
But this seems to be very complex, since you need first to catch a token (for app+device) to establish a connection…
Is there maybe another way? Or how was it done by others? I would be really thankful for any help!
Please take a look at the GameLift developer’s guide: A Guide to Amazon GameLift & Game Servers | AWS Game Tech Blog, which has the answers that you need with reference architectures in sections:
- “Standalone Game Session Servers with a Serverless Backend”: Flexmatch SNS topic triggers a lambda to store tickets into dynamodb, and separate client calls to fetch ticket status would poll this table for ticket status updates.
- “Standalone Game Session Servers with WebSockets-based Backend”: Flexmatch SNS topic triggers a lambda to call game clients directly via ApiGateway Websocket
Actual I could not find your 2 mentioned points in your link (not even in the ebook).
But nonetheless, that helped me already a lot!
But just one additional question regarding SNS:
I created a SNS topic with a lambda target and logged the events in lambda.
And when 2 players were requesting for matchmaking, I got actual “3” message of type “MatchmakingSucceeded” for the same match (same matchId).
Is this on purpose? I mean one would be enough, and since I have to pay for each lambda-call this is a bit annoying.
Hmm, that’s strange, is it consistently reproducible? If so, could you PM me more information (e.g. region, account id, matchmaking configuration name, timestamp, match id, ticket ids, etc.) for us to investigate?
Alternatively, FlexMatch also emit messages to CloudWatch Event, perhaps try setting up a lambda to listen to CW events to see if the issue persists? If so, please let us know.
Another approach is to put SQS in between your SNS and Lambda (i.e. SNS → SQS → Lambda), the benefits are:
- You are able to batch process multiple records with a single lambda execution (Using AWS Lambda with Amazon SQS - AWS Lambda), you could potentially do some deduping there.
- You are able to reprocess failed records (however, game sessions are short-lived so this feature may not be that useful)
thanks again and thanks for your offer to help!
Actual the same happened also with a CloudWatch Event, 3 instead of 1 message.
But I could figure out to resolve the problem. I had an error in my lambda function, which caused it to run ~3000ms. It seems when there is no return to the sns/event within a second, then it will trigger again a lambda function.
So as soon as the lambda problem was solved and it was running <1000ms, the problem was gone.
Then I came to see that I can not filter the messages of SNS coming from GameLift, because there were no “MessageAttributes” on it. The whole MatchmakingMessage was put stringified in “message”. And as I understood, you can only filter for “MessageAttributes”.
But at least CloudWatch Event had the option to filter for the messages I needed (MatchmakingSucceeded, MatchmakingTimedOut, MatchmakingFailed), so I used this instead (higher latency of ~500ms, instead of ~30ms with sns, but it’s still fine)
So everything is working now, thanks again for the help!
Glad you fixed the issue! I have submitted a feature request to add MessageAttributes to Flexmatch/GameSessionQueue SNS messages.
For other folks in the future, please +1 on this if you also want this feature, so you could help us prioritize, thanks!