Vertx上的并发

时间:2017-03-14 16:13:20

标签: java vert.x

我已加入其中一个Vertx爱好者,单线程主框架可能无法为我工作,因为在我的服务器中可能会有50个文件下载请求,因为我已经创建了这个类

public abstract T onRun() throws Exception;
public abstract void onSuccess(T result);
public abstract void onException();

private static final int poolSize = Runtime.getRuntime().availableProcessors();
private static final long maxExecuteTime = 120000;

private static WorkerExecutor mExecutor;

private static final String BG_THREAD_TAG = "BG_THREAD";

protected RoutingContext ctx;

private boolean isThreadInBackground(){
    return Thread.currentThread().getName() != null && Thread.currentThread().getName().equals(BG_THREAD_TAG);
}

//on success will not be called if exception be thrown
public BackgroundExecutor(RoutingContext ctx){

    this.ctx = ctx;

    if(mExecutor == null){
        mExecutor = MyVertxServer.vertx.createSharedWorkerExecutor("my-worker-pool",poolSize,maxExecuteTime);
    }

    if(!isThreadInBackground()){

    /** we are unlocking the lock before res.succeeded , because it might take long and keeps any thread waiting */

    mExecutor.executeBlocking(future -> {
        try{

              Thread.currentThread().setName(BG_THREAD_TAG);

              T result = onRun();
              future.complete(result);

        }catch (Exception e) {
            GUI.display(e);
            e.printStackTrace();
            onException();
            future.fail(e);
        }

              /** false here means they should not be parallel , and will run without order multiple times on same context*/
            },false, res -> {

                if(res.succeeded()){
                    onSuccess((T)res.result());
                }

            });

    }else{


        GUI.display("AVOIDED DUPLICATE BACKGROUND THREADING");
        System.out.println("AVOIDED DUPLICATE BACKGROUND THREADING");

        try{

              T result = onRun();

              onSuccess((T)result);

        }catch (Exception e) {
            GUI.display(e);
            e.printStackTrace();
            onException();          
        }
    }

}

允许处理程序扩展它并像这样使用它

public abstract class DefaultFileHandler implements MyHttpHandler{

public abstract File getFile(String suffix);

@Override
public void Handle(RoutingContext ctx, VertxUtils utils, String suffix) {
    new BackgroundExecutor<Void>(ctx) {

        @Override
        public Void onRun() throws Exception {

            File file = getFile(URLDecoder.decode(suffix, "UTF-8"));

            if(file == null || !file.exists()){
                utils.sendResponseAndEnd(ctx.response(),404);
                return null;
            }else{
                utils.sendFile(ctx, file);
            }
            return null;
        }

        @Override
        public void onSuccess(Void result) {}

        @Override
        public void onException() {
            utils.sendResponseAndEnd(ctx.response(),404);
        }
    };
}

以下是我初始化vertx服务器的方法

vertx.deployVerticle(MainDeployment.class.getCanonicalName(),res -> {
          if (res.succeeded()) {

                GUI.display("Deployed");

              } else {
                res.cause().printStackTrace();
              }
            });

    server.requestHandler(router::accept).listen(port);

这是我的MainDeployment类

public class MainDeployment extends AbstractVerticle{

  @Override
  public void start() throws Exception {

    // Different ways of deploying verticles

    // Deploy a verticle and don't wait for it to start

   for(Entry<String, MyHttpHandler> entry : MyVertxServer.map.entrySet()){
       MyVertxServer.router.route(entry.getKey()).handler(new Handler<RoutingContext>() {

            @Override
            public void handle(RoutingContext ctx) {

                String[] handlerID = ctx.request().uri().split(ctx.currentRoute().getPath());

                String suffix = handlerID.length > 1 ? handlerID[1] : null;
                entry.getValue().Handle(ctx, new VertxUtils(), suffix);

            }
        });
   }

  }
}

这在我需要它的时间和地点工作得很好,但我仍然想知道是否有更好的方法来处理这样的Vertx上的concurencies,如果是这样的例子将非常感激。非常感谢

2 个答案:

答案 0 :(得分:1)

我不完全了解您的问题和解决方案的原因。为什么不实现一个Verticle来处理你的http上传并多次部署它?我认为处理50个并发上传应该是vert.x的小菜一碟。

  

使用Verticle名称部署Verticle时,您可以指定要部署的Verticle实例的数量:

     

DeploymentOptions options = new DeploymentOptions().setInstances(16); vertx.deployVerticle("com.mycompany.MyOrderProcessorVerticle", options);

     

这对于跨多个核心轻松扩展非常有用。例如,您可能要在计算机上部署Web服务器Verticle和多个核心,因此您希望部署多个实例以利用所有核心。

http://vertx.io/docs/vertx-core/java/#_specifying_number_of_verticle_instances

答案 1 :(得分:0)

vertx是一个设计良好的模型,因此不会发生并发问题。 通常,vertx不推荐使用多线程模型。 (因为处理并不容易。)

如果选择多线程模型,则必须考虑共享数据..

简单来说,如果你只想分割EventLoop Area, 首先,确保检查一些CPU核心。 然后设置实例数。

DeploymentOptions options = new DeploymentOptions().setInstances(4);
vertx.deployVerticle("com.mycompany.MyOrderProcessorVerticle", options);

但是,如果你有4个CPU的核心,你不会设置超过4个实例。 如果您设置为四个或更多,性能将无法提高。

vertx concurrency reference

http://vertx.io/docs/vertx-core/java/