基于tomcat8的WebSocket聊天Demo
參考:
http://svn.apache.org/viewvc/tomcat/trunk/webapps/examples/WEB-INF/classes/websocket/chat/ChatAnnotation.java?view=markup
需要 websocket-api
<dependency>
<groupId>javax.websocket</groupId>
<artifactId>javax.websocket-api</artifactId>
<version>1.0</version>
<scope>provided</scope>
</dependency>
ChatAnnotation.java
package jmind.ws.tomcat.java7;
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.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import jmind.core.util.HTMLUtil;
/**
* tomcat8 & java7
* @author wbxie
* 2013-11-9
*/
@ServerEndpoint(value = "/ws/chat")
public class ChatAnnotation {
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, HTMLUtil.cleanAll(message.toString()));
broadcast(filteredMessage);
}
private static void broadcast(String msg) {
for (ChatAnnotation client : connections) {
try {
client.session.getBasicRemote().sendText(msg);
} catch (IOException 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 xml
catalina.sh
JAVA_OPTS="-server -Xmx4000M -Xms4000M -Xmn1200M -XX:PermSize=256m -XX:MaxPermSize=256m -Xss512K -XX:+ExplicitGCInvokesConcurrent -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:+CMSParallelRemarkEnabled -XX:+UseCMSCompactAtFullCollection -XX:CMSFullGCsBeforeCompaction=0 -XX:+CMSClassUnloadingEnabled -XX:LargePageSizeInBytes=128M -XX:+UseFastAccessorMethods -XX:CMSInitiatingOccupancyFraction=80 -XX:SoftRefLRUPolicyMSPerMB=0" JAVA_OPTS="$JAVA_OPTS -Djava.nio.channels.spi.SelectorProvider=sun.nio.ch.EPollSelectorProvider"
server.xml 配置
配置线程池 <Executor name="tomcatThreadPool" namePrefix="catalina-exec-" maxThreads="500" minSpareThreads="10"/> 配置nio <Connector URIEncoding="UTF-8" executor="tomcatThreadPool" asyncTimeout="900000" maxConnections="40000" port="9079" protocol="org.apache.coyote.http11.Http11NioProtocol" connectionTimeout="40000" acceptCount="200" maxThreads="20000" redirectPort="8443" />
注 ,tomcat8 nio 最大连接数配置 使用 maxConnections 默认10000
参考:
http://tomcat.apache.org/tomcat-8.0-doc/config/http.html
編輯 tomcat/conf/Catalina/localhost/ROOT.xml
<?xml version="1.0" encoding="UTF-8"?> <Context path="" docBase="/Users/wbxie/work/workspace/chineseall/jmind-websocket/target/jmind-websocket-2.0.2-SNAPSHOT" reloadable="false" antiJARLocking="true" antiResourceLocking="false"></Context>
epoll 在linux 下启动:
JDK 6.0 以及JDK 5.0 update 9 的 nio支持epoll (仅限 Linux 系统 ),对并发idle connection会有大幅度的性能提升,这就是很多网络服务器应用程序需要的。
启用的方法如下:
-Djava.nio.channels.spi.SelectorProvider=sun.nio.ch.EPollSelectorProvider
例如在 Linux 下运行的 Tomcat 使用 NIO Connector ,那么启用 epoll 对性能的提升会有帮助。
而 Tomcat 要启用这个选项的做法是在 catalina.sh 的开头加入下面这一行
CATALINA_OPTS='-Djava.nio.channels.spi.SelectorProvider=sun.nio.ch.EPollSelectorProvider'
或者
JAVA_OPTS="$JAVA_OPTS -Djava.nio.channels.spi.SelectorProvider=sun.nio.ch.EPollSelectorProvider"