问题
I have a TCP based Netty application with multiple clients that need to communicate with each other. I store all of the Channel references in a ChannelGroup.
While I know that I can write to every client in a ChannelGroup by calling ChannelGroup.write, but what would be an efficient way to write to all but one of these channels, for example:
'A','B','C' are in a Channel Group together and 'A' needs to send to 'B' and 'C', 'B' needs to send to 'A' and 'C', etc. What would be the best way to do this? Here are some options I thought of but some feedback would be appreciated:
Just iterate through the Group and write to the channels individually (don't use ChannelGroup.write in this case)
Repeatedly "remake/clone" the ChannelGroup so it contains only the channels to write to. I would then call ChannelGroup.write on the modified group, then restore the group to the full group.
Write to all channels but implement some Handler logic to discard (either on Encode or Downstream Handler) and not write the message if it is from the excluded channel.
As far as design trade offs are concerned, messages are sent as rapidly as possible, ChannelGroups are relatively small <20 channels and messages are about 1kb in size each (500 bytes - 2 kb). Also, there is a scenario under which many of the connections are on the same host as the Server if different logic works better for localhost feedback on this would be greatly appreciated.
Thanks so much for any help!
回答1:
I would not do #2. So far as I know, there is no inherent performance benefit to writing to a channel group. If you look at the code for DefaultChannelGroup, it simply iterates through the registered channels, issues the write and collects the futures:
public ChannelGroupFuture write(Object message) {
Map<Integer, ChannelFuture> futures =
new LinkedHashMap<Integer, ChannelFuture>(size());
if (message instanceof ChannelBuffer) {
ChannelBuffer buf = (ChannelBuffer) message;
for (Channel c: nonServerChannels.values()) {
futures.put(c.getId(), c.write(buf.duplicate()));
}
} else {
for (Channel c: nonServerChannels.values()) {
futures.put(c.getId(), c.write(message));
}
}
return new DefaultChannelGroupFuture(this, futures);
}
.... although you do get the benefit of a multiplexed future, which if you care about the completion callbacks, is useful.
I would not do #3 either since you are just giving the downstream handlers more work to do, discarding data that you went to all the bother to write in the first place.
So I would either:
- Implement Option #1
- Extend DefaultChannelGroup and add a write method that is clever enough to skip the channel in question. You would probably have to provide a bit more meta-data when you add the channels to the group.
来源:https://stackoverflow.com/questions/10503586/writing-to-all-but-one-in-a-tcp-netty-channelgroup