/******************************************************************************* * Copyright 2011 Netflix * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ package com.netflix.astyanax.connectionpool.impl; import java.util.List; import java.util.Map; import java.util.Random; import java.util.TreeMap; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicLong; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.base.Function; import com.google.common.base.Suppliers; import com.google.common.collect.Lists; import com.netflix.astyanax.connectionpool.ConnectionPool; import com.netflix.astyanax.connectionpool.ConnectionPoolMonitor; import com.netflix.astyanax.connectionpool.Host; import com.netflix.astyanax.connectionpool.HostConnectionPool; import com.netflix.astyanax.connectionpool.LatencyScoreStrategy.Instance; import com.netflix.astyanax.connectionpool.LatencyScoreStrategy.Listener; import com.netflix.astyanax.connectionpool.exceptions.BadRequestException; import com.netflix.astyanax.connectionpool.exceptions.ConnectionAbortedException; import com.netflix.astyanax.connectionpool.exceptions.ConnectionException; import com.netflix.astyanax.connectionpool.exceptions.HostDownException; import com.netflix.astyanax.connectionpool.exceptions.OperationException; import com.netflix.astyanax.connectionpool.exceptions.OperationTimeoutException; import com.netflix.astyanax.connectionpool.exceptions.PoolTimeoutException; import com.netflix.astyanax.connectionpool.exceptions.TimeoutException; import com.netflix.astyanax.connectionpool.exceptions.TokenRangeOfflineException; import com.netflix.astyanax.connectionpool.exceptions.TransportException; import com.netflix.astyanax.connectionpool.exceptions.UnknownException; import com.netflix.astyanax.connectionpool.impl.ConnectionPoolConfigurationImpl; import com.netflix.astyanax.connectionpool.impl.RoundRobinConnectionPoolImpl; import com.netflix.astyanax.retry.RunOnce; import com.netflix.astyanax.test.ProbabalisticFunction; import com.netflix.astyanax.test.TestClient; import com.netflix.astyanax.test.TestConnectionFactory; import com.netflix.astyanax.test.TestConstants; import com.netflix.astyanax.test.TestDriver; import com.netflix.astyanax.test.TestHostType; import com.netflix.astyanax.test.TestOperation; public class Stress { private static Logger LOG = LoggerFactory.getLogger(Stress.class); /** * @param args */ public static void main(String[] args) { ConnectionPoolConfigurationImpl config; config = new ConnectionPoolConfigurationImpl(TestConstants.CLUSTER_NAME + "_" + TestConstants.KEYSPACE_NAME); // config.setMaxConns(100); config.setMaxFailoverCount(-1); config.setMaxTimeoutWhenExhausted(1000); config.setMaxConnsPerHost(25); config.setInitConnsPerHost(0); config.setTimeoutWindow(5000); config.setMaxTimeoutCount(10); config.setRetrySuspendWindow(5000); config.setLatencyScoreStrategy(new EmaLatencyScoreStrategyImpl(1000, 0, 20)); // config.setRetryBackoffStrategy(new // ExponentialRetryBackoffStrategy(20, 1000, 2000)); final ConnectionPoolMonitor monitor = new CountingConnectionPoolMonitor(); TestConnectionFactory factory = new TestConnectionFactory(config, monitor); final ConnectionPool<TestClient> pool = new RoundRobinConnectionPoolImpl<TestClient>(config, factory, monitor); pool.start(); final List<Host> hosts = Lists.newArrayList( new Host("127.0.0.1", TestHostType.GOOD_FAST.ordinal()), new Host("127.0.0.2", TestHostType.GOOD_FAST.ordinal()), new Host("127.0.0.3", TestHostType.GOOD_FAST.ordinal()), new Host("127.0.0.4", TestHostType.GOOD_FAST.ordinal()), new Host("127.0.0.5", TestHostType.GOOD_FAST.ordinal()), new Host("127.0.0.6", TestHostType.GOOD_FAST.ordinal()), new Host("127.0.0.7", TestHostType.GOOD_FAST.ordinal()), new Host("127.0.0.8", TestHostType.GOOD_FAST.ordinal()), // new Host("127.0.0.9", TestHostType.GOOD_SLOW.ordinal()), new Host("127.0.0.10", TestHostType.SWAP_EVERY_200.ordinal()), new Host("127.0.0.11", TestHostType.ALTERNATING_SOCKET_TIMEOUT_200.ordinal()) // new Host("127.0.0.12", TestHostType.ALTERNATING_SOCKET_TIMEOUT_200.ordinal()), // new Host("127.0.0.13", TestHostType.CONNECT_FAIL_FIRST_TWO.ordinal()) ); for (Host host : hosts) { pool.addHost(host, true); } final Map<Host, AtomicLong> counts = new TreeMap<Host, AtomicLong>(); for (HostConnectionPool<TestClient> p : pool.getActivePools()) { counts.put(p.getHost(), new AtomicLong()); } System.out.println(monitor.toString()); final AtomicBoolean timeoutsEnabled = new AtomicBoolean(false); final AtomicLong lastOperationCount = new AtomicLong(); EmaLatencyScoreStrategyImpl latency = new EmaLatencyScoreStrategyImpl(1000, 0, 10); final Instance sampler = latency.createInstance(); latency.start(new Listener() { @Override public void onUpdate() { } @Override public void onReset() { } }); final Function<TestDriver, Void> function = new ProbabalisticFunction.Builder<TestDriver, Void>() .withDefault(new Function<TestDriver, Void>() { public Void apply(TestDriver arg0) { return null; } }) .withAlways(new Runnable() { public void run() { think(10, 30); } }) // .withProbability(0.0001, new Function<TestDriver, Void>() { // public Void apply(@Nullable TestDriver arg0) { // if (timeoutsEnabled.get()) { // think(1100, 0); // throw new RuntimeException(new TimeoutException("TimeoutException")); // } // return null; // } // }) // .withProbability(0.0001, new Function<TestDriver, Void>() { // public Void apply(@Nullable TestDriver arg0) { // throw new RuntimeException(new UnknownException(new Exception("UnknownExceptionDescription"))); // } // }) // .withProbability(0.0001, new Function<TestDriver, Void>() { // public Void apply(@Nullable TestDriver arg0) { // think(1000, 0); // throw new RuntimeException(new OperationTimeoutException("OperationTimeoutException")); // } // }) // .withProbability(0.0001, new Function<TestDriver, Void>() { // public Void apply(@Nullable TestDriver arg0) { // throw new RuntimeException(new HostDownException("HostDownException")); // } // }) // .withProbability(0.01, new Function<TestDriver, Void>() { // public Void apply(@Nullable TestDriver arg0) { // throw new RuntimeException(new ConnectionAbortedException("ConnectionAbortedException")); // } // }) // .withProbability(0.0001, new Function<TestDriver, Void>() { // public Void apply(@Nullable TestDriver arg0) { // throw new RuntimeException(new BadRequestException("BadRequestException")); // } // }) // .withProbability(0.0001, new Function<TestDriver, Void>() { // public Void apply(@Nullable TestDriver arg0) { // throw new RuntimeException(new TokenRangeOfflineException("TokenRangeOfflineException")); // } // }) // .withProbability(0.0001, new Function<TestDriver, Void>() { // public Void apply(@Nullable TestDriver arg0) { // throw new RuntimeException(new TransportException("TransportException")); // } // }) .build(); final List<HostConnectionPool<TestClient>> hostPools = Lists.newArrayList(pool.getActivePools()); final TestDriver driver = new TestDriver.Builder() .withIterationCount(0) .withThreadCount(200) // .withFutures(100, TimeUnit.MILLISECONDS) .withCallsPerSecondSupplier(Suppliers.ofInstance(200)) // .withFutures(100, TimeUnit.MILLISECONDS) .withCallback(new Function<TestDriver, Void>() { public Void apply(final TestDriver driver) { long startTime = System.nanoTime(); try { pool.executeWithFailover(new TestOperation() { public String execute(TestClient client) throws ConnectionException, OperationException { try { function.apply(driver); return null; } catch (RuntimeException e) { if (e.getCause() instanceof ConnectionException) throw (ConnectionException)e.getCause(); throw e; } } }, new RunOnce()); } catch (PoolTimeoutException e) { LOG.info(e.getMessage()); } catch (ConnectionException e) { } finally { sampler.addSample((System.nanoTime() - startTime)/1000000); } return null; } }) // // Event to turn timeouts on/off // .withRecurringEvent(10, TimeUnit.SECONDS, new Function<TestDriver, Void>() { @Override public Void apply(TestDriver driver) { timeoutsEnabled.getAndSet(!timeoutsEnabled.get()); // LOG.info("Toggle timeouts " + timeoutsEnabled.get()); return null; } }) // // Print status information // .withRecurringEvent(1, TimeUnit.SECONDS, new Function<TestDriver, Void>() { @Override public Void apply(TestDriver driver) { long opCount = lastOperationCount.get(); lastOperationCount.set(driver.getOperationCount()); System.out.println("" + driver.getRuntime() + "," + sampler.getScore() + "," + (lastOperationCount.get() - opCount)); System.out.println(monitor.toString()); System.out.println(monitor.toString()); for (HostConnectionPool<TestClient> host : pool.getPools()) { System.out.println(" " + host.toString()); } return null; } }) // // Remove a random host // .withRecurringEvent(10, TimeUnit.SECONDS, new Function<TestDriver, Void>() { @Override public Void apply(TestDriver driver) { // System.out.println("Latency: " + sampler.getScore()); // // List<Host> newHosts = Lists.newArrayList(hosts); // newHosts.remove(new Random().nextInt(hosts.size())); // pool.setHosts(newHosts); // // System.out.println(monitor.toString()); // for (HostConnectionPool<TestClient> host : pool.getPools()) { // System.out.println(" " + host.toString()); // } return null; } }) .build(); driver.start(); try { driver.await(); } catch (InterruptedException e) { } } private static void think(int min, int max) { try { if (max > min) { Thread.sleep(min + new Random().nextInt(max - min)); } else { Thread.sleep(min); } } catch (InterruptedException e) { } } }