dovecot-2.0: master: When process_limit fills up, wait 10s befor...
dovecot at dovecot.org
dovecot at dovecot.org
Thu Oct 20 18:28:51 EEST 2011
details: http://hg.dovecot.org/dovecot-2.0/rev/d4e15513192a
changeset: 12949:d4e15513192a
user: Timo Sirainen <tss at iki.fi>
date: Thu Oct 20 18:37:09 2011 +0300
description:
master: When process_limit fills up, wait 10s before closing pending connections.
It might have only been a temporary burst that gets resolved quickly enough.
diffstat:
src/master/service-monitor.c | 63 ++++++++++++++++++++++++++++++++++++-------
src/master/service.h | 3 ++
2 files changed, 55 insertions(+), 11 deletions(-)
diffs (131 lines):
diff -r 6f1442a0d1c6 -r d4e15513192a src/master/service-monitor.c
--- a/src/master/service-monitor.c Thu Oct 20 18:26:15 2011 +0300
+++ b/src/master/service-monitor.c Thu Oct 20 18:37:09 2011 +0300
@@ -22,10 +22,12 @@
#define SERVICE_STARTUP_FAILURE_THROTTLE_SECS 60
#define SERVICE_DROP_WARN_INTERVAL_SECS 60
+#define SERVICE_DROP_TIMEOUT_MSECS (10*1000)
static void service_monitor_start_extra_avail(struct service *service);
static void service_status_more(struct service_process *process,
const struct master_status *status);
+static void service_monitor_listen_start_force(struct service *service);
static void service_process_kill_idle(struct service_process *process)
{
@@ -195,6 +197,32 @@
service_throttle(service, SERVICE_STARTUP_FAILURE_THROTTLE_SECS);
}
+static void service_drop_timeout(struct service *service)
+{
+ struct service_listener *const *lp;
+ int fd;
+
+ i_assert(service->process_avail == 0);
+
+ /* drop all pending connections */
+ array_foreach(&service->listeners, lp) {
+ while ((fd = net_accept((*lp)->fd, NULL, NULL)) > 0)
+ net_disconnect(fd);
+ }
+
+ service_monitor_listen_start_force(service);
+ service->listen_pending = TRUE;
+}
+
+static void service_monitor_listen_pending(struct service *service)
+{
+ service_monitor_listen_stop(service);
+ service->listen_pending = TRUE;
+
+ service->to_drop = timeout_add(SERVICE_DROP_TIMEOUT_MSECS,
+ service_drop_timeout, service);
+}
+
static void service_drop_connections(struct service_listener *l)
{
struct service *service = l->service;
@@ -216,12 +244,16 @@
reach connection limit */
service_login_notify(service, TRUE);
- service_monitor_listen_stop(service);
- service->listen_pending = TRUE;
+ service_monitor_listen_pending(service);
+ } else if (!service->listen_pending) {
+ /* maybe this is a temporary peak, stop for a while and
+ see if it goes away */
+ service_monitor_listen_pending(service);
} else {
- /* just accept and close the connection, so it's clear that
- this is happening because of the limit, rather than because
- the service processes aren't answering fast enough */
+ /* this has been happening for a while now. just accept and
+ close the connection, so it's clear that this is happening
+ because of the limit, rather than because the service
+ processes aren't answering fast enough */
fd = net_accept(l->fd, NULL, NULL);
if (fd > 0)
net_disconnect(fd);
@@ -271,17 +303,14 @@
}
}
-void service_monitor_listen_start(struct service *service)
+static void service_monitor_listen_start_force(struct service *service)
{
struct service_listener *const *listeners;
- if (service->process_avail > 0 ||
- (service->process_count == service->process_limit &&
- service->listen_pending))
- return;
-
service->listening = TRUE;
service->listen_pending = FALSE;
+ if (service->to_drop != NULL)
+ timeout_remove(&service->to_drop);
array_foreach(&service->listeners, listeners) {
struct service_listener *l = *listeners;
@@ -291,6 +320,16 @@
}
}
+void service_monitor_listen_start(struct service *service)
+{
+ if (service->process_avail > 0 ||
+ (service->process_count == service->process_limit &&
+ service->listen_pending))
+ return;
+
+ service_monitor_listen_start_force(service);
+}
+
void service_monitor_listen_stop(struct service *service)
{
struct service_listener *const *listeners;
@@ -303,6 +342,8 @@
}
service->listening = FALSE;
service->listen_pending = FALSE;
+ if (service->to_drop != NULL)
+ timeout_remove(&service->to_drop);
}
static int service_login_create_notify_fd(struct service *service)
diff -r 6f1442a0d1c6 -r d4e15513192a src/master/service.h
--- a/src/master/service.h Thu Oct 20 18:26:15 2011 +0300
+++ b/src/master/service.h Thu Oct 20 18:37:09 2011 +0300
@@ -88,6 +88,9 @@
/* if a process fails before servicing its first request, assume it's
broken and start throtting new process creations */
struct timeout *to_throttle;
+ /* when process_limit is reached, wait for a while until we actually
+ start dropping pending connections */
+ struct timeout *to_drop;
/* Last time a "dropping client connections" warning was logged */
time_t last_drop_warning;
More information about the dovecot-cvs
mailing list