Home  >  Article  >  Java  >  How to solve the problem when SpringBoot is deployed to external Tomcat and cannot be registered to the Nacos server

How to solve the problem when SpringBoot is deployed to external Tomcat and cannot be registered to the Nacos server

WBOY
WBOYforward
2023-05-13 23:13:042398browse

What happened

Recently, I have done a project bidding demonstration (POC) environment support, which needs to be integrated with the Nacos server. Considering that existing projects already have Nacos-related dependencies, isn't that simple? Create a new server, configure it and restart it a few times, right? However, things are far from being as simple as thought. The same code can be successfully registered when run in my local IDE, but cannot be deployed in the demo environment Tomcat War.

After the remote Debug code, it was found that the threads of the Nacos client were started, but the registration was not successful.

Thinking

I thought it might be related to the Tomcat deployment mode, so I checked the official issue and StackOverFlow

The event is published as part of Spring Boot starting the embedded Tomcat instance . If you're deploying to an external container, there's no embedded container to start and, therefore, no event is published. – Andy Wilkinson

Roughly speaking, only when Spring Boot starts the embedded Tomcat successfully, The WebServerInitializedEvent event will be released. The Nacos client will wait for this event to occur before registering itself with the server. And because it is deployed in external Tomcat, the embedded Tomcat will not be initialized, so this event will not be triggered.

So the solution is to call part of the code for events such as Nacos and let them start registration.

Nacos's automatic registration class is NacosAutoServiceRegistration, which inherits Spring Cloud's AbstractAutoServiceRegistration, bind(WebServerInitializedEvent) in AbstractAutoServiceRegistration, etc. Method listens for events, sets the port number and starts registration. Here this.port is obtained from the event and needs to be obtained by ourselves.

How to solve the problem when SpringBoot is deployed to external Tomcat and cannot be registered to the Nacos server

The location where the port is set is visible. It is taken from org.springframework.cloud.client.serviceregistry.Registration. Just set it. That's it.

How to solve the problem when SpringBoot is deployed to external Tomcat and cannot be registered to the Nacos server

Solution

I wrote a complete configuration class and placed it under the ISSUE, which is posted directly below.

import java.lang.management.ManagementFactory;
import java.util.Set;
 
import javax.annotation.PostConstruct;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.management.Query;
 
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
 
import com.alibaba.cloud.nacos.registry.NacosAutoServiceRegistration;
import com.alibaba.cloud.nacos.registry.NacosRegistration;
 
@Configuration
public class NacosWarDeployConfig {
    private static final Logger logger = LoggerFactory.getLogger(NacosWarDeployConfig.class);
 
    @Autowired
    private Environment env;
    @Autowired
    private NacosRegistration registration;
    @Autowired
    private NacosAutoServiceRegistration nacosAutoServiceRegistration;
 
    @PostConstruct
    public void nacosServerRegister() {
        if (registration != null) {
            registration.setPort(getTomcatPort());
            nacosAutoServiceRegistration.start();
        }
    }
 
    public int getTomcatPort() {
        try {
            return getProvideTomcatPort();
        } catch (Exception e) {
            logger.warn("obtain provide tomcat port failed, fallback to embeded tomcat port.");
        }
        return getEmbeddedTomcatPort();
    }
 
    private int getProvideTomcatPort() throws MalformedObjectNameException, NullPointerException {
        MBeanServer beanServer = ManagementFactory.getPlatformMBeanServer();
        Set<ObjectName> objectNames = beanServer.queryNames(new ObjectName("*:type=Connector,*"),
                Query.match(Query.attr("protocol"), Query.value("HTTP/1.1")));
        String port = objectNames.iterator().next().getKeyProperty("port");
        return Integer.valueOf(port);
    }
 
    private int getEmbeddedTomcatPort() {
        return env.getProperty("server.port", Integer.class, 8080);
    }
 
}

The above is the detailed content of How to solve the problem when SpringBoot is deployed to external Tomcat and cannot be registered to the Nacos server. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:yisu.com. If there is any infringement, please contact admin@php.cn delete