Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

calling check_heartbeat causes connection to close #617

Closed
rbro opened this issue Nov 3, 2018 · 6 comments
Closed

calling check_heartbeat causes connection to close #617

rbro opened this issue Nov 3, 2018 · 6 comments
Assignees
Milestone

Comments

@rbro
Copy link

rbro commented Nov 3, 2018

I am running into an issue with 2.8.0 or later with long running processes and calling check_heartbeat to keep the connection active. The problem existed in 2.7.2 and earlier, but I had a workaround that no longer seems to work in 2.8.0. I mentioned it originally in #507 (comment).

The connection is being closed even if check_heartheart() is called because $this->last_read stays the same. This caused reconnect() to be called in 2.7.2, and in 2.8.0, the exception "Missed server heartbeat" is thrown.

The workaround I found in 2.7.2 was to call read(0) instead of check_heartbeat(). That got around it since $this->last_read is updated after each call. That line seems to have been removed from the end of the read() function in 2.8.0:

$this->last_read = microtime(true);

If you run the below script, you will get the exception "Missed server heartbeat" after about 5 seconds even though you are calling check_heartbeat(). If you call read(0), you will get the same exception. If you try calling read(0) against 2.7.2 code, you won't get an exception because the read(0) call will keep the connection active since last_read will get updated, and therefore, the old "reconnect" function won't get called.

Is there something that can be changed so that either:

  • check_heartbeat() will not close the connection and instead keep it active?
  • or can the line be restored to the read() function so that $last_read will still get updated, which will allow calling read(0) in a loop to keep the connection active?

Thanks for your help.

<?php
require_once __DIR__.'/vendor/autoload.php';

$connection = new \PhpAmqpLib\Connection\AMQPStreamConnection('localhost', 5672, 'guest', 'guest', '/', $insist=false, $login_method='AMQPLAIN', $login_response=null, $locale='en_US', $connection_timeout=3, $read_write_timeout=60, $context=null, $keepalive=false, $heartbeat=2);

for ($i = 0; $i <= 10; $i++)
{
	sleep(1);

	$connection->getIO()->check_heartbeat();
	//$connection->getIO()->read(0);
}
@lukebakken lukebakken added this to the 2.8.1 milestone Nov 6, 2018
@lukebakken lukebakken self-assigned this Nov 6, 2018
lukebakken added a commit that referenced this issue Nov 6, 2018
@lukebakken
Copy link
Collaborator

I will restore the line that updates last_read since that will be the easiest fix. The check_heartbeat method probably shouldn't detect missed server heartbeats because those frames aren't actually being read in either I/O implementation - you have to call $channel->wait() to actually read heartbeat frames.

@rbro
Copy link
Author

rbro commented Nov 7, 2018

Thanks, appreciate your help and quick response.

@lukebakken
Copy link
Collaborator

@rbro please test v2.8.1-rc3. Thank you!

@rbro
Copy link
Author

rbro commented Nov 8, 2018

Thanks, I confirm it's good now. Is calling read(0) the best way for now to keep the connection active?

@lukebakken
Copy link
Collaborator

The correct way is to wait on a channel and do your work quickly or in a separate process. Otherwise, this method is the only (hacky) option at this point. C'est la vie!

@rbro
Copy link
Author

rbro commented Nov 10, 2018

Thanks, in my case, I'm offloading the work to php-fpm using https://github.com/hollodotme/fast-cgi-client, so I'm calling read(0) while waiting for the fastcgi response to come back. Is there a way that I can wait for that response while also calling $channel->wait() to keep the rabbitmq connection going? Right now, I'm doing:

while (true)
{
	if (fastcgi response is ready)
	{
		// process it
		break;
	}
	
	$connection->getIO()->read(0);
}

kratkyzobak pushed a commit to kratkyzobak/php-amqplib that referenced this issue Feb 9, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants