Skip to content

DeltaFIFO makes MemoryLeak #912

Closed
Closed
@huhu-sky

Description

@huhu-sky

What i found

i import java client sdk and use list-watch function with informer; while my application running for about several hours, it occured gc all the time; I dump the hprof file to the EclipseMAT tool and found some memory leak suspects.

image

image

image

How can i resolve this problem, or is there something i wrong; Thanks .

public class ListWatchInformer {

    final K8sService k8s;
    SharedInformerFactory svcFactory;
    SharedInformerFactory epFactory;
    SharedInformerFactory nacosSvcFactory;

    private SharedIndexInformer<V1Service> serviceInformer;
    private SharedIndexInformer<V1Endpoints> endpointsInformer;
    private SharedIndexInformer<V1Service> nacosServiceInformer;

    @Autowired
    public ListWatchInformer(K8sService k8s) {
        this.k8s = k8s;
        init();
    }

    public void init() {
        this.svcFactory = new SharedInformerFactory();
        this.epFactory = new SharedInformerFactory();
        this.nacosSvcFactory = new SharedInformerFactory();
        CoreV1Api coreV1Api = k8s.getConn(ServiceConstants.ClusterId_Test).coreV1Api;
        // service list watch
        this.serviceInformer = svcInformer(svcFactory, coreV1Api, ServiceConstants.FixedNacosK8sLabelSelector);
        svcFactory.startAllRegisteredInformers();
        // endpoints list watch
        this.endpointsInformer = epInformer(epFactory, coreV1Api, ServiceConstants.FixedNacosK8sLabelSelector);
        epFactory.startAllRegisteredInformers();
        // nacos service list watch
        this.nacosServiceInformer = namespacedServiceInformer(nacosSvcFactory, ServiceConstants.NacosNamespace, coreV1Api, null);
        nacosSvcFactory.startAllRegisteredInformers();
    }


    public SharedIndexInformer<V1Service> svcInformer() {
        return serviceInformer;
    }

    public SharedIndexInformer<V1Endpoints> epInformer() {
        return endpointsInformer;
    }

    public SharedIndexInformer<V1Service> nacosSvcInformer() {
        return nacosServiceInformer;
    }

    public SharedInformerFactory epFactory(){
        return epFactory;
    }
    public SharedInformerFactory svcFactory(){
        return svcFactory;
    }
    public SharedInformerFactory nacosSvcFactory(){
        return nacosSvcFactory;
    }

    public V1Service getSvc(String namespace, String name) {
        String key = namespace + "/" + name;
        return getSvc(key);
    }

    public V1Service getNacosSvc(String name) {
        if (nacosServiceInformer != null && nacosServiceInformer.getIndexer() != null) {
            return nacosServiceInformer.getIndexer().getByKey(ServiceConstants.NacosNamespace + "/" + name);
        }
        return null;
    }

    public V1Service getSvc(String key) {
        if (serviceInformer != null && serviceInformer.getIndexer() != null) {
            return serviceInformer.getIndexer().getByKey(key);
        }
        return null;
    }

    public V1Endpoints getEp(String namespace, String name) {
        String key = namespace + "/" + name;
        return getEp(key);
    }

    public V1Endpoints getEp(String key) {
        if (endpointsInformer != null && endpointsInformer.getIndexer() != null) {
            return endpointsInformer.getIndexer().getByKey(key);
        }
        return null;
    }

    private SharedIndexInformer<V1Endpoints> epInformer(SharedInformerFactory factory, CoreV1Api coreV1Api, String label) {
        // service informer
        SharedIndexInformer<V1Endpoints> endpointsInformer =
                factory.sharedIndexInformerFor(
                        (CallGeneratorParams params) -> {
                            try {
                                return coreV1Api.listEndpointsForAllNamespacesCall(null, null, null, label,
                                        null, null, params.resourceVersion, params.timeoutSeconds, params.watch, null,null);
                            } catch (ApiException e) {
                                Loggers.K8S_LOG.error("endpointsInformer: endpoints list error: {}", e);
                                Loggers.K8S_LOG.error("endpointsInformer: endpoints list error, responseBody: {}, message: {}, stack: {}", e.getResponseBody(), e.getMessage(),e.getStackTrace());
                            }
                            return null;
                        },
                        V1Endpoints.class,
                        V1EndpointsList.class);

        endpointsInformer.addEventHandler(epHandler());
        return endpointsInformer;
    }

    private SharedIndexInformer<V1Service> svcInformer(SharedInformerFactory factory, CoreV1Api coreV1Api, String label) {
        // service informer
        SharedIndexInformer<V1Service> serviceInformer =
                factory.sharedIndexInformerFor(
                        (CallGeneratorParams params) -> {
                            try {
                                return coreV1Api.listServiceForAllNamespacesCall(null, null, null, label,
                                        null, null, params.resourceVersion, params.timeoutSeconds, params.watch, null,null);
                            } catch (ApiException e) {
                                Loggers.K8S_LOG.error("serviceInformer: service list error: {}", e);
                                Loggers.K8S_LOG.error("serviceInformer: service list error, responseBody: {}, message: {}, stack: {}", e.getResponseBody(), e.getMessage(),e.getStackTrace());
                            }
                            return null;
                        },
                        V1Service.class,
                        V1ServiceList.class);

        serviceInformer.addEventHandler(serviceHandler());
        return serviceInformer;
    }

    private SharedIndexInformer<V1Service> namespacedServiceInformer(SharedInformerFactory factory, String namespace, CoreV1Api coreV1Api, String label) {
        // service informer
        SharedIndexInformer<V1Service> serviceInformer =
                factory.sharedIndexInformerFor(
                        (CallGeneratorParams params) -> {
                            try {
                                return coreV1Api.listNamespacedServiceCall(namespace, null, null, null, null,
                                        label, null, params.resourceVersion, params.timeoutSeconds, params.watch, null,null);
                            } catch (ApiException e) {
                                Loggers.K8S_LOG.error("serviceInformer: service list error: {}", e);
                                Loggers.K8S_LOG.error("serviceInformer: service list error, responseBody: {}, message: {}, stack: {}", e.getResponseBody(), e.getMessage(),e.getStackTrace());
                            }
                            return null;
                        },
                        V1Service.class,
                        V1ServiceList.class);

        serviceInformer.addEventHandler(serviceHandler());
        return serviceInformer;
    }

    private ResourceEventHandler<V1Endpoints> epHandler() {
        return new ResourceEventHandler<V1Endpoints>() {
            @Override
            public void onAdd(V1Endpoints ep) {
                if (Loggers.K8S_LOG.isInfoEnabled()) {
                    Loggers.K8S_LOG.info("endpointsInformer: ep added!, namespace: {}, name: {}, origin: {}",
                            ep.getMetadata().getNamespace(), ep.getMetadata().getName(), ep.getSubsets());
                }
            }

            @Override
            public void onUpdate(V1Endpoints ep, V1Endpoints newEp) {
                if (Loggers.K8S_LOG.isInfoEnabled()) {
                    if (!ep.getMetadata().getResourceVersion().equals(newEp.getMetadata().getResourceVersion())) {
                        Loggers.K8S_LOG.info("endpointsInformer: ep updated!, namespace: {}, name: {}, oldSubsets: {}, newSubsets: {}, oldVersion: {}, newVersion: {}",
                                ep.getMetadata().getNamespace(), ep.getMetadata().getName(), ep.getSubsets(), newEp.getSubsets(),
                                ep.getMetadata().getResourceVersion(), newEp.getMetadata().getResourceVersion());
                    }
                }
            }

            @Override
            public void onDelete(V1Endpoints ep, boolean deletedFinalStateUnknown) {
                if (Loggers.K8S_LOG.isInfoEnabled()) {
                    Loggers.K8S_LOG.info("endpointsInformer: ep deleted!, namespace: {}, name: {}, origin: {}",
                            ep.getMetadata().getNamespace(), ep.getMetadata().getName(), ep.getSubsets());
                }
            }
        };
    }

    private ResourceEventHandler<V1Service> serviceHandler() {
        return new ResourceEventHandler<V1Service>() {
            @Override
            public void onAdd(V1Service srv) {
                if (Loggers.K8S_LOG.isInfoEnabled()) {
                    Loggers.K8S_LOG.info("serviceInformer: srv added!, namespace: {}, name: {}, origin: {}",
                            srv.getMetadata().getNamespace(), srv.getMetadata().getName(),
                            srv.getMetadata().getAnnotations().get(ServiceConstants.Nacos2K8sServiceNameAnno_Key));
                }
            }

            @Override
            public void onUpdate(V1Service srv, V1Service newSrv) {
                if (Loggers.K8S_LOG.isInfoEnabled()) {
                    if (!srv.getMetadata().getResourceVersion().equals(newSrv.getMetadata().getResourceVersion())) {
                        Loggers.K8S_LOG.info("serviceInformer: srv updated!, namespace: {}, name: {}, origin: {}, oldVersion: {}, newVersion: {}",
                                srv.getMetadata().getNamespace(), srv.getMetadata().getName(),
                                srv.getMetadata().getAnnotations().get(ServiceConstants.Nacos2K8sServiceNameAnno_Key),
                                srv.getMetadata().getResourceVersion(), newSrv.getMetadata().getResourceVersion());
                        if (Loggers.K8S_LOG.isDebugEnabled()) {
                            Loggers.K8S_LOG.info("serviceInformer: srv updated!, namespace: {}, name: {}, origin: {}, old: {}, new: {}",
                                    srv.getMetadata().getNamespace(), srv.getMetadata().getName(),
                                    srv.getMetadata().getAnnotations().get(ServiceConstants.Nacos2K8sServiceNameAnno_Key),
                                    srv, newSrv);
                        }
                    }
                }
            }

            @Override
            public void onDelete(V1Service srv, boolean deletedFinalStateUnknown) {
                if (Loggers.K8S_LOG.isInfoEnabled()) {
                    Loggers.K8S_LOG.info("serviceInformer: srv deleted!, namespace: {}, name: {}, origin: {}",
                            srv.getMetadata().getNamespace(), srv.getMetadata().getName(),
                            srv.getMetadata().getAnnotations().get(ServiceConstants.Nacos2K8sServiceNameAnno_Key));
                }
            }
        };
    }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    lifecycle/rottenDenotes an issue or PR that has aged beyond stale and will be auto-closed.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions