• tomcat源码解析三


    分析http请求的路径分析,之前说过socket完成对端口的监听:

    先看下connector:

     public Connector(String protocol) {...
            try {
                Class<?> clazz = Class.forName(protocolHandlerClassName);//默认的protocolHandler为String protocolHandlerClassName ="org.apache.coyote.http11.Http11NioProtocol";...
    startInternal(){...
        protocolHandler.start();
    ...}
    AbstractProtocol.start(){...
        endpoint.start();
    ...}
    

    查看EndPoint,java8后使用的是NioEndpoint:查看ctrl+F12可以看到有相关的几个内部类Acceptor(接受请求)、Poller(从请求池中获取请求)、SocketProcessor(解析请求)

    Acceptor.run(){...     
         socket = serverSock.accept();// Accept the next incoming connection from the server...
        if (running && !paused) {
             if (!setSocketOptions(socket)) {// setSocketOptions() will hand the socket off to an appropriate processor if successful
    ...}
    setSocketOptions(){
        if (isSSLEnabled()) {
             channel = new SecureNioChannel(socket, bufhandler, selectorPool, this);//https
           } else {
             channel = new NioChannel(socket, bufhandler);//http1.1
           }...
        getPoller0().register(channel);
    }
    //Registers a newly created socket with the poller.
    public void register(final NioChannel socket) {
          socket.setPoller(this);
          NioSocketWrapper ka = new NioSocketWrapper(socket, NioEndpoint.this);
          socket.setSocketWrapper(ka);
          ka.setPoller(this);
          ka.setReadTimeout(getSocketProperties().getSoTimeout());
          ka.setWriteTimeout(getSocketProperties().getSoTimeout());
          ka.setKeepAliveLeft(NioEndpoint.this.getMaxKeepAliveRequests());
          ka.setSecure(isSSLEnabled());
          ka.setReadTimeout(getConnectionTimeout());
          ka.setWriteTimeout(getConnectionTimeout());
          PollerEvent r = eventCache.pop();
          ka.interestOps(SelectionKey.OP_READ);//this is what OP_REGISTER turns into.
          if ( r==null) r = new PollerEvent(socket,ka,OP_REGISTER);
          else r.reset(socket,ka,OP_REGISTER);
          addEvent(r);//注册当前channel封装成pollerEvent进队列
    }
    

    查看Poller

    run() {...
         events();//遍历pollerEvent依次调用pollerEvent的run将socket注册进selector(选择processor)中...
         Iterator<SelectionKey> iterator = keyCount > 0 ? selector.selectedKeys().iterator() : null;
            // Walk through the collection of ready keys and dispatch any active event.
            while (iterator != null && iterator.hasNext()) {
               SelectionKey sk = iterator.next();
               NioSocketWrapper attachment = (NioSocketWrapper)sk.attachment();
               // Attachment may be null if another thread has called cancelledKey()
                  if (attachment == null) {
                      iterator.remove();
                  } else {
                      iterator.remove();
                      processKey(sk, attachment);
    ...}
    processKey{...
        if ( attachment.getSendfileData() != null ) {...
           processSendfile(sk,attachment, false);
            if (sk.isReadable()) {// Read goes before writec
            if (!processSocket(attachment, SocketEvent.OPEN_READ, true)) {
        ...} 
    ...}
    processSocket{...
        sc = createSocketProcessor(socketWrapper, event);//创建socketProcessor给coyotaAdapter用 默认是Http11Processor
        Executor executor = getExecutor();
                if (dispatch && executor != null) {
                    executor.execute(sc);
    ...}
    AbstractHttp11Protocol.createProcessor(){...
            Http11Processor processor = new Http11Processor(this, getEndpoint());
            processor.setAdapter(getAdapter());//设置Adapter
            processor.setMaxKeepAliveRequests(getMaxKeepAliveRequests());
            processor.setConnectionUploadTimeout(getConnectionUploadTimeout());
            processor.setDisableUploadTimeout(getDisableUploadTimeout());
            processor.setRestrictedUserAgents(getRestrictedUserAgents());
            processor.setMaxSavePostSize(getMaxSavePostSize());
            return processor;
    ...}
    

    查看CoyoteAdapter

    service{...
            Request request = (Request) req.getNote(ADAPTER_NOTES);
            Response response = (Response) res.getNote(ADAPTER_NOTES);
            if (request == null) {
                // Create objects
                request = connector.createRequest();
                request.setCoyoteRequest(req);
                response = connector.createResponse();
                response.setCoyoteResponse(res);
    
                // Link objects
                request.setResponse(response);
                response.setRequest(request);...
             try {
                // Parse and set Catalina and configuration specific request parameters
                postParseSuccess = postParseRequest(req, request, res, response);//在map中解析业务请求
                if (postParseSuccess) {
                    //check valves if we support async
                    request.setAsyncSupported(
                            connector.getService().getContainer().getPipeline().isAsyncSupported());
                    // Calling the container
                    connector.getService().getContainer().getPipeline().getFirst().invoke(
                            request, response);//开始转向Cotainer Engine 每个容器有一个管道如@1,维护Valve(connector.getService().getContainer().getPipeline().getFirst())
                }
    ...}
    @1
    StandardEngine.startInternal{...
        // Start the Valves in our pipeline (including the basic), if any
            if (pipeline instanceof Lifecycle) {
                ((Lifecycle) pipeline).start();
            }
    ...}
    

    查看StandardEngineValve:

    //责任链模式
    invoke(){...
        // Select the Host to be used for this Request
        Host host = request.getHost();...
        // Ask this Host to process this request
            host.getPipeline().getFirst().invoke(request, response);
    ...}
    

    查看StandardHostValve:

    invoke(Request request, Response response){...
        // Select the Context to be used for this Request
        Context context = request.getContext();
        if (context == null) {
            return;
        }
        if (request.isAsyncSupported()) {
            request.setAsyncSupported(context.getPipeline().isAsyncSupported());
        }
    ...}
    

    查看StandardWrapperValve:

    invoke(Request request, Response response){...
            // Allocate a servlet instance to process this request
            try {
                if (!unavailable) {
                    servlet = wrapper.allocate();//实例化servlet
                }...
            MessageBytes requestPathMB = request.getRequestPathMB();
            DispatcherType dispatcherType = DispatcherType.REQUEST;
            if (request.getDispatcherType()==DispatcherType.ASYNC) dispatcherType = DispatcherType.ASYNC;
            request.setAttribute(Globals.DISPATCHER_TYPE_ATTR,dispatcherType);
            request.setAttribute(Globals.DISPATCHER_REQUEST_PATH_ATTR,
                    requestPathMB);
            // Create the filter chain for this request
            ApplicationFilterChain filterChain =
                    ApplicationFilterFactory.createFilterChain(request, wrapper, servlet);//创建过滤链...
            filterChain.doFilter(request.getRequest(), response.getResponse());//执行过滤链
            finally {
                // Release the filter chain (if any) for this request
                if (filterChain != null) {
                    filterChain.release();
                }
                // Deallocate the allocated servlet instance
                try {
                    if (servlet != null) {
                        wrapper.deallocate(servlet);
                    }
    ...}
    
  • 相关阅读:
    [图解算法] 最短路径算法之 “Dijikstra”
    [前端随笔][CSS] 伪类的应用
    [前端随笔][JavaScript] 实现原生的事件监听<Vue原理>
    [图解算法] 最短路径算法之 “Floyd”
    [前端随笔][JavaScript][自制数据可视化] “中国地图”
    [前端随笔][JavaScript] 懒加载的实现(上划一次加载一部分)
    [前端随笔][CSS] 制作一个加载动画 即帖即用
    ThinkPHP下隐藏index.php以及URL伪静态
    PHP基础语法3
    PHP基础语法2
  • 原文地址:https://www.cnblogs.com/leifonlyone/p/12766267.html
Copyright © 2020-2023  润新知