dropwizard的自定义grpc命令立即退出

ncgqoxb0  于 2021-07-12  发布在  Java
关注(0)|答案(1)|浏览(526)

我已经使用dropwizard创建了一个启动grpc服务器的应用程序。我不使用常规服务器,希望使用 java -jar my-fat.jar grpc config.yml 相反。
我通过重写应用程序类中的相应方法,将该命令添加为启动期间唯一可用的命令:

public class App extends Application<Configuration> {

    public static void main(String[] args) throws Exception {
        new App().run(args);
    }

    @Override
    protected void addDefaultCommands(final Bootstrap<Configuration> bootstrap) {
        bootstrap.addCommand(new GrpcCommand(this));
    }
}

我可以使用 java -jar my-fat.jar grpc config.yml . 我的命令如下:

public class GrpcCommand extends EnvironmentCommand<Configuration> {

    public GrpcCommand(Application<Configuration> application) {
        this(application, "grpc", "Runs the Dropwizard application as a gRPC server");
    }

    /**
     * Creates a new environment command.
     *
     * @param application the application providing this command
     * @param name        the name of the command, used for command line invocation
     * @param description a description of the command's purpose
     */
    protected GrpcCommand(final Application<Configuration> application, final String name, final String description) {
        super(application, name, description);
    }

    @Override
    protected void run(final Environment environment, final Namespace namespace, final Configuration configuration) throws Exception {
        final var certificateService = AzureCertificateService.createWithClients(
                AzureSecretClient.create(configuration.getKeyVaultConfiguration()),
                AzureCertificateClient.create(configuration.getKeyVaultConfiguration())
        );

        final var validationService = CertificateValidationService.create(certificateService);
        final var signingService = CertificateSigningService.create(certificateService);

        final Pair<X509Certificate, KeyPair> certificate = certificateService.getSigningCertificateWithKeyPair();

        final BaseApiImpl baseApi = new BaseApiImpl(validationService, signingService);
        final GrpcServer grpcServer = GrpcServer.newBuilder()
                .withBaseApi(baseApi)
                .withConfiguration(configuration.getGrpcConfiguration())
                .withCertificate(certificate.getLeft())
                .withPrivateKey(certificate.getRight().getPrivate())
                .build();

        new Thread(() -> {
            try {
                grpcServer.start();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }).run();

        environment.healthChecks().register("grpc-server", new GrpcServerHealthCheck(grpcServer));
    }
}

线程的启动方式不是用于生产的,我只是想向前走。的启动方法 GrpcServer 班级:

@Override
public void start() throws Exception {
    final NettyServerBuilder nettyServerBuilder = NettyServerBuilder.forPort(configuration.getPort())
            .addService(baseApi)
            .intercept(new OriginInterceptor());

    if (certificate != null && privateKey != null) {
        LOG.info("Got certificate and private key, enabling SSL");
        nettyServerBuilder.sslContext(buildSslContext());
    }

    server = nettyServerBuilder
            .build()
            .start();

    LOG.info("Server started at port {}", server.getPort());
}

我看到了信息 GrpcServer: Server started at port 50441 在我的日志中。但是,应用程序不会保持打开状态。我错过了什么?我对线程的使用不应该创建一个阻止应用程序退出的线程吗?如何在grpc服务器启动后保持应用程序运行?

ki0zmccv

ki0zmccv1#

当我禁用server命令时,jetty也没有启动(当然),这使应用程序保持了以前的活动状态。
我在grpc hello world示例中找到了最简单的解决方案。
我的启动方法现在如下所示:

public void start() throws Exception {
    // Everything else as above

    Runtime.getRuntime().addShutdownHook(new Thread(GrpcServer.this::stop));
    LOG.info("Server started at port {}", server.getPort());
    blockUntilShutdown();
}

private void blockUntilShutdown() throws InterruptedException {
    if (server != null) {
        server.awaitTermination();
    }
}

相关问题