Netty是一款基于NIO(Nonblocking I/O,非阻塞IO)开发的网络通信框架,对比于BIO(Blocking I/O,阻塞IO),他的并发性能得到了很大提高。

Netty为什么传输快

Netty的传输快其实也是依赖了NIO的一个特性——零拷贝。我们知道,Java的内存有堆内存、栈内存和字符串常量池等等,其中堆内存是占用内存空间最大的一块,也是Java对象存放的地方,一般我们的数据如果需要从IO读取到堆内存,中间需要经过Socket缓冲区,也就是说一个数据会被拷贝两次才能到达他的的终点,如果数据量大,就会造成不必要的资源浪费。

Netty针对这种情况,使用了NIO中的另一大特性——零拷贝,当他需要接收数据的时候,他会在堆内存之外开辟一块内存,数据就直接从IO读到了那块内存中去,在netty里面通过ByteBuf可以直接对这些数据进行直接操作,从而加快了传输速度。

Netty和Tomcat有什么区别?

Netty和Tomcat最大的区别就在于通信协议,Tomcat是基于Http协议的,他的实质是一个基于http协议的web容器,但是Netty不一样,他能通过编程自定义各种协议,因为netty能够通过codec自己来编码/解码字节流,完成类似redis访问的功能,这就是netty和tomcat最大的不同。

官方文档

感谢大家的热情反馈,首先这个框架跟原生的websocket配置上有点不一样的,更多详情可以多多看官方的文档,当时我也是觉得很快,但是发现参数设置/端口配置等,还有有点差异的。
https://github.com/YeautyYE/netty-websocket-spring-boot-starter/blob/master/README_zh.md

Netty-websocket-spring-boot-starter

这是个开源的框架。通过它,我们可以像spring-boot-starter-websocket一样使用注解进行开发,只需关注需要的事件(如OnMessage)。并且底层是使用Netty,netty-websocket-spring-boot-starter其他配置和spring-boot-starter-websocket完全一样,当需要调参的时候只需要修改配置参数即可,无需过多的关心handler的设置。

对应的Maven配置:

<!-- 注释掉默认的websocket starter<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId></dependency>-->
<!-- 启用Netty https://mvnrepository.com/artifact/org.yeauty/netty-websocket-spring-boot-starter -->
<dependency><groupId>org.yeauty</groupId><artifactId>netty-websocket-spring-boot-starter</artifactId><version>0.7.6</version>
</dependency>

Websocker注入Bean问题

关于这个问题,可以看最新发表的这篇文章,在参考和研究了网上一些攻略后,项目已经通过该方法注入成功,大家可以参考【关于controller调用controller/service调用service/util调用service/websocket中autowired的解决方法】https://blog.csdn.net/moshowgame/article/details/83415545

快速开始

  • 添加依赖:
 <dependency><groupId>org.yeauty</groupId><artifactId>netty-websocket-spring-boot-starter</artifactId><version>0.7.6</version></dependency>
  • new一个ServerEndpointExporter对象,交给Spring IOC容器,表示要开启WebSocket功能,样例如下:
@Configuration
public class WebSocketConfig {@Beanpublic ServerEndpointExporter serverEndpointExporter() {return new ServerEndpointExporter();}
}
  • 在端点类上加上@ServerEndpoint@Component注解,并在相应的方法上加上@OnOpen@OnClose@OnError@OnMessage@OnBinaryOnEvent注解,样例如下:
@ServerEndpoint
@Component
public class MyWebSocket {@OnOpenpublic void onOpen(Session session, HttpHeaders headers, ParameterMap parameterMap) throws IOException {System.out.println("new connection");String paramValue = parameterMap.getParameter("paramKey");System.out.println(paramValue);}@OnClosepublic void onClose(Session session) throws IOException {System.out.println("one connection closed"); }@OnErrorpublic void onError(Session session, Throwable throwable) {throwable.printStackTrace();}@OnMessagepublic void onMessage(Session session, String message) {System.out.println(message);session.sendText("Hello Netty!");}@OnBinarypublic void onBinary(Session session, byte[] bytes) {for (byte b : bytes) {System.out.println(b);}session.sendBinary(bytes); }@OnEventpublic void onEvent(Session session, Object evt) {if (evt instanceof IdleStateEvent) {IdleStateEvent idleStateEvent = (IdleStateEvent) evt;switch (idleStateEvent.state()) {case READER_IDLE:System.out.println("read idle");break;case WRITER_IDLE:System.out.println("write idle");break;case ALL_IDLE:System.out.println("all idle");break;default:break;}}}

}

  • 打开WebSocket客户端,连接到ws://127.0.0.1:80

注解

@ServerEndpoint

当ServerEndpointExporter类通过Spring配置进行声明并被使用,它将会去扫描带有@ServerEndpoint注解的类
被注解的类将被注册成为一个WebSocket端点
所有的配置项都在这个注解的属性中 ( 如:@ServerEndpoint("/ws") )

@OnOpen

当有新的WebSocket连接进入时,对该方法进行回调
注入参数的类型:Session、HttpHeaders、ParameterMap

@OnClose

当有WebSocket连接关闭时,对该方法进行回调
注入参数的类型:Session

@OnError

当有WebSocket抛出异常时,对该方法进行回调
注入参数的类型:Session、Throwable

@OnMessage

当接收到字符串消息时,对该方法进行回调
注入参数的类型:Session、String

@OnBinary

当接收到二进制消息时,对该方法进行回调
注入参数的类型:Session、byte[]

@OnEvent

当接收到Netty的事件时,对该方法进行回调
注入参数的类型:Session、Object

配置

所有的配置项都在这个注解的属性中

属性 默认值 说明
path “/” WebSocket的path,也可以用value来设置
host “0.0.0.0” WebSocket的host,"0.0.0.0"即是所有本地地址
port 80 WebSocket绑定端口号。如果为0,则使用随机端口(端口获取可见 多端点服务)
bossLoopGroupThreads 0 bossEventLoopGroup的线程数
workerLoopGroupThreads 0 workerEventLoopGroup的线程数
useCompressionHandler false 是否添加WebSocketServerCompressionHandler到pipeline
prefix “” 当不为空时,即是使用application.properties进行配置,详情在 通过application.properties进行配置
optionConnectTimeoutMillis 30000 与Netty的ChannelOption.CONNECT_TIMEOUT_MILLIS一致
optionSoBacklog 128 与Netty的ChannelOption.SO_BACKLOG一致
childOptionWriteSpinCount 16 与Netty的ChannelOption.WRITE_SPIN_COUNT一致
childOptionWriteBufferHighWaterMark 64*1024 与Netty的ChannelOption.WRITE_BUFFER_HIGH_WATER_MARK一致,但实际上是使用ChannelOption.WRITE_BUFFER_WATER_MARK
childOptionWriteBufferLowWaterMark 32*1024 与Netty的ChannelOption.WRITE_BUFFER_LOW_WATER_MARK一致,但实际上是使用 ChannelOption.WRITE_BUFFER_WATER_MARK
childOptionSoRcvbuf -1(即未设置) 与Netty的ChannelOption.SO_RCVBUF一致
childOptionSoSndbuf -1(即未设置) 与Netty的ChannelOption.SO_SNDBUF一致
childOptionTcpNodelay true 与Netty的ChannelOption.TCP_NODELAY一致
childOptionSoKeepalive false 与Netty的ChannelOption.SO_KEEPALIVE一致
childOptionSoLinger -1 与Netty的ChannelOption.SO_LINGER一致
childOptionAllowHalfClosure false 与Netty的ChannelOption.ALLOW_HALF_CLOSURE一致
readerIdleTimeSeconds 0 IdleStateHandler中的readerIdleTimeSeconds一致,并且当它不为0时,将在pipeline中添加IdleStateHandler
writerIdleTimeSeconds 0 IdleStateHandler中的writerIdleTimeSeconds一致,并且当它不为0时,将在pipeline中添加IdleStateHandler
allIdleTimeSeconds 0 IdleStateHandler中的allIdleTimeSeconds一致,并且当它不为0时,将在pipeline中添加IdleStateHandler
maxFramePayloadLength 65536 最大允许帧载荷长度

通过application.properties进行配置

对注解中的prefix进行设置后,即可在application.properties中进行配置。如下:

  • 首先在ServerEndpoint注解中设置prefix的值
@ServerEndpoint(prefix = "netty-websocket")
@Component
public class MyWebSocket {...
}
  • 接下来即可在application.properties中配置
netty-websocket.host=0.0.0.0
netty-websocket.path=/
netty-websocket.port=80

application.properties中的key与注解@ServerEndpoint中属性的对应关系如下:

注解中的属性 配置文件中的key 例子
path {prefix}.path netty-websocket.path
host {prefix}.host netty-websocket.host
port {prefix}.port netty-websocket.port
bossLoopGroupThreads {prefix}.boss-loop-group-threads netty-websocket.boss-loop-group-threads
workerLoopGroupThreads {prefix}.worker-loop-group-threads netty-websocket.worker-loop-group-threads
useCompressionHandler {prefix}.use-compression-handler netty-websocket.use-compression-handler
optionConnectTimeoutMillis {prefix}.option.connect-timeout-millis netty-websocket.option.connect-timeout-millis
optionSoBacklog {prefix}.option.so-backlog netty-websocket.option.so-backlog
childOptionWriteSpinCount {prefix}.child-option.write-spin-count netty-websocket.child-option.write-spin-count
childOptionWriteBufferHighWaterMark {prefix}.child-option.write-buffer-high-water-mark netty-websocket.child-option.write-buffer-high-water-mark
childOptionWriteBufferLowWaterMark {prefix}.child-option.write-buffer-low-water-mark netty-websocket.child-option.write-buffer-low-water-mark
childOptionSoRcvbuf {prefix}.child-option.so-rcvbuf netty-websocket.child-option.so-rcvbuf
childOptionSoSndbuf {prefix}.child-option.so-sndbuf netty-websocket.child-option.so-sndbuf
childOptionTcpNodelay {prefix}.child-option.tcp-nodelay netty-websocket.child-option.tcp-nodelay
childOptionSoKeepalive {prefix}.child-option.so-keepalive netty-websocket.child-option.so-keepalive
childOptionSoLinger {prefix}.child-option.so-linger netty-websocket.child-option.so-linger
childOptionAllowHalfClosure {prefix}.child-option.allow-half-closure netty-websocket.child-option.allow-half-closure
readerIdleTimeSeconds {prefix}.reader-idle-time-seconds netty-websocket.reader-idle-time-seconds
writerIdleTimeSeconds {prefix}.writer-idle-time-seconds netty-websocket.writer-idle-time-seconds
allIdleTimeSeconds {prefix}.all-idle-time-seconds netty-websocket.all-idle-time-seconds
maxFramePayloadLength {prefix}.maxFramePayloadLength netty-websocket.maxFramePayloadLength

自定义Favicon

配置favicon的方式与spring-boot中完全一致。只需将favicon.ico文件放到classpath的根目录下即可。如下:

src/+- main/+- java/|   + <source code>+- resources/+- favicon.ico

自定义错误页面

配置自定义错误页面的方式与spring-boot中完全一致。你可以添加一个 /public/error 目录,错误页面将会是该目录下的静态页面,错误页面的文件名必须是准确的错误状态或者是一串掩码,如下:

src/+- main/+- java/|   + <source code>+- resources/+- public/+- error/|   +- 404.html|   +- 5xx.html+- <other public assets>

多端点服务

  • 在快速启动的基础上,在多个需要成为端点的类上使用@ServerEndpoint@Component注解即可
  • 可通过ServerEndpointExporter.getInetSocketAddressSet()获取所有端点的地址
  • 当地址不同时(即host不同或port不同),使用不同的ServerBootstrap实例
  • 当地址相同,路径(path)不同时,使用同一个ServerBootstrap实例
  • 当多个端点服务的port为0时,将使用同一个随机的端口号
  • 当多个端点的port和path相同时,host不能设为"0.0.0.0",因为"0.0.0.0"意味着绑定所有的host

Springboot2 搭建 高性能Websocket服务器相关推荐

  1. 分享关于搭建高性能WEB服务器的一篇文章

    这篇文章主要介绍了Centos5.4+Nginx-0.8.50+UWSGI-0.9.6.2+Django-1.2.3搭建高性能WEB服务器的相关资料,需要的朋友可以参考下(http://m.0813s ...

  2. Nginx + PHP 搭建高性能web服务器

    写在前面: 1. Issue: *** 'libmcrypt-config --version' returned 2.4.0, but LIBMCRYPT (2.5.8) *** was found ...

  3. Nginx 0.8.x + PHP 5.2.13(FastCGI)搭建高性能Web服务器

    Nginx ("engine x") 是一个高性能的 HTTP 和反向代理服务器,也是一个 IMAP/POP3/SMTP 代理服务器. Nginx 是由 Igor Sysoev 为 ...

  4. 搭建高性能日志服务器,syslog日志服务器搭建

    syslog日志服务器搭建 内容精选 换一换 提供多个业务节点提供共享的日志输出目录,方便分布式应用的日志收集和管理.业务特点:多个业务主机挂载同一个共享文件系统,并发打印日志.大文件小I/O:单个日 ...

  5. Nginx 0.7.x + PHP 5.2.6(FastCGI)搭建高性能web服务器

    #更新组件 sudo -s LANG=C yum -y install gcc gcc-c++ autoconf libjpeg libjpeg-devel libpng libpng-devel f ...

  6. websocket系列:基于netty-websocket-spring-boot-starter轻松实现高性能websocket

    前言 本着死磕websocket的精神继续鼓捣websocket的实现方式.本文通过介绍如何基于netty-websocket-spring-boot-starter轻松实现高性能websocket. ...

  7. SpringBoot2.0集成WebSocket,实现后台向前端推送信息

    SpringBoot+WebSocket集成 什么是WebSocket? 为什么需要 WebSocket? 前言 maven依赖 WebSocketConfig WebSocketServer 消息推 ...

  8. springboot2.3手册:5分钟用Netty搭建高性能异步WebSocket服务

    溪云阁:专注编程教学,架构,JAVA,Python,微服务,机器学习等领域,欢迎关注,一起学习. 断更快两个月了,6月份工作忙到飞起,7月份家里又有事,已经累到躺下就想睡觉的程度了. 现在我们做Web ...

  9. 在IIS上搭建WebSocket服务器(三)

    在IIS上搭建WebSocket服务器(三) 原文:在IIS上搭建WebSocket服务器(三) 编写客户端代码 1.新建一个*.html文件. ws = new WebSocket('ws://19 ...

最新文章

  1. Advanced Memory Allocation 内存分配进阶
  2. golang 定义一个空切片_Golang简单入门教程——函数进阶使用
  3. 群晖挂pt 路由器虚拟服务器设置,群晖挂pt 路由器虚拟服务器设置
  4. db2存储过程 可以使用游标循环嵌套吗_DB2存储过程使用动态游标的例子
  5. 学java的困惑_学习Java - 关于一些代码困惑
  6. Spring Cloud学习(一)
  7. 了解Binder机制原理和底层实现
  8. opencv打开双目
  9. Java 查询Word是否存在关键字,并保留word路径到txt
  10. 微信小程序订阅消息,并跳转指定页面
  11. 基于QT的IM(jabber)库和客户端
  12. 用云真机测试本地应用程序
  13. Java SE 007 流程控制语句 续
  14. cf计算机丢失msvcp100,Win7丢失MSVCP100.dll导致程序无法启动怎们办
  15. android怎么监听多点触摸_Android笔记:触摸事件的分析与总结----多点触控
  16. Python基础之Flask快速入门
  17. 安卓学习笔记---支付宝支付-交易订单处理失败,请稍后再试。(提示ALI59错误)
  18. 头条三年去阿里一面,没过
  19. php微信文本通讯_微信公众号开发之文本消息自动回复php代码
  20. day43--插入排序

热门文章

  1. 为什么要返回function_宇宙飞船返回时,为什么要冒着烧毁的风险加速穿过大气层?...
  2. java动态数组的实现的_基于Java的动态数组分析与实现
  3. Day25 与类相关的魔术方法
  4. windows ffmpeg 推送摄像头数据到rtmp服务
  5. WebDev.WebServer40.exe已停止工作
  6. 程序员面试HR你该看重什么?!
  7. 25+ 个 jQuery 网页拖放操作的插件
  8. 10万美元奖金!CVPR 2021 重磅赛事,安全AI挑战者计划
  9. ECCV 2020 论文大盘点-自动驾驶篇
  10. CVPR 2020 | 基于知识蒸馏的分块监督NAS