使用并发工具实现 RPC 调用流量控制
前言
RPC 服务中,每个服务的容量都是有限的,即资源有限,只能承受住给定的网络请求,所以,在设计 RPC 框架的时候,一定要考虑流量控制这个问题。而 Java 中,实现流量控制有很多中方式,今天说 2 种。
Semaphore 实现流控
代码:
static Semaphore semaphore = new Semaphore(100);
public static void main(String[] args) {
Executor timeTask = Executors.newScheduledThreadPool(1);
((ScheduledExecutorService) timeTask).scheduleAtFixedRate(
() -> semaphore.release(100 - semaphore.availablePermits()), 1000, 1000,
TimeUnit.MILLISECONDS);
Executor pool = Executors.newFixedThreadPool(100);
for (int i = 0; i < 100; i++) {
final int num = i;
pool.execute(() -> {
for (; ; ) {
for (int j = 0; j < 200; j++) {
if (semaphore.tryAcquire()) {
callRpc(num, j);
} else {
System.err.println("call fail");
}
}
}
});
}
}
private static void callRpc(int num, int j) {
System.out.println(String.format("%s - %s: %d %d", new Date(), Thread.currentThread(), num, j));
}
代码中,我们模拟了 100 个线程,每个线程无限调用 RPC。
同时使用另一个定时任务,定时更新 Semaphore 可用许可为 100。
客户端线程调用时,会尝试获取信号量,当获取成功时,才会调用调用 RPC,反之,打印失败。
这个小程序实现了每秒钟限制 100 个请求的 RPC 的流量控制。
AtomicInteger 实现流控
代码:
static AtomicInteger count = new AtomicInteger();
public static void main(String[] args) {
Executor timeTask = Executors.newScheduledThreadPool(1);
((ScheduledExecutorService) timeTask).scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
count.getAndSet(100);
}
}, 1000, 1000, TimeUnit.MILLISECONDS);
Executor pool = Executors.newFixedThreadPool(100);
for (int i = 0; i < 100; i++) {
final int num = i;
pool.execute(() -> {
for (; ; ) {
for (int j = 0; j < 200; j++) {
if (count.get() >= 0) {// 快速判断,否则大量的 CAS 操作将会定时任务更新计数器 count
if (count.decrementAndGet() >= 0) {
callRpc(num, j);
}
}
}
}
});
}
}
private static void callRpc(int num, int j) {
System.out.println(String.format("%s - %s: %d %d", new Date(), Thread.currentThread(), num, j));
}
这段代码和上面的类似,只是使用的 API 不同,这里使用的是 CAS。通过对 CAS 递减,达到流控的目的。
注意,这里有一个双重判断,先判断 count.get() >= 0,为什么呢?
如果直接使用 decrementAndGet 方法,则会使用 CAS,100 个线程并发使用 CAS ,将会导致定时任务的 CAS 操作不够及时。
所以,先判断,是否小于0 ,如果小于0了,就不必尝试 CAS,避免影响定时任务。
使用并发工具实现 RPC 调用流量控制的更多相关文章
- 《精通并发与Netty》学习笔记(07 - 基于Thrift实现Java与Python的RPC调用)
上节我们介绍了基于Thrift实现java与java的RPC调用,本节我们基于Thrift实现Java与Python的RPC调用 首先,修改data.thirft文件,将命名空间由java改为py n ...
- java中的并发工具类
在jdk的并发包里提供了几个非常有用的并发工具类.CountDownLatdch.CyclicBarrier和Semaphore工具类提供了一种并发流程控制的手段,Exchanger工具类则提供了在线 ...
- Java中的4个并发工具类 CountDownLatch CyclicBarrier Semaphore Exchanger
在 java.util.concurrent 包中提供了 4 个有用的并发工具类 CountDownLatch 允许一个或多个线程等待其他线程完成操作,课题点 Thread 类的 join() 方法 ...
- Java中的并发工具类(CountDownLatch、CyclicBarrier、Semaphore、Exchanger)
在JDK的并发包里提供了很多有意思的并发工具类.CountDownLatch.CyclicBarrier和Semaphore 工具类提供了一种并发流程控制的手段,Exchanger 工具类则提供了在线 ...
- 并发工具类(三)控制并发线程的数量 Semphore
前言 JDK中为了处理线程之间的同步问题,除了提供锁机制之外,还提供了几个非常有用的并发工具类:CountDownLatch.CyclicBarrier.Semphore.Exchanger.Ph ...
- 基于AQS实现的Java并发工具类
本文主要介绍一下基于AQS实现的Java并发工具类的作用,然后简单谈一下该工具类的实现原理.其实都是AQS的相关知识,只不过在AQS上包装了一下而已.本文也是基于您在有AQS的相关知识基础上,进行讲解 ...
- 25.大白话说java并发工具类-CountDownLatch,CyclicBarrier,Semaphore,Exchanger
1. 倒计时器CountDownLatch 在多线程协作完成业务功能时,有时候需要等待其他多个线程完成任务之后,主线程才能继续往下执行业务功能,在这种的业务场景下,通常可以使用Thread类的join ...
- java并发之并发工具
在JDK的并发包里提供了几个非常有用的并发工具类.CountDownLatch.CyclicBarrier和Semaphore工具类提供了一种并发流程控制的手段,Exchanger工具类则提供了在线程 ...
- Java 并发系列之八:java 并发工具(4个)
1. CountDownLatch 2. CyclicBarrier 3. Semaphore 4. Exchanger 5. txt java 并发工具 通俗理解 CountDownLatch 等A ...
随机推荐
- 注册Github账户过程
1.首先打开冯老师提供的Github的教程网址:http://www.aehyok.com/Blog/Detail/73.html 2.打开Github的网站(https://github.com/) ...
- SharePoint 列表中增加列编辑功能菜单
需求描述 在企业的部署中,经常将SharePoint和TFS集成在一起,两个系统之间相互读取数据,展现开发进度.在TFS 2018之前版本中,由于TFS的门户定制功能有限,用户比较喜欢使用ShareP ...
- C#: 以管理员权限运行包含有cd命令的.bat文件
最近在做项目的时候遇到一种情:用C#程序以管理员权限去执行一个bat文件,且此bat文件里面有cd命令来进入文件的下一级目录,比如: echo test begin cd test1 setup1.e ...
- 【BZOJ3280】 小R的烦恼(费用流,建模)
有很浓厚的熟悉感?餐巾计划问题? 不就是多了几个医院,相当于快洗部和慢洗部开了分店. 考虑建图: 如果把每一天拆成两个点,一个表示需求,另一个表示拥有的话. 显然就是一个两边的图,考虑如果我现在有人, ...
- 微服务统一登陆认证怎么做?JWT ?
无状态登录原理 1.1.什么是有状态? 有状态服务,即服务端需要记录每次会话的客户端信息,从而识别客户端身份,根据用户身份进行请求的处理,典型的设计如tomcat中的session. 例如登录:用户登 ...
- Linux学习笔记-基本操作2
1. 压缩包管理2. 进程管理3. 网路管理4. ftp服务器搭建5. nfs服务器搭建6. ssh服务器7. scp命令8. 其他命令9. 关机重启 1. 压缩包管理 1>. 屌丝版:不能对目 ...
- Node学习笔记---初识Node
博客原文地址:Claiyre的个人博客 https://claiyre.github.io/ 博客园地址:http://www.cnblogs.com/nuannuan7362/ 如需转载,请在文章开 ...
- ThinkCMF后台验证码不显示,无法登陆怎么办?
ThinkCMF5在本地部署之后,过一段时间可能会莫名其妙的出现后台验证码不显示的问题,不明就里.着急登陆后台的话,可以先禁用后台验证码,方法如下: 打开文件:/app/admin/controlle ...
- Swift 里 Set(一)辅助类型
_UnsafeBitset  是一个固定大小的 bitmap,用来确定指定位置是否有元素存在. HashTable  具体的 hash 碰撞算法在HashTable里实现,目前使用的是简单的开放地 ...
- JPA-style positional param was not an integral ordinal
参数错误 多为SQL语句问题 例如SQL拼装中的空格,换行时首位应多加空格保持语句效果