抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

基于SpingBoot实现异步调用

小水一下

😋哈,终于抓住3月的尾巴,更篇文章~~

来学校之后,把Mysql八股基本过了一遍,微服务又去熟悉了一下,还得边学计组计网操作系统(天杀得jwc反正迟早得学)。每天leetcode倒是坚持了下来,就是平常得应付学校不少破事儿,感觉精力越来越不及以前充沛了😢

最近在准备轮子项目,一个简易数据库(偷师某位来自HIT的学长),支持读提交、可重复读事务隔离级别,包含页面索引,支持MVCC、2PL等等,目前差不多完成一半了,之后完成并且测试通过(这个flag还是不立了)之后,肯定会好好写篇文章把注释搬出来总结一下(哈准备接受拷打)原意是打算做6.824(现6.5840),把分布式实践一下,但是不确定有没有连贯的精力,还得准备个微服务项目和八股,所以还是选择了写这个

好了好了,回归正题

对于异步调用,最开始听到是看JUC八股的时候;再后来在微服务中,某个模块向消息队列发送处理消息,处理模块接收消息处理,也是异步调用的思想。

上游的“我”这里只需要处理好我需要做的任务,剩下的交给下游“你”去完成,“我”只需要返回"我"的任务执行情况。这里的上下游可能是单机中的不同进程,也可以是不同服务器上的不同服务😎

正巧,hx从老师那里接了个需求很模糊的项目,需要调用后台服务执行一个Python脚本,这个脚本运行时间可能是几分钟~十多分钟。自然不能一直让前台等待执行结果,做一个Websocket感觉又比较大材小用,于是我就弄了个异步调用,将接收请求进程和运行脚本线程分开,前台只需要轮询查询执行情况即可。原本我还以为写起来比较麻烦,没想到写架子就花了不到一个小时,反而是层级解耦花了不少时间(掌嘴😤)

具体实现

这里本就是借助SpringBoot实现,所以方便的很

依赖

先得有依赖(这里使用Maven,所以在pom.xml中加入):

1
2
3
4
5
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>你的Spring Boot版本对应的版本号</version>
</dependency>

但是这个依赖是SpringBoot的核心依赖之一,一般只要有starter就行了:

1
2
3
4
 <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>

线程池配置

一般还需要配置一下异步调用线程池,针对服务挂载端的配置调整线程池、任务队列

贴一下我的写法(写在配置文件中,方便一键更改):

application.properties中:

1
2
3
4
5
6
7
8
9
# ------异步线程池配置-------
# 线程池核心线程数
async-settings.corePoolSize=2
# 线程池最大线程数
async-settings.maxPoolSize=4
# 任务队列最大容量
async-settings.queueCapacity=100
# 线程池线程名前缀
async-settings.thread-name-prefix=Async-

写个配置类(用了lombok):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
@Setter
@Getter
@ConfigurationProperties(prefix = "async-settings")
@Configuration
@EnableAsync
public class AsyncConfig extends AsyncConfigurerSupport {

private int corePoolSize;

private int maxPoolSize;

private int queueCapacity;

private String threadNamePrefix;

@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(corePoolSize);
executor.setMaxPoolSize(maxPoolSize);
executor.setQueueCapacity(queueCapacity);
executor.setThreadNamePrefix(threadNamePrefix);
executor.initialize();
return executor;
}
}

注意注解EnableAsync表示启用异步调用

然后在需要异步调用执行的方法上加上@Async注解即可

一般我会把方法实现为返回值为CompletableFuture包裹泛型(CompletableFuture<T> implements Future<T>, CompletionStage<T>),异步方法中发生的异常默认是不会被调用者捕获的。如果你的异步方法返回Future,那么异常将会被封装在Future中,你可以通过Future.get()方法来获取,另外获取执行结果也比较方便

结语

哎哎,真方便真快啊

不过最近看到有个Java框架新秀Solon;
Github地址
Gitee
现在已经是GiteeGVP项目了,看作者在官方群里说效率挺高,和Gin相差无几。之前看了下貌似确实挺轻的,之后好好看看

周末结束力,明天又是早八点半😇

评论