利用Semaphore实现多线程调用接口A且限制接口A的每秒QPS为10

前段时间在群里面发现有个群友抛出一个实际需求:需要通过一个接口拉取数据,这个接口有每秒10QPS限制,请问如何实现数据拉去效率最大化且限制调用拉取接口每秒10PQPS?我觉得这个需求挺有意思的,跟某群友讨论,发现可以利用JUC包下的Semaphore实现,几行代码就能搞定。这里将实现方案做下整理,算是抛砖引玉吧~

利用Semaphore实现多线程调用接口

  • 一、代码实现
    • 1.自定义线程池ExecutorConfig
    • 2.获取数据接口DataFetchService
    • 3.拉取数据接口核心实现RateLimitedDataFetcher
    • 4.接口实现类DataFetchServiceImpl
    • 5.UserController控制层
  • 二、项目结构及源码下载地址

一、代码实现

1.自定义线程池ExecutorConfig

/*** 线程池配置*/
@Component
public class ExecutorConfig {private static int maxPoolSize = Runtime.getRuntime().availableProcessors();private volatile static ExecutorService executorService;public static ExecutorService getThreadPool() {if (executorService == null){synchronized (ExecutorConfig.class){if (executorService == null){executorService =  newThreadPool();}}}return executorService;}private static ExecutorService newThreadPool(){int queueSize = 1000;int corePool = Math.min(10, maxPoolSize);return new ThreadPoolExecutor(corePool, maxPoolSize, 10000L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<>(queueSize),new ThreadPoolExecutor.AbortPolicy());}private ExecutorConfig(){}
}

2.获取数据接口DataFetchService

/*** 获取数据*/
public interface DataFetchService {/*** 获取数据* @return List<User>*/List<User> dataFetchTask();
}

3.拉取数据接口核心实现RateLimitedDataFetcher

@Service
@Slf4j
public class RateLimitedDataFetcher {@Autowiredprivate UserMapper userMapper;private static final int MAX_REQUESTS_PER_SECOND = 10;private Semaphore semaphore = new Semaphore(MAX_REQUESTS_PER_SECOND);private ExecutorService executorService = ExecutorConfig.getThreadPool();public Future<List<User>> fetchData(Integer id) {return executorService.submit((Callable<List<User>>) () -> {try {// 获取许可semaphore.acquire();// 执行网络请求,这里简化为一个延迟操作QueryWrapper qw = new QueryWrapper();//lt是小于,id小于5qw.lt("id", id);return userMapper.selectList(qw);} catch (InterruptedException e) {e.printStackTrace();return null;} finally {// 释放许可semaphore.release();}});}
}

4.接口实现类DataFetchServiceImpl

@Service
@Slf4j
public class DataFetchServiceImpl implements DataFetchService {@Autowiredprivate UserMapper userMapper;@Autowiredprivate RateLimitedDataFetcher rateLimitedDataFetcher;@Overridepublic List<User> dataFetchTask() {List<User> userList = null;try {userList = rateLimitedDataFetcher.fetchData(2).get();} catch (InterruptedException | ExecutionException e) {log.error("DataFetchServiceImpl dataFetchTask error:{}",e.getMessage());}return userList;}
}

5.UserController控制层

/*** 用户控制层** @author hua*/
@RestController
@RequestMapping(value = "/user")
public class UserController {@Autowiredprivate DataFetchService dataFetchService;@GetMapping(value = "/getBatchUser")public ResponseEntity<List<User>> getBatchUser() {List<User> users = dataFetchService.dataFetchTask();HttpStatus status = users == null ? HttpStatus.NOT_FOUND: HttpStatus.OK;return new ResponseEntity<>(users, status);}
}

二、项目结构及源码下载地址

在这里插入图片描述
下载地址 springboot-cacheable 欢迎star哦~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/108109.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[Linux]进程间通信--管道

[Linux]进程间通信–管道 文章目录 [Linux]进程间通信--管道进程间通信的目的实现进程间通信的原理匿名管道匿名管道的通信原理系统接口管道特性管道的协同场景管道的大小 命名管道使用指令创建命名管道使用系统调用创建命名管道 进程间通信的目的 数据传输&#xff1a;一个进…

Unity的GPUSkinning进一步介绍

大家好&#xff0c;我是阿赵。   在几年前&#xff0c;我曾经写过一篇介绍GPUSkinning的文章&#xff0c;这么多年之后&#xff0c;还是看到不停有朋友在翻看这篇旧文章。今天上去GitHub看了一下&#xff0c;GPUSkinning这个开源的插件已经很久没有更新过了&#xff0c;还是停…

【Spring面试】九、Spring MVC相关

文章目录 Q1、Spring事件监听的核心机制是什么&#xff1f;Q2、Spring框架中都用到了哪些设计模式&#xff1f;Q3、Spring是如何整合MyBatis来管理Mapper接口的&#xff1f;Q4、说说SpringMVC如何解决GET和POST的乱码问题的&#xff1f;Q5、Spring MVC的控制器是不是单例模式&a…

【PowerQuery】Excel的PowerQuery的复制

在Excel中构建符合要求的PowerQuery连接之后&#xff0c;所有的PowerQuery 连接已经顺利的保存在Excel 工作簿当中&#xff0c;但是如何去查看已经保存的PowerQuery连接呢&#xff1f;图6.3 显示了查看PowerQuery连接。 Excel界面->数据页签->查询与连接 如果你的Power…

美创科技入选第二届安徽省网络和数据安全应急技术支撑单位

9月11日&#xff0c;2023年安徽省网络安全宣传周活动在阜阳市正式启动。安徽省委常委、宣传部部长陈舜出席并宣布网安周正式启动。阜阳市委书记刘玉杰、省委宣传部副部长、省委网信办主任张杰华出席并致辞。 开幕式上&#xff0c;省委网信办副主任齐海洋发布第二届安徽省网络和…

每日一题 2596. 检查骑士巡视方案

难度&#xff1a;中等 很简单&#xff0c;从第 0 步开始模拟即可&#xff0c;唯一sb的就是测试用例中如果&#xff08;0&#xff0c;0&#xff09;处不为0的话就直接false&#xff0c;而不是去找0在哪 我的代码&#xff1a; class Solution:def checkValidGrid(self, grid: L…

PASCAL VOC2012数据集以及制作自己的数据集

目录 VOC2012目录结构制作自己的数据集标注图片软件使用流程软件使用 VOC2012目录结构 制作自己的数据集 标注图片软件 github开源项目&#xff0c;形成的是xml文件格式 使用流程 软件使用

MySQL之数据类型

目录 一、MySQL数据类型分类 二、数值类型 1、整数类型 2、bit类型 3、小数类型 三、字符串类型 1、char 2、varchar 3、char和varchar比较 四、日期和时间类型 五、enum和set 一、MySQL数据类型分类 MySQL 数据类型可以大致分为以下三类&#xff1a; 数值类型&#xff1a;用于…

长安链BaaS服务平台调研

目录 一、菜单功能二、其他说明2.1、服务平台的部署方式2.2、链本身2.3、建链流程2.4、支持连接已部署的链2.5、链治理投票2.6、支持动态节点操作2.7、支持应用 长安链ChainMaker管理平台文档地址&#xff1a;https://docs.chainmaker.org.cn 一、菜单功能 菜单子菜单/功能点…

RabbitMQ从入门到精通之安装、通讯方式详解

文章目录 RabbitMQ一、RabbitMQ介绍1.1 现存问题 一、RabbitMQ介绍二、RabbitMQ安装三、RabbitMQ架构四、RabbitMQ通信方式4.1 RabbitMQ提供的通讯方式4.2 Helloworld 方式4.2Work queues4.3 Publish/Subscribe4.4 Routing4.5 Topics4.6 RPC (了解) 五、Springboot 操作RabbitM…

frp实现内网穿透

前言 公司的一个项目部署在本地服务器&#xff0c;并且需要通过外网访问。于是我们将系统部署本地服务器后&#xff0c;借助阿里云服务器的公网IP和frp程序&#xff0c;实现内网穿透功能。 将frp服务端部署在阿里云服务器&#xff0c;将frp客户端部署在本地服务器。下载frp g…

Leetcode刷题_链表相关_c++版

&#xff08;1&#xff09;92反转链表–中等 给你单链表的头指针 head 和两个整数 left 和 right &#xff0c;其中 left < right 。请你反转从位置 left 到位置 right 的链表节点&#xff0c;返回 反转后的链表 。 /*** Definition for singly-linked list.* struct Lis…