ZeroMQ + libevent in 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.
Comments
Display comments as Linear | Threaded
Christian Soronellas on :
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 :
Rasmus on :
Amaury Bouchard on :
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 :
George Cooper on :
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