KAFKA-15778 & KAFKA-15779: Implement metrics manager (KIP-714) - #14699
Conversation
…ance state (KIP-714)
| return INSTANCE; | ||
| } | ||
| // Max cache size (16k active client connections per broker) | ||
| private static final int CM_CACHE_MAX_SIZE = 16384; |
There was a problem hiding this comment.
The cache should hold the information of all connected client hence it should support the number of clients that can connect to single broker. Kept it high enough for now but would require suggestions for best approach. @AndrewJSchofield mentioned that it might be the max.connections broker config but the configs uppoer bound is Int.MAX_VALUE hence we need to think about better upper bound here.
There was a problem hiding this comment.
Is this enough? A broker could handle 100s of Ks of connections.
There was a problem hiding this comment.
Then should it be in low 100K i.e. 2^17 = 131072? I am not sure what the right config should be here, I know the cloud providers like MSK typically provides 3000 active connections per broker where this limit is higher in case of Confluent but what typically are the active number of client connecting to broker should be.
There was a problem hiding this comment.
The challenge is that the connections can vary depending on the type of broker host. Larger instance typically can accommodate more connections. Do we need to make this an LRU cache? If a client is terminated or idle, we should remove them from the cache. Otherwise, we probably should just rely on the existing max.connections to control the client connections?
There was a problem hiding this comment.
Do we need to make this an LRU cache? If a client is terminated or idle, we should remove them from the cache
I have started with LRU cache and planning to improve this with cache which timebounds the connection. The KIP says: client instance specific state is maintained in broker memory up to MAX(60*1000, PushIntervalMs * 3) milliseconds. I ll add improvement on the cache to respect that: https://issues.apache.org/jira/browse/KAFKA-15813
| } | ||
| // Max cache size (16k active client connections per broker) | ||
| private static final int CM_CACHE_MAX_SIZE = 16384; | ||
| private final Cache<Uuid, ClientMetricsInstance> clientInstanceCache; |
There was a problem hiding this comment.
The KIP-714 says: This client instance specific state is maintained in broker memory up to MAX(60*1000, PushIntervalMs * 3) milliseconds and is used to enforce the push interval rate-limiting. There is no persistence of client instance metrics state across broker restarts or between brokers.
I have started with LRUCache with oldest entry eviction but will implement something similar to Selector.IdleExpiryManager which cleansup old connections.
|
@junrao @hachikuji @AndrewJSchofield @mjsax Please if I can get feedback on the PR. |
junrao
left a comment
There was a problem hiding this comment.
@apoorvmittal10 : Thanks for the PR. Made a pass of non-testing files. Left a few comments.
| */ | ||
| package kafka.server; | ||
|
|
||
| import java.util.Collections; |
There was a problem hiding this comment.
Should this class be in the same package as other client metric related classes like DefaultClientTelemetryPayload?
There was a problem hiding this comment.
The reason I kept this at kafka.server package as I see all managers (in scala) processing API calls from KafkaApis.scala resides kafka.server package.
| @Override | ||
| public void close() throws IOException { | ||
| // TODO: Implement the close logic to close the client metrics manager. | ||
| // Do nothing for now. |
There was a problem hiding this comment.
Should we clear up the internal data?
There was a problem hiding this comment.
I have cleaned up the subscription map, there is no method currently exposed to clear cache but I ll add that as improvement while improving the cache code.
| // broker's point of view. But the broker does not have this information rather the port could be | ||
| // the broker's port where the client connection is established. We might want to consider removing | ||
| // the client source port from the KIP or use broker port if that can be helpful. | ||
| // TODO: fix port |
There was a problem hiding this comment.
We populate RequestContext in SocketServer. We could obtain the client port through transportLayer.socketChannel().socket().getPort in KafkaChannel.
There was a problem hiding this comment.
Thanks a lot @junrao this is helpful. I will make the changes in subsequent PR to address this. I have created following jira for same: https://issues.apache.org/jira/browse/KAFKA-15811
| } | ||
|
|
||
| private static ByteBuffer decompressMetricsData(CompressionType compressionType, byte[] metrics) { | ||
| // TODO: Add support for decompression of metrics data |
There was a problem hiding this comment.
So, this will be added in a future PR?
There was a problem hiding this comment.
Yes, I have created jira in parent KIP-714 task to address this: https://issues.apache.org/jira/browse/KAFKA-15807. I am planning to get end-to-end metrics flow without compression first.
Thanks a lot for the review @junrao . I have addressed the comments and have a question related to throttleTimeMs for errors in the comments. Please if you can re-review. |
junrao
left a comment
There was a problem hiding this comment.
@apoorvmittal10 : Thanks for the updated PR. Made a pass of all files. A few more comments.
| public PushTelemetryResponse createResponse(int throttleTimeMs, Errors errors) { | ||
| PushTelemetryResponseData responseData = new PushTelemetryResponseData(); | ||
| responseData.setErrorCode(errors.code()); | ||
| responseData.setThrottleTimeMs(throttleTimeMs); |
There was a problem hiding this comment.
The following is my understanding. There are two types of throttling.
- Generic request throttling based on % of CPU a client uses on the broker. This applies to any request, including
PushTelemetry. In this case, the error code is none and thethrottleTimeMsfield is set. The client will mute the channel forthrottleTimeMsbefore sending future requests. PushTelemetryspecific throttling because PushTelemetry is sent too frequently. In this case, we should set THROTTLING_QUOTA_EXCEEDED as the error code and avoid setting thethrottleTimeMsfield since we don't want to the client to mute the channel for all requests.
| } | ||
|
|
||
| public boolean terminating() { | ||
| return terminating; |
There was a problem hiding this comment.
After the instance is terminated, when do we remove the instance form the in-memory state?
There was a problem hiding this comment.
The reason why I didn't remove the instance from in-memory cache as the subsequent requests from terminated client should be rejected. Having said that, the terminated client should also not remain in-memory forever hence the terminated client should be removed from cache as per the eviction policy of cache i.e. MAX(60*1000, PushIntervalMs * 3) milliseconds. This shall be inherently handled by the cache improvement task where we have some time based eviction policy.
|
Thanks for reviewing @junrao, I have updated the PR. |
| @Test | ||
| public void testMaybeUpdateRequestEpochValid() { | ||
| // First request should be accepted. | ||
| assertTrue(clientInstance.maybeUpdateGetRequestEpoch(System.currentTimeMillis())); |
There was a problem hiding this comment.
Could we use MockTime instead of System time?
There was a problem hiding this comment.
As the class/methods I am testing do not have Time reference rather just tries to updates the epoch supplied hence I didn't see any value in using MockTime. However I did change the code and tests for ClientMetricsManager where these methods are invoked from, I started using Time in ClientMetricsManager and corresponding MockTime in ClientMetricsManagerTest which eliminated the use of Thread.sleep.
Please let me know if I am missing anything here.
|
Thanks @junrao for leaving the comments, I have tried to address them. |
junrao
left a comment
There was a problem hiding this comment.
@apoorvmittal10 : Thanks for the updated PR. Left a few more comments.
|
@junrao @AndrewJSchofield Thanks for the LGTM and approving the PR. Below is the test run status, none of the failing tests are related to the changes in the PR but I have tried to debug further. Among 20, 17 have already been reported as flaky test in jira, for remaining 3 I tried to locally reproduce but couldn't hence created New failing - 20
|
|
@apoorvmittal10 : Thanks for triaging the tests. In the mailing list, it seems that we are still leaning towards requiring green builds before merging a PR. |
|
Just merged #14632. Triggering another test run to make sure there are no new issues. |
|
@apoorvmittal10 : It seems that the build for JDK 17 and Scala 2.13 didn't complete. |
Thanks @junrao. Strange to see the failure in. |
|
Hi @junrao, I have triaged the test cases as per the latest run.
|
|
@junrao The tests failures are not related to the changes. |
junrao
left a comment
There was a problem hiding this comment.
Thanks for the analysis, @apoorvmittal10. The PR LGTM.
…e#14699) The PR provide implementation for client metrics manager along with other classes. Manager is responsible to support 3 operations: UpdateSubscription - From kafka-configs.sh and reload from metadata cache. Process Get Telemetry Request - From KafkaApis.scala Process Push Telemetry Request - From KafkaApis.scala Manager maintains an in-memory cache to keep track of client instances against their instance id. Reviewers: Andrew Schofield <aschofield@confluent.io>, Jun Rao <junrao@gmail.com>
…e#14699) The PR provide implementation for client metrics manager along with other classes. Manager is responsible to support 3 operations: UpdateSubscription - From kafka-configs.sh and reload from metadata cache. Process Get Telemetry Request - From KafkaApis.scala Process Push Telemetry Request - From KafkaApis.scala Manager maintains an in-memory cache to keep track of client instances against their instance id. Reviewers: Andrew Schofield <aschofield@confluent.io>, Jun Rao <junrao@gmail.com>
…e#14699) The PR provide implementation for client metrics manager along with other classes. Manager is responsible to support 3 operations: UpdateSubscription - From kafka-configs.sh and reload from metadata cache. Process Get Telemetry Request - From KafkaApis.scala Process Push Telemetry Request - From KafkaApis.scala Manager maintains an in-memory cache to keep track of client instances against their instance id. Reviewers: Andrew Schofield <aschofield@confluent.io>, Jun Rao <junrao@gmail.com>
| return request.getErrorResponse(0, exception); | ||
| } finally { | ||
| // Update the client instance with the latest push request parameters. | ||
| clientInstance.terminating(request.data().terminating()); |
There was a problem hiding this comment.
We noticed an edge case and have opened #23094 to discuss it. It would be great to get your review :)
The PR provide implementation for client metrics manager along with other classes. Manager is responsible to support 3 operations:
kafka-configs.shand reload from metadata cache.Manager maintains an in-memory cache to keep track of client instances against their instance id.
Committer Checklist (excluded from commit message)