【问题标题】:Using Tomcat HTTP and Netty UDP in same Spring Boot Application在同一个 Spring Boot 应用程序中使用 Tomcat HTTP 和 Netty UDP
【发布时间】:2021-02-25 07:25:47
【问题描述】:

我正在编写一个需要能够侦听 UDP 数据报并公开一些 HTTP 端点的应用程序。

我将 Spring Boot 与 Web Starter 用于 HTTP 部分,将 Netty 用于 UDP。

要设置 UDP,我使用以下代码:

@Configuration
class NettyConfig(
        @Value("\${netty.port}")
        val port: Int,
        @Value("\${netty.epoll}")
        val epoll: Boolean
) {

    val log = LoggerFactory.getLogger(NettyConfig::class.java)!!

    @Bean
    fun executor() = Executors.newFixedThreadPool(threads)!!

    @Bean
    fun bootstrap(handlerService: HandlerService): Bootstrap {

        val master: EventLoopGroup
        val clazz: Class<out Channel>

        log.info("Starting Netty Server. EPoll enable: $epoll")

        if (epoll) {
            master = EpollEventLoopGroup(1) 
            clazz = EpollDatagramChannel::class.java
        } else {
            master = NioEventLoopGroup(1) 
            clazz = NioDatagramChannel::class.java
        }

        val bootstrap = Bootstrap()
                .group(master)
                .channel(clazz)
                .option(ChannelOption.SO_SNDBUF, 1048576)
                .option(ChannelOption.SO_RCVBUF, 1048576)
                .option(ChannelOption.RCVBUF_ALLOCATOR, AdaptiveRecvByteBufAllocator(2048, 2048, 64 * 2048))
                .option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)
                .option(ChannelOption.SO_BROADCAST, true)
                .handler(object: ChannelInitializer<DatagramChannel>() {
                    override fun initChannel(ch: DatagramChannel) {
                        ch.pipeline().addLast(
                                LineBasedFrameDecoder(1048576),
                                handler(handlerService))
                    }
                })

        val channel = bootstrap.bind(port).sync().channel()
        log.info("Started Netty Server. Listening on {}", port)
        channel.closeFuture().sync()
        log.info("Stopped Netty Server.")
        return bootstrap
    }
...

其中一个HTTP部分由Spring Starter Web管理,由Tomcat实现。

我想要达到的目标:

  • 应用程序在给定端口(例如 5432)上侦听 UDP 事件
  • 应用程序在 8080 端口上侦听 HTTP 请求
  • 应用程序实现它自己的 HTTP API
  • 应用程序通过 HTTP 公开执行器端点以管理/监控它

这两个部分都在工作,但不能一起工作。通过反复试验,我遇到了以下问题: 如果我注释掉这一行(即不启动 Netty):

val channel = bootstrap.bind(port).sync().channel()

HTTP 部分有效(而 UDP obv. 无效)。如果我把它留在原地 - 一切都开始了,但是,任何对 8080 端口的请求都会给出连接被拒绝的错误。

据我了解,应该没有问题,因为两台服务器都在侦听不同的端口(5432 与 8080),这就是我在日志消息中得到的信息。所以两台服务器之间存在一些重要的交互,我不知道。

如何解决,让两台服务器在同一个 JVM/Spring Boot App 中一起运行?

【问题讨论】:

    标签: java spring-boot netty


    【解决方案1】:

    我怀疑由于 channel.closeFuture().sync()bootstrap @Bean 方法中,您的应用程序没有完成启动。由于启动未完成,Tomcat 没有机会启动,因此无法接受任何传入的连接。

    您应该使用destroy 方法调用channel.closeFuture().sync(),而不是阻止bean 的创建,作为应用程序上下文关闭处理的一部分。为此,您可以实现 DisposibleBean 或使用 @PreDestroy 注释方法。

    【讨论】:

    • 完全正确!我刚刚通过创建引导创建方法@Async 修复了它
    猜你喜欢
    • 2019-06-23
    • 2021-09-04
    • 2015-12-30
    • 2018-08-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-19
    • 1970-01-01
    相关资源
    最近更新 更多