zeromq recv数据延迟太多了

时间:2016-02-17 09:07:26

标签: java multithreading networking zeromq

我写了一个路由器和经销商的例子。

这里是服务器代码,使用路由器 - 经销商接收数据,并向工作人员发送数据以实现负载,当工作人员收到消息时,它将一个Runnable对象放到ExecutorService来计算pi。:

public class MtServer {
private static Logger logger = LoggerFactory.getLogger(MtServer.class);
private static ExecutorService executors = Executors.newFixedThreadPool(2);

static class Worker extends Thread {
    private ZMQ.Socket worker;

    public Worker(ZMQ.Context context) {
        worker = context.socket(ZMQ.REP);
        worker.connect("inproc://workers");
    }

    public void run() {
        while(true) {
            byte[] recs = worker.recv();
            String message = new String(recs);
            String threadName = Thread.currentThread().getName();
            logger.info("thread[{}] receive [{}]", threadName, message);

            executors.submit(new Runnable() {
                public void run() {
                    double pi = 0;
                    for(int i = 0; i < 100000000; i++) {
                        pi += Math.pow(-1, i) / (2 * i + 1) * 4;
                    }
                    logger.info("pi = {}", pi);
                }
            });

            logger.info("server added [{}]", message);
            worker.send(message.getBytes(), 0);
            logger.info("server send [{}] back to client", message);
        }
    }
}

public static void main(String[] args) {
    ZMQ.Context context = ZMQ.context(1);
    ZMQ.Socket clients = context.socket(ZMQ.ROUTER);
    clients.bind("tcp://*:5556");

    ZMQ.Socket workers = context.socket(ZMQ.DEALER);
    workers.bind("inproc://workers");
    for(int i = 0; i < 2; ++i) {
        Worker worker = new Worker(context);
        worker.start();
    }

    ZMQ.proxy(clients, workers, null);

    clients.close();
    workers.close();
    context.term();
}

}

客户端代码,每100毫秒向服务器发送一条消息:

public class HwClient extends Thread {
private static Logger logger = LoggerFactory.getLogger(HwClient.class);

@Override
public void run() {
    String id = UUID.randomUUID().toString().replace("-", "");
    ZContext context = new ZContext();
    ZMQ.Socket requester = context.createSocket(ZMQ.REQ);
    requester.connect("tcp://127.0.0.1:5556");

    int seq = 0;
    while(!Thread.currentThread().isInterrupted()) {
        String message = id + "-" + seq;
        requester.send(message.getBytes(), 0);

        logger.info("client[{}] send [{}] to server", id, message);
        long t1 = System.currentTimeMillis();
        byte[] r = requester.recv();
        long t2 = System.currentTimeMillis();
        logger.info(id + " receive [{}] back from server spend {}ms", message, t2-t1);

        try {
            TimeUnit.MILLISECONDS.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        seq++;
    }

    context.close();
}

public static void main(String[] args) {
    HwClient client = new HwClient();
    client.start();
}

}

我的问题是有时客户端recv数据(t2-t1)的延迟太多,在我的例子中它几乎达到8s,并且延迟与计算pi的执行时间有关,如果我减少数量在worker中循环次数,延迟也会减少,但pi在其他线程中计算!

观察日志,大部分时间,当发生很多延迟时,延迟发生在MtServer中的worker.recv(客户端发送数据和工作人员接收数据之间的时间很长),但有时,它发生在提交运行时对象执行者(工作人员接收数据和工作人员发送数据之间的时间很长)。

一些日志:

[test] 2016-02-17 15:19:11:705 INFO [Thread-0] org.test.HwClient.run(26) | client[f11d3f6f6e9b4476a67053828c214c6e] send [f11d3f6f6e9b4476a67053828c214c6e-3] to server
[test] 2016-02-17 15:19:19:563 INFO [pool-2-thread-2] org.test.MtServer$Worker.run(30) | thread[pool-2-thread-2] receive [f11d3f6f6e9b4476a67053828c214c6e-3]
[test] 2016-02-17 15:19:19:563 INFO [pool-2-thread-2] org.test.MtServer$Worker.run(42) | server added [f11d3f6f6e9b4476a67053828c214c6e-3]
[test] 2016-02-17 15:19:19:563 INFO [pool-2-thread-2] org.test.MtServer$Worker.run(44) | server send [f11d3f6f6e9b4476a67053828c214c6e-3] back to client
[test] 2016-02-17 15:19:19:565 INFO [pool-1-thread-2] org.test.MtServer$Worker$1.run(38) | pi = 3.141592643589326
[test] 2016-02-17 15:19:19:565 INFO [pool-1-thread-1] org.test.MtServer$Worker$1.run(38) | pi = 3.141592643589326
[test] 2016-02-17 15:19:19:563 INFO [Thread-0] org.test.HwClient.run(30) | f11d3f6f6e9b4476a67053828c214c6e receive [f11d3f6f6e9b4476a67053828c214c6e-3] back from server spend 7858ms
[test] 2016-02-17 15:19:19:666 INFO [Thread-0] org.test.HwClient.run(26) | client[f11d3f6f6e9b4476a67053828c214c6e] send [f11d3f6f6e9b4476a67053828c214c6e-4] to server
[test] 2016-02-17 15:19:19:666 INFO [pool-2-thread-1] org.test.MtServer$Worker.run(30) | thread[pool-2-thread-1] receive [f11d3f6f6e9b4476a67053828c214c6e-4]

任何人都可以帮助我吗?感谢。

0 个答案:

没有答案