1

So I am writing my own piece of stuff using jzmq GIT master branch and ZeroMQ 3.2.3.

After installation I tried to test the following simple PUB/SUB program, where a publisher and a subscriber talk in a single process. Since the test is under Windows, I used TCP.

 public class ZMQReadynessTest {

     private ZMQ.Context context;

     @Before
     public void setUp() {
         context = ZMQ.context(1);
     }

     @Test
     public void testSimpleMessage() {
         String topic = "tcp://127.0.0.1:31216";
         final AtomicInteger counter = new AtomicInteger();

      // _____________________________________ create a simple subscriber

         final ZMQ.Socket subscribeSocket = context.socket(ZMQ.SUB);
         subscribeSocket.connect(topic);
         subscribeSocket.subscribe("TestTopic".getBytes());

         Thread subThread = new Thread() {

             @Override
             public void run() {
                 while (true) {
                     String value = null;

                  // This would result in trouble /\/\/\/\/\/\/\/\/\
                     {
                         ByteBuffer buffer = ByteBuffer.allocateDirect(100);
                         if (subscribeSocket.recvZeroCopy( buffer,
                                                           buffer.remaining(),
                                                           ZMQ.DONTWAIT
                                                           ) > 0 ) {

                             buffer.flip();

                             value = buffer.asCharBuffer().toString();
                             System.out.println(buffer.asCharBuffer().toString());
                         }
                     }

                  // This works perfectly + + + + + + + + + + + + + 
                     /*
                     {
                         byte[] bytes = subscribeSocket.recv(ZMQ.DONTWAIT);
                         if (bytes == null || bytes.length == 0) {
                             continue;
                         }

                         value = new String(bytes);
                     }
                      */

                     if (value != null && value.length() > 0) {
                         counter.incrementAndGet();
                         System.out.println(value);
                         break;
                     }
                 }
             }
         };
         subThread.start();

      // _____________________________ create a simple publisher

         ZMQ.Socket publishSocket = context.socket(ZMQ.PUB);
         publishSocket.bind("tcp://*:31216");

         try {
             Thread.sleep(3000); //  + wait 3 sec to make sure its ready
         } catch (InterruptedException e) {
             e.printStackTrace();
             fail();
         }

      // publish a sample message
         try {
             publishSocket.send("TestTopic".getBytes(), ZMQ.SNDMORE);
             publishSocket.send("This is test string".getBytes(), 0);
             subThread.join(100);
         } catch (InterruptedException e) {
             e.printStackTrace();
             fail();
         }

         assertTrue(counter.get() > 0);
         System.out.println(counter.get());
     }
 }

Now as you can see, in the subscriber if I use a simple .recv(ZMQ.DONTWAIT) method, it works perfectly. However, if I am using the direct byte buffer I got nothing returned - and I got the following exception, seems like on program exit:

Exception in thread "Thread-0" org.zeromq.ZMQException: Resource temporarily unavailable(0xb)
at org.zeromq.ZMQ$Socket.recvZeroCopy(Native Method)
at ZMQReadynessTest$1.run(ZMQReadynessTest.java:48)

I also tried to use a simple ByteBuffer (not a direct buffer), which doesn't throw the exception above; but also return me nothing.

Does anybody know how to resolve the above?

I don't want to create byte[] objects all around, as I am doing some high performance system. If this cannot be resolved, I might simply use Unsafe instead. But I really want to work in the "supposed way".

Thanks in advance.

Alex

user3666197
  • 1
  • 6
  • 50
  • 92
Alex Suo
  • 2,977
  • 1
  • 14
  • 22
  • Problem at least partially resolved: it seems after the pub and sub started I must explicitly sleep for a while, say, 1-2 seconds. After that no matter how fast I am sending the data it's fine. – Alex Suo Sep 18 '13 at 08:17
  • Did you get this to work in eclipse? If so, how? I'm trying to get zeromq working through jzmq in eclipse, and it's giving me terrible trouble. – Adam Miller Feb 06 '14 at 18:59
  • @Adam Miller: Yes I got it work. As a surprise, both ZeroMQ as well as some of the commercial MQ products, recommends a pause after creating a topic, or several topics, before you actually start sending messages through. – Alex Suo Feb 07 '14 at 05:08
  • Oh, I'm not actually thinking of that, I'm more interested in how you got jzmq to work with eclipse. Can you guide me through with that? I'm having a problem where it's not compiling my tool that's using zmq in java. – Adam Miller Feb 07 '14 at 07:16
  • 1
    @Adam Miller: 1. Compile it into a JAR and put to the library path 2. In project property, right click the JAR and specify its local library file 3. Statically load jzmq and libzmq during initialization You can look at my open source project at: http://sourceforge.net/p/jalgo/code-0/HEAD/tree/trunk/ Where I have test cases for stuff like simple ZMQ readiness test case, simple message test and full publisher/subscriber wrapping in Java, package org/aso/algo/messaging/bus/zmq/ – Alex Suo Feb 07 '14 at 07:41
  • I was becoming desparate with one of my tests (subscriber would never receive message) but a simple `Thread.sleep` solved the problem. What a terrible bug and I wish we didn't have to go through this workaround. Thanks for finding this workaround @AlexSuo Do you have documentation on the recommended pause before sending messages for a topic? – hanslovsky Jul 27 '18 at 19:01
  • @hanslovsky I reckon it varies per product. In the past when I was working with Informatica LBM (or 29 West LBM as it was called), I was told by their support that 3 seconds is the recommended value. I am not sure what's optimal for JZMQ here but I would probably do a 2 - 5 sec one :) – Alex Suo Jul 31 '18 at 01:28

0 Answers0