赞
踩
最近在做数字货币交易所相关的项目,考虑到性能的一些问题,中间也研究了多个Socket框架,包括T-io、Netty-Socket等,最终放弃SpringBoot默认集成的Socket采用更高效的Netty-Socket来实现。
Netty是一款基于NIO(Nonblocking I/O,非阻塞IO)开发的网络通信框架,对比于BIO(Blocking I/O,阻塞IO),他的并发性能得到了很大提高。
Netty的传输快其实也是依赖了NIO的一个特性——零拷贝。我们知道,Java的内存有堆内存、栈内存和字符串常量池等等,其中堆内存是占用内存空间最大的一块,也是Java对象存放的地方,一般我们的数据如果需要从IO读取到堆内存,中间需要经过Socket缓冲区,也就是说一个数据会被拷贝两次才能到达他的的终点,如果数据量大,就会造成不必要的资源浪费。
Netty针对这种情况,使用了NIO中的另一大特性——零拷贝,当他需要接收数据的时候,他会在堆内存之外开辟一块内存,数据就直接从IO读到了那块内存中去,在netty里面通过ByteBuf可以直接对这些数据进行直接操作,从而加快了传输速度。
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
这是个开源的框架。通过它,我们可以像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>
- <dependency>
- <groupId>org.yeauty</groupId>
- <artifactId>netty-websocket-spring-boot-starter</artifactId>
- <version>0.7.6</version>
- </dependency>
ServerEndpointExporter
对象,交给Spring IOC容器,表示要开启WebSocket功能,样例如下: - @Configuration
- public class WebSocketConfig {
- @Bean
- public ServerEndpointExporter serverEndpointExporter() {
- return new ServerEndpointExporter();
- }
- }
@ServerEndpoint
、@Component
注解,并在相应的方法上加上@OnOpen
、@OnClose
、@OnError
、@OnMessage
、@OnBinary
、OnEvent
注解,样例如下: - import io.netty.handler.codec.http.HttpHeaders;
- import io.netty.handler.timeout.IdleStateEvent;
- import org.springframework.stereotype.Component;
- import org.yeauty.annotation.*;
- import org.yeauty.pojo.ParameterMap;
- import org.yeauty.pojo.Session;
-
- import java.io.IOException;
-
- @ServerEndpoint(prefix = "netty-websocket")
- @Component
- public class MyWebSocket {
-
- @OnOpen
- public void onOpen(Session session, HttpHeaders headers, ParameterMap parameterMap) throws IOException {
- System.out.println("new connection");
-
- String paramValue = parameterMap.getParameter("paramKey");
- System.out.println(paramValue);
- }
-
- @OnClose
- public void onClose(Session session) throws IOException {
- System.out.println("one connection closed");
- }
-
- @OnError
- public void onError(Session session, Throwable throwable) {
- throwable.printStackTrace();
- }
-
- @OnMessage
- public void onMessage(Session session, String message) {
- System.out.println(message);
- session.sendText("Hello Netty!");
- }
-
- @OnBinary
- public void onBinary(Session session, byte[] bytes) {
- for (byte b : bytes) {
- System.out.println(b);
- }
- session.sendBinary(bytes);
- }
-
- @OnEvent
- public 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;
- }
- }
- }
-
- }
prefix
进行设置后,即可在application.properties
中配置: - netty-websocket:
- host: 0.0.0.0
- path: /
- port: 2222
ws://127.0.0.1:2222
@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 | 最大允许帧载荷长度 |
@ServerEndpoint
、@Component
注解即可ServerEndpointExporter.getInetSocketAddressSet()
获取所有端点的地址ServerBootstrap
实例ServerBootstrap
实例"0.0.0.0"
,因为"0.0.0.0"
意味着绑定所有的host
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。