| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You 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 org.apache.ignite.loadtests.job; |
| |
| import java.io.File; |
| import java.io.FileInputStream; |
| import java.io.InputStream; |
| import java.net.URISyntaxException; |
| import java.util.ArrayList; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Properties; |
| import java.util.concurrent.Executor; |
| import java.util.concurrent.Executors; |
| import org.apache.ignite.Ignite; |
| import org.apache.ignite.configuration.IgniteConfiguration; |
| import org.apache.ignite.internal.util.typedef.G; |
| import org.apache.ignite.internal.util.typedef.internal.U; |
| import org.springframework.beans.factory.ListableBeanFactory; |
| import org.springframework.context.support.FileSystemXmlApplicationContext; |
| |
| /** |
| * Tests task/job behavior under load. |
| */ |
| public class GridJobLoadTest implements Runnable { |
| /** Test configuration directory. */ |
| private static final File TEST_CONF_DIR; |
| |
| /** |
| * |
| */ |
| static { |
| try { |
| TEST_CONF_DIR = new File(U.resolveIgniteUrl("/modules/core/src/test/config/job-loadtest").toURI()); |
| } |
| catch (URISyntaxException e) { |
| throw new RuntimeException("Failed to initialize directory.", e); |
| } |
| } |
| |
| /** File with test configuration. */ |
| private static final File TEST_CONFIGURATION_FILE = new File(TEST_CONF_DIR, "job-loadtest.properties"); |
| |
| /** File with client nodes configuration. */ |
| private static final File CLIENT_NODE_CONFIGURATION = new File(TEST_CONF_DIR, "client.xml"); |
| |
| /** File with server nodes configuration. */ |
| private static final File SERVER_NODE_CONFIGURATION = new File(TEST_CONF_DIR, "server.xml"); |
| |
| /** |
| * Main method. |
| * |
| * @param args Command-line parameters. |
| * @throws Exception if test start failed. |
| */ |
| public static void main(String[] args) throws Exception { |
| new GridJobLoadTest().run(); |
| } |
| |
| /** Number of client nodes to run. */ |
| private int clientNodes; |
| |
| /** Number of server nodes to run. */ |
| private int srvNodes; |
| |
| /** Number of submitter threads per client node. */ |
| private int threadsPerClient; |
| |
| /** Parameters for executing jobs. */ |
| private GridJobLoadTestParams taskParams; |
| |
| /** Submission/cancel ratio for submitting threads. */ |
| private int cancelRate; |
| |
| /** Time to sleep between task submissions. */ |
| private long submitDelay; |
| |
| /** Number of nodes running inside this test. */ |
| private int runningNodes; |
| |
| /** |
| * Generate new node number. |
| * |
| * @return a client number unique within this test run. |
| */ |
| private int getNextNodeNum() { |
| return ++runningNodes; |
| } |
| |
| /** |
| * Loads test configuration. |
| * |
| * @throws Exception if configuration is unawailable or broken. |
| */ |
| private void loadTestConfiguration() throws Exception { |
| assert TEST_CONFIGURATION_FILE.isFile(); |
| |
| InputStream in = null; |
| |
| Properties p = new Properties(); |
| |
| try { |
| in = new FileInputStream(TEST_CONFIGURATION_FILE); |
| |
| p.load(in); |
| } |
| finally { |
| U.closeQuiet(in); |
| } |
| |
| clientNodes = Integer.parseInt(p.getProperty("client.nodes.count")); |
| srvNodes = Integer.parseInt(p.getProperty("server.nodes.count")); |
| threadsPerClient = Integer.parseInt(p.getProperty("threads.per.client")); |
| cancelRate = Integer.parseInt(p.getProperty("cancel.rate")); |
| submitDelay = Long.parseLong(p.getProperty("submit.delay")); |
| |
| taskParams = new GridJobLoadTestParams( |
| Integer.parseInt(p.getProperty("jobs.count")), |
| Integer.parseInt(p.getProperty("jobs.test.duration")), |
| Integer.parseInt(p.getProperty("jobs.test.completion.delay")), |
| Double.parseDouble(p.getProperty("jobs.failure.probability")) |
| ); |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public void run() { |
| List<Ignite> clientIgnites = runGrid(); |
| |
| assert clientIgnites.size() == clientNodes; |
| |
| int threadsCnt = clientNodes * threadsPerClient; |
| |
| Executor e = Executors.newFixedThreadPool(threadsCnt); |
| |
| for (Ignite ignite : clientIgnites) { |
| for (int j = 0; j < threadsPerClient; j++) |
| e.execute(new GridJobLoadTestSubmitter(ignite, taskParams, cancelRate, submitDelay)); |
| } |
| } |
| |
| /** |
| * Run all grid nodes as defined in test configuration. |
| * |
| * @return list of run nodes. |
| */ |
| private List<Ignite> runGrid() { |
| List<Ignite> clientIgnites = new ArrayList<>(clientNodes); |
| |
| try { |
| loadTestConfiguration(); |
| |
| for (int i = 0; i < srvNodes; i++) |
| startNode("server", SERVER_NODE_CONFIGURATION); |
| |
| // Start clients in the second order to cache a client node in Ignite. |
| for (int i = 0; i < clientNodes; i++) |
| clientIgnites.add(startNode("client", CLIENT_NODE_CONFIGURATION)); |
| } |
| catch (Exception e) { |
| throw new RuntimeException(e); |
| } |
| |
| return clientIgnites; |
| } |
| |
| /** |
| * Starts new grid node. |
| * |
| * @param igniteInstanceName name of new node. |
| * @param springCfg file with spring configuration to use for this node. |
| * @return a grid instance local to new node |
| * {@link org.apache.ignite.Ignition#start(org.apache.ignite.configuration.IgniteConfiguration)}. |
| * @throws Exception if node run failed. |
| */ |
| protected Ignite startNode(String igniteInstanceName, File springCfg) throws Exception { |
| assert springCfg != null; |
| |
| ListableBeanFactory springCtx = new FileSystemXmlApplicationContext( |
| "file:///" + springCfg.getAbsolutePath()); |
| |
| Map cfgMap = springCtx.getBeansOfType(IgniteConfiguration.class); |
| |
| assert cfgMap != null; |
| assert !cfgMap.isEmpty(); |
| |
| IgniteConfiguration cfg = (IgniteConfiguration)cfgMap.values().iterator().next(); |
| |
| cfg.setIgniteInstanceName(igniteInstanceName + "-" + getNextNodeNum()); |
| |
| return G.start(cfg); |
| } |
| } |