Skip to content

Commit

Permalink
api限流
Browse files Browse the repository at this point in the history
  • Loading branch information
yongmuzhang committed Jan 26, 2017
1 parent 3430d4b commit 052727c
Show file tree
Hide file tree
Showing 12 changed files with 336 additions and 0 deletions.
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/target
/ratelimiter.iml

/.idea
*~

logs/
41 changes: 41 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.zym.ratelimiter</groupId>
<artifactId>ratelimiter</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>ratelimiter Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.2.1</version>
</dependency>
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz-jobs</artifactId>
<version>2.2.1</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.21</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>ratelimiter</finalName>
</build>
</project>
20 changes: 20 additions & 0 deletions src/main/java/com/zym/ratelimiter/Main.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.zym.ratelimiter;

import com.zym.ratelimiter.model.Token;
import com.zym.ratelimiter.service.RateLimiterService;

/**
* Created by zym on 17/1/26.
*/
public class Main {
public static void main(String[] args) throws Exception {
RateLimiterService rateLimiterService = RateLimiterService.getInstance();
//请求api之前, 先获取令牌
Token token = rateLimiterService.pop();
if (token != null) {
System.out.println("成功请求API");
} else {
System.out.println("当前排队人数太多, 请稍后重试");
}
}
}
12 changes: 12 additions & 0 deletions src/main/java/com/zym/ratelimiter/config/Config.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.zym.ratelimiter.config;

/**
* Created by zym on 17/1/25.
*/
public class Config {
public static final String REDIS_HOST_ADDRESS = "127.0.0.1";
public static final Integer REDIS_HOST_PORT = 6379;
public static final String REDIS_HOST_PASSWORD = "";
public static final Integer TOKEN_BUCKET_LENGTH = 10;
public static final String TOKEN_BUCKET_NAME = "rate:limiter";
}
27 changes: 27 additions & 0 deletions src/main/java/com/zym/ratelimiter/job/TokenProducerJob.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.zym.ratelimiter.job;


import com.zym.ratelimiter.model.Token;
import com.zym.ratelimiter.service.RateLimiterService;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Date;

/**
* Created by zym on 17/1/26.
*/
public class TokenProducerJob implements Job {
private static Logger _log = LoggerFactory.getLogger(TokenProducerJob.class);
private RateLimiterService rateLimiterService = RateLimiterService.getInstance();
public TokenProducerJob() {
}

public void execute(JobExecutionContext context) throws JobExecutionException {
Token token = new Token((new Date().toString()));
rateLimiterService.push(token);
}
}
21 changes: 21 additions & 0 deletions src/main/java/com/zym/ratelimiter/model/Token.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.zym.ratelimiter.model;

/**
* Created by zym on 17/1/24.
*/
public class Token {
private String name;

public Token(String name) {
this.name = name;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

}
60 changes: 60 additions & 0 deletions src/main/java/com/zym/ratelimiter/model/TokenBucket.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package com.zym.ratelimiter.model;

import redis.clients.jedis.Jedis;

import java.util.List;

/**
* Created by zym on 17/1/24.
*/
public class TokenBucket {
private String name;
private Integer length;
private Jedis jedis;

public TokenBucket(String name, Integer length, Jedis jedis) {
this.name = name;
this.length = length;
this.jedis = jedis;
}

public Integer push(Token token) {
if (token == null) {
return 0;
} else {
Long size = jedis.llen(this.name);
if (size != null && size < this.length) {
jedis.lpush(this.name, token.getName());
return 1;
} else {
return 0;
}
}
}

public Integer push(List<Token> tokens) {
if (tokens != null && tokens.size() > 0) {
Long size = jedis.llen(this.name);
if ((tokens.size() + size) < this.length) {
for (Token token : tokens) {
jedis.lpush(this.name, token.getName());
}
return tokens.size();
} else {
return 0;
}
} else {
return 0;
}
}

public Token pop() {
String tokeName = jedis.lpop(this.name);
if (tokeName != null) {
return new Token(tokeName);
} else {
return null;
}
}

}
53 changes: 53 additions & 0 deletions src/main/java/com/zym/ratelimiter/service/RateLimiterService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package com.zym.ratelimiter.service;


import com.zym.ratelimiter.config.Config;
import com.zym.ratelimiter.model.Token;
import com.zym.ratelimiter.model.TokenBucket;
import redis.clients.jedis.Jedis;

import java.util.concurrent.locks.ReentrantLock;

/**
* Created by zym on 17/1/24.
*/
public class RateLimiterService {
private static RateLimiterService rateLimiterService;
private static TokenBucket tokenBucket;
private static ReentrantLock lock = new ReentrantLock();
static {
Jedis jedis = new Jedis(Config.REDIS_HOST_ADDRESS, Config.REDIS_HOST_PORT);
// jedis.auth(Config.REDIS_HOST_PASSWORD);
TokenBucket tokenBucket = new TokenBucket(Config.TOKEN_BUCKET_NAME, Config.TOKEN_BUCKET_LENGTH, jedis);
rateLimiterService = new RateLimiterService(tokenBucket);
}
private RateLimiterService(TokenBucket tokenBucket) {
this.tokenBucket = tokenBucket;
}
public static RateLimiterService getInstance(){
return rateLimiterService;
}

public Token pop(){
lock.lock();
Token token = null;
try {
token = this.tokenBucket.pop();
} finally {
lock.unlock();
}
return token;
}

public Integer push(Token token){
lock.lock();
Integer num = 0;
try {
num = this.tokenBucket.push(token);
} finally {
lock.unlock();
}
return num;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package com.zym.ratelimiter.trigger;

import com.zym.ratelimiter.job.TokenProducerJob;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerFactory;
import org.quartz.Trigger;
import org.quartz.impl.StdSchedulerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Date;

import static org.quartz.CronScheduleBuilder.cronSchedule;
import static org.quartz.DateBuilder.nextGivenSecondDate;
import static org.quartz.JobBuilder.newJob;
import static org.quartz.TriggerBuilder.newTrigger;

/**
* Created by zym on 17/1/26.
*/
public class TokenProducerTrigger {

public void run() throws Exception {
Logger log = LoggerFactory.getLogger(TokenProducerTrigger.class);

log.info("------- Initializing ----------------------");

SchedulerFactory schedulerFactory = new StdSchedulerFactory();
Scheduler scheduler = schedulerFactory.getScheduler();

log.info("------- Initialization Complete -----------");

Date runTime = nextGivenSecondDate(new Date(), 10);

log.info("------- Scheduling Job -------------------");

JobDetail tokenProducerJob = newJob(TokenProducerJob.class).withIdentity("tokenProducerJob", "rateLimiter").build();

Trigger tokenProducerTrigger = newTrigger()
.withIdentity("tokenProducerTrigger", "rateLimiter")
.withSchedule(cronSchedule("0/20 * * * * ?"))
.startAt(runTime).build();

scheduler.scheduleJob(tokenProducerJob, tokenProducerTrigger);
log.info(tokenProducerJob.getKey() + " will run at: " + runTime);

scheduler.start();

log.info("------- Started Scheduler -----------------");
}

public static void main(String[] args) throws Exception {

TokenProducerTrigger tokenProducerTrigger = new TokenProducerTrigger();
tokenProducerTrigger.run();

}
}
24 changes: 24 additions & 0 deletions src/main/resources/log4j.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">

<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">

<appender name="default" class="org.apache.log4j.ConsoleAppender">
<param name="target" value="System.out"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="[%p] %d{dd MMM hh:mm:ss.SSS aa} %t [%c]%n%m%n%n"/>
</layout>
</appender>


<logger name="org.quartz">
<level value="info" />
</logger>

<root>
<level value="info" />
<appender-ref ref="default" />
</root>


</log4j:configuration>
7 changes: 7 additions & 0 deletions src/main/webapp/WEB-INF/web.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
<display-name>Archetype Created Web Application</display-name>
</web-app>
5 changes: 5 additions & 0 deletions src/main/webapp/index.jsp
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<html>
<body>
<h2>Hello World!</h2>
</body>
</html>

0 comments on commit 052727c

Please sign in to comment.