开发环境
参见Quarkus入门
- 安装
IntelliJ IDEA
。 - 配置开发
JDK
,可以使用JDK8
,推荐JDK11
。当然如果要尝试Native
,那可以安装GraalVM
。 - 安装
Maven3.6.2
以上。
快速搭建一个Quarkus应用
参见Quarkus Start Coding
我们选择了Quarkus吸引我们的特性,开始体验Reactive编程。
选择完毕后,点击Generate your application
下载工程。
分析POM
引入Quarkus的pom
<dependencyManagement>
<dependencies>
<dependency>
<groupId>${quarkus.platform.group-id}</groupId>
<artifactId>${quarkus.platform.artifact-id}</artifactId>
<version>${quarkus.platform.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
复制代码
Quarkus的版本更新很频繁,但都是通过quarkus-universe-bom
管理的,引入这部分后,后续的版本升级会方便很多。
Reactive Routes
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-vertx-web</artifactId>
</dependency>
复制代码
Quarkus
的Reactive Web
是基于Vert.x
实现的,通过一些注解和封装,让代码编写更简单。
Reactive Panache
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-hibernate-reactive-panache</artifactId>
</dependency>
复制代码
Panache
是基于Hibernate
的实现,类似于JPA,更简单。
Reactive DB Client
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-reactive-mysql-client</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-reactive-pg-client</artifactId>
</dependency>
复制代码
根据数据库选型不同,引入对应的数据库Client
。
OpenAPI
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-smallrye-openapi</artifactId>
</dependency>
复制代码
如果喜欢Swagger
的话,可以引入Quarkus
对应的OpenApi
实现。
接口1-hello1,quarkus
代码
@OpenAPIDefinition(
info = @Info(
title = "Hello API",
version = "1.0.0",
contact = @Contact(
name = "Hello API Support",
url = "http://127.0.0.1:8080/swagger-ui/",
email = "mengxiangyuancc@gmail.com"),
license = @License(
name = "Apache 2.0",
url = "https://www.apache.org/licenses/LICENSE-2.0.html"))
)
@ApplicationScoped
public class HelloResource extends BaseResource {
private static final Logger LOGGER = LoggerFactory.getLogger(HelloResource.class);
@Route(path = "/hello1", methods = HttpMethod.GET)
@Operation(description = "hello1 接口")
void hello1(RoutingContext ctx) {
ctx.response().end("hello1, quarkus");
}
@Route(path = "/hello2", methods = HttpMethod.GET)
String hello2(RoutingContext ctx) {
// non-blocking
return "hello2, quarkus";
}
@Route(path = "/hello3", methods = HttpMethod.GET)
String hello3(@Param Optional<String> name) {
return "hello3, " + name.orElse("quarkus");
}
@Route(path = "/hello4", methods = HttpMethod.GET)
Uni<String> hello4(RoutingContext context) {
return Uni.createFrom().item("hello4, quarkus");
}
}
复制代码
注解
@OpenAPIDefinition
和@Operation
都是OpenApi
的注解,用于生成接口文档。@ApplicationScoped
生成Bean
。@Route(path = "/hello1", methods = HttpMethod.GET)
定义一个Get接口。
启动
以Dev模式启动
./mvnw compile quarkus:dev
复制代码
打包
./mvnw package
复制代码
打包uber-jar
./mvnw package -Dquarkus.package.type=uber-jar
复制代码
打包Native
,需要GraalVM
./mvnw package -Pnative
复制代码
打包Native
,不需要GraalVM
,但需要Docker
。
./mvnw package -Pnative -Dquarkus.native.container-build=true
复制代码
调用
[root@ecs-1b4c-0002 k6]# curl http://127.0.0.1:8080/hello1
hello1, quarkus
复制代码
性能
[root@ecs-1b4c-0002 k6]# wrk -c50 -d20s 'http://localhost:8080/hello1' --latency
Running 20s test @ http://localhost:8080/hello1
2 threads and 50 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 0.92ms 2.57ms 46.89ms 92.41%
Req/Sec 120.34k 22.68k 185.55k 74.75%
Latency Distribution
50% 125.00us
75% 398.00us
90% 2.28ms
99% 12.56ms
4792636 requests in 20.03s, 457.06MB read
Requests/sec: 239328.58
Transfer/sec: 22.82MB
[root@ecs-1b4c-0002 k6]# wrk -c50 -d20s 'http://localhost:8080/hello2' --latency
Running 20s test @ http://localhost:8080/hello2
2 threads and 50 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 1.24ms 3.09ms 57.90ms 90.09%
Req/Sec 124.35k 22.26k 194.19k 74.50%
Latency Distribution
50% 103.00us
75% 506.00us
90% 4.28ms
99% 14.60ms
4949693 requests in 20.02s, 472.04MB read
Requests/sec: 247208.04
Transfer/sec: 23.58MB
[root@ecs-1b4c-0002 ~]# wrk -c50 -d20s 'http://localhost:8080/hello3' --latency
Running 20s test @ http://localhost:8080/hello3
2 threads and 50 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 0.92ms 2.75ms 46.71ms 93.14%
Req/Sec 115.25k 20.64k 177.04k 70.00%
Latency Distribution
50% 130.00us
75% 400.00us
90% 1.63ms
99% 14.12ms
4589497 requests in 20.03s, 437.69MB read
Requests/sec: 229162.08
Transfer/sec: 21.85MB
[root@ecs-1b4c-0002 ~]# wrk -c50 -d20s 'http://localhost:8080/hello4' --latency
Running 20s test @ http://localhost:8080/hello4
2 threads and 50 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 797.89us 2.37ms 53.33ms 93.64%
Req/Sec 109.77k 20.36k 171.02k 70.00%
Latency Distribution
50% 152.00us
75% 390.00us
90% 1.36ms
99% 11.81ms
4375750 requests in 20.07s, 417.30MB read
Requests/sec: 218072.60
Transfer/sec: 20.80MB
复制代码
4C8G服务器下QPS
能达到20W+
。
接口2-查询数据库
代码
Route
@Inject
BrandInfoRepository brandInfoRepository;
@Route(path = "/brandInfo", methods = HttpMethod.GET)
Uni<BrandInfo> brandInfo(@Param Optional<String> brandId) {
return brandInfoRepository.findById(brandId.orElse(""));
}
复制代码
BrandInfoRepository
@ApplicationScoped
public class BrandInfoRepository extends ResourceRepository<BrandInfo> {
}
复制代码
ResourceRepository 不直接继承PanacheRepositoryBase是为了后续扩展的需要。
/**
* Description: 不直接继承 PanacheRepositoryBase .<br>
* <p>Created Time: 2021/5/25 下午5:29 </p>
*
* @author <a href="https://juejin.cn/post/mail to: mengxiangyuancc@gmail.com" rel="nofollow">孟祥元</a>
*/
public class ResourceRepository<Entity> implements PanacheRepositoryBase<Entity, String> {
}
复制代码
BrandInfo
@Entity(name = "brand_info")
public class BrandInfo extends PanacheEntityBase {
@Id
private String brandId;
private String brandName;
// get set ……
}
复制代码
配置文件
quarkus.datasource.db-kind=mysql
quarkus.datasource.username=dev
quarkus.datasource.password=123456
quarkus.datasource.reactive.url=mysql://xxx.xxx.xxx.xxx:3306/quarkus
复制代码
性能
Mysql
数据库中的brand_info
表中大约18万条数据,QPS
达到3万+
[root@ecs-1b4c-0002 ~]# wrk -d20s -c50 http://127.0.0.1:8080/brandInfo?brandId=1000003
Running 20s test @ http://127.0.0.1:8080/brandInfo?brandId=1000003
2 threads and 50 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 1.50ms 1.52ms 40.92ms 97.31%
Req/Sec 18.56k 1.19k 31.68k 82.04%
740605 requests in 20.10s, 92.52MB read
Requests/sec: 36846.26
Transfer/sec: 4.60MB
复制代码
闲话
Quarkus
的 Reactive
编码还是相对简单的,性能较高,充分使用了服务器资源,减少等待。
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END