tomcat8+java7 的WebSocket聊天Demo
基于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"