1、Connector的构成:
Connecttor内部有两大组件:
| 组件 | 作用 |
|---|---|
| ProtocolHandler: | 完成网络通信 && 按照通信协议解析字节流 |
| Adapter | 将Request转换成HttpServletRequest(Response同样),并调用Container。封装影响的Response |
ProtocolHandler 又分为两个组件:
| 组件 | 功能 |
|---|---|
| Endpoint | 主要解决网络通信 |
| Processor | 解析协议 |
2、BIO模式下的类图(tomcat7)
3、Connector整体运行过程:
3.1 JioEndPoint在开始启动过程中,调用startInternal()时 创建Acceptor[]数组,每个acceptor都开启一个专门的线程,用来接收请求。Acceptor的run()方法,用来执行 socket.accept()。接收客户端的请求。
protected class Acceptor extends AbstractEndpoint.Acceptor {
@Override
public void run() {
while (running) {
//if we have reached max connections, wait
// 达到了最大连接数限制则等待
//countUpOrAwaitConnection();
Socket socket = null;
try {
logger.info(" await socket 开始等待客户端socket链接!!! .....");
socket = serverSocketFactory.acceptSocket(serverSocket);
logger.info("接收到一个socket请求!");
} catch (IOException ioe) {
}
// accept之后,开始处理请求
if (!processSocket(socket)) {
//countDownConnection();
// Close socket right away
closeSocket(socket);
}
}
state = AcceptorState.ENDED;
}
}
3.2 Acceptor接收到客户端的请求后,于是开始处理请求 processSocket(socket),将socket放入包装类socketWrapper中,创建SocketProcessor对象。放入线程池中执行。
protected boolean processSocket(Socket socket) {
try {
logger.info("processSocket " + socket.getInetAddress());
if (!running) {
return false;
}
//包装
SocketWrapper<Socket> socketWrapper = new SocketWrapper<>(socket);
socketWrapper.setKeepAliveLeft(getMaxKeepAliveRequests());
//bio,一个socket连接对应一个线程
getExecutor().execute(new SocketProcessor(socketWrapper));
} catch (Exception e) {
logger.error("JioEndpoint processSocket failed . msg ={}", e.getMessage(), e);
return false;
}
return true;
}
3.3 SocketProcessor的执行,核心是调用Processor来解析解析。
@Override
public void run() {
synchronized (socket) {
//处理SSL(证书验证,todo)
Handler.SocketState state = Handler.SocketState.OPEN;
// 当前socket没有关闭则处理socket
if ((state != Handler.SocketState.CLOSED)) {
logger.info(" handler process socket");
// SocketState是Tomcat定义的一个状态,这个状态需要处理一下socket才能确定,因为跟客户端,跟具体的请求信息有关系
if (status == null) {
state = handler.process(socket, SocketStatus.OPEN_READ);
} else {
// status表示应该读数据还是应该写数据
// state表示处理完socket后socket的状态
state = handler.process(socket, status);
}
}
}
socket = null;
}
3.4 ProtocolHandler主要是 创建具体协议对应的Processor来解析协议。
public SocketState process(SocketWrapper<S> wrapper, SocketStatus status) {
if (wrapper == null) {
return SocketState.CLOSED;
}
S socket = wrapper.getSocket();
if (socket == null) {
return SocketState.CLOSED;
}
// 设置为非异步,就是同步
wrapper.setAsync(false);
Processor<S> processor = connections.get(socket);
SocketState state = SocketState.CLOSED;
try {
if (processor == null) {
processor = createProcessor();
}
//真正处理请求的地方
state = processor.process(wrapper);
} catch (Exception e) {
e.printStackTrace();
}
return state;
}
3.5 解析协议的过程,将socket中读出的字节流,按照对应的协议(eg:http1.1) 来进行解析。
@Override
public AbstractEndpoint.Handler.SocketState process(SocketWrapper<S> socketWrapper) throws Exception {
// setting up the I/O
setSocketWrapper(socketWrapper);
// 获取了socket中的inputStream
getInputBuffer().init(socketWrapper, endpoint);
getOutputBuffer().init(socketWrapper, endpoint);
// Flags
keepAlive = true;
// 如果当前活跃的线程数占线程池最大线程数的比例大于75%,那么关闭keepAlive,不再支持长连接
// if (disableKeepAlive()) {
// socketWrapper.setKeepAliveLeft(0);
// }
// 循环响应结果
// 解析请求
if (!getInputBuffer().parseRequestLine(keptAlive)) {
}
···
解析http请求
···
// Process the Protocol component of the request line
// Need to know if this is an HTTP 0.9 request before trying to
// parse headers.
prepareRequestProtocol();
// process the request in the adapter
adapter.service(request, response);
return AbstractEndpoint.Handler.SocketState.CLOSED;
}
3.6 调用adater,封装HttpServletRequest和HttpServletResponse对象,并调用Container。
@Override
public void service(com.jerry.catalina.coyote.Request req, com.jerry.catalina.coyote.Response res) throws Exception {
System.out.println("CoyoteAdapter.service 开始处理请求");
// 生成HttpServletRequest对象
Request request = (Request) req.getNote(ADAPTER_NOTES);
Response response = (Response) res.getNote(ADAPTER_NOTES);
if (request == null) {
} else {
}
boolean postParseSuccess = false;
// 转换请求对象,parse成功后,开始调用Container
postParseSuccess = postParseRequest(req, request, res, response);
if (postParseSuccess) {
// Calling the container
// todo 待完成相应的部分
// connector.getService().getContainer().getPipeline().getFirst().invoke(request, response);
System.out.println("待完成 pipeline");
ByteChunk outputChunk = new ByteChunk();
String info = respInfo();
outputChunk.append(info.getBytes(), 0, info.length());
res.getOutputBuffer().doWrite(outputChunk, res);
}
}