【问题标题】:Jeromq maximum socket opened issueJeromq 最大套接字打开问题
【发布时间】:2014-10-12 08:40:34
【问题描述】:

我在java中有一个server,它接收一个json文件并通过jeromq将它发送到一个C程序。直到上周我才用几个 json 测试它。到目前为止,我还没有发送很多 json,我有另一个组件要发送它们。

Glassfish 因我从未见过的错误而挂起。比如:

[2014-08-19T09:24:32.446+0000] [glassfish 4.0] [WARNING] [] [java.util.prefs] [tid: _ThreadID=141 _ThreadName=Timer-1] [timeMillis: 1408440272446] [levelValue: 900] [[
Could not lock User prefs.  Unix error code 24.]]

[2014-08-19T09:24:32.446+0000] [glassfish 4.0] [WARNING] [] [java.util.prefs] [tid: _ThreadID=141 _ThreadName=Timer-1] [timeMillis: 1408440272446] [levelValue: 900] [[
  Couldn't flush user prefs: java.util.prefs.BackingStoreException: Couldn't get file lock.]]

还有一些与 ZMQ 相关的东西:

[2014-08-15T08:23:30.637+0000] [glassfish 4.0] [SEVERE] [] [] [tid: _ThreadID=2432     _ThreadName=Thread-4] [timeMillis: 140809101063$
  zmq.ZError$IOException: java.io.IOException: Too many open files
    at zmq.Signaler.make_fdpair(Signaler.java:87)
    at zmq.Signaler.<init>(Signaler.java:48)
    at zmq.Mailbox.<init>(Mailbox.java:55)
    at zmq.Ctx.<init>(Ctx.java:127)
    at zmq.ZMQ.zmq_ctx_new(ZMQ.java:225)
    at zmq.ZMQ.zmq_init(ZMQ.java:258)
    at org.jeromq.ZMQ$Context.<init>(ZMQ.java:173)
    at org.jeromq.ZMQ.context(ZMQ.java:155)

    ...

    at java.lang.Thread.run(Thread.java:744)
Caused by: java.io.IOException: Too many open files
    at sun.nio.ch.IOUtil.makePipe(Native Method)
    at sun.nio.ch.PipeImpl.<init>(PipeImpl.java:42)
    at sun.nio.ch.SelectorProviderImpl.openPipe(SelectorProviderImpl.java:50)
    at java.nio.channels.Pipe.open(Pipe.java:150)
    at zmq.Signaler.make_fdpair(Signaler.java:85)
    ... 11 more]] 

我认为这可能与 zmq 的磨损有关。如果服务器只收到一些 json 它永远不会挂起。

我粘贴了我的 java 代码,也许我做错了什么或者我没有关闭一些东西:

首先我创建一个线程来发送 zmq:

new Thread(new SubmitJSONOnBackground(json, this.context)).start();

我的课在后台运行:

public class SubmitJSONOnBackground implements Runnable {
private Collection<JSON> jsons;
private ServletContext context;
public SubmitObservationOnBackground(Collection<JSON> json, ServletContext context) {
    this.jsons = json;
    this.context = context;
}
public void run() {
    SubmitJSONHandler submit = new SubmitJSONHandler(jsons, this.context);
    submit.buildAndSubmitJSON();
}

}

以及发送zmq的方法:

private boolean submitJSON(String message) {
    ZMQ.Context context = ZMQ.context(1);
    ZMQ.Socket sender = context.socket(ZMQ.PUSH);
    sender.connect("tcp://127.0.0.1:9999");
    sender.send(device, ZMQ.SNDMORE);
    sender.send("json", ZMQ.SNDMORE);
    sender.send("["+message+"]", 0);
    sender.close();
    context.term(); 
    return true;
}

我认为没问题,但由于它与 ZMQ 相关的东西失败了,我不确定它是否正常。

【问题讨论】:

  • 您是否正在处理submitJSON 方法引发的任何异常?可能发送方套接字未正确关闭,文件句柄已用尽。使用 try .. finally 阻塞并在关闭套接字之前设置一个 linger。
  • 对不起,什么是逗留?所以你的意思是在 submitJSON 调用之前,设置一个尝试,然后,一个 finally 没有捕获。我在返回之前关闭了套接字,所以我应该在那里设置“逗留”。可以举个例子吗?
  • 尝试不捕获是合法的。关于 linger,从参考手册的字面意思来看: linger period 确定在使用 zmq_close(3) 关闭套接字后,尚未发送到对等方的挂起消息在内存中停留的时间,并进一步影响终止带有 zmq_term(3) 的套接字上下文。检查 [api.zeromq.org/4-0:zmq-setsockopt]
  • @jschiavon 干预 linger 并不能解决 FD 耗尽问题。 OP 请忽略此建议。

标签: java sockets zeromq jeromq


【解决方案1】:

创建和销毁 Context 和 Socket 并不习惯,尤其是在紧密循环中。您应该只创建一个上下文并将其注入您的应用程序。如果你也缓存套接字,你会好得多。

【讨论】:

  • 在这种情况下,我应该创建一个带有单例的类来拥有一个唯一的实例,然后调用 send2ZMQ...
  • 我正在创建单例模式。我在构造函数中设置了 ZMQ.context、context.socket 和 sender.connect,但我不知道如何处理 close 和 term 调用。我知道我不应该随时打电话给他们,因为我永远不会关闭套接字,但我不确定。
  • 这就是为什么我更喜欢管理我的对象的生命周期。我会在我的应用程序范围之外创建上下文,然后将其传入。然后我会创建某种退出处理程序,在应用程序终止时关闭它的资源。一旦超出范围,我将终止上下文。类似于:gist.github.com/trevorbernard/d538ca2df3a847b869f9
  • 我的应用程序的问题是它是一个服务器,所以通常它不应该永远完成。无论如何,我已经解决了我认为的问题。我更新了 jeromq 版本,现在它不会崩溃。我还创建了一个单例,但打开了 1 次上下文并且从不关闭它(我想我应该在某处添加它)。我会奖励您的回答,因为单身人士将来会帮助我。感谢您抽出时间特雷弗。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-23
  • 2013-10-25
  • 2017-03-06
  • 1970-01-01
  • 1970-01-01
  • 2013-09-11
相关资源
最近更新 更多