diff --git a/src/main/java/org/apache/solr/benchmarks/beans/Cluster.java b/src/main/java/org/apache/solr/benchmarks/beans/Cluster.java index 9d714f7a..da0e7b69 100644 --- a/src/main/java/org/apache/solr/benchmarks/beans/Cluster.java +++ b/src/main/java/org/apache/solr/benchmarks/beans/Cluster.java @@ -36,6 +36,9 @@ public class Cluster { @JsonProperty("external-solr-config") public ExternalSolrConfig externalSolrConfig; + @JsonProperty("clusterprops") + public String clusterpropsFilename; + @JsonProperty("provisioning-method") public String provisioningMethod; diff --git a/src/main/java/org/apache/solr/benchmarks/solrcloud/SolrCloud.java b/src/main/java/org/apache/solr/benchmarks/solrcloud/SolrCloud.java index 526e7f17..be098cd1 100644 --- a/src/main/java/org/apache/solr/benchmarks/solrcloud/SolrCloud.java +++ b/src/main/java/org/apache/solr/benchmarks/solrcloud/SolrCloud.java @@ -23,12 +23,14 @@ import java.io.InputStream; import java.io.OutputStream; import java.lang.invoke.MethodHandles; +import java.nio.charset.Charset; import java.util.*; import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; +import org.apache.zookeeper.CreateMode; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; @@ -94,6 +96,7 @@ public SolrCloud(Cluster cluster, String solrPackagePath) throws Exception { * @throws Exception */ public void init() throws Exception { + if ("local".equalsIgnoreCase(cluster.provisioningMethod)) { zookeeper = new LocalZookeeper(); int initValue = zookeeper.start(); @@ -102,6 +105,8 @@ public void init() throws Exception { throw new RuntimeException("Failed to start Zookeeper!"); } + setupClusterProps(); + ExecutorService executor = Executors.newFixedThreadPool(1, new ThreadFactoryBuilder().setNameFormat("nodestarter-threadpool").build()); //Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()/2+1, new ThreadFactoryBuilder().setNameFormat("nodestarter-threadpool").build()); @@ -175,6 +180,7 @@ public void init() throws Exception { System.out.println("Solr nodes: "+getSolrNodesFromTFState()); System.out.println("ZK node: "+getZkNodeFromTFState()); zookeeper = new GenericZookeeper(getZkNodeFromTFState()); + setupClusterProps(); for (String host: getSolrNodesFromTFState()) { nodes.add(new GenericSolrNode(host, cluster.terraformGCPConfig.get("user").toString())); } @@ -182,6 +188,7 @@ public void init() throws Exception { System.out.println("Solr nodes: "+getSolrNodesFromVagrant()); System.out.println("ZK node: "+getZkNodeFromVagrant()); zookeeper = new GenericZookeeper(getZkNodeFromVagrant()); + setupClusterProps(); for (String host: getSolrNodesFromVagrant()) { nodes.add(new GenericSolrNode(host, null)); // TODO fix username for vagrant } @@ -189,7 +196,7 @@ public void init() throws Exception { log.info("ZK node: " + cluster.externalSolrConfig.zkHost); String[] tokens = cluster.externalSolrConfig.zkHost.split(":"); zookeeper = new GenericZookeeper(tokens[0], tokens.length > 1 ? Integer.parseInt(tokens[1]) : null, cluster.externalSolrConfig.zkAdminPort, cluster.externalSolrConfig.zkChroot); - + setupClusterProps(); try (CloudSolrClient client = new CloudSolrClient.Builder().withZkHost(cluster.externalSolrConfig.zkHost).withZkChroot(cluster.externalSolrConfig.zkChroot).build()) { for (String liveNode : client.getClusterStateProvider().getLiveNodes()) { nodes.add(new ExternalSolrNode( @@ -226,9 +233,18 @@ public void init() throws Exception { log.info("Cluster initialized with nodes: " + nodes + ", zkHost: " + zookeeper + ", nodes by role: " + nodesByRole); } - } +private void setupClusterProps() throws IOException, KeeperException, InterruptedException { + // init clusterprops.json + if (cluster.clusterpropsFilename != null) { + String clusterPropsData = FileUtils.readFileToString(new File(cluster.clusterpropsFilename), Charset.forName("UTF-8")); + try (SolrZkClient zkClient = new SolrZkClient(zookeeper.getHost() + ":" + zookeeper.getPort(), 100)) { + zkClient.create("/clusterprops.json", clusterPropsData.getBytes(), CreateMode.PERSISTENT, true); + } + } +} + private Collection getExternalDataNodes(CloudSolrClient client) { try { if (client.getZkStateReader().getZkClient().exists("/node_roles/data/on", true)) { diff --git a/suites/rate-limiting-clusterprops.json b/suites/rate-limiting-clusterprops.json new file mode 100644 index 00000000..c9d11b40 --- /dev/null +++ b/suites/rate-limiting-clusterprops.json @@ -0,0 +1,17 @@ +{ + "rate-limiters": { + "readBuckets": [ + { + "name": "test-bucket", + "conditions": [{ + "queryParamPattern": { + "q-bucket": "test-bucket" + } + }], + "allowedRequests": 2, + "slotAcquisitionTimeoutInMS": 1000 + } + + ] + } +} diff --git a/suites/rate-limiting-local.json b/suites/rate-limiting-local.json new file mode 100644 index 00000000..87617223 --- /dev/null +++ b/suites/rate-limiting-local.json @@ -0,0 +1,132 @@ +{ + "pre-download": ["https://home.apache.org/~ishan/ecommerce-events.json.gz"], + "task-types": { + "indexing": { + "index-benchmark": { + "name": "ECOMMERCE_EVENTS", + "description": "E-Commerce Events dataset", + "replication-type": "cloud", + "dataset-file": "ecommerce-events.json.gz", + "file-format": "json", + "max-docs": 75000000, + "batch-size": 50000, + "id-field": "id", + "min-threads": 32, + "max-threads": 32, + "setups": [ + { + "setup-name": "cloud_3x1", + "collection": "ecommerce-events", + "configset": "conf_ecommerce_events", + "replication-factor": 1, + "shards": 3, + "thread-step": 1 + } + ] + } + }, + "querying": { + "query-benchmark": { + "name": "Facet queries", + "collection": "ecommerce-events", + "query-file": "facets2.json", + "min-threads": 32, + "max-threads": 32, + "json-query": true, + "shuffle": false, + "rpm": 3000, + "total-count": 5000, + "warm-count": 20, + "params": { "q-bucket": "test-bucket" }, + "headers": { "Solr-Request-Type": "QUERY" } + } + }, + "restart-solr-node": { + "restart-solr-node": "${NODE_INDEX}", + "await-recoveries": true + } + }, + "global-variables": { + "collection-counter": 0, + "restart-counter": 0 + }, + "global-constants": { + "HOST": "localhost", + "PORT": "8983" + }, + "execution-plan": { + "task1": { + "type": "indexing", + "description": "Indexing events", + "instances": 1, + "concurrency": 1, + "mode": "sync" + }, + "task2": { + "description": "Restart Solr node", + "instances": 3, + "concurrency": 1, + "type": "restart-solr-node", + "parameters": { + "NODE_INDEX": "${restart-counter}" + }, + "wait-for": "task1", + "mode": "sync", + "pre-task-evals": [ + "inc(restart-counter,1)" + ] + }, + "task3": { + "description": "Querying with facet queries", + "type": "querying", + "instances": 1, + "concurrency": 1, + "wait-for": "task2", + "mode": "sync" + } + }, + "cluster": { + "num-solr-nodes": 3, + "startup-params": "-m 8g -V", + "provisioning-method": "local", + "clusterprops": "suites/rate-limiting-clusterprops.json" + }, + "repositories": [ + { + "commit-id": "d007470bda2f70ba4e1c407ac624e21288947128", + "description": "Solr 8.4", + "name": "git-repository", + "package-subdir": "/solr/package/", + "build-command": "ant ivy-bootstrap && cd solr && ant compile package", + "submodules": false, + "url": "https://github.com/apache/lucene-solr", + "user": "ishan" + }, + { + "commit-id": "dfde16a004206cc92e21cc5a6cad9030fbe13c20", + "description": "Solr 10x", + "name": "solr-repository", + "package-subdir": "/solr/packaging/", + "build-command": "git clean -fdx && cd solr && ../gradlew distTar", + "submodules": false, + "url": "https://github.com/apache/solr", + "user": "ishan" + }, + { + "commit-id": "dfde16a004206cc92e21cc5a6cad9030fbe13c20", + "description": "Noble's repo", + "name": "noble-repository", + "package-subdir": "/solr/packaging/", + "build-command": "git clean -fdx && cd solr && ../gradlew distTar", + "submodules": false, + "url": "https://github.com/cowpaths/fullstory-solr", + "user": "ishan" + } + ], + "metrics": [ + "jvm/solr.jvm/memory.heap.usage", "jvm/solr.jvm/threads.count", "solr.node/solr.node/CONTAINER.bucketedQueryRateLimiter/test-bucket/success", "solr.node/solr.node/CONTAINER.bucketedQueryRateLimiter/test-bucket/fails", "solr.node/solr.node/CONTAINER.bucketedQueryRateLimiter/test-bucket/available", "solr.node/solr.node/CONTAINER.bucketedQueryRateLimiter/test-bucket/queueLength", "solr.node/solr.node/CONTAINER.bucketedQueryRateLimiter/test-bucket/tryWaitAverage" + ], + "zk-metrics": [ + "sum_configs_read_per_namespace", "sum_configs_write_per_namespace" + ] +}