Heim >Java >javaLernprogramm >So lösen Sie das Problem, wenn SpringBoot auf einem externen Tomcat bereitgestellt wird und nicht beim Nacos-Server registriert werden kann

So lösen Sie das Problem, wenn SpringBoot auf einem externen Tomcat bereitgestellt wird und nicht beim Nacos-Server registriert werden kann

WBOY
WBOYnach vorne
2023-05-13 23:13:042417Durchsuche

Was ist passiert

Vor Kurzem führe ich eine POC-Umgebungsunterstützung (Project Bidding Demonstration) durch, die in den Nacos-Server integriert werden muss. Ist das nicht einfach, wenn man bedenkt, dass bestehende Projekte bereits Nacos-bezogene Abhängigkeiten aufweisen? Erstellen Sie einen neuen Server, konfigurieren Sie ihn und starten Sie ihn ein paar Mal neu, oder? Allerdings sind die Dinge bei weitem nicht so einfach wie gedacht. Derselbe Code kann erfolgreich registriert werden, wenn er in meiner lokalen IDE ausgeführt wird, kann jedoch nicht in der Demoumgebung Tomcat+War bereitgestellt werden.

Nach dem Remote-Debuggen des Codes wurde festgestellt, dass die Threads des Nacos-Clients gestartet wurden, die Registrierung jedoch nicht erfolgreich war.

Gedanken

Da ich dachte, dass es mit dem Tomcat-Bereitstellungsmodus zusammenhängen könnte, habe ich das offizielle Problem und StackOverFlow überprüft.

Die Veranstaltung wird als Teil veröffentlicht Wenn Sie die eingebettete Tomcat-Instanz starten, gibt es keinen eingebetteten Container, der gestartet werden muss, und daher wird grob gesagt kein Ereignis veröffentlicht wenn Spring Das WebServerInitializedEvent-Ereignis wird erst freigegeben, nachdem Boot den eingebetteten Tomcat erfolgreich gestartet hat. Der Nacos-Client wartet auf das Eintreten dieses Ereignisses, bevor er sich beim Server registriert. Da es im externen Tomcat bereitgestellt wird, wird das eingebettete Tomcat nicht initialisiert, sodass dieses Ereignis nicht ausgelöst wird.

Die Lösung besteht also darin, einige Veranstaltungscodes wie Nacos anzurufen und sie mit der Registrierung beginnen zu lassen. WebServerInitializedEvent 事件。而Nacos客户端在等这个事件出现才会向服务端注册自己。又因部署在外部Tomcat中就不会初始化内嵌Tomcat,也就没触发这个事件。

所以解决方法就是将Nacos等事件的部分代码调用下,让他们启动注册。

Nacos的自动注册类是 NacosAutoServiceRegistration,它继承Spring Cloud的AbstractAutoServiceRegistration,在AbstractAutoServiceRegistration等的 bind(WebServerInitializedEvent)方法监听事件,设置端口号并启动注册。这里边 this.port 是从事件中获取的,需要我们自行获取。

So lösen Sie das Problem, wenn SpringBoot auf einem externen Tomcat bereitgestellt wird und nicht beim Nacos-Server registriert werden kann

设置port的位置可见,是从org.springframework.cloud.client.serviceregistry.Registration

Die automatische Registrierungsklasse von Nacos ist NacosAutoServiceRegistration, die AbstractAutoServiceRegistration, AbstractAutoServiceRegistration und andere bind von Spring Cloud erbt (WebServerInitializedEvent)-Methode wartet auf Ereignisse, legt die Portnummer fest und startet die Registrierung. Hier wird this.port von der Veranstaltung abgerufen und muss von uns selbst abgerufen werden.

So lösen Sie das Problem, wenn SpringBoot auf einem externen Tomcat bereitgestellt wird und nicht beim Nacos-Server registriert werden kannSpringBoot, das auf externem Tomcat bereitgestellt wird, kann sich nicht beim Nacos-Dienst registrieren So lösen Sie das Problem am Ende

Der Ort, an dem der Port festgelegt ist, ist sichtbar. Er wird von org.springframework.cloud.client.serviceregistry.Registration abgerufen . Einfach einstellen.

#🎜🎜##🎜🎜#Lösung#🎜🎜##🎜🎜#Ich habe eine vollständige Konfigurationsklasse geschrieben und sie unter dem ISSUE platziert, das direkt unten gepostet wird. #🎜🎜#
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);
    }
 
}

Das obige ist der detaillierte Inhalt vonSo lösen Sie das Problem, wenn SpringBoot auf einem externen Tomcat bereitgestellt wird und nicht beim Nacos-Server registriert werden kann. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:yisu.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen