Aws-mobile-appsync-sdk-js: every subscription opens a new websocket connection

Created on 17 Apr 2018  Â·  7Comments  Â·  Source: awslabs/aws-mobile-appsync-sdk-js

Is this normal ? I'm having problems understanding why every subscription needs to open a new websocket connection, especially since the total number of ws connections might be limited.

Let's presume that I have joined 50 chat rooms and I'd like to receive updates on all of them... apparently that creates 50 connections. Of course we can lower this a bit by only subscribing to visible ones or some other ideas but if anyone can explain why it's necessary to have this behavior, that'll be great.

Thanks

question

Most helpful comment

For future readers, depending on your use case, you may be able to minimize your number of subscriptions by thinking about what data is actually needed at the given moment by the user. In the chat app example, you could open a subscription for the currently displayed channel, then a second connection that increments unread counters for every channel the user is in. Then just switch the per-channel subscription whenever the user navigates to a different channel.

All 7 comments

Hi @alez007

With the current implementation, you should be getting about n / 4 active websocket connections (where n = number of GraphQL subscriptions).

My suggestion would be to avoid having so many subscriptions active at the same time by unsubscribing from unused ones (e.g. react-apollo takes care of this for you onComponentWillUnmount or similar) or having a more generic subscription.

Maybe something like creating a GraphQL subscription that notifies per-user (not per chat room)?

Thanks. I ended up doing a per user subscription but that doesn't solve
much because it creates unnecessary requests from sender of the mutation.
If you have a chat with 10 users you don't want to add 10 mutation requests
when you send a message.

Anyway, I'm trying to find out if this is a library design issue or appsync
does forces this behaviour.

If I can't get to the bottom of this then the only real solution is to use
AWS iot and subscribe to that and not use graphql subscriptions at all.

On Thu, Apr 19, 2018, 3:07 PM Manuel Iglesias notifications@github.com
wrote:

Hi @alez007 https://github.com/alez007

With the current implementation, you should be getting about n / 4 active
websocket connections (where n = number of GraphQL subscriptions).

My suggestion would be to avoid having so many subscriptions active at the
same time by unsubscribing from unused ones (e.g. react-apollo takes care
of this for you onComponentWillUnmount or similar) or having a more
generic subscription.

Maybe something like creating a GraphQL subscription that notifies
per-user (not per chat room)?

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/awslabs/aws-mobile-appsync-sdk-js/issues/97#issuecomment-382749862,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AAcC1uHM6aocwunUFyk2rYSAYrqN0NJ2ks5tqJo7gaJpZM4TYcu_
.

Hi @alez007 the way AppSync partitions websocket connections is for scalability and security partitioning. We did a lot of design and investigation and the service just happens to send back batches to the clients (n/4 as @manueliglesias mentioned) then the client automatically manages the subscriptions. From a client standpoint, there is no impact to the SDK having multiple connections open that we've found, but I'm interested in knowing if you have a technical reason otherwise?

I'm not sure what you mean by "If you have a chat with 10 users you don't want to add 10 mutation requests when you send a message." With AppSync if you have a chat room then all you need to do is send one mutation and all participants will get that message.

Also related to your question, you can now attach resolvers to subscriptions that allow client authorization to take place at connection time. You can see an example (simplified) of this here: https://docs.aws.amazon.com/appsync/latest/devguide/security-authorization-use-cases.html#real-time-data

So really you could model this in several ways with AppSync and clients can try to connect to chat rooms (using something in the arguments for room ID or similar) and then checking the user identity.

Thank you @undefobj I've already tackled the security aspect of subscriptions resolvers, very nice. Now, returning to the problem at hand, there is one real solution I found to solve the idea of a simple chat system with channels and no limit to the number of users in every channel:

  1. you subscribe all the users to the channels they have joined then yes, you send one mutation and everyone will receive the data, this is basically my problem with 50 channels joined, it helps of course that the library only has n/4 connections, even if there is no standard defined about the max ws connection limit for every browser, we know that there is such a limit... anyway in these cases the bottleneck is at the server level which in this case is of no concern
  2. you subscribe each user to itself, this is for 1-1 conversation and contact support, in case you want to invite someone to chat or open a chat room or invite to connect etc, you just send a mutation to their subscribed id

Another problem is detecting when someone has disconnected, afaik appsync does not have the ability to trigger something if a connection has been closed.

So as a bottomline, based on the above idea, if I have joined 50 channels, I'll have 50 + 1 (the self subscribed channel) / 4 connections which is maybe 13, is that what you're saying ?

I'm afraid I don't understand the question you're asking above in #1. If someone is authorized for a subscription then a mutation to that subscription will send a notification to that subscriber. That's the way GraphQL subscriptions work. If you don't want all people to receive a notification then you should control the subscription using arguments in the subscription per the documentation here: https://docs.aws.amazon.com/appsync/latest/devguide/real-time-data.html#using-subscription-arguments

So going back to your original question, yes multiple websockey connections may be opened but this is an implementation detail that the SDK manages and may or may not change in the future as we make further service optimizations. However, it doesn't impact clients in any way and is just a technical detail that shouldn't impact your application design.

For the last question, you are correct today there is no disconnect lifecycle however we have this on our roadmap.

Yes, I think this thread has gone too far, please feel free to close it. It was never about me lacking subscription conditions or security... every subscription to a chat room for example has the roomId condition and every subscription is using a resolver that validates the right of that identity to actually subscribe.

All I wanted to know if it's a normal behavior to open multiple WS connections for something that, in my opinion, can be handled by one WS connection. You answered that question and I'm happy with the response, I'll continue on this path. Thank you so much and happy coding ;)

For future readers, depending on your use case, you may be able to minimize your number of subscriptions by thinking about what data is actually needed at the given moment by the user. In the chat app example, you could open a subscription for the currently displayed channel, then a second connection that increments unread counters for every channel the user is in. Then just switch the per-channel subscription whenever the user navigates to a different channel.

Was this page helpful?
0 / 5 - 0 ratings