Ratchetを利用してPHPでWebソケット 2 デプロイ編

Javascript

以前に
Ratchetを利用してPHPでWebソケット 1
ということで、Ratchetを使ってWebソケットを実装しようというのをやりましたが、それから半年以上たって、やっとデプロイするときがやってきました。(゜∀゜)
時間空きすぎて、Ratchetのことをほとんど覚えていなかった…。
しかし、Ratchetを利用してPHPでWebソケット 1の記事が役に立ったことは言うまでもありません。

下記のサイトに親切にデプロイのやり方が書いてあるので、盲目的にまずやってみます。
http://socketo.me/docs/deploy

まず、HAProxyというものを導入します。
http://www.haproxy.org/

ググるとロードバランサーとしてご利用の方が多そうですが、これをつまりWebsocketと別のポートで接続しなくてもよいようにするために利用します。

これだけで、それなりのボリュームになりそうなので、
Linux初心者がHAProxyを導入する
という記事に書いておきます。

次に、Supervisorというプロセス管理ツールを入れます。
これは、Ratchetを永遠にw生かしておくために入れます。
Linux初心者がSupervisorを導入する

で、デプロイのコードを簡潔に書こうと思います。

構造は下記の通りです。

 Ratchet
   |  
   ---bin
   |   --chat-server,php
   |   --push-server.php
   |
   ---src
       --MyApp
          --Chat.php
          --entry.php
          --Pusher.php

ちなみに、HAProxyによって、Webソケットはポート番号1337ですので、各コードの中で1337を指定しています。
詳しくはここを見てくれってばよ→Linux初心者がHAProxyを導入する

上から順に行きます。

chat-server.php

 <?php
 use Ratchet\Server\IoServer;
 use MyApp\Chat;
 
    require dirname(__DIR__) . '/vendor/autoload.php';
 
    $server = IoServer::factory(
        new Chat(),
        1337
    );
 
    $server->run();
 ?>

push-server.php

 <?php
    require dirname(__DIR__) . '/vendor/autoload.php';
 
    $loop   = React\EventLoop\Factory::create();
    $pusher = new MyApp\Pusher;
 
    // Listen for the web server to make a ZeroMQ push after an ajax request
    $context = new React\ZMQ\Context($loop);
    $pull = $context->getSocket(ZMQ::SOCKET_PULL);
    $pull->bind('tcp://127.0.0.1:5555'); // Binding to 127.0.0.1 means the only client that can connect is itself
    $pull->on('message', array($pusher, 'onBlogEntry'));
 
    // Set up our WebSocket server for clients wanting real-time updates
    $webSock = new React\Socket\Server($loop);
    $webSock->listen(1337, '0.0.0.0'); // Binding to 0.0.0.0 means remotes can connect
    $webServer = new Ratchet\Server\IoServer(
        new Ratchet\Http\HttpServer(
            new Ratchet\WebSocket\WsServer(
                new Ratchet\Wamp\WampServer(
                    $pusher
                )
            )
        ),
        $webSock
    );
 
    $loop->run();

Chat.php

 <?php
 namespace MyApp;
 use Ratchet\MessageComponentInterface;
 use Ratchet\ConnectionInterface;
 
 class Chat implements MessageComponentInterface {
    protected $clients;
 
    public function __construct() {
        $this->clients = new \SplObjectStorage;
    }
 
    public function onOpen(ConnectionInterface $conn) {
        // Store the new connection to send messages to later
        $this->clients->attach($conn);
 
        echo "New connection! ({$conn->resourceId})\n";
    }
 
    public function onMessage(ConnectionInterface $from, $msg) {
        $numRecv = count($this->clients) - 1;
        echo sprintf('Connection %d sending message "%s" to %d other connection%s' . "\n"
            , $from->resourceId, $msg, $numRecv, $numRecv == 1 ? '' : 's');
 
        foreach ($this->clients as $client) {
            if ($from !== $client) {
                // The sender is not the receiver, send to each client connected
                $client->send($msg);
            }
        }
    }
 
    public function onClose(ConnectionInterface $conn) {
        // The connection is closed, remove it, as we can no longer send it messages
        $this->clients->detach($conn);
 
        echo "Connection {$conn->resourceId} has disconnected\n";
    }
 
    public function onError(ConnectionInterface $conn, \Exception $e) {
        echo "An error has occurred: {$e->getMessage()}\n";
 
        $conn->close();
    }
 }

entry.php …今回、本体のWebアプリはCakePHP3で作っていますが本体と連動しているのがこいつです。

 <?php
 //CakePHPからincludeで呼び出しされて利用される
 
 ini_set( 'display_errors', 1 ); 
 
    $entryData = array(
        'category' => "id".$shipper_id
      , 'title'    => $title
      , 'article'  => 'hogeraccho'
      , 'when'     => time()
    );
    
    
    // This is our new stuff
    $context = new ZMQContext();
    $socket = $context->getSocket(ZMQ::SOCKET_PUSH, 'my pusher');
    $socket->connect("tcp://localhost:5555");
 
    $socket->send(json_encode($entryData));
    

Pusher.php

 <?php
 namespace MyApp;
 use Ratchet\ConnectionInterface;
 use Ratchet\Wamp\WampServerInterface; 
 
 class Pusher implements WampServerInterface {
 
    /**
     * A lookup of all the topics clients have subscribed to
     */
    protected $subscribedTopics = array();
 
    public function onSubscribe(ConnectionInterface $conn, $topic) {
        $this->subscribedTopics[$topic->getId()] = $topic;
    }
 
    /**
     * @param string JSON'ified string we'll receive from ZeroMQ
     */
    public function onBlogEntry($entry) {
        $entryData = json_decode($entry, true);
 
        // If the lookup topic object isn't set there is no one to publish to
        if (!array_key_exists($entryData['category'], $this->subscribedTopics)) {
            return;
        }
 
        $topic = $this->subscribedTopics[$entryData['category']];
 
        // re-send the data to all the clients subscribed to that category
        $topic->broadcast($entryData);
    }
 
    public function onUnSubscribe(ConnectionInterface $conn, $topic) {
    }
    public function onOpen(ConnectionInterface $conn) {
    }
    public function onClose(ConnectionInterface $conn) {
    }
    public function onCall(ConnectionInterface $conn, $id, $topic, array $params) {
        // In this application if clients send data it's because the user hacked around in console
        $conn->callError($id, $topic, 'You are not allowed to make calls')->close();
    }
    public function onPublish(ConnectionInterface $conn, $topic, $event, array $exclude, array $eligible) {
        // In this application if clients send data it's because the user hacked around in console
        $conn->close();
    }
    public function onError(ConnectionInterface $conn, \Exception $e) {
    }
 }

bin/push-server.php
をSupervisorでの設定により、起動させることによって、Ratchetが常時動作します。
詳しくは→Linux初心者がSupervisorを導入する

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です