Rabbitmq AMQPConnection Speed - php

I am using RabbitMQ and the PhpAmqpLib from Videla.
It takes PHP about 50ms to establish a connection with Rabbit (55ms with connection, 5ms with the connection part commented out).
/**
*
* #return \PhpAmqpLib\Connection\AMQPConnection
*/
private function connect(){
return new AMQPConnection(
$this->rabbitHost,
$this->rabbitPort,
$this->rabbitUser,
$this->rabbitPassword);
}
Is there a way to make a persistent connection (similar to MySQL) or another trick to speed it up? A message has to be sent to RabbitMQ on every page load.
Thanks.

You could extend PhpAmqpLib\Wire\IO\StreamIO and pass a STREAM_CLIENT_PERSISTENT flag ,but you'd have to wire up the connection manually.
I'm not sure if the connection out lives the process though, you'd have to look in to that.

Related

DB Connection in PHP Socket Server

I'm running a Yii2 console application which starts a websocket chat service. That all is working fine and as it's supposed to, but after some time of inactivity I get SQLSTATE[HY000]: General error: 2006 MySQL server has gone away. I tried to increase timeouts, set the user abort to false and to set PDO::ATTR_PERSISTENT => true in the PDO's constructor, but this is still happening.
Is there a way to check if a database connection is still active or if not how to reconnect to the db. Either in pure php or better with the Yii2 framework.
I had a similar problem and solved it by creating my own class for DB connection, which ensures that connection is active before actual query.
class DbConnection extends \yii\db\Connection {
private $stamp;
/**
* {#inheritdoc}
*/
public function createCommand($sql = null, $params = []) {
try {
// send ping on every 10 seconds
if ($this->stamp < time()) {
$this->stamp = time() + 10;
parent::createCommand('SELECT 1')->execute();
}
} catch (\yii\db\Exception $e) {
// if ping fail, reconnect
$this->close();
$this->open();
}
return parent::createCommand($query);
}
}
Once every 10 seconds it sends "ping" query before creating a command. If ping fails (connection was interrupted), it tries to reconnect.
This will not prevent from disconnecting, but it will automatically reconnect in case if connection was interrupted. This may be tricky if you're using transactions - if connection is interrupted in the middle of transaction, transaction will be implicitly rollback by DB, and above code will implicitly reconnect, so you don't even notice that your transaction was rollback at some point.
Also I didn't test it in master-slave configuration. But it worked perfectly fine in my case (read only connection to single server), so you may use it as a base and adjust for your needs with additional checks for transactions or master/slave connections.
Not sure about where exactly you should go for this code exactly, but the concerned code to check if the connection is active following methods in yii\db\Connection class can be used
getIsActive() : Returns a value indicating whether the DB connection
is established.
and to reconnect you can use
open() : Establishes a DB connection. It does nothing if a DB
connection has already been established.
if(Yii::$app->db->isActive === FALSE){
Yii::$app->db->open();
}

Closing database connection

I am doing project using mongodb and zendframework 2 so here I create connection in the constructor
private $conn;
public function __construct(){
$this->conn = new \MongoClient('mongodb://example.com:27017', array("connect" => TRUE));
}
It contain several actions to perform database operations like createdb, dropdb, renamedb like wise. so I close that connection within the __distruct() method
public function __destruct(){
$this->conn->close();
}
my code works fine. but I would like to know is this ok?
PHP closes database connections automatically.
You can read more about this in this post
however
read this
quote:
"Open connections (and similar resources) are automatically destroyed at the end of script execution. However, you should still close or free all connections, result sets and statement handles as soon as they are no longer required. This will help return resources to PHP and MySQL faster."
So basically, in case you have tons of things going in and out of the database, then yes, you might want to close right after.
In my opinion it is rather optional and your own choice wether to kill the process or not.

How Zend DB Manage Database Connections

I am using Zend Framework for my PHP developments and here is a small function I used to execute a query. This is not about an error. The code and everything works fine. But I want to know some concept behind this.
/**
* Get dataset by executing sql statement
*
* #param string $sql - SQL Statement to be executed
*
* #return bool
*/
public function executeQuery($sql)
{
$this->sqlStatement = $sql;
if ($this->isDebug)
{
echo $sql;
exit;
}
$objSQL = $this->objDB->getAdapter()->prepare($sql);
try
{
return $objSQL->execute();
}
catch(Exception $error)
{
$this->logMessage($error->getMessage() . " SQL : " .$sql);
return false;
}
return false;
}
Bellow are unclear areas for me.
How Zend_Db_Table_Abstract Maintain database connections?
Is it creating new connection all the time when I call this function or Does it have some connection pooling?
I didn't write any coding to open or close database connection. So will zend framework automatically close connections?
If this open and close connection works all the time if I execute this function, Is there any performance issue?
Thank you and appreciate your suggestions and opinion on this.
Creating Connection
Creating an instance of an Adapter class does not immediately connect to the RDBMS server. The Adapter saves the connection parameters, and makes the actual connection on demand, the first time you need to execute a query. This ensures that creating an Adapter object is quick and inexpensive. You can create an instance of an Adapter even if you are not certain that you need to run any database queries during the current request your application is serving.
If you need to force the Adapter to connect to the RDBMS, use the getConnection() method. This method returns an object for the connection as represented by the respective PHP database extension. For example, if you use any of the Adapter classes for PDO drivers, then getConnection() returns the PDO object, after initiating it as a live connection to the specific database.
It can be useful to force the connection if you want to catch any exceptions it throws as a result of invalid account credentials, or other failure to connect to the RDBMS server. These exceptions are not thrown until the connection is made, so it can help simplify your application code if you handle the exceptions in one place, instead of at the time of the first query against the database.
Additionally, an adapter can get serialized to store it, for example, in a session variable. This can be very useful not only for the adapter itself, but for other objects that aggregate it, like a Zend_Db_Select object. By default, adapters are allowed to be serialized, if you don't want it, you should consider passing the Zend_Db::ALLOW_SERIALIZATION option with FALSE, see the example above. To respect lazy connections principle, the adapter won't reconnect itself after being unserialized. You must then call getConnection() yourself. You can make the adapter auto-reconnect by passing the Zend_Db::AUTO_RECONNECT_ON_UNSERIALIZE with TRUE as an adapter option.
Closing a Connection
Normally it is not necessary to close a database connection. PHP automatically cleans up all resources and the end of a request. Database extensions are designed to close the connection as the reference to the resource object is cleaned up.
However, if you have a long-duration PHP script that initiates many database connections, you might need to close the connection, to avoid exhausting the capacity of your RDBMS server. You can use the Adapter's closeConnection() method to explicitly close the underlying database connection.
Since release 1.7.2, you could check you are currently connected to the RDBMS server with the method isConnected(). This means that a connection resource has been initiated and wasn't closed. This function is not currently able to test for example a server side closing of the connection. This is internally use to close the connection. It allow you to close the connection multiple times without errors. It was already the case before 1.7.2 for PDO adapters but not for the others.
More information

How do I establish a persistent connection to an Asterisk manager with PHP?

I'm attempting to connect to an Asterisk manager interface, and I'm having a problem with the code blocking, as well as connection persistence. Below is what I have, followed by a description of what's going wrong:
/**
* The parameters for connecting to the server
*/
$params = array('server' => '192.168.1.100', 'port' => '5038');
/**
* Instantiate Asterisk object and connect to server
*/
$ast = new Net_AsteriskManager($params);
/**
* Connect to server
*/
try {
$ast->connect();
} catch (PEAR_Exception $e) {
echo $e;
}
/**
* Login to manager API
*/
try {
$ast->login('admin', 'abcdefghi');
} catch(PEAR_Exception $e) {
echo $e;
}
The above code works, as far as connecting. I'm able to fetch data through it.
The issue is sending a query is taking quite long time, and when I observe the server in realtime mode (console) I see that the user admin is getting log out from server after output is sent.
In other words, 'admin' is getting logged out even though I have not explicitly logged out in the code. How can I make this connection persistent?
Asterisk AMI does not automatically closes the connection however it is network layer who does it, when it detect no activity for long time (=timeout) it drops the connection. To make a connection persistence it is required to keep it busy (=keep alive), whenever connection is idle your application should send keep alive packets to destination server at specified interval (=TTL). We can use any type of command as keep alive packet like in asterisk you can use "Ping".
However if you are looking some existing ready to use solution then you can use some AMI Proxy for that. here are some known AMI proxies
I think you just have use php-agi.php class. it already have all you need. No any need write it again.
php-agi.php distributed with any asterisk and can be found in /var/lib/asterisk/agi-bin/

PHP/MySQL: Create new connection for each query?

I have a webpage with some mysql querys,
I must start new db connection and db close after every query or its more efficiently start an only one db connection at the top of the code and close at the bottom of the script?
Thanks!
Never create a new connection for every query; it's very wasteful and will overburden your MySQL server.
Creating one connection at the top of your script is enough - all subsequent queries will use that connection until the end of the page. You can even use that connection in other scripts that are include()ed into the script with your mysql_connect() call in it.
I prefer to create some sort of class called Database of which upon creation will create a database connection using mysqli (OOP version of mysql).
This way i do not have to worry about that and i have a static class that has access to the database.
class MyAPI {
private static $database = false;
public static function GetDatabase() {
if (MyAPI::$database === false) {
MyAPI::$database = new Database(credentials can go here)
}
return MyAPI::$database;
}
}
Now your system with the includsion of your API and your database can access the database and its initialization code does not have to be peppered around your files depending on what part of the program is running and your database/connection will not be created if it is not needed (only until it is called).
Just for fun i also like to have a function in my Database class that will perform a query and return its results, this way i do not have to have the SAME while loop over and over again throughout my code depending on where i make these calls.
I also forgot to answer your question. No multiple connections! its baaaad.
Only create one connection. You don't even have to close it manually.
multiple connexion is better for security and tracking.
if you're going though a firewall between front and back there will be a timeout defined so a single connection will be a problem.
but if your web server is on the same host as mysql, a single connection will be more efficient.

Categories