背景
我们正在使用 Memcached 云在 Heroku 中使用 1 个 dyno 开发 Java 服务。
问题
同时我们正在开发和测试它,它工作正常。但是,当我们决定在真实环境中对其进行测试时,它开始返回以下错误:
java.lang.OutOfMemoryError: unable to create new native thread
java.lang.Thread.start0(Native Method)
java.lang.Thread.start(Thread.java:717)
net.spy.memcached.MemcachedConnection.<init>(MemcachedConnection.java:306) net.spy.memcached.DefaultConnectionFactory.createConnection(DefaultConnectionFactory.java:209)
net.spy.memcached.MemcachedClient.<init>(MemcachedClient.java:209)
Memcached.<init>(Memcached.java:34)
Main.lambda$main$1(Main.java:101)
spark.SparkBase$1.handle(SparkBase.java:311)
spark.webserver.MatcherFilter.doFilter(MatcherFilter.java:159)
spark.webserver.JettyHandler.doHandle(JettyHandler.java:60)
org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:179)
org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:136)
org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:97)
org.eclipse.jetty.server.Server.handle(Server.java:451)
org.eclipse.jetty.server.HttpChannel.run(HttpChannel.java:252)
org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:266)
org.eclipse.jetty.io.AbstractConnection$ReadCallback.run(AbstractConnection.java:240)
org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:596)
org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:527)
java.lang.Thread.run(Thread.java:748)
我们没有太多的客户来达到 256 个进程或线程(1 dyno 的限制)
解决方法
我们还不知道
代码
<!--Main-->
//...
try {
memcached = new Memcached ();
}
catch (Exception e) {
memcached = null;
}
//...
<!--Memcached-->
public class Memcached {
private MemcachedClient memcachedClient;
private boolean connected;
public Memcached () throws Exception {
setConnected(true);
try {
AuthDescriptor ad = new AuthDescriptor(new String[] { "PLAIN" },
new PlainCallbackHandler(System.getenv("MEMCACHEDCLOUD_USERNAME"),
System.getenv("MEMCACHEDCLOUD_PASSWORD")
)
);
setMemcachedClient(new MemcachedClient(
new ConnectionFactoryBuilder()
.setDaemon(true)
.setFailureMode(FailureMode.Retry)
.setProtocol(ConnectionFactoryBuilder.Protocol.BINARY) //this is the line 34
.setAuthDescriptor(ad).build(),
AddrUtil.getAddresses(System.getenv("MEMCACHEDCLOUD_SERVERS"))
));
} catch (Exception ex) {
// the Memcached client could not be initialized
setConnected(false);
throw new Exception ("{\"ErrorCode\":20,\"Portal\":\"Memcached\",\"ResponseCode\":\"\",\"Message\":\""
+ ex.getMessage() + "\"}");
}
}
public String get (String service, String fromCurrency, String toCurrency) {
if (!isConnected()) {
return null;
}
try {
return (String) getMemcachedClient().get(service + ";" + fromCurrency + ";" + toCurrency);
}
catch (Exception e) {
return null;
}
}
public boolean set (String service, String fromCurrency, String toCurrency, String value) {
if (!isConnected()) {
return false;
}
try {
double hour = Double.parseDouble(System.getenv("TIME_CACHE_HOUR"));
getMemcachedClient().set(service + ";" + fromCurrency + ";" + toCurrency, (int)(60 * 60 * hour), value);
return true;
}catch (Exception e) {
return false;
}
}
public boolean isConnected () {
return this.connected;
}
private void setConnected (boolean connected) {
this.connected = connected;
}
private MemcachedClient getMemcachedClient () {
return this.memcachedClient;
}
private void setMemcachedClient (MemcachedClient memcachedClient) {
this.memcachedClient = memcachedClient;
}
任何人都知道我们该如何解决这个错误?
编辑:我已阅读帖子Java: Unable to create new native thread,但这不是我们的问题。我们检查了他们在那里所说的属性,但我们有很好的价值。但是,我可以看到每次初始化 memcached 时,它都会创建一个新线程,但是当服务停止时该线程不会被删除。有问题。