Skip to content

Commit

Permalink
✨ add host quota with iot guide http project
Browse files Browse the repository at this point in the history
  • Loading branch information
sanshengshui committed Aug 12, 2019
1 parent 5b3becf commit 3b64367
Show file tree
Hide file tree
Showing 8 changed files with 205 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package com.sanshengshui.http.quota;

import com.sanshengshui.http.quota.inmemory.IntervalRegistryCleaner;
import com.sanshengshui.http.quota.inmemory.IntervalRegistryLogger;
import com.sanshengshui.http.quota.inmemory.KeyBasedIntervalRegistry;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

/**
* @author james mu
* @date 2019/8/12 上午9:16
*/
public class AbstractQuotaService implements QuotaService {

private final KeyBasedIntervalRegistry requestRegistry;
private final RequestLimitPolicy requestsPolicy;
private final IntervalRegistryCleaner registryCleaner;
private final IntervalRegistryLogger registryLogger;
private final boolean enabled;

public AbstractQuotaService(KeyBasedIntervalRegistry requestRegistry, RequestLimitPolicy requestsPolicy,
IntervalRegistryCleaner registryCleaner, IntervalRegistryLogger registryLogger,
boolean enabled) {
this.requestRegistry = requestRegistry;
this.requestsPolicy = requestsPolicy;
this.registryCleaner = registryCleaner;
this.registryLogger = registryLogger;
this.enabled = enabled;
}

@PostConstruct
public void init() {
if (enabled) {
registryCleaner.schedule();
registryLogger.schedule();
}
}

@PreDestroy
public void close() {
if (enabled) {
registryCleaner.stop();
registryLogger.stop();
}
}

@Override
public boolean isQuotaExceeded(String key){
if (enabled) {
long count = requestRegistry.tick(key);
return !requestsPolicy.isValid(count);
}
return false;
}
}


Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.sanshengshui.http.quota;

/**
* @author james mu
* @date 2019/8/12 上午9:14
*/
public interface QuotaService {

boolean isQuotaExceeded(String key);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.sanshengshui.http.quota;

/**
* @author james mu
* @date 2019/8/12 上午9:18
*/
public abstract class RequestLimitPolicy {

private final long limit;

public RequestLimitPolicy(long limit) {
this.limit = limit;
}

public boolean isValid(long currentValue) {
return currentValue <= limit;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.sanshengshui.http.quota.host;

import com.sanshengshui.http.quota.inmemory.IntervalRegistryCleaner;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

/**
* @author james mu
* @date 2019/8/12 上午9:49
*/
@Component
public class HostIntervalRegistryCleaner extends IntervalRegistryCleaner {

public HostIntervalRegistryCleaner(HostRequestIntervalRegistry intervalCleaner,
@Value("${quota.host.cleanPeriodMs}") long cleanPeriodMs) {
super(intervalCleaner, cleanPeriodMs);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.sanshengshui.http.quota.host;

import com.sanshengshui.http.quota.inmemory.IntervalRegistryLogger;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
* @author james mu
* @date 2019/8/12 上午10:03
*/
@Slf4j
@Component
public class HostIntervalRegistryLogger extends IntervalRegistryLogger {

private final long logIntervalMin;

public HostIntervalRegistryLogger(@Value("${quota.host.log.topSize}") int topSize,
@Value("${quota.host.log.intervalMin}") long logIntervalMin,
HostRequestIntervalRegistry intervalRegistry) {
super(topSize, logIntervalMin, intervalRegistry);
this.logIntervalMin = logIntervalMin;
}

protected void log(Map<String, Long> top, int uniqHosts, long requestsCount) {
long rps = requestsCount / TimeUnit.MINUTES.toSeconds(logIntervalMin);
StringBuilder builder = new StringBuilder("Quota Statistic : ");
builder.append("uniqHosts : ").append(uniqHosts).append("; ");
builder.append("requestsCount : ").append(requestsCount).append("; ");
builder.append("RPS : ").append(rps).append(" ");
builder.append("top -> ");
for (Map.Entry<String, Long> host : top.entrySet()) {
builder.append(host.getKey()).append(" : ").append(host.getValue()).append("; ");
}

log.info(builder.toString());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.sanshengshui.http.quota.host;

import com.sanshengshui.http.quota.inmemory.KeyBasedIntervalRegistry;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

/**
* @author james mu
* @date 2019/8/12 上午9:56
*/
@Component
@Slf4j
public class HostRequestIntervalRegistry extends KeyBasedIntervalRegistry {

public HostRequestIntervalRegistry(@Value("${quota.host.intervalMs}") long intervalDurationMs,
@Value("${quota.host.ttlMs}") long ttlMs,
@Value("${quota.host.whitelist}") String whiteList,
@Value("${quota.host.blacklist}") String blackList) {
super(intervalDurationMs, ttlMs, whiteList, blackList, "host");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.sanshengshui.http.quota.host;

import com.sanshengshui.http.quota.RequestLimitPolicy;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

/**
* @author james mu
* @date 2019/8/12 上午10:14
*/
@Component
public class HostRequestLimitPolicy extends RequestLimitPolicy {

public HostRequestLimitPolicy(@Value("${quota.host.limit}") long limit) {
super(limit);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.sanshengshui.http.quota.host;

import com.sanshengshui.http.quota.AbstractQuotaService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

/**
* @author james mu
* @date 2019/8/12 上午9:13
*/
@Service
@Slf4j
public class HostRequestsQuotaService extends AbstractQuotaService {

public HostRequestsQuotaService(HostRequestIntervalRegistry requestRegistry, HostRequestLimitPolicy requestsPolicy,
HostIntervalRegistryCleaner registryCleaner, HostIntervalRegistryLogger registryLogger,
@Value("${quota.host.enabled}") boolean enabled) {
super(requestRegistry, requestsPolicy, registryCleaner, registryLogger, enabled);
}
}

0 comments on commit 3b64367

Please sign in to comment.