Add option to select an IP randomly instead of using the order provided by getaddrinfo, which is proximity based.
This commit is contained in:
parent
f75c848250
commit
4570496547
|
|
@ -192,8 +192,9 @@ public:
|
||||||
* Constructor
|
* Constructor
|
||||||
* @param handler User implemented handler object
|
* @param handler User implemented handler object
|
||||||
* @param hostname The address to connect to
|
* @param hostname The address to connect to
|
||||||
|
* @param random Randomly select one of the IP addresses that belong to the hostname
|
||||||
*/
|
*/
|
||||||
TcpConnection(TcpHandler *handler, const Address &address);
|
TcpConnection(TcpHandler *handler, const Address &address, bool random = false);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* No copying
|
* No copying
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,17 @@
|
||||||
/**
|
/**
|
||||||
* AddressInfo.h
|
* AddressInfo.h
|
||||||
*
|
*
|
||||||
* Utility wrapper arround "getAddressInfo()"
|
* Utility wrapper around "getAddressInfo()"
|
||||||
*
|
*
|
||||||
* @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
|
* @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
|
||||||
* @copyright 2015 Copernica BV
|
* @copyright 2015 Copernica BV
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dependencies
|
||||||
|
*/
|
||||||
|
#include <sys/time.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Include guard
|
* Include guard
|
||||||
*/
|
*/
|
||||||
|
|
@ -35,8 +40,9 @@ public:
|
||||||
* Constructor
|
* Constructor
|
||||||
* @param hostname
|
* @param hostname
|
||||||
* @param port
|
* @param port
|
||||||
|
* @param randomOrder
|
||||||
*/
|
*/
|
||||||
AddressInfo(const char *hostname, uint16_t port = 5672)
|
AddressInfo(const char *hostname, uint16_t port = 5672, bool randomOrder = false)
|
||||||
{
|
{
|
||||||
// store portnumber in buffer
|
// store portnumber in buffer
|
||||||
auto portnumber = std::to_string(port);
|
auto portnumber = std::to_string(port);
|
||||||
|
|
@ -63,6 +69,25 @@ public:
|
||||||
// store in vector
|
// store in vector
|
||||||
_v.push_back(current);
|
_v.push_back(current);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Do we want to have a random order of the addresses?
|
||||||
|
// This may be useful since getaddrinfo is sorting the addresses on proximity
|
||||||
|
// (e.g. https://lists.debian.org/debian-glibc/2007/09/msg00347.html),
|
||||||
|
// which may break loadbalancing..
|
||||||
|
if (randomOrder)
|
||||||
|
{
|
||||||
|
// We need to seed the random number generator. Normally time is taken
|
||||||
|
// for this. Since we want to have randomness within a second we use
|
||||||
|
// more precision via timeval
|
||||||
|
struct timeval time;
|
||||||
|
gettimeofday(&time, nullptr);
|
||||||
|
|
||||||
|
// We seed with the precision of miliseconds.
|
||||||
|
srand((time.tv_sec * 1000) + (time.tv_usec / 1000));
|
||||||
|
|
||||||
|
// shuffle the vector.
|
||||||
|
std::random_shuffle(_v.begin(), _v.end());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -99,4 +124,3 @@ public:
|
||||||
* End of namespace
|
* End of namespace
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,10 +23,11 @@ namespace AMQP {
|
||||||
* Constructor
|
* Constructor
|
||||||
* @param handler User implemented handler object
|
* @param handler User implemented handler object
|
||||||
* @param hostname The address to connect to
|
* @param hostname The address to connect to
|
||||||
|
* @param random Randomly select one of the IP addresses that belong to the hostname
|
||||||
*/
|
*/
|
||||||
TcpConnection::TcpConnection(TcpHandler *handler, const Address &address) :
|
TcpConnection::TcpConnection(TcpHandler *handler, const Address &address, bool random) :
|
||||||
_handler(handler),
|
_handler(handler),
|
||||||
_state(new TcpResolver(this, address.hostname(), address.port(), address.secure(), address.option("connectTimeout", 5))),
|
_state(new TcpResolver(this, address.hostname(), address.port(), address.secure(), address.option("connectTimeout", 5), random)),
|
||||||
_connection(this, address.login(), address.vhost())
|
_connection(this, address.login(), address.vhost())
|
||||||
{
|
{
|
||||||
// tell the handler
|
// tell the handler
|
||||||
|
|
@ -286,4 +287,3 @@ void TcpConnection::onLost(TcpState *state)
|
||||||
* End of namespace
|
* End of namespace
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -85,6 +85,12 @@ private:
|
||||||
*/
|
*/
|
||||||
std::thread _thread;
|
std::thread _thread;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do we want to have random ordering
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
bool _random;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Run the thread
|
* Run the thread
|
||||||
|
|
@ -98,7 +104,7 @@ private:
|
||||||
if (_secure && !OpenSSL::valid()) throw std::runtime_error("Secure connection cannot be established: libssl.so cannot be loaded");
|
if (_secure && !OpenSSL::valid()) throw std::runtime_error("Secure connection cannot be established: libssl.so cannot be loaded");
|
||||||
|
|
||||||
// get address info
|
// get address info
|
||||||
AddressInfo addresses(_hostname.data(), _port);
|
AddressInfo addresses(_hostname.data(), _port, _random);
|
||||||
|
|
||||||
// the pollfd structure, needed for poll()
|
// the pollfd structure, needed for poll()
|
||||||
pollfd fd;
|
pollfd fd;
|
||||||
|
|
@ -188,13 +194,15 @@ public:
|
||||||
* @param portnumber The portnumber for the lookup
|
* @param portnumber The portnumber for the lookup
|
||||||
* @param secure Do we need a secure tls connection when ready?
|
* @param secure Do we need a secure tls connection when ready?
|
||||||
* @param timeout timeout per connection attempt
|
* @param timeout timeout per connection attempt
|
||||||
|
* @param random Do we want to have random oredering of the address of the host to connect to
|
||||||
*/
|
*/
|
||||||
TcpResolver(TcpParent *parent, std::string hostname, uint16_t port, bool secure, int timeout) :
|
TcpResolver(TcpParent *parent, std::string hostname, uint16_t port, bool secure, int timeout, bool random) :
|
||||||
TcpExtState(parent),
|
TcpExtState(parent),
|
||||||
_hostname(std::move(hostname)),
|
_hostname(std::move(hostname)),
|
||||||
_secure(secure),
|
_secure(secure),
|
||||||
_port(port),
|
_port(port),
|
||||||
_timeout(timeout)
|
_timeout(timeout),
|
||||||
|
_random(random)
|
||||||
{
|
{
|
||||||
// tell the event loop to monitor the filedescriptor of the pipe
|
// tell the event loop to monitor the filedescriptor of the pipe
|
||||||
parent->onIdle(this, _pipe.in(), readable);
|
parent->onIdle(this, _pipe.in(), readable);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue