You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@james.apache.org by bt...@apache.org on 2022/05/04 01:10:44 UTC

[james-project] branch master updated (98b53e6439 -> 5b9155995f)

This is an automated email from the ASF dual-hosted git repository.

btellier pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git


    from 98b53e6439 JAMES-3752 Allow disabling ImapChannelUpstreamHandler heartbeat handler
     new ef0b073344 JAMES-3737 Allow configuring boss thread count for protocols
     new 6074bc1905 JAMES-3737 Document thread tuning for protocols
     new 5b9155995f JAMES-3737 Allow configuring ElasticSearch connections

The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../james/backends/es/v7/ClientProvider.java       |  3 ++
 .../backends/es/v7/ElasticSearchConfiguration.java | 40 ++++++++++++++++++---
 .../james/protocols/netty/AbstractAsyncServer.java | 42 ++++++++++++++++------
 .../ROOT/pages/configure/elasticsearch.adoc        |  9 +++++
 .../docs/modules/ROOT/pages/configure/imap.adoc    | 14 ++++++++
 .../docs/modules/ROOT/pages/configure/pop3.adoc    | 13 +++++++
 .../docs/modules/ROOT/pages/configure/sieve.adoc   | 15 +++++++-
 .../docs/modules/ROOT/pages/configure/smtp.adoc    | 13 +++++++
 .../lib/netty/AbstractConfigurableAsyncServer.java |  4 ++-
 src/site/xdoc/server/config-elasticsearch.xml      |  6 ++++
 src/site/xdoc/server/config-imap4.xml              | 15 ++++++++
 src/site/xdoc/server/config-pop3.xml               | 13 +++++++
 src/site/xdoc/server/config-smtp-lmtp.xml          | 15 ++++++--
 13 files changed, 183 insertions(+), 19 deletions(-)


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org


[james-project] 03/03: JAMES-3737 Allow configuring ElasticSearch connections

Posted by bt...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

btellier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git

commit 5b9155995f1fbe627f7a69477722f43e62815a7b
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Mon Apr 18 17:08:12 2022 +0700

    JAMES-3737 Allow configuring ElasticSearch connections
    
    To quote the driver itself: default settings for connection
    pooling may be too constraining. These limits might be hit
    with a few concurrent ElasticSearch request. Exposing these setting is thus interesting.
---
 .../james/backends/es/v7/ClientProvider.java       |  3 ++
 .../backends/es/v7/ElasticSearchConfiguration.java | 40 +++++++++++++++++++---
 .../ROOT/pages/configure/elasticsearch.adoc        |  9 +++++
 src/site/xdoc/server/config-elasticsearch.xml      |  6 ++++
 4 files changed, 54 insertions(+), 4 deletions(-)

diff --git a/backends-common/elasticsearch-v7/src/main/java/org/apache/james/backends/es/v7/ClientProvider.java b/backends-common/elasticsearch-v7/src/main/java/org/apache/james/backends/es/v7/ClientProvider.java
index 9d4fc151cc..a8b16ffc22 100644
--- a/backends-common/elasticsearch-v7/src/main/java/org/apache/james/backends/es/v7/ClientProvider.java
+++ b/backends-common/elasticsearch-v7/src/main/java/org/apache/james/backends/es/v7/ClientProvider.java
@@ -76,6 +76,9 @@ public class ClientProvider implements Provider<ReactorElasticSearchClient> {
             configureHostScheme(builder);
             configureTimeout(builder);
 
+            configuration.getMaxConnections().ifPresent(builder::setMaxConnTotal);
+            configuration.getMaxConnectionsPerHost().ifPresent(builder::setMaxConnPerRoute);
+
             builder.setThreadFactory(NamedThreadFactory.withName("ElasticSearch-driver"));
 
             return builder;
diff --git a/backends-common/elasticsearch-v7/src/main/java/org/apache/james/backends/es/v7/ElasticSearchConfiguration.java b/backends-common/elasticsearch-v7/src/main/java/org/apache/james/backends/es/v7/ElasticSearchConfiguration.java
index a29140a2f6..b7dedbac23 100644
--- a/backends-common/elasticsearch-v7/src/main/java/org/apache/james/backends/es/v7/ElasticSearchConfiguration.java
+++ b/backends-common/elasticsearch-v7/src/main/java/org/apache/james/backends/es/v7/ElasticSearchConfiguration.java
@@ -307,6 +307,8 @@ public class ElasticSearchConfiguration {
         private Optional<HostScheme> hostScheme;
         private Optional<Credential> credential;
         private Optional<SSLConfiguration> sslTrustConfiguration;
+        private Optional<Integer> maxConnectionsPerHost;
+        private Optional<Integer> maxConnections;
 
         public Builder() {
             hosts = ImmutableList.builder();
@@ -319,6 +321,8 @@ public class ElasticSearchConfiguration {
             hostScheme = Optional.empty();
             credential = Optional.empty();
             sslTrustConfiguration = Optional.empty();
+            maxConnectionsPerHost = Optional.empty();
+            maxConnections = Optional.empty();
         }
 
         public Builder addHost(Host host) {
@@ -359,6 +363,16 @@ public class ElasticSearchConfiguration {
             return this;
         }
 
+        public Builder maxConnectionsPerHost(Optional<Integer> maxConnectionsPerHost) {
+            this.maxConnectionsPerHost = maxConnectionsPerHost;
+            return this;
+        }
+
+        public Builder maxConnections(Optional<Integer> maxConnections) {
+            this.maxConnections = maxConnections;
+            return this;
+        }
+
         public Builder requestTimeout(Optional<Duration> requestTimeout) {
             this.requestTimeout = requestTimeout;
             return this;
@@ -397,7 +411,7 @@ public class ElasticSearchConfiguration {
                 requestTimeout.orElse(DEFAULT_REQUEST_TIMEOUT),
                 hostScheme.orElse(DEFAULT_SCHEME),
                 credential,
-                sslTrustConfiguration.orElse(DEFAULT_SSL_TRUST_CONFIGURATION));
+                sslTrustConfiguration.orElse(DEFAULT_SSL_TRUST_CONFIGURATION), maxConnections, maxConnectionsPerHost);
         }
     }
 
@@ -420,6 +434,8 @@ public class ElasticSearchConfiguration {
     public static final String ELASTICSEARCH_NB_SHARDS = "elasticsearch.nb.shards";
     public static final String ELASTICSEARCH_RETRY_CONNECTION_MIN_DELAY = "elasticsearch.retryConnection.minDelay";
     public static final String ELASTICSEARCH_RETRY_CONNECTION_MAX_RETRIES = "elasticsearch.retryConnection.maxRetries";
+    public static final String ELASTICSEARCH_MAX_CONNECTIONS = "elasticsearch.max.connections";
+    public static final String ELASTICSEARCH_MAX_CONNECTIONS_PER_HOSTS = "elasticsearch.max.connections.per.hosts";
 
     public static final int DEFAULT_CONNECTION_MAX_RETRIES = 7;
     public static final int DEFAULT_CONNECTION_MIN_DELAY = 3000;
@@ -448,6 +464,8 @@ public class ElasticSearchConfiguration {
             .waitForActiveShards(configuration.getInteger(WAIT_FOR_ACTIVE_SHARDS, DEFAULT_WAIT_FOR_ACTIVE_SHARDS))
             .minDelay(Optional.ofNullable(configuration.getInteger(ELASTICSEARCH_RETRY_CONNECTION_MIN_DELAY, null)))
             .maxRetries(Optional.ofNullable(configuration.getInteger(ELASTICSEARCH_RETRY_CONNECTION_MAX_RETRIES, null)))
+            .maxConnections(Optional.ofNullable(configuration.getInteger(ELASTICSEARCH_MAX_CONNECTIONS, null)))
+            .maxConnectionsPerHost(Optional.ofNullable(configuration.getInteger(ELASTICSEARCH_MAX_CONNECTIONS_PER_HOSTS, null)))
             .build();
     }
 
@@ -540,9 +558,11 @@ public class ElasticSearchConfiguration {
     private final HostScheme hostScheme;
     private final Optional<Credential> credential;
     private final SSLConfiguration sslConfiguration;
+    private final Optional<Integer> maxConnections;
+    private final Optional<Integer> maxConnectionsPerHost;
 
     private ElasticSearchConfiguration(ImmutableList<Host> hosts, int nbShards, int nbReplica, int waitForActiveShards, int minDelay, int maxRetries, Duration requestTimeout,
-                                       HostScheme hostScheme, Optional<Credential> credential, SSLConfiguration sslConfiguration) {
+                                       HostScheme hostScheme, Optional<Credential> credential, SSLConfiguration sslConfiguration, Optional<Integer> maxConnections, Optional<Integer> maxConnectionsPerHost) {
         this.hosts = hosts;
         this.nbShards = nbShards;
         this.nbReplica = nbReplica;
@@ -553,6 +573,8 @@ public class ElasticSearchConfiguration {
         this.hostScheme = hostScheme;
         this.credential = credential;
         this.sslConfiguration = sslConfiguration;
+        this.maxConnections = maxConnections;
+        this.maxConnectionsPerHost = maxConnectionsPerHost;
     }
 
     public ImmutableList<Host> getHosts() {
@@ -595,6 +617,14 @@ public class ElasticSearchConfiguration {
         return sslConfiguration;
     }
 
+    public Optional<Integer> getMaxConnections() {
+        return maxConnections;
+    }
+
+    public Optional<Integer> getMaxConnectionsPerHost() {
+        return maxConnectionsPerHost;
+    }
+
     @Override
     public final boolean equals(Object o) {
         if (o instanceof ElasticSearchConfiguration) {
@@ -609,7 +639,9 @@ public class ElasticSearchConfiguration {
                 && Objects.equals(this.requestTimeout, that.requestTimeout)
                 && Objects.equals(this.hostScheme, that.hostScheme)
                 && Objects.equals(this.credential, that.credential)
-                && Objects.equals(this.sslConfiguration, that.sslConfiguration);
+                && Objects.equals(this.sslConfiguration, that.sslConfiguration)
+                && Objects.equals(this.maxConnections, that.maxConnections)
+                && Objects.equals(this.maxConnectionsPerHost, that.maxConnectionsPerHost);
         }
         return false;
     }
@@ -617,6 +649,6 @@ public class ElasticSearchConfiguration {
     @Override
     public final int hashCode() {
         return Objects.hash(hosts, nbShards, nbReplica, waitForActiveShards, minDelay, maxRetries, requestTimeout,
-            hostScheme, credential, sslConfiguration);
+            hostScheme, credential, sslConfiguration, maxConnections, maxConnectionsPerHost);
     }
 }
diff --git a/server/apps/distributed-app/docs/modules/ROOT/pages/configure/elasticsearch.adoc b/server/apps/distributed-app/docs/modules/ROOT/pages/configure/elasticsearch.adoc
index 3cd61a5867..6d3c1fd6cb 100644
--- a/server/apps/distributed-app/docs/modules/ROOT/pages/configure/elasticsearch.adoc
+++ b/server/apps/distributed-app/docs/modules/ROOT/pages/configure/elasticsearch.adoc
@@ -34,6 +34,15 @@ You may consult the https://www.elastic.co/guide/en/elasticsearch/reference/7.10
 
 | elasticsearch.retryConnection.minDelay
 | Minimum delay between connection attempts
+
+| elasticsearch.max.connections
+| Maximum count of HTTP connections allowed for the ElasticSearch driver. Optional integer, if unspecified driver defaults
+applies (30 connections).
+
+| elasticsearch.max.connections.per.hosts
+| Maximum count of HTTP connections per host allowed for the ElasticSearch driver. Optional integer, if unspecified driver defaults
+applies (10 connections).
+
 |===
 
 === Mailbox search
diff --git a/src/site/xdoc/server/config-elasticsearch.xml b/src/site/xdoc/server/config-elasticsearch.xml
index 0cd6d1349b..c3bd3276cd 100644
--- a/src/site/xdoc/server/config-elasticsearch.xml
+++ b/src/site/xdoc/server/config-elasticsearch.xml
@@ -87,6 +87,12 @@
           <dt><strong>elasticsearch.index.name</strong></dt>
           <dd><strong>Deprecated</strong> Use <strong>elasticsearch.index.mailbox.name</strong> instead. <br/>
               Name of the mailbox index backed by the alias. It will be created if missing.</dd>
+          <dt><strong>elasticsearch.max.connections</strong></dt>
+          <dd>Maximum count of HTTP connections allowed for the ElasticSearch driver. Optional integer, if unspecified driver defaults
+              applies (30 connections).</dd>
+          <dt><strong>elasticsearch.max.connections.per.hosts</strong></dt>
+          <dd>Maximum count of HTTP connections per host allowed for the ElasticSearch driver. Optional integer, if unspecified driver defaults
+              applies (10 connections).</dd>
           <dt><strong>elasticsearch.alias.read.mailbox.name</strong></dt>
           <dd>Name of the alias to use by Apache James for mailbox reads. It will be created if missing.
               The target of the alias is the index name configured above.</dd>


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org


[james-project] 02/03: JAMES-3737 Document thread tuning for protocols

Posted by bt...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

btellier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git

commit 6074bc19052c3e64d327605a5387e7357237c340
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Mon Apr 18 16:37:34 2022 +0700

    JAMES-3737 Document thread tuning for protocols
---
 .../apache/james/protocols/netty/AbstractAsyncServer.java |  4 ++--
 .../docs/modules/ROOT/pages/configure/imap.adoc           | 14 ++++++++++++++
 .../docs/modules/ROOT/pages/configure/pop3.adoc           | 13 +++++++++++++
 .../docs/modules/ROOT/pages/configure/sieve.adoc          | 15 ++++++++++++++-
 .../docs/modules/ROOT/pages/configure/smtp.adoc           | 13 +++++++++++++
 src/site/xdoc/server/config-imap4.xml                     | 15 +++++++++++++++
 src/site/xdoc/server/config-pop3.xml                      | 13 +++++++++++++
 src/site/xdoc/server/config-smtp-lmtp.xml                 | 15 +++++++++++++--
 8 files changed, 97 insertions(+), 5 deletions(-)

diff --git a/protocols/netty/src/main/java/org/apache/james/protocols/netty/AbstractAsyncServer.java b/protocols/netty/src/main/java/org/apache/james/protocols/netty/AbstractAsyncServer.java
index 13d343319b..93036043a4 100644
--- a/protocols/netty/src/main/java/org/apache/james/protocols/netty/AbstractAsyncServer.java
+++ b/protocols/netty/src/main/java/org/apache/james/protocols/netty/AbstractAsyncServer.java
@@ -63,7 +63,7 @@ public abstract class AbstractAsyncServer implements ProtocolServer {
     private final ChannelGroup channels = new DefaultChannelGroup(ImmediateEventExecutor.INSTANCE);
 
     private volatile int ioWorker = DEFAULT_IO_WORKER_COUNT;
-    private volatile Optional<Integer> bossWorker = Optional.of(DEFAULT_IO_WORKER_COUNT);
+    private volatile Optional<Integer> bossWorker = Optional.of(DEFAULT_BOSS_WORKER_COUNT);
 
     private List<InetSocketAddress> addresses = new ArrayList<>();
 
@@ -123,7 +123,7 @@ public abstract class AbstractAsyncServer implements ProtocolServer {
         ServerBootstrap bootstrap = new ServerBootstrap();
         bootstrap.channel(NioServerSocketChannel.class);
 
-        bossGroup = bossWorker.map(count -> new NioEventLoopGroup(2, NamedThreadFactory.withName(jmxName + "-boss")));
+        bossGroup = bossWorker.map(count -> new NioEventLoopGroup(count, NamedThreadFactory.withName(jmxName + "-boss")));
         workerGroup = new NioEventLoopGroup(ioWorker, NamedThreadFactory.withName(jmxName + "-io"));
 
         bossGroup.<Runnable>map(boss -> () -> bootstrap.group(boss, workerGroup))
diff --git a/server/apps/distributed-app/docs/modules/ROOT/pages/configure/imap.adoc b/server/apps/distributed-app/docs/modules/ROOT/pages/configure/imap.adoc
index fc60ea4ce0..646e74a061 100644
--- a/server/apps/distributed-app/docs/modules/ROOT/pages/configure/imap.adoc
+++ b/server/apps/distributed-app/docs/modules/ROOT/pages/configure/imap.adoc
@@ -107,6 +107,20 @@ will use the specified value.
 | connectionLimitPerIP
 | Set the maximum simultaneous incoming connections per IP for this service
 
+| bossWorkerCount
+| Set the maximum count of boss threads. Boss threads are responsible for accepting incoming IMAP connections
+and initializing associated resources. Optional integer, by default, boss threads are not used and this responsibility is being dealt with
+by IO threads.
+
+| ioWorkerCount
+| Set the maximum count of IO threads. IO threads are responsible for receiving incoming IMAP messages and framing them
+(split line by line). IO threads also take care of compression and SSL encryption. Their tasks are short-lived and non-blocking.
+Optional integer, defaults to 2 times the count of CPUs.
+
+| maxExecutorCount
+| Set the maximum count of worker threads. Worker threads takes care of potentially blocking tasks like decoding IMAP requests
+(litterals can be buffered to temporary files) or executing IMAP commands. Optional integer, defaults to 16.
+
 | ignoreIDLEUponProcessing
 | true or false - Allow disabling the heartbeat handler. Defaults to true.
 |===
diff --git a/server/apps/distributed-app/docs/modules/ROOT/pages/configure/pop3.adoc b/server/apps/distributed-app/docs/modules/ROOT/pages/configure/pop3.adoc
index e065937f17..fdde5ebf39 100644
--- a/server/apps/distributed-app/docs/modules/ROOT/pages/configure/pop3.adoc
+++ b/server/apps/distributed-app/docs/modules/ROOT/pages/configure/pop3.adoc
@@ -55,4 +55,17 @@ will use the specified value.
 
 | handler.handlerchain
 | This loads the core CommandHandlers. Only remove this if you really know what you are doing.
+
+| bossWorkerCount
+| Set the maximum count of boss threads. Boss threads are responsible for accepting incoming POP3 connections
+and initializing associated resources. Optional integer, by default, boss threads are not used and this responsibility is being dealt with
+by IO threads.
+
+| ioWorkerCount
+| Set the maximum count of IO threads. IO threads are responsible for receiving incoming POP3 messages and framing them
+(split line by line). IO threads also take care of compression and SSL encryption. Their tasks are short-lived and non-blocking.
+Optional integer, defaults to 2 times the count of CPUs.
+
+| maxExecutorCount
+| Set the maximum count of worker threads. Worker threads takes care of potentially blocking tasks like executing POP3 requests. Optional integer, defaults to 16.
 |===
\ No newline at end of file
diff --git a/server/apps/distributed-app/docs/modules/ROOT/pages/configure/sieve.adoc b/server/apps/distributed-app/docs/modules/ROOT/pages/configure/sieve.adoc
index 87d5ff623a..b7a27dad59 100644
--- a/server/apps/distributed-app/docs/modules/ROOT/pages/configure/sieve.adoc
+++ b/server/apps/distributed-app/docs/modules/ROOT/pages/configure/sieve.adoc
@@ -61,7 +61,7 @@ will bind to all network interfaces for the machine If the tag or value is omitt
 | Set to true to support STARTTLS or SSL for the Socket.
 To use this you need to copy sunjce_provider.jar to /path/james/lib directory. To create a new keystore execute:
 `keytool -genkey -alias james -keyalg RSA -storetype PKCS12 -keystore /path/to/james/conf/keystore`.
-Please note that each IMAP server exposed on different port can specify its own keystore, independently from any other
+Please note that each ManageSieve server exposed on different port can specify its own keystore, independently from any other
 TLS based protocols.
 
 | connectionBacklog
@@ -76,4 +76,17 @@ TLS based protocols.
 | connectionLimitPerIP
 | Set the maximum simultaneous incoming connections per IP for this service
 
+| bossWorkerCount
+| Set the maximum count of boss threads. Boss threads are responsible for accepting incoming ManageSieve connections
+and initializing associated resources. Optional integer, by default, boss threads are not used and this responsibility is being dealt with
+by IO threads.
+
+| ioWorkerCount
+| Set the maximum count of IO threads. IO threads are responsible for receiving incoming ManageSieve messages and framing them
+(split line by line). IO threads also take care of compression and SSL encryption. Their tasks are short-lived and non-blocking.
+Optional integer, defaults to 2 times the count of CPUs.
+
+| maxExecutorCount
+| Set the maximum count of worker threads. Worker threads takes care of potentially blocking tasks like executing ManageSieve commands.
+Optional integer, defaults to 16.
 |===
\ No newline at end of file
diff --git a/server/apps/distributed-app/docs/modules/ROOT/pages/configure/smtp.adoc b/server/apps/distributed-app/docs/modules/ROOT/pages/configure/smtp.adoc
index 18bdcde53c..33d4e4536d 100644
--- a/server/apps/distributed-app/docs/modules/ROOT/pages/configure/smtp.adoc
+++ b/server/apps/distributed-app/docs/modules/ROOT/pages/configure/smtp.adoc
@@ -146,6 +146,19 @@ If none is specified a default is generated
 | The configuration handler chain. See xref:configure/smtp-hooks.adoc[this page] for configuring out-of the
 box extra SMTP handlers and hooks.
 
+| bossWorkerCount
+| Set the maximum count of boss threads. Boss threads are responsible for accepting incoming SMTP connections
+and initializing associated resources. Optional integer, by default, boss threads are not used and this responsibility is being dealt with
+by IO threads.
+
+| ioWorkerCount
+| Set the maximum count of IO threads. IO threads are responsible for receiving incoming SMTP messages and framing them
+(split line by line). IO threads also take care of compression and SSL encryption. Their tasks are short-lived and non-blocking.
+Optional integer, defaults to 2 times the count of CPUs.
+
+| maxExecutorCount
+| Set the maximum count of worker threads. Worker threads takes care of potentially blocking tasks like executing SMTP commands.
+Optional integer, defaults to 16.
 |===
 
 === OIDC setup
diff --git a/src/site/xdoc/server/config-imap4.xml b/src/site/xdoc/server/config-imap4.xml
index 77c923d68d..e3d971d692 100644
--- a/src/site/xdoc/server/config-imap4.xml
+++ b/src/site/xdoc/server/config-imap4.xml
@@ -97,6 +97,21 @@
         <dd>Claim string uses to identify user. E.g: "email_address". Only configure this when you want to authenticate IMAP server using a OIDC provider.</dd>
         <dt><strong>auth.oidc.scope</strong></dt>
         <dd>An OAuth scope that is valid to access the service (RF: RFC7628). Only configure this when you want to authenticate IMAP server using a OIDC provider.</dd>
+
+        <dt><strong>bossWorkerCount</strong></dt>
+        <dd>Set the maximum count of boss threads. Boss threads are responsible for accepting incoming IMAP connections
+          and initializing associated resources. Optional integer, by default, boss threads are not used and this responsibility is being dealt with
+            by IO threads</dd>
+
+        <dt><strong>ioWorkerCount</strong></dt>
+        <dd>Set the maximum count of IO threads. IO threads are responsible for receiving incoming IMAP messages and framing them
+          (split line by line). IO threads also take care of compression and SSL encryption. Their tasks are short-lived and non-blocking.
+              Optional integer, defaults to 2 times the count of CPUs.</dd>
+
+        <dt><strong>maxExecutorCount</strong></dt>
+        <dd>Set the maximum count of worker threads. Worker threads takes care of potentially blocking tasks like decoding IMAP requests
+              (litterals can be buffered to temporary files) or executing IMAP commands. Optional integer, defaults to 16.</dd>
+
         <dt><strong>ignoreIDLEUponProcessing</strong></dt>
         <dd>true or false - Allow disabling the heartbeat handler. Defaults to true.</dd>
       </dl>
diff --git a/src/site/xdoc/server/config-pop3.xml b/src/site/xdoc/server/config-pop3.xml
index 7de2635c78..fd53a2ed7f 100644
--- a/src/site/xdoc/server/config-pop3.xml
+++ b/src/site/xdoc/server/config-pop3.xml
@@ -69,6 +69,19 @@
         <dt><strong>handler.handlerchain</strong></dt>
         <dd>This loads the core CommandHandlers. Only remove this if you really 
              know what you are doing</dd>
+        <dt><strong>bossWorkerCount</strong></dt>
+        <dd>Set the maximum count of boss threads. Boss threads are responsible for accepting incoming POP3 connections
+              and initializing associated resources. Optional integer, by default, boss threads are not used and this responsibility is being dealt with
+              by IO threads</dd>
+
+        <dt><strong>ioWorkerCount</strong></dt>
+        <dd>Set the maximum count of IO threads. IO threads are responsible for receiving incoming POP3 messages and framing them
+              (split line by line). IO threads also take care of compression and SSL encryption. Their tasks are short-lived and non-blocking.
+              Optional integer, defaults to 2 times the count of CPUs.</dd>
+
+        <dt><strong>maxExecutorCount</strong></dt>
+        <dd>Set the maximum count of worker threads. Worker threads takes care of potentially blocking tasks like executing POP3 requests.
+            Optional integer, defaults to 16.</dd>
       </dl>
 
   </section>
diff --git a/src/site/xdoc/server/config-smtp-lmtp.xml b/src/site/xdoc/server/config-smtp-lmtp.xml
index f444ba5417..8a9593b06a 100644
--- a/src/site/xdoc/server/config-smtp-lmtp.xml
+++ b/src/site/xdoc/server/config-smtp-lmtp.xml
@@ -148,9 +148,20 @@
       <dd>This sets the SMTPGreeting which will be used when connect to the smtpserver 
           If none is specified a default is generated</dd>
       <dt><strong>handler.handlerchain</strong></dt>
-      <dd></dd>
-      <dt><strong>handler.handlerchain</strong></dt>
       <dd>The configuration handler chain</dd>
+      <dt><strong>bossWorkerCount</strong></dt>
+      <dd>Set the maximum count of boss threads. Boss threads are responsible for accepting incoming SMTP connections
+            and initializing associated resources. Optional integer, by default, boss threads are not used and this responsibility is being dealt with
+            by IO threads</dd>
+
+      <dt><strong>ioWorkerCount</strong></dt>
+      <dd>Set the maximum count of IO threads. IO threads are responsible for receiving incoming SMTP messages and framing them
+            (split line by line). IO threads also take care of compression and SSL encryption. Their tasks are short-lived and non-blocking.
+            Optional integer, defaults to 2 times the count of CPUs.</dd>
+
+      <dt><strong>maxExecutorCount</strong></dt>
+      <dd>Set the maximum count of worker threads. Worker threads takes care of potentially blocking tasks like
+          executing SMTP commands. Optional integer, defaults to 16.</dd>
     </dl>
 
       <subsection name="OIDC set up">


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org


[james-project] 01/03: JAMES-3737 Allow configuring boss thread count for protocols

Posted by bt...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

btellier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git

commit ef0b073344506845a319e06e3c723e66a407d39d
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Mon Apr 18 16:37:09 2022 +0700

    JAMES-3737 Allow configuring boss thread count for protocols
    
    These threads are used for accepting incoming connections.
    
     - Ability to specify the thread count
     - Ability to instead rely on IO threads
---
 .../james/protocols/netty/AbstractAsyncServer.java | 42 ++++++++++++++++------
 .../lib/netty/AbstractConfigurableAsyncServer.java |  4 ++-
 2 files changed, 34 insertions(+), 12 deletions(-)

diff --git a/protocols/netty/src/main/java/org/apache/james/protocols/netty/AbstractAsyncServer.java b/protocols/netty/src/main/java/org/apache/james/protocols/netty/AbstractAsyncServer.java
index 392c5a65f4..13d343319b 100644
--- a/protocols/netty/src/main/java/org/apache/james/protocols/netty/AbstractAsyncServer.java
+++ b/protocols/netty/src/main/java/org/apache/james/protocols/netty/AbstractAsyncServer.java
@@ -21,6 +21,7 @@ package org.apache.james.protocols.netty;
 import java.net.InetSocketAddress;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Optional;
 
 import org.apache.james.protocols.api.ProtocolServer;
 import org.apache.james.util.concurrent.NamedThreadFactory;
@@ -49,11 +50,12 @@ import io.netty.util.concurrent.ImmediateEventExecutor;
 public abstract class AbstractAsyncServer implements ProtocolServer {
 
     public static final int DEFAULT_IO_WORKER_COUNT = Runtime.getRuntime().availableProcessors() * 2;
+    public static final int DEFAULT_BOSS_WORKER_COUNT = 2;
     private volatile int backlog = 250;
     
     private volatile int timeout = 120;
 
-    private EventLoopGroup bossGroup;
+    private Optional<EventLoopGroup> bossGroup;
     private EventLoopGroup workerGroup;
 
     private volatile boolean started;
@@ -61,7 +63,8 @@ public abstract class AbstractAsyncServer implements ProtocolServer {
     private final ChannelGroup channels = new DefaultChannelGroup(ImmediateEventExecutor.INSTANCE);
 
     private volatile int ioWorker = DEFAULT_IO_WORKER_COUNT;
-    
+    private volatile Optional<Integer> bossWorker = Optional.of(DEFAULT_IO_WORKER_COUNT);
+
     private List<InetSocketAddress> addresses = new ArrayList<>();
 
     protected String jmxName;
@@ -80,7 +83,11 @@ public abstract class AbstractAsyncServer implements ProtocolServer {
     }
 
     /**
-     * Set the IO-worker thread count to use. Default is nCores * 2
+     * Set the IO-worker thread count to use.
+     *
+     * IO threads are used for receiving and framing IMAP messages.
+     *
+     * Default is nCores * 2
      */
     public void setIoWorkerCount(int ioWorker) {
         if (started) {
@@ -89,6 +96,20 @@ public abstract class AbstractAsyncServer implements ProtocolServer {
         this.ioWorker = ioWorker;
     }
 
+    /**
+     * Set the Boss-worker thread count to use.
+     *
+     * Boss threads are responsible of accepting new connections.
+     *
+     * Default is to not use boss threads and let the IO threads hand over this responsibility.
+     */
+    public void setBossWorkerCount(Optional<Integer> bossWorker) {
+        if (started) {
+            throw new IllegalStateException("Can only be set when the server is not running");
+        }
+        this.bossWorker = bossWorker;
+    }
+
     @Override
     public synchronized void bind() throws Exception {
         if (started) {
@@ -102,10 +123,12 @@ public abstract class AbstractAsyncServer implements ProtocolServer {
         ServerBootstrap bootstrap = new ServerBootstrap();
         bootstrap.channel(NioServerSocketChannel.class);
 
-        bossGroup = new NioEventLoopGroup(2, NamedThreadFactory.withName(jmxName + "-boss"));
+        bossGroup = bossWorker.map(count -> new NioEventLoopGroup(2, NamedThreadFactory.withName(jmxName + "-boss")));
         workerGroup = new NioEventLoopGroup(ioWorker, NamedThreadFactory.withName(jmxName + "-io"));
 
-        bootstrap.group(bossGroup, workerGroup);
+        bossGroup.<Runnable>map(boss -> () -> bootstrap.group(boss, workerGroup))
+            .orElse(() -> bootstrap.group(workerGroup))
+            .run();
 
         ChannelInitializer<SocketChannel> factory = createPipelineFactory();
 
@@ -139,17 +162,14 @@ public abstract class AbstractAsyncServer implements ProtocolServer {
         }
 
         List<Future<?>> futures = new ArrayList<>();
-        if (bossGroup != null) {
-            futures.add(bossGroup.shutdownGracefully());
-        }
+
+        bossGroup.ifPresent(boss -> futures.add(boss.shutdownGracefully()));
 
         if (workerGroup != null) {
             futures.add(workerGroup.shutdownGracefully());
         }
 
-        if (channels != null) {
-            futures.add(channels.close());
-        }
+        futures.add(channels.close());
 
         if (gracefulShutdown) {
             futures.forEach(Throwing.<Future<?>>consumer(Future::await).sneakyThrow());
diff --git a/server/protocols/protocols-library/src/main/java/org/apache/james/protocols/lib/netty/AbstractConfigurableAsyncServer.java b/server/protocols/protocols-library/src/main/java/org/apache/james/protocols/lib/netty/AbstractConfigurableAsyncServer.java
index 3935072f87..18c30622dc 100644
--- a/server/protocols/protocols-library/src/main/java/org/apache/james/protocols/lib/netty/AbstractConfigurableAsyncServer.java
+++ b/server/protocols/protocols-library/src/main/java/org/apache/james/protocols/lib/netty/AbstractConfigurableAsyncServer.java
@@ -166,6 +166,8 @@ public abstract class AbstractConfigurableAsyncServer extends AbstractAsyncServe
         jmxName = config.getString("jmxName", getDefaultJMXName());
         int ioWorker = config.getInt("ioWorkerCount", DEFAULT_IO_WORKER_COUNT);
         setIoWorkerCount(ioWorker);
+        Integer bossWorker = config.getInteger("bossWorkerCount", null);
+        setBossWorkerCount(Optional.ofNullable(bossWorker));
 
         executorGroup = new DefaultEventExecutorGroup(config.getInt("maxExecutorCount", DEFAULT_MAX_EXECUTOR_COUNT),
             NamedThreadFactory.withName(jmxName));
@@ -445,7 +447,7 @@ public abstract class AbstractConfigurableAsyncServer extends AbstractAsyncServe
     
     @Override
     protected AbstractChannelPipelineFactory createPipelineFactory() {
-        return new AbstractSSLAwareChannelPipelineFactory(getTimeout(), connectionLimit, connPerIP,
+        return new AbstractSSLAwareChannelPipelineFactory<>(getTimeout(), connectionLimit, connPerIP,
             getEncryption(), getFrameHandlerFactory(), getExecutorGroup()) {
 
             @Override


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org