package resa.examples.outdet;
import backtype.storm.Config;
import backtype.storm.StormSubmitter;
import backtype.storm.topology.TopologyBuilder;
import backtype.storm.tuple.Fields;
import resa.metrics.RedisMetricsCollector;
import resa.topology.ResaTopologyBuilder;
import resa.util.ConfigUtil;
import resa.util.ResaConfig;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;
import java.util.stream.DoubleStream;
import java.util.stream.Stream;
/**
* Created by ding on 14-3-17.
*/
public class OutlierDetectionTop {
public static List<double[]> generateRandomVectors(int dimension, int vectorCount) {
Random rand = new Random();
return Stream.generate(() -> {
double[] v = DoubleStream.generate(rand::nextGaussian).limit(dimension).toArray();
double sum = Math.sqrt(Arrays.stream(v).map((d) -> d * d).sum());
return Arrays.stream(v).map((d) -> d / sum).toArray();
}).limit(vectorCount).collect(Collectors.toList());
}
public static void main(String[] args) throws Exception {
Config conf = ConfigUtil.readConfig(new File(args[1]));
if (conf == null) {
throw new RuntimeException("cannot find conf file " + args[1]);
}
ResaConfig resaConfig = ResaConfig.create();
resaConfig.putAll(conf);
TopologyBuilder builder = new ResaTopologyBuilder();
int numWorkers = ConfigUtil.getInt(conf, "a-worker.count", 1);
int numAckers = ConfigUtil.getInt(conf, "a-acker.count", 1);
resaConfig.setNumWorkers(numWorkers);
resaConfig.setNumAckers(numAckers);
String host = (String) conf.get("redis.host");
int port = ConfigUtil.getInt(conf, "redis.port", 6379);
String queue = (String) conf.get("redis.queue");
int defaultTaskNum = ConfigUtil.getInt(conf, "a-task.default", 10);
//set spout
int objectCount = ConfigUtil.getIntThrow(conf, "a-spout.object.size");
builder.setSpout("objectSpout",
new ObjectSpout(host, port, queue, objectCount),
ConfigUtil.getInt(conf, "a-spout.parallelism", 1));
List<double[]> randVectors = generateRandomVectors(ConfigUtil.getIntThrow(conf, "a-projection.dimension"),
ConfigUtil.getIntThrow(conf, "a-projection.size"));
builder.setBolt("projection",
new Projection(new ArrayList<>(randVectors)), ConfigUtil.getInt(conf, "a-projection.parallelism", 1))
.setNumTasks(defaultTaskNum)
.shuffleGrouping("objectSpout");
int minNeighborCount = ConfigUtil.getIntThrow(conf, "a-detector.neighbor.count.min");
double maxNeighborDistance = ConfigUtil.getDoubleThrow(conf, "a-detector.neighbor.distance.max");
builder.setBolt("detector",
new Detector(objectCount, minNeighborCount, maxNeighborDistance),
ConfigUtil.getInt(conf, "a-detector.parallelism", 1))
.setNumTasks(defaultTaskNum)
.fieldsGrouping("projection", new Fields(Projection.PROJECTION_ID_FIELD));
builder.setBolt("updater",
new Updater(randVectors.size()), ConfigUtil.getInt(conf, "a-updater.parallelism", 1))
.setNumTasks(defaultTaskNum)
.fieldsGrouping("detector", new Fields(ObjectSpout.TIME_FILED, ObjectSpout.ID_FILED));
if (ConfigUtil.getBoolean(conf, "a-metric.resa", false)) {
resaConfig.addDrsSupport();
resaConfig.put(ResaConfig.REBALANCE_WAITING_SECS, 0);
System.out.println("ResaMetricsCollector is registered");
}
if (ConfigUtil.getBoolean(conf, "a-metric.redis", true)) {
resaConfig.registerMetricsConsumer(RedisMetricsCollector.class);
System.out.println("RedisMetricsCollector is registered");
}
StormSubmitter.submitTopology(args[0], resaConfig, builder.createTopology());
}
}