You can also use Sockjs Tornado + Rabbit MQ + Memcached in order to scale horizontally.
RabbitMQ brocker will play role of messaging bus from physical Server A to physical Server B.
All information about servers may be stored in memcache. For instance you need to send message M from client-socket C1(A) to client-socket C2(B):
- if receiver of A hosted on the same server (by checking memcache), send msg directly using SockJS Router
- otherwise send M via RabbitMQ brocker B1(A) (by using routing logic) to B2(A), where SockJS router B can directly send your message to original receiver C2(B).
Since AMQP protocol of RabbitMQ utilizing Erlang, message passing is very stable and quite good for high-load distributed applications. To support my words, look here: http://www.rabbitmq.com/blog/2012/04/25/rabbitmq-performance-measurements-part-2/
Each physical server (with the following power Xenon 4-nodes, MEM 4Gb, HDD- 140 -1000Gb) can handle 3-5 sockjs tornado instances. SockJS implementation also quite good utilizes reverse proxy (HaProxy) via additional params in url.
For distributed testing you can use gemetr, or tsung (based on erlang).
I used this approach in couple of distributed apps.
In addition, don't forget to use Tornado memory as L1 cache.