AbstractEndpoint是基础的通信端点的实现,那么也就有具体的实现.其中一个就是JIoEndpoint,它的作用是处理访问的TCP连接.具体的实现是主线程启动一个Acceptor线程,它将启用一个阻塞型Socket侦听Tcp连接,获得连接后对每个连接启动一个worker线程进行处理.这是一个典型的Listen-Accept-Handle实现.
先看下它是怎么实现AbstractEndPoint的Acceptor,它简单的实现了一个run方法.这个线程在生命周期的init中将被启动.
public void run() {
int errorDelay = 0;
// Loop until we receive a shutdown command
while (running) {
// Loop if endpoint is paused
while (paused && running) {
state = AcceptorState.PAUSED;
try {
Thread.sleep(50);
} catch (InterruptedException e) {
// Ignore
}
}
if (!running) {
break;
}
state = AcceptorState.RUNNING;
try {
//if we have reached max connections, wait
countUpOrAwaitConnection();
Socket socket = null;
try {
// Accept the next incoming connection from the server
// socket
socket = serverSocketFactory.acceptSocket(serverSocket);
} catch (IOException ioe) {
countDownConnection();
// Introduce delay if necessary
errorDelay = handleExceptionWithDelay(errorDelay);
// re-throw
throw ioe;
}
// Successful accept, reset the error delay
errorDelay = 0;
// Configure the socket
if (running && !paused && setSocketOptions(socket)) {
// Hand this socket off to an appropriate processor
if (!processSocket(socket)) {
countDownConnection();
// Close socket right away
closeSocket(socket);
}
} else {
countDownConnection();
// Close socket right away
closeSocket(socket);
}
} catch (IOException x) {
if (running) {
log.error(sm.getString("endpoint.accept.fail"), x);
}
} catch (NullPointerException npe) {
if (running) {
log.error(sm.getString("endpoint.accept.fail"), npe);
}
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
log.error(sm.getString("endpoint.accept.fail"), t);
}
}
state = AcceptorState.ENDED;
}
从上面代码看出,最外层的while是一直存在的,除非服务器不是运行状态.而while (paused && running) 是标志着这个端点处于暂停服务状态.如果countUpOrAwaitConnection线程没有进入等待队列的话就接受socket,也就是接受TCP连接请求.这里的Socket是阻塞Socket.正因为是阻塞的Socket,所以需要多线程处理.也就是所谓的worker线程,下面看下processSocket方法.
protected boolean processSocket(Socket socket) {
// Process the request from this socket
try {
SocketWrapper<socket> wrapper = new SocketWrapper<socket>(socket);
wrapper.setKeepAliveLeft(getMaxKeepAliveRequests());
// During shutdown, executor may be null - avoid NPE
if (!running) {
return false;
}
getExecutor().execute(new SocketProcessor(wrapper));
} catch (RejectedExecutionException x) {
log.warn("Socket processing request was rejected for:"+socket,x);
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
log.error(sm.getString("endpoint.process.fail"), t);
return false;
}
return true;
}
processSocket对新的连接进行处理.但是很显然它所做的仅仅是Socket的包装和异常处理.还有启动work线程.也就是SocketProcessor.该方法的注释是Process a new connection from a new client. Wraps the socket so keep-alive and other attributes can be tracked and then passes the socket to the executor for processing.下面看下worker线程(SocketProcessor)的run方法实现.
public void run() {
boolean launch = false;
synchronized (socket) {
try {
SocketState state = SocketState.OPEN;
try {
// SSL handshake
serverSocketFactory.handshake(socket.getSocket());
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
if (log.isDebugEnabled()) {
log.debug(sm.getString("endpoint.err.handshake"), t);
}
// Tell to close the socket
state = SocketState.CLOSED;
}
if ((state != SocketState.CLOSED)) {
if (status == null) {
state = handler.process(socket, SocketStatus.OPEN);
} else {
state = handler.process(socket,status);
}
}
if (state == SocketState.CLOSED) {
// Close socket
if (log.isTraceEnabled()) {
log.trace("Closing socket:"+socket);
}
countDownConnection();
try {
socket.getSocket().close();
} catch (IOException e) {
// Ignore
}
} else if (state == SocketState.OPEN ||
state == SocketState.UPGRADING ||
state == SocketState.UPGRADED){
socket.setKeptAlive(true);
socket.access();
launch = true;
} else if (state == SocketState.LONG) {
socket.access();
waitingRequests.add(socket);
}
} finally {
if (launch) {
try {
getExecutor().execute(new SocketProcessor(socket, SocketStatus.OPEN));
} catch (RejectedExecutionException x) {
log.warn("Socket reprocessing request was rejected for:"+socket,x);
try {
//unable to handle connection at this time
handler.process(socket, SocketStatus.DISCONNECT);
} finally {
countDownConnection();
}
} catch (NullPointerException npe) {
if (running) {
log.error(sm.getString("endpoint.launch.fail"),
npe);
}
}
}
}
}
socket = null;
// Finish up this request
}
方法这么长key point就一个地方state = handler.process(socket,status).这个handler继承了AbstractEndpoint的Handler这个Handler还是没有给出具体的实现.具体的实现在具体的Protocol中.可以确定的是,它的实现应该有个轮询处理.知道了Acceptor和和Worker.那就看看他们的生命周期.生命周期函数是实现了父类AbstractEndpoint的抽象方法.
public void bind() throws Exception {
// Initialize thread count defaults for acceptor
if (acceptorThreadCount == 0) {
acceptorThreadCount = 1;
}
// Initialize maxConnections
if (getMaxConnections() == 0) {
// User hasn't set a value - use the default
setMaxConnections(getMaxThreadsExecutor(true));
}
if (serverSocketFactory == null) {
if (isSSLEnabled()) {
serverSocketFactory =
handler.getSslImplementation().getServerSocketFactory(this);
} else {
serverSocketFactory = new DefaultServerSocketFactory(this);
}
}
if (serverSocket == null) {
try {
if (getAddress() == null) {
serverSocket = serverSocketFactory.createSocket(getPort(),
getBacklog());
} else {
serverSocket = serverSocketFactory.createSocket(getPort(),
getBacklog(), getAddress());
}
} catch (BindException orig) {
......
}
}
}
bind主要是初始化acceptor的线程数,这里是1.最大连接数和创建ServerSocket.接着是startInternal方法.它的作用是创建Worker线程池,连接限制锁存器.还有启动Acceptor线程.最后值得一提的是它启动了一个timeoutThread.这是一个对连接超时进行处理的线程.有了Acceptor,Worker和TimeoutThread.这样JIoEndpoint在生命周期内就能接受TCP连接,并转发给Handler处理.