19.2. Connector Configuration

19.2.1. Define Thread Pools for HTTP Connector in JBoss EAP 6

Summary

Thread Pools in JBoss EAP 6 can be shared between different components using the Executor model. These pools can be shared not only by different (HTTP) connectors, but also by other components within JBoss EAP 6 that support the Executor model. Getting the HTTP connector thread pool to match your current web performance requirements is a tricky art and requires close monitoring of the current thread pool and the current and anticipated web load demands. In this task, you will learn how to set the a thread pool for an HTTP Connector using the Executor model. You will learn how to set this using both the Command Line Interface and by modifying the XML configuration file.

Procedure 19.1. Setup a thread pool for an HTTP Connector

  1. Define a thread factory

    Open up your configuration file (standalone.xml if modifying for a standalone server or domain.xml if modifying for a domain based configuration. This file will be in the EAP_HOME/standalone/configuration or the EAP_HOME/domain/configuration folder).
    Add the following subsystem entry, changing the values to suit your server requirements.
    <subsystem xmlns="urn:jboss:domain:threads:1.1">
        <thread-factory name="http-connector-factory" thread-name-pattern="HTTP-%t" priority="9" group-name="uq-thread-pool"/>
    </subsystem>
    
    If you prefer to use the CLI to do this task, then execute the following command in a CLI command prompt:
    [standalone@localhost:9999 /] ./subsystem=threads/thread-factory=http-connector-factory:add(thread-name-pattern="HTTP-%t", priority="9", group-name="uq-thread-pool")
  2. Create an executor

    You can use one of six in-built executor classes to act as the executor for this factory. The six executors are:
    • unbounded-queue-thread-pool: This type of thread pool always accepts tasks. If fewer than the maximum number of threads are running, a new thread is started up to run the submitted task; otherwise, the task is placed into an unbounded FIFO queue to be executed when a thread is available.

      Note

      The single-thread executor type provided by Executors.singleThreadExecutor() is essentially an unbounded-queue executor with a thread limit of one. This type of executor is deployed using the unbounded-queue-thread-pool-executor element.
    • bounded-queue-thread-pool: This type of executor maintains a fixed-length queue and two pool sizes: a core size and a maximum size. When a task is accepted, if the number of running pool threads is less than the core size, a new thread is started to execute the task. If space remains in the queue, the task is placed in the queue. If the number of running pool threads is less than the maximum size, a new thread is started to execute the task. If blocking is enabled on the executor, the calling thread will block until space becomes available in the queue. The task is delegated to the handoff executor, if a handoff executor is configured. Otherwise, the task is rejected.
    • blocking-bounded-queue-thread-pool: A thread pool executor with a bounded queue where threads submittings tasks may block. Such a thread pool has a core and maximum size and a specified queue length. When a task is submitted, if the number of running threads is less than the core size, a new thread is created. Otherwise, if there is room in the queue, the task is enqueued. Otherwise, if the number of running threads is less than the maximum size, a new thread is created. Otherwise, the caller blocks until room becomes available in the queue.
    • queueless-thread-pool: Sometimes, a simple thread pool is required to run tasks in separate threads, reusing threads as they complete their tasks with no intervening queue. This type of pool is ideal for handling tasks which are long-running, perhaps utilizing blocking I/O, since tasks are always started immediately upon acceptance rather than accepting a task and then delaying its execution until other running tasks have completed. This type of executor is declared using the queueless-thread-pool-executor element.
    • blocking-queueless-thread-pool: A thread pool executor with no queue where threads submittings tasks may block. When a task is submitted, if the number of running threads is less than the maximum size, a new thread is created. Otherwise, the caller blocks until another thread completes its task and accepts the new one.
    • scheduled-thread-pool:This is a special type of executor whose purpose is to execute tasks at specific times and time intervals, based on the java.util.concurrent.ScheduledThreadPoolExecutor class. This type of executor is configured with the scheduled-thread-pool-executor element:
    In this example, we will use the unbounded-queue-thread-pool to act as the executor. Modify the values of max-threads and keepalive-time parameters to suit your server needs.
    <unbounded-queue-thread-pool name="uq-thread-pool">
      <thread-factory name="http-connector-factory" />
      <max-threads count="10" />
      <keepalive-time time="30" unit="seconds" />
    </unbounded-queue-thread-pool>
    
    Or if you prefer to use the CLI:
    [standalone@localhost:9999 /] ./subsystem=threads/unbounded-queue-thread-pool=uq-thread-pool:add(thread-factory="http-connector-factory", keepalive-time={time=30, unit="seconds"}, max-threads=30)
  3. Make the HTTP web connector use this thread pool

    In the same configuration file, locate the HTTP connector element under the web subsystem and modify it to use the thread pool defined in the previous steps.
    <connector name="http" protocol="HTTP/1.1" scheme="http" socket-binding="http" executor="uq-thread-pool" />
    Again, if you prefer to use the CLI:
    [standalone@localhost:9999 /] ./subsystem=web/connector=http:write-attribute(name=executor, value="uq-thread-pool")
  4. Restart the server

    Restart the server (standalone or domain) so that the changes can take effect. Use the following CLI commands to confirm if the changes from the steps above have taken place:
    [standalone@localhost:9999 /] ./subsystem=threads:read-resource(recursive=true)
    {                  
        "outcome" => "success",
        "result" => {
            "blocking-bounded-queue-thread-pool" => undefined,
            "blocking-queueless-thread-pool" => undefined,
            "bounded-queue-thread-pool" => undefined,
            "queueless-thread-pool" => undefined,
            "scheduled-thread-pool" => undefined,
            "thread-factory" => {"http-connector-factory" => {
                "group-name" => "uq-thread-pool",
                "name" => "http-connector-factory",
                "priority" => 9,
                "thread-name-pattern" => "HTTP-%t"
            }},
            "unbounded-queue-thread-pool" => {"uq-thread-pool" => {
                "keepalive-time" => {
                    "time" => 30L,
                    "unit" => "SECONDS"
                },
                "max-threads" => 30,
                "name" => "uq-thread-pool",
                "thread-factory" => "http-connector-factory"
            }}
        }
    }
    [standalone@localhost:9999 /] ./subsystem=web/connector=http:read-resource(recursive=true)
    {
        "outcome" => "success",
        "result" => {
            "configuration" => undefined,
            "enable-lookups" => false,
            "enabled" => true,
            "executor" => "uq-thread-pool",
            "max-connections" => undefined,
            "max-post-size" => 2097152,
            "max-save-post-size" => 4096,
            "name" => "http",
            "protocol" => "HTTP/1.1",
            "proxy-name" => undefined,
            "proxy-port" => undefined,
            "redirect-port" => 443,
            "scheme" => "http",
            "secure" => false,
            "socket-binding" => "http",
            "ssl" => undefined,
            "virtual-server" => undefined
        }
    }
    
Result

You have successfully created a thread factory and an executor and modified your HTTP Connector to use this thread pool.