情况:有基于 freebsd 7.2 的服务器,安装了 tomcat 7。Tomcat 7运行巨大的多线程服务器应用程序,该应用程序通过ServerSocket从一些不同的设备读取数据。因此,对于不同的设备,每个端口都有一些侦听器线程。当设备被授权时,侦听器会创建一个从授权设备收集数据的新线程(每个线程 1 个设备),顺便说一下,传入的数据并不那么大。还有客户端的 Web 套接字侦听器,它的工作方式相同 - 每个客户端 1 个线程。这一切都非常好,直到设备数量从 200 增加到 1500(客户端数量也增加了,接近 300)。理想情况下,进程必须与 3000 多个活动线程一起工作,但它会压缩。
以下是应用程序所基于的线程池的代码。
public class MultiThreadPool {
private static final int INITIAL_POOL_SIZE = 1250;
private final LinkedBlockingQueue<Runnable> queue = new LinkedBlockingQueue<Runnable>();
private final ThreadPoolExecutor exec = new ThreadPoolExecutor(INITIAL_POOL_SIZE, Integer.MAX_VALUE, 1, TimeUnit.MINUTES, queue, new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread th = new Thread(r);
//th.setDaemon(true);
th.setContextClassLoader(null);
th.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread t, Throwable e) {
//t.setDaemon(true);
//throw new UnsupportedOperationException("Not supported yet.");
}
});
return th;
}
});
private static class SingletonHolder {
private final static MultiThreadPool instance = new MultiThreadPool();
}
private static MultiThreadPool getInstance() {
return SingletonHolder.instance;
}
public MultiThreadPool() {
}
public static void initPool() {
getInstance();
}
public static void executeRunnable(Runnable r) {
try {
getInstance().exec.execute(r);
} catch (OutOfMemoryError e) {
System.out.println("** Out of memory: " + e.getMessage());
}
}
public static void stopPool() {
getInstance().exec.shutdownNow();
//getInstance().executor.shutdownNow();
}
}
所有线程都在通过ExecuteRunnable(Runnable r)过程运行。例如,将INITIAL_POOL_SIZE(ThreadPoolExecutor的核心大小)增加到1300会导致OutOfMemoryError:无法创建本机线程。同样,如果INITIAL_POOL_SIZE保持在1250,那么队列中的另一个线程在一些核心线程未完成之前根本不工作。这导致客户端在这两种情况下都无法正常工作。
我已经尝试使用-Xss,-server,-Xms,-Xmx,-Xss,perm size等来操作JVM。甚至使用loader.conf和login.conf增加了操作系统硬限制。但所有这些都没有多大帮助或使情况变得更糟。freebsd 中是否有另一个限制,可以通过部署具有其他配置的内核来增加?
无论如何,我需要增加服务器上活动线程的数量来处理全套设备和客户端。顺便说一句,设备至少每5秒发送一次数据。
请告诉我解决此问题的正确方法!
附言:这个应用程序是由另一个人创建的,所以我不能说太多,因为它真的很庞大。但如果您需要,我会尽力为您提供更多信息。
不管内存如何,操作系统似乎受限于它可以创建的线程数量。根据您使用的操作系统,查看限制,并查看是否可以增加数量。
例如,对于mac,您可以通过
sysctl kern.num_threads
kern.num_threads: 10240
对于linux
cat /proc/sys/kernel/threads-max
3500
等等。
您可以通过两种方式解决此问题。