spring-cloud / spring-cloud-commons

Common classes used in different Spring Cloud implementations
Apache License 2.0
707 stars 704 forks source link

Spring Boot 2.6.14 + Spring Cloud Context 3.1.5 fullgc #1204

Open Johnson-Jia opened 1 year ago

Johnson-Jia commented 1 year ago

Spring Boot 2.6.14 Nacos 2.1.1 Spring Cloud Context 3.1.5

Use Environment#getProperty to get the configuration center object. Generates a large number of LinkedHashSet objects. Cause the jvm to be full gc.

The code in BootstrapPropertySource is as follows:

@Override
    public String[] getPropertyNames() {
        Set<String> names = new LinkedHashSet<>();
        names.addAll(Arrays.asList(this.delegate.getPropertyNames()));

        return StringUtils.toStringArray(names);
    }

The Environment#getProperty method is used inside the for loop.

Johnson-Jia commented 1 year ago

The code call link is as follows 1676259874383

Johnson-Jia commented 1 year ago

微信图片_20230213114739_看图王

jizhuozhi commented 1 year ago

The Environment#getProperty method is used inside the for loop.

Hello, @Johnson-Jia . It seems the cache of SpringIterableConfigurationPropertySource is not enabled, so each time getProperty will create a new copy of propertyNames for updating mappings.

Not sure whether a bug it is, but you could use ConfigurablePropertySources immediately to lookup your property.

jizhuozhi commented 1 year ago

Hello, @Johnson-Jia .

In my experience, although each execution of getProperty will execute getPropertyNames to get a copy, but because these objects are all life and death, they will be collected in the young generation, unless they exceed the early promotion size (by default -XX:+PretenureSizeThreshold=2m, or half the region size in G1).

This is rarely the case as a dynamic configuration in my experience, so you have more detailed GC logs or heap analysis graphs to give us more helpful information?

Johnson-Jia commented 1 year ago

Thank you. How to enable caching instead of generating a copy of propertyNames every time you use getProperty.

Use scenarios are as follows:

Ten thousand records were queried from the database, and the relevant business logic was executed circularly. The 'getProperty' method was called in the loop, thus a large number of 'propertyNames' configuration objects that could not be recycled were found in the memory snapshot.

Johnson-Jia commented 1 year ago

你好,@jizhuozhi
是不是我的使用方式有问题?还是确实是 Spring Cloud 的一个问题?

场景: 从数据库查出几千或者上万条记录,然后循环这个列表并在循环内使用 getProperty 获取相关配置,看内存快照的信息造成了大量的对象无法被回收。

jizhuozhi commented 1 year ago

Hello, @Johnson-Jia .

This is neither your problem nor spring-cloud's problem. Cache-related logic is provided by spring-boot.

According to the content communicated with spring-boot members (https://github.com/spring-projects/spring-boot/issues/34172#issuecomment-1428945752), configuration in the following way may solve your problem

ConfigurationPropertyCaching.get(environment).setTimeToLive(timeToLive);
Johnson-Jia commented 1 year ago

Thanks @jizhuozhi