tomcat建立连接
来源:互联网 发布:mac怎么装虚拟机win10 编辑:程序博客网 时间:2024/05/21 07:49
参考资料: Tomcat7.0源码分析——请求原理分析(上)
servlet应用放入tomcat中启动后就可以接受请求,那在tomcat中是怎么实现的呢?
1、ProtocolHandler接口是真正处理请求的地方,这个接口是在Connector中初始化的。在Connector中有两个方法用来初始化和启动ProtocolHandler
@Override protected void initInternal() throws LifecycleException { super.initInternal(); // 构造Adapter对象,Adapter用来适配不同的网络协议 adapter = new CoyoteAdapter(this); protocolHandler.setAdapter(adapter); if (null == parseBodyMethodsSet) { setParseBodyMethods(getParseBodyMethods()); } try { // 初始化ProtocolHandler,ProtocolHandler用来处理请求 protocolHandler.init(); } catch (Exception e) { throw new LifecycleException(sm.getString("coyoteConnector.protocolHandlerInitializationFailed"), e); } // 初始化MapperListener,MapperListener注册host mapperListener.init(); } @Override protected void startInternal() throws LifecycleException { if (getPort() < 0) { throw new LifecycleException(sm.getString("coyoteConnector.invalidPort", Integer.valueOf(getPort()))); } // 设置Connector已经启动 setState(LifecycleState.STARTING); try { // 启动protocolHandler protocolHandler.start(); } catch (Exception e) { String errPrefix = ""; if (this.service != null) { errPrefix += "service.getName(): \"" + this.service.getName() + "\"; "; } throw new LifecycleException(errPrefix + " " + sm.getString("coyoteConnector.protocolHandlerStartFailed"), e); } // 启动MapperListener mapperListener.start(); }
2、我们来看看初始化ProtocolHandler的方法,ProtocolHandler默认使用Http11Protocol实例化,Http11Protocol直接继承了AbstractProtocol的init方法。
@Override public void init() throws Exception { if (getLog().isInfoEnabled()) { getLog().info(sm.getString("abstractProtocolHandler.init", getName())); } if (oname == null) { oname = createObjectName(); if (oname != null) { Registry.getRegistry(null, null).registerComponent(this, oname, null); } } if (this.domain != null) { try { tpOname = new ObjectName(domain + ":type=ThreadPool,name=" + getName()); Registry.getRegistry(null, null).registerComponent(endpoint, tpOname, null); } catch (Exception e) { getLog().error(sm.getString("abstractProtocolHandler.mbeanRegistrationFailed", tpOname, getName()), e); } rgOname = new ObjectName(domain + ":type=GlobalRequestProcessor,name=" + getName()); Registry.getRegistry(null, null).registerComponent(getHandler().getGlobal(), rgOname, null); } String endpointName = getName(); endpoint.setName(endpointName.substring(1, endpointName.length() - 1)); try { // 重点是这个方法,JIoEndpoint做为初始化的实现,创建服务器socket endpoint.init(); } catch (Exception ex) { getLog().error(sm.getString("abstractProtocolHandler.initError", getName()), ex); throw ex; } }
3、JioEndpoint创建socket的方法
@Override public void bind() throws Exception { // 初始化接受请求线程数量 if (acceptorThreadCount == 0) { acceptorThreadCount = 1; } // 初始化socket最大连接数 if (getMaxConnections() == 0) { setMaxConnections(getMaxThreads()); } if (serverSocketFactory == null) { if (isSSLEnabled()) { // 创建Socket工厂 serverSocketFactory = handler.getSslImplementation().getServerSocketFactory(this); } else { serverSocketFactory = new DefaultServerSocketFactory(this); } } if (serverSocket == null) { try { if (getAddress() == null) { // 创建服务器socket serverSocket = serverSocketFactory.createSocket(getPort(), getBacklog()); } else { serverSocket = serverSocketFactory.createSocket(getPort(), getBacklog(), getAddress()); } } catch (BindException orig) { String msg; if (getAddress() == null) msg = orig.getMessage() + " <null>:" + getPort(); else msg = orig.getMessage() + getAddress().toString() + ":" + getPort(); BindException be = new BindException(msg); be.initCause(orig); throw be; } } }
4、现在我们的服务端socket已经创建好了,接下来启动这个socket,启动和初始化相似,Http11Protocol直接继承了AbstractProtocol的start方法。
@Override public void start() throws Exception { if (getLog().isInfoEnabled()) getLog().info(sm.getString("abstractProtocolHandler.start", getName())); try { // 还是交给JIoEndpoint来启动 endpoint.start(); } catch (Exception ex) { getLog().error(sm.getString("abstractProtocolHandler.startError", getName()), ex); throw ex; } }
5、JioEndpoint启动socket的方法
@Override public void startInternal() throws Exception { if (!running) { running = true; paused = false; if (getExecutor() == null) { // 初始化线程池 createExecutor(); } // 设置最大连接数,超过阻塞线程 initializeConnectionLatch(); // 启动接受请求的线程 startAcceptorThreads(); // 启动链接超时的线程 Thread timeoutThread = new Thread(new AsyncTimeout(), getName() + "-AsyncTimeout"); timeoutThread.setPriority(threadPriority); timeoutThread.setDaemon(true); timeoutThread.start(); } }
public void createExecutor() { internalExecutor = true; // 创建任务队列 TaskQueue taskqueue = new TaskQueue(); // 创建线程工厂 TaskThreadFactory tf = new TaskThreadFactory(getName() + "-exec-", daemon, getThreadPriority()); // 初始化线程池 executor = new ThreadPoolExecutor(getMinSpareThreads(), getMaxThreads(), 60, TimeUnit.SECONDS,taskqueue, tf); // 任务队列使用线程池产生 taskqueue.setParent( (ThreadPoolExecutor) executor); }
7、启动接受请求的线程
protected final void startAcceptorThreads() { // 创建一个线程数组 int count = getAcceptorThreadCount(); acceptors = new Acceptor[count]; for (int i = 0; i < count; i++) { // 实例化线程类 acceptors[i] = createAcceptor(); // 使用Thread 启动 Thread t = new Thread(acceptors[i], getName() + "-Acceptor-" + i); t.setPriority(getAcceptorThreadPriority()); t.setDaemon(getDaemon()); t.start(); } }
8、接受请求的线程类
protected class Acceptor extends AbstractEndpoint.Acceptor { @Override public void run() { int errorDelay = 0; // 无限循环直接接受到shutdown后退出 while (running) { // 收到线程暂停的命令后暂停50ms while (paused && running) { state = AcceptorState.PAUSED; try { Thread.sleep(50); } catch (InterruptedException e) { } } if (!running) { break; } state = AcceptorState.RUNNING; try { // 达到了最大连接数,线程阻塞 countUpOrAwaitConnection(); Socket socket = null; try { // 从服务端socket接受链接 socket = serverSocketFactory.acceptSocket(serverSocket); } catch (IOException ioe) { errorDelay = handleExceptionWithDelay(errorDelay); throw ioe; } errorDelay = 0; if (running && !paused && setSocketOptions(socket)) { if (!processSocket(socket)) { closeSocket(socket); } } else { 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; } }
到此为止,请求和服务器之间的链接已经建立好了。
阅读全文
0 0
- Tomcat建立软连接
- tomcat建立连接
- Myeclipse与Tomcat建立连接
- 建立基于 JDBC 的 Tomcat 连接池
- 建立基于 JDBC 的 Tomcat 连接池
- 建立基于 JDBC 的 Tomcat 连接池
- TOMCAT建立SSL连接双向认证
- 建立MyEclipse与Tomcat的连接
- 源码包安装 建立软连接tomcat
- Tomcat 虚拟目录配置or Tomcat软连接如何建立?
- Connection-采用tomcat连接池建立Connecton连接
- Tomcat 5.0.28 MySQL 5 连接池的建立
- Tomcat 5.0.28 MySQL 5 连接池的建立(转)
- 关于tomcat发布遇到locathost无法建立连接的问题
- 建立连接
- 建立连接
- tomcat 无法连接127.0.0.1 无法建立到 127.0.0.1 服务器的连接 localhost可以访问
- 在tomcat下建立虚拟站点并配置mysql连接池
- SYD8801微信接入测试结果
- 对抗式生成网络---验证码的生成
- MySQL 安装配置
- java实现单点登录
- Python open()文件处理使用介绍
- tomcat建立连接
- 111. Minimum & Maximum Depth of Binary Tree
- RocketMQ在windows上安装和开发使用
- 如何判断是否是原生js函数
- angular-cli 常见用法
- 自定义View
- Android,Android介绍。
- Spring入门(Bean装配,@Qualifier)
- 松柏先生:电商的这六道死穴不解开,就等死吧!