【问题标题】:How to prevent embedded netty server from starting with spring-boot-starter-webflux?如何防止嵌入式netty服务器从spring-boot-starter-webflux启动?
【发布时间】:2017-09-20 07:36:41
【问题描述】:

我想使用 Springs 新的响应式 webflux 扩展在客户端和服务器应用程序之间建立通信。

对于依赖管理,我使用 gradle。 我在服务器端以及客户端的 build.gradle 文件基本上是:

buildscript {
    repositories {
        mavenCentral()
        maven { url "https://repo.spring.io/snapshot" }
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:2.0.0.BUILD-SNAPSHOT")
    }
}

repositories {
    mavenCentral()
    maven { url "https://repo.spring.io/snapshot" }
}

apply plugin: 'java'
apply plugin: 'org.springframework.boot'
apply plugin: "io.spring.dependency-management" 

dependencies {
    compile("org.springframework.boot:spring-boot-starter-webflux")
}

(需要注意的是 2.0.0.BUILD-SNAPSHOT 是一个移动的目标,由于依赖关系内部的变化,手头的问题可能有一天会消失)

当我启动服务器端应用程序时,一切都正常启动,包括嵌入式 netty 服务器的启动。

但是当启动客户端应用程序时,也会启动一个 netty 服务器,导致“java.net.BindException: Address already in use”,因为客户端 netty 服务器侦听与服务器端 netty 服务器相同的端口。

我的问题是:为什么netty首先在客户端启动,我该如何防止它?

根据 Spring-Boot 文档,Spring 尝试确定是否需要 Web 支持并相应地配置 Spring 应用程序上下文。

根据文档,这可以通过调用 setWebEnvironment(false) 来覆盖。我的客户端启动代码如下所示:

@SpringBootApplication(scanBasePackages = { "com.tatics.flux.main" })
public class Client {
    public static void main(String[] args) throws Exception {
        SpringApplication app = new SpringApplication(Client.class);
        app.setWebEnvironment(false);
        app.run(Client.class, args);

        WebClient webClient = WebClient.create();

        Mono<String> result = webClient
                .post()
                .uri("http://localhost:8080/fluxService")

                // This does not work any more: .body("Hallo")
                // and must be replaced by:
                .body(BodyInserters.fromObject("Hallo"))

                .accept(MediaType.TEXT_PLAIN)
                .exchange()
                .flatMap(response -> response.bodyToMono(String.class));
    }
}

不幸的是,netty 仍在启动。 我还注意到 setWebEnvironment(false) 被标记为已弃用。

感谢任何有关如何防止 netty 启动但保留所有 webflux 依赖项的帮助。

以下是自动配置报告的摘录:

=========================
AUTO-CONFIGURATION REPORT
=========================

Positive matches:
-----------------
...

ReactiveWebServerAutoConfiguration matched:
  - found ReactiveWebApplicationContext (OnWebApplicationCondition)

ReactiveWebServerAutoConfiguration#defaultReactiveWebServerCustomizer matched:
  - @ConditionalOnMissingBean (types: org.springframework.boot.autoconfigure.web.reactive.DefaultReactiveWebServerCustomizer; SearchStrategy: all) did not find any beans (OnBeanCondition)

ReactiveWebServerConfiguration.ReactorNettyAutoConfiguration matched:
  - @ConditionalOnClass found required class 'reactor.ipc.netty.http.server.HttpServer'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)
  - @ConditionalOnMissingBean (types: org.springframework.boot.web.reactive.server.ReactiveWebServerFactory; SearchStrategy: all) did not find any beans (OnBeanCondition)

ReactorCoreAutoConfiguration matched:
  - @ConditionalOnClass found required classes 'reactor.core.publisher.Mono', 'reactor.core.publisher.Flux'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)

...

Negative matches:
-----------------
...
ReactiveWebServerConfiguration.JettyAutoConfiguration:
  Did not match:
     - @ConditionalOnClass did not find required class 'org.eclipse.jetty.server.Server' (OnClassCondition)

ReactiveWebServerConfiguration.TomcatAutoConfiguration:
  Did not match:
     - @ConditionalOnClass did not find required class 'org.apache.catalina.startup.Tomcat' (OnClassCondition)

ReactiveWebServerConfiguration.UndertowAutoConfiguration:
  Did not match:
     - @ConditionalOnClass did not find required class 'io.undertow.Undertow' (OnClassCondition)

...

ReactiveWebServerConfiguration.JettyAutoConfiguration:
  Did not match:
     - @ConditionalOnClass did not find required class 'org.eclipse.jetty.server.Server' (OnClassCondition)

ReactiveWebServerConfiguration.TomcatAutoConfiguration:
  Did not match:
     - @ConditionalOnClass did not find required class 'org.apache.catalina.startup.Tomcat' (OnClassCondition)

ReactiveWebServerConfiguration.UndertowAutoConfiguration:
  Did not match:
     - @ConditionalOnClass did not find required class 'io.undertow.Undertow' (OnClassCondition)

【问题讨论】:

    标签: java spring spring-boot spring-webflux


    【解决方案1】:

    除了@Brian_Clozel 答案:

    您可以通过在 application.yml 中指定来禁用 Netty(或任何其他服务器):

    spring.main.web-application-type: none
    

    或application.properties:

    spring.main.web-application-type=none
    

    【讨论】:

      【解决方案2】:

      您的代码的主要问题是您当前正在创建一个SpringApplication,然后您对其进行自定义 - 最后删除所有内容并运行静态方法run(Object primarySource, String... args)

      以下应该有效:

      @SpringBootApplication
      public class Client {
      
          public static void main(String[] args) throws Exception {
              SpringApplication app = new SpringApplication(Client.class);
              app.setWebApplicationType(WebApplicationType.NONE);
              app.run(args);
          }
      
          @Bean
          public CommandLineRunner myCommandLineRunner() {
            return args -> {
              // we have to block here, since command line runners don't
              // consume reactive types and simply return after the execution
              String result = WebClient.create("http://localhost:8080")
                      .post()
                      .uri("/fluxService")
                      .body("Hallo")
                      .accept(MediaType.TEXT_PLAIN)
                      .retrieve()
                      .bodyToMono(String.class)
                      .block();
              // print the result?
            };
          }
      }
      

      如果没有,请使用--debug 标志运行您的应用程序,并将自动配置报告的相关部分添加到您的问题中,尤其是处理服务器的自动配置。

      【讨论】:

      • 你好布赖恩,我用 app.setWebEnvironment(false) 交换了 app.setWebApplicationType(WebApplicationType.NONE);不幸的是,这并没有阻止 netty 启动和随后的“地址已在使用”错误。我在哪里可以获得有关 setWebApplicationType(WebApplicationType.NONE) 参数的信息?
      • 嗨!您可以从 IDE 或 javadoc 获取该信息,因为 setWebEnvironment 从 2.0 开始已被弃用。请分享您的自动配置报告,以便我们找出您的服务器启动的原因。
      • 我在帖子中添加了自动配置报告的摘录
      • 我已经编辑了我的答案以反映问题出在哪里;即,如果您想自定义 SpringApplication 实例,请不要调用静态 run 方法。
      • 这里是关于如何disable the internal web server的spring文档。在大多数情况下,如果有应用程序属性,还有一个选项可以在您的 Java 代码中设置它,就像 @BrianClozel 显示的那样。
      猜你喜欢
      • 2017-08-28
      • 2022-11-20
      • 2021-05-25
      • 1970-01-01
      • 2019-10-11
      • 2018-07-12
      • 2019-04-24
      • 1970-01-01
      • 2019-10-28
      相关资源
      最近更新 更多