-
Notifications
You must be signed in to change notification settings - Fork 12
Broker support for QuotaRecord and DescribeClientQuotas #477
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
8ef5a1a
2a1e7d9
1bdb82a
e3fa08f
13bb515
fc9cc3d
8ad11d4
b81b4c0
25f96ae
a07cceb
4503dc4
b441431
81c46f3
3efd9b9
d0390b0
0f3f8f3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -23,7 +23,6 @@ import java.util | |
| import java.util.{Collections, Optional, Properties} | ||
| import java.util.concurrent.ConcurrentHashMap | ||
| import java.util.concurrent.atomic.AtomicInteger | ||
|
|
||
| import kafka.admin.{AdminUtils, RackAwareMode} | ||
| import kafka.api.ElectLeadersRequestOps | ||
| import kafka.api.{ApiVersion, KAFKA_0_11_0_IV0, KAFKA_2_3_IV0} | ||
|
|
@@ -90,8 +89,9 @@ import scala.collection.mutable.ArrayBuffer | |
| import scala.collection.{Map, Seq, Set, immutable, mutable} | ||
| import scala.util.{Failure, Success, Try} | ||
| import kafka.coordinator.group.GroupOverview | ||
| import kafka.server.metadata.BrokerMetadataListener | ||
| import kafka.server.metadata.{BrokerMetadataListener, QuotaCache} | ||
| import org.apache.kafka.common.message.DescribeConfigsRequestData.DescribeConfigsResource | ||
| import org.apache.kafka.common.quota.ClientQuotaEntity | ||
| import org.apache.kafka.common.requests.DescribeConfigsResponse.ConfigSource | ||
|
|
||
| import scala.annotation.nowarn | ||
|
|
@@ -120,7 +120,8 @@ class KafkaApis(val requestChannel: RequestChannel, | |
| val tokenManager: DelegationTokenManager, | ||
| val brokerFeatures: BrokerFeatures, | ||
| val finalizedFeatureCache: FinalizedFeatureCache, | ||
| brokerMetadataListener: BrokerMetadataListener) extends ApiRequestHandler with Logging { | ||
| brokerMetadataListener: BrokerMetadataListener, | ||
| val quotaCache: QuotaCache) extends ApiRequestHandler with Logging { | ||
|
|
||
| val apisUtils = new ApisUtils(new LogContext(s"[BrokerApis id=${config.brokerId}] "), | ||
| requestChannel, authorizer, quotas, time, Some(groupCoordinator), Some(txnCoordinator)) | ||
|
|
@@ -249,7 +250,7 @@ class KafkaApis(val requestChannel: RequestChannel, | |
| case ApiKeys.ALTER_PARTITION_REASSIGNMENTS => maybeForward(request, handleAlterPartitionReassignmentsRequest) | ||
| case ApiKeys.LIST_PARTITION_REASSIGNMENTS => handleListPartitionReassignmentsRequest(request) | ||
| case ApiKeys.OFFSET_DELETE => handleOffsetDeleteRequest(request) | ||
| case ApiKeys.DESCRIBE_CLIENT_QUOTAS => maybeForward(request, handleDescribeClientQuotasRequest) | ||
| case ApiKeys.DESCRIBE_CLIENT_QUOTAS => handleDescribeClientQuotasRequest(request) | ||
| case ApiKeys.ALTER_CLIENT_QUOTAS => maybeForward(request, handleAlterClientQuotasRequest) | ||
| case ApiKeys.DESCRIBE_USER_SCRAM_CREDENTIALS => handleDescribeUserScramCredentialsRequest(request) | ||
| case ApiKeys.ALTER_USER_SCRAM_CREDENTIALS => maybeForward(request, handleAlterUserScramCredentialsRequest) | ||
|
|
@@ -3205,8 +3206,15 @@ class KafkaApis(val requestChannel: RequestChannel, | |
| .setThrottleTimeMs(requestThrottleMs) | ||
| .setEntries(entriesData.asJava))) | ||
| } else { | ||
| val result = quotaCache.describeClientQuotas(describeClientQuotasRequest.filter()) | ||
| val resultAsJava = new util.HashMap[ClientQuotaEntity, util.Map[String, java.lang.Double]](result.size) | ||
|
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These conversions are annoying, but I don't know how to avoid them (unless we just use Java classes in the QuotaCache code) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's not a hot path, so I personally don't see a real need to change the |
||
| result.foreach { case (entity, quotas) => | ||
| resultAsJava.put(new ClientQuotaEntity(entity.toMap.asJava), | ||
| quotas.map { case (key, quota) => key -> Double.box(quota)}.asJava) | ||
| } | ||
| apisUtils.sendResponseMaybeThrottle(request, requestThrottleMs => | ||
| describeClientQuotasRequest.getErrorResponse(requestThrottleMs, Errors.CLUSTER_AUTHORIZATION_FAILED.exception)) | ||
| DescribeClientQuotasResponse.fromQuotaEntities(resultAsJava, requestThrottleMs) | ||
| ) | ||
| } | ||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -22,7 +22,6 @@ import java.net.{InetAddress, SocketTimeoutException} | |
| import java.util | ||
| import java.util.concurrent._ | ||
| import java.util.concurrent.atomic.{AtomicBoolean, AtomicInteger, AtomicReference} | ||
|
|
||
| import kafka.api.{KAFKA_0_9_0, KAFKA_2_2_IV0, KAFKA_2_4_IV1} | ||
| import kafka.cluster.Broker | ||
| import kafka.common.{GenerateBrokerIdException, InconsistentBrokerIdException, InconsistentClusterIdException} | ||
|
|
@@ -33,6 +32,7 @@ import kafka.log.LogManager | |
| import kafka.metrics.{KafkaMetricsReporter, KafkaYammerMetrics} | ||
| import kafka.network.SocketServer | ||
| import kafka.security.CredentialProvider | ||
| import kafka.server.metadata.QuotaCache | ||
| import kafka.utils._ | ||
| import kafka.zk.{BrokerInfo, KafkaZkClient} | ||
| import org.apache.kafka.clients.{ApiVersions, ClientDnsLookup, ManualMetadataUpdater, NetworkClient, NetworkClientUtils} | ||
|
|
@@ -326,7 +326,8 @@ class LegacyBroker(val config: KafkaConfig, | |
| dataPlaneRequestProcessor = new KafkaApis(socketServer.dataPlaneRequestChannel, | ||
| replicaManager, adminManager, groupCoordinator, transactionCoordinator, | ||
| kafkaController, forwardingManager, zkClient, config.brokerId, config, metadataCache, metrics, authorizer, quotaManagers, | ||
| fetchManager, brokerTopicStats, _clusterId, time, tokenManager, brokerFeatures, featureCache, null) | ||
| fetchManager, brokerTopicStats, _clusterId, time, tokenManager, brokerFeatures, featureCache, null, | ||
| new QuotaCache()) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should this be null since it isn't used in the legacy case? Not sure if we should change the parameter to be an
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yea we could use an As an aside: it's going to get pretty messy in this class as we add members which are optional (or nullable). Maybe we should try to extract an interface from LegacyAdminManager and use that rather than adding more members to KafkaApis for kip-500 functionality. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think at some point the ZooKeeper-related stuff will be removed -- that might be a good time to try to trim things down/clean it up a bit? |
||
|
|
||
| dataPlaneRequestHandlerPool = new KafkaRequestHandlerPool(config.brokerId, socketServer.dataPlaneRequestChannel, dataPlaneRequestProcessor, time, | ||
| config.numIoThreads, s"${SocketServer.DataPlaneMetricPrefix}RequestHandlerAvgIdlePercent", SocketServer.DataPlaneThreadPrefix) | ||
|
|
@@ -335,7 +336,8 @@ class LegacyBroker(val config: KafkaConfig, | |
| controlPlaneRequestProcessor = new KafkaApis(controlPlaneRequestChannel, | ||
| replicaManager, adminManager, groupCoordinator, transactionCoordinator, | ||
| kafkaController, forwardingManager, zkClient, config.brokerId, config, metadataCache, metrics, authorizer, quotaManagers, | ||
| fetchManager, brokerTopicStats, _clusterId, time, tokenManager, brokerFeatures, featureCache, null) | ||
| fetchManager, brokerTopicStats, _clusterId, time, tokenManager, brokerFeatures, featureCache, null, | ||
| new QuotaCache()) | ||
|
mumrah marked this conversation as resolved.
Outdated
|
||
|
|
||
| controlPlaneRequestHandlerPool = new KafkaRequestHandlerPool(config.brokerId, socketServer.controlPlaneRequestChannelOpt.get, controlPlaneRequestProcessor, time, | ||
| 1, s"${SocketServer.ControlPlaneMetricPrefix}RequestHandlerAvgIdlePercent", SocketServer.ControlPlaneThreadPrefix) | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we need an authorization check here. The above authorization check only occurs if we are in legacy mode. Maybe perform a single authorization check at the top before branching based on adminManager being null or not?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It also occurs to me that we need tests for these KIP-500 states (this comment is a general comment, so probably unnecessary to add the test now -- just something we'll have to do before opening a PR to the
apacherepo)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yea, thanks I missed the authz thing. Will fix.
What kind of tests are you thinking? I think KafkaApis is mainly tested through integration/system tests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I could see a unit test that confirms unauthorized requests are denied (one version for legacy, one version for KIP-500). I could also see a KIP-500 unit test that confirms a mock QuotaCache is asked to handle the request. Then as long as QuotaCache is tested that should be enough.