From bd83012e761232c743aaeb597bd2dc0a44ed2371 Mon Sep 17 00:00:00 2001 From: James Abley Date: Fri, 8 May 2009 23:07:52 +0100 Subject: [PATCH] Add basic JMX functionality --- LICENSE | 1 - ivy/ivy.xml | 2 +- .../java/com/eternus/ratelimit/Enablable.java | 41 ++++++ .../com/eternus/ratelimit/FixedBucket.java | 9 ++ .../com/eternus/ratelimit/RateLimiter.java | 2 +- .../ratelimit/jmx/ManagedRateLimiter.java | 117 ++++++++++++++++++ .../jmx/ManagedRateLimiterMBean.java | 29 +++++ 7 files changed, 198 insertions(+), 3 deletions(-) create mode 100644 src/main/java/com/eternus/ratelimit/Enablable.java create mode 100644 src/main/java/com/eternus/ratelimit/jmx/ManagedRateLimiter.java create mode 100644 src/main/java/com/eternus/ratelimit/jmx/ManagedRateLimiterMBean.java diff --git a/LICENSE b/LICENSE index 0d0978e..4bf9f61 100644 --- a/LICENSE +++ b/LICENSE @@ -5,7 +5,6 @@ you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ivy/ivy.xml b/ivy/ivy.xml index a71a693..016d1ae 100644 --- a/ivy/ivy.xml +++ b/ivy/ivy.xml @@ -6,7 +6,7 @@ - + diff --git a/src/main/java/com/eternus/ratelimit/Enablable.java b/src/main/java/com/eternus/ratelimit/Enablable.java new file mode 100644 index 0000000..6862e38 --- /dev/null +++ b/src/main/java/com/eternus/ratelimit/Enablable.java @@ -0,0 +1,41 @@ +/* + * Copyright 2009 James Abley + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.eternus.ratelimit; + +/** + * Interface defining whether a service can be enabled or not. + * + * @author jabley + * + */ +public interface Enablable { + + /** + * Returns true if this service is enabled, otherwise false. + * + * @return true if this service is enabled, otherwise false + */ + boolean isEnabled(); + + /** + * Sets the enabled state of this service. + * + * @param enabled + * the enabled state + */ + void setEnabled(boolean enabled); + +} \ No newline at end of file diff --git a/src/main/java/com/eternus/ratelimit/FixedBucket.java b/src/main/java/com/eternus/ratelimit/FixedBucket.java index 99c5e7b..a1d1915 100644 --- a/src/main/java/com/eternus/ratelimit/FixedBucket.java +++ b/src/main/java/com/eternus/ratelimit/FixedBucket.java @@ -114,4 +114,13 @@ public boolean isEnabled() { return enabled; } + /** + * {@inheritDoc} + */ + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + + } diff --git a/src/main/java/com/eternus/ratelimit/RateLimiter.java b/src/main/java/com/eternus/ratelimit/RateLimiter.java index 6682075..8c07907 100644 --- a/src/main/java/com/eternus/ratelimit/RateLimiter.java +++ b/src/main/java/com/eternus/ratelimit/RateLimiter.java @@ -21,7 +21,7 @@ * @author jabley * */ -public interface RateLimiter { +public interface RateLimiter extends Enablable { /** * Method called by clients to check whether they should service the current request or not. Returns a non-null diff --git a/src/main/java/com/eternus/ratelimit/jmx/ManagedRateLimiter.java b/src/main/java/com/eternus/ratelimit/jmx/ManagedRateLimiter.java new file mode 100644 index 0000000..30c5cda --- /dev/null +++ b/src/main/java/com/eternus/ratelimit/jmx/ManagedRateLimiter.java @@ -0,0 +1,117 @@ +/* + * Copyright 2009 James Abley + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.eternus.ratelimit.jmx; + +import javax.management.MBeanNotificationInfo; +import javax.management.Notification; +import javax.management.NotificationBroadcasterSupport; +import javax.management.monitor.MonitorNotification; + +import com.eternus.ratelimit.Key; +import com.eternus.ratelimit.RateLimiter; +import com.eternus.ratelimit.Token; + +/** + * JMX MBean which will send out notifications around a {@link RateLimiter} implementation. + * + * @author jabley + * + */ +public class ManagedRateLimiter extends NotificationBroadcasterSupport implements RateLimiter, ManagedRateLimiterMBean { + + /** + * The name of the JXM notification that will be sent for successfully serviced requests. + */ + private static final String JMX_MONITOR_RATE_LIMIT_SERVICE_TYPE = "jmx.monitor.rate-limit.service"; + + /** + * The non-null delegate. + */ + private final RateLimiter delegate; + + /** + * The JMX notification sequence number. + */ + private long sequenceNumber; + + /** + * Creates a new {@link ManagedRateLimiter} which will delegate the implementation to the specified non-null + * {@link RateLimiter}. + * + * @param delegate + * a non-null {@link RateLimiter} around which this MBean will send notifications + */ + public ManagedRateLimiter(RateLimiter delegate) { + if (delegate == null) { + throw new IllegalArgumentException("delegate cannot be null"); + } + this.delegate = delegate; + } + + /** + * {@inheritDoc} + */ + @Override + public MBeanNotificationInfo[] getNotificationInfo() { + String[] types = new String[] { JMX_MONITOR_RATE_LIMIT_SERVICE_TYPE, + MonitorNotification.THRESHOLD_VALUE_EXCEEDED }; + MBeanNotificationInfo info = new MBeanNotificationInfo(types, Notification.class.getName(), + "rate-limited request processed"); + return new MBeanNotificationInfo[] { info }; + } + + /** + * {@inheritDoc} + */ + @Override + public Token getToken(Key key) { + Token token = delegate.getToken(key); + + if (token.isUsable()) { + sendNotification(new Notification(JMX_MONITOR_RATE_LIMIT_SERVICE_TYPE, this, getSequenceNumber(), + "allowed request " + key)); + } else { + sendNotification(new Notification(MonitorNotification.THRESHOLD_VALUE_EXCEEDED, this, getSequenceNumber(), + "denied request " + key)); + } + + return token; + } + + /** + * {@inheritDoc} + */ + public boolean isEnabled() { + return this.delegate.isEnabled(); + } + + /** + * {@inheritDoc} + */ + public void setEnabled(boolean enabled) { + this.delegate.setEnabled(enabled); + } + + /** + * Returns the next sequence number for the JMX notification. + * + * @return the next positive sequence number + */ + private synchronized long getSequenceNumber() { + return ++this.sequenceNumber; + } + +} diff --git a/src/main/java/com/eternus/ratelimit/jmx/ManagedRateLimiterMBean.java b/src/main/java/com/eternus/ratelimit/jmx/ManagedRateLimiterMBean.java new file mode 100644 index 0000000..f089a8f --- /dev/null +++ b/src/main/java/com/eternus/ratelimit/jmx/ManagedRateLimiterMBean.java @@ -0,0 +1,29 @@ +/* + * Copyright 2009 James Abley + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.eternus.ratelimit.jmx; + +import com.eternus.ratelimit.Enablable; +import com.eternus.ratelimit.RateLimiter; + +/** + * MBean interface for managing {@link RateLimiter}s. + * + * @author jabley + * + */ +public interface ManagedRateLimiterMBean extends Enablable { + +}