Package com.linkedin.venice.listener
Class ReadQuotaEnforcementHandler
java.lang.Object
io.netty.channel.ChannelHandlerAdapter
io.netty.channel.ChannelInboundHandlerAdapter
io.netty.channel.SimpleChannelInboundHandler<RouterRequest>
com.linkedin.venice.listener.ReadQuotaEnforcementHandler
- All Implemented Interfaces:
RoutingDataRepository.RoutingDataChangedListener
,StoreDataChangedListener
,io.netty.channel.ChannelHandler
,io.netty.channel.ChannelInboundHandler
@Sharable
public class ReadQuotaEnforcementHandler
extends io.netty.channel.SimpleChannelInboundHandler<RouterRequest>
implements RoutingDataRepository.RoutingDataChangedListener, StoreDataChangedListener
-
Nested Class Summary
Nested classes/interfaces inherited from interface io.netty.channel.ChannelHandler
io.netty.channel.ChannelHandler.Sharable
-
Field Summary
-
Constructor Summary
ConstructorDescriptionReadQuotaEnforcementHandler
(VeniceServerConfig serverConfig, ReadOnlyStoreRepository storeRepository, CompletableFuture<HelixCustomizedViewOfflinePushRepository> customizedViewRepository, String nodeId, AggServerQuotaUsageStats stats, io.tehuti.metrics.MetricsRepository metricsRepository) ReadQuotaEnforcementHandler
(VeniceServerConfig serverConfig, ReadOnlyStoreRepository storeRepository, CompletableFuture<HelixCustomizedViewOfflinePushRepository> customizedViewRepository, String nodeId, AggServerQuotaUsageStats stats, io.tehuti.metrics.MetricsRepository metricsRepository, Clock clock) -
Method Summary
Modifier and TypeMethodDescriptionvoid
channelRead0
(io.netty.channel.ChannelHandlerContext ctx, RouterRequest request) enforceQuota
(RouterRequest request) Enforce quota for a given request.Helper methods for unit testingprotected static double
getNodeResponsibilityForQuota
(PartitionAssignment partitionAssignment, String nodeId) Recalculates the amount of quota that this node should serve given the partition assignment.static int
getRcu
(RouterRequest request) Initially, this is the key count.getStats()
void
handleStoreChanged
(Store store) This is where we add newTokenBucket
for new store version and remove irrelevant ones.void
handleStoreCreated
(Store store) Do NOT try to acquire the lock of store repository again in the implementation, otherwise a dead lock issue will happen.void
handleStoreDeleted
(String storeName) final void
init()
Initialize token buckets for all resources in the customized view repository.boolean
We only ever expect the initialized value to flip from false to true, but that initialization might happen in a different thread.void
onCustomizedViewAdded
(PartitionAssignment partitionAssignment) void
onCustomizedViewChange
(PartitionAssignment partitionAssignment) void
onExternalViewChange
(PartitionAssignment partitionAssignment) Handle routing data changed event.void
onPartitionStatusChange
(String topic, ReadOnlyPartitionStatus partitionStatus) void
onRoutingDataDeleted
(String kafkaTopic) Methods inherited from class io.netty.channel.SimpleChannelInboundHandler
acceptInboundMessage, channelRead
Methods inherited from class io.netty.channel.ChannelInboundHandlerAdapter
channelActive, channelInactive, channelReadComplete, channelRegistered, channelUnregistered, channelWritabilityChanged, exceptionCaught, userEventTriggered
Methods inherited from class io.netty.channel.ChannelHandlerAdapter
ensureNotSharable, handlerAdded, handlerRemoved, isSharable
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
Methods inherited from interface io.netty.channel.ChannelHandler
handlerAdded, handlerRemoved
Methods inherited from interface com.linkedin.venice.meta.StoreDataChangedListener
handleStoreDeleted
-
Field Details
-
SERVER_OVER_CAPACITY_MSG
- See Also:
-
INVALID_REQUEST_RESOURCE_MSG
- See Also:
-
-
Constructor Details
-
ReadQuotaEnforcementHandler
public ReadQuotaEnforcementHandler(VeniceServerConfig serverConfig, ReadOnlyStoreRepository storeRepository, CompletableFuture<HelixCustomizedViewOfflinePushRepository> customizedViewRepository, String nodeId, AggServerQuotaUsageStats stats, io.tehuti.metrics.MetricsRepository metricsRepository) -
ReadQuotaEnforcementHandler
public ReadQuotaEnforcementHandler(VeniceServerConfig serverConfig, ReadOnlyStoreRepository storeRepository, CompletableFuture<HelixCustomizedViewOfflinePushRepository> customizedViewRepository, String nodeId, AggServerQuotaUsageStats stats, io.tehuti.metrics.MetricsRepository metricsRepository, Clock clock)
-
-
Method Details
-
getRcu
Initially, this is the key count. As we develop a more accurate capacity model, this method can be refined.- Parameters:
request
-- Returns:
-
getNodeResponsibilityForQuota
protected static double getNodeResponsibilityForQuota(PartitionAssignment partitionAssignment, String nodeId) Recalculates the amount of quota that this node should serve given the partition assignment. Assumes each partition gets an even portion of quota, and for each partition divides the quota by the readyToServe instances.- Parameters:
partitionAssignment
-nodeId
-- Returns:
-
init
public final void init()Initialize token buckets for all resources in the customized view repository. -
isInitialized
public boolean isInitialized()We only ever expect the initialized value to flip from false to true, but that initialization might happen in a different thread. By only checking the volatile variable if it is false, we guarantee that we see the change as early as possible and also allow the thread to cache the value once it goes true.- Returns:
-
enforceQuota
Enforce quota for a given request. This is common to both HTTP and GRPC handlers. Respective handlers will take actions such as retaining the request and passing it to the next handler, or sending an error response.- Parameters:
request
- RouterRequest- Returns:
- QuotaEnforcementResult
-
channelRead0
- Specified by:
channelRead0
in classio.netty.channel.SimpleChannelInboundHandler<RouterRequest>
-
onExternalViewChange
Description copied from interface:RoutingDataRepository.RoutingDataChangedListener
Handle routing data changed event.- Specified by:
onExternalViewChange
in interfaceRoutingDataRepository.RoutingDataChangedListener
- Parameters:
partitionAssignment
- Newest partitions assignments information including resource name and all of instances assigned to this resource. If the number of partition is 0, it means the kafka topic is deleted.
-
onCustomizedViewChange
- Specified by:
onCustomizedViewChange
in interfaceRoutingDataRepository.RoutingDataChangedListener
-
onCustomizedViewAdded
- Specified by:
onCustomizedViewAdded
in interfaceRoutingDataRepository.RoutingDataChangedListener
-
onPartitionStatusChange
- Specified by:
onPartitionStatusChange
in interfaceRoutingDataRepository.RoutingDataChangedListener
-
onRoutingDataDeleted
- Specified by:
onRoutingDataDeleted
in interfaceRoutingDataRepository.RoutingDataChangedListener
-
handleStoreCreated
Description copied from interface:StoreDataChangedListener
Do NOT try to acquire the lock of store repository again in the implementation, otherwise a dead lock issue will happen.- Specified by:
handleStoreCreated
in interfaceStoreDataChangedListener
-
handleStoreDeleted
- Specified by:
handleStoreDeleted
in interfaceStoreDataChangedListener
-
handleStoreChanged
This is where we add newTokenBucket
for new store version and remove irrelevant ones. We should keep the same number of token buckets as the number of active versions. This is because readers like FC might be lagging behind or vice versa. This way quota will still be enforced properly during the version swap or transition period.- Specified by:
handleStoreChanged
in interfaceStoreDataChangedListener
-
getActiveStoreVersions
Helper methods for unit testing -
getStoreRepository
-
getStats
-