hello all, we use namko for our python micro-sevices and so far, it work
great.
our next move will be to allow rpc call from php scripts.
I am working on a proof of concept, which will probably lead to a open
sourced adapter for at least RPC.
(right now, I have a rpc call PHP => python with results.)
but my POC encounter a heavy performance issue.
the setup is a simple consumer-producer.
python consumer call the get method of producer, which return 42.
my benchmark give me from 16s with 5000 async call to 18s with synchronous
call.
but the php script which create reply-to queue and mimic python side, run
in 1.5sec for async, to *263*s (!!!!) for synchronous call.
i don't know if this is somehing to do with eventlet or mono-threading...
but if you have any tips...
the php service code:
<?php
/**
* Created by PhpStorm.
* User: dbernard
* Time: 17:03
*/
require_once __DIR__ . '/vendor/autoload.php';
use PhpAmqpLib\Connection\AMQPStreamConnection;
use PhpAmqpLib\Message\AMQPMessage;
class ConsumerRpcClient {
private $connection;
private $channel;
private $callback_queue;
private $response;
private $corr_id;
private $reply_id;
public function __construct() {
$this->connection = new AMQPStreamConnection(
'172.18.0.2', 5672, 'guest', 'guest');
$this->channel = $this->connection->channel();
$this->channel->basic_qos(null, 10, null);
$this->reply_id = uniqid();
list($this->callback_queue, ,) = $this->channel->queue_declare(
"rpc.reply-phpconsumer-".$this->reply_id, false, false, true, true);
$this->channel->queue_bind($this->callback_queue, 'nameko-rpc', $this->reply_id);
$this->channel->basic_consume(
$this->callback_queue, '', false, false, false, false,
array($this, 'on_response'));
}
public function on_response($rep) {
if($rep->get('correlation_id') == $this->corr_id) {
$this->response = $rep->body;
}
$rep->delivery_info['channel']->basic_ack($rep->delivery_info['delivery_tag']);
}
public function call_async($n) {
$this->response = null;
$this->corr_id = uniqid();
$msg = new AMQPMessage(
(string) $n,
array('correlation_id' => $this->corr_id,
'reply_to' => $this->reply_id,
'content_encoding' => 'utf-8',
'content_type' => 'application/x-myjson'
)
);
$this->channel->basic_publish($msg, 'nameko-rpc', 'producer.get');
}
public function call($n) {
$this->call_async($n);
while(!$this->response) {
$this->channel->wait();
}
return $this->response;
}
};
$consumer_rpc = new ConsumerRpcClient();
$start = microtime(true);
assert( $consumer_rpc->call('{"args": [], "kwargs": {}}') === '{"result": 42, "error": null}');
for ($i = 0; $i < 5000; $i++) {
$consumer_rpc->call('{"args": [], "kwargs": {}}');
}
$end = microtime(true);
echo 'called '.$i.' times in '.($end - $start).' seconds';
the python producer code
class Producer(object):
"""
a fake service that produce data in a specified time
used to test service auto scale
public events
···
* Date: 09/04/18
#############
rcp
###
set(rate)
get()
"""
name = 'producer'
@rpc
def get(self):
"""
create a service on the valide scaler
:param service:
:return:
"""
# eventlet.patcher.original('time').sleep(0.009)
return 42