Hot questions for Using ZeroMQ in ratchet

Question:

I was trying to deploy my websocket server and start running it but always gives:

PHP Fatal error:
Uncaught exception 'React\Socket\ConnectionException'
with message       'Could not bind to tcp://my_ip_here:8080:
                    Address already in use'
in                 /var/www/html/webscoket/vendor/react/socket/src/Server.php:29

here's my server.php:

<?php
require dirname(__DIR__) . '/vendor/autoload.php';

use Ratchet\Server\IoServer;
use Ratchet\Http\HttpServer;
use Ratchet\WebSocket\WsServer;
use React\Socket\Server;
use React\ZMQ\Context;

$loop   = React\EventLoop\Factory::create();
$app    = new onyxsocket();
$webSock = new Server($loop);
$webSock->listen(8080, 'my_ip_here');
$webServer = new IoServer(
    new HttpServer(
        new WsServer(
            $app
        )
    ),
    $webSock
);

$context = new Context($loop);
$pull = $context->getSocket(ZMQ::SOCKET_PULL);
$pull->bind('tcp://my_ip_here:5555');
$pull->on('error', function ($e) {
    var_dump($e->getMessage());
});
$pull->on('message', array($app, 'onbroadcast'));
$loop->run();

What I've tried so far is to check available ports that can be used in the production server: netstat - anp gave me idea that port 8080 is free. But the problem is it still show the error Address already in use. I also tried other ports given by the administrator but no luck.

The server.php that I'm trying to deploy is working fine on localhost. But I don't know what do I need to do to make it work on a production server.

Need help. Thanks.


Answer:

from @user3666197 comment above:

Clarify the code, pls. Your server-code ZeroMQ .bind() -s to port# 5555. So whose code binds to localhost port# 8080, that is reported in an unhandled exception above? How do you clean for a gracefull-exit any crashed EventLoop/Factory to release resources and avoid hanging orphans?

I decided to recheck the netstat: netstat -tulpen and check for the ports 8080 and 5555 and find out that there is registered PID on the port currently connecting. These application was also the same script that I want to run on console, server.php.

I kill the PID: kill PID_number and run the server.php on console again. It worked.

Question:

I have a WebSocket server (modified Ratchet) that uses ZermoMQ for pushing messages to the server. Recently I've migrated the server onto a new VPS.

The implementation is identical but for some reason when I request a PHP script over HTTP, then ZeroMQ doesn't send the payload to the WebSocket server but when I run the script through the terminal, it works.

This is the script that gets new requests to be sent to Websocket Server:

<?php

if(isset($_POST['identity'], $_POST['identifier'], $_POST['env'], $_POST['action'], $_POST['payload'])){
    $identity = $_POST['identity'];
    $identifier = $_POST['identifier'];
    $env = $_POST['env'];
    $action = $_POST['action'];
    $payload = $_POST['payload'];

    $context = new ZMQContext();
    $client = $context->getSocket(ZMQ::SOCKET_PUSH, 'ICU push');
    $client->connect('tcp://127.0.0.1:21002');
    $client->send(json_encode(array('identity' => $identity, 'env' => $env, 'message' => formatRequest($identifier, $action, $payload))));
} else {
    echo "Invalid request";
    exit;
}

And the server start script:

<?php
require_once(__DIR__ . '/../vendor/autoload.php');
require_once(__DIR__ . '/../autoload.php');

use Ratchet\Server\IoServer;
use Ratchet\Http\HttpServer;
use Ratchet\WebSocket\WsServer;
use Ratchet\Wamp\WampServer;
use ICU\Server;
use ICU\Logger;

$logger = new Logger();
$logger->setInteractive(true);

$loop = React\EventLoop\Factory::create();
$server  = new Server('test');

$context = new React\ZMQ\Context($loop);

$pull = $context->getSocket(ZMQ::SOCKET_PULL);
$pull->bind("tcp://127.0.0.1:21002");
$pull->on('message', array($server, 'onNewRequest'));
$logger->info("ZMQ listening on TCP 127.0.0.1:21002");

$webSock = new React\Socket\Server($loop);
$webSock->listen(21001, '0.0.0.0');
$webServer = new IoServer(
    new HttpServer(
        new WsServer(
            new WampServer(
                $server
            )
        )
    ),
    $webSock
);

$logger->info("ICU Server listening on 0.0.0.0:21001");

$loop->run();

The HTTP request itself doesn't fail. Response code is 200 and there are no errors in error log. Also when echoing through-out the script, I see the script gets executed fully but ZeroMQ won't send it to the Websocket server.

I checked with netstat and ports 21001 and 21002 are running and listening. Also I added iptables entries for both (though 21001 should be enough since ZeroMQ is only used on the local level but just in case).

This is a CentOS 7 server and I have libzmq installed along with the zmq pecl extension.

$ php -i | grep "zmq"
/etc/php.d/zmq.ini
zmq
libzmq version => 4.1.3

Have I missed something in my code or could this be a server configuration issue?


Answer:

After many days of debugging, the issue fell to SELinux.

It seems that ZeroMQ connections get denied when SELinux is in enforcing mode.

For anyone encountering such issue, you need to disable SELinux:

sudo setenforce 0

Question:

I am using PHP Ratchet (push integration) for my app with real time biddings and it works like a charm.

Due to high traffic we moved our app on AWS platform and we have a multiple app server instances and one of them (Ratchet).

$pull->bind('tcp://127.0.0.1:5555'); // Binding to 127.0.0.1 means the only client that can connect is itself

This means than I can connect only from one app instance, but can I add here mutliple clients (my app instances on AWS)? I need to connect from multiple localhosts machines due to load balancing.

Is there any way for doing this?


Answer:

You can bind to 0.0.0.0 instead of 127.0.0.1 which will allow all connections from any server as long as they can access port 5555 on that machine.

Question:

I am setting up a blog between our clients and us so they can have a space to talk about the different commercial transactions (each commercial transaction has a reference number and has it's own information).

Right now I was able to setup Ratchet with ZeroMQ and Autobahn to achieve this. Whenever a user updates the blog, the rest of the users who are subscribed to them get the information pushed into their browsers.

However, I have the subscription method linked to a button in the main page. (The whole idea is that they will click on the reference on the left menu bar, and the blog entries will appear on the right side of the screen).

What this is causing is that if the user clicks on the same reference multiple times, or if the user goes to other reference and then comes back to the first reference, whenever there's an update on the blog, the user receives multiple updates (one per click -> each click triggers a subscription).

Any idea how to prevent this from happening?

Here's how the jquery that creates the session looks like:

$('.reference-container').on('click', function(){
    idReferencia = $(this).attr('id');
    $('#modifyReference').val(idReferencia);

    console.log('Creating connection with server on topic: ' + idReferencia + '..');


    var conn = new ab.Session('wss://plt.prolog-mex.com/wss2/',

        function() {
            conn.subscribe(idReferencia, function(topic, data) {
                $('#messageBoard').prepend('<p class="message-nonown">'+data.article+'</p>')
                console.log('New article published to category "' + topic + '" : ' + data.title);
            });
        },
        function() {
            console.warn('WebSocket connection closed');
        },
        {'skipSubprotocolCheck': true}
    );
    console.log
});

Answer:

You are creating both a new WAMP session and a subscription on that session on each button click.

What you should do is check on click whether both already exist, and just do nothing if this is the case.

Question:

I am trying to follow this tutorial for Ratchet/ZMQ Socket programming: http://socketo.me/docs/push

with a bit of customisation to learn abit more about it.

The server itself is running fine and the connection between front-end html seems to be connecting right. But I cant figure the PHP file that sends a message to the server.

CODES BELOW:

SENDER.PHP

$context    = new ZMQContext();
$socket     = $context->getSocket(ZMQ::SOCKET_PUSH,'my pusher');
$socket->connect('tcp://127.0.0.1:5555');
$socket->send("SENDING A MESSAGE");

The code above is what Im having problems with. When I run the code in the command line

php sender.php

The server should at least display some feed back but it doesnt give me anything. And the sender.php just exits. Im stuck trying to figure out what Im missing. At least the front-html bit works. How can I get the sender.php to send the message? Any suggestion/advise/help would be greatly appreciated.

Below are the rest of my codes:

INDEX.html

This html file is connecting as Im getting the message from the constructor.

ab.debug(true,true);
var conn = new ab.Session('ws://localhost:8080',
        function() {
            conn.subscribe('kittensCategory', function(data) {
                // This is where you would add the new article to the DOM (beyond the scope of this tutorial)
                console.log("New data available: ",data);
            });
        },
        function() {
            console.warn('WebSocket connection closed');
        },
        {'skipSubprotocolCheck': true}
);

SERVER.PHP

use Models\SCSTRealtimeSubsObject;

// The event loop that will keep on triggering
$loop   = React\EventLoop\Factory::create();

// Our custom pusher that will do the logic, $loop is optional
$pusher =  new SCSTRealtimeSubsObject;

// 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);
//Binding to itself means the client can only connect to itself
$pull->bind("tcp://127.0.0.1:5555");
//On a 'message' event, pass the data to the myMessageHandler method of the MyPusherClass
$pull->on('message', array($pusher, 'customAction'));

// Set up our WebSocket server for clients wanting real-time updates
$webSock = new React\Socket\Server('0.0.0.0:8080', $loop); // 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();

PUSHER.PHP

class SCSTRealtimeSubsObject implements WampServerInterface {

    public function __construct() {
        echo "Constructor call. \n";
    }
    public function customAction($msg){ // Message from the onMessage
        echo "There was a message: $msg";
    }
    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
    //                  WampServerInterface Implementations
    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

    public function onOpen(ConnectionInterface $conn) {
        echo "New connection! ({$conn->resourceId}) \n";
    }
    public function onClose(ConnectionInterface $conn) {
        // The connection is closed, remove it, as we can no longer send it messages
        echo "Connection {$conn->resourceId} has disconnected \n";
    }
    public function onError(ConnectionInterface $conn, \Exception $e) {
        echo "There is an error ". $e->getMessage();
    }
    public function onSubscribe(ConnectionInterface $conn, $topic) {
        echo "New subscriber : $topic \n";
    }
    public function onUnSubscribe(ConnectionInterface $conn, $topic) {
        echo "Unsubscribed : $topic \n";
    }
    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
        echo "Published $topic. \n";
        $conn->close();
    }
}

Answer:

Finally found the answer. I forgot to enclosed that my development server is on Windows.

In my case, php cli is firewalled by windows and is blocked from accessing any networks and ports.

To fix this go to control panel -> windows firewall. Look for inbound CLI this is most likely the PhP exe. Allow access to network and that should do the trick.

Question:

I am using PHP and ratchet, I am dealing with how I can create an event from the server side and push it to the clients.

I know I can use ZeroMQ, but this will also create an overhead, each time an event has to be notified, a new socket connection is made.

So I was wondering, wouldn't that be better to have a thread which is always selecting from a MySQL table named "SocketQueue" using memory as engine?

Does this architecture make the app lose the attribute of "Realtime"?


Answer:

Lets first skip the marketing lingoand focus on rigorous system design

While one can read a lot of tags like real-time, ultra-fast, low-latency, these do not represent the same and have much different level of importance in rigorous system design decisions.

Fast

Yes, speed is a nice to have feature, but not always could be achieved at a reasonable cost or uniformly guaranteed including worst-case situations in production eco-system. So being "fast" helps, but is not a cornerstone in a real-time system design.

Low-latency

The same applies here, latency is a principal cost one has to pay on transaction under review. Again, it is fine, if the latency scale is not a-priori devastating the system design, but once it is feasible in principle, the real-time system design is focused rather on latency jitter, not on a latency value per se, as we have to live with the reality and the system has to be proved to robustly handle all the various latency levels as an indivisible part of the production eco-system reality.

Real-time

Well, a system may be called a real-time system, if it has such a property, that the design has been cross-validated by a rigorous a-priori proof that under all possible circumstances, the real-time execution scheduling has robustly met a given internal time-horizon, within which the system has a positive proof of it's ability to "be always in time" for all of it's internal processing sub-tasks.

In case any item from this semidefinition aboveis not present - be it: - R/T-design internal scheduling time horizon - R/T-design validation - R/T-design positive proof of it's robustness in "being always in time" under conditions abovethe efforts fail to be rigorously real-timeand cannot hold an attribute of "Real-Time"

A carefull reader has already noticed, that the rules of real-time-ness did not say anything about how long that internal scheduling time-horizon is about to last.

Yes, real-time system can have it's abilities designed and positively proved to robustly meet all sub-tasks within a horizon of 1 [us] or 1 [ms] or 1[s] or 1 [min] or 1 [hour], whereas in all cases the real-time execution is considered as a rigorous real-time system.

Do Real-time systems, having about an hour long scheduling, have still some reason? Sure they have and are quite a common design target, just imagine an Earth / Deep-Space Satellite radio-uplink and ground control station operations coordinated across a link, that takes a few hours to just get any telemetry/control data there and back.

Yes, not all real world processes can live with such long scheduling horizon, and need to have this threshold on a safe distance from a Nyquist stability criterion, because the controlled process imposes some additional conditions for stable ( i.e. robust ) control.

At the same time, going to the far end of the opposite end of the real-time scheduling spectrum, too tight scheduling time-horizons need not save the Project as design has to fit into all real-hardware material constraints ( no one can send signals faster than a speed of light ( and forget about Quantum Entaglement, even this will not save you in this ), power-consumption limitations and still be economically feasible, including the costs of system-design, programming and validation.

Just-Enough-Scaling is a must

Back to the sketched components.

ZeroMQ ought be considered as a rather persistent communication + signalling layer. My distributed system applications use ZeroMQ and benefit from this approach and provide reasonable services, under a due care, down to some tens of [us] scheduling framing.

Any attempt to setup a ZeroMQ socket ad-hoc is a no-go idea, as the setup overheads are not in line with real-time design intentions. This is an imperative engineering practice to setup these a-priori, once the system is being started and perform the self-diagnosing tasks, before the whole eco-system could be declared as RTO in an R/T mode.

Your [messaging+signalling]-layer design does not need to have an external dependency on any MySQL table to decide on proper routing of the messages / signal distribution. May need to spend some longer time with the ZeroMQ internalities, but this is one of the strongest powers of the ZeroMQ specialisation.

For the sake of a real-time mode of operations, ZeroMQ does not depend on any Message-Broker entity, which would make your real-time designs another level of nightmare, as your design cannot have any tools/controls on this (btw. a core)-element of the messaging/signalling layer, while your sub-tasks are all heavily dependent on the smooth, just-enough-long latency of Broker-mediated message/signal delivery.

MySQL engine will have the biggest variance in "being always in time". Vast engineering efforts are to be expected in providing a reasonable set of non-traditional programming approaches so as to bear the responsibility to positively proof the robustness of sub-task scheduling.

Question:

I'm creating a chat on my website, a push notifications system, users activity widget ( updating on the fly ) etc.

My website is built on PHP, so I decided to use Ratchet as a websocket server for my tasks. I've installed all required components and I learned the guide on http://socketo.me/docs/push and started to code.

This is inside a ChatMsg( $item ){...} method in the model.php file. It creates a PUSH socket-access-point archetype and sends a message with JSON-data to server via ZeroMQ after inserting a new item in a database:

$context = new ZMQContext();
$socket = $context->getSocket(ZMQ::SOCKET_PUSH, 'my pusher');
$socket->connect("tcp://localhost:5555");
$socket->send(json_encode($sData));

Answer:

I created not persistent ZMQ::Context and ZMQ::Socket and my problem was solved:

$context = new ZMQContext(1, false);
$socket = $context->getSocket(ZMQ::SOCKET_PUSH);

Question:

I'm trying to install ZeroMQ for the push integration on Ratchet, I have successfully integrated Ratchet unto my Laravel 5 app. I downloaded and install the zeroMQ software and in the PHP binding instruction page, I followed the set up instruction for windows section since I'm on windows 10

Download the latest snapshot from http://snapshot.zero.mq/

Copy libzmq.dll into your php directory (e.g. C:\wamp\bin\php\php5.3.8)

Copy the appropriate version of php_zmq.dll to your php extension directory (e.g. C:\wamp\bin\php\php5.3.8\ext)

Add the following line to your php.ini:

extension=php_zmq.dll

since http://snapshot.zero.mq/ is a broken link so I look around the internet for other source and I found this link and downloaded the php_zmq-1.1.3-7.0-ts-vc14-x64.zip one. I copy the libzmq.dll to C:\wamp\bin\php\php5.5.12 as instructed as well as the php_zmq.dll to C:\wamp\bin\php\php5.5.12\ext and then I add

extension=php_zmq.dll

to my php ini and restarted my wamp server but it throws me this warning,

PHP Startup: Unable to load dynamic library 'c/wamp/bin/php/php5.5.12/ext/php_zmq.dll' - The specified module could not be found

Any ideas, help please?


Answer:

I downloaded the correct file from here https://pecl.php.net/package/zmq that match unto my php version and then restart my computer and now its working.