mirror of
https://github.com/pgbackrest/pgbackrest.git
synced 2025-01-30 05:39:12 +02:00
Support for dual stack connections.
The prior code would only connect to the first address provided by getaddrinfo(). Instead try each address in the list. If all connections fail then wait and try them all again until timeout. Currently a round robin approach is used where each connection attempt must fail before the next connection is attempted. This works fine, for example, when an ipv6 address has no route to the host, but will work less well when a host answers but doesn't respond in a timely fashion. We may consider a Happy Eyeballs approach in the future, but since pgBackRest is primarily a background process, it is not clear that slightly improved response time (in the case of failed connections) is worth the extra complexity.
This commit is contained in:
parent
9d3a605900
commit
39bb8a0d3a
@ -1,6 +1,25 @@
|
||||
<release date="XXXX-XX-XX" version="2.48dev" title="Under Development">
|
||||
<release-core-list>
|
||||
<release-feature-list>
|
||||
<release-item>
|
||||
<commit subject="Adjust Wait object to be more accurate when nested."/>
|
||||
<commit subject="Aggregate error retries in ErrorRetry output."/>
|
||||
<commit subject="Refactor address list lookup to include all returned addresses.">
|
||||
<github-pull-request id="2174"/>
|
||||
</commit>
|
||||
<commit subject="Support for dual stack connections.">
|
||||
<github-issue id="2154"/>
|
||||
<github-pull-request id="2175"/>
|
||||
</commit>
|
||||
|
||||
<release-item-contributor-list>
|
||||
<release-item-contributor id="david.steele"/>
|
||||
<release-item-reviewer id="stephen.frost"/>
|
||||
</release-item-contributor-list>
|
||||
|
||||
<p>Support for dual stack connections.</p>
|
||||
</release-item>
|
||||
|
||||
<release-item>
|
||||
<github-issue id="2007"/>
|
||||
<github-pull-request id="2141"/>
|
||||
|
@ -9,6 +9,7 @@ Socket Client
|
||||
#include <unistd.h>
|
||||
|
||||
#include "common/debug.h"
|
||||
#include "common/error/retry.h"
|
||||
#include "common/io/client.h"
|
||||
#include "common/io/socket/address.h"
|
||||
#include "common/io/socket/client.h"
|
||||
@ -72,8 +73,13 @@ sckClientOpen(THIS_VOID)
|
||||
|
||||
MEM_CONTEXT_TEMP_BEGIN()
|
||||
{
|
||||
Wait *const wait = waitNew(this->timeoutConnect);
|
||||
ErrorRetry *const errRetry = errRetryNew();
|
||||
bool retry;
|
||||
Wait *wait = waitNew(this->timeoutConnect);
|
||||
|
||||
// Get an address list for the host
|
||||
const AddressInfo *const addrInfo = addrInfoNew(this->host, this->port);
|
||||
unsigned int addrInfoIdx = 0;
|
||||
|
||||
do
|
||||
{
|
||||
@ -83,8 +89,8 @@ sckClientOpen(THIS_VOID)
|
||||
|
||||
TRY_BEGIN()
|
||||
{
|
||||
// Get an address for the host. We are only going to try the first address returned.
|
||||
const struct addrinfo *const addressFound = addrInfoGet(addrInfoNew(this->host, this->port), 0);
|
||||
// Get next address for the host
|
||||
const struct addrinfo *const addressFound = addrInfoGet(addrInfo, addrInfoIdx);
|
||||
|
||||
// Connect to the host
|
||||
fd = socket(addressFound->ai_family, addressFound->ai_socktype, addressFound->ai_protocol);
|
||||
@ -106,19 +112,32 @@ sckClientOpen(THIS_VOID)
|
||||
}
|
||||
CATCH_ANY()
|
||||
{
|
||||
if (fd != -1)
|
||||
close(fd);
|
||||
// Close socket
|
||||
close(fd);
|
||||
|
||||
// Retry if wait time has not expired
|
||||
if (waitMore(wait))
|
||||
// Add the error retry info
|
||||
errRetryAdd(errRetry);
|
||||
|
||||
// Increment address info index and reset if the end has been reached. When the end has been reached sleep for a bit
|
||||
// to hopefully have better chance at succeeding, otherwise continue right to the next address as long as there is
|
||||
// some time left.
|
||||
addrInfoIdx++;
|
||||
|
||||
if (addrInfoIdx >= addrInfoSize(addrInfo))
|
||||
{
|
||||
LOG_DEBUG_FMT("retry %s: %s", errorTypeName(errorType()), errorMessage());
|
||||
retry = true;
|
||||
|
||||
statInc(SOCKET_STAT_RETRY_STR);
|
||||
addrInfoIdx = 0;
|
||||
retry = waitMore(wait);
|
||||
}
|
||||
else
|
||||
RETHROW();
|
||||
retry = waitRemaining(wait) > 0;
|
||||
|
||||
// Error when no retries remain
|
||||
if (!retry)
|
||||
THROWP(errRetryType(errRetry), strZ(errRetryMessage(errRetry)));
|
||||
|
||||
// Log retry
|
||||
LOG_DEBUG_FMT("retry %s: %s", errorTypeName(errorType()), errorMessage());
|
||||
statInc(SOCKET_STAT_RETRY_STR);
|
||||
}
|
||||
TRY_END();
|
||||
}
|
||||
|
@ -306,7 +306,8 @@ testRun(void)
|
||||
|
||||
TEST_ERROR_FMT(
|
||||
httpRequestResponse(httpRequestNewP(client, STRDEF("GET"), STRDEF("/")), false), HostConnectError,
|
||||
"unable to connect to 'localhost:%u (127.0.0.1)': [111] Connection refused",
|
||||
"unable to connect to 'localhost:%u (127.0.0.1)': [111] Connection refused\n"
|
||||
"[RETRY DETAIL OMITTED]",
|
||||
hrnServerPort(0));
|
||||
|
||||
HRN_FORK_BEGIN()
|
||||
|
@ -368,7 +368,9 @@ testRun(void)
|
||||
|
||||
TEST_ASSIGN(client, sckClientNew(STRDEF("localhost"), hrnServerPort(0), 100, 100), "new client");
|
||||
TEST_ERROR_FMT(
|
||||
ioClientOpen(client), HostConnectError, "unable to connect to 'localhost:%u (127.0.0.1)': [111] Connection refused",
|
||||
ioClientOpen(client), HostConnectError,
|
||||
"unable to connect to 'localhost:%u (127.0.0.1)': [111] Connection refused\n"
|
||||
"[RETRY DETAIL OMITTED]",
|
||||
hrnServerPort(0));
|
||||
|
||||
// This address should not be in use in a test environment -- if it is the test will fail
|
||||
@ -451,7 +453,9 @@ testRun(void)
|
||||
client, tlsClientNewP(sckClientNew(STRDEF("localhost"), hrnServerPort(0), 100, 100), STRDEF("X"), 100, 100, true),
|
||||
"new client");
|
||||
TEST_ERROR_FMT(
|
||||
ioClientOpen(client), HostConnectError, "unable to connect to 'localhost:%u (127.0.0.1)': [111] Connection refused",
|
||||
ioClientOpen(client), HostConnectError,
|
||||
"unable to connect to 'localhost:%u (127.0.0.1)': [111] Connection refused\n"
|
||||
"[RETRY DETAIL OMITTED]",
|
||||
hrnServerPort(0));
|
||||
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
|
Loading…
x
Reference in New Issue
Block a user