Search in sources :

Example 6 with QueueSpecification

use of co.cask.cdap.app.queue.QueueSpecification in project cdap by caskdata.

the class FlowQueuePendingCorrector method run.

/**
   * Corrects queue.pending metric for a flowlet.
   */
public void run(FlowId flowId, String producerFlowlet, String consumerFlowlet, String flowletQueue, FlowSpecification flow) throws Exception {
    System.out.println("Running queue.pending correction on flow '" + flowId + "' producerFlowlet '" + producerFlowlet + "' consumerFlowlet '" + consumerFlowlet + "' flowletQueue '" + flowletQueue + "'");
    Map<RunId, ProgramRuntimeService.RuntimeInfo> runtimeInfos = programRuntimeService.list(flowId);
    Preconditions.checkState(runtimeInfos.isEmpty(), "Cannot run tool when flow " + flowId + " is still running");
    SimpleQueueSpecificationGenerator queueSpecGenerator = new SimpleQueueSpecificationGenerator(flowId.getParent());
    Table<QueueSpecificationGenerator.Node, String, Set<QueueSpecification>> table = queueSpecGenerator.create(flow);
    Preconditions.checkArgument(table.contains(QueueSpecificationGenerator.Node.flowlet(producerFlowlet), consumerFlowlet), "Flowlet " + producerFlowlet + " is not emitting to " + consumerFlowlet);
    Set<QueueSpecification> queueSpecs = table.get(QueueSpecificationGenerator.Node.flowlet(producerFlowlet), consumerFlowlet);
    boolean validQueue = false;
    for (QueueSpecification queueSpec : queueSpecs) {
        if (queueSpec.getQueueName().getSimpleName().equals(flowletQueue)) {
            validQueue = true;
            break;
        }
    }
    Preconditions.checkArgument(validQueue, "Queue " + flowletQueue + " does not exist for the given flowlets");
    QueueName queueName = QueueName.fromFlowlet(flowId, producerFlowlet, flowletQueue);
    long consumerGroupId = FlowUtils.generateConsumerGroupId(flowId, consumerFlowlet);
    long correctQueuePendingValue;
    try {
        HBaseQueueDebugger.QueueStatistics stats = queueDebugger.scanQueue(queueName, consumerGroupId);
        correctQueuePendingValue = stats.getUnprocessed() + stats.getProcessedAndNotVisible();
    } catch (NotFoundException e) {
        // OK since flowlet queue exists, but actual queue doesn't exist
        // (e.g. when running upgrade tool from 2.8 to 3.0)
        correctQueuePendingValue = 0;
    }
    Map<String, String> tags = ImmutableMap.<String, String>builder().put(Constants.Metrics.Tag.NAMESPACE, flowId.getNamespace()).put(Constants.Metrics.Tag.APP, flowId.getApplication()).put(Constants.Metrics.Tag.FLOW, flowId.getProgram()).put(Constants.Metrics.Tag.CONSUMER, consumerFlowlet).put(Constants.Metrics.Tag.PRODUCER, producerFlowlet).put(Constants.Metrics.Tag.FLOWLET_QUEUE, flowletQueue).build();
    MetricDataQuery query = new MetricDataQuery(0, 0, Integer.MAX_VALUE, 1, ImmutableMap.of("system.queue.pending", AggregationFunction.SUM), tags, ImmutableList.<String>of(), null);
    Collection<MetricTimeSeries> results = metricStore.query(query);
    long queuePending;
    if (results.isEmpty()) {
        queuePending = 0;
    } else {
        System.out.println("Got results: " + GSON.toJson(results));
        Preconditions.checkState(results.size() == 1);
        List<TimeValue> timeValues = results.iterator().next().getTimeValues();
        Preconditions.checkState(timeValues.size() == 1);
        TimeValue timeValue = timeValues.get(0);
        queuePending = timeValue.getValue();
    }
    metricsCollectionService.startAndWait();
    MetricsContext collector = metricsCollectionService.getContext(tags);
    collector.gauge("queue.pending", correctQueuePendingValue);
    System.out.printf("Adjusted system.queue.pending metric from %d to %d (tags %s)\n", queuePending, correctQueuePendingValue, GSON.toJson(tags));
    // stop will flush the metrics
    metricsCollectionService.stopAndWait();
}
Also used : HBaseQueueDebugger(co.cask.cdap.data.tools.HBaseQueueDebugger) Set(java.util.Set) MetricsContext(co.cask.cdap.api.metrics.MetricsContext) NotFoundException(co.cask.cdap.common.NotFoundException) MetricTimeSeries(co.cask.cdap.api.metrics.MetricTimeSeries) SimpleQueueSpecificationGenerator(co.cask.cdap.internal.app.queue.SimpleQueueSpecificationGenerator) QueueSpecification(co.cask.cdap.app.queue.QueueSpecification) RunId(org.apache.twill.api.RunId) MetricDataQuery(co.cask.cdap.api.metrics.MetricDataQuery) QueueName(co.cask.cdap.common.queue.QueueName) TimeValue(co.cask.cdap.api.dataset.lib.cube.TimeValue)

Example 7 with QueueSpecification

use of co.cask.cdap.app.queue.QueueSpecification in project cdap by caskdata.

the class FlowUtils method getAllConsumerGroups.

/**
   * Gets all consumer group configurations for the given queue.
   */
private static Set<ConsumerGroupConfig> getAllConsumerGroups(Program program, FlowSpecification flowSpec, QueueName queueName, Table<QueueSpecificationGenerator.Node, String, Set<QueueSpecification>> queueSpecs) {
    Set<ConsumerGroupConfig> groupConfigs = Sets.newHashSet();
    SchemaGenerator schemaGenerator = new ReflectionSchemaGenerator();
    // Get all the consumers of this queue.
    for (Map.Entry<String, FlowletDefinition> entry : flowSpec.getFlowlets().entrySet()) {
        String flowletId = entry.getKey();
        for (QueueSpecification queueSpec : Iterables.concat(queueSpecs.column(flowletId).values())) {
            if (!queueSpec.getQueueName().equals(queueName)) {
                continue;
            }
            try {
                // Inspect the flowlet consumer
                FlowletDefinition flowletDefinition = entry.getValue();
                Class<?> flowletClass = program.getClassLoader().loadClass(flowletDefinition.getFlowletSpec().getClassName());
                long groupId = generateConsumerGroupId(program.getId(), flowletId);
                addConsumerGroup(queueSpec, flowletClass, groupId, flowletDefinition.getInstances(), schemaGenerator, groupConfigs);
            } catch (ClassNotFoundException e) {
                // There is no way for not able to load a Flowlet class as it should be verified during deployment.
                throw Throwables.propagate(e);
            }
        }
    }
    return groupConfigs;
}
Also used : FlowletDefinition(co.cask.cdap.api.flow.FlowletDefinition) SchemaGenerator(co.cask.cdap.internal.io.SchemaGenerator) ReflectionSchemaGenerator(co.cask.cdap.internal.io.ReflectionSchemaGenerator) QueueSpecification(co.cask.cdap.app.queue.QueueSpecification) ReflectionSchemaGenerator(co.cask.cdap.internal.io.ReflectionSchemaGenerator) ConsumerGroupConfig(co.cask.cdap.data2.queue.ConsumerGroupConfig) Map(java.util.Map)

Example 8 with QueueSpecification

use of co.cask.cdap.app.queue.QueueSpecification in project cdap by caskdata.

the class FlowUtils method configureQueue.

/**
   * Configures all queues being used in a flow.
   *
   * @return A Multimap from flowletId to QueueName where the flowlet is a consumer of.
   */
public static Multimap<String, QueueName> configureQueue(Program program, FlowSpecification flowSpec, final StreamAdmin streamAdmin, QueueAdmin queueAdmin, TransactionExecutorFactory txExecutorFactory) {
    // Generate all queues specifications
    ApplicationId appId = new ApplicationId(program.getNamespaceId(), program.getApplicationId());
    Table<QueueSpecificationGenerator.Node, String, Set<QueueSpecification>> queueSpecs = new SimpleQueueSpecificationGenerator(appId).create(flowSpec);
    // For each queue in the flow, gather all consumer groups information
    Multimap<QueueName, ConsumerGroupConfig> queueConfigs = HashMultimap.create();
    // Loop through each flowlet and generate the map from consumer flowlet id to queue
    ImmutableSetMultimap.Builder<String, QueueName> resultBuilder = ImmutableSetMultimap.builder();
    for (Map.Entry<String, FlowletDefinition> entry : flowSpec.getFlowlets().entrySet()) {
        String flowletId = entry.getKey();
        for (QueueSpecification queueSpec : Iterables.concat(queueSpecs.column(flowletId).values())) {
            resultBuilder.put(flowletId, queueSpec.getQueueName());
        }
    }
    // For each queue, gather all consumer groups.
    for (QueueSpecification queueSpec : Iterables.concat(queueSpecs.values())) {
        QueueName queueName = queueSpec.getQueueName();
        queueConfigs.putAll(queueName, getAllConsumerGroups(program, flowSpec, queueName, queueSpecs));
    }
    try {
        // Configure each stream consumer in the Flow. Also collects all queue configurers.
        final List<ConsumerGroupConfigurer> groupConfigurers = Lists.newArrayList();
        final Map<StreamId, Map<Long, Integer>> streamConfigurers = Maps.newHashMap();
        for (Map.Entry<QueueName, Collection<ConsumerGroupConfig>> entry : queueConfigs.asMap().entrySet()) {
            LOG.info("Queue config for {} : {}", entry.getKey(), entry.getValue());
            if (entry.getKey().isStream()) {
                Map<Long, Integer> configs = Maps.newHashMap();
                for (ConsumerGroupConfig config : entry.getValue()) {
                    configs.put(config.getGroupId(), config.getGroupSize());
                }
                streamConfigurers.put(entry.getKey().toStreamId(), configs);
            } else {
                groupConfigurers.add(new ConsumerGroupConfigurer(queueAdmin.getQueueConfigurer(entry.getKey()), entry.getValue()));
            }
        }
        // Configure queue transactionally
        try {
            Transactions.createTransactionExecutor(txExecutorFactory, groupConfigurers).execute(new TransactionExecutor.Subroutine() {

                @Override
                public void apply() throws Exception {
                    for (ConsumerGroupConfigurer configurer : groupConfigurers) {
                        configurer.configure();
                    }
                    for (Map.Entry<StreamId, Map<Long, Integer>> entry : streamConfigurers.entrySet()) {
                        streamAdmin.configureGroups(entry.getKey(), entry.getValue());
                    }
                }
            });
        } finally {
            for (ConsumerGroupConfigurer configurer : groupConfigurers) {
                Closeables.closeQuietly(configurer);
            }
        }
        return resultBuilder.build();
    } catch (Exception e) {
        LOG.error("Failed to configure queues", e);
        throw Throwables.propagate(e);
    }
}
Also used : StreamId(co.cask.cdap.proto.id.StreamId) Set(java.util.Set) FlowletDefinition(co.cask.cdap.api.flow.FlowletDefinition) QueueName(co.cask.cdap.common.queue.QueueName) ConsumerGroupConfig(co.cask.cdap.data2.queue.ConsumerGroupConfig) ImmutableSetMultimap(com.google.common.collect.ImmutableSetMultimap) TransactionExecutor(org.apache.tephra.TransactionExecutor) IOException(java.io.IOException) SimpleQueueSpecificationGenerator(co.cask.cdap.internal.app.queue.SimpleQueueSpecificationGenerator) Collection(java.util.Collection) QueueSpecification(co.cask.cdap.app.queue.QueueSpecification) ApplicationId(co.cask.cdap.proto.id.ApplicationId) Map(java.util.Map)

Example 9 with QueueSpecification

use of co.cask.cdap.app.queue.QueueSpecification in project cdap by caskdata.

the class SimpleQueueSpecificationGenerator method create.

/**
   * Given a {@link FlowSpecification}.
   *
   * @param input {@link FlowSpecification}
   * @return A {@link Table}
   */
@Override
public Table<Node, String, Set<QueueSpecification>> create(FlowSpecification input) {
    Table<Node, String, Set<QueueSpecification>> table = HashBasedTable.create();
    String flow = input.getName();
    Map<String, FlowletDefinition> flowlets = input.getFlowlets();
    // Iterate through connections of a flow.
    for (FlowletConnection connection : input.getConnections()) {
        final String source = connection.getSourceName();
        final String target = connection.getTargetName();
        String sourceNamespace = connection.getSourceNamespace() == null ? appId.getNamespace() : connection.getSourceNamespace();
        Node sourceNode;
        Set<QueueSpecification> queueSpec;
        if (connection.getSourceType() == FlowletConnection.Type.FLOWLET) {
            sourceNode = new Node(connection.getSourceType(), source);
            queueSpec = generateQueueSpecification(appId, flow, connection, flowlets.get(target).getInputs(), flowlets.get(source).getOutputs());
        } else {
            sourceNode = new Node(connection.getSourceType(), sourceNamespace, source);
            queueSpec = generateQueueSpecification(appId, flow, connection, flowlets.get(target).getInputs(), ImmutableMap.<String, Set<Schema>>of(connection.getSourceName(), ImmutableSet.of(STREAM_EVENT_SCHEMA)));
        }
        Set<QueueSpecification> queueSpecifications = table.get(sourceNode, target);
        if (queueSpecifications == null) {
            queueSpecifications = Sets.newHashSet();
            table.put(sourceNode, target, queueSpecifications);
        }
        queueSpecifications.addAll(queueSpec);
    }
    return table;
}
Also used : FlowletDefinition(co.cask.cdap.api.flow.FlowletDefinition) ImmutableSet(com.google.common.collect.ImmutableSet) Set(java.util.Set) FlowletConnection(co.cask.cdap.api.flow.FlowletConnection) QueueSpecification(co.cask.cdap.app.queue.QueueSpecification)

Example 10 with QueueSpecification

use of co.cask.cdap.app.queue.QueueSpecification in project cdap by caskdata.

the class FlowQueuePendingCorrector method run.

public void run(final FlowId flowId, FlowSpecification flow) throws Exception {
    /* Temporary check. Can be removed when FlowId class is ready */
    Preconditions.checkArgument(ProgramType.FLOW == flowId.getType(), "Unexpected program type %s, FlowPendingQueueCorrector only runs on flows", flowId.getType());
    System.out.println("Running queue.pending correction on flow " + flowId);
    SimpleQueueSpecificationGenerator queueSpecGenerator = new SimpleQueueSpecificationGenerator(flowId.getParent());
    Table<QueueSpecificationGenerator.Node, String, Set<QueueSpecification>> table = queueSpecGenerator.create(flow);
    for (Table.Cell<QueueSpecificationGenerator.Node, String, Set<QueueSpecification>> cell : table.cellSet()) {
        if (cell.getRowKey().getType() == FlowletConnection.Type.FLOWLET) {
            String producerFlowlet = cell.getRowKey().getName();
            String consumerFlowlet = cell.getColumnKey();
            for (QueueSpecification queue : cell.getValue()) {
                run(flowId, producerFlowlet, consumerFlowlet, queue.getQueueName().getSimpleName());
            }
        }
    }
}
Also used : Set(java.util.Set) Table(com.google.common.collect.Table) QueueSpecification(co.cask.cdap.app.queue.QueueSpecification) SimpleQueueSpecificationGenerator(co.cask.cdap.internal.app.queue.SimpleQueueSpecificationGenerator)

Aggregations

QueueSpecification (co.cask.cdap.app.queue.QueueSpecification)10 Set (java.util.Set)8 SimpleQueueSpecificationGenerator (co.cask.cdap.internal.app.queue.SimpleQueueSpecificationGenerator)6 Map (java.util.Map)6 FlowletDefinition (co.cask.cdap.api.flow.FlowletDefinition)5 QueueName (co.cask.cdap.common.queue.QueueName)5 Schema (co.cask.cdap.api.data.schema.Schema)3 ImmutableSet (com.google.common.collect.ImmutableSet)3 FlowletConnection (co.cask.cdap.api.flow.FlowletConnection)2 MetricsContext (co.cask.cdap.api.metrics.MetricsContext)2 QueueSpecificationGenerator (co.cask.cdap.app.queue.QueueSpecificationGenerator)2 Node (co.cask.cdap.app.queue.QueueSpecificationGenerator.Node)2 NotFoundException (co.cask.cdap.common.NotFoundException)2 ConsumerGroupConfig (co.cask.cdap.data2.queue.ConsumerGroupConfig)2 ApplicationId (co.cask.cdap.proto.id.ApplicationId)2 ImmutableSetMultimap (com.google.common.collect.ImmutableSetMultimap)2 Table (com.google.common.collect.Table)2 TypeToken (com.google.common.reflect.TypeToken)2 IOException (java.io.IOException)2 Tick (co.cask.cdap.api.annotation.Tick)1