springCloudGateway+Nacos注册与转发Netty+WebSocket

Netty+WebSocket是一开始单体应用中与前端交互使用的,最近开始搞Cloud想着移植过来使用

具体官方描述本文就不体现了 直接开始实现 以及解决过程中遇到的问题

1.首先编写netty端代码,由于是微服务模式就直接新建一个项目

        

server:
  port: 8085
spring:
  application:
    name: mall-im
    
netty:
  # Netty端口
  port: 9001
  application:
    # Netty应用名称
    name: mall-im-netty

1.1 由于Netty 需要额外启动所以配置一个启动器,这里有一个小坑,很多同学习惯把自定义启动放到服务启动类里,其实也没事,但是只要你使用@RefreshScope注解后就会产生自定义启动被启动了两次的问题,感兴趣的同学可以自己尝试一下

/**
 * Netty 额外启动类
 *
 * @author 杨旭
 * @email 18811132173@163.com
 * @create 2023/11/16 17:25
 */
@Component
public class NettyCommandLineRunner implements CommandLineRunner {

    @Resource
    private NettyWebSocketServer nettyServer;

    @Override
    public void run(String... args) throws Exception {
        //netty 服务端启动的端口不可和Springboot启动类的端口号重复
        nettyServer.start();

        //关闭服务器的时候同时关闭Netty服务
        Runtime.getRuntime().addShutdownHook(new Thread(() -> nettyServer.destroy()));
    }
}

1.2 定义启动

/**
 * Netty启动类
 *
 * @author 杨旭
 * @email 18811132173@163.com
 * @create 2023/11/16 16:39
 */
@Slf4j
@Component
public class NettyWebSocketServer {

    private Channel channel;

    /**
     * bossGroup连接线程组,主要负责接受客户端连接,一般一个线程足矣
     */
    EventLoopGroup boosGroup = new NioEventLoopGroup();
    /**
     * workerGroup工作线程组,主要负责网络IO读写
     */
    EventLoopGroup workGroup = new NioEventLoopGroup();

    @Resource
    private NacosDiscoveryProperties nacosDiscoveryProperties;
    /**
     * Netty端口
     */
    @Value("${netty.port}")
    private Integer nettyPort;
    /**
     * Netty应用名称
     */
    @Value("${netty.application.name}")
    private String nettyName;

    @Async
    public void start() {
        log.error("=================Netty 端口启动:{}==================", nettyPort);
        try {
            //绑定端口
            ServerBootstrap bootstrap = new ServerBootstrap();
            // 临时存放已完成三次握手的请求的队列的最大长度
            bootstrap.option(ChannelOption.SO_BACKLOG, 1024);
            // 设置两个线程组
            bootstrap.group(boosGroup, workGroup)
                    // 非阻塞异步服务端TCP Socket 连接
                    .channel(NioServerSocketChannel.class)
                    // 使用本地地址,绑定端口号
                    .localAddress(nettyPort)
                    //初始化handler
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            log.info("=================收到新的链接:{}==================", socketChannel.localAddress());
                            ChannelPipeline pipeline = socketChannel.pipeline();
                            // 将请求和映带消息节码为HTTP消息
                            pipeline.addLast("http-codec", new HttpServerCodec());
                            // 向客户端发送HTML5文件
                            socketChannel.pipeline().addLast("http-chunked", new ChunkedWriteHandler());
                            // 将HTTP消息的多个部分合成一条完整的HTTP消息
                            pipeline.addLast("aggregator", new HttpObjectAggregator(8192));
                            // 进行设置心跳检测
                            socketChannel.pipeline().addLast(new IdleStateHandler(60, 30, 60 * 30, TimeUnit.SECONDS));
                            // 配置通道处理 来进行业务处理
                            pipeline.addLast("handler", new WebSocketHandler());
                        }
                    });
            registerNamingService(nettyName, nettyPort);
            //绑定Netty的启动端口
            channel = bootstrap.bind(nettyPort).sync().channel();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 将Netty服务注册进Nacos
     *
     * @param nettyName 服务名称
     * @param nettyPort 服务端口号
     */
    private void registerNamingService(String nettyName, Integer nettyPort) {
        try {
            Properties properties = new Properties();
            properties.setProperty(PropertyKeyConst.SERVER_ADDR, nacosDiscoveryProperties.getServerAddr());
            properties.setProperty(PropertyKeyConst.NAMESPACE, nacosDiscoveryProperties.getNamespace());
            NamingService namingService = NamingFactory.createNamingService(properties);
            InetAddress address = InetAddress.getLocalHost();
            namingService.registerInstance(nettyName, address.getHostAddress(), nettyPort);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @PreDestroy
    public void destroy() {
        log.error("=================Netty服务关闭==================");
        if (channel != null) {
            channel.close();
        }
        boosGroup.shutdownGracefully();
        workGroup.shutdownGracefully();
    }
}

1.3 业务实现,由于具体的业务还没想好怎么做所以就空下来了,本文主要是集成

/**
 * Netty业务实现类
 *
 * @author 杨旭
 * @email 18811132173@163.com
 * @create 2023/11/16 16:42
 */
public class WebSocketHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {
    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, TextWebSocketFrame textWebSocketFrame) throws Exception {
        // TODO: 具体业务处理
    }
}

这个时候启动服务,可以看到已经成功启动了

使用工具访问一下

2.接下来就是怎么将Netty用gateway 进行访问,同样具体的路由配置以及规则不进行赘述,大家自行百度

2.1 gateway增加路由

- id: mall-im
  uri: lb:ws://mall-im-netty
  predicates:
     - Path=/ws/**
  filters:
     - StripPrefix=1

2.2 增加路由后重新启动服务,并额外启动一个服务,开发环境多实例运行,注意(开发环境需要手动将.yml文件中端口号修改)多实例运行点击工具栏上方的启动,正常或调试均可

2.3 用gateway进行访问

 

2.4 可以多尝试几次,这样就能实验出负载均衡的效果了

2.5 PS:如果是后端管理系统,发送个通知之类的 到目前为止,将业务处理实现就可以了,但如果是即时通讯,就会出现一个问题,A在9001,B在9002 这样两个人怎么进行通讯呢?

有思路的小伙伴咱们可以一起讨论下

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
根据提供的引用内容,springcloud nacos gateway knife的问题可能是关于如何在Spring Cloud中使用Nacos作为注册中心和配置中心,以及如何引入Knife4j的相关依赖的。下面是一个可能的回答: 在你的Spring Cloud项目中,你可以通过引入Nacos的相关依赖来将Nacos作为注册中心和配置中心。具体来说,你需要在pom.xml中引入以下依赖: ```xml <!-- Nacos注册中心依赖 --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> <version>${nacos.version}</version> </dependency> <!-- Nacos配置中心依赖 --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> <version>${nacos.version}</version> </dependency> ``` 请在pom.xml中添加上述依赖以启用Nacos作为注册中心和配置中心。 另外,如果你还想在服务和网关中使用Knife4j,你需要在pom.xml中引入以下依赖: ```xml <!-- Knife4j依赖 --> <dependency> <groupId>com.github.xiaoymin</groupId> <artifactId>knife4j-spring-boot-starter</artifactId> <version>2.0.3</version> </dependency> ``` 请在pom.xml中添加上述依赖以启用Knife4j。 此外,你还需要在配置文件中进行相应的配置。例如,你可以在application.yml或application.properties中添加以下配置: ```yaml spring: profiles: active: dev application: name: bssp-gateway-service cloud: nacos: config: server-addr: 127.0.0.1:8848 namespace: 3a44ef28-b35c-44bb-8cd2-873c14ebc911 group: DEFAULT_GROUP file-extension: yml discovery: server-addr: 127.0.0.1:8848 namespace: 3a44ef28-b35c-44bb-8cd2-873c14ebc911 gateway: discovery: locator: enabled: true ``` 请根据你的具体需求修改上述配置,确保Nacos和Knife4j的配置正确。 希望以上信息对你有帮助。如果还有其他问题,请随时提问。
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值