繁体   English   中英

在相同的 Spring 启动应用程序中使用 Tomcat HTTP 和 Netty UDP

[英]Using Tomcat HTTP and Netty UDP in same Spring Boot Application

我正在编写一个需要能够侦听 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 应用程序中一起运行?

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM