# php nameko adapter

**URL:** <https://discourse.nameko.io/t/php-nameko-adapter/251>\
**Category:** googlegroup\
**Created:** [April 10, 2018, 10:20am UTC](https://discourse.nameko.io/t/php-nameko-adapter/251 "2018-04-10T10:20:22Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![Darius](https://avatars.discourse-cdn.com/v4/letter/d/58956e/32.png) [@Darius](https://discourse.nameko.io/u/Darius)\
**Post date:** [April 10, 2018, 10:20am UTC](https://discourse.nameko.io/t/php-nameko-adapter/251/1 "2018-04-10T10:20:22Z")

</div>

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 {  
&nbsp;&nbsp;&nbsp;private $connection;  
&nbsp;&nbsp;&nbsp;private $channel;  
&nbsp;&nbsp;&nbsp;private $callback\_queue;  
&nbsp;&nbsp;&nbsp;private $response;  
&nbsp;&nbsp;&nbsp;private $corr\_id;  
&nbsp;&nbsp;&nbsp;private $reply\_id;

&nbsp;&nbsp;&nbsp;public function \_\_construct() {  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-\>connection = new AMQPStreamConnection(  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'172.18.0.2', 5672, 'guest', 'guest');  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-\>channel = $this-\>connection-\>channel();  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-\>channel-\>basic\_qos(null, 10, null);  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-\>reply\_id = uniqid();  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;list($this-\>callback\_queue, ,) = $this-\>channel-\>queue\_declare(  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"rpc.reply-phpconsumer-".$this-\>reply\_id, false, false, true, true);  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-\>channel-\>queue\_bind($this-\>callback\_queue, 'nameko-rpc', $this-\>reply\_id);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-\>channel-\>basic\_consume(  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-\>callback\_queue, '', false, false, false, false,  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;array($this, 'on\_response'));  
&nbsp;&nbsp;&nbsp;}  
&nbsp;&nbsp;&nbsp;public function on\_response($rep) {  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if($rep-\>get('correlation\_id') == $this-\>corr\_id) {  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-\>response = $rep-\>body;  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$rep-\>delivery\_info['channel']-\>basic\_ack($rep-\>delivery\_info['delivery\_tag']);  
&nbsp;&nbsp;&nbsp;}  
&nbsp;&nbsp;&nbsp;public function call\_async($n) {  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-\>response = null;  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-\>corr\_id = uniqid();

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$msg = new AMQPMessage(  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(string) $n,  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;array('correlation\_id' =\> $this-\>corr\_id,  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'reply\_to' =\> $this-\>reply\_id,  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'content\_encoding' =\> 'utf-8',  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'content\_type' =\> 'application/x-myjson'

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;);  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-\>channel-\>basic\_publish($msg, 'nameko-rpc', 'producer.get');  
&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;public function call($n) {  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-\>call\_async($n);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while(!$this-\>response) {  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-\>channel-\>wait();  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return $this-\>response;  
&nbsp;&nbsp;&nbsp;}  
};

$consumer\_rpc = new ConsumerRpcClient();  
$start = microtime(true);

assert( $consumer\_rpc-\>call('{"args": [], "kwargs": {}}') === '{"result": 42, "error": null}');

for ($i = 0; $i \< 5000; $i++) {  
&nbsp;&nbsp;&nbsp;$consumer\_rpc-\>call('{"args": [], "kwargs": {}}');  
}  
$end = microtime(true);  
echo 'called '.$i.' times in '.($end - $start).' seconds';

the python producer code

class Producer(object):  
&nbsp;&nbsp;&nbsp;&nbsp;"""  
&nbsp;&nbsp;&nbsp;&nbsp;a fake service that produce data in a specified time  
&nbsp;&nbsp;&nbsp;&nbsp;used to test service auto scale  
&nbsp;&nbsp;&nbsp;&nbsp;  
&nbsp;&nbsp;&nbsp;&nbsp;public events

> **···**
>
> \* Date: 09/04/18  
> &nbsp;&nbsp;&nbsp;&nbsp;#############  
> &nbsp;&nbsp;&nbsp;&nbsp;  
> &nbsp;&nbsp;&nbsp;&nbsp;rcp  
> &nbsp;&nbsp;&nbsp;&nbsp;###  
> &nbsp;&nbsp;&nbsp;&nbsp;  
> &nbsp;&nbsp;&nbsp;&nbsp;set(rate)  
> &nbsp;&nbsp;&nbsp;&nbsp;  
> &nbsp;&nbsp;&nbsp;&nbsp;get()  
> &nbsp;&nbsp;&nbsp;&nbsp;  
> &nbsp;&nbsp;&nbsp;&nbsp;"""  
> &nbsp;&nbsp;&nbsp;&nbsp;name = 'producer'
> 
> &nbsp;&nbsp;&nbsp;&nbsp;@rpc  
> &nbsp;&nbsp;&nbsp;&nbsp;def get(self):  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"""  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;create a service on the valide scaler  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:param service:  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:return:  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"""  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# eventlet.patcher.original('time').sleep(0.009)  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return 42

---

<div class="post-metadata">

**Author:** ![mattbennett](https://yyz1.discourse-cdn.com/flex031/user_avatar/discourse.nameko.io/mattbennett/32/13_2.png) [@mattbennett](https://discourse.nameko.io/u/mattbennett)\
**Post date:** [April 11, 2018, 9:08am UTC](https://discourse.nameko.io/t/php-nameko-adapter/251/2 "2018-04-11T09:08:28Z")

</div>

Your benchmark should be the standalone RPC client found in  
nameko.standalone.rpc -- this is a single-threaded, non-eventlet  
implementation.

Are you creating a new reply queue for every request? That would kill your  
performance.

Also check that your client is allowing multiple RPC requests to be in  
flight at the same time, rather than waiting for a reply before dispatching  
the next one.

> **···**
>
> On Tuesday, 10 April 2018 11:20:22 UTC+1, dar...@yupeek.com wrote:
> 
> > 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  
> > \* Date: 09/04/18  
> > \* Time: 17:03  
> > \*/
> > 
> > require\_once \_\_DIR\_\_ . '/vendor/autoload.php';  
> > use PhpAmqpLib\Connection\AMQPStreamConnection;  
> > use PhpAmqpLib\Message\AMQPMessage;
> > 
> > class ConsumerRpcClient {  
> > &nbsp;&nbsp;&nbsp;private $connection;  
> > &nbsp;&nbsp;&nbsp;private $channel;  
> > &nbsp;&nbsp;&nbsp;private $callback\_queue;  
> > &nbsp;&nbsp;&nbsp;private $response;  
> > &nbsp;&nbsp;&nbsp;private $corr\_id;  
> > &nbsp;&nbsp;&nbsp;private $reply\_id;
> > 
> > &nbsp;&nbsp;&nbsp;public function \_\_construct() {  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-\>connection = new AMQPStreamConnection(  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'172.18.0.2', 5672, 'guest', 'guest');  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-\>channel = $this-\>connection-\>channel();  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-\>channel-\>basic\_qos(null, 10, null);  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-\>reply\_id = uniqid();  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;list($this-\>callback\_queue, ,) = $this-\>channel-\>queue\_declare(  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"rpc.reply-phpconsumer-".$this-\>reply\_id, false, false, true, true);  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-\>channel-\>queue\_bind($this-\>callback\_queue, 'nameko-rpc', $this-\>reply\_id);
> > 
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-\>channel-\>basic\_consume(  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-\>callback\_queue, '', false, false, false, false,  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;array($this, 'on\_response'));  
> > &nbsp;&nbsp;&nbsp;}  
> > &nbsp;&nbsp;&nbsp;public function on\_response($rep) {  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if($rep-\>get('correlation\_id') == $this-\>corr\_id) {  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-\>response = $rep-\>body;  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$rep-\>delivery\_info['channel']-\>basic\_ack($rep-\>delivery\_info['delivery\_tag']);  
> > &nbsp;&nbsp;&nbsp;}  
> > &nbsp;&nbsp;&nbsp;public function call\_async($n) {  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-\>response = null;  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-\>corr\_id = uniqid();
> > 
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$msg = new AMQPMessage(  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(string) $n,  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;array('correlation\_id' =\> $this-\>corr\_id,  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'reply\_to' =\> $this-\>reply\_id,  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'content\_encoding' =\> 'utf-8',  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'content\_type' =\> 'application/x-myjson'
> > 
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;)  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;);  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-\>channel-\>basic\_publish($msg, 'nameko-rpc', 'producer.get');  
> > &nbsp;&nbsp;&nbsp;}
> > 
> > &nbsp;&nbsp;&nbsp;public function call($n) {  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-\>call\_async($n);
> > 
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while(!$this-\>response) {  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-\>channel-\>wait();  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return $this-\>response;  
> > &nbsp;&nbsp;&nbsp;}  
> > };
> > 
> > $consumer\_rpc = new ConsumerRpcClient();  
> > $start = microtime(true);
> > 
> > assert( $consumer\_rpc-\>call('{"args": , "kwargs": {}}') === '{"result": 42, "error": null}');
> > 
> > for ($i = 0; $i \< 5000; $i++) {  
> > &nbsp;&nbsp;&nbsp;$consumer\_rpc-\>call('{"args": , "kwargs": {}}');  
> > }  
> > $end = microtime(true);  
> > echo 'called '.$i.' times in '.($end - $start).' seconds';
> > 
> > the python producer code
> > 
> > class Producer(object):  
> > &nbsp;&nbsp;&nbsp;&nbsp;"""  
> > &nbsp;&nbsp;&nbsp;&nbsp;a fake service that produce data in a specified time  
> > &nbsp;&nbsp;&nbsp;&nbsp;used to test service auto scale  
> > &nbsp;&nbsp;&nbsp;&nbsp;  
> > &nbsp;&nbsp;&nbsp;&nbsp;public events  
> > &nbsp;&nbsp;&nbsp;&nbsp;#############  
> > &nbsp;&nbsp;&nbsp;&nbsp;  
> > &nbsp;&nbsp;&nbsp;&nbsp;rcp  
> > &nbsp;&nbsp;&nbsp;&nbsp;###  
> > &nbsp;&nbsp;&nbsp;&nbsp;  
> > &nbsp;&nbsp;&nbsp;&nbsp;set(rate)  
> > &nbsp;&nbsp;&nbsp;&nbsp;  
> > &nbsp;&nbsp;&nbsp;&nbsp;get()  
> > &nbsp;&nbsp;&nbsp;&nbsp;  
> > &nbsp;&nbsp;&nbsp;&nbsp;"""  
> > &nbsp;&nbsp;&nbsp;&nbsp;name = 'producer'
> > 
> > &nbsp;&nbsp;&nbsp;&nbsp;@rpc  
> > &nbsp;&nbsp;&nbsp;&nbsp;def get(self):  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"""  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;create a service on the valide scaler  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:param service:  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:return:  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"""  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# eventlet.patcher.original('time').sleep(0.009)  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return 42

---

<div class="post-metadata">

**Author:** ![Darius](https://avatars.discourse-cdn.com/v4/letter/d/58956e/32.png) [@Darius](https://discourse.nameko.io/u/Darius)\
**Post date:** [April 11, 2018, 9:41am UTC](https://discourse.nameko.io/t/php-nameko-adapter/251/3 "2018-04-11T09:41:44Z")

</div>

thanks for the reply 🙂

I wrote a standalone client which work with similar performances as the  
service oriented one (18s for 5000 calls), so it seem it's not that.

there is only one queue created, and every 5000 calls use it for reply. the  
for reuse the same connexion.

my python benchmark with problem is synchronous (wait for reply before  
sending other request). the php implementation do it the same way.

I did a xhprof for the php script, and the time cost is in the fread  
function. so it seem it's not the php script which is incrimined, but it  
wait looooong for the reply from rabbitmq.

I will work on it to implement a better request, respecting all header ans  
property sent by nameko implementation.

is there a specific missing header that can lead the producer to run very  
slowly ?

> **···**
>
> Le mercredi 11 avril 2018 11:08:28 UTC+2, Matt Yule-Bennett a écrit :
> 
> > Your benchmark should be the standalone RPC client found in  
> > nameko.standalone.rpc -- this is a single-threaded, non-eventlet  
> > implementation.
> > 
> > Are you creating a new reply queue for every request? That would kill your  
> > performance.
> > 
> > Also check that your client is allowing multiple RPC requests to be in  
> > flight at the same time, rather than waiting for a reply before dispatching  
> > the next one.
> > 
> > On Tuesday, 10 April 2018 11:20:22 UTC+1, dar...@yupeek.com wrote:
> > 
> > > 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  
> > > \* Date: 09/04/18  
> > > \* Time: 17:03  
> > > \*/
> > > 
> > > require\_once \_\_DIR\_\_ . '/vendor/autoload.php';  
> > > use PhpAmqpLib\Connection\AMQPStreamConnection;  
> > > use PhpAmqpLib\Message\AMQPMessage;
> > > 
> > > class ConsumerRpcClient {  
> > > &nbsp;&nbsp;&nbsp;private $connection;  
> > > &nbsp;&nbsp;&nbsp;private $channel;  
> > > &nbsp;&nbsp;&nbsp;private $callback\_queue;  
> > > &nbsp;&nbsp;&nbsp;private $response;  
> > > &nbsp;&nbsp;&nbsp;private $corr\_id;  
> > > &nbsp;&nbsp;&nbsp;private $reply\_id;
> > > 
> > > &nbsp;&nbsp;&nbsp;public function \_\_construct() {  
> > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-\>connection = new AMQPStreamConnection(  
> > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'172.18.0.2', 5672, 'guest', 'guest');  
> > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-\>channel = $this-\>connection-\>channel();  
> > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-\>channel-\>basic\_qos(null, 10, null);  
> > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-\>reply\_id = uniqid();  
> > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;list($this-\>callback\_queue, ,) = $this-\>channel-\>queue\_declare(  
> > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"rpc.reply-phpconsumer-".$this-\>reply\_id, false, false, true, true);  
> > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-\>channel-\>queue\_bind($this-\>callback\_queue, 'nameko-rpc', $this-\>reply\_id);
> > > 
> > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-\>channel-\>basic\_consume(  
> > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-\>callback\_queue, '', false, false, false, false,  
> > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;array($this, 'on\_response'));  
> > > &nbsp;&nbsp;&nbsp;}  
> > > &nbsp;&nbsp;&nbsp;public function on\_response($rep) {  
> > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if($rep-\>get('correlation\_id') == $this-\>corr\_id) {  
> > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-\>response = $rep-\>body;  
> > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}  
> > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$rep-\>delivery\_info['channel']-\>basic\_ack($rep-\>delivery\_info['delivery\_tag']);  
> > > &nbsp;&nbsp;&nbsp;}  
> > > &nbsp;&nbsp;&nbsp;public function call\_async($n) {  
> > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-\>response = null;  
> > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-\>corr\_id = uniqid();
> > > 
> > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$msg = new AMQPMessage(  
> > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(string) $n,  
> > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;array('correlation\_id' =\> $this-\>corr\_id,  
> > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'reply\_to' =\> $this-\>reply\_id,  
> > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'content\_encoding' =\> 'utf-8',  
> > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'content\_type' =\> 'application/x-myjson'
> > > 
> > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;)  
> > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;);  
> > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-\>channel-\>basic\_publish($msg, 'nameko-rpc', 'producer.get');  
> > > &nbsp;&nbsp;&nbsp;}
> > > 
> > > &nbsp;&nbsp;&nbsp;public function call($n) {  
> > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-\>call\_async($n);
> > > 
> > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while(!$this-\>response) {  
> > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-\>channel-\>wait();  
> > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}  
> > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return $this-\>response;  
> > > &nbsp;&nbsp;&nbsp;}  
> > > };
> > > 
> > > $consumer\_rpc = new ConsumerRpcClient();  
> > > $start = microtime(true);
> > > 
> > > assert( $consumer\_rpc-\>call('{"args": , "kwargs": {}}') === '{"result": 42, "error": null}');
> > > 
> > > for ($i = 0; $i \< 5000; $i++) {  
> > > &nbsp;&nbsp;&nbsp;$consumer\_rpc-\>call('{"args": , "kwargs": {}}');  
> > > }  
> > > $end = microtime(true);  
> > > echo 'called '.$i.' times in '.($end - $start).' seconds';
> > > 
> > > the python producer code
> > > 
> > > class Producer(object):  
> > > &nbsp;&nbsp;&nbsp;&nbsp;"""  
> > > &nbsp;&nbsp;&nbsp;&nbsp;a fake service that produce data in a specified time  
> > > &nbsp;&nbsp;&nbsp;&nbsp;used to test service auto scale  
> > > &nbsp;&nbsp;&nbsp;&nbsp;  
> > > &nbsp;&nbsp;&nbsp;&nbsp;public events  
> > > &nbsp;&nbsp;&nbsp;&nbsp;#############  
> > > &nbsp;&nbsp;&nbsp;&nbsp;  
> > > &nbsp;&nbsp;&nbsp;&nbsp;rcp  
> > > &nbsp;&nbsp;&nbsp;&nbsp;###  
> > > &nbsp;&nbsp;&nbsp;&nbsp;  
> > > &nbsp;&nbsp;&nbsp;&nbsp;set(rate)  
> > > &nbsp;&nbsp;&nbsp;&nbsp;  
> > > &nbsp;&nbsp;&nbsp;&nbsp;get()  
> > > &nbsp;&nbsp;&nbsp;&nbsp;  
> > > &nbsp;&nbsp;&nbsp;&nbsp;"""  
> > > &nbsp;&nbsp;&nbsp;&nbsp;name = 'producer'
> > > 
> > > &nbsp;&nbsp;&nbsp;&nbsp;@rpc  
> > > &nbsp;&nbsp;&nbsp;&nbsp;def get(self):  
> > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"""  
> > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;create a service on the valide scaler  
> > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:param service:  
> > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:return:  
> > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"""  
> > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# eventlet.patcher.original('time').sleep(0.009)  
> > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return 42

---

<div class="post-metadata">

**Author:** ![mattbennett](https://yyz1.discourse-cdn.com/flex031/user_avatar/discourse.nameko.io/mattbennett/32/13_2.png) [@mattbennett](https://discourse.nameko.io/u/mattbennett)\
**Post date:** [April 11, 2018, 12:23pm UTC](https://discourse.nameko.io/t/php-nameko-adapter/251/4 "2018-04-11T12:23:06Z")

</div>

No header that I'm aware of would cause performance problems if missing.

You may want to check out the issue  
at [Missing detailed docs on RPC implementation (integration with other frameworks) · Issue #354 · nameko/nameko · GitHub](https://github.com/nameko/nameko/issues/354) for some detailed info on  
the RPC implementation.

> **···**
>
> On Wednesday, April 11, 2018 at 10:41:44 AM UTC+1, dar...@yupeek.com wrote:
> 
> > thanks for the reply 🙂
> > 
> > I wrote a standalone client which work with similar performances as the  
> > service oriented one (18s for 5000 calls), so it seem it's not that.
> > 
> > there is only one queue created, and every 5000 calls use it for reply.  
> > the for reuse the same connexion.
> > 
> > my python benchmark with problem is synchronous (wait for reply before  
> > sending other request). the php implementation do it the same way.
> > 
> > I did a xhprof for the php script, and the time cost is in the fread  
> > function. so it seem it's not the php script which is incrimined, but it  
> > wait looooong for the reply from rabbitmq.
> > 
> > I will work on it to implement a better request, respecting all header ans  
> > property sent by nameko implementation.
> > 
> > is there a specific missing header that can lead the producer to run very  
> > slowly ?
> > 
> > Le mercredi 11 avril 2018 11:08:28 UTC+2, Matt Yule-Bennett a écrit :
> > 
> > > Your benchmark should be the standalone RPC client found in  
> > > nameko.standalone.rpc -- this is a single-threaded, non-eventlet  
> > > implementation.
> > > 
> > > Are you creating a new reply queue for every request? That would kill  
> > > your performance.
> > > 
> > > Also check that your client is allowing multiple RPC requests to be in  
> > > flight at the same time, rather than waiting for a reply before dispatching  
> > > the next one.
> > > 
> > > On Tuesday, 10 April 2018 11:20:22 UTC+1, dar...@yupeek.com wrote:
> > > 
> > > > 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  
> > > > \* Date: 09/04/18  
> > > > \* Time: 17:03  
> > > > \*/
> > > > 
> > > > require\_once \_\_DIR\_\_ . '/vendor/autoload.php';  
> > > > use PhpAmqpLib\Connection\AMQPStreamConnection;  
> > > > use PhpAmqpLib\Message\AMQPMessage;
> > > > 
> > > > class ConsumerRpcClient {  
> > > > &nbsp;&nbsp;&nbsp;private $connection;  
> > > > &nbsp;&nbsp;&nbsp;private $channel;  
> > > > &nbsp;&nbsp;&nbsp;private $callback\_queue;  
> > > > &nbsp;&nbsp;&nbsp;private $response;  
> > > > &nbsp;&nbsp;&nbsp;private $corr\_id;  
> > > > &nbsp;&nbsp;&nbsp;private $reply\_id;
> > > > 
> > > > &nbsp;&nbsp;&nbsp;public function \_\_construct() {  
> > > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-\>connection = new AMQPStreamConnection(  
> > > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'172.18.0.2', 5672, 'guest', 'guest');  
> > > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-\>channel = $this-\>connection-\>channel();  
> > > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-\>channel-\>basic\_qos(null, 10, null);  
> > > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-\>reply\_id = uniqid();  
> > > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;list($this-\>callback\_queue, ,) = $this-\>channel-\>queue\_declare(  
> > > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"rpc.reply-phpconsumer-".$this-\>reply\_id, false, false, true, true);  
> > > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-\>channel-\>queue\_bind($this-\>callback\_queue, 'nameko-rpc', $this-\>reply\_id);
> > > > 
> > > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-\>channel-\>basic\_consume(  
> > > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-\>callback\_queue, '', false, false, false, false,  
> > > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;array($this, 'on\_response'));  
> > > > &nbsp;&nbsp;&nbsp;}  
> > > > &nbsp;&nbsp;&nbsp;public function on\_response($rep) {  
> > > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if($rep-\>get('correlation\_id') == $this-\>corr\_id) {  
> > > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-\>response = $rep-\>body;  
> > > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}  
> > > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$rep-\>delivery\_info['channel']-\>basic\_ack($rep-\>delivery\_info['delivery\_tag']);  
> > > > &nbsp;&nbsp;&nbsp;}  
> > > > &nbsp;&nbsp;&nbsp;public function call\_async($n) {  
> > > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-\>response = null;  
> > > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-\>corr\_id = uniqid();
> > > > 
> > > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$msg = new AMQPMessage(  
> > > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(string) $n,  
> > > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;array('correlation\_id' =\> $this-\>corr\_id,  
> > > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'reply\_to' =\> $this-\>reply\_id,  
> > > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'content\_encoding' =\> 'utf-8',  
> > > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'content\_type' =\> 'application/x-myjson'
> > > > 
> > > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;)  
> > > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;);  
> > > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-\>channel-\>basic\_publish($msg, 'nameko-rpc', 'producer.get');  
> > > > &nbsp;&nbsp;&nbsp;}
> > > > 
> > > > &nbsp;&nbsp;&nbsp;public function call($n) {  
> > > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-\>call\_async($n);
> > > > 
> > > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while(!$this-\>response) {  
> > > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-\>channel-\>wait();  
> > > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}  
> > > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return $this-\>response;  
> > > > &nbsp;&nbsp;&nbsp;}  
> > > > };
> > > > 
> > > > $consumer\_rpc = new ConsumerRpcClient();  
> > > > $start = microtime(true);
> > > > 
> > > > assert( $consumer\_rpc-\>call('{"args": , "kwargs": {}}') === '{"result": 42, "error": null}');
> > > > 
> > > > for ($i = 0; $i \< 5000; $i++) {  
> > > > &nbsp;&nbsp;&nbsp;$consumer\_rpc-\>call('{"args": , "kwargs": {}}');  
> > > > }  
> > > > $end = microtime(true);  
> > > > echo 'called '.$i.' times in '.($end - $start).' seconds';
> > > > 
> > > > the python producer code
> > > > 
> > > > class Producer(object):  
> > > > &nbsp;&nbsp;&nbsp;&nbsp;"""  
> > > > &nbsp;&nbsp;&nbsp;&nbsp;a fake service that produce data in a specified time  
> > > > &nbsp;&nbsp;&nbsp;&nbsp;used to test service auto scale  
> > > > &nbsp;&nbsp;&nbsp;&nbsp;  
> > > > &nbsp;&nbsp;&nbsp;&nbsp;public events  
> > > > &nbsp;&nbsp;&nbsp;&nbsp;#############  
> > > > &nbsp;&nbsp;&nbsp;&nbsp;  
> > > > &nbsp;&nbsp;&nbsp;&nbsp;rcp  
> > > > &nbsp;&nbsp;&nbsp;&nbsp;###  
> > > > &nbsp;&nbsp;&nbsp;&nbsp;  
> > > > &nbsp;&nbsp;&nbsp;&nbsp;set(rate)  
> > > > &nbsp;&nbsp;&nbsp;&nbsp;  
> > > > &nbsp;&nbsp;&nbsp;&nbsp;get()  
> > > > &nbsp;&nbsp;&nbsp;&nbsp;  
> > > > &nbsp;&nbsp;&nbsp;&nbsp;"""  
> > > > &nbsp;&nbsp;&nbsp;&nbsp;name = 'producer'
> > > > 
> > > > &nbsp;&nbsp;&nbsp;&nbsp;@rpc  
> > > > &nbsp;&nbsp;&nbsp;&nbsp;def get(self):  
> > > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"""  
> > > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;create a service on the valide scaler  
> > > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:param service:  
> > > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:return:  
> > > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"""  
> > > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# eventlet.patcher.original('time').sleep(0.009)  
> > > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return 42
