目录
阅读本篇请先看(一)Tomcat架构及运行原理之基本架构文章。
1.Connector部分源码流程
1.1 Connector
从上一篇笔记我们已经知道了在service的init方法和start方法会分别调用Connector的init和start方法,因此我们看这个类时只需要关注init和start即可。其部分关键源码如下:
public class Connector extends LifecycleMBeanBase {
public Connector() {
this("org.apache.coyote.http11.Http11NioProtocol");
}
public Connector(String protocol) {
boolean aprConnector = AprLifecycleListener.isAprAvailable() &&
AprLifecycleListener.getUseAprConnector();
// 根据传进来的协议判断,但在这里是直接确定处理类的
if ("HTTP/1.1".equals(protocol) || protocol == null) {
...
} else {
protocolHandlerClassName = protocol;
}
ProtocolHandler p = null;
try {
// 实例化协议处理类,实际上是Http11NioProtocol
Class<?> clazz = Class.forName(protocolHandlerClassName);
p = (ProtocolHandler) clazz.getConstructor().newInstance();
} catch (Exception e) {
...
} finally {
this.protocolHandler = p;
}
...
}
protected Service service = null;
protected String scheme = "http";
// 协议处理类,这个类及其抽象父类都很重要
protected final ProtocolHandler protocolHandler;
// 实际上类型是CoyoteAdapter
protected Adapter adapter = null;
@Override
protected void initInternal() throws LifecycleException {
super.initInternal();
// 跑到这里protocolHandler一定是不为空的对象,毕竟构造函数都那样玩了
if (protocolHandler == null) {
throw new LifecycleException(
sm.getString("..."));
}
// 直接实例化CoyoteAdapter类型给Adapter
adapter = new CoyoteAdapter(this);
// adapter和protocolHandler关联
protocolHandler.setAdapter(adapter);
if (service != null) {
// 前面获取的线程池在这里派上了用场
protocolHandler.setUtilityExecutor(service.getServer()
.getUtilityExecutor());
}
// 设置默认的body解析方式(这里设置的是POST)
if (null == parseBodyMethodsSet) {
setParseBodyMethods(getParseBodyMethods());
}
if (protocolHandler.isAprRequired() &&
!AprLifecycleListener.isInstanceCreated()) {
throw new LifecycleException(sm.getString("...",
getProtocolHandlerClassName()));
}
if (protocolHandler.isAprRequired() &&
!AprLifecycleListener.isAprAvailable()) {
throw new LifecycleException(sm.getString("...",
getProtocolHandlerClassName()));
}
// 中间略过
...
try {
// 经典的initInternal再调用init方法,这个流程后面再分析
protocolHandler.init();
} catch (Exception e) {
throw new LifecycleException(
sm.getString("..."), e);
}
}
@Override
protected void startInternal() throws LifecycleException {
if (getPortWithOffset() < 0) {
throw new LifecycleException(sm.getString(
"...", Integer.valueOf(getPortWithOffset())));
}
setState(LifecycleState.STARTING);
try {
// 经典的startInternal再调用start方法
protocolHandler.start();
} catch (Exception e) {
throw new LifecycleException(
sm.getString("..."), e);
}
}
}
从这里可以明显的感觉到Connector主要通信对象就是protocolHandler,完成了架构图中的第一步:Connector和protocolHandler的关系。
1.2 ProtocolHandler系列
1.2.1 ProtocolHandler
上面说了ProtocolHandler的具体类型是Http11NioProtocol。因此我们看到这个类的关键源码:
public interface ProtocolHandler {
public Adapter getAdapter();
public void setAdapter(Adapter adapter);
public Executor getExecutor();
public void setExecutor(Executor executor);
public ScheduledExecutorService getUtilityExecutor();
public void setUtilityExecutor(
ScheduledExecutorService utilityExecutor);
public void init() throws Exception;
public void start() throws Exception;
public void pause() throws Exception;
public void resume() throws Exception;
public void stop() throws Exception;
public void destroy() throws Exception;
public void addUpgradeProtocol(UpgradeProtocol upgradeProtocol);
public UpgradeProtocol[] findUpgradeProtocols();
}
1.2.2 Http11NioProtocol
具体实现类关键源码:
public class Http11NioProtocol
extends AbstractHttp11JsseProtocol<NioChannel> {
public Http11NioProtocol() {
super(new NioEndpoint());
}
@Override
protected String getNamePrefix() {
if (isSSLEnabled()) {
return "https-" + getSslImplementationShortName()+ "-nio";
} else {
return "http-nio";
}
}
}
没错,这个实现类只有这个构造函数以及getNamePrefix方法返回的内容我们真正会用到,而其它的方法都是调用父类的endpoint来进行操作,等下再详细分析。
1.2.3 AbstractHttp11Protocol
其关键源码如下:
public abstract class AbstractHttp11Protocol<S>
extends AbstractProtocol<S> {
public AbstractHttp11Protocol(AbstractEndpoint<S,?> endpoint) {
// 继续调用父类方法
super(endpoint);
setConnectionTimeout(Constants.DEFAULT_CONNECTION_TIMEOUT);
// 设置handler,这个在后续处理具体的socket时会用到,需要特别留意
ConnectionHandler<S> cHandler = new ConnectionHandler<>(this);
setHandler(cHandler);
getEndpoint().setHandler(cHandler);
}
@Override
public void init() throws Exception {
// 初始化时对upgradeProtocol进行配置
for (UpgradeProtocol upgradeProtocol : upgradeProtocols) {
configureUpgradeProtocol(upgradeProtocol);
}
super.init();
}
private void configureUpgradeProtocol(
UpgradeProtocol upgradeProtocol) {
// HTTP Upgrade,将http类型的添加缓存
String httpUpgradeName = upgradeProtocol
.getHttpUpgradeName(getEndpoint().isSSLEnabled());
boolean httpUpgradeConfigured = false;
if (httpUpgradeName != null && httpUpgradeName.length() > 0) {
httpUpgradeProtocols.put(httpUpgradeName, upgradeProtocol);
httpUpgradeConfigured = true;
getLog().info(sm.getString("...",
getName(), httpUpgradeName));
}
}
@Override
protected Processor createProcessor() {
// 将会在handler中被调用,用来返回具体的processor处理类
Http11Processor processor = new Http11Processor(this, adapter);
return processor;
}
}
1.2.4 AbstractProtocol
前面实现的功能有限,都是正对某个具体类型的实现类,但是AbstractProtocol则是全部适用的,因此也注定这个类的逻辑相较于其它的会比较复杂。其关键部分源码如下:
public abstract class AbstractProtocol<S> implements ProtocolHandler,
MBeanRegistration {
// 终于架构图中的endPoint、handler、processor和adapter都出现了
// acceptor接着往下分析
private final AbstractEndpoint<S,?> endpoint;
protected Adapter adapter;
private Handler<S> handler;
private final Set<Processor> waitingProcessors =
Collections.newSetFromMap(
new ConcurrentHashMap<Processor, Boolean>());
public AbstractProtocol(AbstractEndpoint<S,?> endpoint) {
this.endpoint = endpoint;
setConnectionLinger(Constants.DEFAULT_CONNECTION_LINGER);
setTcpNoDelay(Constants.DEFAULT_TCP_NO_DELAY);
}
@Override
public void init() throws Exception {
...
// 忽略前面无关紧要的代码,init方法就这么简洁
// 直接调用了endpoint的init方法
String endpointName = getName();
endpoint.setName(endpointName.substring(1,
endpointName.length()-1));
endpoint.setDomain(domain);
endpoint.init();
}
@Override
public void start() throws Exception {
...
// 忽略了前面无关紧要的代码,这里还是那么简洁。。
endpoint.start();
monitorFuture = getUtilityExecutor().scheduleWithFixedDelay(
new Runnable() {
@Override
public void run() {
if (!isPaused()) {
startAsyncTimeout();
}
}
}, 0, 60, TimeUnit.SECONDS);
}
}
1.3 Endpoint
前面出现过这么多次也终于轮到Endpoint出场了,这个类已经和ProtocolHandler的具体实现类绑定了,如Http11NioProtocol使用的类型就是写死的NioEndpoint类型。
1.3.1 AbstractEndpoint
分析具体实现类时先关注一下其父类做了什么。关键源码如下:
public abstract class AbstractEndpoint<S,U> {
public static interface Handler<S> {
public enum SocketState {
OPEN, CLOSED, LONG, ASYNC_END, SENDFILE, UPGRADING,
UPGRADED, SUSPENDED
}
public SocketState process(SocketWrapperBase<S> socket,
SocketEvent status);
// 其它方法忽略
}
protected enum BindState {
UNBOUND, BOUND_ON_INIT, BOUND_ON_START, SOCKET_CLOSED_ON_STOP
}
// 盼来盼去终于盼到你了,现在Connector中的几个关键角色已经全部就位
protected Acceptor<U> acceptor;
protected SynchronizedStack<SocketProcessorBase<S>> processorCache;
private Executor executor = null;
private ScheduledExecutorService utilityExecutor = null;
private Handler<S> handler = null;
public final void init() throws Exception {
if (bindOnInit) {
bindWithCleanup();
bindState = BindState.BOUND_ON_INIT;
}
// 后面的可以忽略
...
}
private void bindWithCleanup() throws Exception {
try {
bind();
} catch (Throwable t) {
unbind();
throw t;
}
}
public final void start() throws Exception {
if (bindState == BindState.UNBOUND) {
bindWithCleanup();
bindState = BindState.BOUND_ON_START;
}
startInternal();
}
public abstract void bind() throws Exception;
public abstract void unbind() throws Exception;
public abstract void startInternal() throws Exception;
public abstract void stopInternal() throws Exception;
protected abstract SocketProcessorBase<S> createSocketProcessor(
SocketWrapperBase<S> socketWrapper, SocketEvent event);
public boolean processSocket(SocketWrapperBase<S> socketWrapper,
SocketEvent event, boolean dispatch) {
// 这个方法将会被子类NioEndpoint的Poller轮询器轮询到事件时调用
try {
if (socketWrapper == null) {
return false;
}
SocketProcessorBase<S> sc = null;
if (processorCache != null) {
// 从缓存中去除
sc = processorCache.pop();
}
if (sc == null) {
// 如果sc为空则调用子类实现方法创建一个processor
sc = createSocketProcessor(socketWrapper, event);
} else {
sc.reset(socketWrapper, event);
}
// 获取线程池不为空且dispatch为true,则使用线程池去调用
Executor executor = getExecutor();
if (dispatch && executor != null) {
// 使用线程池启动线程,一般而言正常的请求都会使用线程池启动
// 这个线程池类型是Tomcat自己实现的ThreadPoolExecutor
executor.execute(sc);
} else {
// 否则直接启动线程
sc.run();
}
} catch (RejectedExecutionException ree) {
return false;
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
return false;
}
return true;
}
public void createExecutor() {
// 在NioEndpoint的startInternal方法中间将会被调用
// 用来初始化executor线程池对象,虽然都是Tomcat自己封装实现的
// 但逻辑都和Java官方差不多
internalExecutor = true;
// Tomcat实现的阻塞队列
TaskQueue taskqueue = new TaskQueue();
// Tomcat实现的线程工厂
TaskThreadFactory tf = new TaskThreadFactory(getName() + "-exec-",
daemon, getThreadPriority());
// Tomcat实现的线程池类型,从传入的参数也可以看出来Tomcat的线程数量配置
// 需要注意的是getMaxThreads()方法的返回值,默认为10,但是最大是不能
// 超过Tomcat的最大线程数量maxThreads,当超过时将会使用maxThreads的值
executor = new ThreadPoolExecutor(getMinSpareThreads(),
getMaxThreads(), 60, TimeUnit.SECONDS,taskqueue, tf);
taskqueue.setParent( (ThreadPoolExecutor) executor);
}
protected void startAcceptorThread() {
// 该方法将会在NioEndpoint的startInternal方法末尾调用
acceptor = new Acceptor<>(this);
String threadName = getName() + "-Acceptor";
acceptor.setThreadName(threadName);
// 将acceptor用线程封装,异步调用acceptor的run方法,这里面的run方法
// 很关键,是用户请求到Tomcat接受的第一步,在这里面将会成为所有请求
// 的起点站,具体的流程后面分析
Thread t = new Thread(acceptor, threadName);
t.setPriority(getAcceptorThreadPriority());
t.setDaemon(getDaemon());
t.start();
}
}
看完这些关键方法源码后只能说简洁,抽象父类只提供各个方法的调用顺序和一些必要的操作,其它的都交给子类实现,模板模式的经典运用。
1.3.2 NioEndpoint
其父类AbstractJsseEndpoint实际上就对SSL做了一些额外的处理,在启动流程这都是无关紧要的,因此忽略。NioEndpoint的关键部分源码如下,其源码可能比较长,因为很多操作都是在这个类中完成的(大部分是在内部类中):
public class NioEndpoint
extends AbstractJsseEndpoint<NioChannel,SocketChannel> {
private NioSelectorPool selectorPool = new NioSelectorPool();
private volatile ServerSocketChannel serverSock = null;
private volatile CountDownLatch stopLatch = null;
private SynchronizedStack<PollerEvent> eventCache;
private SynchronizedStack<NioChannel> nioChannels;
private Poller poller = null;
@Override
public void bind() throws Exception {
// 父类的init方法将会调用该方法
// 这个方法没什么看的,只是对serverSock和socket进行初始化绑定
initServerSocket();
setStopLatch(new CountDownLatch(1));
// 调用父类初始化SSL
initialiseSsl();
// 初始化selector
selectorPool.open(getName());
}
@Override
public void startInternal() throws Exception {
// 父类的start方法将会调用进来
// 判断如果当前的endpoint没有在运行,则进入
if (!running) {
// 设置为运行状态
running = true;
paused = false;
// 下面几个if可以忽略
if (socketProperties.getProcessorCache() != 0) {
processorCache = new SynchronizedStack<>(
SynchronizedStack.DEFAULT_SIZE,
socketProperties.getProcessorCache());
}
if (socketProperties.getEventCache() != 0) {
eventCache = new SynchronizedStack<>(
SynchronizedStack.DEFAULT_SIZE,
socketProperties.getEventCache());
}
if (socketProperties.getBufferPool() != 0) {
nioChannels = new SynchronizedStack<>(
SynchronizedStack.DEFAULT_SIZE,
socketProperties.getBufferPool());
}
// 调用父类的方法创建executor
if (getExecutor() == null) {
createExecutor();
}
initializeConnectionLatch();
// 从名字也可以看出来这个对象的大致作用:轮询器,即一直轮询
// 是否有PollerEvent事件,如果有则对时间进行处理
poller = new Poller();
Thread pollerThread = new Thread(poller, getName() +
"-ClientPoller");
pollerThread.setPriority(threadPriority);
pollerThread.setDaemon(true);
pollerThread.start();
// 调用父类的方法启动Acceptor线程,进行请求轮询
startAcceptorThread();
}
}
@Override
protected SocketChannel serverSocketAccept() throws Exception {
// 调用已经绑定过地址的serverSock去获取Socket
// 如果获取到则返回,没有获取到则轮询获取
return serverSock.accept();
}
@Override
protected boolean setSocketOptions(SocketChannel socket) {
// 这个方法将会在Acceptor轮询到有socket请求被调用
// 具体的调用位置将在分析Acceptor时说明
try {
// 这中间是对SSL协议安全性进行判断,从而确定具体使用哪个channel类型
// 无关紧要,因此略过
...
// 这个对象如果debug过Tomcat请求流程就知道,Tomcat线程池执行的
// socket对象便是这个类型,是在放进poller轮询器前封装的socket
NioSocketWrapper socketWrapper = new NioSocketWrapper(channel,
this);
channel.setSocketWrapper(socketWrapper);
socketWrapper.setReadTimeout(getConnectionTimeout());
socketWrapper.setWriteTimeout(getConnectionTimeout());
socketWrapper.setKeepAliveLeft(NioEndpoint.this
.getMaxKeepAliveRequests());
socketWrapper.setSecure(isSSLEnabled());
// 注册进轮询器,在这里面将会被转换成PollerEvent事件,并放进阻塞
// 队列中,随后将被轮询器读取并执行
poller.register(channel, socketWrapper);
return true;
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
try {
log.error(sm.getString("endpoint.socketOptionsError"), t);
} catch (Throwable tt) {
ExceptionUtils.handleThrowable(tt);
}
}
return false;
}
@Override
protected SocketProcessorBase<NioChannel> createSocketProcessor(
SocketWrapperBase<NioChannel> socketWrapper,
SocketEvent event) {
// 这个方法在AbstractEndpoint父类中被调用以获得processor实例
return new SocketProcessor(socketWrapper, event);
}
public class Poller implements Runnable {
private Selector selector;
private final SynchronizedQueue<PollerEvent> events =
new SynchronizedQueue<>();
public void register(final NioChannel socket,
final NioSocketWrapper socketWrapper) {
// 在setSocketOptions方法中将会调用进来
socketWrapper.interestOps(SelectionKey.OP_READ);
PollerEvent r = null;
if (eventCache != null) {
r = eventCache.pop();
}
// 使用PollerEvent事件封装socket
if (r == null) {
r = new PollerEvent(socket, OP_REGISTER);
} else {
r.reset(socket, OP_REGISTER);
}
// 添加进事件阻塞队列
addEvent(r);
}
private void addEvent(PollerEvent event) {
// 添加进阻塞队列
events.offer(event);
if (wakeupCounter.incrementAndGet() == 0) {
selector.wakeup();
}
}
@Override
public void run() {
// 在startInternal方法中将会启动poller线程
// 在run方法中如果poller没有被关闭,那么这个循环将会一直执行下去
while (true) {
boolean hasEvents = false;
try {
if (!close) {
// 如果没有关闭,则获取event事件
hasEvents = events();
if (wakeupCounter.getAndSet(-1) > 0) {
keyCount = selector.selectNow();
} else {
keyCount = selector.select(selectorTimeout);
}
wakeupCounter.set(0);
}
if (close) {
// 如果关闭了则最后获取一次事件,以防止还有事件没有读取
events();
timeout(0, false);
try {
// 关闭selector
selector.close();
} catch (IOException ioe) {
...
}
break;
}
} catch (Throwable x) {
...
continue;
}
// 如果当前事件数量为0,则获取
if (keyCount == 0) {
hasEvents = (hasEvents | events());
}
// 从selector中获取SelectionKey,这个selectionKey
// 就是在events中获取到的
Iterator<SelectionKey> iterator = keyCount > 0 ?
selector.selectedKeys().iterator() : null;
while (iterator != null && iterator.hasNext()) {
SelectionKey sk = iterator.next();
// 获取selectionKey对应的socketWrapper
NioSocketWrapper socketWrapper =
(NioSocketWrapper) sk.attachment();
if (socketWrapper == null) {
iterator.remove();
} else {
iterator.remove();
// 不为空,则执行processKey方法
processKey(sk, socketWrapper);
}
}
timeout(keyCount,hasEvents);
}
// 锁数量-1
getStopLatch().countDown();
}
public boolean events() {
boolean result = false;
PollerEvent pe = null;
// 这里会一直轮询events阻塞队列,当在addEvents方法中添加了事件
// 轮询方法将会获取到添加的事件,并进行处理
for (int i = 0, size = events.size(); i < size &&
(pe = events.poll()) != null; i++ ) {
result = true;
try {
// 获得轮询事件后启动线程,在PollerEvent的run方法中
// 将会使用socket和对应的socketWrapper去注册SelectionKey
// 而注册成功的SelectionKey将会在Poller方法中被读取执行
pe.run();
pe.reset();
if (running && !paused && eventCache != null) {
// 将事件添加进缓存中
eventCache.push(pe);
}
} catch ( Throwable x ) {
...
}
}
return result;
}
protected void processKey(SelectionKey sk,
NioSocketWrapper socketWrapper) {
try {
// 如果关闭,则取消对SelectionKey的处理,processSocket方法
// 处理逻辑在AbstractEndpoint中,前面已经分析过了
if (close) {
cancelledKey(sk, socketWrapper);
} else if (sk.isValid() && socketWrapper != null) {
if (sk.isReadable() || sk.isWritable()) {
if (socketWrapper.getSendfileData() != null) {
// 处理文件类型
processSendfile(sk, socketWrapper, false);
} else {
unreg(sk, socketWrapper, sk.readyOps());
boolean closeSocket = false;
// Read goes before write
if (sk.isReadable()) {
// 处理可读类型
if (socketWrapper.readOperation != null) {
if (!socketWrapper.readOperation
.process()) {
closeSocket = true;
}
} else if (!processSocket(socketWrapper,
SocketEvent.OPEN_READ, true)) {
closeSocket = true;
}
}
if (!closeSocket && sk.isWritable()) {
// 处理可写类型
if (socketWrapper.writeOperation != null){
if (!socketWrapper.writeOperation
.process()) {
closeSocket = true;
}
} else if (!processSocket(socketWrapper,
SocketEvent.OPEN_WRITE, true)) {
closeSocket = true;
}
}
if (closeSocket) {
cancelledKey(sk, socketWrapper);
}
}
}
} else {
cancelledKey(sk, socketWrapper);
}
} catch (CancelledKeyException ckx) {
cancelledKey(sk, socketWrapper);
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
}
}
}
}
至此,NioEndpoint中比较重要的部分便已经分析完了,这个类的主要作用便是注册启动请求接收器Acceptor、Poller轮询器,使其一直运行以接收用户随时请求进来的请求再处理。这里面的处理逻辑比较多也比较长,因此需要从init和start方法一步一步来看,要不然看着看着可能人就晕了。
1.4 Acceptor
其部分关键源码如下:
public class Acceptor<U> implements Runnable {
private final AbstractEndpoint<?,U> endpoint;
protected volatile AcceptorState state = AcceptorState.NEW;
@Override
public void run() {
int errorDelay = 0;
// 如果endpoint处于运行状态,则循环会一直进行
// 即如果Tomcat没有关闭,则Acceptor这个线程会一直在这里轮询
while (endpoint.isRunning()) {
// 如果endpoint处于暂停状态,则一直循环睡眠
while (endpoint.isPaused() && endpoint.isRunning()) {
state = AcceptorState.PAUSED;
try {
Thread.sleep(50);
} catch (InterruptedException e) {
...
}
}
// 已经停止,则直接退出
if (!endpoint.isRunning()) {
break;
}
// 处于运行状态
state = AcceptorState.RUNNING;
try {
// 如果已经达到最大连接,就等待直到有空闲线程出来
endpoint.countUpOrAwaitConnection();
if (endpoint.isPaused()) {
continue;
}
U socket = null;
try {
// 从endpoint获取socket连接,这里面会一直轮询,直到有新
// 的socket才会退出来,因此这里可以看成是阻塞的方法
socket = endpoint.serverSocketAccept();
} catch (Exception ioe) {
endpoint.countDownConnection();
if (endpoint.isRunning()) {
errorDelay = handleExceptionWithDelay(errorDelay);
throw ioe;
} else {
break;
}
}
errorDelay = 0;
// endpoint正常运行
if (endpoint.isRunning() && !endpoint.isPaused()) {
// 调用前面说过的setSocketOptions方法,将获取到的Socket
// 放进轮询器中执行
if (!endpoint.setSocketOptions(socket)) {
endpoint.closeSocket(socket);
}
} else {
// endpoint未正常运行,则销毁socket连接
endpoint.destroySocket(socket);
}
} catch (Throwable t) {
...
}
}
// 如果退出,则代表Acceptor已经结束
state = AcceptorState.ENDED;
}
}
可以看到,这个类的执行流程很简单,就是单纯的在这里通过EndPoint轮询获取Socket,如果获取到了Socket也就是请求,则再传给Endpoint去处理(纯正的打工仔)。
1.5 ServerSocketChannelImpl
该类的作用便是获取已经绑定的地址的请求,如果有则返回,如果没有则一直监听地址是否有新的请求(其实也就是一直阻塞轮询)。其部分关键源码如下:
class ServerSocketChannelImpl extends ServerSocketChannel
implements SelChImpl {
private static NativeDispatcher nd;
private final FileDescriptor fd;
ServerSocket socket;
public SocketChannel accept() throws IOException {
synchronized (lock) {
// 判断绑定的地址端口是否可用
if (!isOpen())
throw new ClosedChannelException();
if (!isBound())
throw new NotYetBoundException();
SocketChannel sc = null;
int n = 0;
FileDescriptor newfd = new FileDescriptor();
InetSocketAddress[] isaa = new InetSocketAddress[1];
try {
// 开始获取socket
begin();
if (!isOpen())
return null;
thread = NativeThread.current();
for (;;) {
// 一直轮询是否有新的socket请求,如果没有继续轮询
// 如果有则break退出
n = accept(this.fd, newfd, isaa);
if ((n == IOStatus.INTERRUPTED) && isOpen())
continue;
break;
}
} finally {
thread = 0;
end(n > 0);
assert IOStatus.check(n);
}
if (n < 1)
return null;
// 获得newfd,并封装返回
IOUtil.configureBlocking(newfd, true);
InetSocketAddress isa = isaa[0];
// 创建新的socket对象
sc = new SocketChannelImpl(provider(), newfd, isa);
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
try {
sm.checkAccept(isa.getAddress().getHostAddress(),
isa.getPort());
} catch (SecurityException x) {
sc.close();
throw x;
}
}
return sc;
}
}
}
1.6 SocketProcessorBase
NioEndpoint的processSocket方法中,使用了SocketProcessorBase及其子类SocketProcessor来传入Executor进行运行处理,也就意味着SocketProcessorBase是实现了Runnable线程接口的,后面对于Socket的具体处理会在这里面进行,因此这一环节也不能错过。其部分关键源码如下:
public abstract class SocketProcessorBase<S> implements Runnable {
protected SocketWrapperBase<S> socketWrapper;
protected SocketEvent event;
@Override
public final void run() {
synchronized (socketWrapper) {
if (socketWrapper.isClosed()) {
return;
}
doRun();
}
}
protected abstract void doRun();
}
可以看到这个方法很简单,只是保存了两个对象以及调用了子类实现来完成doRun方法。我们接着看到NioEndpoint中实现的SocketProcessor。其部分关键源码如下:
protected class SocketProcessor extends SocketProcessorBase<NioChannel> {
@Override
protected void doRun() {
// 获取Socket和Poller,如果装填判断失败则关闭销毁
NioChannel socket = socketWrapper.getSocket();
SelectionKey key = socket.getIOChannel()
.keyFor(socket.getSocketWrapper().getPoller()
.getSelector());
Poller poller = NioEndpoint.this.poller;
if (poller == null) {
socketWrapper.close();
return;
}
try {
// 准备开始进行握手
int handshake = -1;
try {
if (key != null) {
if (socket.isHandshakeComplete()) {
// 不需要握手,直接完成
handshake = 0;
} else if (event == SocketEvent.STOP ||
event == SocketEvent.DISCONNECT ||
event == SocketEvent.ERROR) {
// 因为某些原因握手失败了
handshake = -1;
} else {
// 进行握手,如果没抛异常,握手成功
handshake = socket.handshake(key.isReadable(),
key.isWritable());
event = SocketEvent.OPEN_READ;
}
}
} catch (IOException x) {
handshake = -1;
} catch (CancelledKeyException ckx) {
handshake = -1;
}
// 如果成功则使用handler进行相应的处理,失败则进行销毁操作
if (handshake == 0) {
SocketState state = SocketState.OPEN;
// 这个的handler实际上是在AbstractHttp11Protocol类中
// 写死的,类型为AbstractProtocol的内部类ConnectionHandler
if (event == null) {
state = getHandler()
.process(socketWrapper, SocketEvent.OPEN_READ);
} else {
state = getHandler()
.process(socketWrapper, event);
}
if (state == SocketState.CLOSED) {
poller.cancelledKey(key, socketWrapper);
}
} else if (handshake == -1 ) {
poller.cancelledKey(key, socketWrapper);
} else if (handshake == SelectionKey.OP_READ){
socketWrapper.registerReadInterest();
} else if (handshake == SelectionKey.OP_WRITE){
socketWrapper.registerWriteInterest();
}
} catch (CancelledKeyException cx) {
poller.cancelledKey(key, socketWrapper);
} catch (VirtualMachineError vme) {
ExceptionUtils.handleThrowable(vme);
} catch (Throwable t) {
poller.cancelledKey(key, socketWrapper);
} finally {
socketWrapper = null;
event = null;
if (running && !paused && processorCache != null) {
processorCache.push(this);
}
}
}
}
1.7 ConnectionHandler
由前面的SocketProcessor流程我们可以知道现在已经进入到了handler来处理Socket了,因此我们看到这部分的源码。ConnectionHandler是AbstractProtocol的内部类,其关键源码如下:
protected static class ConnectionHandler<S>
implements AbstractEndpoint.Handler<S> {
private final AbstractProtocol<S> proto;
private final AtomicLong registerCount = new AtomicLong(0);
private final Map<S,Processor> connections = new ConcurrentHashMap<>();
@Override
public SocketState process(SocketWrapperBase<S> wrapper,
SocketEvent status) {
if (wrapper == null) {
// 为空则直接跳出
return SocketState.CLOSED;
}
S socket = wrapper.getSocket();
// 第一次进来connections里面肯定为空,因此获取不到
Processor processor = connections.get(socket);
// 如果是异步已经有专门的线程去处理了,因此直接返回即可
if (SocketEvent.TIMEOUT == status && (processor == null ||
!processor.isAsync() ||
!processor.checkAsyncTimeoutGeneration())) {
return SocketState.OPEN;
}
if (processor != null) {
// 确保不会触发异步超时
getProtocol().removeWaitingProcessor(processor);
} else if (status == SocketEvent.DISCONNECT ||
status == SocketEvent.ERROR) {
// 如果状态异常则直接返回
return SocketState.CLOSED;
}
ContainerThreadMarker.set();
try {
// 一种类型的socket第一次一定是null,需要进行实例化
// 下面无关紧要的略过
...
if (processor == null) {
// 使用AbstractProtocol中的createProcessor获得具体的处理类
// 这个类型在Http11NioProtocol类中的方法中已经写死了
// 可以具体确定为Http11Processor类型
processor = getProtocol().createProcessor();
register(processor);
}
processor.setSslSupport(
wrapper.getSslSupport(getProtocol()
.getClientCertProvider()));
// 将创建好的processor和socket关联起来
connections.put(socket, processor);
SocketState state = SocketState.CLOSED;
do {
// 调用processor来处理wrapper和status
// 根据返回状态来进行具体的后置处理
// 如果是普通的HTTP请求直接在里面就处理完了,返回的状态
// 后续用不到,会直接返回,结束这个方法流程
state = processor.process(wrapper, status);
// UPGRADING状态Websocket会用到,但是普通的http请求用不到
if (state == SocketState.UPGRADING) {
// 这里略过
...
if (upgradeToken == null) {
...
} else {
HttpUpgradeHandler httpUpgradeHandler =
upgradeToken.getHttpUpgradeHandler();
release(processor);
// 根据upgradeToken来获取具体的Websocket处理类
processor = getProtocol()
.createUpgradeProcessor(wrapper,
upgradeToken);
wrapper.unRead(leftOverInput);
wrapper.setUpgraded(true);
connections.put(socket, processor);
// 在这里面调用进去处理WebSocket
if (upgradeToken.getInstanceManager() == null) {
httpUpgradeHandler
.init((WebConnection) processor);
} else {
ClassLoader oldCL = upgradeToken
.getContextBind().bind(false, null);
try {
httpUpgradeHandler
.init((WebConnection) processor);
} finally {
upgradeToken.getContextBind()
.unbind(false, oldCL);
}
}
if (httpUpgradeHandler instanceof
InternalHttpUpgradeHandler) {
if (((InternalHttpUpgradeHandler)
httpUpgradeHandler).hasAsyncIO()) {
state = SocketState.LONG;
}
}
}
}
} while ( state == SocketState.UPGRADING);
...
// 如果成功则会直接返回状态
return state;
}
// 后面都是失败后的处理逻辑了,无需关心
...
// 处理完再将对应关系删除
connections.remove(socket);
// 释放资源
release(processor);
return SocketState.CLOSED;
}
}
至此这一篇便告一段落了,这一篇讲解了Connector从初始化到运行时获取Socket请求并交给对应的processor进行处理。逻辑稍微复杂,需要一步一步跟着源码走,并且由于这里面大部分类都是由多线程运行的,更加让人迷惑,但只要理解了这里面的运行方式和逻辑就很清晰明了了。