V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
wellR
V2EX  ›  Java

在 SpringBoot 中使用 Netty 的思路,偷梁换柱之计

  •  
  •   wellR · 2023-04-15 21:53:07 +08:00 · 3963 次点击
    这是一个创建于 588 天前的主题,其中的信息可能已经有所发展或是发生改变。

    项目中准备用 netty 做些定制化的功能,自然而然用上了 SpringBoot 这套,招不在老管用就好。思路就是不启动 tomcat ,在主线程启动 netty 。

    	public static void main(String[] args) {
            StopWatch stopWatch = new StopWatch();
            stopWatch.start("start app...");
            ConfigurableApplicationContext context = SpringApplication.run(NettyServer.class, args);
            //get bean
            SecondHandler handler = context.getBean(SecondHandler.class);
            int port = context.getEnvironment().getProperty("server.port", Integer.class, 9000);
            EventLoopGroup bossGroup = new NioEventLoopGroup(1);
            EventLoopGroup workerGroup = new NioEventLoopGroup(16);
            try {
                ServerBootstrap b = new ServerBootstrap();
                b.group(bossGroup, workerGroup)
                        .channel(NioServerSocketChannel.class)
                        .localAddress(new InetSocketAddress(port))
                        .childHandler(new ChannelInitializer<SocketChannel>() {
                            @Override
                            public void initChannel(SocketChannel ch) {
                                ch.pipeline()
                                        .addLast("codec", new HttpServerCodec())
                                        .addLast("compressor", new HttpContentCompressor())
                                        .addLast("aggregator", new HttpObjectAggregator(65536))
                                        .addLast("handler", handler);
                            }
                        })
                        .childOption(ChannelOption.SO_KEEPALIVE, true);
                ChannelFuture f = b.bind().sync();
                stopWatch.stop();
                log.info("Netty Server started ,Listening on {}, info={}", port, stopWatch.prettyPrint());
                f.channel().closeFuture().sync();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                workerGroup.shutdownGracefully();
                bossGroup.shutdownGracefully();
            }
        }
    

    项目链接

    30 条回复    2023-05-06 08:48:46 +08:00
    liuhai233
        1
    liuhai233  
       2023-04-15 21:56:52 +08:00 via iPhone
    不是可以选 reactive 嘛,默认就是 netty 了吧
    wellR
        2
    wellR  
    OP
       2023-04-15 22:03:08 +08:00
    @liuhai233 哦 webflux 没在生产上用过,相对来说 netty 更好做定制化开发
    chendy
        3
    chendy  
       2023-04-15 22:06:08 +08:00
    不启动 tomcat 可以直接不要 tomcat ,留个啥东西不让 main 退出就行…
    wellR
        4
    wellR  
    OP
       2023-04-15 22:14:00 +08:00
    @chendy 是这样的,一直以来用 SpringBoot 搞 web 开发都形成思维定势了,这次是打开思路了,SpringBoot 还可以来做 webMvc 开发之外的东西
    wellR
        5
    wellR  
    OP
       2023-04-15 22:16:57 +08:00
    SpringBoot 用了这么久了,才知道 SpringApplication.run 返回了 ApplicationContext ,哈
    fzdwx
        6
    fzdwx  
       2023-04-15 23:32:46 +08:00   ❤️ 1
    以前我也写过一个类似的哈哈 https://github.com/fzdwx/sky
    lsk569937453
        7
    lsk569937453  
       2023-04-15 23:35:57 +08:00   ❤️ 1
    不要加 springboot-web 的 starter,直接用 springboot 的 CommandLineRunner 里运行 netty 即可啊
    silentsky
        8
    silentsky  
       2023-04-16 00:29:13 +08:00 via Android
    这么巧 今天我也在整这个
    zhiyu1998
        9
    zhiyu1998  
       2023-04-16 01:26:52 +08:00
    学到了,感谢分享
    dreamlike
        10
    dreamlike  
       2023-04-16 03:14:20 +08:00 via Android
    🤔你这样写其实没有把 server 的生命周期托管给 spring 看起来,
    wellR
        11
    wellR  
    OP
       2023-04-16 08:21:43 +08:00 via Android
    @dreamlike 是的,这是野路子
    niuroumian
        12
    niuroumian  
       2023-04-16 08:28:14 +08:00   ❤️ 1
    没必要折腾,https://armeria.dev/
    cnzjl
        13
    cnzjl  
       2023-04-16 09:06:45 +08:00   ❤️ 1
    用 Smartlifecycle ,不添加 web 依赖
    dreamlike
        14
    dreamlike  
       2023-04-16 11:58:31 +08:00 via Android
    等下 我看了你这个代码 其实就是搞了一个基于 netty 的 http 服务器,我建议直接换 vertx or quarkus 吧
    LeegoYih
        15
    LeegoYih  
       2023-04-16 12:04:29 +08:00
    这样写不就好了?

    SpringApplication application = new SpringApplication(NettyServer.class);
    application.setApplicationContextFactory(ApplicationContextFactory.ofContextClass(AnnotationConfigApplicationContext.class));
    application.run(args);
    LeegoYih
        16
    LeegoYih  
       2023-04-16 12:16:29 +08:00
    new SpringApplicationBuilder(ChatServerApplication.class)
    .web(WebApplicationType.NONE)
    .run(args);
    WispZhan
        17
    WispZhan  
       2023-04-16 16:37:20 +08:00 via Android
    不理解,为什么不直接用 vert.x 之类的?
    wellR
        18
    wellR  
    OP
       2023-04-16 18:21:23 +08:00
    @dreamlike 是的,要做一个异步实时响应的服务。webflux 不好上手,请问 vertx 的使用体验如何,与 webflux 比怎么样
    wellR
        19
    wellR  
    OP
       2023-04-16 18:29:15 +08:00
    大体流程:
    1 、客户端发送请求,参数中有业务数据、超时时间与回调接口;
    2 、服务 A 收到请求,初步处理 task 再发 mq
    3 、服务 B 消费 mq 进行一系列比较耗时的操作之后将处理结果发到 mq 广播消息
    4 、服务 A 消费 mq 响应客户端
    5 、若上述处理流程中超时了,则立即返回客户端,后台 task 跑完了会调客户端的回调
    dreamlike
        20
    dreamlike  
       2023-04-16 19:15:44 +08:00 via Android
    @wellR 我看这个需求很简单 也没有什么复杂的逻辑 直接 vertx 上吧 又轻又快 用好 eventbus ,开发速度应该是爆杀 webflux 的,开 n 个 vertical 跑满核心就行了
    cookii
        21
    cookii  
       2023-04-17 00:55:18 +08:00
    直接用 webflux 。除非是非 http 协议
    crazyweeds
        22
    crazyweeds  
       2023-04-17 09:24:50 +08:00
    太复杂,直接:
    CountDownLatch countdown = new CountDownLatch(1);
    countdown.await();
    然后 netty 该怎么写就怎么写。
    justRua
        23
    justRua  
       2023-04-17 09:44:25 +08:00
    有现成的 grpc-spring-boot-starter ,协议是 grpc ,实现是 netty
    byte10
        24
    byte10  
       2023-04-17 10:57:33 +08:00
    我用的是 springboot + vert.x ,我也推荐你使用 vert.x ,当然,最好直接用虚拟线程 + vert.x ,不过我好像测试出现 bug 。你尝试一下
    wellR
        25
    wellR  
    OP
       2023-04-17 11:03:56 +08:00 via Android
    @byte10 java 中现在能用虚拟线程了吗
    byte10
        26
    byte10  
       2023-04-17 11:11:58 +08:00
    @wellR java 19 就有预览版,现在 java20 版本也出来了。预计明年应该可以出生产 版吧。前期我推荐使用 线程池 来解决代码同步编程的问题(异步转同步 ),后续直接使用虚拟线程代替线程池,完美接管。可以先了解下 虚拟线程的目前存在的问题吧
    wellR
        27
    wellR  
    OP
       2023-04-17 11:45:31 +08:00
    @byte10 生产上还是 java8 ,不敢上太高版本的
    wellR
        28
    wellR  
    OP
       2023-04-17 11:48:53 +08:00
    @byte10 我的解决思路是,缓存 ChannelHandlerContext ,等待回调或者 mq 消息,再取出对应的 ChannelHandlerContext 执行 writeAndFlush 响应客户端
    cslive
        29
    cslive  
       2023-04-18 09:04:17 +08:00
    将 tomcat 依赖改成 netty 也可以啊,又不非得用 tomcat 启动
    tramm
        30
    tramm  
       2023-05-06 08:48:46 +08:00
    啊, 我一直以为不加 web 依赖, 就没有 Tomcat 了...
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1224 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 18:18 · PVG 02:18 · LAX 10:18 · JFK 13:18
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.