springboot之springboot与netty整合方案

 更新时间:2023年06月27日 15:12:26   作者:RachelHwang  
这篇文章主要介绍了VUE之关于store状态管理核心解析,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

1、简单概述

Netty是一个高性能、异步事件驱动的NIO框架,基于JAVA NIO提供的API实现。

它提供了对TCP、UDP和文件传输的支持,作为一个异步NIO框架,Netty的所有IO操作都是异步非阻塞的,通过Future-Listener机制,用户可以方便的主动获取或者通过通知机制获得IO操作结果。

作为当前最流行的NIO框架,Netty在互联网领域、大数据分布式计算领域、游戏行业、通信行业等获得了广泛的应用,一些业界著名的开源组件也基于Netty的NIO框架构建。

Netty 对 JDK 自带的 NIO 的 API 进行封装,解决上述问题,主要特点有:

  • 设计优雅,适用于各种传输类型的统一 API 阻塞和非阻塞 Socket;基于灵活且可扩展的事件模型,可以清晰地分离关注点;高度可定制的线程模型,单线程,一个或多个线程池;真正的无连接数据报套接字支持(自 3.1 起)。
  • 使用方便,详细记录的 Javadoc,用户指南和示例;没有其他依赖项,JDK 5(Netty 3.x)或 6(Netty 4.x)就足够了。
  • 高性能,吞吐量更高,延迟更低;减少资源消耗;最小化不必要的内存复制。
  • 安全,完整的 SSL/TLS 和 StartTLS 支持。
  • 社区活跃,不断更新,社区活跃,版本迭代周期短,发现的 Bug 可以被及时修复,同时,更多的新功能会被加入。

2、IO模型

Netty 作为异步事件驱动的网络,高性能之处主要来自于其 I/O 模型和线程处理模型,前者决定如何收发数据,后者决定如何处理数据。

I/O 复用模型:

在 I/O 复用模型中,会用到 Select,这个函数也会使进程阻塞,但是和传统的JAVA阻塞 I/O 所不同的是这两个函数可以同时阻塞多个 I/O 操作。

而且可以同时对多个读操作,多个写操作的 I/O 函数进行检测,直到有数据可读或可写时,才真正调用 I/O 操作函数。

Netty 的非阻塞 I/O 的实现关键是基于 I/O 复用模型,这里用 Selector 对象表示:

Netty 的 IO 线程 NioEventLoop 由于聚合了多路复用器 Selector,可以同时并发处理成百上千个客户端连接。

当线程从某客户端 Socket 通道进行读写数据时,若没有数据可用时,该线程可以进行其他任务。

线程通常将非阻塞 IO 的空闲时间用于在其他通道上执行 IO 操作,所以单独的线程可以管理多个输入和输出通道。

由于读写操作都是非阻塞的,这就可以充分提升 IO 线程的运行效率,避免由于频繁 I/O 阻塞导致的线程挂起。

一个 I/O 线程可以并发处理 N 个客户端连接和读写操作,这从根本上解决了传统同步阻塞 I/O 一连接一线程模型,架构的性能、弹性伸缩能力和可靠性都得到了极大的提升。

3、事件模型

下图描述了Netty进行事件处理的流程。

Channel是连接的通道,是ChannelEvent的产生者,而ChannelPipeline可以理解为ChannelHandler的集合。

在这里插入图片描述

在Netty里,所有事件都来自ChannelEvent接口,这些事件涵盖监听端口、建立连接、读写数据等网络通讯的各个阶段。

而事件的处理者就是ChannelHandler,这样,不但是业务逻辑,连网络通讯流程中底层的处理,都可以通过实现ChannelHandler来完成了。

事实上,Netty内部的连接处理、协议编解码、超时等机制,都是通过handler完成的。

3、springboot与netty集成

3.1 添加netty+springboot依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>
<dependency>
    <groupId>io.netty</groupId>
    <artifactId>netty-all</artifactId>
    <version>4.1.28.Final</version>
</dependency>

3.2 netty服务端配置

/**
 * 服务端基本配置,通过一个静态单例类,保证启动时候只被加载一次
 */
@Component
public class WsServer {
	/**
	 * 单例静态内部类
	 */
	public static class SingletionWServer{
		static final WsServer instance = new WsServer(); 
	}
	public static WsServer getInstance(){
		return SingletionWServer.instance;
	}
	private EventLoopGroup mainGroup ;
	private EventLoopGroup subGroup;
	private ServerBootstrap server;
	private ChannelFuture future;
	public WsServer(){
		mainGroup = new NioEventLoopGroup();
		subGroup = new NioEventLoopGroup();
		server = new ServerBootstrap();
		server.group(mainGroup, subGroup)
				.channel(NioServerSocketChannel.class)
				.childHandler(new WsServerInitialzer());//添加自定义初始化处理器
	}
	public void start(){
		future = this.server.bind(8081);
		System.err.println("netty 服务端启动完毕 .....");
	}
}

自定义初始化处理器: WsServerInitialzer

public class WsServerInitialzer extends ChannelInitializer<SocketChannel>{
	@Override
	protected void initChannel(SocketChannel ch) throws Exception {
		ChannelPipeline pipeline = ch.pipeline();
		//websocket基于http协议,所以需要http编解码器
		pipeline.addLast(new HttpServerCodec());
		//添加对于读写大数据流的支持
		pipeline.addLast(new ChunkedWriteHandler());
		//对httpMessage进行聚合
		pipeline.addLast(new HttpObjectAggregator(1024*64));
		// ================= 上述是用于支持http协议的 ==============
		//websocket 服务器处理的协议,用于给指定的客户端进行连接访问的路由地址
		//比如处理一些握手动作(ping,pong)
		pipeline.addLast(new WebSocketServerProtocolHandler("/ws"));
		//自定义handler
		pipeline.addLast(new ChatHandler());
	}
}

自定义handler类: ChatHandler

/**
 * 上文中需要自定义处理的handler
 * TextWebSocketFrame  用于为websockt处理文本的对象
 */
public class ChatHandler extends SimpleChannelInboundHandler<TextWebSocketFrame>{
	//用于记录和管理所有客户端的channel
	private static ChannelGroup clients = 
			new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
	@Override
	protected void messageReceived(ChannelHandlerContext ctx, TextWebSocketFrame msg) 
			throws Exception {
		//客户端传递过来的消息
		String content = msg.text();
		System.out.println("接收到了客户端的消息是:" + content);
		//将客户端发送过来的消息刷到所有的channel中
		for(Channel channel : clients){
			channel.writeAndFlush(
					new TextWebSocketFrame("[服务器接收到了客户端的消息:]" + LocalDateTime.now()+",消息为:" + content));
		}	
	}
	//客户端创建的时候触发,当客户端连接上服务端之后,就可以获取该channel,然后放到channelGroup中进行统一管理	
	@Override
	public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
		clients.add(ctx.channel());
	}
	//客户端销毁的时候触发,
	@Override
	public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
		//当handlerRemoved 被触发时候,channelGroup会自动移除对应的channel
		//clients.remove(ctx.channel());
		System.out.println("客户端断开,当前被移除的channel的短ID是:" +ctx.channel().id().asShortText());
	}
}

配置springboot启动加载netty服务

/**
 * netty服务端启动加载配置
 */
@Component
public class NettybootServerInitConfig implements ApplicationListener<ContextRefreshedEvent>{
	@Override
	public void onApplicationEvent(ContextRefreshedEvent event) {
		if(event.getApplicationContext().getParent() == null){
			WsServer.getInstance().start();
		}
	}
}

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • 在vue-cli项目中如何使用swiper

    在vue-cli项目中如何使用swiper

    这篇文章主要介绍了在vue-cli项目中如何使用swiper问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-07-07
  • 在vue2.0中引用element-ui组件库的方法

    在vue2.0中引用element-ui组件库的方法

    这篇文章主要介绍了在vue2.0中引用element-ui组件库,需要的朋友可以参考下
    2018-06-06
  • 详解vue-cli 3.0 build包太大导致首屏过长的解决方案

    详解vue-cli 3.0 build包太大导致首屏过长的解决方案

    这篇文章主要介绍了详解vue-cli 3.0 build包太大导致首屏过长的解决方案,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-11-11
  • vue解决使用$http获取数据时报错的问题

    vue解决使用$http获取数据时报错的问题

    今天小编就为大家分享一篇vue解决使用$http获取数据时报错的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-10-10
  • Vue自定义组件使用事件修饰符的踩坑记录

    Vue自定义组件使用事件修饰符的踩坑记录

    vue提倡的是在方法中只有对数据的处理,所以提供了事件修饰符用于DOM的事件处理,下面这篇文章主要给大家介绍了关于Vue自定义组件使用事件修饰符的相关资料,需要的朋友可以参考下
    2021-05-05
  • Vue联动Echarts实现数据大屏展示

    Vue联动Echarts实现数据大屏展示

    这篇文章主要为大家介绍了Vue联动Echarts实现数据大屏的展示示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-04-04
  • vue table直接定位到指定元素的操作代码

    vue table直接定位到指定元素的操作代码

    最近遇到这样的需求点击某一个节点,弹窗,直接定位到点击的节点,高亮并显示数据,下面小编给大家带来了vue table直接定位到指定元素的操作代码,需要的朋友可以参考下
    2022-11-11
  • vue如何读取外部配置文件

    vue如何读取外部配置文件

    这篇文章主要介绍了vue如何读取外部配置文件问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-03-03
  • 在Vue当中同时配置多个路由文件的方法案例代码

    在Vue当中同时配置多个路由文件的方法案例代码

    这篇文章主要介绍了在Vue当中同时配置多个路由文件的方法,包含具体代码,本文分步骤结合示例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-12-12
  • Vue3 企业级组件库框架搭建 pnpm monorepo实战示例

    Vue3 企业级组件库框架搭建 pnpm monorepo实战示例

    这篇文章主要为大家介绍了Vue3 企业级组件库框架搭建 pnpm monorepo实战示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-11-11

最新评论