chengnl / study Goto Github PK
View Code? Open in Web Editor NEW日常学习
日常学习
在ifeve网站上看到这一道题,开始的时候我理解错了,理解成:
实现一个流控程序,控制客户端每秒或者一段时间访问服务端不超过N次,客户端多线程并发请求。
自己的一段实现逻辑如下:
服务端:
import java.util.Date;
/**
*@author chengnl
*@date 2015年2月10日 下午8:52:25
*@version 1.0
*@Description:模拟服务
*/
public class MockServer {
private VisitCount visitCount;
private int maxLimitVisit=100;
public MockServer() {
this.visitCount=new VisitCount();
}
public int visit(){
int result=0;
long time = new Date().getSeconds();
if(time==this.visitCount.getTime()){
long count= this.visitCount.getCount().getAndIncrement();
if(count>this.maxLimitVisit-1)
result= 1;
}else{
synchronized (visitCount) {
if(time!=this.visitCount.getTime()){
this.visitCount.setTime(time);
this.visitCount.getCount().set(0);
}
}
long count= this.visitCount.getCount().getAndIncrement();
if(count>this.maxLimitVisit-1)
result= 1;
}
System.out.println("time="+time+",count="+this.visitCount.getCount()+",result="+result);
return result;
}
}
package exercise.concurrency.one.way1;
import java.util.concurrent.atomic.AtomicLong;
/**
*@author chengnl
*@date 2015年2月10日 下午8:48:43
*@version 1.0
*@Description:访问计数
*/
public class VisitCount {
private long time=0;
private AtomicLong count= new AtomicLong(0);
public long getTime() {
return time;
}
public void setTime(long time) {
this.time = time;
}
public AtomicLong getCount() {
return count;
}
}
思路:通过原子变量和同步机制,控制每秒每个客户端访问的次数.具体见study的exercise.concurrency.one.way1包里面。
思考应用场景:实际是一种服务端限流机制,当访问压力上来后,根据压力测试阀值,控制服务访问,确保服务不会崩溃。
采用的策略:是访问舍弃,也就是压力过大后直接舍弃访问,返回不能访问结果。如果要采用等待策略,则使用信号量。
回到正题,题目中实际是客户端限流,ifeve提供了几种实现方式:
方式一:
package exercise.concurrency.one.way3;
import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
/**
* @author chengnl
* @date 2015年2月10日 下午11:34:50
* @version 1.0
* @Description:TODO类描述
*/
public class MockClient2 {
final static int MAX_QPS = 10;
final static Semaphore semaphore = new Semaphore(MAX_QPS);
final static AtomicInteger accessCount = new AtomicInteger(0);
public static void main(String[] args) throws Exception {
// release semaphore thread
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
semaphore.release(accessCount.getAndSet(0));
}
}, 1000, 1000, TimeUnit.MILLISECONDS);
// lots of concurrent calls: 100 * 1000
ExecutorService pool = Executors.newFixedThreadPool(100);
for (int i = 100; i > 0; i--) {
final int x = i;
pool.submit(new Runnable() {
@Override
public void run() {
for (int j = 1000; j > 0; j--) {
try {
Thread.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
semaphore.acquireUninterruptibly(1);
accessCount.incrementAndGet();
remoteCall(x, j);
}
}
});
}
pool.shutdown();
pool.awaitTermination(1, TimeUnit.HOURS);
System.out.println("done");
}
private static void remoteCall(int i, int j) {
System.out.println(String.format("%s – %s: %d %d", new Date(),
Thread.currentThread(), i, j));
}
}
思路:使用信号量获取请求许可,没有就等待,另外开启线程重置。
方式二:
package exercise.concurrency.one.way2;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
/**
*@author chengnl
*@date 2015年2月10日 下午8:52:25
*@version 1.0
*@Description:模拟服务
*/
public class MockServer {
private AtomicLong count = new AtomicLong(100);
public MockServer() {
Executors.newSingleThreadScheduledExecutor().scheduleAtFixedRate(new Runnable(){
@Override
public void run() {
count.set(100);
System.out.println("1 秒过去了");
}
}, 1, 1, TimeUnit.SECONDS);
}
public int visit(){
if(count.decrementAndGet()>0){
System.out.println("允许访问。"+count.longValue());
return 0;
}
return 1;
}
}
思路:通过原子变量控制访问次数,开启单线程重置。
两种方式都很好的实现了客户端限流,一种通过信号量等待策略,一种是舍弃策略。
根据这个题目,引申应用场景:
1、在微服务架构中,服务于服务之间调用非常频繁,存在设计服务调用限流机制。
2、开放式平台服务接口中存在设计接口调用次数限制。服务端针对某一个凭证和方法限流。
基于这两个应用场景,存在两种方式限流:
1、客户端限流
限制低优先级调用流量,防止频繁调用。单服务访问限流,平滑的访问(阻塞队列,平滑舍弃)
2、服务端限流
服务端可以根据调用客户端和方法两个维度限流,确保服务正常运行,也有基于整个服务端服务的整体限流机制。
服务等待长时间阻塞存在问题:
线程在处理I/O资源(sockets,文件句柄,数据库连接等)时进入等待状态,就会占用资源,导致性能问题,所以要设置合理的舍弃机制,确保永远被阻塞,如超时,直接异常舍弃等。
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.