如何告诉 Eureka Client 注册哪个端口(Spring Cloud)

Posted

技术标签:

【中文标题】如何告诉 Eureka Client 注册哪个端口(Spring Cloud)【英文标题】:How tell Eureka Client which port to register (Spring Cloud) 【发布时间】:2019-06-12 23:07:36 【问题描述】:

我有一个用 Spring Boot 实现的 Eureka 客户端,它有两个活动端口: 9005 用于 https,9010 用于 http。

Https 由 Spring Boot 原生实现。 Http只是代码中添加的一个额外的简单TomcatServletWebServerFactory

现在的问题是这个 Eureka 客户端使用应用程序属性中指定的 https 端口注册自己为 9005:

server:
   port: 9005
   ssl:
      enabled: true
      ...
   http:
      port: 9010
      address: 127.0.0.1

但我希望这个客户端使用 http 端口 9010 注册自己。

当然,Eureka Server 本身运行在 localhost 上,所有其他注册的服务也在 localhost 上,只使用 http。

Https 用于非 WEB 浏览器的外部客户端,并且在那里使用自定义证书。

我已经在客户端尝试过nonSecurePort,但这似乎是服务器端唯一的配置参数。我的 Eureka Client 的配置(除了上面定义的端口配置):

eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/
    healthcheck:
      enabled: true
  instance:
    preferIpAddress: true
    leaseRenewalIntervalInSeconds: 1
    leaseExpirationDurationInSeconds: 2
    nonSecurePortEnabled: true
    nonSecurePort: 9010

额外的 HttpServer 实现:

public ServletWebServerFactory servletContainer(@Value("$server.http.port") int httpPort, @Value("$server.http.address") String httpHost) throws UnknownHostException 
    Connector connector = new Connector(TomcatServletWebServerFactory.DEFAULT_PROTOCOL);
    connector.setPort(httpPort);
    connector.setAttribute("address", InetAddress.getByName(httpHost).getHostAddress());
    TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();
    tomcat.addAdditionalTomcatConnectors(connector);
    return tomcat;

【问题讨论】:

eureka.instance.non-secure-port 是要走的路。它不是仅服务器端的配置。问题是,根据您的配置,安全端口也处于活动状态,如果是,则 eureka 默认使用此端口。如果您不想使用安全端口,请在 eureka.instance.secure-port-enabled=false 中禁用它。 @spencergibb,没有帮助 :( 我什至尝试过明确设置 health-check-url 等。这些设置似乎被简单地忽略了。一些配置问题?hostname: localhost non-secure-port-enabled: true non-secure-port: 9010 secure-port-enabled: false health-check-url: http://$eureka.instance.hostname:$eureka.instance.non-secure-port/ctx/health status-page-url: http://$eureka.instance.hostname:$eureka.instance.non-secure-port/ctx/info home-page-url: http://$eureka.instance.hostname:$eureka.instance.non-secure-port/ctx 对不起,我之前评论中的 ctx 前缀是错误的。并且网址没有被完全忽略。如果我点击链接,它会打开 status-page-url 中指定的页面。然而,Eureka 服务器上的 Web GUI 仍然显示 https 端口,并且日志显示端口 9005 (https)。同样在日志中,我首先从 com.netflix.discovery.DiscoveryClient 收到“正在注册服务...”消息,然后才收到“Tomcat 在端口上启动:9005 (https) 9010 (http) with context path ''” ... 你有没有得到答案,我也无法设置服务向 Eureka 注册的端口 @waqask87,不,我放弃了。我已经实现了自己的 https ServletContainer 而不是 http。所以 http 变成了原生的,而 https 是在 TomcatServletWebServerFactory 和 org.springframework.boot.web.server.Ssl 的帮助下实现的。希望这会有所帮助。 【参考方案1】:

解决此问题的一种方法是将 SSL 连接器添加为附加连接器,并将非安全连接器保留为默认连接器。

将 SSL 连接器添加为附加连接器:

@Configuration
public class HttpsConfiguration 

    @Value("$sslConfig.key-alias")
    private String keyAlias;

    @Value("$sslConfig.key-store")
    private String keyStoreFile;

    @Value("$sslConfig.key-password")
    private String keyPassword;

    @Value("$sslConfig.key-store-type")
    private String keyStoreType;

    @Value("$sslConfig.port")
    private int sslPort;

    @Bean
    public ServletWebServerFactory servletContainer() 
        TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();
        tomcat.addAdditionalTomcatConnectors(createSslConnector());
        return tomcat;
    

    private Connector createSslConnector() 
        Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
        Http11NioProtocol protocol = (Http11NioProtocol) connector.getProtocolHandler();
        connector.setScheme("https");
        connector.setSecure(true);
        protocol.setSSLEnabled(true);

        connector.setPort(sslPort);
        protocol.setKeystoreFile(keyStoreFile);
        protocol.setKeystorePass(keyPassword);
        protocol.setKeyAlias(keyAlias);
        protocol.setKeystoreType(keyStoreType);
        return connector;
    

连接器的对应配置:

sslConfig:
    key-alias: ode-https
    key-store-type: JKS
    key-password: password
    key-store: ode-https.jks
    port: 443  

如果您不确定如何生成密钥对,可以使用以下命令作为起点:

keytool -genkey -alias ode-https -storetype JKS -keyalg RSA -keys ize 2048 -validity 365 -keystore ode-https.jks

【讨论】:

【参考方案2】:

我从上面的评论中提取答案,使其更明显。

我没有找到直接解决问题的方法,所以我实现了自己的 https ServletContainer 而不是 http。 这意味着 http 成为原生的,而 https 是在 TomcatServletWebServerFactoryorg.springframework.boot.web.server.Ssl 的帮助下实现的。

有关初始化 TomcatServletWebServerFactory,请参见此处: https://www.baeldung.com/embeddedservletcontainercustomizer-configurableembeddedservletcontainer-spring-boot

@Component
public class CustomContainer implements
     WebServerFactoryCustomizer<TomcatServletWebServerFactory> 

  @Override
  public void customize(TomcatServletWebServerFactory factory) 
     factory.setContextPath("");
     factory.setPort(443);
  

启用 SSL:

Ssl ssl = new Ssl();
ssl.setEnabled(true);
// set your keystore here if required
...
// assign ssl to the new Tomcat instance
factory.setSsl(ssl);

我希望这会有所帮助。我没有在这里发布确切的代码 sn-p,因为不幸的是,在一些大公司(他们对自己的知识产权疯狂并且可能与 OSS 许可证发生冲突)它带来的麻烦多于帮助。请 google 获取 https 和 TomcatServletWebServerFactory 示例。

【讨论】:

这与评论相同,添加您为实现此目的所做的代码和配置将帮助其他面临同样问题的人。【参考方案3】:

在启用 Spring Security 后在 Cloud Foundry 上部署 Spring Boot 应用程序时,我遇到了同样的问题。有趣的是我没有在应用程序上启用 HTTPS(仅 8080 端口),但在 Eureka Server 注册的 URL 指向端口 443。

我已经设法解决了这个问题,在应用程序的application.properties 上添加了以下几行(第一行用于使用容器到容器网络,最后两行解决了这个问题)。

eureka.instance.preferIpAddress=true
eureka.instance.securePortEnabled=false
eureka.instance.nonSecurePort=8080

我正在使用 Spring Boot 2.2.8.RELEASE 和 Spring Cloud Hoxton.SR6

【讨论】:

以上是关于如何告诉 Eureka Client 注册哪个端口(Spring Cloud)的主要内容,如果未能解决你的问题,请参考以下文章

Eureka 注册服务列表显示 IP 配置

曹工说mini-dubbo--分析eureka client源码,想办法把我们的服务提供者注册到eureka server(上)

曹工说mini-dubbo--分析eureka client源码,想办法把我们的服务提供者注册到eureka server(上)

SpringCloud Eureka(注册中心集群)

26 eureka问题汇总

Eureka集群