HandlerCollection - AtomicReference
Simple Arch
https://github.com/eclipse/jetty.project
"Jetty is a lightweight highly scalable java based web server and servlet engine. Our goal is to support web protocols like HTTP, HTTP/2 and WebSocket in a high volume low latency way that provides maximum performance while retaining the ease of use and compatibility with years of servlet development. Jetty is a modern fully async web server that has a long history as a component oriented technology easily embedded into applications while still offering a solid traditional distribution for webapp deployment."
Server - Thread Pool - Queue
Server
/**
* Jetty HTTP Servlet Server.
* This class is the main class for the Jetty HTTP Servlet server.
* It aggregates Connectors (HTTP request receivers) and request Handlers.
* The server is itself a handler and a ThreadPool. Connectors use the ThreadPool methods
* to run jobs that will eventually call the handle method.
*/
QueuedThreadPool
Compare with ThreadPoolExcutor
- corePoolSize → minThreads
- maximumPoolSize → maxThreads
- workQueue → queue
- keepAliveTime → idleTimeout
- threadFactory → threadFactory(by default, it's itself)
Diff:
- QueuedThreadPool has NO RejectedExecutionHandler
- QueuedThreadPool._reservedThreads
TryExecutor/ReservedThreadExecutor -
Calls to {@link #execute(Runnable)} on a {@link ReservedThreadExecutor} will either succeed
with a Thread immediately being assigned the Runnable task, or fail if no Thread is
available.
- QueuedThreadPool._threadGroup
- because by default, the threadFactory is itself
BlockingArrayQueue
/**
* A BlockingQueue backed by a circular array capable or growing.
* This queue is uses a variant of the two lock queue algorithm to provide an efficient queue or list backed by a growable circular array.
* Unlike {@link java.util.concurrent.ArrayBlockingQueue}, this class is able to grow and provides a blocking put call.
* The queue has both a capacity (the size of the array currently allocated) and a max capacity (the maximum size that may be allocated), which defaults to
* {@link Integer#MAX_VALUE}.
*/
why to use growable circular array?why not linked list(e.g. LinkedBlockingQueue)?
→ why array but linked list?
-
Extra overhead for each 'Node'
→ why growable circular array?
- concurrent offer&take
- control the length
why int[] indexes?
-
false sharing: https://en.wikipedia.org/wiki/False_sharing
-
MemoryUtils.getIntegersPerCacheLine()
HandlerCollection - AtomicReference
public class HandlerCollection extends AbstractHandlerContainer
{
protected final AtomicReference<Handlers> _handlers = new AtomicReference<>();
protected boolean updateHandlers(Handlers old, Handlers handlers){
return _handlers.compareAndSet(old, handlers);
}
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response){
Handlers handlers = _handlers.get();
for (Handler handler : handlers._handlers){
handler.handle(target, baseRequest, request, response);
}
}
protected static class Handlers{
private final Handler[] _handlers;
protected Handlers(Handler[] handlers){ this._handlers = handlers;}
public Handler[] getHandlers(){ return _handlers;}
}
}
→ why define the internal static class 'Handlers" ?
- Extendibility
- reachable to '_handlers'
- Tips: In java, array is also an object
Connecter - Reactor - NIO
Connecter is designed to have below functions:
- listen to the request
- establish connection
- read/write data
Jetty has a complex implementation for Connector, when try to understand it, we could start from 'Reactor Pattern' and 'java NIO'.
Reactor Pattern
"The reactor design pattern is an event handling pattern for handling service requests delivered concurrently to a service handler by one or more inputs. The service handler then demultiplexes the incoming requests and dispatches them synchronously to the associated request handlers."
(Ref to: https://en.wikipedia.org/wiki/Reactor_pattern)
One-Reactor&Single Threaded Implementation vs Multi-Reactor&Multi Threaded Implementation
(Quoted from: http://gee.cs.oswego.edu/dl/cpjslides/nio.pdf )
- single thread to listen to the request
- single thread to establish connection and read/write datas
- multi worker threads to handle request
Java NIO
- Channel is like a Socket
- register Channel to Selector
- Selector.select() will gather all avail channels, this call could be Non-blocking
Jetty Connector