init顺序
| 1 | Bootstrap | 
start顺序
| 1 | Bootstrap | 
请求处理
- NioEndpoint.bind() - 1 
 2
 3- - 创建ServerSocketChannel,绑定地址、端口,设置成阻塞模式 
 - 初始化SSL
 - 开启NioSelectorPool
- NioEndpoint.startInternal() - 1 
 2
 3
 4- - 创建processorCache、eventCache、nioChannels栈 
 - 创建worker线程池,默认大小200
 - 创建Poller线程池并启动,大小为2和cpu最大核心数的最小值
 - 创建Acceptor线程池并启动,默认大小1
- NioEndpoint.Acceptor.run() - 1 
 2
 3
 4
 5
 6
 7
 8- - countUpOrAwaitConnection()连接数减一 
 - Acceptor线程阻塞处理ServerSocketChannel.accept()返回SocketChannel
 - countDownConnection()出异常加回去
 - setSocketOptions从SocketChannel取出Socket包装到NioChannel,并设置成非阻塞模式
 - 使用Poller线程register NioChannel
 - eventCache取出PollerEvent修改为OP_REGISTER然后添加回去
 - 唤醒Poller线程的Selector
 - wakeupCounter加一
- NioEndpoint.Poller.run() - 1 
 2
 3
 4
 5- - 调用events()处理PollerEvent 
 - 执行读取到的PollerEvent.run()
 - PollerEvent.run()判断PollerEvent若是OP_REGISTER,则往NioChannel注册读事件,使用Poller线程的Selector
 - select到SelectionKey,调用processKey处理
 - 执行processKey处理读写事件
- AbstractEndpoint.processSocket() - 1 
 2
 3
 4
 5
 6- - processorCache.pop()缓存复用 
 - 没缓存则调用createSocketProcessor()创建SocketProcessor
 - 使用worker线程池处理
 - SocketProcessor.run()->doRun()
 - getHandler().process()处理请求(AbstractProtocol.ConnectionHandler.process)
 - SocketProcessor把自己push到processorCache缓存复用
- AbstractHttp11Protocol.AbstractHttp11Protocol() 
创建应用协议层1
2- 构造方法传入endpoint
- 创建ConnectionHandler并设置给endpoint
- AbstractProtocol.ConnectionHandler.process() - 1 
 2
 3- - 从connections缓存复用Processor 
 - 不存在缓存则调用相应协议的getProtocol().createProcessor()
 - 缓存至connections复用
- AbstractHttp11Protocol.createProcessor() - 1 
 2
 3
 4
 5
 6- - 创建Http11Processor 
 - Http11Processor构造方法创建Request、Response
 - 创建HttpParser用于解析http数据
 - 创建Http11InputBuffer、Http11OutputBuffer分别设置给Request、Response
 - 给Http11InputBuffer添加一系列的InputFilter
 - 给Http11OutputBuffer添加一系列的OutputFilter
- AbstractProcessorLight.process() -> Http11Processor - 1 
 2
 3
 4- - Http11Processor.service() 
 - inputBuffer.parseRequestLine()解析请求行
 - inputBuffer.parseHeaders解析请求头
 - Http11Processor.prepareRequest()准备请求
- CoyoteAdapter.service() - 处理请求 - 1 
 2
 3- - 创建org.apache.catalina.connector.Request存储老的org.apache.coyote.Request 
 - 创建org.apache.catalina.connector.Response存储老的org.apache.coyote.Response
 - 从connector.getURICharset()读取URI字符集类型,设置到org.apache.coyote.Request的parameters
- CoyoteAdapter.postParseRequest() - 1 
 2
 3
 4
 5
 6
 7- - 若是OPTIONS *,则直接打印访问日志并返回(添加Allow头GET, HEAD, POST, PUT, DELETE, OPTIONS) 
 - parsePathParameters解析路径参数
 - 解码URI(% +)
 - URI处理,反斜杠\转斜杆/,穿越/../ /./处理
 - B2CConverter转换URI
 - 检测前面对于穿越有没有处理干净
 - 从URL或者Cookie中读取SessionId
- org.apache.catalina.mapper -> internalMap -> internalMapWrapper - 1 
 2
 3- - host+uri匹配 
 - 读取servletPath
 - 把匹配到的数据放到传入的MappingData参数中返回
- pipeline处理 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18- - org.apache.catalina.core.StandardEngineValve#invoke 
 - org.apache.catalina.valves.AbstractAccessLogValve#invoke
 - org.apache.catalina.valves.ErrorReportValve#invoke
 - org.apache.catalina.core.StandardHostValve#invoke
 - org.apache.catalina.authenticator.AuthenticatorBase#invoke
 - org.apache.catalina.core.StandardContextValve#invoke
 - org.apache.catalina.core.StandardWrapperValve#invoke
 - org.apache.catalina.core.ApplicationFilterChain#doFilter
 - org.apache.catalina.core.ApplicationFilterChain#internalDoFilter
 - javax.servlet.http.HttpServlet#service
 jsp:
 - org.apache.jasper.servlet.JspServlet#service
 - org.apache.jasper.servlet.JspServlet#serviceJspFile
 - org.apache.jasper.servlet.JspServletWrapper#service
 servlet:
 - org.apache.catalina.servlets.DefaultServlet#service
 - javax.servlet.http.HttpServlet#service
 - org.apache.catalina.servlets.DefaultServlet#doGet
请求头解析
- inputBuffer.parseRequestLine解析请求行 - 1 
 2
 3
 4
 5- 1. 跳过CR LF空行 
 2. 解析method,读取到第一个空格或\t结束
 3. 跳过一些空格和\t
 4. 解析URI,判断URI字符是否合规,CR后不能接LF
 5. 判断协议字符是否合规
- inputBuffer.parseHeaders解析请求头 - 1 
 2- 1. 不断读取请求头,以:分隔name和value 
 2. 大写的name会转小写
- Http11Processor.prepareRequest()准备请求 - 1 
 2
 3
 4
 5
 6
 7
 8- 1. 读取头Connection判断是close还是keep-alive 
 2. 读取头expect判断是否100-continue
 3. 读取头host判断是否为空
 4. 如果URI是"http://"、"https://"开头的,需要去除
 5. 如果URI带有host,并且与host头不一致,将使用URI的host作为新的host头
 6. 如果是HTTP/1.1,则读取transfer-encoding,遍历值,选择解码filter添加
 7. 读取头content-length
 8. 解析host,得到serverPort和serverNameMB
- 连接数:默认10000
- ServerSocket accept积压数:默认100
- accept线程数:默认1
- poller线程数:2和cpu最大核心数的最小值