首先看BIO模式。
<Connector port="8081" protocol="HTTP/1.1"
connectionTimeout="20000"
protocol设定为"HTTP/1.1",这里指org.apache.coyote.http11.Http11Protocol,
- public void setProtocol(String protocol) {
- if (AprLifecycleListener.isAprAvailable()) {
- if ("HTTP/1.1".equals(protocol)) {
- setProtocolHandlerClassName
- ("org.apache.coyote.http11.Http11AprProtocol");
- } else if ("AJP/1.3".equals(protocol)) {
- setProtocolHandlerClassName
- ("org.apache.coyote.ajp.AjpAprProtocol");
- } else if (protocol != null) {
- setProtocolHandlerClassName(protocol);
- } else {
- setProtocolHandlerClassName
- ("org.apache.coyote.http11.Http11AprProtocol");
- }
- } else {
- if ("HTTP/1.1".equals(protocol)) {
- setProtocolHandlerClassName
- ("org.apache.coyote.http11.Http11Protocol");
- } else if ("AJP/1.3".equals(protocol)) {
- setProtocolHandlerClassName
- ("org.apache.jk.server.JkCoyoteHandler");
- } else if (protocol != null) {
- setProtocolHandlerClassName(protocol);
- }
- }
- }
我们这里没有apr 也没有ajp.所以ProtocolHandlerClassName就是org.apache.coyote.http11.Http11Protocol,Http11Protocol在init里,会初始化JioEndpoint。
以后的工作主要由JioEndpoint来处理请求连接,来看看JioEndpoint的init方法:
- public void init()
- throws Exception {
-
- if (initialized)
- return;
-
-
- if (acceptorThreadCount == 0) {
- acceptorThreadCount = 1;
- }
- if (serverSocketFactory == null) {
- serverSocketFactory = ServerSocketFactory.getDefault();
- }
- if (serverSocket == null) {
- try {
- if (address == null) {
- serverSocket = serverSocketFactory.createSocket(port, backlog);
- } else {
- serverSocket = serverSocketFactory.createSocket(port, backlog, address);
- }
- } catch (BindException orig) {
- String msg;
- if (address == null)
- msg = orig.getMessage() + " <null>:" + port;
- else
- msg = orig.getMessage() + " " +
- address.toString() + ":" + port;
- BindException be = new BindException(msg);
- be.initCause(orig);
- throw be;
- }
- }
-
-
-
- initialized = true;
-
主要目的就是创建ServerSocket. 有了服务端的listener.
Http11Protocol启动的时候,相应的启动JioEndpoint.
- public void start()
- throws Exception {
-
- if (!initialized) {
- init();
- }
- if (!running) {
- running = true;
- paused = false;
-
-
- if (executor == null) {
- workers = new WorkerStack(maxThreads);
- }
-
-
- for (int i = 0; i < acceptorThreadCount; i++) {
- Thread acceptorThread = new Thread(new Acceptor(), getName() + "-Acceptor-" + i);
- acceptorThread.setPriority(threadPriority);
- acceptorThread.setDaemon(daemon);
- acceptorThread.start();
- }
- }
- }
在①处,WorkerStack模拟一个栈,里面用数组存储工作线程(Tomcat这帮人就喜欢用数组)。用来处理请求过来的socket.
-
-
-
- protected class Acceptor implements Runnable {
-
-
-
-
- public void run() {
-
-
- while (running) {
-
-
- while (paused) {
- try {
- Thread.sleep(1000);
- } catch (InterruptedException e) {
-
- }
- }
-
-
- try {
- Socket socket = serverSocketFactory.acceptSocket(serverSocket);
- serverSocketFactory.initSocket(socket);
-
- if (!processSocket(socket)) {
-
- try {
- socket.close();
- } catch (IOException e) {
-
- }
- }
- }catch ( IOException x ) {
- if ( running ) log.error(sm.getString("endpoint.accept.fail"), x);
- } catch (Throwable t) {
- log.error(sm.getString("endpoint.accept.fail"), t);
- }
-
-
-
- }
-
- }
- }
- serverSocketFactory.acceptSocket用init方法里创建的severSocket accept一个连接Socket。然后processSocket(socket).
- 下面看processSocke(socket)方法:
-
- protected boolean processSocket(Socket socket) {
- try {
- if (executor == null) {
- getWorkerThread().assign(socket);
- } else {
- executor.execute(new SocketProcessor(socket));
- }
- } catch (Throwable t) {
-
-
- log.error(sm.getString("endpoint.process.fail"), t);
- return false;
- }
- return true;
- }
getWorkerThread()方法是从刚才创建的工作线程栈WorkerStack中取得一个工作线程。
这段代码很简单,就不说了,有兴趣看一下Tomcat的源代码(Class:JioEndpoint).
- protected class Worker implements Runnable {
-
- protected Thread thread = null;
- protected boolean available = false;
- protected Socket socket = null;
-
-
-
-
-
-
-
-
-
-
- synchronized void assign(Socket socket) {
-
-
- while (available) {
- try {
- wait();
- } catch (InterruptedException e) {
- }
- }
-
- this.socket = socket;
- available = true;
- notifyAll();
-
- }
-
-
-
-
-
-
- private synchronized Socket await() {
-
- while (!available) {
- try {
- wait();
- } catch (InterruptedException e) {
- }
- }
-
-
- Socket socket = this.socket;
- available = false;
- notifyAll();
-
- return (socket);
-
- }
-
-
-
-
- public void run() {
-
-
- while (running) {
-
-
- Socket socket = await();
- if (socket == null)
- continue;
-
-
- if (!setSocketOptions(socket) || !handler.process(socket)) {
-
- try {
- socket.close();
- } catch (IOException e) {
- }
- }
-
-
- socket = null;
- recycleWorkerThread(this);
-
- }
-
- }
-
-
-
- public void start() {
- thread = new Thread(this);
- thread.setName(getName() + "-" + (++curThreads));
- thread.setDaemon(true);
- thread.start();
- }
- }
首行看一下刚刚被调用的assign方法,Worker类通过available互斥。Available可理解为是否还有现成的Socket绑定在这个工作线程上,true表示有。Assign首先判断Available,如果有可用socket,即Available为true,则wait直到被唤醒。 This method is called from our Connector's thread.告诉我们该方法由连接器线程调用。那么工作线程自己呢。看run方法,调用了await,按照上面的理解,如果没有可用的socket,即Available为false,则wait直到被唤醒。如果为true,刚马上拿走这个socket.并把Available设为false.就可以有新的Socket放进来了。
但这里有点问题,从WorkerStack栈出取出的Worker或者新建的Worker,Available肯定都为false.那么assign方法的
while (available)循环就没有必要了。不清楚为什么作者这么写。
获得Socket之后交由handler去处理,这里的handler就
是Http11Protocol$Http11ConnectionHandler,处理流程,以会再讨论。
本文转自 anranran 51CTO博客,原文链接:http://blog.51cto.com/guojuanjun/538310