ActiveMQ in failover with PHP/Stomp client - php

here is the goal: a PHP application connecting to an ActiveMQ failover cluster (Master/Slave) using Stomp.
Here are the versions:
ActiveMQ 5.7
PHP stomp 1.0.5 stable
PHP 5.4.4-14+deb7u14 (cli)
Here is the setup:
2 servers with ActiveMQ;
keepalived installed on both servers, sharing a VIP
the PHP script is the following
< ? php
$queue = '/queue/test';
try {
$stomp = new Stomp("tcp://VIP:61613");
} catch(StompException $e) {
die('Connection failed: ' . $e->getMessage());
}
$stomp->subscribe($queue);
while ($stomp->hasFrame())
{
$frame = $stomp->readFrame();
var_dump($frame);
print_r($frame->headers["message-id"]."\n");
if ($stomp->ack($frame))
print_r("Frame ACK!\n");
else
die("ACK Error");
}
?>
With a consequent number of messages, we get these kinds of error in the ActiveMQ debug log
2014-10-03 13:19:13,941 | DEBUG | Transport Connection to:
tcp://127.0.0.1:37125 failed: java.io.EOFException |
org.apache.activemq.broker.TransportConnection.Transport | ActiveMQ
Transport: tcp:///127.0.0.1:37125#61613 java.io.EOFException
at java.io.DataInputStream.readByte(DataInputStream.java:267)
at org.apache.activemq.transport.stomp.StompWireFormat.readHeaderLine(StompWireFormat.java:155)
at org.apache.activemq.transport.stomp.StompWireFormat.readLine(StompWireFormat.java:148)
at org.apache.activemq.transport.stomp.StompWireFormat.parseAction(StompWireFormat.java:170)
at org.apache.activemq.transport.stomp.StompWireFormat.unmarshal(StompWireFormat.java:98)
at org.apache.activemq.transport.tcp.TcpTransport.readCommand(TcpTransport.java:229)
at org.apache.activemq.transport.tcp.TcpTransport.doRun(TcpTransport.java:221)
at org.apache.activemq.transport.tcp.TcpTransport.run(TcpTransport.java:204)
at java.lang.Thread.run(Thread.java:745)
This causes the STOMP connection to drop, and leads us to other issues.
It seems that the ActiveMQ errors might be linked to the keepalived setup, and that the better configuration would be to use failover scheme in the client.
We tried these connection strings in the Stomp object creation:
> failover://tcp://IP1:61613,tcp://IP2:61613
> failover:tcp://IP1:61613,tcp://IP2:61613
> failover://(tcp://IP1:61613,tcp://IP2:61613)
> failover:(tcp://IP1:61613,tcp://IP2:61613)
But they all lead to Invalid broker URI error.
Can't find much doc/issues on the web about such thing..
Any recommandation or advise on implementing failover client side?

PHP Stomp does not support failover by default, you have to implement it yourself to support it, like shown in the following example:
$urls = array('ip1:61613','ip2:61613');
$conn = null;
foreach ($urls as $url) {
$url = "tcp://".$url;
try {
$conn = new \Stomp($url,$user,$passwd);
} catch(\Exception $e) {
}
if ($this->conn) {
break;
}
}

Related

Mongodb connectivity error

<?php
/**
* Connects to MongoDB server.
* Stops code execution on`enter code here` connection error.
*
* You do not need to use this file, just any place to globally assign a MongoDB instance to $db.
*
* Define constants in your config or here
*/
define('MDB_USERNAME', 'root');
define('MDB_PASSWORD', 'asd');
define('MDB_HOST', 'localhost:80');
define('MDB_NAME', 'abc');
if (!class_exists('Mongo')) {
die("Mongo class not existing. Did you install the PHP MongoDB extension?");
}
try {
$conn = new MongoClient("mongodb://".MDB_USERNAME.":".MDB_PASSWORD."#".MDB_HOST."/".MDB_NAME);
$conn->authenticate('root','gynadfehurbo');
$db = $conn->selectDB(MDB_NAME);
} catch (MongoConnectionException $e) {
die($e->getMessage()); // In production you might want to turn this off.
}
Mongodb connectivity problem.
while am trying to connect mongodb with php got authentication problem ..By giving port the above error is replaced as connection refused .then i changed the port that error has been replaced as
Failed to connect to: localhost:80: Read timed out after reading 0 bytes, waited for 60.000000 seconds
$server = "mongodb://localhost:27017/dbname"; // Connecting to server
$c = new MongoClient($server );
if($c->connected)
echo "Connected successfully";
else
echo "Connection failed";

Catch an exception in a shutdown function

I'm working on some PHP code that needs to obtain a database resource, mark it as locked for the duration of its run and mark it as not locked when done. The lock is obtained at startup by updating a value in the table, and I've registered a shutdown function to release the lock when the script terminates for any reason.
The problem I'm having is that the connection to the server (a Microsoft SQL database server) doesn't appear to be very reliable in the live environment, and that seems to be the usual reason for abnormal script termination. Obviously I can't unlock the database resource when I'm not connected but I at least want to be able to handle the failure to do that cleanly.
The following is a heavily cut down version of the main script.
try {
echo "Connecting to server...\n";
$obj_adaptor = get_remote_db ();
echo "Beginning sync...\n";
if (FALSE != ($bol_locked = $obj_adaptor -> lock_server_db ())) {
// Do work here
} else {
throw new RuntimeException ("Failed to obtain remote database lock!");
}
} catch (Exception $obj_ex) {
echo "Operation failed with an exception!\n\n";
echo "Details: \n";
echo $obj_ex -> getMessage () . PHP_EOL;
echo $obj_ex -> getTraceAsString () . PHP_EOL;
}
My shutdown function looks like this:
$arr_shutdown_func = function () {
global $bol_locked, $obj_adaptor;
if ($bol_locked) {
echo "Releasing lock...\n";
try {
echo $obj_adaptor -> unlock_server_db ()?
"Done\n":
"Failed to unlock database! Use force_remote_db_unlock script to force a database unlock\n";
} catch (PDOException $obj_ex) {
echo "Failed to unlock database! Use force_remote_db_unlock script to force a database unlock\n";
}
} else {
echo "No lock to release\n";
}
};
// Set up ctrl-c listener
if (function_exists ('pcntl_signal')) {
pcntl_signal (SIGINT, $arr_shutdown_func);
pcntl_signal (SIGTERM, $arr_shutdown_func);
// Register shutdown functions
register_shutdown_function ($arr_shutdown_func);
set_exception_handler ($arr_shutdown_func);
I was expecting in the event of the connection being lost for the script to attempt to release the database lock but failing, and echoing out the message about not being able to release the lock.
However, what I actually get is:
PHP Fatal error: Uncaught exception 'Zend_Db_Statement_Exception'
with message 'SQLSTATE[HY000]: General error: 20047 DBPROCESS is dead
or not enabled [20047] (severity 1) [(null)]' in
Zend/Db/Statement/Pdo.php:238
I've tried to find a definitive answer on whether or not it's possible to catch exceptions in a shutdown function but haven't had much luck so far so I'm still looking. However, if it's possible to deal with exceptions in a shutdown function I'd appreciate knowing what's wrong with the approach I'm applying.
I've just tested this out with a simple code and I don't get disconnected before shutdown function.
<?
mysql_connect('localhost','xxx','xxx') or die(mysql_error());
mysql_select_db('xxx');
register_shutdown_function("s");
function s() {
echo 'xxxx';
$qa = mysql_query('SELECT * FROM xxx') or die(mysql_error());
while($q = mysql_fetch_array($qa)) {
print_r($q);
}
}
?>
What version of PHP are you using?
PHP 5.5.3 (cli) (built: Aug 23 2013 08:41:45) Copyright (c) 1997-2013
The PHP Group Zend Engine v2.5.0, Copyright (c) 1998-2013 Zend
Technologies

php get message from rabbitmq error

My amqp extension version is 1.0.1 & AMQP protocol version is 0-9-1
get messages from queue :
<?php
try {
$conn = new AMQPConnection() ;
$conn->setLogin('guest') ;
$conn->setPassword('guest') ;
$conn->connect() ;
if ($conn->isConnected()) {
$channel = new AMQPChannel($conn) ;
if ($channel->isConnected())
{
$queue = new AMQPQueue($channel) ;
$queue->setName('test_queue') ;
$queue->setFlags(AMQP_DURABLE | AMQP_AUTODELETE) ;
$queue->declare() ;
$messages = $queue->get(AMQP_AUTOACK) ;
print_r($messages->getBody()) ;
}
} else {
echo "connect failure ... " ;
}
$conn->disconnect() ;} catch (Exception $e) {
echo $e->getMessage() ;}?>
and it doesn't work ..
Server channel error: 406, message: PRECONDITION_FAILED - parameters for queue 'test_queue' in vhost '/' not equivalent
It seems to me that the queue already exists and it was declared (created) previously with different parameters in the vhost. Queues need to be declared exactly with the same parameters every time (or deleted and recreated with the desired parameters). Try deleting the queue via the management plugin (http://www.rabbitmq.com/management.html) and then running your script again
If your queue has already been created you don't need to create it (using 'declare' method) and bind with exchange once again. IMHO you shouldn't do it as a) these actions require administrative privileges b) it's enough to to it only once c) you might not have got administrative rights on production and your code would be broken.
I believe it's better to create and bind all required queues with management console or any other tool you like and then receive messages this way
// consider using connection more than once. that's only for illustration purposes.
$connection = new AMQPConnection([ put your credentials here ]);
$connection->connect();
if(!$connection->isConnected()) {
throw new Exception('Connection failed.');
}
$chnlObj = new AMQPChannel($connection);
$queObj = new AMQPQueue($chnlObj);
$queObj->setName('yourQueueName');
echo $queObj->get(AMQP_AUTOACK)->getBody();
// consider using connection more than once. that's only for illustration purposes.
$connection->disconnect();

What is "New transaction is not allowed" error in PHP and SQLSRV driver for?

I'm working on a web application written with PHP and uses SQL Server 2008. To connect to database, I used SQLSRV driever of Microsoft. In a part of this application, I have to use SQL Transactions. As Microsoft suggested, I did it exactly based on this article. The main processes in my codes follow these steps:
1- starting sql transaction
2- send information to PHP files through jQuery and check the result sent by JSON
3- rollback if the result was false and go to the next query if it was true.
4- commit transactions if no error occurred and all results were ok.
// This is my pseudo code
if (sqlsrv_begin_transaction( $sqlsrv->sqlsrvLink ) === true) {
$firstQuery = sqlsrv_query($stmt1);
if (!$firstQuery) {
sqlsrv_rollback();
} else {
$nextQuery = sqlsrv_query($stmt2);
if (!$nextQuery) {
sqlsrv_rollback();
} else {
sqlsrv_commit();
}
}
} else {
print_r(sqlsrv_errors()); // Here is where I get the error below.
}
The problem I have is this error:
[Microsoft][SQL Server Native Client 10.0][SQL Server] New transaction is not allowed because there are other threads running in the session
I'm using SQLSRV driver ver.2.
What is this error for? How can I solve it?
I included the my own sqlsrv class to the first part of index.php containing the methods below:
function __construct($dbServerName,$dbUsername,$dbPassword,$dbName)
{
$connectionInfo = array("Database"=> $dbName, "CharacterSet" => "UTF-8");
$this->sqlsrvLink = sqlsrv_connect($dbServerName, $connectionInfo);
if ($this->sqlsrvLink === false) {
$this->sqlsrvError = sqlsrv_errors();
}
}
function __destruct()
{
sqlsrv_close($this->sqlsrvLink);
}
i think you should set MultipleActiveResultSets to true when you want to connect to sql server :
$conn = sqlsrv_connect('127.0.0.1', array
(
'Database' => 'Adventureworks',
'MultipleActiveResultSets' => true, // MARS ENABLED
));
http://php.net/manual/de/ref.pdo-sqlsrv.connection.php
From your error, It seems like $nextQuery = sqlsrv_query($stmt2); is starting a new transaction in the same session. Can you commit !$firstQuery before starting the second?

Connecting to MQ using PHP/Linux

Is there anyone out there who successfully is using PHP/Linux to connect to MQ? For days I have desperately been trying to get this to work but to no avail. IF there's anyone out there who is doing this, how?
As I see it there's two extensions to use:
a) mqseries -> a thin wrapper to the C API
b) SAM 1.1.0 -> taking a more general approach
I've tried both but for a) I am able to do MQCONNX successfully, but not MQOPEN and for b) I am not getting past the MQCONN stage. I've tried both the 7 and the 6 Client. Our server is running 6.0.0.0.
Note; we've successfully been connecting to the server using .NET for years.
So this is what I've done so far:
Installed the MQClient from RPM packages
Installed IA94/XMS
Succesfully built the sam_xms.so extension and included that in my php.ini
Successfulyl built mqseries.so extension and included that as well.
Successfully been running the Samples from the mq client installation (amqsputc and amqsgetc) and been passing messages back and forth.
Using the mqseries PECL extension this is the error I get:
MQOPEN failed; CompCode:2 Reason:2044 Text:2044
Using the SAM PECL extension I get this instead:
<--SAMConnection.SetDebug()
-->SAMConnection.Connect()
-->SAMConnection.Create(proto=wmq:client)
SAMConnection.Create() get_cfg_var() ""
SAMConnection.Create() calling factory - SAM/sam_factory_xms.php
SAMConnection.Create() rc = SAMXMSConnection
<--SAMConnection.Create()
SAMConnection.Connect() connection created for protocol wmq:client
SAMConnection.Connect() connect failed (208) Unable to create XMS connection!
<--SAMConnection.Connect() rc=
-->SAMConnection.IsConnected()
SAMConnection.IsConnected() isconnected failed (208) Unable to create XMS connection!
<--SAMConnection.IsConnected() rc=
Connection failed (208) Unable to create XMS connection!
Neither of these errors generates anything in /var/mqm/errors...
Here's my sample code for mqseries:
mqseries_conn('MQED', $conn, $comp_code, $reason);
if ($comp_code !== MQSERIES_MQCC_OK) {
printf("<br>MQCONNX failed; Connx CompCode:%d Reason:%d Text:%s<br>\n", $comp_code, $reason, $reason);
exit;
}
else
{
printf("<br>MQCONNX successful: Connx CompCode:%d Reason:%d Text:%s<br>\n<br>", $comp_code, $reason, $reason);
}
$mqods = array('ObjectName'=>'MYPUTQUEUE');
mqseries_open($conn, $mqods,
MQSERIES_MQOO_INPUT_AS_Q_DEF | MQSERIES_MQOO_FAIL_IF_QUIESCING | MQSERIES_MQOO_OUTPUT,
$obj, $comp_code,$reason);
if ($comp_code !== MQSERIES_MQCC_OK) {
printf("<br><br>MQOPEN failed; CompCode:%d Reason:%d Text:%s<br><br>",
$comp_code,
$reason,
$reason);
}
else
{
printf("<br><br>MQOPEN successful; CompCode:%d Reason:%d Text:%s<br><br>",
$comp_code,
$reason,
$reason);
}
Here's the sample code using the SAM extension:
$conn->connect(SAM_WMQ_CLIENT, array(SAM_BROKER => 'MQED',SAM_TRANSACTIONS => SAM_MANUAL));
if($conn->isConnected())
{
$msg = new SAMMessage('MY MESSAGE');
$msg->header->SAM_REPLY_TO = 'MYGETQUEUE';
$correlid = $conn->send('MYPUTQUEUE', $msg);
if (!$correlid) {
// The Send failed!
echo "Send failed ($conn->errno) $conn->error";
} else {
$resp = $conn->receive('MYGETQUEUE', array(SAM_CORRELID => $correlid));
}
$conn->disconnect();
}
else
{
echo "Connection failed ($conn->errno) $conn->error";
}
Thank you everyone in advance!
Note, this is a continuation of the discussion on Trying to connect to MQ using PHP; almost there
Update #1: MQPUT1 works, but MQOPEN is still returning 2044.

Categories