Merge branch '2.1' into 2.2

This commit is contained in:
Johan Wikman 2018-02-10 08:14:50 +02:00
commit e346968e0e
7 changed files with 108 additions and 16 deletions

View File

@ -699,6 +699,22 @@ has multiple interfaces.
local_address=192.168.1.254
```
#### `users_refresh_time`
How often, in seconds, MaxScale at most may refresh the users from the
backend server.
MaxScale will at startup load the users from the backend server, but if
the authentication of a user fails, MaxScale assumes it is because a new
user has been created and will thus refresh the users. By default, MaxScale
will do that at most once per 30 seconds and with this configuration option
that can be changed. The minimum allowed value is 10 seconds. A negative
value disables the refreshing entirelly. Note that using `maxadmin` it is
possible to explicitly cause the users of a service to be reloaded.
```
users_refresh_time=120
```
### Service
A service represents the database service that MariaDB MaxScale offers to the

View File

@ -28,6 +28,12 @@ For any problems you encounter, please consider submitting a bug report at
## New Features
### Users Refresh Time
It is now possible to adjust how frequently MaxScale may refresh
the users of service. Please refer to the documentation for
[details](../Getting-Started/Configuration-Guide.md#users_refresh_time).
### Local Address
It is now possible to specify what local address MaxScale should

View File

@ -232,6 +232,7 @@ typedef struct
time_t query_retry_timeout; /**< Timeout for query retries */
bool substitute_variables; /**< Should environment variables be substituted */
char* local_address; /**< Local address to use when connecting */
time_t users_refresh_time; /**< How often the users can be refreshed */
} MXS_CONFIG;
/**

View File

@ -78,8 +78,8 @@ typedef struct
*/
typedef struct
{
int nloads;
time_t last;
time_t last; /*<< When was the users loaded the last time. */
bool warned; /**< Has it been warned that the limit has been exceeded. */
} SERVICE_REFRESH_RATE;
typedef struct server_ref_t
@ -106,8 +106,8 @@ typedef struct server_ref_t
#define SERVICE_PARAM_UNINIT -1
/* Refresh rate limits for load users from database */
#define USERS_REFRESH_TIME 30 /* Allowed time interval (in seconds) after last update*/
#define USERS_REFRESH_MAX_PER_TIME 4 /* Max number of load calls within the time interval */
#define USERS_REFRESH_TIME_DEFAULT 30 /* Allowed time interval (in seconds) after last update*/
#define USERS_REFRESH_TIME_MIN 10 /* Minimum allowed time interval (in seconds)*/
/** Default timeout values used by the connections which fetch user authentication data */
#define DEFAULT_AUTH_CONNECT_TIMEOUT 3

View File

@ -146,6 +146,7 @@ const char CN_TYPE[] = "type";
const char CN_UNIX[] = "unix";
const char CN_USER[] = "user";
const char CN_USERS[] = "users";
const char CN_USERS_REFRESH_TIME[] = "users_refresh_time";
const char CN_VERSION_STRING[] = "version_string";
const char CN_WEIGHTBY[] = "weightby";
@ -1660,6 +1661,44 @@ handle_global_item(const char *name, const char *value)
{
gateway.local_address = MXS_STRDUP_A(value);
}
else if (strcmp(name, CN_USERS_REFRESH_TIME) == 0)
{
char* endptr;
long users_refresh_time = strtol(value, &endptr, 0);
if (*endptr == '\0')
{
if (users_refresh_time < 0)
{
MXS_NOTICE("Value of '%s' is less than 0, users will "
"not be automatically refreshed.", CN_USERS_REFRESH_TIME);
// Strictly speaking they will be refreshed once every 68 years,
// but I just don't beleave the uptime will be that long.
users_refresh_time = INT32_MAX;
}
else if (users_refresh_time < USERS_REFRESH_TIME_MIN)
{
MXS_WARNING("%s is less than the allowed minimum value of %d for the "
"configuration option '%s', using the minimum value.",
value, USERS_REFRESH_TIME_MIN, CN_USERS_REFRESH_TIME);
users_refresh_time = USERS_REFRESH_TIME_MIN;
}
if (users_refresh_time > INT32_MAX)
{
// To ensure that there will be no overflows when
// we later do arithmetic.
users_refresh_time = INT32_MAX;
}
gateway.users_refresh_time = users_refresh_time;
}
else
{
MXS_ERROR("%s is an invalid value for '%s', using default %d instead.",
value, CN_USERS_REFRESH_TIME, USERS_REFRESH_TIME_DEFAULT);
gateway.users_refresh_time = USERS_REFRESH_TIME_DEFAULT;
}
}
else
{
for (i = 0; lognames[i].name; i++)

View File

@ -335,6 +335,34 @@ serviceStartPort(SERVICE *service, SERV_LISTENER *port)
}
}
MXS_CONFIG* config = config_get_global_options();
time_t last;
bool warned;
/**
* At service start last update is set to config->users_refresh_time seconds earlier.
* This way MaxScale could try reloading users just after startup. But only if user
* refreshing has not been turned off.
*/
if (config->users_refresh_time == INT32_MAX)
{
last = time(NULL);
warned = true; // So that there will not be a refresh rate warning.
}
else
{
last = time(NULL) - config->users_refresh_time;
warned = false;
}
int nthreads = config_threadcount();
for (int i = 0; i < nthreads; ++i)
{
service->rate_limits[i].last = last;
service->rate_limits[i].warned = warned;
}
if (port->listener->func.listen(port->listener, config_bind))
{
port->listener->session = session_alloc(service, port->listener);
@ -1629,22 +1657,24 @@ int service_refresh_users(SERVICE *service)
self = 0;
}
MXS_CONFIG* config = config_get_global_options();
/* Check if refresh rate limit has been exceeded */
if ((now < service->rate_limits[self].last + USERS_REFRESH_TIME) ||
(service->rate_limits[self].nloads >= USERS_REFRESH_MAX_PER_TIME))
if (now < service->rate_limits[self].last + config->users_refresh_time)
{
MXS_ERROR("[%s] Refresh rate limit exceeded for load of users' table.", service->name);
if (!service->rate_limits[self].warned)
{
MXS_WARNING("[%s] Refresh rate limit (once every %ld seconds) exceeded for "
"load of users' table.",
service->name, config->users_refresh_time);
service->rate_limits[self].warned = true;
}
}
else
{
service->rate_limits[self].nloads++;
service->rate_limits[self].last = now;
service->rate_limits[self].warned = false;
/** If we have reached the limit on users refreshes, reset refresh time and count */
if (service->rate_limits[self].nloads >= USERS_REFRESH_MAX_PER_TIME)
{
service->rate_limits[self].nloads = 0;
service->rate_limits[self].last = now;
}
ret = 0;
LISTENER_ITERATOR iter;

View File

@ -703,8 +703,8 @@ static bool get_hostname(DCB *dcb, char *client_hostname, size_t size)
if (lookup_result != 0 && lookup_result != EAI_NONAME)
{
MXS_ERROR("Client hostname lookup failed for '%s', getnameinfo() returned: '%s'.",
dcb->remote, gai_strerror(lookup_result));
MXS_WARNING("Client hostname lookup failed for '%s', getnameinfo() returned: '%s'.",
dcb->remote, gai_strerror(lookup_result));
}
return lookup_result == 0;