Skip to content

ZeroMQ + libevent in PHP

PHP While waiting for a connection in Frankfurt I had a quick look at what it would take to make ZeroMQ and libevent co-exist in PHP and it was actually quite easy. Well, easy after Mikko Koppanen added a way to get the underlying socket fd from the ZeroMQ PHP extension. To get this working, install the PHP ZeroMQ extension and the PHP libevent extension. First, a little event-driven server that listens on loopback port 5555 and waits for 10 messages and then exits.

Server.php

<?php
function print_line($fd, $events, $arg) {
    static $msgs = 1; 
    echo "CALLBACK FIRED" . PHP_EOL;
    if($arg[0]->getsockopt (ZMQ::SOCKOPT_EVENTS) & ZMQ::POLL_IN) {
        echo "Got incoming data" . PHP_EOL;
        var_dump ($arg[0]->recv());
        $arg[0]->send("Got msg $msgs");
	if($msgs++ >= 10) event_base_loopexit($arg[1]);
    }
}

// create base and event
$base = event_base_new();
$event = event_new();

// Allocate a new context
$context = new ZMQContext();

// Create sockets
$rep = $context->getSocket(ZMQ::SOCKET_REP);

// Connect the socket
$rep->bind("tcp://127.0.0.1:5555");

// Get the stream descriptor
$fd = $rep->getsockopt(ZMQ::SOCKOPT_FD);

// set event flags
event_set($event, $fd, EV_READ | EV_PERSIST, "print_line", array($rep, $base));

// set event base
event_base_set($event, $base);

// enable event
event_add($event);

// start event loop
event_base_loop($base);

Client.php

<?php
// Create new queue object
$queue = new ZMQSocket(new ZMQContext(), ZMQ::SOCKET_REQ, "MySock1");
$queue->connect("tcp://127.0.0.1:5555");

// Assign socket 1 to the queue, send and receive
var_dump($queue->send("hello there!")->recv());

You will notice when you run it that the server gets a couple of events that are not actually incoming messages. Right now ZeroMQ doesn't expose the nature of these events, but they are the socket initialization and client connect. You will also get one for the client disconnect. A future version of the ZeroMQ library will expose these so you can properly catch when clients connect to your server.

There really isn't much else to say. The code should be self-explanatory. If not, see the PHP libevent docs and the PHP ZeroMQ docs. And if you build something cool with this, please let me know.

Trackbacks

No Trackbacks

Comments

Display comments as Linear | Threaded

Christian Soronellas on :

Hi Rasmus,

Great post! Congrats for it! :D In fact I'm writing an HTTP server based on libevent (for now, is on early development stages) ... but I didn't think to use ZMQ and I just realize that could be interesting to use it ...

If want to check it, it's on github!

https://github.com/theUniC/Hawk

Greetings!
Christian.

Amaury Bouchard on :

For this kind of development, is there a real benefit to use libevent instead of ZeroMQ's polling feature?

Rasmus on :

If all you are doing is ZeroMQ, perhaps not. But if you are also fielding other types of events then zmq's polling isn't going to help you, and you probably don't want to use both libevent and the built-in polling. In those cases making zmq play nice with libevent becomes quite important.

Amaury Bouchard on :

In addition to ZMQ sockets, ZMQ's polling is able to manage any PHP sockets and streams, as well as timeouts. Maybe it's less configurable than libevent, but I never found a real use case where a feature was missing.

Libevent is pretty smart (using epoll, kqueue, ...). I don't know how ZMQ's polling is implemented; perhaps there is some systems on which it's less optimized than libevent, but honestly I never saw any problem with it.

Am I missing something?

Rasmus on :

zmq_poll() doesn't use epoll/kqueue, it is just a regular poll(). zmq does use epoll/kqueue for the internal io threads. However, I am not sure there is much of a performance difference in this case. It might be nice to get some benchmarks on that. Beyond the epoll/kqueue thing, libevent also has a richer featureset and if you already have a libevent-based application it is useful to know that you can slide zmq in there quite easily.

George Cooper on :

Christian,

We've been playing with this concept for a little over a month now. In fact, our lead engineer on this is named Christian too! Pretty funny.

If you want to see some of what we're doing, check out https://sourceforge.net/projects/eglooframework on the branch feature/Server.

Early benchmarks are impressive. We've been one of the fastest frameworks for a while now and are starting to get traction - Petflow.com uses us for instance - but once we started implementing our stateful context model we saw performance gains of over 1800% w/ Smarty and almost a full 2500% w/ embedded template engine extensions.

Check us out. Always interested in feedback.

Best,
George

Add Comment

Enclosing asterisks marks text as bold (*word*), underscore are made via _word_.
E-Mail addresses will not be displayed and will only be used for E-Mail notifications.
Form options