Giter Club home page Giter Club logo

study's People

Contributors

chengnl avatar

Stargazers

 avatar  avatar  avatar

Watchers

 avatar  avatar

study's Issues

实现一个流控程序。控制客户端每秒调用某个远程服务不超过N次,客户端是会多线程并发调用。

在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,文件句柄,数据库连接等)时进入等待状态,就会占用资源,导致性能问题,所以要设置合理的舍弃机制,确保永远被阻塞,如超时,直接异常舍弃等。

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.