SelectorManager从本身的Selector数组中选择一个Selector来处理这个Channel,并创建一个任务Accept交给ManagedSelector,ManagedSelector在处理这个任务主要做了两步:
- 调用Selector#register把Channel注册到Selector上,拿到一个SelectionKey
_key = _channel.register(selector, SelectionKey.OP_ACCEPT, this);
- ,创建一个EndPoint和Connection,并跟这个SelectionKey(Channel)绑定
private void createEndPoint(SelectableChannel channel, SelectionKey selectionKey) throws IOException { //1. 创建EndPoint EndPoint endPoint = _selectorManager.newEndPoint(channel, this, selectionKey); //2. 创建Connection Connection connection = _selectorManager.newConnection(channel, endPoint, selectionKey.attachment()); //3. 把EndPoint、Connection和SelectionKey绑在一起 endPoint.setConnection(connection); selectionKey.attach(endPoint); }
就好像到餐厅吃饭:
- 先点菜(注册I/O事件)
- 服务员(ManagedSelector)给你一个单子(SelectionKey)
- 等菜做好了(I/O事件到了)
- 服务员根据单子就知道是哪桌点了这个菜,于是喊一嗓子某某桌的菜做好了(调用了
getEndPoint().fillInterested(_readCallback);
- 绑定在SelectionKey上的EndPoint的方法)
ManagedSelector并没有调用直接EndPoint的方法去处理数据,而是通过调用EndPoint的方法返回一个Runnable,然后把这个Runnable扔给线程池执行,这个Runnable才会去真正读数据和处理请求。
Connection
这个Runnable是EndPoint的一个内部类,它会调用Connection的回调方法来处理请求。Jetty的Connection组件类比就是Tomcat的Processor,负责具体协议的解析,得到Request对象,并调用Handler容器进行处理。下面我简单介绍一下它的具体实现类HttpConnection对请求和响应的处理过程。
请求处理:HttpConnection并不会主动向EndPoint读取数据,而是向在EndPoint中注册一堆回调方法:
getEndPoint().fillInterested(_readCallback);
告诉EndPoint,数据到了你就调我这些回调方法_readCallback吧,有点异步I/O的感觉,也就是说Jetty在应用层面模拟了异步I/O模型。
回调方法_readCallback里,会调用EndPoint的接口去读数据,读完后让HTTP解析器去解析字节流,HTTP解析器会将解析后的数据,包括请求行、请求头相关信息存到Request对象。
响应处理:Connection调用Handler进行业务处理,Handler会通过Response对象来操作响应流,向流里面写入数据,HttpConnection再通过EndPoint把数据写到Channel,这样一次响应就完成了。
Connector的工作流
1.Acceptor监听连接请求,当有连接请求到达时就接受连接,一个连接对应一个Channel,Acceptor将Channel交给ManagedSelector来处理
2.ManagedSelector把Channel注册到Selector上,并创建一个EndPoint和Connection跟这个Channel绑定,接着就不断地检测I/O事件
3.I/O事件到了就调用EndPoint的方法拿到一个Runnable,并扔给线程池执行
4.线程池中调度某个线程执行Runnable
5.Runnable执行时,调用回调函数,这个回调函数是Connection注册到EndPoint中的
6.回调函数内部实现,其实就是调用EndPoint的接口方法来读数据
7.Connection解析读到的数据,生成请求对象并交给Handler组件去处理
Handler
一个接口,有一堆实现类,Jetty的Connector组件调用这些接口来处理Servlet请求,我们先来看看这个接口定义成什么样子。
public interface Handler extends LifeCycle, Destroyable { // 处理请求的方法 public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException; // 每个Handler都关联一个Server组件,被Server管理 public void setServer(Server server); public Server getServer(); // 销毁方法相关的资源 public void destroy(); }