【问题标题】:Receiving data causes "too many files open"接收数据导致“打开的文件过多”
【发布时间】:2018-03-22 00:11:47
【问题描述】:

在我的客户端中,我通过 ZeroMQ 收到大量输入,这些输入需要不断更新。我的服务器是用 python 编写的,但这无关紧要。这就是我在MainActivity 中所做的:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        /********************************NETWORK********************************/
        new NetworkCall().execute("");
    }

    private class NetworkCall extends AsyncTask<String, Void, String> {

        @Override
        protected String doInBackground(String... params) {
            while (true) {
                try {
                    ZMQ.Context context = ZMQ.context(1);

                    // Connect to server
                    ZMQ.Socket requester = context.socket(ZMQ.REQ);
                    String address = "tcp://xxx.xx.xx.xx";
                    int port = 5000;
                    requester.connect(address + ":" + port);

                    // Initialize poll set
                    ZMQ.Poller poller = new ZMQ.Poller(1);
                    poller.register(requester, ZMQ.Poller.POLLIN);

                    requester.send("COORDINATES");

                    //while (true) {
                    String data;
                    poller.poll();

                    data = requester.recvStr();
                    System.out.println(data);

                    if (data == null) {
                        try {
                            sleep(100);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    } requester.close();
                } catch (IllegalStateException ise) {
                    ise.printStackTrace();
                }
            }
        }

        @Override
        protected void onPostExecute(String result) {
        }

        @Override
        protected void onPreExecute() {
        }

        @Override
        protected void onProgressUpdate(Void... values) {
        }
    }
}

在我的设备上执行此代码后,我会得到大约 5-9 个输入数据字符串,这些字符串是我从服务器接收的,但随后出现以下异常:

E/AndroidRuntime: FATAL EXCEPTION: AsyncTask #2
                  Process: com.example.viktoria.gazefocus, PID: 31339
                  java.lang.RuntimeException: An error occurred while executing doInBackground()
                      at android.os.AsyncTask$3.done(AsyncTask.java:353)
                      at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:383)
                      at java.util.concurrent.FutureTask.setException(FutureTask.java:252)
                      at java.util.concurrent.FutureTask.run(FutureTask.java:271)
                      at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:245)
                      at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
                      at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
                      at java.lang.Thread.run(Thread.java:764)
                   Caused by: com.example.viktoria.gazefocus.zmq.ZError$IOException: java.io.IOException: Too many open files
                      at com.example.viktoria.gazefocus.zmq.Signaler.makeFdPair(Signaler.java:94)
                      at com.example.viktoria.gazefocus.zmq.Signaler.<init>(Signaler.java:50)
                      at com.example.viktoria.gazefocus.zmq.Mailbox.<init>(Mailbox.java:51)
                      at com.example.viktoria.gazefocus.zmq.Ctx.<init>(Ctx.java:128)
                      at com.example.viktoria.gazefocus.zmq.ZMQ.zmq_ctx_new(ZMQ.java:244)
                      at com.example.viktoria.gazefocus.zmq.ZMQ.zmqInit(ZMQ.java:277)
                      at org.zeromq.ZMQ$Context.<init>(ZMQ.java:269)
                      at org.zeromq.ZMQ.context(ZMQ.java:254)
                      at com.example.viktoria.gazefocus.MainActivity$NetworkCall.doInBackground(MainActivity.java:73)
                      at com.example.viktoria.gazefocus.MainActivity$NetworkCall.doInBackground(MainActivity.java:67)
                      at android.os.AsyncTask$2.call(AsyncTask.java:333)
                      at java.util.concurrent.FutureTask.run(FutureTask.java:266)
                      at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:245) 
                      at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162) 
                      at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636) 
                      at java.lang.Thread.run(Thread.java:764) 
                   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:155)
                      at com.example.viktoria.gazefocus.zmq.Signaler.makeFdPair(Signaler.java:91)
                      at com.example.viktoria.gazefocus.zmq.Signaler.<init>(Signaler.java:50) 
                      at com.example.viktoria.gazefocus.zmq.Mailbox.<init>(Mailbox.java:51) 
                      at com.example.viktoria.gazefocus.zmq.Ctx.<init>(Ctx.java:128) 
                      at com.example.viktoria.gazefocus.zmq.ZMQ.zmq_ctx_new(ZMQ.java:244) 
                      at com.example.viktoria.gazefocus.zmq.ZMQ.zmqInit(ZMQ.java:277) 
                      at org.zeromq.ZMQ$Context.<init>(ZMQ.java:269) 
                      at org.zeromq.ZMQ.context(ZMQ.java:254) 
                      at com.example.viktoria.gazefocus.MainActivity$NetworkCall.doInBackground(MainActivity.java:73) 
                      at com.example.viktoria.gazefocus.MainActivity$NetworkCall.doInBackground(MainActivity.java:67) 
                      at android.os.AsyncTask$2.call(AsyncTask.java:333) 
                      at java.util.concurrent.FutureTask.run(FutureTask.java:266) 
                      at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:245) 
                      at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162) 
                      at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636) 
                      at java.lang.Thread.run(Thread.java:764) 

显然打开的文件太多。经过研究(我使用的是 Ubuntu 16.04)我将ulimit 更改为ulimit -n 10000。仍然会发生此异常。有时我得到更多的输入数据,有时更少。此外,如果我在 onCreate() 方法中设置类似 Executor executor = Executors.newFixedThreadPool(5); 的内容,则什么都不会改变。

如何解决这个问题?

感谢阅读!

【问题讨论】:

    标签: java android networking zeromq


    【解决方案1】:

    您有泄漏,因为您没有关闭/结束/释放某些东西。我认为必须终止上下文:关闭请求者后context.term()...

    【讨论】:

    • 总是那些显而易见的事情......干杯!
    • 否定,先生,调用 .term()* 方法毕竟不会保存游戏,因为无限 while( true ){...} 循环会生成新的 Context() - 对每个循环进行实例化,并且从不拆除前一次传递期间使用的任何资源,无论是在下一次往返期间还是在异常处理期间。这不会飞。
    • @ user3666197 - 相信我,当您在循环中的每次迭代中定义上下文时,它会飞起来。相同数量的上下文,一些数量终止,余额 0,没有泄漏,问题解决了。
    【解决方案2】:

    嗯,在 设计中,用于信令/消息传递设置成本的基础设施是不可忽略的。有些用例更宽容,有些则更少。

    每次方法调用总是获取一个新的 Context() 实例,并在通过对它的 .term()* 进行清理调用后立即将其丢弃 -方法肯定比挂起应用程序或冻结设备要好,但它远非公平设计,尊重进程延迟和资源“生态”。

    最好先设置一个半持久的资源基础设施(每个Context()-instance 通常是一个非常昂贵的实例化玩具(API 4.2+ 截至 2018 年第一季度),对于Socket()-instances 来说不是那么尖锐,但类似于 Poller() 和所有它的 internal-AccessPoint(s) 注册钩子,但原理也可以扩展到它们。

    早期重构代码将有助于避免将昂贵资源用作“一次性消耗品”的情况。

    部分:

          while (true) {
                 try {
                        ZMQ.Context context = ZMQ.context(1);
    
                        //                     Connect to server
                        ZMQ.Socket requester = context.socket( ZMQ.REQ );
                        String address = "tcp://xxx.xx.xx.xx";
                        int port = 5000;
                        requester.connect( address + ":" + port );
                        ...
                 }
                 ...
          }
    

    完全是一种资源破坏性反模式,具有重复的延迟,甚至存在远程挂断和远程拒绝等类似问题的风险。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-21
      • 1970-01-01
      • 1970-01-01
      • 2019-09-26
      • 1970-01-01
      相关资源
      最近更新 更多