Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Non-daemon threads prevents application from stopping #6464

Open
Hronom opened this issue Oct 18, 2024 · 2 comments
Open

Non-daemon threads prevents application from stopping #6464

Hronom opened this issue Oct 18, 2024 · 2 comments

Comments

@Hronom
Copy link

Hronom commented Oct 18, 2024

Describe the bug

Seems like kubernetes-client uses non-daemon threads under the hood. This prevents application from being closed.

Essentially, in spring boot framework, there possibility to create beans and if beans has method close it will be automatically closed by framework as soon, as application start to shutdown. But when you use non daemon threads - it's never happen.

Please switch to usage of daemon threads, so they will not stop application from shutdown. This helps to use this client in more comfortable way.

Fabric8 Kubernetes Client version

6.13.4

Steps to reproduce

Create spring application with configuration class like this:

@Configuration
public class KubernetesClientConfiguration {

    @Bean
    public KubernetesClient kubernetesClient() {
        return new KubernetesClientBuilder().build();
    }
}

Run app and see that it not stopping.

Expected behavior

Application not blocked from stopping.

Runtime

Kubernetes (vanilla)

Kubernetes API Server version

1.25.3@latest

Environment

Linux

Fabric8 Kubernetes Client Logs

No response

Additional context

No response

@Hronom
Copy link
Author

Hronom commented Oct 18, 2024

Workaround - create custom OkHttpClientFactory:

import io.fabric8.kubernetes.client.okhttp.OkHttpClientFactory;
import okhttp3.Dispatcher;
import okhttp3.internal.Util;

import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class CustomOkHttpClientFactory extends OkHttpClientFactory {

    @Override
    protected Dispatcher initDispatcher() {
        // Inspired by https://github.com/open-telemetry/opentelemetry-java/issues/3900#issue-1056599664
        // Matches OkHttp defaults(check Dispatcher) except daemon=true instead of false
        ThreadPoolExecutor daemonExecutorService = new ThreadPoolExecutor(
                0,
                Integer.MAX_VALUE,
                60,
                TimeUnit.SECONDS,
                new SynchronousQueue<>(),
                Util.threadFactory("OkHttp Daemon Dispatcher", true)
        );

        Dispatcher dispatcher = new Dispatcher(daemonExecutorService);
        // websockets and long-running http requests count against this and eventually starve
        // the work that can be done
        dispatcher.setMaxRequests(Integer.MAX_VALUE);
        // long-running http requests count against this and eventually exhaust
        // the work that can be done
        dispatcher.setMaxRequestsPerHost(Integer.MAX_VALUE);
        return dispatcher;
    }
}

and then create client like this:

@Configuration
public class KubernetesClientConfiguration {

    @Bean
    public KubernetesClient kubernetesClient() {
        return new KubernetesClientBuilder()
                .withHttpClientFactory(new CustomOkHttpClientFactory())
                .build();
    }
}

After this everything fine.

@manusa
Copy link
Member

manusa commented Nov 25, 2024

Have you tried using a different HttpClient implementation like Vert.x (io.fabric8:kubernetes-httpclient-vertx) or Jetty (io.fabric8:kubernetes-httpclient-jetty)?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants