Sprboot + Nacos multi-environment deployment

Sprboot + Nacos multi-environment deployment

Problem Description

What nacos is is is not elaborated here. In this blog, the function is as the center of spring boot dynamic configuration. With spring cloud, multi-environment deployment can be easily realized, but with spring boot, problems arise and can not be achieved. Examples are as follows


The application.properties configuration is as follows

server.port=8088
spring.profiles.active=local
nacos.config.server-addr=127.0.0.1:8848

The application-local.properties configuration is as follows

nacos.config.group=LOCAL

The application-myself.properties configuration is as follows

nacos.config.group=MYSELF

The expected effect is that maven is packaged according to different environments, which is very convenient, and the overall change of the project is very small.
It happens that nacos has a spring boot integration solution
github address

But when the whole project is pulled down, it will not work at all, and there will be an error: endpoint not blank, should be the nacos configuration center address not configured or not found.
So if you can't, do it yourself.

Solutions

There are two ways to configure nacos, one is hard-coded and the other is pure configuration file, so there are two ways to solve this problem.
First,
Hard coding, that is, annotating the startup class

@NacosPropertySource(
        groupId = "MYSELF",
        dataId = "eco-mock",
        autoRefreshed = true,
        type = ConfigType.PROPERTIES
)

Almost like this, it's like a way to change the value of the group before the project starts, or the value of the dataId (used to distinguish different configuration environments)

Two.
Pure configuration file

#Turn on configuration preload
nacos.config.bootstrap.enable=true

# Master Configuration Server Address
nacos.config.server-addr=127.0.0.1:8848
# Master configuration data-id
nacos.config.data-id=eco-mock
# Master configuration group-id
nacos.config.group=MYSELF
# Master Configuration File Type
nacos.config.type=properties
# Maximum number of retries for master configuration
nacos.config.max-retry=10
# Main Configuration Opens Automatic Refresh
nacos.config.auto-refresh=true
# Main Configuration Retry Time
nacos.config.config-retry-time=2333
# Master Configuration Monitor Long Polling Timeout
nacos.config.config-long-poll-timeout=46000
# The main configuration opens the registered listener preload configuration service (unless special business requirements do not recommend opening this parameter)
nacos.config.enable-remote-sync-config=true

In some way, let nacos.config.group=MYSELF change this number or let application.properties become our specified environment configuration

Preparation

Configuration of nacos configuration center
dataId:eco-mock
group:myself

eco.test.nacos=myself
eco.enable.sendMsg=false

dataId:eco-mock
group:local

eco.test.nacos=local
eco.enable.sendMsg=false

Configuration file as described above

Output data in reinjected code

@Configuration
@Slf4j
public class CommonParam {
    public static String TEST_NACOS;

    @NacosValue(value = "${eco.test.nacos}",autoRefreshed = true)
    public void setTestNacos(String testNacos) {
        log.info("modify eco.test.nacos ==> {}", testNacos);
        this.TEST_NACOS = testNacos;
    }
}

Specific implementation

Scheme 1 (Personal Recommendation)

First, if the value in the annotation is to be modified only when the class load is initialized, it is to be modified in the static code block of the startup class.

import com.alibaba.nacos.api.config.ConfigType;
import com.alibaba.nacos.spring.context.annotation.config.NacosPropertySource;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.util.Map;
import java.util.Properties;
@NacosPropertySource(
        groupId = "",
        dataId = "eco-mock",
        autoRefreshed = true,
        type = ConfigType.PROPERTIES
)
@EnableScheduling
@SpringBootApplication
public class MockApplication {
    
    static {
        try {
            Properties properties = new Properties();
            properties.load(MockApplication.class.getClassLoader().getResourceAsStream("application.properties"));
			// Read the currently deployed environment from the configuration file
            String profile = properties.getProperty("spring.profiles.active");
			// Read the group corresponding to the specified environment
            properties.load(MockApplication.class.getClassLoader().getResourceAsStream(String.format("application-%s.properties", profile)));
            String groupId = properties.getProperty("nacos.config.group");

			// Assignment
            NacosPropertySource annotation = MockApplication.class.getAnnotation(NacosPropertySource.class);
            InvocationHandler ih = Proxy.getInvocationHandler(annotation);
            Field memberValuesField  = ih.getClass().getDeclaredField("memberValues");
            memberValuesField .setAccessible(true);
            Map map = (Map) memberValuesField .get(ih);
            map.put("groupId", groupId);

        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    public static void main(String[] args) {
        SpringApplication springApplication = new SpringApplication(MockApplication.class);

        springApplication.run(args);
    }

}

First modify the application.properties configuration spring.profiles.active=local


The startup log is as follows

Then configure spring.profiles.active=myself with application.properties

Explain successful configuration
Online projects need only be modified to spring.profiles.active=@activatedProperties@and then deployed according to the maven specified environment.

Programme II

Take a look at this blog maven scheme in
The idea is the same, because the configuration file preloads the application.properties.
Then I just need to package the specified configuration files, such as application-local.properties, into application.properties.
I will not write about the specific implementation, much the same as little.

summary

If there is a better and more elegant solution, I hope to leave a message to learn, thank you!

Tags: Spring Java Maven

Posted on Mon, 09 Sep 2019 05:51:19 -0700 by coolispaul