1.简介
Vert.x
VertX是一个用于构建高性能、可伸缩和响应式应用程序的开发平台。其基于事件驱动和非阻塞的架构,可以轻松地处理高并发的请求。
VertX提供了许多用于构建应用程序的库和工具,包括网络、数据库、分布式计算等。它支持多种编程语言,包括Java、Kotlin、Groovy和JavaScript。
Restful API
Restful API 是一种设计风格,用于构建网络服务的 API。"RESTful" 代表 "Representational State Transfer",是一种通信协议,用于在不同的计算机系统之间传递和操作资源。RESTful API 的设计原则简单且具有可扩展性,并且具有良好的可读性和可维护性。它使用 HTTP 协议的各种方法(如 GET、POST、PUT、DELETE)来操作资源,通过对 URI(Uniform Resource Identifier)的操作来实现对资源的访问和操作。RESTful API 通常返回数据的表示形式(如 JSON 或 XML),并根据 HTTP 状态码提供响应。通过遵循 RESTful API 的设计原则,可以使 API 更加易于使用和理解,以及更具有可靠性和可扩展性。
本文主要基于VertX+SQL Server进行一个API的压力测试,与传统MVC架构的API服务进行对比。
具体的功能就是实现读取SQL Server的一张表。
2.VertX API服务实现
整体实现代码
package org.fff.vertx_test;
import io.vertx.core.AbstractVerticle;
import io.vertx.core.Promise;
import io.vertx.core.http.HttpServer;
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.web.Route;
import io.vertx.ext.web.Router;
import io.vertx.mssqlclient.MSSQLBuilder;
import io.vertx.mssqlclient.MSSQLConnectOptions;
import io.vertx.sqlclient.Pool;
import io.vertx.sqlclient.PoolOptions;
import io.vertx.sqlclient.Row;
import io.vertx.sqlclient.RowSet;
import java.util.List;
public class MainVerticle extends AbstractVerticle {
@Override
public void start(Promise<Void> startPromise) throws Exception {
HttpServer server = vertx.createHttpServer();
MSSQLConnectOptions connectOptions = new MSSQLConnectOptions()
.setPort(1433)
.setHost("localhost")
.setDatabase("TutorialDB")
.setUser("sa")
.setPassword("123456");
// Pool options
PoolOptions poolOptions = new PoolOptions()
.setMaxSize(100);
// Create the pooled client
Pool client = MSSQLBuilder.pool()
.with(poolOptions)
.connectingTo(connectOptions)
.using(vertx)
.build();
Router router = Router.router(vertx);
Route route1 = router.get("/dbw");
route1.handler(ctx -> {
client
.query("SELECT * FROM DeviceType")
.execute()
.onComplete(ar -> {
if (ar.succeeded()) {
RowSet<Row> result = ar.result();
JsonArray jsonResponse = new JsonArray();
List<String> columnsNames = result.columnsNames();
int columnsNamesSize = columnsNames.size();
for (Row row : result) {
JsonObject obj = new JsonObject();
for(int i = 0; i<columnsNamesSize; i++){
if(row.getValue(i) == null){
obj.put(columnsNames.get(i),"null");
}else{
obj.put(columnsNames.get(i),row.getValue(i).toString());
}
}
jsonResponse.add(obj);
}
ctx.response().putHeader("content-type", "application/json");
// 结束响应并发送 JSON 对象
ctx.response().end(jsonResponse.encode());
}
else {
System.out.println("Failure: " + ar.cause().getMessage());
}
});
});
server.requestHandler(router).listen(8888);
}
}
2.1 数据库连接
根据官方的示例,数据连接的实现为:
import io.vertx.mssqlclient.MSSQLBuilder;
import io.vertx.mssqlclient.MSSQLConnectOptions;
import io.vertx.sqlclient.Pool;
import io.vertx.sqlclient.PoolOptions;
MSSQLConnectOptions connectOptions = new MSSQLConnectOptions()
.setPort(1433)
.setHost("localhost")
.setDatabase("TutorialDB")
.setUser("sa")
.setPassword("123456");
// Pool options
PoolOptions poolOptions = new PoolOptions()
.setMaxSize(100);
// Create the pooled client
Pool client = MSSQLBuilder.pool()
.with(poolOptions)
.connectingTo(connectOptions)
.using(vertx)
.build();
2.2 结合简单响应+请求体处理完成查库
Router router = Router.router(vertx);
Route route1 = router.get("/dbw");
route1.handler(ctx -> {
client
.query("SELECT * FROM DeviceType")
.execute()
.onComplete(ar -> {
if (ar.succeeded()) {
RowSet<Row> result = ar.result();
JsonArray jsonResponse = new JsonArray();
List<String> columnsNames = result.columnsNames();
int columnsNamesSize = columnsNames.size();
for (Row row : result) {
JsonObject obj = new JsonObject();
for(int i = 0; i<columnsNamesSize; i++){
if(row.getValue(i) == null){
obj.put(columnsNames.get(i),"null");
}else{
obj.put(columnsNames.get(i),row.getValue(i).toString());
}
}
jsonResponse.add(obj);
}
ctx.response().putHeader("content-type", "application/json");
// 结束响应并发送 JSON 对象
ctx.response().end(jsonResponse.encode());
}
else {
System.out.println("Failure: " + ar.cause().getMessage());
}
});
});
3.注解式MVC架构API服务实现
Mapper
@Mapper
public interface UserMapperSqlserver {
@Select("SELECT * FROM DeviceType")
List<DeviceTypeDetail> FetchAllInfo();
}
Service
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserMapperSqlserver userMapperSqlserver;
@Override
public List<DeviceTypeDetail> FetchAllInfo() {
return userMapperSqlserver.FetchAllInfo();
}
}
Controller
@CrossOrigin
@RestController
public class UserContoller {
@Autowired
private UserService userService;
@GetMapping("/getallinfo1")
public List<DeviceTypeDetail> FetchAllInfo1()
{
return userService.FetchAllInfo();
}
}
4.不严谨的Jmeter压力测试
测试参数:
VertX测试效果:
Samples | 20000 |
Average | 314 |
Median | 328 |
90% Line | 336 |
95% Line | 341 |
99% Line | 357 |
Min | 3 |
Maximum | 386 |
Error % | 0.00% |
Throughput | 5971.8/sec |
Received KB/sec | 59455.11 |
Sent KB/sec | 711.48 |
MVC测试效果:
Vertx MVC
Samples | 20000 |
Average | 941 |
Median | 1166 |
90% Line | 1400 |
95% Line | 1459 |
99% Line | 4058 |
Min | 1 |
Maximum | 7459 |
Error % | 0.55% |
Throughput | 1980.4/sec |
Received KB/sec | 24589.05 |
Sent KB/sec | 259.66 |
可以看出来VertX 效果还是很强大的吞吐量拉满