The message server uses the socket, in order to avoid the server overload, only allows 500 socket connections, when one is not enough, the expansion of the message server is inevitable, the problem, how to make the link on the different message server users can implement the message sent?
In order to realize the message communication, we must make the message server itself interoperable, think of two ways, one is the message server cross-linking, the other is to add a special message server, the message server is not open, only responsible for message forwarding and push.
The following tests do not consider firewalls and so on. Test only for feasibility and efficiency.
Test environment
Flow chart
The entire flowchart is as follows:
Flowchart Description:
client1
You can client2
send a message to or from another client
and receive other client
messages that are sent.
Redis
To save the client
connection information, assign each user a unique key
, including the link to which server, the forwarding server timed to detect the message server, such as the message server is hung off, by the forwarding server to clean up all the links Redis has been hung off.
The complete process:
1. Client1
Client2
send a message
2. Socket1
received the message, according key从Redis
to Client2
the connection information taken out, connected to the local, direct push Client2
to, the process is over.
3. If the connection is not local, push the message to the forwarding server, the forwarding server pushes the message to the message server where the connection is located, and the message server receives the message and pushes it Client2
.
4. End of message sending.
Encoding implementation
Socket
Create a server.php on Socket1 with the following content:
<?phpService side$serv =New Swoole_server ("0.0.0.0",9501);Redis$redis =New \redis ();$redis->connect ("192.168.0.231",6379);Client$proxy =New Swoole_client (Swoole_tcp | Swoole_keep);$proxy->connect ("192.168.0.203",9501);$serv->on (' Start ',function($serv) {Echo"Service:start ...";});$serv->on (' Connect ',function($serv,$FD) {});$serv->on (' Receive ',function($serv,$FD,$from _id,$data) {Global$redis;$data = (Array) Json_decode ($DATA);$cmd =$data [' cmd '];Switch ($cmd) {Case"Login":LandingSave connection Information$save =Array' FD ' =$FD,' Socket_ip ' ="192.168.0.201");$redis->set ($data [' Name '], serialize ($save));BreakCase"Chat":$RECV = Unserialize ($redis->get ($data [' recv '));if ($RECV [' Socket_ip ']! ="192.168.0.201") {Need to forward$data [' cmd '] =' Forward ';$data [' recv_ip '] =$RECV [' Socket_ip '];$serv->task (Json_encode ($data)); }else {Send directly$serv->send ($RECV [' FD '],"{$data [' send ']} sent you a message: {$data [' content ']}"); }BreakCase"Forward":Receive forwarded messages$RECV = Unserialize ($redis->get ($data [' recv '));$serv->send ($RECV [' FD '],"{$data [' send ']} sent you a message: {$data [' content ']}");Break }$serv->send ($FD, ' swoole: '. $data); });$serv->on (' Task ',function($serv,$task _id,$from _id,$data) {Global $proxy; $proxy->send ( $data);}); $serv->on (function ( $serv, $task _ ID, $data) {}); $serv->on ( function ( $serv, $FD) { "client:close.\n";}); $serv->set (array ( ' task_worker_num ' = Span class= "number" >4)); $serv->start ();
Just change the IP on the Socket2. 192.168.0.201 changed to 192.168.0.202.
Proxy
Create a script proxy.php on the forwarding server with the following content:
$serv =New Swoole_server ("0.0.0.0",9501);Service side$serv->on (' Start ',function($serv) {Echo"Service:start ...";});$serv->on (' Connect ',function($serv,$FD) {});$serv->on (' Receive ',function($serv,$FD,$from _id,$data) {Global$redis;$serv->task ($DATA); });$serv->on (' Task ',function($serv,$task _id,$from _id,$data) {$forward = (Array) Json_decode ($DATA);$client =New Swoole_client (SWOOLE_SOCK_TCP, Swoole_sock_sync);$client->connect ($forward [' Recv_ip '],9501);unset$forward [' Recv_ip ']);$client->send (Json_encode ($forward)); $client->close ();}); $serv->on (' finish ', function ($serv, $task _id, $data) {}); $serv->on (' close ', function ($serv, $fd) { echo "client:close.\n";}); $serv->set (array (' task_worker_num ' = 4)); $serv->start ();
Test
Note the order of opening
1. Turn on the forwarding server PHP proxy.php
2. Open the socket server PHP server.php, respectively
You can see two messaging servers on the forwarding server already connected
3. Start testing, open two Telnet respectively, connect two message servers, send message test:
Landing
Send Message Test
The message was successfully received.
Based on the powerful swoole
extension, so that PHP efficient implementation of these possibilities, the current message server to the forwarding server is a long connection, the forwarding server to the message server is a short connection, there are performance bottlenecks, but also wasted connectivity resources. The next step is to transform the growth connection, and the client of the messaging server uses async.
Swoole-based distributed socket Messaging server architecture