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处理.