Search in sources :

Example 1 with HealthCheckProcessor

use of io.questdb.cutlass.http.processors.HealthCheckProcessor in project questdb by bluestreak01.

the class IODispatcherTest method testMaxConnections.

@Test
public void testMaxConnections() throws Exception {
    LOG.info().$("started maxConnections").$();
    assertMemoryLeak(() -> {
        HttpServerConfiguration httpServerConfiguration = new DefaultHttpServerConfiguration();
        final int listenBackLog = 10;
        final int activeConnectionLimit = 5;
        final int nExcessConnections = 20;
        AtomicInteger openCount = new AtomicInteger(0);
        AtomicInteger closeCount = new AtomicInteger(0);
        final IODispatcherConfiguration configuration = new DefaultIODispatcherConfiguration() {

            @Override
            public int getActiveConnectionLimit() {
                return activeConnectionLimit;
            }

            @Override
            public int getListenBacklog() {
                return listenBackLog;
            }

            @Override
            public long getQueuedConnectionTimeout() {
                return 300_000;
            }
        };
        try (IODispatcher<HttpConnectionContext> dispatcher = IODispatchers.create(configuration, new IOContextFactory<HttpConnectionContext>() {

            @SuppressWarnings("resource")
            @Override
            public HttpConnectionContext newInstance(long fd, IODispatcher<HttpConnectionContext> dispatcher1) {
                openCount.incrementAndGet();
                return new HttpConnectionContext(httpServerConfiguration.getHttpContextConfiguration()) {

                    @Override
                    public void close() {
                        closeCount.incrementAndGet();
                        super.close();
                    }
                }.of(fd, dispatcher1);
            }
        })) {
            HttpRequestProcessorSelector selector = new HttpRequestProcessorSelector() {

                @Override
                public HttpRequestProcessor select(CharSequence url) {
                    return null;
                }

                @Override
                public HttpRequestProcessor getDefaultProcessor() {
                    return new HealthCheckProcessor();
                }

                @Override
                public void close() {
                }
            };
            AtomicBoolean serverRunning = new AtomicBoolean(true);
            SOCountDownLatch serverHaltLatch = new SOCountDownLatch(1);
            new Thread(() -> {
                try {
                    do {
                        dispatcher.run(0);
                        dispatcher.processIOQueue((operation, context) -> context.handleClientOperation(operation, selector, EmptyRescheduleContext));
                    } while (serverRunning.get());
                } finally {
                    serverHaltLatch.countDown();
                }
            }).start();
            LongList openFds = new LongList();
            LongHashSet closedFds = new LongHashSet();
            final long sockAddr = Net.sockaddr("127.0.0.1", 9001);
            final long buf = Unsafe.malloc(4096, MemoryTag.NATIVE_DEFAULT);
            final int N = activeConnectionLimit + listenBackLog;
            try {
                for (int i = 0; i < N; i++) {
                    long fd = Net.socketTcp(true);
                    TestUtils.assertConnect(fd, sockAddr);
                    openFds.add(fd);
                }
                // let dispatcher catchup
                long startNanos = System.nanoTime();
                while (dispatcher.isListening()) {
                    long endNanos = System.nanoTime();
                    if (TimeUnit.NANOSECONDS.toSeconds(endNanos - startNanos) > 30) {
                        Assert.fail("Timed out waiting for despatcher to stop listening");
                    }
                    LockSupport.parkNanos(1);
                }
                final String request = "GET /status?x=1&a=%26b&c&d=x HTTP/1.1\r\n" + "Host: localhost:9000\r\n" + "Connection: keep-alive\r\n" + "Cache-Control: max-age=0\r\n" + "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8\r\n" + "User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.48 Safari/537.36\r\n" + "Accept-Encoding: gzip,deflate,sdch\r\n" + "Accept-Language: en-US,en;q=0.8\r\n" + "Cookie: textwrapon=false; textautoformat=false; wysiwyg=textarea\r\n" + "\r\n";
                long mem = TestUtils.toMemory(request);
                // Active connection limit is reached and backlog is full, check we get connection closed
                for (int i = 0; i < nExcessConnections; i++) {
                    long fd = Net.socketTcp(true);
                    if (fd > 0) {
                        int nSent = Net.send(fd, mem, request.length());
                        Assert.assertTrue(nSent < 0);
                        Net.close(fd);
                    }
                }
                try {
                    for (int i = 0; i < N; i++) {
                        if (i == activeConnectionLimit) {
                            for (int j = 0; j < activeConnectionLimit; j++) {
                                long fd = openFds.getQuick(j);
                                Net.close(fd);
                                closedFds.add(fd);
                            }
                        }
                        long fd = openFds.getQuick(i);
                        Assert.assertEquals(request.length(), Net.send(fd, mem, request.length()));
                        // ensure we have response from server
                        Assert.assertTrue(0 < Net.recv(fd, buf, 64));
                        if (i < activeConnectionLimit) {
                            // dont close any connections until the first connections have been processed and check that the dispatcher
                            // is not listening
                            Assert.assertFalse(dispatcher.isListening());
                        } else {
                            Net.close(fd);
                            closedFds.add(fd);
                        }
                    }
                } finally {
                    Unsafe.free(mem, request.length(), MemoryTag.NATIVE_DEFAULT);
                }
            } finally {
                for (int i = 0; i < openFds.size(); i++) {
                    long fd = openFds.getQuick(i);
                    if (!closedFds.contains(fd)) {
                        Net.close(fd);
                    }
                }
                Net.freeSockAddr(sockAddr);
                Unsafe.free(buf, 4096, MemoryTag.NATIVE_DEFAULT);
                Assert.assertFalse(configuration.getActiveConnectionLimit() < dispatcher.getConnectionCount());
                serverRunning.set(false);
                serverHaltLatch.await();
            }
        }
    });
}
Also used : IOOperation(io.questdb.network.IOOperation) DefaultIODispatcherConfiguration(io.questdb.network.DefaultIODispatcherConfiguration) Log(io.questdb.log.Log) WorkerPoolConfiguration(io.questdb.mp.WorkerPoolConfiguration) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) TestUtils.assertMemoryLeak(io.questdb.test.tools.TestUtils.assertMemoryLeak) WorkerPool(io.questdb.mp.WorkerPool) Timestamps(io.questdb.std.datetime.microtime.Timestamps) TestLatchedCounterFunctionFactory(io.questdb.griffin.engine.functions.test.TestLatchedCounterFunctionFactory) QueryCache(io.questdb.cutlass.http.processors.QueryCache) io.questdb.std(io.questdb.std) IODispatchers(io.questdb.network.IODispatchers) CyclicBarrier(java.util.concurrent.CyclicBarrier) SOCountDownLatch(io.questdb.mp.SOCountDownLatch) LockSupport(java.util.concurrent.locks.LockSupport) StaticContentProcessor(io.questdb.cutlass.http.processors.StaticContentProcessor) CountDownLatch(java.util.concurrent.CountDownLatch) Path(io.questdb.std.str.Path) io.questdb.cairo(io.questdb.cairo) AllowAllCairoSecurityContext(io.questdb.cairo.security.AllowAllCairoSecurityContext) IORequestProcessor(io.questdb.network.IORequestProcessor) NotNull(org.jetbrains.annotations.NotNull) JsonQueryProcessor(io.questdb.cutlass.http.processors.JsonQueryProcessor) TextImportProcessor(io.questdb.cutlass.http.processors.TextImportProcessor) IODispatcher(io.questdb.network.IODispatcher) AbstractCharSequence(io.questdb.std.str.AbstractCharSequence) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) MPSequence(io.questdb.mp.MPSequence) IOContextFactory(io.questdb.network.IOContextFactory) NetUtils(io.questdb.cutlass.NetUtils) SqlException(io.questdb.griffin.SqlException) SCSequence(io.questdb.mp.SCSequence) IOContext(io.questdb.network.IOContext) TestUtils(io.questdb.test.tools.TestUtils) SqlCompiler(io.questdb.griffin.SqlCompiler) LogFactory(io.questdb.log.LogFactory) Metrics(io.questdb.Metrics) HealthCheckProcessor(io.questdb.cutlass.http.processors.HealthCheckProcessor) NetworkFacadeImpl(io.questdb.network.NetworkFacadeImpl) SqlExecutionContextImpl(io.questdb.griffin.SqlExecutionContextImpl) NetworkFacade(io.questdb.network.NetworkFacade) RingQueue(io.questdb.mp.RingQueue) PeerDisconnectedException(io.questdb.network.PeerDisconnectedException) TimeUnit(java.util.concurrent.TimeUnit) SharedRandom(io.questdb.griffin.engine.functions.rnd.SharedRandom) AtomicLong(java.util.concurrent.atomic.AtomicLong) PeerIsSlowToReadException(io.questdb.network.PeerIsSlowToReadException) StringSink(io.questdb.std.str.StringSink) Net(io.questdb.network.Net) MillisecondClock(io.questdb.std.datetime.millitime.MillisecondClock) IODispatcherConfiguration(io.questdb.network.IODispatcherConfiguration) org.junit(org.junit) SqlExecutionContext(io.questdb.griffin.SqlExecutionContext) TemporaryFolder(org.junit.rules.TemporaryFolder) ByteSequence(io.questdb.std.str.ByteSequence) InputStream(java.io.InputStream) DefaultIODispatcherConfiguration(io.questdb.network.DefaultIODispatcherConfiguration) IODispatcherConfiguration(io.questdb.network.IODispatcherConfiguration) AbstractCharSequence(io.questdb.std.str.AbstractCharSequence) SOCountDownLatch(io.questdb.mp.SOCountDownLatch) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) DefaultIODispatcherConfiguration(io.questdb.network.DefaultIODispatcherConfiguration) HealthCheckProcessor(io.questdb.cutlass.http.processors.HealthCheckProcessor)

Aggregations

Metrics (io.questdb.Metrics)1 io.questdb.cairo (io.questdb.cairo)1 AllowAllCairoSecurityContext (io.questdb.cairo.security.AllowAllCairoSecurityContext)1 NetUtils (io.questdb.cutlass.NetUtils)1 HealthCheckProcessor (io.questdb.cutlass.http.processors.HealthCheckProcessor)1 JsonQueryProcessor (io.questdb.cutlass.http.processors.JsonQueryProcessor)1 QueryCache (io.questdb.cutlass.http.processors.QueryCache)1 StaticContentProcessor (io.questdb.cutlass.http.processors.StaticContentProcessor)1 TextImportProcessor (io.questdb.cutlass.http.processors.TextImportProcessor)1 SqlCompiler (io.questdb.griffin.SqlCompiler)1 SqlException (io.questdb.griffin.SqlException)1 SqlExecutionContext (io.questdb.griffin.SqlExecutionContext)1 SqlExecutionContextImpl (io.questdb.griffin.SqlExecutionContextImpl)1 SharedRandom (io.questdb.griffin.engine.functions.rnd.SharedRandom)1 TestLatchedCounterFunctionFactory (io.questdb.griffin.engine.functions.test.TestLatchedCounterFunctionFactory)1 Log (io.questdb.log.Log)1 LogFactory (io.questdb.log.LogFactory)1 MPSequence (io.questdb.mp.MPSequence)1 RingQueue (io.questdb.mp.RingQueue)1 SCSequence (io.questdb.mp.SCSequence)1