I want to send a stream (channel in Go) of messages to every client that connects to me through a websocket. There's a new message to send every ~100ms. How do I maintain a list of open connections with connections being opened and closed all the time while having to do some sort of iteration over that list to send out the messages for >50,000 connections? Right now I'm storing connections in a map that synchronizes with a single mutex, but I'm not sure if that can scale.
The best way is not maintaining a list at all.
Each connection should connect to a hub with a given identifier (eg:user id, connection id, etc...), subscribe for messages for such identifier and publish messages with that identifier. Also subscribe for global messages and group messages if you want.
UPDATE:
To scale to 50K+ connections you are going to need a more distributed approach rather than a simple map with a mutex. For example: https://github.com/bitly/nsq (made in GO) "NSQ is a realtime distributed messaging platform designed to operate at scale, handling billions of messages per day."
This problem can be stated more generally: You have a collection of values. You need to iterate over the collection, add to the collection and remove from the collection with high concurrency.
I would start with what you propose: use a map protected by a mutex.
If you find that there's high contention on the mutex, then consider lock striping. This is where you use N mutex and map pairs where the pair is selected by a hash of the key.