Connector
全类名:org.apache.catalina.connector.Connector;
构造方法
创建Http11NioProtocol,给成员变量protocolHandler赋值。
也可以根据server.xml的配置,修改指定的protocol
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
/**
* Defaults to using HTTP/1.1 NIO implementation.
*/
public Connector() {
this("HTTP/1.1");
}
public Connector(String protocol) {
boolean apr = AprStatus.getUseAprConnector() && AprStatus.isInstanceCreated()
&& AprLifecycleListener.isAprAvailable();
ProtocolHandler p = null;
try {
// 没有开启apr,默认创建的是Http11NioProtocol
p = ProtocolHandler.create(protocol, apr);
} catch (Exception e) {
log.error(sm.getString(
"coyoteConnector.protocolHandlerInstantiationFailed"), e);
}
if (p != null) {
protocolHandler = p;
protocolHandlerClassName = protocolHandler.getClass().getName();
} else {
protocolHandler = null;
protocolHandlerClassName = protocol;
}
// Default for Connector depends on this system property
setThrowOnFailure(Boolean.getBoolean("org.apache.catalina.startup.EXIT_ON_INIT_FAILURE"));
}
init方法
Connector也是一个生命周期类,看看init做了什么?
主要是给protocolHandler设置adapter CoyoteAdapter,这个类用于将接收到的请求进行处理,后面讲请求处理过程时再详细看下这块代码。
还有就是初始化protocolHandler 也即调用Http11NioProtocol的init方法。
@Override
protected void initInternal() throws LifecycleException {
super.initInternal();
// 非核心主流程 省略
// Initialize adapter
adapter = new CoyoteAdapter(this);
protocolHandler.setAdapter(adapter);
// 非核心主流程 省略
try {
protocolHandler.init();
} catch (Exception e) {
throw new LifecycleException(
sm.getString("coyoteConnector.protocolHandlerInitializationFailed"), e);
}
}
Http11NioProtocol的构造方法给 创建了一个NioEndpoint并赋值给成员变量endpoint
public Http11NioProtocol() {
super(new NioEndpoint());
}
// 父类的构造方法
public AbstractProtocol(AbstractEndpoint<S,?> endpoint) {
this.endpoint = endpoint;
setConnectionLinger(Constants.DEFAULT_CONNECTION_LINGER);
setTcpNoDelay(Constants.DEFAULT_TCP_NO_DELAY);
}
protocolHandler.init(),最终会调到父类AbstractProtocol.init方法,方法里面会调endpoint.init();
下面是endpoint.init()方法
public final void init() throws Exception {
if (bindOnInit) {
bindWithCleanup();
bindState = BindState.BOUND_ON_INIT;
}
}
// bindWithCleanup 方法最终会调NioEndpoint的bind方法
@Override
public void bind() throws Exception {
initServerSocket();
setStopLatch(new CountDownLatch(1));
// Initialize SSL if needed
initialiseSsl();
}
NioEndpoint的bind方法会调initServerSocket(),该方法主要会执行:
// 获取一个ServerSocket
serverSock = ServerSocketChannel.open();
socketProperties.setProperties(serverSock.socket());
InetSocketAddress addr = new InetSocketAddress(getAddress(), getPortWithOffset());
// 绑定地址,并设置最大可接收连接数,默认100,可在server.xml上修改
serverSock.bind(addr, getAcceptCount());
// 设置阻塞模式
serverSock.configureBlocking(true); //mimic APR behavior
到此,Connector的init方法结束。
start方法
也是调protocolHandler的start方法,即Http11NioProtocol的start方法
@Override
protected void startInternal() throws LifecycleException {
// 非核心主流程 省略
try {
protocolHandler.start();
} catch (Exception e) {
throw new LifecycleException(
sm.getString("coyoteConnector.protocolHandlerStartFailed"), e);
}
}
会调父类AbstractProtocol的start方法,里面会调endpoint.start();然后会调NioEndpoint的startInternal方法
/**
* Start the NIO endpoint, creating acceptor, poller threads.
*/
@Override
public void startInternal() throws Exception {
if (!running) {
running = true;
paused = false;
// 非核心主流程 省略
// Create worker collection 当接收到请求时会由该线程池处理
if (getExecutor() == null) {
createExecutor();
}
// 初始化最大可连接数
initializeConnectionLatch();
// Start poller thread 启动一个请求事件轮询线程
poller = new Poller();
Thread pollerThread = new Thread(poller, getName() + "-Poller");
pollerThread.setPriority(threadPriority);
pollerThread.setDaemon(true);
pollerThread.start();
// 启动接受连接线程
startAcceptorThread();
}
}
核心做了4件事:
1)创建处理请求线程池 createExecutor()
接收到请求会由该线程池处理
public void createExecutor() {
internalExecutor = true;
TaskQueue taskqueue = new TaskQueue();
TaskThreadFactory tf = new TaskThreadFactory(getName() + "-exec-", daemon, getThreadPriority());
// 默认最小10个,最大200个线程
executor = new ThreadPoolExecutor(getMinSpareThreads(), getMaxThreads(), 60, TimeUnit.SECONDS,taskqueue, tf);
taskqueue.setParent( (ThreadPoolExecutor) executor);
}
2)初始化最大可连接数 initializeConnectionLatch()
protected LimitLatch initializeConnectionLatch() {
if (maxConnections==-1) {
return null;
}
if (connectionLimitLatch==null) {
connectionLimitLatch = new LimitLatch(getMaxConnections());
}
return connectionLimitLatch;
}
在接收连接之前会判断是否还可以接收连接,会调用endpoint.countUpOrAwaitConnection();
protected void countUpOrAwaitConnection() throws InterruptedException {
if (maxConnections==-1) {
return;
}
LimitLatch latch = connectionLimitLatch;
if (latch!=null) {
// 会阻塞线程,直到获得一个“连接资格”
latch.countUpOrAwait();
}
}
3)启动一个事件轮询线程Poller
直接看Poller的run方法,run方法核心处理逻辑:
// 会判断是否有新的连接socket事件,有的话将socket注册到selector,并监听读事件
hasEvents = events();
// 检查是否有读事件
keyCount = selector.select(selectorTimeout);
// 处理读请求
processKey(sk, socketWrapper);
4)启动一个监听连接的线程 startAcceptorThread()
protected void startAcceptorThread() {
acceptor = new Acceptor<>(this);
String threadName = getName() + "-Acceptor";
acceptor.setThreadName(threadName);
Thread t = new Thread(acceptor, threadName);
t.setPriority(getAcceptorThreadPriority());
t.setDaemon(getDaemon());
t.start();
}
会启动Acceptor线程,直接看Acceptor的run方法,核心逻辑:
//if we have reached max connections, wait 达到了最多的连接数,等待
endpoint.countUpOrAwaitConnection();
// 等待获取一个连接
socket = endpoint.serverSocketAccept();
// 处理连接
endpoint.setSocketOptions(socket)
// 增加注册事件,然后由
poller.register(socketWrapper)
endpoint.setSocketOptions(socket),底层会调poller.register(socketWrapper),该方法是会给poller增加一个注册事件,然后由poller run方法扫描到该事件后,将socket注册到selector,并监听读事件
sc.register(getSelector(), SelectionKey.OP_READ, socketWrapper);
到此,Connector启动结束,可以正常接收请求。