Tomcat下WebSocket最大连接数测试调优
默认情况下,Tomcat的WebSocket最大连接数为200。
WebSocket后台代码
package com.chat.demo;
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.io.IOException;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.atomic.AtomicInteger;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
//import org.apache.juli.logging.Log;
//import org.apache.juli.logging.LogFactory;
//import util.HTMLFilter;
@ServerEndpoint(value = "/websocket/chat")
public class ChatAnnotation {
//private static final Log log = LogFactory.getLog(ChatAnnotation.class);
private static final String GUEST_PREFIX = "Guest";
private static final AtomicInteger connectionIds = new AtomicInteger(0);
private static final Set<ChatAnnotation> connections =
new CopyOnWriteArraySet<ChatAnnotation>();
private final String nickname;
private Session session;
public ChatAnnotation() {
nickname = GUEST_PREFIX + connectionIds.getAndIncrement();
}
@OnOpen
public void start(Session session) {
this.session = session;
connections.add(this);
String message = String.format("* %s %s", nickname, "has joined.");
broadcast(message);
}
@OnClose
public void end() {
connections.remove(this);
String message = String.format("* %s %s",
nickname, "has disconnected.");
broadcast(message);
}
@OnMessage
public void incoming(String message) {
// Never trust the client
String filteredMessage = String.format("%s: %s",
nickname, message.toString());
broadcast(filteredMessage);
}
@OnError
public void onError(Throwable t) throws Throwable {
System.out.println("Chat Error: " + t.toString());
}
private static void broadcast(String msg) {
for (ChatAnnotation client : connections) {
try {
synchronized (client) {
client.session.getBasicRemote().sendText(msg);
}
} catch (IOException e) {
//log.debug("Chat Error: Failed to send message to client", e);
connections.remove(client);
try {
client.session.close();
} catch (IOException e1) {
// Ignore
}
String message = String.format("* %s %s",
client.nickname, "has been disconnected.");
broadcast(message);
}
}
}
}
启动Tomcat,注意ws的地址,然后运行测试WebSocket连接数代码
package com.jiafuwei.java.snake;
import java.net.URI;
import javax.websocket.ClientEndpoint;
import javax.websocket.ContainerProvider;
import javax.websocket.Session;
import javax.websocket.WebSocketContainer;
@ClientEndpoint
public class WebSocketTest {
private String deviceId;
private Session session;
public WebSocketTest () {
}
public WebSocketTest (String deviceId) {
this.deviceId = deviceId;
}
protected boolean start() {
WebSocketContainer Container = ContainerProvider.getWebSocketContainer();
String uri = "ws://localhost:8028/lhychat/websocket/chat";
System.out.println("Connecting to " + uri);
try {
session = Container.connectToServer(WebSocketTest.class, URI.create(uri));
System.out.println("count: " + deviceId);
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
public static void main(String[] args) {
for (int i = 1; i< 1000; i++) {
WebSocketTest wSocketTest = new WebSocketTest(String.valueOf(i));
if (!wSocketTest.start()) {
System.out.println("测试结束!");
break;
}
}
}
}
运行结果为每次循环到第200个的时候,测试结束了,WebSocket后台代码开始报错。
如何增加并发数呢,只需在server.xml文件中,增加 maxThreads=”300″ 这样最大的并发数就变成了300。
<Connector maxConnections="300" maxThreads="300" URIEncoding="UTF-8" connectionTimeout="20000" port="8028" protocol="HTTP/1.1" redirectPort="8443" useBodyEncodingForURI="true"/>
但是需要强调的是:完全依赖于片面的调大maxThreads是不行的,应用服务器优化是一个系统性的问题。
你得根据实际情况适当调整,包括最大线程数、队列大小、超时、内存参数等。
你首先得弄清楚目前的业务瓶颈在哪里,如果是业务处理花时间多,你maxThreads设置的再大,过多请求进来排队也得超时。
如果一个tomcat节点已经很吃力,也没有其他明显的性能瓶颈,那你就该考虑用tomcat集群了。
所以到这里你就明白了,自己开发和维护websocket服务,在高并发高连接数需求下,是一件吃力不讨好的事情。如果这个时候有一套即开即用的高性能websocket第三方服务,那该是多美好的一件事件啊。
这样美好的事情还真有!
目前GoEasy提供完整的websocket前后端解决方案,简单的几行代码集成,即可快速搭建您的专属websocket服务。 同时支持各种前端技术框架如小程序、uniapp、vue,支持各种服务端语言如php、java、python等。对websocket有需求的开发者可以来注册试用一下【立即注册】