目录
Endpoint端点,在Tomcat中也就是接收socket连接和处理连接的地方(ServerSocket.accept())
位于连接器组件Connector中的协议处理器ProtocolHandler中
AbstractEndpoint声明了三个组件,Accepter, SocketProcessor,以及一个Handler接口。
- Accepter 顾名思义,ServerSocket.accept()接收socket连接
- SocketProcessor 模板方法,子类实现具体的SocketProcessor类,处理接收到的socket,SocketProcessor处理完了就该转给具体协议层处理了
- Handler 协议层创建的处理器,endpoint调用
暂时只看了一个子类NioEndpoint,NioEndpoint中还定义了一个组件Poller,由Accepter负责监听,接收到scoket连接后,Poller中使用Selector.select() 监听读写事件,若读写就绪,转给SocketProcessor处理。
AbstractEndpoint
抽象父类中除了下边设置连接属性的方法外
模板模式定义了bind()、startInternal 及 创建和启动Accepter、Processor,处理Socket的方法
bind() 绑定ServerSocket端口
startInternal() 创建和启动Accepter等组件
public abstract class AbstractEndpoint<S> {
private volatile LimitLatch connectionLimitLatch = null;
private Executor executor = null;
protected Acceptor[] acceptors;
// processor的缓存
protected SynchronizedStack<SocketProcessorBase<S>> processorCache;
protected abstract Acceptor createAcceptor();
protected abstract SocketProcessorBase<S> createSocketProcessor(
SocketWrapperBase<S> socketWrapper, SocketEvent event);
public abstract void bind() throws Exception;
public abstract void unbind() throws Exception;
public abstract void startInternal() throws Exception;
public abstract void stopInternal() throws Exception;
public void init() throws Exception {
if (bindOnInit) {
bind();
bindState = BindState.BOUND_ON_INIT;
}
//。。。
}
public final void start() throws Exception {
if (bindState == BindState.UNBOUND) {
bind();
bindState = BindState.BOUND_ON_START;
}
startInternal();
}
protected final void startAcceptorThreads() {
int count = getAcceptorThreadCount();
acceptors = new Acceptor[count];
for (int i = 0; i < count; i++) {
acceptors[i] = createAcceptor();
String threadName = getName() + "-Acceptor-" + i;
acceptors[i].setThreadName(threadName);
Thread t = new Thread(acceptors[i], threadName);
t.setPriority(getAcceptorThreadPriority());
t.setDaemon(getDaemon());
t.start();
}
}
public boolean processSocket(SocketWrapperBase<S> socketWrapper,
SocketEvent event, boolean dispatch) {
try {
if (socketWrapper == null) {
return false;
}
// 是否有可重用的 SocketProcessor
SocketProcessorBase<S> sc = processorCache.pop();
if (sc == null) {
sc = createSocketProcessor(socketWrapper, event);
} else {
sc.reset(socketWrapper, event);
}
Executor executor = getExecutor();
if (dispatch && executor != null) {
executor.execute(sc);
} else {
sc.run();
}
} catch (RejectedExecutionException ree) {
getLog().warn(sm.getString("endpoint.executor.fail", socketWrapper) , ree);
return false;
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
// This means we got an OOM or similar creating a thread, or that
// the pool and its queue are full
getLog().error(sm.getString("endpoint.process.fail"), t);
return false;
}
return true;
}
}
NioEndpoint
来看父类抽象方法bind() 和 startInternal()的实现
public class NioEndpoint extends AbstractJsseEndpoint<NioChannel> {
private volatile ServerSocketChannel serverSock = null;
@Override
public void bind() throws Exception {
// endpoint初始化的时候调用bind(), 创建serversocket
serverSock = ServerSocketChannel.open();
socketProperties.setProperties(serverSock.socket());
// 获取端口号
InetSocketAddress addr = (getAddress()!=null?new InetSocketAddress(getAddress(),getPort()):new InetSocketAddress(getPort()));
// 绑定地址和定义连接队列最大多少 ,默认100
serverSock.socket().bind(addr, getAcceptCount());
serverSock.configureBlocking(true); //mimic APR behavior
// 设置acceptor线程和poller数量
if (acceptorThreadCount == 0) {
acceptorThreadCount = 1;
}
if (pollerThreadCount <= 0) {
pollerThreadCount = 1;
}
setStopLatch(new CountDownLatch(pollerThreadCount));
// 如果启用了https连接,这里初始化jsse或者openssl相关类
initialiseSsl();
// 启动selector池
selectorPool.open();
}
/**
* Start the NIO endpoint, creating acceptor, poller threads.
*/
@Override
public void startInternal() throws Exception {
if (!running) {
running = true;
paused = false;
processorCache = new SynchronizedStack<>(SynchronizedStack.DEFAULT_SIZE,
socketProperties.getProcessorCache());
eventCache = new SynchronizedStack<>(SynchronizedStack.DEFAULT_SIZE,
socketProperties.getEventCache());
nioChannels = new SynchronizedStack<>(SynchronizedStack.DEFAULT_SIZE,
socketProperties.getBufferPool());
// 创建执行器ThreadPoolExecutor (10, 200)
if ( getExecutor() == null ) {
createExecutor();
}
// 设置最大连接数,10000默认
initializeConnectionLatch();
// 启动Poller线程
pollers = new Poller[getPollerThreadCount()];
for (int i=0; i<pollers.length; i++) {
pollers[i] = new Poller();
Thread pollerThread = new Thread(pollers[i], getName() + "-ClientPoller-"+i);
pollerThread.setPriority(threadPriority);
pollerThread.setDaemon(true);
pollerThread.start();
}
// 启动acceptor
startAcceptorThreads();
}
}
@Override
protected AbstractEndpoint.Acceptor createAcceptor() {
return new Acceptor();
}
@Override
protected SocketProcessorBase<NioChannel> createSocketProcessor(
SocketWrapperBase<NioChannel> socketWrapper, SocketEvent event) {
return new SocketProcessor(socketWrapper, event);
}
}
Acceptor
serverSocket.accept() 监听接收连接,一旦有socket接入,更新连接数,封装socket并注册到Poller中
protected class Acceptor extends AbstractEndpoint.Acceptor {
@Override
public void run() {
int errorDelay = 0;
// 死循环接收连接,直到接受到shutdown指令
while (running) {
// 当endpoint 被暂停,睡会
while (paused && running) {
state = AcceptorState.PAUSED;
try {
Thread.sleep(50);
} catch (InterruptedException e) {
// Ignore
}
}
// shutdown指令
if (!running) {
break;
}
state = AcceptorState.RUNNING;
try {
// 增加连接数,当到达最大连接时会阻塞等待
countUpOrAwaitConnection();
SocketChannel socket = null;
try {
// socket accept()阻塞监听
socket = serverSock.accept();
} catch (IOException ioe) {
// 异常释放连接数
countDownConnection();
if (running) {
// 延迟报错,首次报错50ms,后续 * 2, 最大1600ms
// 为了防止特殊情况accept报错时,过度消耗cpu及触发日志记录
// 例如,到达最大打开文件数限制
errorDelay = handleExceptionWithDelay(errorDelay);
throw ioe;
} else {
break;
}
}
// Successful accept, reset the error delay
errorDelay = 0;
// Configure the socket
if (running && !paused) {
// 成功接收到一个socket, 进行封装和注册到poller
// 如果失败,关闭socket
if (!setSocketOptions(socket)) {
closeSocket(socket);
}
} else {
closeSocket(socket);
}
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
log.error(sm.getString("endpoint.accept.fail"), t);
}
}
state = AcceptorState.ENDED;
}
org.apache.tomcat.util.net.NioEndpoint#setSocketOptions
protected boolean setSocketOptions(SocketChannel socket) {
// Process the connection
try {
// disable blocking, APR style, we are gonna be polling it
socket.configureBlocking(false);
Socket sock = socket.socket();
socketProperties.setProperties(sock);
// nioChannels 是Niochannel 对象的缓存
NioChannel channel = nioChannels.pop();
if (channel == null) {
// 缓存无可用,创建新的buffer 和 Niochannel
SocketBufferHandler bufhandler = new SocketBufferHandler(
socketProperties.getAppReadBufSize(),
socketProperties.getAppWriteBufSize(),
socketProperties.getDirectBuffer());
if (isSSLEnabled()) {
channel = new SecureNioChannel(socket, bufhandler, selectorPool, this);
} else {
channel = new NioChannel(socket, bufhandler);
}
} else {
channel.setIOChannel(socket);
channel.reset();
}
// poller数组中顺序取一个poller注册channel
getPoller0().register(channel);
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
try {
log.error("",t);
} catch (Throwable tt) {
ExceptionUtils.handleThrowable(tt);
}
// Tell to close the socket
return false;
}
return true;
}
Poller
public class Poller implements Runnable {
private Selector selector;
private final SynchronizedQueue<PollerEvent> events =
new SynchronizedQueue<>();
private AtomicLong wakeupCounter = new AtomicLong(0);
public Poller() throws IOException {
this.selector = Selector.open();
}
}
刚看到注册了,先来看注册NioChannel方法
org.apache.tomcat.util.net.NioEndpoint.Poller#register
将Accepter接收到的NioChannel封装为一个注册事件PollerEvent,放入Poller组件的队列中,Poller线程在run方法中,消费事件进行注册,也就是将SocketChannel注册到Selector上(socketChannel.register(selector, .....))
public void register(final NioChannel socket) {
// 将NioChannel 绑定poller
socket.setPoller(this);
// NioChannel 封装类,设置属性
NioSocketWrapper ka = new NioSocketWrapper(socket, NioEndpoint.this);
socket.setSocketWrapper(ka);
ka.setPoller(this);
ka.setReadTimeout(getSocketProperties().getSoTimeout());
ka.setWriteTimeout(getSocketProperties().getSoTimeout());
ka.setKeepAliveLeft(NioEndpoint.this.getMaxKeepAliveRequests());
ka.setSecure(isSSLEnabled());
ka.setReadTimeout(getConnectionTimeout());
ka.setWriteTimeout(getConnectionTimeout());
// 设置对这个NioSocketWrapper关注读事件
// 往事件队列中增加注册此NioSocket的事件,在poller.run中执行
PollerEvent r = eventCache.pop();
ka.interestOps(SelectionKey.OP_READ);//this is what OP_REGISTER turns into.
if ( r==null) r = new PollerEvent(socket,ka,OP_REGISTER);
else r.reset(socket,ka,OP_REGISTER);
addEvent(r);
}
private void addEvent(PollerEvent event) {
// 添加队列并唤醒select
events.offer(event);
// 计数器,每次唤醒只调用一次wakeup
if ( wakeupCounter.incrementAndGet() == 0 ) selector.wakeup();
}
org.apache.tomcat.util.net.NioEndpoint.Poller#run
把socket注册到selector并关注读事件,阻塞select() 监听,监听到事件活动processKey()进行处理
public void run() {
// Loop until destroy() is called
while (true) {
boolean hasEvents = false;
try {
if (!close) {
// 执行注册事件,执行成功返回true
hasEvents = events();
// 没有唤醒操作的化,阻塞select
if (wakeupCounter.getAndSet(-1) > 0) {
//if we are here, means we have other stuff to do
//do a non blocking select
keyCount = selector.selectNow();
} else {
keyCount = selector.select(selectorTimeout);
}
wakeupCounter.set(0);
}
if (close) {
events();
timeout(0, false);
try {
selector.close();
} catch (IOException ioe) {
log.error(sm.getString("endpoint.nio.selectorCloseFail"), ioe);
}
break;
}
} catch (Throwable x) {
ExceptionUtils.handleThrowable(x);
log.error("",x);
continue;
}
// select无结果或被中断、唤醒出来后,再处理一波事件
if ( keyCount == 0 ) hasEvents = (hasEvents | events());
Iterator<SelectionKey> iterator =
keyCount > 0 ? selector.selectedKeys().iterator() : null;
// 循环就绪事件,处理对应的NioChannel
while (iterator != null && iterator.hasNext()) {
SelectionKey sk = iterator.next();
NioSocketWrapper attachment = (NioSocketWrapper)sk.attachment();
if (attachment == null) {
iterator.remove();
} else {
iterator.remove();
processKey(sk, attachment);
}
}//while
// 处理超时socket,从selector移除它
timeout(keyCount,hasEvents);
}//while
getStopLatch().countDown();
}
// PollerEvent 是一个Runnable
// 执行PollerEvent队列事件,例如注册NioChannel,从selector移除,设置关注事件等
// 代码上注册就是socket.register(selector, 注册)
// 设置关注事件就是key.interestOps() | interestOps
public boolean events() {
boolean result = false;
PollerEvent pe = null;
for (int i = 0, size = events.size(); i < size && (pe = events.poll()) != null; i++ ) {
result = true;
try {
pe.run();
pe.reset();
if (running && !paused) {
eventCache.push(pe);
}
} catch ( Throwable x ) {
log.error("",x);
}
}
return result;
}
org.apache.tomcat.util.net.NioEndpoint.Poller#processKey
移除当前SelectionKey就绪事件,处理读写事件
protected void processKey(SelectionKey sk, NioSocketWrapper attachment) {
if ( close ) {
cancelledKey(sk);
} else if ( sk.isValid() && attachment != null ) {
if (sk.isReadable() || sk.isWritable() ) {
if ( attachment.getSendfileData() != null ) {
processSendfile(sk,attachment, false);
} else {
// 移除就绪事件
unreg(sk, attachment, sk.readyOps());
boolean closeSocket = false;
// Read goes before write
// 处理读写
if (sk.isReadable()) {
if (!processSocket(attachment, SocketEvent.OPEN_READ, true)) {
closeSocket = true;
}
}
if (!closeSocket && sk.isWritable()) {
if (!processSocket(attachment, SocketEvent.OPEN_WRITE, true)) {
closeSocket = true;
}
}
if (closeSocket) {
cancelledKey(sk);
}
}
}
} else {
//invalid key
cancelledKey(sk);
}
}
org.apache.tomcat.util.net.AbstractEndpoint#processSocket
Poller将就绪的socket交给SocketProcessor来处理
public boolean processSocket(SocketWrapperBase<S> socketWrapper,
SocketEvent event, boolean dispatch) {
// 缓存中查找是否有现成的processor
SocketProcessorBase<S> sc = processorCache.pop();
if (sc == null) {
sc = createSocketProcessor(socketWrapper, event);
} else {
sc.reset(socketWrapper, event);
}
// 执行processor,处理socket事件
Executor executor = getExecutor();
if (dispatch && executor != null) {
executor.execute(sc);
} else {
sc.run();
}
return true;
}
SocketProcessor
处理poller中的就绪socket并将socket传递给对应的协议处理器的连接处理器解析socket内容
抽象AbstractEndpoint类中只定义了抽象方法创建SocketProcessor,不同的实现类中(AprEndpoint/NioEndpoint/Nio2Endpoint),即不同的IO模式有不同的SocketProcessor实现类
protected abstract SocketProcessorBase<S> createSocketProcessor(
SocketWrapperBase<S> socketWrapper, SocketEvent event);
主要处理代码如下一行,调用应用协议层Handler解析socket内容。还有其他的处理,例如SSL握手等,现不细看
getHandler().process(socketWrapper, event)
ConnectionHandler
ConnectionHandler定义在协议处理器ProtocolHandler接口的抽象类AbstractProtocol中,在new Http11NioProtocol()时候被创建并设置到endpoint中
只关注普通的HTTP请求,所以只看核心的几行,创建Processor进行请求处理,Processor实现类和具体协议实现类相关,在具体协议的Processor实现类中真正解析socket内容。
Http11Processor
HTTP11中的实现如下,关联当前Connector中的CoyoteAdapter对象
创建对象时, Http11Processor会绑定一对请求和响应对象,之后的解析简单来说就是为这两个对象设置各种属性
org.apache.coyote.http11.Http11Processor#service
此方法开始解析socket,根据Http协议解析socket内容将各种信息设置到Request和Response对象中,协议处理器ProtocolHandler的任务到这就完成了。
下一步需要交给Engine中部署的应用去实际处理,CoyoteAdapter作为Connector和Engine中间的连接组件对请求响应对象执行必要的处理,并交给Engine
调用CoyoteAdapter处理请求响应对
根据标志位来判断socket连接是否需要关闭和保持连接,是否需要继续Poll监听读,是否需要升级协议