Как правильно запустить веб-сервер micronaut из команды picocli? - PullRequest
0 голосов
/ 11 октября 2019

У меня приложение micronaut cli .

Некоторые команды - это долго выполняющиеся процессы, которые я хочу отслеживать с конечными точками микронавтика

, посколькукогда вы используете приложение cli, микронавт обнаруживает и не запускает веб-сервер.

В этой длительной команде я добавил это для запуска веб-сервера:


        applicationContext
            .findBean(EmbeddedServer.class)
            .ifPresent(server -> {
                // start server
                long start = System.currentTimeMillis();
                server.start();

                log.info(
                    "Startup completed in {} ms. Server Running: {}",
                    System.currentTimeMillis() - start,
                    server.getURL()
                );

                // force exit
                if (server.isForceExit()) {
                    System.exit(0);
                }
            });

Большая часть кода взята из Micronaut.java .

Полный исходный код команды:

package test;

import io.micronaut.configuration.picocli.PicocliRunner;
import io.micronaut.context.ApplicationContext;
import io.micronaut.runtime.server.EmbeddedServer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import picocli.CommandLine;

import javax.inject.Inject;
import java.util.concurrent.Callable;

@CommandLine.Command(
    name = "test",
    mixinStandardHelpOptions = true,
    subcommands = {
        TestApp.TestServer.class,
    }
)
public class TestApp implements Callable<Object> {
    public static void main(String[] args) throws Exception {
        PicocliRunner.call(TestApp.class, args);
    }

    @Override
    public Object call() throws Exception {
        return PicocliRunner.call(TestApp.class, "--help");
    }

    @CommandLine.Command(
        name = "server",
        description = "Start a webserver"
    )
    public static class TestServer implements Runnable {
        @Inject
        ApplicationContext applicationContext;

        Logger log = LoggerFactory.getLogger(TestServer.class);

        @Override
        public void run() {
            applicationContext
                .findBean(EmbeddedServer.class)
                .ifPresent(server -> {
                    // start server
                    long start = System.currentTimeMillis();
                    server.start();

                    log.info(
                        "Startup completed in {} ms. Server Running: {}",
                        System.currentTimeMillis() - start,
                        server.getURL()
                    );

                    // force exit
                    if (server.isForceExit()) {
                        System.exit(0);
                    }
                });
        }
    }
}

Веб-сервер запускается нормально. Я добавил 2 конечных точки, регистратор и здоровье. Конечная точка регистратора работает хорошо, но конечная точка работоспособности (как и большинство других конечных точек) не работает с этой трассировкой стека: Full Stacktrace

io.reactivex.exceptions.UndeliverableException: The exception could not be delivered to the consumer because it has already canceled/disposed the flow or the exception has nowhere to go to begin with. Further reading: https://github.com/ReactiveX/RxJava/wiki/What's-different-in-2.0#error-handling | java.util.concurrent.RejectedExecutionException: Task java.util.concurrent.FutureTask@1f5e667f[Not completed, task = java.util.concurrent.Executors$RunnableAdapter@1615aa7e[Wrapped task = io.micronaut.http.context.ServerRequestContext$$Lambda$653/0x00000008406af040@5f7931cf]] rejected from java.util.concurrent.ThreadPoolExecutor@33dd1064[Terminated, pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 0]
    at io.reactivex.plugins.RxJavaPlugins.onError(RxJavaPlugins.java:367)
...
Caused by: java.util.concurrent.RejectedExecutionException: Task java.util.concurrent.FutureTask@1f5e667f[Not completed, task = java.util.concurrent.Executors$RunnableAdapter@1615aa7e[Wrapped task = io.micronaut.http.context.ServerRequestContext$$Lambda$653/0x00000008406af040@5f7931cf]] rejected from java.util.concurrent.ThreadPoolExecutor@33dd1064[Terminated, pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 0]
    at java.base/java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2055)
....
    at io.micronaut.scheduling.instrument.InstrumentedExecutorService.submit(InstrumentedExecutorService.java:89)
    at io.micronaut.core.async.publisher.AsyncSingleResultPublisher$ExecutorServiceSubscription.request(AsyncSingleResultPublisher.java:98)
    at io.reactivex.internal.operators.flowable.FlowableFlatMap$InnerSubscriber.onSubscribe(FlowableFlatMap.java:656)
    at io.micronaut.core.async.publisher.AsyncSingleResultPublisher.subscribe(AsyncSingleResultPublisher.java:59)
...
    at io.reactivex.Flowable.subscribe(Flowable.java:14805)
    ... 38 more
Exception in thread "nioEventLoopGroup-1-4" io.reactivex.exceptions.UndeliverableException: The exception could not be delivered to the consumer because it has already canceled/disposed the flow or the exception has nowhere to go to begin with. Further reading: https://github.com/ReactiveX/RxJava/wiki/What's-different-in-2.0#error-handling | java.util.concurrent.RejectedExecutionException: Task java.util.concurrent.FutureTask@1f5e667f[Not completed, task = java.util.concurrent.Executors$RunnableAdapter@1615aa7e[Wrapped task = io.micronaut.http.context.ServerRequestContext$$Lambda$653/0x00000008406af040@5f7931cf]] rejected from java.util.concurrent.ThreadPoolExecutor@33dd1064[Terminated, pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 0]
...
    at io.micronaut.http.context.ServerRequestTracingPublisher.lambda$subscribe$0(ServerRequestTracingPublisher.java:52)
    at io.micronaut.http.context.ServerRequestContext.with(ServerRequestContext.java:52)
    at io.micronaut.http.context.ServerRequestTracingPublisher.subscribe(ServerRequestTracingPublisher.java:52)
    at io.micronaut.core.async.publisher.Publishers.lambda$map$2(Publishers.java:133)
...
    at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: java.util.concurrent.RejectedExecutionException: Task java.util.concurrent.FutureTask@1f5e667f[Not completed, task = java.util.concurrent.Executors$RunnableAdapter@1615aa7e[Wrapped task = io.micronaut.http.context.ServerRequestContext$$Lambda$653/0x00000008406af040@5f7931cf]] rejected from java.util.concurrent.ThreadPoolExecutor@33dd1064[Terminated, pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 0]
    ... 38 more
2019-10-11 17:18:50,689 WARN  nioEventLoopGroup-1-4    i.n.u.c.AbstractEventExecutor        A task raised an exception. Task: io.reactivex.internal.schedulers.ExecutorScheduler$ExecutorWorker@7ebe5c10
java.lang.NullPointerException: Actually not, but can't throw other exceptions due to RS
    at io.reactivex.Flowable.subscribe(Flowable.java:14814)
...
    at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: java.util.concurrent.RejectedExecutionException: Task java.util.concurrent.FutureTask@1f5e667f[Not completed, task = java.util.concurrent.Executors$RunnableAdapter@1615aa7e[Wrapped task = io.micronaut.http.context.ServerRequestContext$$Lambda$653/0x00000008406af040@5f7931cf]] rejected from java.util.concurrent.ThreadPoolExecutor@33dd1064[Terminated, pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 0]
    at java.base/java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2055)
    at java.base/java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:825)
    at java.base/java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1355)
    at java.base/java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:118)
    at io.micronaut.scheduling.instrument.InstrumentedExecutorService.submit(InstrumentedExecutorService.java:89)
    at io.micronaut.core.async.publisher.AsyncSingleResultPublisher$ExecutorServiceSubscription.request(AsyncSingleResultPublisher.java:98)
    at io.reactivex.internal.operators.flowable.FlowableFlatMap$InnerSubscriber.onSubscribe(FlowableFlatMap.java:656)
    at io.micronaut.core.async.publisher.AsyncSingleResultPublisher.subscribe(AsyncSingleResultPublisher.java:59)
    at io.reactivex.internal.operators.flowable.FlowableFlatMap$MergeSubscriber.onNext(FlowableFlatMap.java:163)
    at io.reactivex.internal.operators.flowable.FlowableFromIterable$IteratorSubscription.slowPath(FlowableFromIterable.java:236)
    at io.reactivex.internal.operators.flowable.FlowableFromIterable$BaseRangeSubscription.request(FlowableFromIterable.java:124)
    at io.reactivex.internal.operators.flowable.FlowableFlatMap$MergeSubscriber.onSubscribe(FlowableFlatMap.java:117)
    at io.reactivex.internal.operators.flowable.FlowableFromIterable.subscribe(FlowableFromIterable.java:69)
    at io.reactivex.internal.operators.flowable.FlowableFromIterable.subscribeActual(FlowableFromIterable.java:47)
    at io.reactivex.Flowable.subscribe(Flowable.java:14805)
    ... 38 common frames omitted

Любой ключ, чтобы сделать это?

1 Ответ

0 голосов
/ 14 октября 2019

Благодаря Грэму Роше, который дает правильное направление здесь: https://github.com/micronaut-projects/micronaut-picocli/issues/9.

Правильный запуск веб-сервера из кли:

applicationContext
            .findBean(EmbeddedServer.class)
            .ifPresent(server -> {
                // start server
                long start = System.currentTimeMillis();
                server.start();
             });

Но вы должны позаботиться о том, чтобыВаша команда должна хранить всю логику в главном потоке. В случае многопоточного приложения сервер будет отключен, если вы не ожидаете всех потоков в основной команде

...