概要
- Connector组成
- Connector分类
- Conector请求处理流程
-
1.Connector组成
Connector中包含一个ProtocolHandler和AdapterProtocolHandler创建对应Endpoint,用来处理请求。Adapter是Connector与Container容器之间的一个连接器。```java public class Connector extends LifecycleMBeanBase {// 协议Handler
protected final ProtocolHandler protocolHandler; // Coyote adapter. protected Adapter adapter = null; public Connector() {
// 默认使用niothis("org.apache.coyote.http11.Http11NioProtocol");
}
public Connector(String protocol) { // 传入协议名称
boolean aprConnector = AprLifecycleListener.isAprAvailable() &&AprLifecycleListener.getUseAprConnector(); // 是否开启Aprif ("HTTP/1.1".equals(protocol) || protocol == null) { // HTTP/1.1if (aprConnector) {protocolHandlerClassName = "org.apache.coyote.http11.Http11AprProtocol";} else {protocolHandlerClassName = "org.apache.coyote.http11.Http11NioProtocol";}} else if ("AJP/1.3".equals(protocol)) { // AJP/1.3if (aprConnector) {protocolHandlerClassName = "org.apache.coyote.ajp.AjpAprProtocol";} else {protocolHandlerClassName = "org.apache.coyote.ajp.AjpNioProtocol";}} else {protocolHandlerClassName = protocol; // 其他自定义协议实现}ProtocolHandler p = null;try {// 反射获取协议处理类Class<?> clazz = Class.forName(protocolHandlerClassName);// 实例化p = (ProtocolHandler) clazz.getConstructor().newInstance();} catch (Exception e) {log.error(sm.getString("coyoteConnector.protocolHandlerInstantiationFailed"), e);} finally {this.protocolHandler = p;}...
} } ```
2.Connector分类
可以分为以下三类
- Http Connector:解析HTTP请求,又分为BIO Http Connector和NIO Http Connector,即阻塞IO Connector和非阻塞IO Connector。本文主要分析NIO Http Connector的实现过程。
- APR HTTP Connector:解析HTTP请求,用C实现,通过JNI调用的。主要提升对静态资源(如HTML、图片、CSS、JS等)的访问性能。
- AJP Connector:基于AJP协议,用于Tomcat与HTTP服务器通信定制的协议,能提供较高的通信速度和效率。如与Apache服务器集成时,采用这个协议。
具体要使用哪种Connector可以在server.xml文件中通过protocol属性配置如下:
<Connector port="8080" protocol="org.apache.coyote.http11.Http11AprProtocol"connectionTimeout="20000"redirectPort="8443" />
每一类Connector对应这一种protocolHandler,protocolHandler用来监听服务器某个端口的请求,但并不处理(处理请求由容器组件完成)。
3.Conector请求处理流程

- Acceptor为监听线程,调用serverSocketAccept()阻塞,本质上调用ServerSocketChannel.accept()
- Acceptor将接受的Socket封装成PollerEvent,调用Poll的register方法放到Poll的同步队列中
- Poller线程循环从队列获取数据,然后把socketWrapper包装成SocketProcessor
- SocketProcessor调用getHandler()获取对应的ConnectionHandler
- ConnectionHandler把socket交由Http11Processor处理,解析http的Header和Body
- Http11Processor调用service()把包装好的request和response传给CoyoteAdapter
- CoyoteAdapter会通过Mapper把请求对应的session、servlet等关联好,准备传给Containe
4.Connector初始化流程
本文以sprng boot为例
//spring boot启动public ConfigurableApplicationContext run(String... args) {...try {ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);configureIgnoreBeanInfo(environment);Banner printedBanner = printBanner(environment);context = createApplicationContext();exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,new Class[] { ConfigurableApplicationContext.class }, context);prepareContext(context, environment, listeners, applicationArguments, printedBanner);refreshContext(context);//spring启动,扫描并且初始化bean;启动了内置web容器afterRefresh(context, applicationArguments);stopWatch.stop();.....return context;}
在ServletWebServerApplicationContext的onRefresh()方会创建servlet容器
protected void onRefresh() {super.onRefresh();try {//创建servlet容器createWebServer();}catch (Throwable ex) {throw new ApplicationContextException("Unable to start web server", ex);}}
在TomcatServletWebServerFactory#getWebServer()中会创建tomcat
public WebServer getWebServer(ServletContextInitializer... initializers) {if (this.disableMBeanRegistry) {Registry.disableRegistry();}//创建tomcatTomcat tomcat = new Tomcat();File baseDir = (this.baseDirectory != null) ? this.baseDirectory : createTempDir("tomcat");tomcat.setBaseDir(baseDir.getAbsolutePath());//创建http nio连接器Connector connector = new Connector(this.protocol);connector.setThrowOnFailure(true);//创建server和service,并把连接器放到service中tomcat.getService().addConnector(connector);customizeConnector(connector);tomcat.setConnector(connector);tomcat.getHost().setAutoDeploy(false);configureEngine(tomcat.getEngine());for (Connector additionalConnector : this.additionalTomcatConnectors) {tomcat.getService().addConnector(additionalConnector);}prepareContext(tomcat.getHost(), initializers);return getTomcatWebServer(tomcat);}
在增加的过程中会启动connetot
public void addConnector(Connector connector) {synchronized (connectorsLock) {connector.setService(this);Connector results[] = new Connector[connectors.length + 1];System.arraycopy(connectors, 0, results, 0, connectors.length);results[connectors.length] = connector;connectors = results;}try {if (getState().isAvailable()) {//启动连接器connector.start();}} catch (LifecycleException e) {throw new IllegalArgumentException(sm.getString("standardService.connector.startFailed", connector), e);}// Report this property change to interested listenerssupport.firePropertyChange("connector", null, connector);}
下面以Http11NioProtocol为例分析启动初始化过程:
在Connector的startInternal()方法中启动了protocolHandler,代码如下:
protected void startInternal() throws LifecycleException {if (getPortWithOffset() < 0) {throw new LifecycleException(sm.getString("coyoteConnector.invalidPort", Integer.valueOf(getPortWithOffset())));}setState(LifecycleState.STARTING);try {//启动protocolHandlerprotocolHandler.start();} catch (Exception e) {throw new LifecycleException(sm.getString("coyoteConnector.protocolHandlerStartFailed"), e);}}
在AbstractProtocol的start()方法中启动endpoint
@Overridepublic void start() throws Exception {if (getLog().isInfoEnabled()) {getLog().info(sm.getString("abstractProtocolHandler.start", getName()));logPortOffset();}//启动endpointendpoint.start();monitorFuture = getUtilityExecutor().scheduleWithFixedDelay(new Runnable() {@Overridepublic void run() {if (!isPaused()) {startAsyncTimeout();}}}, 0, 60, TimeUnit.SECONDS);}
在NioEndpoint的startInternal()方法,创建creating acceptor, poller threads.
/*** Start the NIO endpoint, creating acceptor, poller threads.*/@Overridepublic void startInternal() throws Exception {if (!running) {running = true;paused = false;if (socketProperties.getProcessorCache() != 0) {processorCache = new SynchronizedStack<>(SynchronizedStack.DEFAULT_SIZE,socketProperties.getProcessorCache());}if (socketProperties.getEventCache() != 0) {eventCache = new SynchronizedStack<>(SynchronizedStack.DEFAULT_SIZE,socketProperties.getEventCache());}if (socketProperties.getBufferPool() != 0) {nioChannels = new SynchronizedStack<>(SynchronizedStack.DEFAULT_SIZE,socketProperties.getBufferPool());}// Create worker collectionif (getExecutor() == null) {createExecutor();}initializeConnectionLatch();// Start poller threadpoller = new Poller();Thread pollerThread = new Thread(poller, getName() + "-ClientPoller");pollerThread.setPriority(threadPriority);pollerThread.setDaemon(true);//调用SynchronizedQueue.poll(),直到拿到PollerEventpollerThread.start();//创建接收器,在AbstractEndpoint#startAcceptorThread()中创建Acceptor,然后启动//最终调用NioEndpoint#serverSocketAccept(),启动socketServer//开始监听,到这Connector启动就结束了//Acceptor接收到请求封装成PollerEvent然后放到SynchronizedQueue中startAcceptorThread();}}
5.总结
Connector负责创建Request和ResponseConnector初始化时会创建对应的Endpoint;Endpoint监听一个指定端口,负责对请求报文的解析和响应报文组装Connector初始化时会创建对应的Adapter;Adapter将Request,Response交给给容器处理
