dubbo

Dubbo Rest HttpServer分析

2020-02-20  本文已影响0人  晴天哥_王志

TomcatHttpServer

public class TomcatHttpServer extends AbstractHttpServer {

    private static final Logger logger = LoggerFactory.getLogger(TomcatHttpServer.class);

    private final Tomcat tomcat;
    private final URL url;

    public TomcatHttpServer(URL url, final HttpHandler handler) {
        super(url, handler);
        this.url = url;

        // 绑定handler到DispatcherServlet对象当中
        DispatcherServlet.addHttpHandler(url.getPort(), handler);
        String baseDir = new File(System.getProperty("java.io.tmpdir")).getAbsolutePath();

        tomcat = new Tomcat();

        // 设置tomcat的目录和端口号
        tomcat.setBaseDir(baseDir);
        tomcat.setPort(url.getPort());

        // 设置tomcat的connector属性
        tomcat.getConnector().setProperty(
                "maxThreads", String.valueOf(url.getParameter(Constants.THREADS_KEY, Constants.DEFAULT_THREADS)));
        tomcat.getConnector().setProperty(
                "maxConnections", String.valueOf(url.getParameter(Constants.ACCEPTS_KEY, -1)));
        tomcat.getConnector().setProperty("URIEncoding", "UTF-8");
        tomcat.getConnector().setProperty("connectionTimeout", "60000");
        tomcat.getConnector().setProperty("maxKeepAliveRequests", "-1");
        tomcat.getConnector().setProtocol("org.apache.coyote.http11.Http11NioProtocol");

        // 设置Context属性
        Context context = tomcat.addContext("/", baseDir);

        // 绑定dispatcher属性到serverlet当中
        Tomcat.addServlet(context, "dispatcher", new DispatcherServlet());

        // 设置tomcat的servlet的mapping属性
        context.addServletMapping("/*", "dispatcher");

        // 添加servletContext到全局的ServletManager当中
        ServletManager.getInstance().addServletContext(url.getPort(), context.getServletContext());

        try {
            // 启动tomcat服务
            tomcat.start();
        } catch (LifecycleException e) {
            throw new IllegalStateException("Failed to start tomcat server at " + url.getAddress(), e);
        }
    }
}

JettyHttpServer

public class JettyHttpServer extends AbstractHttpServer {

    private static final Logger logger = LoggerFactory.getLogger(JettyHttpServer.class);

    private Server server;
    private URL url;

    public JettyHttpServer(URL url, final HttpHandler handler) {
        super(url, handler);
        this.url = url;
        Log.setLog(new StdErrLog());
        Log.getLog().setDebugEnabled(false);

        // 绑定handler到DispatcherServlet对象当中
        DispatcherServlet.addHttpHandler(url.getParameter(Constants.BIND_PORT_KEY, url.getPort()), handler);

        // 设置线程属性
        int threads = url.getParameter(Constants.THREADS_KEY, Constants.DEFAULT_THREADS);
        QueuedThreadPool threadPool = new QueuedThreadPool();
        threadPool.setDaemon(true);
        threadPool.setMaxThreads(threads);
        threadPool.setMinThreads(threads);

        // 设置connector对象属性
        SelectChannelConnector connector = new SelectChannelConnector();
        String bindIp = url.getParameter(Constants.BIND_IP_KEY, url.getHost());
        if (!url.isAnyHost() && NetUtils.isValidLocalHost(bindIp)) {
            connector.setHost(bindIp);
        }
        connector.setPort(url.getParameter(Constants.BIND_PORT_KEY, url.getPort()));

        // 创建server对象并绑定线程池和connector对象
        server = new Server();
        server.setThreadPool(threadPool);
        server.addConnector(connector);

        // 绑定servletMapping 到 ServletHandler
        ServletHandler servletHandler = new ServletHandler();
        ServletHolder servletHolder = servletHandler.addServletWithMapping(DispatcherServlet.class, "/*");
        servletHolder.setInitOrder(2);

        //  绑定context到server对象并绑定ServletHandler
        Context context = new Context(server, "/", Context.SESSIONS);
        context.setServletHandler(servletHandler);

        // 添加servletContext到全局的ServletManager当中
        ServletManager.getInstance().addServletContext(url.getParameter(Constants.BIND_PORT_KEY, url.getPort()), context.getServletContext());

        try {
            // 启动server
            server.start();
        } catch (Exception e) {
            throw new IllegalStateException("Failed to start jetty server on " + url.getParameter(Constants.BIND_IP_KEY) + ":" + url.getParameter(Constants.BIND_PORT_KEY) + ", cause: "
                    + e.getMessage(), e);
        }
    }
}

DubboHttpServer

public class DubboHttpServer extends BaseRestServer {
    //HttpServletDispatcher内包含resteasy的ServletContainerDispatcher
    private final HttpServletDispatcher dispatcher = new HttpServletDispatcher();
    // resteasy的ResteasyDeployment
    private final ResteasyDeployment deployment = new ResteasyDeployment();
    private HttpBinder httpBinder; // httpBinderApative
    private HttpServer httpServer;

    public DubboHttpServer(HttpBinder httpBinder) {
        this.httpBinder = httpBinder;
    }

    @Override
    protected void doStart(URL url) {
        // 绑定RestHandler到具体的server当中
        httpServer = httpBinder.bind(url, new RestHandler());

        // 获取serverletContext的上下文信息
        ServletContext servletContext = ServletManager.getInstance().getServletContext(url.getPort());
        if (servletContext == null) {
            servletContext = ServletManager.getInstance().getServletContext(ServletManager.EXTERNAL_SERVER_PORT);
        }
        if (servletContext == null) {
            throw new RpcException("No servlet context found. If you are using server='servlet', " +
                    "make sure that you've configured " + BootstrapListener.class.getName() + " in web.xml");
        }
        // 绑定deployment到servletContext当中,
        // servletContext为jettyHttpServer或TomcatHttpServer中servletContext
        servletContext.setAttribute(ResteasyDeployment.class.getName(), deployment);

        try {
            // 绑定HttpServer中servletContext到dispatcher当中
            dispatcher.init(new SimpleServletConfig(servletContext));
        } catch (ServletException e) {
            throw new RpcException(e);
        }
    }

    protected ResteasyDeployment getDeployment() {
        return deployment;
    }

    private class RestHandler implements HttpHandler {

        @Override
        public void handle(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
            RpcContext.getContext().setRemoteAddress(request.getRemoteAddr(), request.getRemotePort());
            // 执行真正的分发动作,由HttpServletDispatcher执行
            dispatcher.service(request, response);
        }
    }
}
public abstract class BaseRestServer implements RestServer {

    @Override
    public void start(URL url) {
        getDeployment().getMediaTypeMappings().put("json", "application/json");
        getDeployment().getMediaTypeMappings().put("xml", "text/xml");
        getDeployment().getProviderClasses().add(RpcContextFilter.class.getName());
        getDeployment().getProviderClasses().add(RpcExceptionMapper.class.getName());

        loadProviders(url.getParameter(Constants.EXTENSION_KEY, ""));

        doStart(url);
    }

    @Override
    public void deploy(Class resourceDef, Object resourceInstance, String contextPath) {
        if (StringUtils.isEmpty(contextPath)) {
            getDeployment().getRegistry().addResourceFactory(new DubboResourceFactory(resourceInstance, resourceDef));
        } else {
            getDeployment().getRegistry().addResourceFactory(new DubboResourceFactory(resourceInstance, resourceDef), contextPath);
        }
    }
}

RestProtocol

public class RestProtocol extends AbstractProxyProtocol {

    private static final int DEFAULT_PORT = 80;
    private final Map<String, RestServer> servers = new ConcurrentHashMap<String, RestServer>();
    private final RestServerFactory serverFactory = new RestServerFactory();
    private final List<ResteasyClient> clients = Collections.synchronizedList(new LinkedList<ResteasyClient>());

    private volatile ConnectionMonitor connectionMonitor;

    @Override
    protected <T> Runnable doExport(T impl, Class<T> type, URL url) throws RpcException {
        String addr = getAddr(url);
        Class implClass = (Class) StaticContext.getContext(Constants.SERVICE_IMPL_CLASS).get(url.getServiceKey());
        RestServer server = servers.get(addr);
        if (server == null) {
            server = serverFactory.createServer(url.getParameter(Constants.SERVER_KEY, "jetty"));
            server.start(url);
            servers.put(addr, server);
        }

        String contextPath = getContextPath(url);
        if ("servlet".equalsIgnoreCase(url.getParameter(Constants.SERVER_KEY, "jetty"))) {
            ServletContext servletContext = ServletManager.getInstance().getServletContext(ServletManager.EXTERNAL_SERVER_PORT);
            if (servletContext == null) {
                throw new RpcException("No servlet context found. Since you are using server='servlet', " +
                        "make sure that you've configured " + BootstrapListener.class.getName() + " in web.xml");
            }
            String webappPath = servletContext.getContextPath();
            if (StringUtils.isNotEmpty(webappPath)) {
                webappPath = webappPath.substring(1);
                if (!contextPath.startsWith(webappPath)) {
                    throw new RpcException("Since you are using server='servlet', " +
                            "make sure that the 'contextpath' property starts with the path of external webapp");
                }
                contextPath = contextPath.substring(webappPath.length());
                if (contextPath.startsWith("/")) {
                    contextPath = contextPath.substring(1);
                }
            }
        }

        final Class resourceDef = GetRestful.getRootResourceClass(implClass) != null ? implClass : type;
        // 部署对应的impl对象到server当中
        server.deploy(resourceDef, impl, contextPath);

        final RestServer s = server;
        return new Runnable() {
            @Override
            public void run() {
                // TODO due to dubbo's current architecture,
                // it will be called from registry protocol in the shutdown process and won't appear in logs
                s.undeploy(resourceDef);
            }
        };
    }
}
上一篇下一篇

猜你喜欢

热点阅读