Search in sources :

Example 1 with HttpApiRequest

use of com.bluenimble.platform.plugins.inbound.http.impl.HttpApiRequest in project serverless by bluenimble.

the class JettyPlugin method init.

@Override
public void init(final ApiServer server) throws Exception {
    Log.setLog(new JettyLogger(this));
    // load favicon
    InputStream favicon = null;
    try {
        favicon = new FileInputStream(new File(home, FavIcon));
        FavIconContent = IOUtils.toByteArray(favicon);
    } finally {
        IOUtils.closeQuietly(favicon);
    }
    Integer poolIdleTimeout = Json.getInteger(pool, Pool.IdleTimeout, 300);
    /*
		It is very important to limit the task queue of Jetty. By default, the queue is unbounded! As a result, 
		if under high load in excess of the processing power of the webapp, jetty will keep a lot of requests on the queue. 
		Even after the load has stopped, Jetty will appear to have stopped responding to new requests as it still has lots of requests on 
		the queue to handle.
		
		For a high reliability system, it should reject the excess requests immediately (fail fast) by using a queue with 
		a bounded capability. The capability (maximum queue length) should be calculated according to the "no-response" time tolerable. 
		For example, if the webapp can handle 100 requests per second, and if you can allow it one minute to recover from excessive high load, 
		you can set the queue capability to 60*100=6000. If it is set too low, it will reject requests too soon and can't handle normal load 
		spike.
		
		Below is a sample configuration:
		
		<Configure id="Server" class="org.eclipse.jetty.server.Server">
		    <Set name="ThreadPool">
		      <New class="org.eclipse.jetty.util.thread.QueuedThreadPool">
		        <!-- specify a bounded queue -->
		        <Arg>
		           <New class="java.util.concurrent.ArrayBlockingQueue">
		              <Arg type="int">6000</Arg>
		           </New>
		      </Arg>
		        <Set name="minThreads">10</Set>
		        <Set name="maxThreads">200</Set>
		        <Set name="detailedDump">false</Set>
		      </New>
		    </Set>
		</Configure>
		Configure the number of threads according to the webapp. 
		That is, how many threads it needs in order to achieve the best performance. 
		Configure with mind to limiting memory usage maximum available. Typically >50 and <500.
		 */
    int capacity = server.weight() + 2;
    QueuedThreadPool tp = new QueuedThreadPool(capacity, capacity, poolIdleTimeout * 1000, new ArrayBlockingQueue<Runnable>(capacity * 2));
    tp.setDetailedDump(false);
    tp.setThreadsPriority(Thread.NORM_PRIORITY);
    httpServer = new Server(tp);
    ServerConnector connector = new ServerConnector(httpServer);
    connector.setPort(port);
    connector.setIdleTimeout(idleTimeout * 1000);
    httpServer.addConnector(connector);
    if (ssl != null && !Lang.isNullOrEmpty(ssl.getString(Ssl.Keystore)) && !Lang.isNullOrEmpty(ssl.getString(Ssl.Password))) {
        HttpConfiguration https = new HttpConfiguration();
        https.addCustomizer(new SecureRequestCustomizer());
        SslContextFactory sslContextFactory = new SslContextFactory();
        sslContextFactory.setKeyStorePath(new File(ssl.getString(Ssl.Keystore)).getAbsolutePath());
        sslContextFactory.setKeyStorePassword(Json.getString(ssl, Ssl.Password));
        sslContextFactory.setKeyManagerPassword(Json.getString(ssl, Ssl.StorePassword, Json.getString(ssl, Ssl.Password)));
        sslContextFactory.setKeyStoreType(Json.getString(ssl, Ssl.StoreType, "JKS"));
        String[] aCiphers = null;
        // include ciphers
        JsonArray ciphers = Json.getArray(Json.getObject(ssl, Ssl.ciphers.class.getSimpleName()), Ssl.ciphers.Include);
        if (ciphers != null && !ciphers.isEmpty()) {
            aCiphers = new String[ciphers.count()];
            for (int i = 0; i < ciphers.count(); i++) {
                aCiphers[i] = (String) ciphers.get(i);
            }
            sslContextFactory.setIncludeCipherSuites(aCiphers);
        }
        // exclude ciphers
        ciphers = Json.getArray(Json.getObject(ssl, Ssl.ciphers.class.getSimpleName()), Ssl.ciphers.Exclude);
        if (ciphers != null && !ciphers.isEmpty()) {
            aCiphers = new String[ciphers.count()];
            for (int i = 0; i < ciphers.count(); i++) {
                aCiphers[i] = (String) ciphers.get(i);
            }
            sslContextFactory.setExcludeCipherSuites(aCiphers);
        }
        ServerConnector sslConnector = new ServerConnector(httpServer, new SslConnectionFactory(sslContextFactory, "http/1.1"), new HttpConnectionFactory(https));
        int sslPort = Json.getInteger(ssl, Ssl.Port, 443);
        sslConnector.setPort(sslPort);
        sslConnector.setIdleTimeout(Json.getInteger(ssl, Ssl.IdleTimeout, idleTimeout) * 1000);
        httpServer.addConnector(sslConnector);
    }
    for (Connector cn : httpServer.getConnectors()) {
        for (ConnectionFactory x : cn.getConnectionFactories()) {
            if (x instanceof HttpConnectionFactory) {
                ((HttpConnectionFactory) x).getHttpConfiguration().setSendServerVersion(false);
                ((HttpConnectionFactory) x).getHttpConfiguration().setSendXPoweredBy(false);
            }
        }
    }
    ServletContextHandler sContext = new ServletContextHandler(ServletContextHandler.NO_SESSIONS);
    sContext.setContextPath(context);
    if (gzip) {
        sContext.setGzipHandler(new GzipHandler());
    }
    httpServer.setHandler(sContext);
    ServletHolder apiHolder = new ServletHolder(new HttpServlet() {

        private static final long serialVersionUID = -4391155835460802144L;

        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            if (FavIconPath.equals(req.getRequestURI())) {
                resp.getOutputStream().write(FavIconContent);
                return;
            }
            execute(req, resp);
        }

        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            execute(req, resp);
        }

        @Override
        protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            execute(req, resp);
        }

        @Override
        protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            execute(req, resp);
        }

        protected void execute(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            try {
                ApiRequest request = new HttpApiRequest(req, tracer());
                request.getNode().set(ApiRequest.Fields.Node.Id, server.id());
                request.getNode().set(ApiRequest.Fields.Node.Type, server.type());
                request.getNode().set(ApiRequest.Fields.Node.Version, server.version());
                server.execute(request, new HttpApiResponse(request.getNode(), request.getId(), resp), CodeExecutor.Mode.Async);
            } catch (Exception e) {
                throw new ServletException(e.getMessage(), e);
            }
        }
    });
    sContext.addServlet(apiHolder, Lang.SLASH + Lang.STAR);
    // cross origin
    FilterHolder holder = new FilterHolder(CORSFilter.class);
    holder.setName("CORS");
    holder.setInitParameter("cors.supportedMethods", "GET, POST, HEAD, PUT, DELETE, PATCH, OPTIONS");
    holder.setInitParameter("cors.exposedHeaders", "Accept,Authorization,Cache-Control,Content-Type,DNT,If-Modified-Since,Keep-Alive,Origin,User-Agent,X-Requested-With,BN-Execution-Time,BN-Node-Id,BN-Node-Type");
    sContext.addFilter(holder, "/*", EnumSet.of(DispatcherType.INCLUDE, DispatcherType.FORWARD, DispatcherType.REQUEST, DispatcherType.ERROR));
    // monitor
    if (monitor) {
        MBeanContainer mbContainer = new MBeanContainer(ManagementFactory.getPlatformMBeanServer());
        httpServer.addEventListener(mbContainer);
        httpServer.addBean(mbContainer);
        httpServer.addBean(Log.getLog());
    }
    // start server
    httpServer.start();
    httpServer.join();
}
Also used : ServerConnector(org.eclipse.jetty.server.ServerConnector) Connector(org.eclipse.jetty.server.Connector) FilterHolder(org.eclipse.jetty.servlet.FilterHolder) ApiServer(com.bluenimble.platform.server.ApiServer) Server(org.eclipse.jetty.server.Server) ServletHolder(org.eclipse.jetty.servlet.ServletHolder) HttpConfiguration(org.eclipse.jetty.server.HttpConfiguration) SslConnectionFactory(org.eclipse.jetty.server.SslConnectionFactory) ApiRequest(com.bluenimble.platform.api.ApiRequest) HttpApiRequest(com.bluenimble.platform.plugins.inbound.http.impl.HttpApiRequest) ServerConnector(org.eclipse.jetty.server.ServerConnector) HttpServletRequest(javax.servlet.http.HttpServletRequest) ServletException(javax.servlet.ServletException) HttpApiResponse(com.bluenimble.platform.plugins.inbound.http.impl.HttpApiResponse) SslContextFactory(org.eclipse.jetty.util.ssl.SslContextFactory) HttpConnectionFactory(org.eclipse.jetty.server.HttpConnectionFactory) SslConnectionFactory(org.eclipse.jetty.server.SslConnectionFactory) ConnectionFactory(org.eclipse.jetty.server.ConnectionFactory) QueuedThreadPool(org.eclipse.jetty.util.thread.QueuedThreadPool) MBeanContainer(org.eclipse.jetty.jmx.MBeanContainer) HttpApiRequest(com.bluenimble.platform.plugins.inbound.http.impl.HttpApiRequest) SecureRequestCustomizer(org.eclipse.jetty.server.SecureRequestCustomizer) HttpConnectionFactory(org.eclipse.jetty.server.HttpConnectionFactory) FileInputStream(java.io.FileInputStream) InputStream(java.io.InputStream) HttpServlet(javax.servlet.http.HttpServlet) HttpServletResponse(javax.servlet.http.HttpServletResponse) IOException(java.io.IOException) FileInputStream(java.io.FileInputStream) ServletException(javax.servlet.ServletException) IOException(java.io.IOException) JsonArray(com.bluenimble.platform.json.JsonArray) GzipHandler(org.eclipse.jetty.server.handler.gzip.GzipHandler) ServletContextHandler(org.eclipse.jetty.servlet.ServletContextHandler) File(java.io.File)

Aggregations

ApiRequest (com.bluenimble.platform.api.ApiRequest)1 JsonArray (com.bluenimble.platform.json.JsonArray)1 HttpApiRequest (com.bluenimble.platform.plugins.inbound.http.impl.HttpApiRequest)1 HttpApiResponse (com.bluenimble.platform.plugins.inbound.http.impl.HttpApiResponse)1 ApiServer (com.bluenimble.platform.server.ApiServer)1 File (java.io.File)1 FileInputStream (java.io.FileInputStream)1 IOException (java.io.IOException)1 InputStream (java.io.InputStream)1 ServletException (javax.servlet.ServletException)1 HttpServlet (javax.servlet.http.HttpServlet)1 HttpServletRequest (javax.servlet.http.HttpServletRequest)1 HttpServletResponse (javax.servlet.http.HttpServletResponse)1 MBeanContainer (org.eclipse.jetty.jmx.MBeanContainer)1 ConnectionFactory (org.eclipse.jetty.server.ConnectionFactory)1 Connector (org.eclipse.jetty.server.Connector)1 HttpConfiguration (org.eclipse.jetty.server.HttpConfiguration)1 HttpConnectionFactory (org.eclipse.jetty.server.HttpConnectionFactory)1 SecureRequestCustomizer (org.eclipse.jetty.server.SecureRequestCustomizer)1 Server (org.eclipse.jetty.server.Server)1