mirror of
https://github.com/samba-team/samba.git
synced 2024-12-22 13:34:15 +03:00
s3:rpc_server: distribute clients based on available association group slots
The important factor to distribute connection to workers should be the number of used association group slots instead of the raw number of connections. If one worker has a lot of association groups with just one connection each, but another with few association groups, but multiple connections per association group. The one with less association groups should get the connection. Note each worker is only able to allocate UINT16_MAX allocation groups, but the number of connections is only limited by RAM. Signed-off-by: Stefan Metzmacher <metze@samba.org> Reviewed-by: Andrew Bartlett <abartlet@samba.org>
This commit is contained in:
parent
40e780ad16
commit
f8b76235fe
@ -72,9 +72,22 @@ interface rpc_host_msg
|
||||
*/
|
||||
uint32 worker_index;
|
||||
|
||||
|
||||
/**
|
||||
* @brief How many clients this process serves right now
|
||||
* @brief How many association groups this process serves right now
|
||||
*
|
||||
* @note while this is uint32, we currently only support 16-bit
|
||||
* values, as we use the worker_index in the high 16-bits of
|
||||
* so we only have 16-bit per worker in order to form the 32-bit
|
||||
* association group id.
|
||||
*/
|
||||
uint32 num_clients;
|
||||
uint32 num_association_groups;
|
||||
|
||||
/**
|
||||
* @brief How many client connections this process serves right now
|
||||
*
|
||||
* @note might be greater or equal to num_association_groups.
|
||||
*/
|
||||
uint32 num_connections;
|
||||
} rpc_worker_status;
|
||||
}
|
||||
|
@ -170,7 +170,8 @@ struct rpc_work_process {
|
||||
* MSG_RPC_HOST_WORKER_STATUS sent by workers whenever a
|
||||
* client exits.
|
||||
*/
|
||||
uint32_t num_clients;
|
||||
uint32_t num_associations;
|
||||
uint32_t num_connections;
|
||||
|
||||
/*
|
||||
* Send SHUTDOWN to an idle child after a while
|
||||
@ -1177,7 +1178,7 @@ static struct rpc_work_process *rpc_host_find_worker(struct rpc_server *server)
|
||||
if (!worker->available) {
|
||||
continue;
|
||||
}
|
||||
if (worker->num_clients == 0) {
|
||||
if (worker->num_associations == 0) {
|
||||
/*
|
||||
* We have an idle worker...
|
||||
*/
|
||||
@ -1191,13 +1192,28 @@ static struct rpc_work_process *rpc_host_find_worker(struct rpc_server *server)
|
||||
best_worker = worker;
|
||||
continue;
|
||||
}
|
||||
if (worker->num_clients < best_worker->num_clients) {
|
||||
if (worker->num_associations < best_worker->num_associations) {
|
||||
/*
|
||||
* It's also busy, but has less clients
|
||||
* It's also busy, but has less association groups
|
||||
* (logical clients)
|
||||
*/
|
||||
best_worker = worker;
|
||||
continue;
|
||||
}
|
||||
if (worker->num_associations > best_worker->num_associations) {
|
||||
/*
|
||||
* It's not better
|
||||
*/
|
||||
continue;
|
||||
}
|
||||
/*
|
||||
* Ok, with the same number of association groups
|
||||
* we pick the one with the lowest number of connections
|
||||
*/
|
||||
if (worker->num_connections < best_worker->num_connections) {
|
||||
best_worker = worker;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (perfect_worker != NULL) {
|
||||
@ -1242,7 +1258,7 @@ static struct rpc_work_process *rpc_host_find_idle_worker(
|
||||
if (!worker->available) {
|
||||
continue;
|
||||
}
|
||||
if (worker->num_clients == 0) {
|
||||
if (worker->num_associations == 0) {
|
||||
return &server->workers[i];
|
||||
}
|
||||
}
|
||||
@ -1374,11 +1390,13 @@ again:
|
||||
goto done;
|
||||
}
|
||||
|
||||
DBG_INFO("Sending %s client %s to %d with %"PRIu32" clients\n",
|
||||
DBG_INFO("Sending %s client %s to %d with "
|
||||
"%"PRIu32" associations and %"PRIu32" connections\n",
|
||||
client_type,
|
||||
server->rpc_server_exe,
|
||||
worker->pid,
|
||||
worker->num_clients);
|
||||
worker->num_associations,
|
||||
worker->num_connections);
|
||||
|
||||
iov = (struct iovec) {
|
||||
.iov_base = blob.data, .iov_len = blob.length,
|
||||
@ -1404,7 +1422,10 @@ again:
|
||||
nt_errstr(status));
|
||||
goto done;
|
||||
}
|
||||
worker->num_clients += 1;
|
||||
if (assoc_group_id == 0) {
|
||||
worker->num_associations += 1;
|
||||
}
|
||||
worker->num_connections += 1;
|
||||
TALLOC_FREE(worker->exit_timer);
|
||||
|
||||
TALLOC_FREE(server->host->np_helper_shutdown);
|
||||
@ -1850,7 +1871,7 @@ static void rpc_host_exit_worker(
|
||||
}
|
||||
w->exit_timer = NULL;
|
||||
|
||||
SMB_ASSERT(w->num_clients == 0);
|
||||
SMB_ASSERT(w->num_associations == 0);
|
||||
|
||||
status = messaging_send(
|
||||
server->host->msg_ctx,
|
||||
@ -1930,9 +1951,10 @@ static void rpc_host_child_status_recv(
|
||||
}
|
||||
|
||||
worker->available = true;
|
||||
worker->num_clients = status_message.num_clients;
|
||||
worker->num_associations = status_message.num_association_groups;
|
||||
worker->num_connections = status_message.num_connections;
|
||||
|
||||
if (worker->num_clients != 0) {
|
||||
if (worker->num_associations != 0) {
|
||||
TALLOC_FREE(worker->exit_timer);
|
||||
} else {
|
||||
worker->exit_timer = tevent_add_timer(
|
||||
@ -2333,10 +2355,11 @@ static bool rpc_host_dump_status_filter(
|
||||
}
|
||||
|
||||
fprintf(f,
|
||||
" worker[%zu]: pid=%d, num_clients=%"PRIu32"\n",
|
||||
" worker[%zu]: pid=%d, num_associations=%"PRIu32", num_connections=%"PRIu32"\n",
|
||||
j,
|
||||
(int)w->pid,
|
||||
w->num_clients);
|
||||
w->num_associations,
|
||||
w->num_connections);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -95,11 +95,13 @@ static void rpc_worker_print_interface(
|
||||
|
||||
static NTSTATUS rpc_worker_report_status(struct rpc_worker *worker)
|
||||
{
|
||||
uint8_t buf[12];
|
||||
uint8_t buf[16];
|
||||
DATA_BLOB blob = { .data = buf, .length = sizeof(buf), };
|
||||
enum ndr_err_code ndr_err;
|
||||
NTSTATUS status;
|
||||
|
||||
worker->status.num_association_groups = worker->dce_ctx->assoc_groups_num;
|
||||
|
||||
if (DEBUGLEVEL >= 10) {
|
||||
NDR_PRINT_DEBUG(rpc_worker_status, &worker->status);
|
||||
}
|
||||
@ -129,7 +131,19 @@ static void rpc_worker_connection_terminated(
|
||||
NTSTATUS status;
|
||||
bool found = false;
|
||||
|
||||
SMB_ASSERT(worker->status.num_clients > 0);
|
||||
/*
|
||||
* We need to drop the association group reference
|
||||
* explicitly here in order to avoid the order given
|
||||
* by the destructors. rpc_worker_report_status() below,
|
||||
* expects worker->dce_ctx->assoc_groups_num to be updated
|
||||
* already.
|
||||
*/
|
||||
if (conn->assoc_group != NULL) {
|
||||
talloc_unlink(conn, conn->assoc_group);
|
||||
conn->assoc_group = NULL;
|
||||
}
|
||||
|
||||
SMB_ASSERT(worker->status.num_connections > 0);
|
||||
|
||||
for (w = worker->conns; w != NULL; w = w->next) {
|
||||
if (w == ncacn_conn) {
|
||||
@ -141,7 +155,7 @@ static void rpc_worker_connection_terminated(
|
||||
|
||||
DLIST_REMOVE(worker->conns, ncacn_conn);
|
||||
|
||||
worker->status.num_clients -= 1;
|
||||
worker->status.num_connections -= 1;
|
||||
|
||||
status = rpc_worker_report_status(worker);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
@ -467,7 +481,7 @@ static void rpc_worker_new_client(
|
||||
TALLOC_FREE(client);
|
||||
|
||||
DLIST_ADD(worker->conns, ncacn_conn);
|
||||
worker->status.num_clients += 1;
|
||||
worker->status.num_connections += 1;
|
||||
|
||||
dcesrv_loop_next_packet(dcesrv_conn, pkt, buffer);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user