public ZMsg recv() { ZMsg reply = null; Poller items = new Poller(1); items.register(client, Poller.POLLIN); if (items.poll(timeout * 1000) == -1) { return null; } if (items.pollin(0)) { ZMsg msg = ZMsg.recvMsg(client, 0); // 非阻塞 if (verbose) { log.format("I:receive reply"); msg.dump(log.out()); } assert (msg.size() >= 4); ZFrame empty = msg.pop(); assert (empty.getData().length == 0); empty.destroy(); ZFrame header = msg.pop(); assert (MDP.C_CLIENT.equals(header.toString())); header.destroy(); ZFrame replyService = msg.pop(); replyService.destroy(); reply = msg; } return reply; }
/** * 发送的消息格式: [000] [006] MDPC01 [004] echo [011] Hello world * * @param service * @param request */ public void send(String service, ZMsg request) { assert (request == null); request.addFirst(service); // 在reqeust前面添加帧 request.addFirst(MDP.C_CLIENT.newFrame()); request.addFirst(""); if (verbose) { log.format("I:send request to '%s' service.\n", service); request.dump(log.out()); } request.send(client); }
// The main task is an LRU queue with heartbeating on workers so we can // detect crashed or blocked worker tasks: public static void main(final String[] args) { final ZContext ctx = new ZContext(); final Socket frontend = ctx.createSocket(ZMQ.ROUTER); final Socket backend = ctx.createSocket(ZMQ.ROUTER); frontend.bind("tcp://*:5555"); // For clients backend.bind("tcp://*:5556"); // For workers // List of available workers final ArrayList<Worker> workers = new ArrayList<Worker>(); // Send out heartbeats at regular intervals long heartbeat_at = System.currentTimeMillis() + HEARTBEAT_INTERVAL; while (true) { final PollItem items[] = { new PollItem(backend, ZMQ.Poller.POLLIN), new PollItem(frontend, ZMQ.Poller.POLLIN) }; // Poll frontend only if we have available workers final int rc = ZMQ.poll(items, workers.size() > 0 ? 2 : 1, HEARTBEAT_INTERVAL); if (rc == -1) { break; // Interrupted } // Handle worker activity on backend if (items[0].isReadable()) { // Use worker address for LRU routing final ZMsg msg = ZMsg.recvMsg(backend); if (msg == null) { break; // Interrupted } // Any sign of life from worker means it's ready final ZFrame address = msg.unwrap(); final Worker worker = new Worker(address); worker.ready(workers); // Validate control message, or return reply to client if (msg.size() == 1) { final ZFrame frame = msg.getFirst(); final String data = new String(frame.getData()); if (!data.equals(PPP_READY) && !data.equals(PPP_HEARTBEAT)) { System.out.println("E: invalid message from worker"); msg.dump(System.out); } msg.destroy(); } else { msg.send(frontend); } } if (items[1].isReadable()) { // Now get next client request, route to next worker final ZMsg msg = ZMsg.recvMsg(frontend); if (msg == null) { break; // Interrupted } msg.push(Worker.next(workers)); msg.send(backend); } // We handle heartbeating after any socket activity. First we send // heartbeats to any idle workers if it's time. Then we purge any // dead workers: if (System.currentTimeMillis() >= heartbeat_at) { for (final Worker worker : workers) { worker.address.send(backend, ZFrame.REUSE + ZFrame.MORE); final ZFrame frame = new ZFrame(PPP_HEARTBEAT); frame.send(backend, 0); } heartbeat_at = System.currentTimeMillis() + HEARTBEAT_INTERVAL; } Worker.purge(workers); } // When we're done, clean up properly while (workers.size() > 0) { final Worker worker = workers.remove(0); } workers.clear(); ctx.destroy(); }