Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Quota management via Admin Client has gone through a couple drafts of proposals (KIP-248, KIP-422). While improvements have been made to the Admin interface for configuration handling, fitting quotas into the API would be restrictive because they don't fit the natural key-value pairing. Therefore, it'd be beneficial to have a quota-native API for administrating quotas, which would offer a more direct an intuitive and less error-prone interface, convey additional useful information beyond what a the configuration APIs could provide, and provide for future extensibility as quotas types are added or evolveevolved.

Background

Quotas are defined in terms of a user and  and client ID, where the user acts as a specific opaque principal, and the client ID as a more generic group identifier.

...

Public Interfaces


Code Block
    /**
     * Represents the Describesdefault howname tofor filteran quota entities.
     */
entity, i.e. the entity that's matched
     public* classwhen QuotaFilteran {
exact match isn't found.
     // Matches the default entity's name.*/
    public final static String public static final String DEFAULT;QUOTA_ENTITY_DEFAULT = // implementation defined

    /**
    // Matches* onlyDescribes entitiesan with the name omittedentity type.
     */
    public static final String NULL;

enum QuotaEntity {
        USER,        // MatchesThe everyuser entity nameprincipal.
        public static final String ANY;CLIENT_ID,   // The client ID.

        /**
/ Note others may be added in the future.
 * @param non-null user the user to match, or a sentinel filter value
 }

    public class QuotaFilter {
       public enum Rule {
 * @param non-null clientId the client ID to matchEXACT, or a sentinel filter// value
exact name match
       */
  NOT,      public QuotaFilter(String user, String clientId);// matches all non-matching names
        public String user();
PREFIX,   // matches all names with the public String clientId();given prefix

    }

    public class// ListQuotasOptionsNote {
others may be added in the future.
  // Default.
    }

    public class ListQuotasResult {/**
        /**
    * A filtering rule to be applied.
     * @return the collection*
 of entities that matched the filter
  * @param entity the entity the rule applies */to
        Collection<QuotaEntity> entities();
    }

* @param rule the rule to apply
    public interface Admin extends AutoCloseable* {
@param match the non-null string that's applied by the /**rule
        */
 * Lists entities matching the provided filterpublic that have quotas defined.QuotaFilter(QuotaEntity entity, Rule rule, String match);

       public QuotaEntity *entity();
       public Rule *rule();
 For example, to determine the quota forpublic users that belongs to a particular client, set
     String match();
    }

    public class DescribeQuotasOptions {
    * filter.user() to QuotaFilter.ANY and// filterDefault.clientId()
 to the client ID.}

    public class DescribeQuotasResult {
        /**
         * Alternatively,@return tothe determinecollection whichof usersentities havethat specificmatched quotathe values, set filter.user()
filter
         */
    * to the user nameKafkaFuture<Collection<Map<QuotaEntity, andString>>> filter.clientIdentities();
 to QuotaFilter.NULL.   }

    public interface Admin extends AutoCloseable */{
        ListQuotasResult listQuotas(QuotaFilter filter);
/**
        }
Code Block
    /**
     * The quota types. * Describes all entities matching all provided filters (logical AND) that have at least one
     */
    public* enumquota QuotaTypevalue {defined.
        CONSUMER_BYTE_RATE,
 */
         PRODUCER_BYTE_RATE,
        REQUEST_PERCENTAGE,DescribeQuotasResult describeQuotas(Collection<QuotaFilter> filters, DescribeQuotasOptions options);
    }


Code Block

    /**
     * The quota configuration for a specific user and client IDtypes.
     */
    public classenum QuotaConfigQuotaType {

        /**CONSUMER_BYTE_RATE,
         * How the quota is applied to the quota entity.PRODUCER_BYTE_RATE,
        REQUEST_PERCENTAGE,

         *//
 Note others may be added in  public enum Entity {the future.
    }

    public class DescribeEffectiveQuotasOptions  USER,{
        // Whether Theto useromit principal.
any inherited values in the result.       CLIENT_IDIf true, then undefined // The client ID.values for
        // the entity's config // Others may will be addedexcluded infrom the futureresults.
        }
//
        /**
/ Default: false.
       * HowDescribeQuotasOptions the quota is applied to the quota entity.
         */
        public enum Behavior {setOmitInheritedValues(boolean omitInheritedValues);

        // Whether to include the list of overridden values for every quota type in the result.
        //
    SET,        // Sets the value, overwriting and lower precedence SET values.
   Default: false.
        DescribeQuotasOptions setOmitOverriddenValues(boolean omitOverriddenValues);
    }

    public RESTRICT,class DescribeEffectiveQuotasResult {
 // Adds a limit (upper bound) to higher precedence values. /**
         * Information about //a Othersspecific mayquota be added in the futureconfiguration value.
        }

        /** */
        public *class TheValue units{
 for the quota.
         /**/
        public enum Units {
  * @param source the entity source for the value
  BPS,           * @param //value Bytesthe per second, on a global scale.non-null value
            BPS_PER_BROKER,  // Bytes per second, on a per-broker level.
 */
            public Value(Map<QuotaEntity, String> source, Double value);

           SHARE, public Map<QuotaEntity, String> source();
       // The shares, used for determiningpublic proportional quota.Double value();
        }

        /**
         * Information about the value for a specific quota configuration valuetype.
         */
        public class ValueEntry {
            /**
             * @param sourcevalue the entity source for theactive quota value
             * @param behavior the behavior for applying the quota overriddenValues all values that are overridden due to being lower in specificity
             */
 @param units the units to apply to the value
   public Entry(Value value, List<Value> overriddenValues);

      * @param value the non-null   public Value value();
             */public List<Value> overriddenValues();
        }

    public Value(Map<Entity, String> source, Behavior behavior, Units units, Double value);
 /**
         * Maps a quota type to its configuration publicentry.
 Map<Entity, String> source();
      *
      public Behavior behavior();
 * Note that if `options.omitInheritedValues` is true, then this config may publicnot Units units();map every
         * quota type publicto Double value();
        }

        /**
         * Information about the value for a quota type.
         */
        public class Entry {
            /**
             * @param value the active quota value
             * @param overriddenValues list of all values lower that are ignored due to being lower in the hierarchy
             */
            public Entry(Value value, List<Value> overriddenValues);
            public Value value();
            public List<Value> overriddenValues();
        }

        /**
         * Maps quota type to its configuration entry.
         *
         * Note that, depending upon the settings in the request's options, this config may not map every
         * quota type to an entry. If a key is not contained in the map, then that quota type's value
         * is not specified.
         */
        public Map<QuotaType, Entry> config();
    }

    /**
     * Identifies a quota entity. If a entity key type has a value, then it's a specified name,
     * if the value is the empty string, then the default name is used, otherwise if the key is
     * omitted or the value is null, then the name is omitted entirely.
     *
     * For example:
     *
     *   {user="kafka-user", clientId="kafka-client-id"} corresponds to quota source `USER_CLIENT` with
     *   specified user "kafka-user" and client ID "kafka-client-id".
     *
     *   {user="kafka-user", clientId=Optional.empty()} corresponds to quota source `USER_DEFAULT_CLIENT`
     *   with specified user "kafka-user" and default client ID.
     *
     *   {user=null, clientId="kafka-client-id"} corresponds to quota source `CLIENT` for client with
     *   ID "kafka-client-id".
     */
    public class QuotaEntity {
        public QuotaEntity(Map<Entity, String> entity);
        public Optional<String> user();
        public Optional<String> clientId();
    }

    public class DescribeQuotasOptions {
        // Whether to include the inherited values in the result. If false, then undefined values for
        // the config entries will be ommitted in the results.
        //
an entry. If a key is not contained in the map, then that quota type's value
         * is not specified.
         *//
 Default: true.
      public KafkaFuture<Map<QuotaType, DescribeQuotasOptionsEntry>> setWantInheritedValuesconfig(boolean wantInheritedValues);

    }

    //public Whetherinterface toAdmin includeextends theAutoCloseable overridden{
 values for every quota type in the result./**
        //
 * Describes the effective quotas for the // Default: trueprovided entities.
        DescribeQuotasOptions setWantOverriddenValues(boolean wantOverriddenValues);
      }
*/
    public class DescribeQuotasResult {
 DescribeEffectiveQuotasResult describeEffectiveQuotas(Collection<QuotaEntity> quotaEntities,
     Map<QuotaEntity, QuotaConfig> configs;
    }

    public interface Admin extends AutoCloseable {
        /**
         * Describes the quotas for the provided entities.
         */
        DescribeQuotasResult describeQuotas(Collection<QuotaEntity>DescribeEffectiveQuotasOptions quotaEntitiesoptions);
    }


Code Block
    public class AlterQuotasOp {
        /**
         * @param type the quota type to alter
         * @param the new value for the quota, otherwise if null, then the existing value is cleared
         */
        public QuotaAlteration(QuotaType type, Double value);
        public QuotaType type();
        public Double value();
    }

    public class AlterQuotasOptions {
        // Default.
    }

    public class AlterQuotasResult {
        /**
         * @return map of a quota entity update to its future
         */
        public Map<QuotaEntity, KafkaFuture<Void>> futures();
    }

    public interface Admin extends AutoCloseable {
        /**
         * Alters the quotas as specified for the provided quota entities.
         *
         * @param alterations the alterations to perform
         * @return the result of the alterations
         */
        AlterQuotasResult alterQuotas(Map<QuotaEntity, AlterQuotasOp> alterations);
    }

...