Tomcat Architecture Series-3.Mastering Tomcat Connector

Mastering Tomcat Connector: HTTP, AJP and NIO Implementation

Introduction

Tomcat Connectors are crucial components that handle all communication between clients and the servlet containers. This article deep dives into different types of connectors, their implementations, and how to optimize them for production use.

Table of Contents

  1. Connector Architecture Overview
  2. Http Connector Deep Dive
  3. AJP Connector Analysis
  4. NIO Connector Implementation
  5. Performance Optimization
  6. Advanced Configuration
  7. Troubleshooting Guide

1. Connector Architecture Overview

1.1 Basic Connector Structure

<span>public</span> <span>interface</span> <span>Connector</span> <span>{</span>
<span>// Core connector methods</span>
<span>public</span> <span>void</span> <span>setService</span><span>(</span><span>Service</span> <span>service</span><span>);</span>
<span>public</span> <span>Service</span> <span>getService</span><span>();</span>
<span>public</span> <span>void</span> <span>init</span><span>()</span> <span>throws</span> <span>LifecycleException</span><span>;</span>
<span>public</span> <span>void</span> <span>start</span><span>()</span> <span>throws</span> <span>LifecycleException</span><span>;</span>
<span>public</span> <span>void</span> <span>stop</span><span>()</span> <span>throws</span> <span>LifecycleException</span><span>;</span>
<span>// Protocol configuration</span>
<span>public</span> <span>void</span> <span>setProtocol</span><span>(</span><span>String</span> <span>protocol</span><span>);</span>
<span>public</span> <span>String</span> <span>getProtocol</span><span>();</span>
<span>// Port configuration</span>
<span>public</span> <span>void</span> <span>setPort</span><span>(</span><span>int</span> <span>port</span><span>);</span>
<span>public</span> <span>int</span> <span>getPort</span><span>();</span>
<span>}</span>
<span>public</span> <span>interface</span> <span>Connector</span> <span>{</span>
  <span>// Core connector methods</span>
  <span>public</span> <span>void</span> <span>setService</span><span>(</span><span>Service</span> <span>service</span><span>);</span>
  <span>public</span> <span>Service</span> <span>getService</span><span>();</span>
  <span>public</span> <span>void</span> <span>init</span><span>()</span> <span>throws</span> <span>LifecycleException</span><span>;</span>
  <span>public</span> <span>void</span> <span>start</span><span>()</span> <span>throws</span> <span>LifecycleException</span><span>;</span>
  <span>public</span> <span>void</span> <span>stop</span><span>()</span> <span>throws</span> <span>LifecycleException</span><span>;</span>

  <span>// Protocol configuration</span>
  <span>public</span> <span>void</span> <span>setProtocol</span><span>(</span><span>String</span> <span>protocol</span><span>);</span>
  <span>public</span> <span>String</span> <span>getProtocol</span><span>();</span>

  <span>// Port configuration</span>
  <span>public</span> <span>void</span> <span>setPort</span><span>(</span><span>int</span> <span>port</span><span>);</span>
  <span>public</span> <span>int</span> <span>getPort</span><span>();</span>
<span>}</span>
public interface Connector { // Core connector methods public void setService(Service service); public Service getService(); public void init() throws LifecycleException; public void start() throws LifecycleException; public void stop() throws LifecycleException; // Protocol configuration public void setProtocol(String protocol); public String getProtocol(); // Port configuration public void setPort(int port); public int getPort(); }

Enter fullscreen mode Exit fullscreen mode

1.2 Connector Pipline

<span>public</span> <span>class</span> <span>ConnectorPipeline</span> <span>{</span>
<span>private</span> <span>final</span> <span>List</span><span><</span><span>Valve</span><span>></span> <span>valves</span> <span>=</span> <span>new</span> <span>ArrayList</span><span><>();</span>
<span>private</span> <span>Valve</span> <span>basic</span> <span>=</span> <span>null</span><span>;</span>
<span>public</span> <span>void</span> <span>addValve</span><span>(</span><span>Valve</span> <span>valve</span><span>)</span> <span>{</span>
<span>valves</span><span>.</span><span>add</span><span>(</span><span>valve</span><span>);</span>
<span>}</span>
<span>public</span> <span>void</span> <span>invoke</span><span>(</span><span>Request</span> <span>request</span><span>,</span> <span>Response</span> <span>response</span><span>)</span> <span>{</span>
<span>// Process through valve chain</span>
<span>for</span> <span>(</span><span>Valve</span> <span>valve</span> <span>:</span> <span>valves</span><span>)</span> <span>{</span>
<span>valve</span><span>.</span><span>invoke</span><span>(</span><span>request</span><span>,</span> <span>response</span><span>);</span>
<span>}</span>
<span>// Finally invoke basic valve</span>
<span>if</span> <span>(</span><span>basic</span> <span>!=</span> <span>null</span><span>)</span> <span>{</span>
<span>basic</span><span>.</span><span>invoke</span><span>(</span><span>request</span><span>,</span> <span>response</span><span>);</span>
<span>}</span>
<span>}</span>
<span>}</span>
<span>public</span> <span>class</span> <span>ConnectorPipeline</span> <span>{</span>
  <span>private</span> <span>final</span> <span>List</span><span><</span><span>Valve</span><span>></span> <span>valves</span> <span>=</span> <span>new</span> <span>ArrayList</span><span><>();</span>
  <span>private</span> <span>Valve</span> <span>basic</span> <span>=</span> <span>null</span><span>;</span>

  <span>public</span> <span>void</span> <span>addValve</span><span>(</span><span>Valve</span> <span>valve</span><span>)</span> <span>{</span>
    <span>valves</span><span>.</span><span>add</span><span>(</span><span>valve</span><span>);</span>
  <span>}</span>

  <span>public</span> <span>void</span> <span>invoke</span><span>(</span><span>Request</span> <span>request</span><span>,</span> <span>Response</span> <span>response</span><span>)</span> <span>{</span>
    <span>// Process through valve chain</span>
    <span>for</span> <span>(</span><span>Valve</span> <span>valve</span> <span>:</span> <span>valves</span><span>)</span> <span>{</span>
      <span>valve</span><span>.</span><span>invoke</span><span>(</span><span>request</span><span>,</span> <span>response</span><span>);</span>
    <span>}</span>
    <span>// Finally invoke basic valve</span>
    <span>if</span> <span>(</span><span>basic</span> <span>!=</span> <span>null</span><span>)</span> <span>{</span>
      <span>basic</span><span>.</span><span>invoke</span><span>(</span><span>request</span><span>,</span> <span>response</span><span>);</span>
    <span>}</span>
  <span>}</span>
<span>}</span>
public class ConnectorPipeline { private final List<Valve> valves = new ArrayList<>(); private Valve basic = null; public void addValve(Valve valve) { valves.add(valve); } public void invoke(Request request, Response response) { // Process through valve chain for (Valve valve : valves) { valve.invoke(request, response); } // Finally invoke basic valve if (basic != null) { basic.invoke(request, response); } } }

Enter fullscreen mode Exit fullscreen mode

2.HTTP Connector Deep Dive

HTTP/1.1 Protocol Implementation

<span>public</span> <span>class</span> <span>Http11Protocol</span> <span>extends</span> <span>AbstractHttp11Protocol</span><span><</span><span>NioChannel</span><span>></span> <span>{</span>
<span>@Override</span>
<span>protected</span> <span>void</span> <span>initializeConnectionLatch</span><span>()</span> <span>{</span>
<span>// Initialize connection count</span>
<span>connectionLatch</span> <span>=</span> <span>new</span> <span>CountDownLatch</span><span>(</span><span>1</span><span>);</span>
<span>}</span>
<span>@Override</span>
<span>protected</span> <span>Processor</span> <span>createProcessor</span><span>()</span> <span>{</span>
<span>// Create HTTP processor</span>
<span>Http11Processor</span> <span>processor</span> <span>=</span> <span>new</span> <span>Http11Processor</span><span>(</span>
<span>getMaxHttpHeaderSize</span><span>(),</span>
<span>getEndpoint</span><span>(),</span>
<span>getMaxTrailerSize</span><span>(),</span>
<span>allowedTrailerHeaders</span><span>,</span>
<span>getMaxExtensionSize</span><span>(),</span>
<span>getMaxSwallowSize</span><span>(),</span>
<span>getHttp11Protocol</span><span>().</span><span>getRelaxedPathChars</span><span>(),</span>
<span>getHttp11Protocol</span><span>().</span><span>getRelaxedQueryChars</span><span>());</span>
<span>processor</span><span>.</span><span>setAdapter</span><span>(</span><span>getAdapter</span><span>());</span>
<span>return</span> <span>processor</span><span>;</span>
<span>}</span>
<span>}</span>
<span>public</span> <span>class</span> <span>Http11Protocol</span> <span>extends</span> <span>AbstractHttp11Protocol</span><span><</span><span>NioChannel</span><span>></span> <span>{</span>

  <span>@Override</span>
  <span>protected</span> <span>void</span> <span>initializeConnectionLatch</span><span>()</span> <span>{</span>
    <span>// Initialize connection count</span>
    <span>connectionLatch</span> <span>=</span> <span>new</span> <span>CountDownLatch</span><span>(</span><span>1</span><span>);</span>
  <span>}</span>

  <span>@Override</span>
  <span>protected</span> <span>Processor</span> <span>createProcessor</span><span>()</span> <span>{</span>
    <span>// Create HTTP processor</span>
    <span>Http11Processor</span> <span>processor</span> <span>=</span> <span>new</span> <span>Http11Processor</span><span>(</span>
      <span>getMaxHttpHeaderSize</span><span>(),</span>
      <span>getEndpoint</span><span>(),</span>
      <span>getMaxTrailerSize</span><span>(),</span>
      <span>allowedTrailerHeaders</span><span>,</span>
      <span>getMaxExtensionSize</span><span>(),</span>
      <span>getMaxSwallowSize</span><span>(),</span>
      <span>getHttp11Protocol</span><span>().</span><span>getRelaxedPathChars</span><span>(),</span>
      <span>getHttp11Protocol</span><span>().</span><span>getRelaxedQueryChars</span><span>());</span>
    <span>processor</span><span>.</span><span>setAdapter</span><span>(</span><span>getAdapter</span><span>());</span>
    <span>return</span> <span>processor</span><span>;</span>
  <span>}</span>
<span>}</span>
public class Http11Protocol extends AbstractHttp11Protocol<NioChannel> { @Override protected void initializeConnectionLatch() { // Initialize connection count connectionLatch = new CountDownLatch(1); } @Override protected Processor createProcessor() { // Create HTTP processor Http11Processor processor = new Http11Processor( getMaxHttpHeaderSize(), getEndpoint(), getMaxTrailerSize(), allowedTrailerHeaders, getMaxExtensionSize(), getMaxSwallowSize(), getHttp11Protocol().getRelaxedPathChars(), getHttp11Protocol().getRelaxedQueryChars()); processor.setAdapter(getAdapter()); return processor; } }

Enter fullscreen mode Exit fullscreen mode

2.2 HTTP Request Processing

<span>public</span> <span>class</span> <span>Http11Processor</span> <span>implements</span> <span>ActionHook</span><span>,</span> <span>Processor</span> <span>{</span>
<span>@Override</span>
<span>public</span> <span>SocketState</span> <span>process</span><span>(</span><span>SocketWrapperBase</span><span><?></span> <span>socketWrapper</span><span>)</span>
<span>throws</span> <span>IOException</span> <span>{</span>
<span>// Initialize request and response</span>
<span>Request</span> <span>req</span> <span>=</span> <span>new</span> <span>Request</span><span>();</span>
<span>Response</span> <span>res</span> <span>=</span> <span>new</span> <span>Response</span><span>();</span>
<span>// Parse HTTP request</span>
<span>parseRequest</span><span>(</span><span>socketWrapper</span><span>,</span> <span>req</span><span>);</span>
<span>// Process request</span>
<span>getAdapter</span><span>().</span><span>service</span><span>(</span><span>req</span><span>,</span> <span>res</span><span>);</span>
<span>// Send response</span>
<span>sendResponse</span><span>(</span><span>res</span><span>);</span>
<span>return</span> <span>SocketState</span><span>.</span><span>CLOSED</span><span>;</span>
<span>}</span>
<span>}</span>
<span>public</span> <span>class</span> <span>Http11Processor</span> <span>implements</span> <span>ActionHook</span><span>,</span> <span>Processor</span> <span>{</span>

  <span>@Override</span>
  <span>public</span> <span>SocketState</span> <span>process</span><span>(</span><span>SocketWrapperBase</span><span><?></span> <span>socketWrapper</span><span>)</span>
    <span>throws</span> <span>IOException</span> <span>{</span>
    <span>// Initialize request and response</span>
    <span>Request</span> <span>req</span> <span>=</span> <span>new</span> <span>Request</span><span>();</span>
    <span>Response</span> <span>res</span> <span>=</span> <span>new</span> <span>Response</span><span>();</span>

    <span>// Parse HTTP request</span>
    <span>parseRequest</span><span>(</span><span>socketWrapper</span><span>,</span> <span>req</span><span>);</span>

    <span>// Process request</span>
    <span>getAdapter</span><span>().</span><span>service</span><span>(</span><span>req</span><span>,</span> <span>res</span><span>);</span>

    <span>// Send response</span>
    <span>sendResponse</span><span>(</span><span>res</span><span>);</span>

    <span>return</span> <span>SocketState</span><span>.</span><span>CLOSED</span><span>;</span>
  <span>}</span>
<span>}</span>
public class Http11Processor implements ActionHook, Processor { @Override public SocketState process(SocketWrapperBase<?> socketWrapper) throws IOException { // Initialize request and response Request req = new Request(); Response res = new Response(); // Parse HTTP request parseRequest(socketWrapper, req); // Process request getAdapter().service(req, res); // Send response sendResponse(res); return SocketState.CLOSED; } }

Enter fullscreen mode Exit fullscreen mode

3. AJP Connector Analysis

3.1 AJP Protocol Implementation

<span>public</span> <span>class</span> <span>AjpProtocol</span> <span>extends</span> <span>AbstractAjpProtocol</span><span><</span><span>NioChannel</span><span>></span> <span>{</span>
<span>@Override</span>
<span>protected</span> <span>Processor</span> <span>createProcessor</span><span>()</span> <span>{</span>
<span>AjpProcessor</span> <span>processor</span> <span>=</span> <span>new</span> <span>AjpProcessor</span><span>(</span><span>getPacketSize</span><span>(),</span> <span>getEndpoint</span><span>());</span>
<span>processor</span><span>.</span><span>setAdapter</span><span>(</span><span>getAdapter</span><span>());</span>
<span>return</span> <span>processor</span><span>;</span>
<span>}</span>
<span>@Override</span>
<span>protected</span> <span>void</span> <span>initializeConnectionLatch</span><span>()</span> <span>{</span>
<span>connectionLatch</span> <span>=</span> <span>new</span> <span>CountDownLatch</span><span>(</span><span>1</span><span>);</span>
<span>}</span>
<span>}</span>
<span>public</span> <span>class</span> <span>AjpProtocol</span> <span>extends</span> <span>AbstractAjpProtocol</span><span><</span><span>NioChannel</span><span>></span> <span>{</span>

  <span>@Override</span>
  <span>protected</span> <span>Processor</span> <span>createProcessor</span><span>()</span> <span>{</span>
    <span>AjpProcessor</span> <span>processor</span> <span>=</span> <span>new</span> <span>AjpProcessor</span><span>(</span><span>getPacketSize</span><span>(),</span> <span>getEndpoint</span><span>());</span>
    <span>processor</span><span>.</span><span>setAdapter</span><span>(</span><span>getAdapter</span><span>());</span>
    <span>return</span> <span>processor</span><span>;</span>
  <span>}</span>

  <span>@Override</span>
  <span>protected</span> <span>void</span> <span>initializeConnectionLatch</span><span>()</span> <span>{</span>
    <span>connectionLatch</span> <span>=</span> <span>new</span> <span>CountDownLatch</span><span>(</span><span>1</span><span>);</span>
  <span>}</span>
<span>}</span>
public class AjpProtocol extends AbstractAjpProtocol<NioChannel> { @Override protected Processor createProcessor() { AjpProcessor processor = new AjpProcessor(getPacketSize(), getEndpoint()); processor.setAdapter(getAdapter()); return processor; } @Override protected void initializeConnectionLatch() { connectionLatch = new CountDownLatch(1); } }

Enter fullscreen mode Exit fullscreen mode

3.2 AJP Message Structure

<span>public</span> <span>class</span> <span>AjpMessage</span> <span>{</span>
<span>private</span> <span>final</span> <span>byte</span><span>[]</span> <span>buf</span><span>;</span>
<span>private</span> <span>int</span> <span>pos</span><span>;</span>
<span>public</span> <span>void</span> <span>reset</span><span>()</span> <span>{</span>
<span>pos</span> <span>=</span> <span>0</span><span>;</span>
<span>}</span>
<span>public</span> <span>void</span> <span>appendByte</span><span>(</span><span>int</span> <span>val</span><span>)</span> <span>{</span>
<span>buf</span><span>[</span><span>pos</span><span>++]</span> <span>=</span> <span>(</span><span>byte</span><span>)</span> <span>val</span><span>;</span>
<span>}</span>
<span>public</span> <span>void</span> <span>appendInt</span><span>(</span><span>int</span> <span>val</span><span>)</span> <span>{</span>
<span>buf</span><span>[</span><span>pos</span><span>++]</span> <span>=</span> <span>(</span><span>byte</span><span>)</span> <span>((</span><span>val</span> <span>>>></span> <span>8</span><span>)</span> <span>&</span> <span>0xFF</span><span>);</span>
<span>buf</span><span>[</span><span>pos</span><span>++]</span> <span>=</span> <span>(</span><span>byte</span><span>)</span> <span>(</span><span>val</span> <span>&</span> <span>0xFF</span><span>);</span>
<span>}</span>
<span>}</span>
<span>public</span> <span>class</span> <span>AjpMessage</span> <span>{</span>
    <span>private</span> <span>final</span> <span>byte</span><span>[]</span> <span>buf</span><span>;</span>
    <span>private</span> <span>int</span> <span>pos</span><span>;</span>

    <span>public</span> <span>void</span> <span>reset</span><span>()</span> <span>{</span>
        <span>pos</span> <span>=</span> <span>0</span><span>;</span>
    <span>}</span>

    <span>public</span> <span>void</span> <span>appendByte</span><span>(</span><span>int</span> <span>val</span><span>)</span> <span>{</span>
        <span>buf</span><span>[</span><span>pos</span><span>++]</span> <span>=</span> <span>(</span><span>byte</span><span>)</span> <span>val</span><span>;</span>
    <span>}</span>

    <span>public</span> <span>void</span> <span>appendInt</span><span>(</span><span>int</span> <span>val</span><span>)</span> <span>{</span>
        <span>buf</span><span>[</span><span>pos</span><span>++]</span> <span>=</span> <span>(</span><span>byte</span><span>)</span> <span>((</span><span>val</span> <span>>>></span> <span>8</span><span>)</span> <span>&</span> <span>0xFF</span><span>);</span>
        <span>buf</span><span>[</span><span>pos</span><span>++]</span> <span>=</span> <span>(</span><span>byte</span><span>)</span> <span>(</span><span>val</span> <span>&</span> <span>0xFF</span><span>);</span>
    <span>}</span>
<span>}</span>
public class AjpMessage { private final byte[] buf; private int pos; public void reset() { pos = 0; } public void appendByte(int val) { buf[pos++] = (byte) val; } public void appendInt(int val) { buf[pos++] = (byte) ((val >>> 8) & 0xFF); buf[pos++] = (byte) (val & 0xFF); } }

Enter fullscreen mode Exit fullscreen mode

4. NIO Connector Implementation

4.1 NIO Endpoint

<span>public</span> <span>class</span> <span>NioEndpoint</span> <span>extends</span> <span>AbstractJsseEndpoint</span><span><</span><span>NioChannel</span><span>,</span><span>SocketChannel</span><span>></span> <span>{</span>
<span>private</span> <span>Poller</span><span>[]</span> <span>pollers</span><span>;</span>
<span>private</span> <span>NioSelectorPool</span> <span>selectorPool</span><span>;</span>
<span>@Override</span>
<span>protected</span> <span>void</span> <span>startInternal</span><span>()</span> <span>throws</span> <span>Exception</span> <span>{</span>
<span>// Initialize NIO components</span>
<span>if</span> <span>(!</span><span>running</span><span>)</span> <span>{</span>
<span>running</span> <span>=</span> <span>true</span><span>;</span>
<span>paused</span> <span>=</span> <span>false</span><span>;</span>
<span>// Create worker collection</span>
<span>processorCache</span> <span>=</span> <span>new</span> <span>SynchronizedStack</span><span><>(</span>
<span>SynchronizedStack</span><span>.</span><span>DEFAULT_SIZE</span><span>,</span>
<span>socketProperties</span><span>.</span><span>getProcessorCache</span><span>());</span>
<span>// Start poller threads</span>
<span>pollers</span> <span>=</span> <span>new</span> <span>Poller</span><span>[</span><span>getPollerThreadCount</span><span>()];</span>
<span>for</span> <span>(</span><span>int</span> <span>i</span> <span>=</span> <span>0</span><span>;</span> <span>i</span> <span><</span> <span>pollers</span><span>.</span><span>length</span><span>;</span> <span>i</span><span>++)</span> <span>{</span>
<span>pollers</span><span>[</span><span>i</span><span>]</span> <span>=</span> <span>new</span> <span>Poller</span><span>();</span>
<span>Thread</span> <span>pollerThread</span> <span>=</span> <span>new</span> <span>Thread</span><span>(</span><span>pollers</span><span>[</span><span>i</span><span>]);</span>
<span>pollerThread</span><span>.</span><span>start</span><span>();</span>
<span>}</span>
<span>}</span>
<span>}</span>
<span>}</span>
<span>public</span> <span>class</span> <span>NioEndpoint</span> <span>extends</span> <span>AbstractJsseEndpoint</span><span><</span><span>NioChannel</span><span>,</span><span>SocketChannel</span><span>></span> <span>{</span>

    <span>private</span> <span>Poller</span><span>[]</span> <span>pollers</span><span>;</span>
    <span>private</span> <span>NioSelectorPool</span> <span>selectorPool</span><span>;</span>

    <span>@Override</span>
    <span>protected</span> <span>void</span> <span>startInternal</span><span>()</span> <span>throws</span> <span>Exception</span> <span>{</span>
        <span>// Initialize NIO components</span>
        <span>if</span> <span>(!</span><span>running</span><span>)</span> <span>{</span>
            <span>running</span> <span>=</span> <span>true</span><span>;</span>
            <span>paused</span> <span>=</span> <span>false</span><span>;</span>

            <span>// Create worker collection</span>
            <span>processorCache</span> <span>=</span> <span>new</span> <span>SynchronizedStack</span><span><>(</span>
                    <span>SynchronizedStack</span><span>.</span><span>DEFAULT_SIZE</span><span>,</span>
                    <span>socketProperties</span><span>.</span><span>getProcessorCache</span><span>());</span>

            <span>// Start poller threads</span>
            <span>pollers</span> <span>=</span> <span>new</span> <span>Poller</span><span>[</span><span>getPollerThreadCount</span><span>()];</span>
            <span>for</span> <span>(</span><span>int</span> <span>i</span> <span>=</span> <span>0</span><span>;</span> <span>i</span> <span><</span> <span>pollers</span><span>.</span><span>length</span><span>;</span> <span>i</span><span>++)</span> <span>{</span>
                <span>pollers</span><span>[</span><span>i</span><span>]</span> <span>=</span> <span>new</span> <span>Poller</span><span>();</span>
                <span>Thread</span> <span>pollerThread</span> <span>=</span> <span>new</span> <span>Thread</span><span>(</span><span>pollers</span><span>[</span><span>i</span><span>]);</span>
                <span>pollerThread</span><span>.</span><span>start</span><span>();</span>
            <span>}</span>
        <span>}</span>
    <span>}</span>
<span>}</span>
public class NioEndpoint extends AbstractJsseEndpoint<NioChannel,SocketChannel> { private Poller[] pollers; private NioSelectorPool selectorPool; @Override protected void startInternal() throws Exception { // Initialize NIO components if (!running) { running = true; paused = false; // Create worker collection processorCache = new SynchronizedStack<>( SynchronizedStack.DEFAULT_SIZE, socketProperties.getProcessorCache()); // Start poller threads pollers = new Poller[getPollerThreadCount()]; for (int i = 0; i < pollers.length; i++) { pollers[i] = new Poller(); Thread pollerThread = new Thread(pollers[i]); pollerThread.start(); } } } }

Enter fullscreen mode Exit fullscreen mode

4.2 NIO Channel Implementation

<span>public</span> <span>class</span> <span>NioChannel</span> <span>implements</span> <span>ByteChannel</span> <span>{</span>
<span>private</span> <span>final</span> <span>SocketChannel</span> <span>sc</span><span>;</span>
<span>private</span> <span>final</span> <span>NioEndpoint</span> <span>endpoint</span><span>;</span>
<span>@Override</span>
<span>public</span> <span>int</span> <span>read</span><span>(</span><span>ByteBuffer</span> <span>dst</span><span>)</span> <span>throws</span> <span>IOException</span> <span>{</span>
<span>return</span> <span>sc</span><span>.</span><span>read</span><span>(</span><span>dst</span><span>);</span>
<span>}</span>
<span>@Override</span>
<span>public</span> <span>int</span> <span>write</span><span>(</span><span>ByteBuffer</span> <span>src</span><span>)</span> <span>throws</span> <span>IOException</span> <span>{</span>
<span>return</span> <span>sc</span><span>.</span><span>write</span><span>(</span><span>src</span><span>);</span>
<span>}</span>
<span>}</span>
<span>public</span> <span>class</span> <span>NioChannel</span> <span>implements</span> <span>ByteChannel</span> <span>{</span>
  <span>private</span> <span>final</span> <span>SocketChannel</span> <span>sc</span><span>;</span>
  <span>private</span> <span>final</span> <span>NioEndpoint</span> <span>endpoint</span><span>;</span>

  <span>@Override</span>
  <span>public</span> <span>int</span> <span>read</span><span>(</span><span>ByteBuffer</span> <span>dst</span><span>)</span> <span>throws</span> <span>IOException</span> <span>{</span>
    <span>return</span> <span>sc</span><span>.</span><span>read</span><span>(</span><span>dst</span><span>);</span>
  <span>}</span>

  <span>@Override</span>
  <span>public</span> <span>int</span> <span>write</span><span>(</span><span>ByteBuffer</span> <span>src</span><span>)</span> <span>throws</span> <span>IOException</span> <span>{</span>
    <span>return</span> <span>sc</span><span>.</span><span>write</span><span>(</span><span>src</span><span>);</span>
  <span>}</span>
<span>}</span>
public class NioChannel implements ByteChannel { private final SocketChannel sc; private final NioEndpoint endpoint; @Override public int read(ByteBuffer dst) throws IOException { return sc.read(dst); } @Override public int write(ByteBuffer src) throws IOException { return sc.write(src); } }

Enter fullscreen mode Exit fullscreen mode

5. Performance Optimization

5.1 Thread Pool Configuration

<span><Connector</span> <span>port=</span><span>"8080"</span> <span>protocol=</span><span>"HTTP/1.1"</span>
<span>maxThreads=</span><span>"200"</span>
<span>minSpareThreads=</span><span>"10"</span>
<span>maxConnections=</span><span>"10000"</span>
<span>acceptCount=</span><span>"100"</span>
<span>connectionTimeout=</span><span>"20000"</span><span>/></span>
<span><Connector</span> <span>port=</span><span>"8080"</span> <span>protocol=</span><span>"HTTP/1.1"</span>
           <span>maxThreads=</span><span>"200"</span>
           <span>minSpareThreads=</span><span>"10"</span>
           <span>maxConnections=</span><span>"10000"</span>
           <span>acceptCount=</span><span>"100"</span>
           <span>connectionTimeout=</span><span>"20000"</span><span>/></span>
<Connector port="8080" protocol="HTTP/1.1" maxThreads="200" minSpareThreads="10" maxConnections="10000" acceptCount="100" connectionTimeout="20000"/>

Enter fullscreen mode Exit fullscreen mode

5.2 Buffer Size Optimization

<span>public</span> <span>class</span> <span>ConnectorOptimizer</span> <span>{</span>
<span>public</span> <span>void</span> <span>optimizeBuffers</span><span>(</span><span>Connector</span> <span>connector</span><span>)</span> <span>{</span>
<span>// Set optimal buffer sizes</span>
<span>connector</span><span>.</span><span>setProperty</span><span>(</span><span>"socketBuffer"</span><span>,</span> <span>"65536"</span><span>);</span>
<span>connector</span><span>.</span><span>setProperty</span><span>(</span><span>"maxHttpHeaderSize"</span><span>,</span> <span>"8192"</span><span>);</span>
<span>connector</span><span>.</span><span>setProperty</span><span>(</span><span>"maxPostSize"</span><span>,</span> <span>"2097152"</span><span>);</span>
<span>}</span>
<span>}</span>
<span>public</span> <span>class</span> <span>ConnectorOptimizer</span> <span>{</span>
  <span>public</span> <span>void</span> <span>optimizeBuffers</span><span>(</span><span>Connector</span> <span>connector</span><span>)</span> <span>{</span>
    <span>// Set optimal buffer sizes</span>
    <span>connector</span><span>.</span><span>setProperty</span><span>(</span><span>"socketBuffer"</span><span>,</span> <span>"65536"</span><span>);</span>
    <span>connector</span><span>.</span><span>setProperty</span><span>(</span><span>"maxHttpHeaderSize"</span><span>,</span> <span>"8192"</span><span>);</span>
    <span>connector</span><span>.</span><span>setProperty</span><span>(</span><span>"maxPostSize"</span><span>,</span> <span>"2097152"</span><span>);</span>
  <span>}</span>
<span>}</span>
public class ConnectorOptimizer { public void optimizeBuffers(Connector connector) { // Set optimal buffer sizes connector.setProperty("socketBuffer", "65536"); connector.setProperty("maxHttpHeaderSize", "8192"); connector.setProperty("maxPostSize", "2097152"); } }

Enter fullscreen mode Exit fullscreen mode

6. Advanced Configuration

6.1 SSL Configuration

<span><Connector</span> <span>port=</span><span>"8443"</span> <span>protocol=</span><span>"org.apache.coyote.http11.Http11NioProtocol"</span>
<span>SSLEnabled=</span><span>"true"</span>
<span>maxThreads=</span><span>"150"</span> <span>scheme=</span><span>"https"</span> <span>secure=</span><span>"true"</span>
<span>keystoreFile=</span><span>"conf/localhost-rsa.jks"</span>
<span>keystorePass=</span><span>"changeit"</span>
<span>clientAuth=</span><span>"false"</span> <span>sslProtocol=</span><span>"TLS"</span><span>/></span>
<span><Connector</span> <span>port=</span><span>"8443"</span> <span>protocol=</span><span>"org.apache.coyote.http11.Http11NioProtocol"</span>
           <span>SSLEnabled=</span><span>"true"</span>
           <span>maxThreads=</span><span>"150"</span> <span>scheme=</span><span>"https"</span> <span>secure=</span><span>"true"</span>
           <span>keystoreFile=</span><span>"conf/localhost-rsa.jks"</span>
           <span>keystorePass=</span><span>"changeit"</span>
           <span>clientAuth=</span><span>"false"</span> <span>sslProtocol=</span><span>"TLS"</span><span>/></span>
<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol" SSLEnabled="true" maxThreads="150" scheme="https" secure="true" keystoreFile="conf/localhost-rsa.jks" keystorePass="changeit" clientAuth="false" sslProtocol="TLS"/>

Enter fullscreen mode Exit fullscreen mode

6.2 Compression Setting

<span><Connector</span> <span>port=</span><span>"8080"</span> <span>protocol=</span><span>"HTTP/1.1"</span>
<span>compression=</span><span>"on"</span>
<span>compressionMinSize=</span><span>"2048"</span>
<span>noCompressionUserAgents=</span><span>"gozilla, traviata"</span>
<span>compressableMimeType=</span><span>"text/html,text/xml,text/plain,text/css, text/javascript,application/javascript"</span><span>/></span>
<span><Connector</span> <span>port=</span><span>"8080"</span> <span>protocol=</span><span>"HTTP/1.1"</span>
           <span>compression=</span><span>"on"</span>
           <span>compressionMinSize=</span><span>"2048"</span>
           <span>noCompressionUserAgents=</span><span>"gozilla, traviata"</span>
           <span>compressableMimeType=</span><span>"text/html,text/xml,text/plain,text/css, text/javascript,application/javascript"</span><span>/></span>
<Connector port="8080" protocol="HTTP/1.1" compression="on" compressionMinSize="2048" noCompressionUserAgents="gozilla, traviata" compressableMimeType="text/html,text/xml,text/plain,text/css, text/javascript,application/javascript"/>

Enter fullscreen mode Exit fullscreen mode

7.Troubleshooting Guide

7.1 Common Issues and Solutions

<span>public</span> <span>class</span> <span>ConnectorTroubleshooter</span> <span>{</span>
<span>public</span> <span>void</span> <span>diagnoseConnector</span><span>(</span><span>Connector</span> <span>connector</span><span>)</span> <span>{</span>
<span>// Check connection state</span>
<span>if</span> <span>(!</span><span>connector</span><span>.</span><span>getState</span><span>().</span><span>isAvailable</span><span>())</span> <span>{</span>
<span>// Check port availability</span>
<span>if</span> <span>(!</span><span>isPortAvailable</span><span>(</span><span>connector</span><span>.</span><span>getPort</span><span>()))</span> <span>{</span>
<span>throw</span> <span>new</span> <span>ConnectorException</span><span>(</span><span>"Port "</span> <span>+</span> <span>connector</span><span>.</span><span>getPort</span><span>()</span> <span>+</span> <span>" is in use"</span><span>);</span>
<span>}</span>
<span>// Check thread pool</span>
<span>if</span> <span>(</span><span>connector</span><span>.</span><span>getProperty</span><span>(</span><span>"maxThreads"</span><span>)</span> <span>==</span> <span>null</span><span>)</span> <span>{</span>
<span>logger</span><span>.</span><span>warn</span><span>(</span><span>"Thread pool not configured properly"</span><span>);</span>
<span>}</span>
<span>}</span>
<span>}</span>
<span>}</span>
<span>public</span> <span>class</span> <span>ConnectorTroubleshooter</span> <span>{</span>
    <span>public</span> <span>void</span> <span>diagnoseConnector</span><span>(</span><span>Connector</span> <span>connector</span><span>)</span> <span>{</span>
        <span>// Check connection state</span>
        <span>if</span> <span>(!</span><span>connector</span><span>.</span><span>getState</span><span>().</span><span>isAvailable</span><span>())</span> <span>{</span>
            <span>// Check port availability</span>
            <span>if</span> <span>(!</span><span>isPortAvailable</span><span>(</span><span>connector</span><span>.</span><span>getPort</span><span>()))</span> <span>{</span>
                <span>throw</span> <span>new</span> <span>ConnectorException</span><span>(</span><span>"Port "</span> <span>+</span> <span>connector</span><span>.</span><span>getPort</span><span>()</span> <span>+</span> <span>" is in use"</span><span>);</span>
            <span>}</span>

            <span>// Check thread pool</span>
            <span>if</span> <span>(</span><span>connector</span><span>.</span><span>getProperty</span><span>(</span><span>"maxThreads"</span><span>)</span> <span>==</span> <span>null</span><span>)</span> <span>{</span>
                <span>logger</span><span>.</span><span>warn</span><span>(</span><span>"Thread pool not configured properly"</span><span>);</span>
            <span>}</span>
        <span>}</span>
    <span>}</span>
<span>}</span>
public class ConnectorTroubleshooter { public void diagnoseConnector(Connector connector) { // Check connection state if (!connector.getState().isAvailable()) { // Check port availability if (!isPortAvailable(connector.getPort())) { throw new ConnectorException("Port " + connector.getPort() + " is in use"); } // Check thread pool if (connector.getProperty("maxThreads") == null) { logger.warn("Thread pool not configured properly"); } } } }

Enter fullscreen mode Exit fullscreen mode

7.2 Performance Monitor

<span>public</span> <span>class</span> <span>ConnectorMonitor</span> <span>{</span>
<span>private</span> <span>final</span> <span>JmxConnectorStats</span> <span>stats</span><span>;</span>
<span>public</span> <span>void</span> <span>monitorConnector</span><span>()</span> <span>{</span>
<span>// Monitor active connections</span>
<span>int</span> <span>activeConnections</span> <span>=</span> <span>stats</span><span>.</span><span>getActiveConnections</span><span>();</span>
<span>// Monitor request processing time</span>
<span>long</span> <span>processingTime</span> <span>=</span> <span>stats</span><span>.</span><span>getProcessingTime</span><span>();</span>
<span>// Monitor thread pool usage</span>
<span>int</span> <span>activeThreads</span> <span>=</span> <span>stats</span><span>.</span><span>getCurrentThreadCount</span><span>();</span>
<span>int</span> <span>maxThreads</span> <span>=</span> <span>stats</span><span>.</span><span>getMaxThreads</span><span>();</span>
<span>// Log or alert if thresholds exceeded</span>
<span>if</span> <span>(</span><span>activeConnections</span> <span>></span> <span>threshold</span><span>)</span> <span>{</span>
<span>logger</span><span>.</span><span>warn</span><span>(</span><span>"Too many active connections: "</span> <span>+</span> <span>activeConnections</span><span>);</span>
<span>}</span>
<span>}</span>
<span>}</span>
<span>public</span> <span>class</span> <span>ConnectorMonitor</span> <span>{</span>
    <span>private</span> <span>final</span> <span>JmxConnectorStats</span> <span>stats</span><span>;</span>

    <span>public</span> <span>void</span> <span>monitorConnector</span><span>()</span> <span>{</span>
        <span>// Monitor active connections</span>
        <span>int</span> <span>activeConnections</span> <span>=</span> <span>stats</span><span>.</span><span>getActiveConnections</span><span>();</span>

        <span>// Monitor request processing time</span>
        <span>long</span> <span>processingTime</span> <span>=</span> <span>stats</span><span>.</span><span>getProcessingTime</span><span>();</span>

        <span>// Monitor thread pool usage</span>
        <span>int</span> <span>activeThreads</span> <span>=</span> <span>stats</span><span>.</span><span>getCurrentThreadCount</span><span>();</span>
        <span>int</span> <span>maxThreads</span> <span>=</span> <span>stats</span><span>.</span><span>getMaxThreads</span><span>();</span>

        <span>// Log or alert if thresholds exceeded</span>
        <span>if</span> <span>(</span><span>activeConnections</span> <span>></span> <span>threshold</span><span>)</span> <span>{</span>
            <span>logger</span><span>.</span><span>warn</span><span>(</span><span>"Too many active connections: "</span> <span>+</span> <span>activeConnections</span><span>);</span>
        <span>}</span>
    <span>}</span>
<span>}</span>
public class ConnectorMonitor { private final JmxConnectorStats stats; public void monitorConnector() { // Monitor active connections int activeConnections = stats.getActiveConnections(); // Monitor request processing time long processingTime = stats.getProcessingTime(); // Monitor thread pool usage int activeThreads = stats.getCurrentThreadCount(); int maxThreads = stats.getMaxThreads(); // Log or alert if thresholds exceeded if (activeConnections > threshold) { logger.warn("Too many active connections: " + activeConnections); } } }

Enter fullscreen mode Exit fullscreen mode

Conclusion

Understanding Tomcat Connection is essential for:

  • Optimal performance tuning
  • Proper security configuration
  • Effective troubleshooting
  • Scalable application deployment

References

  • Apache Tomcat Connector Configuration Documentation
  • NIO Framework Documentation
  • Java Network Programming Guide
  • Performance Tuning Best Practices

原文链接:Tomcat Architecture Series-3.Mastering Tomcat Connector

© 版权声明
THE END
喜欢就支持一下吧
点赞10 分享
Happiness is not something you postpone for the future; it is something you design for the present.
幸福不应该留到未来品尝,幸福是你专门为当下的自己所准备的
评论 抢沙发

请登录后发表评论

    暂无评论内容