Hey team, noob AWS question: I am currently using Beanstalk with auto-scaling. I want to achieve the following load balancing rule: 1. Given websocket requests http://myapi.com?param=1 http://myapi.com?param=1 http://myapi.com?param=2 2. I want all the requests with the same param to route to the same ec2 instance. Reading through the documentation for Beanstalk, and I am not sure that this is achieveable with "Application Load Balancer". Mainly, it seems like I can route to specific 'target groups' , but beanstalk only creates one target group. How would you achieve this?
Do you need a custom proxy server for routing messages?
I feel like there's going to be significant amount of complexity there, considering • what happens while you're redeploying code to your stateful services? • what happens when they die/restart? • what happens if you need to re-partition?
Just beating around the neighboring bushes: • might API gateway's websocket support help? https://theburningmonk.com/2024/04/here-are-four-ways-you-can-implement-websockets-using-serverless/ • could it help to use regular HTTP requests for the upstream (client->server) messages? how would that change the design? • can you get away with a single (big?) ec2 instance and worry about horizontal scaling later on, when you know the traffic pattern better?
• consider pusher and ably as 3rd party services for server->client messages (they simplify the design considerably and take all of the problems of stateful services off your plate)
(I realize these are not direct answers to your question, just ideas from someone who's built similar things before)
Thanks for diving deeper @pesterhazy! > can you get away with a single (big?) ec2 instance and worry about horizontal scaling later on, when you know the traffic pattern better? We've been going this approach for a while, but I'd love to evolve this a bit more. I'll look deeper into the alternatives you've suggested
are you sure you just don't want sticky sessions?
The problem I am trying to solve for is like this:
I have some state that a few different websocket connections need to share.
• For example: for document id = A, 'who is online', 'the state of all the cursors', etc
I could keep this state in Redis. But right now I'd love to keep this as simple as I can and plop the state in the machine itself.
If I keep the state in memory though, then I need to make sure that all the relevant websockets for document id = N go to the same instance id.
Do you think sticky sessions is the right idea for this?
sticky sessions are a feature that allow you to route requests from the same "session" (which can be kind of nebulously defined, but generally ends up being requests from a user agent with a given cookie) to the same target
so if the "state" exists within a single session then sticky sessions will work for this
To make sure I understand, could something like this work? • User A in Toronto, user B in New York • User A could make two separate websocket requests: ◦ 1) document id = a ◦ 2) document id = b • User B makes two separate requests: ◦ 1) document id = c ◦ 2) document id = a I guess before I make the websocket request, I can set a specific cookie, so User A's 1) request and User B's 2) request go to the same machine?
I am not sure, I think that it outside the scope of sticky sessions
sticky sessions tend to be more about making sure a single users requests bucketed by some time window all go to the same machine (allowing for things like using in memory session stores), I haven't seen it ever used in a cross user context
Thanks for the context hiredman! Agreed, sticky sessions don't feel like the right fit for this. Will keep exploring
Doesn’t seem possible https://stackoverflow.com/questions/56865221/aws-alb-same-string-in-url-should-go-to-same-ec2-instance I’d simply deploy elasticache and use it to store the session data - it’s not difficult
Thanks for the SO find @jumar! I am worried elasticache may be too slow for the use-cases I am thinking about: mainly sharing changes like cursor movements. I may be overthinking it though; could be interesting to just try it
The http request from the end user is bound to be significantly slower than roundtrip to the cache in the same aws AZ / region
My team used Pusher for collaborative editing, it worked ok but the issue of pinning state was sort of still there - as the system had to direct incoming messages from editing sessions to the right node which acted as the coordinator for given session