美文网首页
tomcat源码分析(3) Connector 分析

tomcat源码分析(3) Connector 分析

作者: 全都是泡沫啦 | 来源:发表于2018-08-29 17:26 被阅读0次

    快速创建Connector测试类

    1.创建类名为TestConnector,执行main方法

    public class TestConnector {
        public static void main(String[] args) throws Exception {
            Connector connector = new Connector("HTTP/1.1");
            connector.setPort(8080);
            connector.init();//protocolHandler.init(); 这里主要是绑定8080端口的ServerSocketChannel
            /**
             * 替换init的Adapter初始化
             * adapter = new CoyoteAdapter(this); //连接Service的桥梁,通过他将request response 传入到webapps 的应用当中
             * protocolHandler.setAdapter(adapter);
             * Adapter是对读写io的数据与业务处理的适配
             */
            connector.getProtocolHandler().setAdapter(new Adapter() {
                @Override
                public void service(Request req, Response res) throws Exception {
                    res.setStatus(200);
                    res.doWrite(ByteBuffer.wrap("Hello World...".getBytes()));
                }
    
                @Override
                public boolean prepare(Request req, Response res) throws Exception {
                    return false;
                }
    
                @Override
                public boolean asyncDispatch(Request req, Response res, SocketEvent status) throws Exception {
                    return false;
                }
    
                @Override
                public void log(Request req, Response res, long time) {
                }
    
                @Override
                public void checkRecycled(Request req, Response res) {
                }
    
                @Override
                public String getDomain() {
                    return null;
                }
            });
            connector.start();
            System.in.read();
        }
    }
    
    

    2.浏览器输入http://127.0.0.1:8080/ 页面返回Hello World...
    3.Connector的构造函数中使用setProtocol进行协议的选择创建ProtocolHandler

    public Connector(String protocol) {
            setProtocol(protocol);
            // Instantiate protocol handler
            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;
            }
            //省略非关键代码....
    }
    public void setProtocol(String protocol) {
        boolean aprConnector = AprLifecycleListener.isAprAvailable() &&
                AprLifecycleListener.getUseAprConnector();
        if ("HTTP/1.1".equals(protocol) || protocol == null) {
            if (aprConnector) {
                setProtocolHandlerClassName("org.apache.coyote.http11.Http11AprProtocol");
            } else {
                setProtocolHandlerClassName("org.apache.coyote.http11.Http11NioProtocol");
            }
        } else if ("AJP/1.3".equals(protocol)) {
            if (aprConnector) {
                setProtocolHandlerClassName("org.apache.coyote.ajp.AjpAprProtocol");
            } else {
                setProtocolHandlerClassName("org.apache.coyote.ajp.AjpNioProtocol");
            }
        } else {
            setProtocolHandlerClassName(protocol);
        }
    }
    
    

    4.connector.init();

    @Override
    protected void initInternal() throws LifecycleException {
        ...  
        adapter = new CoyoteAdapter(this);
        protocolHandler.setAdapter(adapter);
        ...
        try {
            protocolHandler.init();//bind() serverSock.socket().bind(addr,getAcceptCount());
        } catch (Exception e) {
            throw new LifecycleException(
                    sm.getString("coyoteConnector.protocolHandlerInitializationFailed"), e);
        }
        ...
    }
    

    5.connector.start();

    @Override
    protected void startInternal() throws LifecycleException {
        ...
        try {
            protocolHandler.start();//开始接受tcp请求连接
        } catch (Exception e) {
            throw new LifecycleException(
                    sm.getString("coyoteConnector.protocolHandlerStartFailed"), e);
        }
        ...
    }
    

    6.通过上述步骤中我们发现connector 中大部分操作都是基于protocolHandler (默认不启动apr我们使用的是org.apache.coyote.http11.Http11NioProtocol)。我们脑子里会出现大体的流程 protocolHandler 创建服务器套接字并将其绑定到指定的本地8080端口,侦听并接受到此套接字的连接,将读取的数据封装为request 创建response,传入到Adapter 进行业务处理(写入响应码:200 写入body:Hello World...)将response中通过socket返回客户端。这个只是可以简单的描述流程,这个过程中涉及到nio的实现,线程模型的设计,长短连接的控制,如何通过优化提高并发,会在后续分析Http11NioProtocol中设计

    7.补充发一下张图片(http1.1默认是开始keepalive) 访问tomcat抓包的内容.png

    注意:Wireshark中npcap可以进行抓取127.0.0.1的数据

    相关文章

      网友评论

          本文标题:tomcat源码分析(3) Connector 分析

          本文链接:https://www.haomeiwen.com/subject/adhkwftx.html