Semaphore信号量
Semaphore信号量非常适合高并发访问,新系统在上线之前,要对系统的访问量进行评估。这一般是根据以往的经验、数据、历年的访问量、推广力度等进行一个合理的评估,当评估值太大则投入的资源得不到实际的效果,会浪费资源;当评估值太小则某个时间点一个高峰值的访问量上来会直接压垮系统。
解决高并发关键在业务,要将业务进行划分,划分为不同的层次和模块。针对某个具体模块,使用nginx等进行分流,分给部署同一个系统的多个tomcat服务器,使其负载均衡。整个架构可能包括:商品系统、促销系统、购物车系统、支付系统等,在网络的入口处使用nginx,将流量分配到不同的模块,分别进行处理。下面是互联网企业关心的一些相关概念。nginx可以处理大概2000万的并发,若并发量更大的化,可以考虑在nginx之前添加LVS
PV(page view):网站的总访问量,页面浏览量或点击量,用户每刷新一次就会被记录一次。
UV(unique visitor):访问网站的一台电脑客户端为一个访客。一般来讲,时间上以00:00-24:00之间相同ip的客户端只记录一次。
QPS(query per second):每秒查询数,qps很大程度上代表了系统业务上的繁忙程度,每次请求的背后,可能对应着多次磁盘IO、多次网络请求、多个CPU时间片等。一旦当前qps超过所设定的预警阈值,可以考虑增加机器对集群扩容,以免压力过大导致宕机,可以根据前期的压力测试得到估值,再结合后期综合运维的情况,估算出阈值。
RT(response time):请求的响应时间,这个指标非常关键,直接说明前端用户的体验,因此任何系统设计师都想降低rt的时间。
当然还涉及CPU、内存、网络、磁盘等情况,更细节的问题很多,如:每秒select、update、delete操作的数量等数据库层面的统计。
一般来讲,对要上线的系统进行多轮压力测试以后,可以对系统进行峰值评估,采用所谓的80/20原则,即80%的访问请求将在20%的时间内到达。这样我们可以根据系统对应的PV计算出峰值qps。
峰值qps=(总PV*80%)/(60*60*24*20%)
然后在将总的峰值qps除以单台机器所能承受的最高qps值,就是所需要机器的数量
机器数=总的峰值qps/压测得到的单台机器极限qps
Semaphore控制系统的流量
拿到信号量的线程可以进入,否则就等待。通过acquire()和release()获得和释放访问许可,控制访问acquire()、release();之间代码段的线程个数。
UseSemaphore.java
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
public class UseSemaphore {
public static void main(String[] args) {
// 线程池
ExecutorService exec = Executors.newCachedThreadPool();
// 只能5个线程同时访问
final Semaphore semp = new Semaphore(5);
// 模拟20个客户端访问
for (int index = 0; index < 20; index++) {
final int NO = index;
Runnable run = new Runnable() {
public void run() {
try { //在semp.acquire();与semp.release();之间的代码最多允许5个线程同时执行
// 获取许可
semp.acquire();
System.out.println("Accessing: " + NO);
//模拟实际业务逻辑
Thread.sleep((long) (Math.random() * 10000));
// 访问完后,释放
semp.release();
} catch (InterruptedException e) {
}
}
};
exec.execute(run); //交给线程池处理
}
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
//关闭线程池
exec.shutdown();
}
}
在Eclipse的console中输出: