Skip to content

Commit

Permalink
Enhance to reuse duplicate spring beans to reduce memory usage.
Browse files Browse the repository at this point in the history
  • Loading branch information
KomachiSion committed Dec 25, 2024
1 parent 1609df9 commit a8ebfba
Show file tree
Hide file tree
Showing 13 changed files with 481 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.io.ClassPathResource;
import org.springframework.jmx.support.MBeanRegistrationSupport;
import org.springframework.jmx.support.RegistrationPolicy;

/**
* Nacos bootstrap class.
Expand All @@ -38,6 +40,7 @@ public class NacosBootstrap {

public static void main(String[] args) {
ConfigurableApplicationContext coreContext = startCoreContext(args);
coreContext.getBean(MBeanRegistrationSupport.class).setRegistrationPolicy(RegistrationPolicy.IGNORE_EXISTING);
String type = coreContext.getEnvironment()
.getProperty(Constants.NACOS_DEPLOYMENT_TYPE, Constants.NACOS_DEPLOYMENT_TYPE_MERGED);
if (Constants.NACOS_DEPLOYMENT_TYPE_MERGED.equals(type)) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Copyright 1999-2023 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.alibaba.nacos.console.config;

import com.alibaba.nacos.core.web.NacosWebBean;
import com.alibaba.nacos.sys.env.Constants;
import com.alibaba.nacos.sys.env.NacosDuplicateConfigurationBeanPostProcessor;
import com.alibaba.nacos.sys.env.NacosDuplicateSpringBeanPostProcessor;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
* Bean Post Processor Configuration for nacos console.
*
* @author xiweng.yy
*/
@Configuration
@NacosWebBean
@ConditionalOnProperty(value = Constants.NACOS_DUPLICATE_BEAN_ENHANCEMENT_ENABLED, havingValue = "true", matchIfMissing = true)
public class NacosConsoleBeanPostProcessorConfiguration {

@Bean
public InstantiationAwareBeanPostProcessor nacosDuplicateSpringBeanPostProcessor(
ConfigurableApplicationContext context) {
return new NacosDuplicateSpringBeanPostProcessor(context);
}

@Bean
public InstantiationAwareBeanPostProcessor nacosDuplicateConfigurationBeanPostProcessor(
ConfigurableApplicationContext context) {
return new NacosDuplicateConfigurationBeanPostProcessor(context);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package com.alibaba.nacos.prometheus.conf;

import com.alibaba.nacos.core.web.NacosWebBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;
Expand All @@ -31,6 +32,7 @@
* @author vividfish
*/
@Configuration
@NacosWebBean
public class PrometheusSecurityConfiguration {

@Bean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import com.alibaba.nacos.server.NacosNormalBeanTypeFilter;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.AutoConfigurationExcludeFilter;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
Expand All @@ -29,10 +30,11 @@
*
* @author xiweng.yy
*/
@SpringBootApplication
@SpringBootApplication()
@ComponentScan(basePackages = "com.alibaba.nacos", excludeFilters = {
@Filter(type = FilterType.REGEX, pattern = "com\\.alibaba\\.nacos\\.console.*"),
@Filter(type = FilterType.CUSTOM, classes = {NacosNormalBeanTypeFilter.class})})
@Filter(type = FilterType.CUSTOM, classes = {NacosNormalBeanTypeFilter.class,
AutoConfigurationExcludeFilter.class})})
@PropertySource("classpath:nacos-server.properties")
public class NacosServerWebApplication {

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Copyright 1999-2023 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.alibaba.nacos.server;

import com.alibaba.nacos.core.web.NacosWebBean;
import com.alibaba.nacos.sys.env.Constants;
import com.alibaba.nacos.sys.env.NacosDuplicateConfigurationBeanPostProcessor;
import com.alibaba.nacos.sys.env.NacosDuplicateSpringBeanPostProcessor;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
* Bean Post Processor Configuration for nacos web server.
*
* @author xiweng.yy
*/
@Configuration
@NacosWebBean
@ConditionalOnProperty(value = Constants.NACOS_DUPLICATE_BEAN_ENHANCEMENT_ENABLED, havingValue = "true", matchIfMissing = true)
public class NacosWebBeanPostProcessorConfiguration {

@Bean
public InstantiationAwareBeanPostProcessor nacosDuplicateSpringBeanPostProcessor(
ConfigurableApplicationContext context) {
return new NacosDuplicateSpringBeanPostProcessor(context);
}

@Bean
public InstantiationAwareBeanPostProcessor nacosDuplicateConfigurationBeanPostProcessor(
ConfigurableApplicationContext context) {
return new NacosDuplicateConfigurationBeanPostProcessor(context);
}
}
3 changes: 2 additions & 1 deletion server/src/main/resources/nacos-server.properties
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,5 @@

### nacos console port:
server.port=${nacos.server.main.port:8080}
server.servlet.contextPath=${nacos.server.contextPath:/nacos}
server.servlet.contextPath=${nacos.server.contextPath:/nacos}
spring.sql.init.mode=never
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* Copyright 1999-2023 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.alibaba.nacos.sys.env;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
import org.springframework.context.ConfigurableApplicationContext;

/**
* Abstract Nacos Duplicate Bean Post Processor of {@link InstantiationAwareBeanPostProcessor} to reduce duplicate rebuild bean for spring beans.
*
* @author xiweng.yy
*/
public abstract class AbstractNacosDuplicateBeanPostProcessor implements InstantiationAwareBeanPostProcessor {

private final ConfigurableApplicationContext coreContext;

protected AbstractNacosDuplicateBeanPostProcessor(ConfigurableApplicationContext context) {
coreContext = null == context.getParent() ? context : (ConfigurableApplicationContext) context.getParent();
}

@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
if (!coreContext.containsBean(beanName)) {
return null;
}
BeanDefinition beanDefinition = coreContext.getBeanFactory().getBeanDefinition(beanName);
return isReUsingBean(beanClass, beanName, beanDefinition) ? coreContext.getBean(beanName) : null;
}

/**
* Judge whether re-use beans from core context.
*
* @param beanClass bean class
* @param beanName bean name
* @param beanDefinition bean definition
* @return {@code true} means re-use beans from core context, otherwise {@code false} means to re-build bean in sub context.
*/
protected abstract boolean isReUsingBean(Class<?> beanClass, String beanName, BeanDefinition beanDefinition);
}
2 changes: 2 additions & 0 deletions sys/src/main/java/com/alibaba/nacos/sys/env/Constants.java
Original file line number Diff line number Diff line change
Expand Up @@ -89,4 +89,6 @@ public interface Constants {
String NACOS_DEPLOYMENT_TYPE_SERVER = "server";

String NACOS_DEPLOYMENT_TYPE_CONSOLE = "console";

String NACOS_DUPLICATE_BEAN_ENHANCEMENT_ENABLED = "nacos.sys.duplicate.bean.enhancement.enabled";
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright 1999-2023 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.alibaba.nacos.sys.env;

import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Configuration;

/**
* Nacos {@link InstantiationAwareBeanPostProcessor} to reduce duplicate rebuild bean for spring configuration.
*
* @author xiweng.yy
*/
public class NacosDuplicateConfigurationBeanPostProcessor extends AbstractNacosDuplicateBeanPostProcessor {

public NacosDuplicateConfigurationBeanPostProcessor(ConfigurableApplicationContext context) {
super(context);
}

@Override
protected boolean isReUsingBean(Class<?> beanClass, String beanName, BeanDefinition beanDefinition) {
return isConfiguration(beanClass);
}

private boolean isConfiguration(Class<?> beanClass) {
return null != beanClass.getAnnotation(Configuration.class) || null != beanClass.getAnnotation(
AutoConfiguration.class);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* Copyright 1999-2023 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.alibaba.nacos.sys.env;

import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
import org.springframework.context.ConfigurableApplicationContext;

/**
* Nacos {@link InstantiationAwareBeanPostProcessor} to reduce duplicate rebuild bean for spring beans.
*
* <p>
* For some important spring beans like spring context beans, if reuse from parent, will cause some problem. So skip.
* </p>
*
* @author xiweng.yy
*/
public class NacosDuplicateSpringBeanPostProcessor extends AbstractNacosDuplicateBeanPostProcessor {

public NacosDuplicateSpringBeanPostProcessor(ConfigurableApplicationContext context) {
super(context);
}

@Override
protected boolean isReUsingBean(Class<?> beanClass, String beanName, BeanDefinition beanDefinition) {
return !isContextBean(beanClass);
}

private boolean isContextBean(Class<?> beanClass) {
return isContextClass(beanClass.getCanonicalName());
}

private boolean isContextClass(String beanClassName) {
return beanClassName.startsWith("org.springframework.context")
|| beanClassName.startsWith("org.springframework.boot.context");
}
}
Loading

0 comments on commit a8ebfba

Please sign in to comment.