Vertx 因多个文件上传请求而变慢
Vertx slows down with multiple file upload requests
我正在尝试创建一个大型文件服务器(200 万并发),经过大量搜索后我发现 Vertx 最适合此类任务。所以我想出了这段代码
public void uploadFile(Vertx vertx,RoutingContext ctx,String targetFilePath,FileUploadListener mListener) {
ctx.request().pause();
new File(targetFilePath).getParentFile().mkdirs();
vertx.fileSystem().open(targetFilePath, new OpenOptions(), new Handler<AsyncResult<AsyncFile>>() {
@Override
public void handle(AsyncResult<AsyncFile> arg0) {
try {
AsyncFile file = arg0.result();
if(file == null) {
Logger.Log("file null");
mListener.onFail();
return;
}
Pump pump = Pump.pump(ctx.request(), file);
ctx.request().endHandler(v1 -> file.close(v2 -> {
mListener.onSuccess(new File(targetFilePath));
}));
pump.start();
ctx.request().resume();
}catch (Exception e) {
e.printStackTrace();
Logger.Log(e);
mListener.onFail();
return;
}
}
});
}
当多个请求尝试使用此方法同时上传文件时(9mb 文件需要 1 秒,但 100 个 9mb 文件需要 1 分钟)上传过程变慢了。我有什么事情吗?缺少提高并发性或因为 im 运行 this on Windows 10,套接字有这样的速度限制?谢谢
这是我的 MainVerticle
public class MainDeployment extends AbstractVerticle{
private Router router = Router.router(vertx);
@Override
public void start() throws Exception {
//GUI.display("Sub Verticle Has Deployed");
// Different ways of deploying verticles
// Deploy a verticle and don't wait for it to start
for(Entry<String, MyHttpHandler> entry : MyVertxServer.map.entrySet()){
router.route(entry.getKey()).handler(new Handler<RoutingContext>() {
@Override
public void handle(RoutingContext ctx) {
System.out.println(ctx.request().uri());
String[] handlerID = ctx.request().uri().split(ctx.currentRoute().getPath());
String suffix = handlerID.length > 1 ? handlerID[1] : null;
entry.getValue().Handle(ctx, new VertxUtils(), suffix);
}
});
}
MyVertxServer.server.requestHandler(router::accept);
}
}
您的代码看起来不错。您的测试方法不是。实际上,这与 Vertx 无关。
首先,从用于下载的同一台机器上传(从 Vertx 的角度来看,它会下载你上传的文件)会将 Vertx 可用的资源量减少一半。你有什么,可能是 4 个 CPU?其中 2 个将忙于上传,只有另外两个会处理您的请求。
然后是网络。事实上,我很惊讶你能在一秒钟内上传 9Mb。那是一些严肃的网络。
当然还有硬盘。为了您的实验,我希望您上传一个缓存在内存中的文件。否则,您现在有 100 个进程一次又一次地读取该文件,而其他 100 个进程则尝试写入它。即使您拥有一流的 SSD,这也是一个很大的挑战。
所以,说了这么多,您现在需要算一下。首先,将代码部署到与客户端不同的机器上。
我正在尝试创建一个大型文件服务器(200 万并发),经过大量搜索后我发现 Vertx 最适合此类任务。所以我想出了这段代码
public void uploadFile(Vertx vertx,RoutingContext ctx,String targetFilePath,FileUploadListener mListener) {
ctx.request().pause();
new File(targetFilePath).getParentFile().mkdirs();
vertx.fileSystem().open(targetFilePath, new OpenOptions(), new Handler<AsyncResult<AsyncFile>>() {
@Override
public void handle(AsyncResult<AsyncFile> arg0) {
try {
AsyncFile file = arg0.result();
if(file == null) {
Logger.Log("file null");
mListener.onFail();
return;
}
Pump pump = Pump.pump(ctx.request(), file);
ctx.request().endHandler(v1 -> file.close(v2 -> {
mListener.onSuccess(new File(targetFilePath));
}));
pump.start();
ctx.request().resume();
}catch (Exception e) {
e.printStackTrace();
Logger.Log(e);
mListener.onFail();
return;
}
}
});
}
当多个请求尝试使用此方法同时上传文件时(9mb 文件需要 1 秒,但 100 个 9mb 文件需要 1 分钟)上传过程变慢了。我有什么事情吗?缺少提高并发性或因为 im 运行 this on Windows 10,套接字有这样的速度限制?谢谢
这是我的 MainVerticle
public class MainDeployment extends AbstractVerticle{
private Router router = Router.router(vertx);
@Override
public void start() throws Exception {
//GUI.display("Sub Verticle Has Deployed");
// Different ways of deploying verticles
// Deploy a verticle and don't wait for it to start
for(Entry<String, MyHttpHandler> entry : MyVertxServer.map.entrySet()){
router.route(entry.getKey()).handler(new Handler<RoutingContext>() {
@Override
public void handle(RoutingContext ctx) {
System.out.println(ctx.request().uri());
String[] handlerID = ctx.request().uri().split(ctx.currentRoute().getPath());
String suffix = handlerID.length > 1 ? handlerID[1] : null;
entry.getValue().Handle(ctx, new VertxUtils(), suffix);
}
});
}
MyVertxServer.server.requestHandler(router::accept);
}
}
您的代码看起来不错。您的测试方法不是。实际上,这与 Vertx 无关。 首先,从用于下载的同一台机器上传(从 Vertx 的角度来看,它会下载你上传的文件)会将 Vertx 可用的资源量减少一半。你有什么,可能是 4 个 CPU?其中 2 个将忙于上传,只有另外两个会处理您的请求。
然后是网络。事实上,我很惊讶你能在一秒钟内上传 9Mb。那是一些严肃的网络。
当然还有硬盘。为了您的实验,我希望您上传一个缓存在内存中的文件。否则,您现在有 100 个进程一次又一次地读取该文件,而其他 100 个进程则尝试写入它。即使您拥有一流的 SSD,这也是一个很大的挑战。
所以,说了这么多,您现在需要算一下。首先,将代码部署到与客户端不同的机器上。