mirror of
https://github.com/zongzibinbin/MallChat.git
synced 2026-03-13 21:53:41 +08:00
feat:websocket压测测试类
This commit is contained in:
@@ -0,0 +1,20 @@
|
||||
package com.abin.mallchat.common.websocket;
|
||||
|
||||
import io.netty.channel.EventLoopGroup;
|
||||
import io.netty.channel.nio.NioEventLoopGroup;
|
||||
|
||||
public class Simulator {
|
||||
public static void start() {
|
||||
String serverIp = "101.33.251.36";
|
||||
int serverPort = 8090;
|
||||
EventLoopGroup group = new NioEventLoopGroup();
|
||||
for (int i = 0; i < 10000; i++) {
|
||||
WebSocketConnector client = new WebSocketConnector(serverIp, serverPort, group);
|
||||
client.doConnect();
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
start();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
package com.abin.mallchat.common.websocket;
|
||||
|
||||
import io.netty.bootstrap.Bootstrap;
|
||||
import io.netty.channel.*;
|
||||
import io.netty.channel.socket.SocketChannel;
|
||||
import io.netty.channel.socket.nio.NioSocketChannel;
|
||||
import io.netty.handler.codec.http.DefaultHttpHeaders;
|
||||
import io.netty.handler.codec.http.HttpClientCodec;
|
||||
import io.netty.handler.codec.http.HttpObjectAggregator;
|
||||
import io.netty.handler.codec.http.websocketx.WebSocketClientHandshakerFactory;
|
||||
import io.netty.handler.codec.http.websocketx.WebSocketVersion;
|
||||
import io.netty.handler.stream.ChunkedWriteHandler;
|
||||
import io.netty.handler.timeout.IdleStateHandler;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
/**
|
||||
* WebSocket协议类型的模拟客户端连接器类
|
||||
*
|
||||
* @author duyanjun
|
||||
* @since 2022/10/13 杜燕军 新建
|
||||
*/
|
||||
@Slf4j
|
||||
public class WebSocketConnector {
|
||||
// 服务器ip
|
||||
protected String serverIp;
|
||||
// 服务器通信端口
|
||||
protected int serverSocketPort;
|
||||
// 事件循环线程池
|
||||
protected EventLoopGroup group;
|
||||
// 网络通道
|
||||
private Channel channel;
|
||||
|
||||
/**
|
||||
* WebSocket协议类型的模拟客户端连接器构造方法
|
||||
*
|
||||
* @param serverIp
|
||||
* @param serverSocketPort
|
||||
* @param group
|
||||
*/
|
||||
public WebSocketConnector(String serverIp, int serverSocketPort, EventLoopGroup group) {
|
||||
this.serverIp = serverIp;
|
||||
this.serverSocketPort = serverSocketPort;
|
||||
this.group = group;
|
||||
}
|
||||
|
||||
public void doConnect() {
|
||||
try {
|
||||
String URL = "ws://" + this.serverIp + ":" + this.serverSocketPort + "/";
|
||||
URI uri = new URI(URL);
|
||||
final WebSocketIoHandler handler =
|
||||
new WebSocketIoHandler(
|
||||
WebSocketClientHandshakerFactory.newHandshaker(
|
||||
uri, WebSocketVersion.V13, null, true, new DefaultHttpHeaders()));
|
||||
Bootstrap bootstrap = new Bootstrap();
|
||||
bootstrap.group(group).channel(NioSocketChannel.class)
|
||||
//.option(ChannelOption.TCP_NODELAY, true)
|
||||
.option(ChannelOption.SO_KEEPALIVE, true)
|
||||
.handler(new ChannelInitializer<SocketChannel>() {
|
||||
@Override
|
||||
protected void initChannel(SocketChannel ch) throws Exception {
|
||||
ChannelPipeline pipeline = ch.pipeline();
|
||||
//空闲事件
|
||||
pipeline.addLast(new IdleStateHandler(0, 10, 0));
|
||||
// 添加一个http的编解码器
|
||||
pipeline.addLast(new HttpClientCodec());
|
||||
// 添加一个用于支持大数据流的支持
|
||||
pipeline.addLast(new ChunkedWriteHandler());
|
||||
// 添加一个聚合器,这个聚合器主要是将HttpMessage聚合成FullHttpRequest/Response
|
||||
pipeline.addLast(new HttpObjectAggregator(1024 * 64));
|
||||
pipeline.addLast(handler);
|
||||
}
|
||||
});
|
||||
try {
|
||||
synchronized (bootstrap) {
|
||||
final ChannelFuture future = bootstrap.connect(this.serverIp, this.serverSocketPort).sync();
|
||||
this.channel = future.channel();
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
log.error("连接服务失败.......................uri:" + uri.toString(), e);
|
||||
} catch (Exception e) {
|
||||
log.error("连接服务失败.......................uri:" + uri.toString(), e);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("连接服务失败.......................", e);
|
||||
} finally {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void disConnect() {
|
||||
this.channel.close();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
package com.abin.mallchat.common.websocket;
|
||||
|
||||
import io.netty.channel.*;
|
||||
import io.netty.handler.codec.http.FullHttpResponse;
|
||||
import io.netty.handler.codec.http.websocketx.*;
|
||||
import io.netty.handler.timeout.IdleState;
|
||||
import io.netty.handler.timeout.IdleStateEvent;
|
||||
import io.netty.util.CharsetUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* WebSocket协议类型的模拟客户端IO处理器类
|
||||
*
|
||||
* @author duyanjun
|
||||
* @since 2022/10/13 杜燕军 新建
|
||||
*/
|
||||
@Slf4j
|
||||
public class WebSocketIoHandler extends SimpleChannelInboundHandler<Object> {
|
||||
|
||||
private final WebSocketClientHandshaker handShaker;
|
||||
|
||||
private ChannelPromise handshakeFuture;
|
||||
|
||||
public WebSocketIoHandler(WebSocketClientHandshaker handShaker) {
|
||||
this.handShaker = handShaker;
|
||||
}
|
||||
|
||||
public ChannelFuture handshakeFuture() {
|
||||
return handshakeFuture;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handlerAdded(ChannelHandlerContext ctx) {
|
||||
handshakeFuture = ctx.newPromise();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelActive(ChannelHandlerContext ctx) {
|
||||
handShaker.handshake(ctx.channel());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelInactive(ChannelHandlerContext ctx) {
|
||||
ctx.close();
|
||||
try {
|
||||
super.channelInactive(ctx);
|
||||
} catch (Exception e) {
|
||||
log.error("channelInactive 异常.", e);
|
||||
}
|
||||
log.warn("WebSocket链路与服务器连接已断开.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
|
||||
Channel ch = ctx.channel();
|
||||
if (!handShaker.isHandshakeComplete()) {
|
||||
try {
|
||||
handShaker.finishHandshake(ch, (FullHttpResponse) msg);
|
||||
handshakeFuture.setSuccess();
|
||||
log.info("WebSocket握手成功,可以传输数据了.");
|
||||
} catch (WebSocketHandshakeException e) {
|
||||
log.warn("WebSocket Client failed to connect");
|
||||
handshakeFuture.setFailure(e);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (msg instanceof FullHttpResponse) {
|
||||
FullHttpResponse response = (FullHttpResponse) msg;
|
||||
throw new IllegalStateException(
|
||||
"Unexpected FullHttpResponse (getStatus=" + response.status() +
|
||||
", content=" + response.content().toString(CharsetUtil.UTF_8) + ')');
|
||||
}
|
||||
|
||||
WebSocketFrame frame = (WebSocketFrame) msg;
|
||||
if (frame instanceof TextWebSocketFrame) {
|
||||
TextWebSocketFrame textFrame = (TextWebSocketFrame) frame;
|
||||
String s = textFrame.text();
|
||||
log.info("WebSocket Client received message: " + s);
|
||||
} else if (frame instanceof PongWebSocketFrame) {
|
||||
log.info("WebSocket Client received pong");
|
||||
} else if (frame instanceof CloseWebSocketFrame) {
|
||||
log.info("WebSocket Client received closing");
|
||||
ch.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
|
||||
log.error("WebSocket链路由于发生异常,与服务器连接已断开.", cause);
|
||||
if (!handshakeFuture.isDone()) {
|
||||
handshakeFuture.setFailure(cause);
|
||||
}
|
||||
ctx.close();
|
||||
super.exceptionCaught(ctx, cause);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
|
||||
if (evt instanceof IdleStateEvent) {
|
||||
IdleStateEvent event = (IdleStateEvent) evt;
|
||||
// 如果写通道处于空闲状态,就发送心跳命令
|
||||
if (IdleState.WRITER_IDLE.equals(event.state())) {
|
||||
// 发送心跳数据
|
||||
ctx.writeAndFlush(new TextWebSocketFrame("{\"type\":2}"));
|
||||
System.out.println("发送心跳数据");
|
||||
}
|
||||
} else {
|
||||
super.userEventTriggered(ctx, evt);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user